You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@climate.apache.org by jo...@apache.org on 2014/05/09 04:03:10 UTC

[01/51] [abbrv] [partial] Adding Jinwon's custom RCMET

Repository: climate
Updated Branches:
  refs/heads/jinwon-rcmet-2.1.3 [created] a6aa1cd2b


http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/webapp/static/bootstrap/css/.svn/text-base/bootstrap-responsive.min.css.svn-base
----------------------------------------------------------------------
diff --git a/src/main/webapp/static/bootstrap/css/.svn/text-base/bootstrap-responsive.min.css.svn-base b/src/main/webapp/static/bootstrap/css/.svn/text-base/bootstrap-responsive.min.css.svn-base
new file mode 100755
index 0000000..ab59da3
--- /dev/null
+++ b/src/main/webapp/static/bootstrap/css/.svn/text-base/bootstrap-responsive.min.css.svn-base
@@ -0,0 +1,9 @@
+/*!
+ * Bootstrap Responsive v2.1.0
+ *
+ * Copyright 2012 Twitter, Inc
+ * Licensed under the Apache License v2.0
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Designed and built with all the love in the world @twitter by @mdo and @fat.
+ */.clearfix{*zoom:1}.clearfix:before,.clearfix:after{display:table;line-height:0;content:""}.clearfix:after{clear:both}.hide-text{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.input-block-level{display:block;width:100%;min-height:30px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.hidden{display:none;visibility:hidden}.visible-phone{display:none!important}.visible-tablet{display:none!important}.hidden-desktop{display:none!important}.visible-desktop{display:inherit!important}@media(min-width:768px) and (max-width:979px){.hidden-desktop{display:inherit!important}.visible-desktop{display:none!important}.visible-tablet{display:inherit!important}.hidden-tablet{display:none!important}}@media(max-width:767px){.hidden-desktop{display:inherit!important}.visible-desktop{display:none!important}.visible-phone{display:inherit!important}.hidden-phone{display:none!important}}@media(min-width:1200px){.row{margin-left:-30px;*zo
 om:1}.row:before,.row:after{display:table;line-height:0;content:""}.row:after{clear:both}[class*="span"]{float:left;margin-left:30px}.container,.navbar-static-top .container,.navbar-fixed-top .container,.navbar-fixed-bottom .container{width:1170px}.span12{width:1170px}.span11{width:1070px}.span10{width:970px}.span9{width:870px}.span8{width:770px}.span7{width:670px}.span6{width:570px}.span5{width:470px}.span4{width:370px}.span3{width:270px}.span2{width:170px}.span1{width:70px}.offset12{margin-left:1230px}.offset11{margin-left:1130px}.offset10{margin-left:1030px}.offset9{margin-left:930px}.offset8{margin-left:830px}.offset7{margin-left:730px}.offset6{margin-left:630px}.offset5{margin-left:530px}.offset4{margin-left:430px}.offset3{margin-left:330px}.offset2{margin-left:230px}.offset1{margin-left:130px}.row-fluid{width:100%;*zoom:1}.row-fluid:before,.row-fluid:after{display:table;line-height:0;content:""}.row-fluid:after{clear:both}.row-fluid [class*="span"]{display:block;float:left;wid
 th:100%;min-height:30px;margin-left:2.564102564102564%;*margin-left:2.5109110747408616%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.row-fluid [class*="span"]:first-child{margin-left:0}.row-fluid .span12{width:100%;*width:99.94680851063829%}.row-fluid .span11{width:91.45299145299145%;*width:91.39979996362975%}.row-fluid .span10{width:82.90598290598291%;*width:82.8527914166212%}.row-fluid .span9{width:74.35897435897436%;*width:74.30578286961266%}.row-fluid .span8{width:65.81196581196582%;*width:65.75877432260411%}.row-fluid .span7{width:57.26495726495726%;*width:57.21176577559556%}.row-fluid .span6{width:48.717948717948715%;*width:48.664757228587014%}.row-fluid .span5{width:40.17094017094017%;*width:40.11774868157847%}.row-fluid .span4{width:31.623931623931625%;*width:31.570740134569924%}.row-fluid .span3{width:23.076923076923077%;*width:23.023731587561375%}.row-fluid .span2{width:14.52991452991453%;*width:14.476723040552828%}.row-fluid .span1{width
 :5.982905982905983%;*width:5.929714493544281%}.row-fluid .offset12{margin-left:105.12820512820512%;*margin-left:105.02182214948171%}.row-fluid .offset12:first-child{margin-left:102.56410256410257%;*margin-left:102.45771958537915%}.row-fluid .offset11{margin-left:96.58119658119658%;*margin-left:96.47481360247316%}.row-fluid .offset11:first-child{margin-left:94.01709401709402%;*margin-left:93.91071103837061%}.row-fluid .offset10{margin-left:88.03418803418803%;*margin-left:87.92780505546462%}.row-fluid .offset10:first-child{margin-left:85.47008547008548%;*margin-left:85.36370249136206%}.row-fluid .offset9{margin-left:79.48717948717949%;*margin-left:79.38079650845607%}.row-fluid .offset9:first-child{margin-left:76.92307692307693%;*margin-left:76.81669394435352%}.row-fluid .offset8{margin-left:70.94017094017094%;*margin-left:70.83378796144753%}.row-fluid .offset8:first-child{margin-left:68.37606837606839%;*margin-left:68.26968539734497%}.row-fluid .offset7{margin-left:62.393162393162385%
 ;*margin-left:62.28677941443899%}.row-fluid .offset7:first-child{margin-left:59.82905982905982%;*margin-left:59.72267685033642%}.row-fluid .offset6{margin-left:53.84615384615384%;*margin-left:53.739770867430444%}.row-fluid .offset6:first-child{margin-left:51.28205128205128%;*margin-left:51.175668303327875%}.row-fluid .offset5{margin-left:45.299145299145295%;*margin-left:45.1927623204219%}.row-fluid .offset5:first-child{margin-left:42.73504273504273%;*margin-left:42.62865975631933%}.row-fluid .offset4{margin-left:36.75213675213675%;*margin-left:36.645753773413354%}.row-fluid .offset4:first-child{margin-left:34.18803418803419%;*margin-left:34.081651209310785%}.row-fluid .offset3{margin-left:28.205128205128204%;*margin-left:28.0987452264048%}.row-fluid .offset3:first-child{margin-left:25.641025641025642%;*margin-left:25.53464266230224%}.row-fluid .offset2{margin-left:19.65811965811966%;*margin-left:19.551736679396257%}.row-fluid .offset2:first-child{margin-left:17.094017094017094%;*mar
 gin-left:16.98763411529369%}.row-fluid .offset1{margin-left:11.11111111111111%;*margin-left:11.004728132387708%}.row-fluid .offset1:first-child{margin-left:8.547008547008547%;*margin-left:8.440625568285142%}input,textarea,.uneditable-input{margin-left:0}.controls-row [class*="span"]+[class*="span"]{margin-left:30px}input.span12,textarea.span12,.uneditable-input.span12{width:1156px}input.span11,textarea.span11,.uneditable-input.span11{width:1056px}input.span10,textarea.span10,.uneditable-input.span10{width:956px}input.span9,textarea.span9,.uneditable-input.span9{width:856px}input.span8,textarea.span8,.uneditable-input.span8{width:756px}input.span7,textarea.span7,.uneditable-input.span7{width:656px}input.span6,textarea.span6,.uneditable-input.span6{width:556px}input.span5,textarea.span5,.uneditable-input.span5{width:456px}input.span4,textarea.span4,.uneditable-input.span4{width:356px}input.span3,textarea.span3,.uneditable-input.span3{width:256px}input.span2,textarea.span2,.uneditable-
 input.span2{width:156px}input.span1,textarea.span1,.uneditable-input.span1{width:56px}.thumbnails{margin-left:-30px}.thumbnails>li{margin-left:30px}.row-fluid .thumbnails{margin-left:0}}@media(min-width:768px) and (max-width:979px){.row{margin-left:-20px;*zoom:1}.row:before,.row:after{display:table;line-height:0;content:""}.row:after{clear:both}[class*="span"]{float:left;margin-left:20px}.container,.navbar-static-top .container,.navbar-fixed-top .container,.navbar-fixed-bottom .container{width:724px}.span12{width:724px}.span11{width:662px}.span10{width:600px}.span9{width:538px}.span8{width:476px}.span7{width:414px}.span6{width:352px}.span5{width:290px}.span4{width:228px}.span3{width:166px}.span2{width:104px}.span1{width:42px}.offset12{margin-left:764px}.offset11{margin-left:702px}.offset10{margin-left:640px}.offset9{margin-left:578px}.offset8{margin-left:516px}.offset7{margin-left:454px}.offset6{margin-left:392px}.offset5{margin-left:330px}.offset4{margin-left:268px}.offset3{margin-
 left:206px}.offset2{margin-left:144px}.offset1{margin-left:82px}.row-fluid{width:100%;*zoom:1}.row-fluid:before,.row-fluid:after{display:table;line-height:0;content:""}.row-fluid:after{clear:both}.row-fluid [class*="span"]{display:block;float:left;width:100%;min-height:30px;margin-left:2.7624309392265194%;*margin-left:2.709239449864817%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.row-fluid [class*="span"]:first-child{margin-left:0}.row-fluid .span12{width:100%;*width:99.94680851063829%}.row-fluid .span11{width:91.43646408839778%;*width:91.38327259903608%}.row-fluid .span10{width:82.87292817679558%;*width:82.81973668743387%}.row-fluid .span9{width:74.30939226519337%;*width:74.25620077583166%}.row-fluid .span8{width:65.74585635359117%;*width:65.69266486422946%}.row-fluid .span7{width:57.18232044198895%;*width:57.12912895262725%}.row-fluid .span6{width:48.61878453038674%;*width:48.56559304102504%}.row-fluid .span5{width:40.05524861878453%;*width:40.0
 0205712942283%}.row-fluid .span4{width:31.491712707182323%;*width:31.43852121782062%}.row-fluid .span3{width:22.92817679558011%;*width:22.87498530621841%}.row-fluid .span2{width:14.3646408839779%;*width:14.311449394616199%}.row-fluid .span1{width:5.801104972375691%;*width:5.747913483013988%}.row-fluid .offset12{margin-left:105.52486187845304%;*margin-left:105.41847889972962%}.row-fluid .offset12:first-child{margin-left:102.76243093922652%;*margin-left:102.6560479605031%}.row-fluid .offset11{margin-left:96.96132596685082%;*margin-left:96.8549429881274%}.row-fluid .offset11:first-child{margin-left:94.1988950276243%;*margin-left:94.09251204890089%}.row-fluid .offset10{margin-left:88.39779005524862%;*margin-left:88.2914070765252%}.row-fluid .offset10:first-child{margin-left:85.6353591160221%;*margin-left:85.52897613729868%}.row-fluid .offset9{margin-left:79.8342541436464%;*margin-left:79.72787116492299%}.row-fluid .offset9:first-child{margin-left:77.07182320441989%;*margin-left:76.96544
 022569647%}.row-fluid .offset8{margin-left:71.2707182320442%;*margin-left:71.16433525332079%}.row-fluid .offset8:first-child{margin-left:68.50828729281768%;*margin-left:68.40190431409427%}.row-fluid .offset7{margin-left:62.70718232044199%;*margin-left:62.600799341718584%}.row-fluid .offset7:first-child{margin-left:59.94475138121547%;*margin-left:59.838368402492065%}.row-fluid .offset6{margin-left:54.14364640883978%;*margin-left:54.037263430116376%}.row-fluid .offset6:first-child{margin-left:51.38121546961326%;*margin-left:51.27483249088986%}.row-fluid .offset5{margin-left:45.58011049723757%;*margin-left:45.47372751851417%}.row-fluid .offset5:first-child{margin-left:42.81767955801105%;*margin-left:42.71129657928765%}.row-fluid .offset4{margin-left:37.01657458563536%;*margin-left:36.91019160691196%}.row-fluid .offset4:first-child{margin-left:34.25414364640884%;*margin-left:34.14776066768544%}.row-fluid .offset3{margin-left:28.45303867403315%;*margin-left:28.346655695309746%}.row-fluid
  .offset3:first-child{margin-left:25.69060773480663%;*margin-left:25.584224756083227%}.row-fluid .offset2{margin-left:19.88950276243094%;*margin-left:19.783119783707537%}.row-fluid .offset2:first-child{margin-left:17.12707182320442%;*margin-left:17.02068884448102%}.row-fluid .offset1{margin-left:11.32596685082873%;*margin-left:11.219583872105325%}.row-fluid .offset1:first-child{margin-left:8.56353591160221%;*margin-left:8.457152932878806%}input,textarea,.uneditable-input{margin-left:0}.controls-row [class*="span"]+[class*="span"]{margin-left:20px}input.span12,textarea.span12,.uneditable-input.span12{width:710px}input.span11,textarea.span11,.uneditable-input.span11{width:648px}input.span10,textarea.span10,.uneditable-input.span10{width:586px}input.span9,textarea.span9,.uneditable-input.span9{width:524px}input.span8,textarea.span8,.uneditable-input.span8{width:462px}input.span7,textarea.span7,.uneditable-input.span7{width:400px}input.span6,textarea.span6,.uneditable-input.span6{width:
 338px}input.span5,textarea.span5,.uneditable-input.span5{width:276px}input.span4,textarea.span4,.uneditable-input.span4{width:214px}input.span3,textarea.span3,.uneditable-input.span3{width:152px}input.span2,textarea.span2,.uneditable-input.span2{width:90px}input.span1,textarea.span1,.uneditable-input.span1{width:28px}}@media(max-width:767px){body{padding-right:20px;padding-left:20px}.navbar-fixed-top,.navbar-fixed-bottom{margin-right:-20px;margin-left:-20px}.container-fluid{padding:0}.dl-horizontal dt{float:none;width:auto;clear:none;text-align:left}.dl-horizontal dd{margin-left:0}.container{width:auto}.row-fluid{width:100%}.row,.thumbnails{margin-left:0}.thumbnails>li{float:none;margin-left:0}[class*="span"],.row-fluid [class*="span"]{display:block;float:none;width:auto;margin-left:0}.span12,.row-fluid .span12{width:100%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.input-large,.input-xlarge,.input-xxlarge,input[class*="span"],select[class*="span"]
 ,textarea[class*="span"],.uneditable-input{display:block;width:100%;min-height:30px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.input-prepend input,.input-append input,.input-prepend input[class*="span"],.input-append input[class*="span"]{display:inline-block;width:auto}.modal{position:fixed;top:20px;right:20px;left:20px;width:auto;margin:0}.modal.fade.in{top:auto}}@media(max-width:480px){.nav-collapse{-webkit-transform:translate3d(0,0,0)}.page-header h1 small{display:block;line-height:20px}input[type="checkbox"],input[type="radio"]{border:1px solid #ccc}.form-horizontal .control-group>label{float:none;width:auto;padding-top:0;text-align:left}.form-horizontal .controls{margin-left:0}.form-horizontal .control-list{padding-top:0}.form-horizontal .form-actions{padding-right:10px;padding-left:10px}.modal{top:10px;right:10px;left:10px}.modal-header .close{padding:10px;margin:-10px}.carousel-caption{position:static}}@media(max-width:979px){body{padding-
 top:0}.navbar-fixed-top,.navbar-fixed-bottom{position:static}.navbar-fixed-top{margin-bottom:20px}.navbar-fixed-bottom{margin-top:20px}.navbar-fixed-top .navbar-inner,.navbar-fixed-bottom .navbar-inner{padding:5px}.navbar .container{width:auto;padding:0}.navbar .brand{padding-right:10px;padding-left:10px;margin:0 0 0 -5px}.nav-collapse{clear:both}.nav-collapse .nav{float:none;margin:0 0 10px}.nav-collapse .nav>li{float:none}.nav-collapse .nav>li>a{margin-bottom:2px}.nav-collapse .nav>.divider-vertical{display:none}.nav-collapse .nav .nav-header{color:#555;text-shadow:none}.nav-collapse .nav>li>a,.nav-collapse .dropdown-menu a{padding:9px 15px;font-weight:bold;color:#555;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}.nav-collapse .btn{padding:4px 10px 4px;font-weight:normal;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.nav-collapse .dropdown-menu li+li a{margin-bottom:2px}.nav-collapse .nav>li>a:hover,.nav-collapse .dropdown-menu a:hover{bac
 kground-color:#f2f2f2}.navbar-inverse .nav-collapse .nav>li>a:hover,.navbar-inverse .nav-collapse .dropdown-menu a:hover{background-color:#111}.nav-collapse.in .btn-group{padding:0;margin-top:5px}.nav-collapse .dropdown-menu{position:static;top:auto;left:auto;display:block;float:none;max-width:none;padding:0;margin:0 15px;background-color:transparent;border:0;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none}.nav-collapse .dropdown-menu:before,.nav-collapse .dropdown-menu:after{display:none}.nav-collapse .dropdown-menu .divider{display:none}.nav-collapse .navbar-form,.nav-collapse .navbar-search{float:none;padding:10px 15px;margin:10px 0;border-top:1px solid #f2f2f2;border-bottom:1px solid #f2f2f2;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.1);-moz-box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.1);box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1p
 x 0 rgba(255,255,255,0.1)}.navbar .nav-collapse .nav.pull-right{float:none;margin-left:0}.nav-collapse,.nav-collapse.collapse{height:0;overflow:hidden}.navbar .btn-navbar{display:block}.navbar-static .navbar-inner{padding-right:10px;padding-left:10px}}@media(min-width:980px){.nav-collapse.collapse{height:auto!important;overflow:visible!important}}


[18/51] [abbrv] [partial] Adding Jinwon's custom RCMET

Posted by jo...@apache.org.
http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/app/lib/angular/.svn/text-base/angular.min.js.svn-base
----------------------------------------------------------------------
diff --git a/src/main/ui/app/lib/angular/.svn/text-base/angular.min.js.svn-base b/src/main/ui/app/lib/angular/.svn/text-base/angular.min.js.svn-base
new file mode 100755
index 0000000..07ea01c
--- /dev/null
+++ b/src/main/ui/app/lib/angular/.svn/text-base/angular.min.js.svn-base
@@ -0,0 +1,161 @@
+/*
+ AngularJS v1.0.5
+ (c) 2010-2012 Google, Inc. http://angularjs.org
+ License: MIT
+*/
+(function(X,Y,q){'use strict';function n(b,a,c){var d;if(b)if(H(b))for(d in b)d!="prototype"&&d!="length"&&d!="name"&&b.hasOwnProperty(d)&&a.call(c,b[d],d);else if(b.forEach&&b.forEach!==n)b.forEach(a,c);else if(!b||typeof b.length!=="number"?0:typeof b.hasOwnProperty!="function"&&typeof b.constructor!="function"||b instanceof L||ca&&b instanceof ca||xa.call(b)!=="[object Object]"||typeof b.callee==="function")for(d=0;d<b.length;d++)a.call(c,b[d],d);else for(d in b)b.hasOwnProperty(d)&&a.call(c,b[d],
+d);return b}function mb(b){var a=[],c;for(c in b)b.hasOwnProperty(c)&&a.push(c);return a.sort()}function fc(b,a,c){for(var d=mb(b),e=0;e<d.length;e++)a.call(c,b[d[e]],d[e]);return d}function nb(b){return function(a,c){b(c,a)}}function ya(){for(var b=aa.length,a;b;){b--;a=aa[b].charCodeAt(0);if(a==57)return aa[b]="A",aa.join("");if(a==90)aa[b]="0";else return aa[b]=String.fromCharCode(a+1),aa.join("")}aa.unshift("0");return aa.join("")}function v(b){n(arguments,function(a){a!==b&&n(a,function(a,d){b[d]=
+a})});return b}function E(b){return parseInt(b,10)}function za(b,a){return v(new (v(function(){},{prototype:b})),a)}function C(){}function na(b){return b}function I(b){return function(){return b}}function w(b){return typeof b=="undefined"}function x(b){return typeof b!="undefined"}function M(b){return b!=null&&typeof b=="object"}function A(b){return typeof b=="string"}function Ra(b){return typeof b=="number"}function oa(b){return xa.apply(b)=="[object Date]"}function B(b){return xa.apply(b)=="[object Array]"}
+function H(b){return typeof b=="function"}function pa(b){return b&&b.document&&b.location&&b.alert&&b.setInterval}function O(b){return A(b)?b.replace(/^\s*/,"").replace(/\s*$/,""):b}function gc(b){return b&&(b.nodeName||b.bind&&b.find)}function Sa(b,a,c){var d=[];n(b,function(b,g,h){d.push(a.call(c,b,g,h))});return d}function Aa(b,a){if(b.indexOf)return b.indexOf(a);for(var c=0;c<b.length;c++)if(a===b[c])return c;return-1}function Ta(b,a){var c=Aa(b,a);c>=0&&b.splice(c,1);return a}function U(b,a){if(pa(b)||
+b&&b.$evalAsync&&b.$watch)throw Error("Can't copy Window or Scope");if(a){if(b===a)throw Error("Can't copy equivalent objects or arrays");if(B(b))for(var c=a.length=0;c<b.length;c++)a.push(U(b[c]));else for(c in n(a,function(b,c){delete a[c]}),b)a[c]=U(b[c])}else(a=b)&&(B(b)?a=U(b,[]):oa(b)?a=new Date(b.getTime()):M(b)&&(a=U(b,{})));return a}function hc(b,a){var a=a||{},c;for(c in b)b.hasOwnProperty(c)&&c.substr(0,2)!=="$$"&&(a[c]=b[c]);return a}function ga(b,a){if(b===a)return!0;if(b===null||a===
+null)return!1;if(b!==b&&a!==a)return!0;var c=typeof b,d;if(c==typeof a&&c=="object")if(B(b)){if((c=b.length)==a.length){for(d=0;d<c;d++)if(!ga(b[d],a[d]))return!1;return!0}}else if(oa(b))return oa(a)&&b.getTime()==a.getTime();else{if(b&&b.$evalAsync&&b.$watch||a&&a.$evalAsync&&a.$watch||pa(b)||pa(a))return!1;c={};for(d in b)if(!(d.charAt(0)==="$"||H(b[d]))){if(!ga(b[d],a[d]))return!1;c[d]=!0}for(d in a)if(!c[d]&&d.charAt(0)!=="$"&&a[d]!==q&&!H(a[d]))return!1;return!0}return!1}function Ua(b,a){var c=
+arguments.length>2?ha.call(arguments,2):[];return H(a)&&!(a instanceof RegExp)?c.length?function(){return arguments.length?a.apply(b,c.concat(ha.call(arguments,0))):a.apply(b,c)}:function(){return arguments.length?a.apply(b,arguments):a.call(b)}:a}function ic(b,a){var c=a;/^\$+/.test(b)?c=q:pa(a)?c="$WINDOW":a&&Y===a?c="$DOCUMENT":a&&a.$evalAsync&&a.$watch&&(c="$SCOPE");return c}function da(b,a){return JSON.stringify(b,ic,a?"  ":null)}function ob(b){return A(b)?JSON.parse(b):b}function Va(b){b&&b.length!==
+0?(b=y(""+b),b=!(b=="f"||b=="0"||b=="false"||b=="no"||b=="n"||b=="[]")):b=!1;return b}function qa(b){b=u(b).clone();try{b.html("")}catch(a){}var c=u("<div>").append(b).html();try{return b[0].nodeType===3?y(c):c.match(/^(<[^>]+>)/)[1].replace(/^<([\w\-]+)/,function(a,b){return"<"+y(b)})}catch(d){return y(c)}}function Wa(b){var a={},c,d;n((b||"").split("&"),function(b){b&&(c=b.split("="),d=decodeURIComponent(c[0]),a[d]=x(c[1])?decodeURIComponent(c[1]):!0)});return a}function pb(b){var a=[];n(b,function(b,
+d){a.push(Xa(d,!0)+(b===!0?"":"="+Xa(b,!0)))});return a.length?a.join("&"):""}function Ya(b){return Xa(b,!0).replace(/%26/gi,"&").replace(/%3D/gi,"=").replace(/%2B/gi,"+")}function Xa(b,a){return encodeURIComponent(b).replace(/%40/gi,"@").replace(/%3A/gi,":").replace(/%24/g,"$").replace(/%2C/gi,",").replace(a?null:/%20/g,"+")}function jc(b,a){function c(a){a&&d.push(a)}var d=[b],e,g,h=["ng:app","ng-app","x-ng-app","data-ng-app"],f=/\sng[:\-]app(:\s*([\w\d_]+);?)?\s/;n(h,function(a){h[a]=!0;c(Y.getElementById(a));
+a=a.replace(":","\\:");b.querySelectorAll&&(n(b.querySelectorAll("."+a),c),n(b.querySelectorAll("."+a+"\\:"),c),n(b.querySelectorAll("["+a+"]"),c))});n(d,function(a){if(!e){var b=f.exec(" "+a.className+" ");b?(e=a,g=(b[2]||"").replace(/\s+/g,",")):n(a.attributes,function(b){if(!e&&h[b.name])e=a,g=b.value})}});e&&a(e,g?[g]:[])}function qb(b,a){b=u(b);a=a||[];a.unshift(["$provide",function(a){a.value("$rootElement",b)}]);a.unshift("ng");var c=rb(a);c.invoke(["$rootScope","$rootElement","$compile","$injector",
+function(a,b,c,h){a.$apply(function(){b.data("$injector",h);c(b)(a)})}]);return c}function Za(b,a){a=a||"_";return b.replace(kc,function(b,d){return(d?a:"")+b.toLowerCase()})}function $a(b,a,c){if(!b)throw Error("Argument '"+(a||"?")+"' is "+(c||"required"));return b}function ra(b,a,c){c&&B(b)&&(b=b[b.length-1]);$a(H(b),a,"not a function, got "+(b&&typeof b=="object"?b.constructor.name||"Object":typeof b));return b}function lc(b){function a(a,b,e){return a[b]||(a[b]=e())}return a(a(b,"angular",Object),
+"module",function(){var b={};return function(d,e,g){e&&b.hasOwnProperty(d)&&(b[d]=null);return a(b,d,function(){function a(c,d,e){return function(){b[e||"push"]([c,d,arguments]);return k}}if(!e)throw Error("No module: "+d);var b=[],c=[],i=a("$injector","invoke"),k={_invokeQueue:b,_runBlocks:c,requires:e,name:d,provider:a("$provide","provider"),factory:a("$provide","factory"),service:a("$provide","service"),value:a("$provide","value"),constant:a("$provide","constant","unshift"),filter:a("$filterProvider",
+"register"),controller:a("$controllerProvider","register"),directive:a("$compileProvider","directive"),config:i,run:function(a){c.push(a);return this}};g&&i(g);return k})}})}function sb(b){return b.replace(mc,function(a,b,d,e){return e?d.toUpperCase():d}).replace(nc,"Moz$1")}function ab(b,a){function c(){var e;for(var b=[this],c=a,h,f,j,i,k,m;b.length;){h=b.shift();f=0;for(j=h.length;f<j;f++){i=u(h[f]);c?i.triggerHandler("$destroy"):c=!c;k=0;for(e=(m=i.children()).length,i=e;k<i;k++)b.push(ca(m[k]))}}return d.apply(this,
+arguments)}var d=ca.fn[b],d=d.$original||d;c.$original=d;ca.fn[b]=c}function L(b){if(b instanceof L)return b;if(!(this instanceof L)){if(A(b)&&b.charAt(0)!="<")throw Error("selectors not implemented");return new L(b)}if(A(b)){var a=Y.createElement("div");a.innerHTML="<div>&#160;</div>"+b;a.removeChild(a.firstChild);bb(this,a.childNodes);this.remove()}else bb(this,b)}function cb(b){return b.cloneNode(!0)}function sa(b){tb(b);for(var a=0,b=b.childNodes||[];a<b.length;a++)sa(b[a])}function ub(b,a,c){var d=
+ba(b,"events");ba(b,"handle")&&(w(a)?n(d,function(a,c){db(b,c,a);delete d[c]}):w(c)?(db(b,a,d[a]),delete d[a]):Ta(d[a],c))}function tb(b){var a=b[Ba],c=Ca[a];c&&(c.handle&&(c.events.$destroy&&c.handle({},"$destroy"),ub(b)),delete Ca[a],b[Ba]=q)}function ba(b,a,c){var d=b[Ba],d=Ca[d||-1];if(x(c))d||(b[Ba]=d=++oc,d=Ca[d]={}),d[a]=c;else return d&&d[a]}function vb(b,a,c){var d=ba(b,"data"),e=x(c),g=!e&&x(a),h=g&&!M(a);!d&&!h&&ba(b,"data",d={});if(e)d[a]=c;else if(g)if(h)return d&&d[a];else v(d,a);else return d}
+function Da(b,a){return(" "+b.className+" ").replace(/[\n\t]/g," ").indexOf(" "+a+" ")>-1}function wb(b,a){a&&n(a.split(" "),function(a){b.className=O((" "+b.className+" ").replace(/[\n\t]/g," ").replace(" "+O(a)+" "," "))})}function xb(b,a){a&&n(a.split(" "),function(a){if(!Da(b,a))b.className=O(b.className+" "+O(a))})}function bb(b,a){if(a)for(var a=!a.nodeName&&x(a.length)&&!pa(a)?a:[a],c=0;c<a.length;c++)b.push(a[c])}function yb(b,a){return Ea(b,"$"+(a||"ngController")+"Controller")}function Ea(b,
+a,c){b=u(b);for(b[0].nodeType==9&&(b=b.find("html"));b.length;){if(c=b.data(a))return c;b=b.parent()}}function zb(b,a){var c=Fa[a.toLowerCase()];return c&&Ab[b.nodeName]&&c}function pc(b,a){var c=function(c,e){if(!c.preventDefault)c.preventDefault=function(){c.returnValue=!1};if(!c.stopPropagation)c.stopPropagation=function(){c.cancelBubble=!0};if(!c.target)c.target=c.srcElement||Y;if(w(c.defaultPrevented)){var g=c.preventDefault;c.preventDefault=function(){c.defaultPrevented=!0;g.call(c)};c.defaultPrevented=
+!1}c.isDefaultPrevented=function(){return c.defaultPrevented};n(a[e||c.type],function(a){a.call(b,c)});Z<=8?(c.preventDefault=null,c.stopPropagation=null,c.isDefaultPrevented=null):(delete c.preventDefault,delete c.stopPropagation,delete c.isDefaultPrevented)};c.elem=b;return c}function fa(b){var a=typeof b,c;if(a=="object"&&b!==null)if(typeof(c=b.$$hashKey)=="function")c=b.$$hashKey();else{if(c===q)c=b.$$hashKey=ya()}else c=b;return a+":"+c}function Ga(b){n(b,this.put,this)}function eb(){}function Bb(b){var a,
+c;if(typeof b=="function"){if(!(a=b.$inject))a=[],c=b.toString().replace(qc,""),c=c.match(rc),n(c[1].split(sc),function(b){b.replace(tc,function(b,c,d){a.push(d)})}),b.$inject=a}else B(b)?(c=b.length-1,ra(b[c],"fn"),a=b.slice(0,c)):ra(b,"fn",!0);return a}function rb(b){function a(a){return function(b,c){if(M(b))n(b,nb(a));else return a(b,c)}}function c(a,b){if(H(b)||B(b))b=m.instantiate(b);if(!b.$get)throw Error("Provider "+a+" must define $get factory method.");return k[a+f]=b}function d(a,b){return c(a,
+{$get:b})}function e(a){var b=[];n(a,function(a){if(!i.get(a))if(i.put(a,!0),A(a)){var c=ta(a);b=b.concat(e(c.requires)).concat(c._runBlocks);try{for(var d=c._invokeQueue,c=0,f=d.length;c<f;c++){var g=d[c],h=g[0]=="$injector"?m:m.get(g[0]);h[g[1]].apply(h,g[2])}}catch(j){throw j.message&&(j.message+=" from "+a),j;}}else if(H(a))try{b.push(m.invoke(a))}catch(o){throw o.message&&(o.message+=" from "+a),o;}else if(B(a))try{b.push(m.invoke(a))}catch(k){throw k.message&&(k.message+=" from "+String(a[a.length-
+1])),k;}else ra(a,"module")});return b}function g(a,b){function c(d){if(typeof d!=="string")throw Error("Service name expected");if(a.hasOwnProperty(d)){if(a[d]===h)throw Error("Circular dependency: "+j.join(" <- "));return a[d]}else try{return j.unshift(d),a[d]=h,a[d]=b(d)}finally{j.shift()}}function d(a,b,e){var f=[],i=Bb(a),g,h,j;h=0;for(g=i.length;h<g;h++)j=i[h],f.push(e&&e.hasOwnProperty(j)?e[j]:c(j));a.$inject||(a=a[g]);switch(b?-1:f.length){case 0:return a();case 1:return a(f[0]);case 2:return a(f[0],
+f[1]);case 3:return a(f[0],f[1],f[2]);case 4:return a(f[0],f[1],f[2],f[3]);case 5:return a(f[0],f[1],f[2],f[3],f[4]);case 6:return a(f[0],f[1],f[2],f[3],f[4],f[5]);case 7:return a(f[0],f[1],f[2],f[3],f[4],f[5],f[6]);case 8:return a(f[0],f[1],f[2],f[3],f[4],f[5],f[6],f[7]);case 9:return a(f[0],f[1],f[2],f[3],f[4],f[5],f[6],f[7],f[8]);case 10:return a(f[0],f[1],f[2],f[3],f[4],f[5],f[6],f[7],f[8],f[9]);default:return a.apply(b,f)}}return{invoke:d,instantiate:function(a,b){var c=function(){},e;c.prototype=
+(B(a)?a[a.length-1]:a).prototype;c=new c;e=d(a,c,b);return M(e)?e:c},get:c,annotate:Bb}}var h={},f="Provider",j=[],i=new Ga,k={$provide:{provider:a(c),factory:a(d),service:a(function(a,b){return d(a,["$injector",function(a){return a.instantiate(b)}])}),value:a(function(a,b){return d(a,I(b))}),constant:a(function(a,b){k[a]=b;l[a]=b}),decorator:function(a,b){var c=m.get(a+f),d=c.$get;c.$get=function(){var a=t.invoke(d,c);return t.invoke(b,null,{$delegate:a})}}}},m=g(k,function(){throw Error("Unknown provider: "+
+j.join(" <- "));}),l={},t=l.$injector=g(l,function(a){a=m.get(a+f);return t.invoke(a.$get,a)});n(e(b),function(a){t.invoke(a||C)});return t}function uc(){var b=!0;this.disableAutoScrolling=function(){b=!1};this.$get=["$window","$location","$rootScope",function(a,c,d){function e(a){var b=null;n(a,function(a){!b&&y(a.nodeName)==="a"&&(b=a)});return b}function g(){var b=c.hash(),d;b?(d=h.getElementById(b))?d.scrollIntoView():(d=e(h.getElementsByName(b)))?d.scrollIntoView():b==="top"&&a.scrollTo(0,0):
+a.scrollTo(0,0)}var h=a.document;b&&d.$watch(function(){return c.hash()},function(){d.$evalAsync(g)});return g}]}function vc(b,a,c,d){function e(a){try{a.apply(null,ha.call(arguments,1))}finally{if(o--,o===0)for(;p.length;)try{p.pop()()}catch(b){c.error(b)}}}function g(a,b){(function R(){n(s,function(a){a()});J=b(R,a)})()}function h(){F!=f.url()&&(F=f.url(),n(V,function(a){a(f.url())}))}var f=this,j=a[0],i=b.location,k=b.history,m=b.setTimeout,l=b.clearTimeout,t={};f.isMock=!1;var o=0,p=[];f.$$completeOutstandingRequest=
+e;f.$$incOutstandingRequestCount=function(){o++};f.notifyWhenNoOutstandingRequests=function(a){n(s,function(a){a()});o===0?a():p.push(a)};var s=[],J;f.addPollFn=function(a){w(J)&&g(100,m);s.push(a);return a};var F=i.href,z=a.find("base");f.url=function(a,b){if(a){if(F!=a)return F=a,d.history?b?k.replaceState(null,"",a):(k.pushState(null,"",a),z.attr("href",z.attr("href"))):b?i.replace(a):i.href=a,f}else return i.href.replace(/%27/g,"'")};var V=[],K=!1;f.onUrlChange=function(a){K||(d.history&&u(b).bind("popstate",
+h),d.hashchange?u(b).bind("hashchange",h):f.addPollFn(h),K=!0);V.push(a);return a};f.baseHref=function(){var a=z.attr("href");return a?a.replace(/^https?\:\/\/[^\/]*/,""):""};var r={},$="",P=f.baseHref();f.cookies=function(a,b){var d,e,f,i;if(a)if(b===q)j.cookie=escape(a)+"=;path="+P+";expires=Thu, 01 Jan 1970 00:00:00 GMT";else{if(A(b))d=(j.cookie=escape(a)+"="+escape(b)+";path="+P).length+1,d>4096&&c.warn("Cookie '"+a+"' possibly not set or overflowed because it was too large ("+d+" > 4096 bytes)!")}else{if(j.cookie!==
+$){$=j.cookie;d=$.split("; ");r={};for(f=0;f<d.length;f++)e=d[f],i=e.indexOf("="),i>0&&(r[unescape(e.substring(0,i))]=unescape(e.substring(i+1)))}return r}};f.defer=function(a,b){var c;o++;c=m(function(){delete t[c];e(a)},b||0);t[c]=!0;return c};f.defer.cancel=function(a){return t[a]?(delete t[a],l(a),e(C),!0):!1}}function wc(){this.$get=["$window","$log","$sniffer","$document",function(b,a,c,d){return new vc(b,d,a,c)}]}function xc(){this.$get=function(){function b(b,d){function e(a){if(a!=m){if(l){if(l==
+a)l=a.n}else l=a;g(a.n,a.p);g(a,m);m=a;m.n=null}}function g(a,b){if(a!=b){if(a)a.p=b;if(b)b.n=a}}if(b in a)throw Error("cacheId "+b+" taken");var h=0,f=v({},d,{id:b}),j={},i=d&&d.capacity||Number.MAX_VALUE,k={},m=null,l=null;return a[b]={put:function(a,b){var c=k[a]||(k[a]={key:a});e(c);w(b)||(a in j||h++,j[a]=b,h>i&&this.remove(l.key))},get:function(a){var b=k[a];if(b)return e(b),j[a]},remove:function(a){var b=k[a];if(b){if(b==m)m=b.p;if(b==l)l=b.n;g(b.n,b.p);delete k[a];delete j[a];h--}},removeAll:function(){j=
+{};h=0;k={};m=l=null},destroy:function(){k=f=j=null;delete a[b]},info:function(){return v({},f,{size:h})}}}var a={};b.info=function(){var b={};n(a,function(a,e){b[e]=a.info()});return b};b.get=function(b){return a[b]};return b}}function yc(){this.$get=["$cacheFactory",function(b){return b("templates")}]}function Cb(b){var a={},c="Directive",d=/^\s*directive\:\s*([\d\w\-_]+)\s+(.*)$/,e=/(([\d\w\-_]+)(?:\:([^;]+))?;?)/,g="Template must have exactly one root element. was: ",h=/^\s*(https?|ftp|mailto):/;
+this.directive=function j(d,e){A(d)?($a(e,"directive"),a.hasOwnProperty(d)||(a[d]=[],b.factory(d+c,["$injector","$exceptionHandler",function(b,c){var e=[];n(a[d],function(a){try{var g=b.invoke(a);if(H(g))g={compile:I(g)};else if(!g.compile&&g.link)g.compile=I(g.link);g.priority=g.priority||0;g.name=g.name||d;g.require=g.require||g.controller&&g.name;g.restrict=g.restrict||"A";e.push(g)}catch(h){c(h)}});return e}])),a[d].push(e)):n(d,nb(j));return this};this.urlSanitizationWhitelist=function(a){return x(a)?
+(h=a,this):h};this.$get=["$injector","$interpolate","$exceptionHandler","$http","$templateCache","$parse","$controller","$rootScope","$document",function(b,i,k,m,l,t,o,p,s){function J(a,b,c){a instanceof u||(a=u(a));n(a,function(b,c){b.nodeType==3&&b.nodeValue.match(/\S+/)&&(a[c]=u(b).wrap("<span></span>").parent()[0])});var d=z(a,b,a,c);return function(b,c){$a(b,"scope");for(var e=c?va.clone.call(a):a,g=0,i=e.length;g<i;g++){var h=e[g];(h.nodeType==1||h.nodeType==9)&&e.eq(g).data("$scope",b)}F(e,
+"ng-scope");c&&c(e,b);d&&d(b,e,e);return e}}function F(a,b){try{a.addClass(b)}catch(c){}}function z(a,b,c,d){function e(a,c,d,i){var h,j,k,o,l,m,t,s=[];l=0;for(m=c.length;l<m;l++)s.push(c[l]);t=l=0;for(m=g.length;l<m;t++)j=s[t],c=g[l++],h=g[l++],c?(c.scope?(k=a.$new(M(c.scope)),u(j).data("$scope",k)):k=a,(o=c.transclude)||!i&&b?c(h,k,j,d,function(b){return function(c){var d=a.$new();d.$$transcluded=!0;return b(d,c).bind("$destroy",Ua(d,d.$destroy))}}(o||b)):c(h,k,j,q,i)):h&&h(a,j.childNodes,q,i)}
+for(var g=[],i,h,j,k=0;k<a.length;k++)h=new ia,i=V(a[k],[],h,d),h=(i=i.length?K(i,a[k],h,b,c):null)&&i.terminal||!a[k].childNodes.length?null:z(a[k].childNodes,i?i.transclude:b),g.push(i),g.push(h),j=j||i||h;return j?e:null}function V(a,b,c,i){var g=c.$attr,h;switch(a.nodeType){case 1:r(b,ea(fb(a).toLowerCase()),"E",i);var j,k,l;h=a.attributes;for(var o=0,m=h&&h.length;o<m;o++)if(j=h[o],j.specified)k=j.name,l=ea(k.toLowerCase()),g[l]=k,c[l]=j=O(Z&&k=="href"?decodeURIComponent(a.getAttribute(k,2)):
+j.value),zb(a,l)&&(c[l]=!0),R(a,b,j,l),r(b,l,"A",i);a=a.className;if(A(a)&&a!=="")for(;h=e.exec(a);)l=ea(h[2]),r(b,l,"C",i)&&(c[l]=O(h[3])),a=a.substr(h.index+h[0].length);break;case 3:x(b,a.nodeValue);break;case 8:try{if(h=d.exec(a.nodeValue))l=ea(h[1]),r(b,l,"M",i)&&(c[l]=O(h[2]))}catch(t){}}b.sort(G);return b}function K(a,b,c,d,e){function i(a,b){if(a)a.require=r.require,m.push(a);if(b)b.require=r.require,s.push(b)}function h(a,b){var c,d="data",e=!1;if(A(a)){for(;(c=a.charAt(0))=="^"||c=="?";)a=
+a.substr(1),c=="^"&&(d="inheritedData"),e=e||c=="?";c=b[d]("$"+a+"Controller");if(!c&&!e)throw Error("No controller: "+a);}else B(a)&&(c=[],n(a,function(a){c.push(h(a,b))}));return c}function j(a,d,e,i,g){var l,p,r,D,F;l=b===e?c:hc(c,new ia(u(e),c.$attr));p=l.$$element;if(K){var J=/^\s*([@=&])\s*(\w*)\s*$/,ja=d.$parent||d;n(K.scope,function(a,b){var c=a.match(J)||[],e=c[2]||b,c=c[1],i,g,h;d.$$isolateBindings[b]=c+e;switch(c){case "@":l.$observe(e,function(a){d[b]=a});l.$$observers[e].$$scope=ja;break;
+case "=":g=t(l[e]);h=g.assign||function(){i=d[b]=g(ja);throw Error(Db+l[e]+" (directive: "+K.name+")");};i=d[b]=g(ja);d.$watch(function(){var a=g(ja);a!==d[b]&&(a!==i?i=d[b]=a:h(ja,a=i=d[b]));return a});break;case "&":g=t(l[e]);d[b]=function(a){return g(ja,a)};break;default:throw Error("Invalid isolate scope definition for directive "+K.name+": "+a);}})}x&&n(x,function(a){var b={$scope:d,$element:p,$attrs:l,$transclude:g};F=a.controller;F=="@"&&(F=l[a.name]);p.data("$"+a.name+"Controller",o(F,b))});
+i=0;for(r=m.length;i<r;i++)try{D=m[i],D(d,p,l,D.require&&h(D.require,p))}catch(z){k(z,qa(p))}a&&a(d,e.childNodes,q,g);i=0;for(r=s.length;i<r;i++)try{D=s[i],D(d,p,l,D.require&&h(D.require,p))}catch(zc){k(zc,qa(p))}}for(var l=-Number.MAX_VALUE,m=[],s=[],p=null,K=null,z=null,D=c.$$element=u(b),r,G,S,ka,R=d,x,w,W,v=0,y=a.length;v<y;v++){r=a[v];S=q;if(l>r.priority)break;if(W=r.scope)ua("isolated scope",K,r,D),M(W)&&(F(D,"ng-isolate-scope"),K=r),F(D,"ng-scope"),p=p||r;G=r.name;if(W=r.controller)x=x||{},
+ua("'"+G+"' controller",x[G],r,D),x[G]=r;if(W=r.transclude)ua("transclusion",ka,r,D),ka=r,l=r.priority,W=="element"?(S=u(b),D=c.$$element=u(Y.createComment(" "+G+": "+c[G]+" ")),b=D[0],C(e,u(S[0]),b),R=J(S,d,l)):(S=u(cb(b)).contents(),D.html(""),R=J(S,d));if(W=r.template)if(ua("template",z,r,D),z=r,W=Eb(W),r.replace){S=u("<div>"+O(W)+"</div>").contents();b=S[0];if(S.length!=1||b.nodeType!==1)throw Error(g+W);C(e,D,b);G={$attr:{}};a=a.concat(V(b,a.splice(v+1,a.length-(v+1)),G));$(c,G);y=a.length}else D.html(W);
+if(r.templateUrl)ua("template",z,r,D),z=r,j=P(a.splice(v,a.length-v),j,D,c,e,r.replace,R),y=a.length;else if(r.compile)try{w=r.compile(D,c,R),H(w)?i(null,w):w&&i(w.pre,w.post)}catch(E){k(E,qa(D))}if(r.terminal)j.terminal=!0,l=Math.max(l,r.priority)}j.scope=p&&p.scope;j.transclude=ka&&R;return j}function r(d,e,i,g){var h=!1;if(a.hasOwnProperty(e))for(var l,e=b.get(e+c),o=0,m=e.length;o<m;o++)try{if(l=e[o],(g===q||g>l.priority)&&l.restrict.indexOf(i)!=-1)d.push(l),h=!0}catch(t){k(t)}return h}function $(a,
+b){var c=b.$attr,d=a.$attr,e=a.$$element;n(a,function(d,e){e.charAt(0)!="$"&&(b[e]&&(d+=(e==="style"?";":" ")+b[e]),a.$set(e,d,!0,c[e]))});n(b,function(b,i){i=="class"?(F(e,b),a["class"]=(a["class"]?a["class"]+" ":"")+b):i=="style"?e.attr("style",e.attr("style")+";"+b):i.charAt(0)!="$"&&!a.hasOwnProperty(i)&&(a[i]=b,d[i]=c[i])})}function P(a,b,c,d,e,i,h){var j=[],k,o,t=c[0],s=a.shift(),p=v({},s,{controller:null,templateUrl:null,transclude:null,scope:null});c.html("");m.get(s.templateUrl,{cache:l}).success(function(l){var m,
+s,l=Eb(l);if(i){s=u("<div>"+O(l)+"</div>").contents();m=s[0];if(s.length!=1||m.nodeType!==1)throw Error(g+l);l={$attr:{}};C(e,c,m);V(m,a,l);$(d,l)}else m=t,c.html(l);a.unshift(p);k=K(a,m,d,h);for(o=z(c.contents(),h);j.length;){var ia=j.pop(),l=j.pop();s=j.pop();var r=j.pop(),D=m;s!==t&&(D=cb(m),C(l,u(s),D));k(function(){b(o,r,D,e,ia)},r,D,e,ia)}j=null}).error(function(a,b,c,d){throw Error("Failed to load template: "+d.url);});return function(a,c,d,e,i){j?(j.push(c),j.push(d),j.push(e),j.push(i)):
+k(function(){b(o,c,d,e,i)},c,d,e,i)}}function G(a,b){return b.priority-a.priority}function ua(a,b,c,d){if(b)throw Error("Multiple directives ["+b.name+", "+c.name+"] asking for "+a+" on: "+qa(d));}function x(a,b){var c=i(b,!0);c&&a.push({priority:0,compile:I(function(a,b){var d=b.parent(),e=d.data("$binding")||[];e.push(c);F(d.data("$binding",e),"ng-binding");a.$watch(c,function(a){b[0].nodeValue=a})})})}function R(a,b,c,d){var e=i(c,!0);e&&b.push({priority:100,compile:I(function(a,b,c){b=c.$$observers||
+(c.$$observers={});d==="class"&&(e=i(c[d],!0));c[d]=q;(b[d]||(b[d]=[])).$$inter=!0;(c.$$observers&&c.$$observers[d].$$scope||a).$watch(e,function(a){c.$set(d,a)})})})}function C(a,b,c){var d=b[0],e=d.parentNode,i,g;if(a){i=0;for(g=a.length;i<g;i++)if(a[i]==d){a[i]=c;break}}e&&e.replaceChild(c,d);c[u.expando]=d[u.expando];b[0]=c}var ia=function(a,b){this.$$element=a;this.$attr=b||{}};ia.prototype={$normalize:ea,$set:function(a,b,c,d){var e=zb(this.$$element[0],a),i=this.$$observers;e&&(this.$$element.prop(a,
+b),d=e);this[a]=b;d?this.$attr[a]=d:(d=this.$attr[a])||(this.$attr[a]=d=Za(a,"-"));if(fb(this.$$element[0])==="A"&&a==="href")D.setAttribute("href",b),e=D.href,e.match(h)||(this[a]=b="unsafe:"+e);c!==!1&&(b===null||b===q?this.$$element.removeAttr(d):this.$$element.attr(d,b));i&&n(i[a],function(a){try{a(b)}catch(c){k(c)}})},$observe:function(a,b){var c=this,d=c.$$observers||(c.$$observers={}),e=d[a]||(d[a]=[]);e.push(b);p.$evalAsync(function(){e.$$inter||b(c[a])});return b}};var D=s[0].createElement("a"),
+S=i.startSymbol(),ka=i.endSymbol(),Eb=S=="{{"||ka=="}}"?na:function(a){return a.replace(/\{\{/g,S).replace(/}}/g,ka)};return J}]}function ea(b){return sb(b.replace(Ac,""))}function Bc(){var b={};this.register=function(a,c){M(a)?v(b,a):b[a]=c};this.$get=["$injector","$window",function(a,c){return function(d,e){if(A(d)){var g=d,d=b.hasOwnProperty(g)?b[g]:gb(e.$scope,g,!0)||gb(c,g,!0);ra(d,g,!0)}return a.instantiate(d,e)}}]}function Cc(){this.$get=["$window",function(b){return u(b.document)}]}function Dc(){this.$get=
+["$log",function(b){return function(a,c){b.error.apply(b,arguments)}}]}function Ec(){var b="{{",a="}}";this.startSymbol=function(a){return a?(b=a,this):b};this.endSymbol=function(b){return b?(a=b,this):a};this.$get=["$parse",function(c){function d(d,f){for(var j,i,k=0,m=[],l=d.length,t=!1,o=[];k<l;)(j=d.indexOf(b,k))!=-1&&(i=d.indexOf(a,j+e))!=-1?(k!=j&&m.push(d.substring(k,j)),m.push(k=c(t=d.substring(j+e,i))),k.exp=t,k=i+g,t=!0):(k!=l&&m.push(d.substring(k)),k=l);if(!(l=m.length))m.push(""),l=1;
+if(!f||t)return o.length=l,k=function(a){for(var b=0,c=l,d;b<c;b++){if(typeof(d=m[b])=="function")d=d(a),d==null||d==q?d="":typeof d!="string"&&(d=da(d));o[b]=d}return o.join("")},k.exp=d,k.parts=m,k}var e=b.length,g=a.length;d.startSymbol=function(){return b};d.endSymbol=function(){return a};return d}]}function Fb(b){for(var b=b.split("/"),a=b.length;a--;)b[a]=Ya(b[a]);return b.join("/")}function wa(b,a){var c=Gb.exec(b),c={protocol:c[1],host:c[3],port:E(c[5])||Hb[c[1]]||null,path:c[6]||"/",search:c[8],
+hash:c[10]};if(a)a.$$protocol=c.protocol,a.$$host=c.host,a.$$port=c.port;return c}function la(b,a,c){return b+"://"+a+(c==Hb[b]?"":":"+c)}function Fc(b,a,c){var d=wa(b);return decodeURIComponent(d.path)!=a||w(d.hash)||d.hash.indexOf(c)!==0?b:la(d.protocol,d.host,d.port)+a.substr(0,a.lastIndexOf("/"))+d.hash.substr(c.length)}function Gc(b,a,c){var d=wa(b);if(decodeURIComponent(d.path)==a)return b;else{var e=d.search&&"?"+d.search||"",g=d.hash&&"#"+d.hash||"",h=a.substr(0,a.lastIndexOf("/")),f=d.path.substr(h.length);
+if(d.path.indexOf(h)!==0)throw Error('Invalid url "'+b+'", missing path prefix "'+h+'" !');return la(d.protocol,d.host,d.port)+a+"#"+c+f+e+g}}function hb(b,a,c){a=a||"";this.$$parse=function(b){var c=wa(b,this);if(c.path.indexOf(a)!==0)throw Error('Invalid url "'+b+'", missing path prefix "'+a+'" !');this.$$path=decodeURIComponent(c.path.substr(a.length));this.$$search=Wa(c.search);this.$$hash=c.hash&&decodeURIComponent(c.hash)||"";this.$$compose()};this.$$compose=function(){var b=pb(this.$$search),
+c=this.$$hash?"#"+Ya(this.$$hash):"";this.$$url=Fb(this.$$path)+(b?"?"+b:"")+c;this.$$absUrl=la(this.$$protocol,this.$$host,this.$$port)+a+this.$$url};this.$$rewriteAppUrl=function(a){if(a.indexOf(c)==0)return a};this.$$parse(b)}function Ha(b,a,c){var d;this.$$parse=function(b){var c=wa(b,this);if(c.hash&&c.hash.indexOf(a)!==0)throw Error('Invalid url "'+b+'", missing hash prefix "'+a+'" !');d=c.path+(c.search?"?"+c.search:"");c=Hc.exec((c.hash||"").substr(a.length));this.$$path=c[1]?(c[1].charAt(0)==
+"/"?"":"/")+decodeURIComponent(c[1]):"";this.$$search=Wa(c[3]);this.$$hash=c[5]&&decodeURIComponent(c[5])||"";this.$$compose()};this.$$compose=function(){var b=pb(this.$$search),c=this.$$hash?"#"+Ya(this.$$hash):"";this.$$url=Fb(this.$$path)+(b?"?"+b:"")+c;this.$$absUrl=la(this.$$protocol,this.$$host,this.$$port)+d+(this.$$url?"#"+a+this.$$url:"")};this.$$rewriteAppUrl=function(a){if(a.indexOf(c)==0)return a};this.$$parse(b)}function Ib(b,a,c,d){Ha.apply(this,arguments);this.$$rewriteAppUrl=function(b){if(b.indexOf(c)==
+0)return c+d+"#"+a+b.substr(c.length)}}function Ia(b){return function(){return this[b]}}function Jb(b,a){return function(c){if(w(c))return this[b];this[b]=a(c);this.$$compose();return this}}function Ic(){var b="",a=!1;this.hashPrefix=function(a){return x(a)?(b=a,this):b};this.html5Mode=function(b){return x(b)?(a=b,this):a};this.$get=["$rootScope","$browser","$sniffer","$rootElement",function(c,d,e,g){function h(a){c.$broadcast("$locationChangeSuccess",f.absUrl(),a)}var f,j,i,k=d.url(),m=wa(k);a?(j=
+d.baseHref()||"/",i=j.substr(0,j.lastIndexOf("/")),m=la(m.protocol,m.host,m.port)+i+"/",f=e.history?new hb(Fc(k,j,b),i,m):new Ib(Gc(k,j,b),b,m,j.substr(i.length+1))):(m=la(m.protocol,m.host,m.port)+(m.path||"")+(m.search?"?"+m.search:"")+"#"+b+"/",f=new Ha(k,b,m));g.bind("click",function(a){if(!a.ctrlKey&&!(a.metaKey||a.which==2)){for(var b=u(a.target);y(b[0].nodeName)!=="a";)if(b[0]===g[0]||!(b=b.parent())[0])return;var d=b.prop("href"),e=f.$$rewriteAppUrl(d);d&&!b.attr("target")&&e&&(f.$$parse(e),
+c.$apply(),a.preventDefault(),X.angular["ff-684208-preventDefault"]=!0)}});f.absUrl()!=k&&d.url(f.absUrl(),!0);d.onUrlChange(function(a){f.absUrl()!=a&&(c.$evalAsync(function(){var b=f.absUrl();f.$$parse(a);h(b)}),c.$$phase||c.$digest())});var l=0;c.$watch(function(){var a=d.url(),b=f.$$replace;if(!l||a!=f.absUrl())l++,c.$evalAsync(function(){c.$broadcast("$locationChangeStart",f.absUrl(),a).defaultPrevented?f.$$parse(a):(d.url(f.absUrl(),b),h(a))});f.$$replace=!1;return l});return f}]}function Jc(){this.$get=
+["$window",function(b){function a(a){a instanceof Error&&(a.stack?a=a.message&&a.stack.indexOf(a.message)===-1?"Error: "+a.message+"\n"+a.stack:a.stack:a.sourceURL&&(a=a.message+"\n"+a.sourceURL+":"+a.line));return a}function c(c){var e=b.console||{},g=e[c]||e.log||C;return g.apply?function(){var b=[];n(arguments,function(c){b.push(a(c))});return g.apply(e,b)}:function(a,b){g(a,b)}}return{log:c("log"),warn:c("warn"),info:c("info"),error:c("error")}}]}function Kc(b,a){function c(a){return a.indexOf(s)!=
+-1}function d(){return o+1<b.length?b.charAt(o+1):!1}function e(a){return"0"<=a&&a<="9"}function g(a){return a==" "||a=="\r"||a=="\t"||a=="\n"||a=="\u000b"||a=="\u00a0"}function h(a){return"a"<=a&&a<="z"||"A"<=a&&a<="Z"||"_"==a||a=="$"}function f(a){return a=="-"||a=="+"||e(a)}function j(a,c,d){d=d||o;throw Error("Lexer Error: "+a+" at column"+(x(c)?"s "+c+"-"+o+" ["+b.substring(c,d)+"]":" "+d)+" in expression ["+b+"].");}function i(){for(var a="",c=o;o<b.length;){var i=y(b.charAt(o));if(i=="."||
+e(i))a+=i;else{var g=d();if(i=="e"&&f(g))a+=i;else if(f(i)&&g&&e(g)&&a.charAt(a.length-1)=="e")a+=i;else if(f(i)&&(!g||!e(g))&&a.charAt(a.length-1)=="e")j("Invalid exponent");else break}o++}a*=1;l.push({index:c,text:a,json:!0,fn:function(){return a}})}function k(){for(var c="",d=o,f,i,j;o<b.length;){var k=b.charAt(o);if(k=="."||h(k)||e(k))k=="."&&(f=o),c+=k;else break;o++}if(f)for(i=o;i<b.length;){k=b.charAt(i);if(k=="("){j=c.substr(f-d+1);c=c.substr(0,f-d);o=i;break}if(g(k))i++;else break}d={index:d,
+text:c};if(Ja.hasOwnProperty(c))d.fn=d.json=Ja[c];else{var m=Kb(c,a);d.fn=v(function(a,b){return m(a,b)},{assign:function(a,b){return Lb(a,c,b)}})}l.push(d);j&&(l.push({index:f,text:".",json:!1}),l.push({index:f+1,text:j,json:!1}))}function m(a){var c=o;o++;for(var d="",e=a,f=!1;o<b.length;){var i=b.charAt(o);e+=i;if(f)i=="u"?(i=b.substring(o+1,o+5),i.match(/[\da-f]{4}/i)||j("Invalid unicode escape [\\u"+i+"]"),o+=4,d+=String.fromCharCode(parseInt(i,16))):(f=Lc[i],d+=f?f:i),f=!1;else if(i=="\\")f=
+!0;else if(i==a){o++;l.push({index:c,text:e,string:d,json:!0,fn:function(){return d}});return}else d+=i;o++}j("Unterminated quote",c)}for(var l=[],t,o=0,p=[],s,J=":";o<b.length;){s=b.charAt(o);if(c("\"'"))m(s);else if(e(s)||c(".")&&e(d()))i();else if(h(s)){if(k(),"{,".indexOf(J)!=-1&&p[0]=="{"&&(t=l[l.length-1]))t.json=t.text.indexOf(".")==-1}else if(c("(){}[].,;:"))l.push({index:o,text:s,json:":[,".indexOf(J)!=-1&&c("{[")||c("}]:,")}),c("{[")&&p.unshift(s),c("}]")&&p.shift(),o++;else if(g(s)){o++;
+continue}else{var n=s+d(),z=Ja[s],V=Ja[n];V?(l.push({index:o,text:n,fn:V}),o+=2):z?(l.push({index:o,text:s,fn:z,json:"[,:".indexOf(J)!=-1&&c("+-")}),o+=1):j("Unexpected next character ",o,o+1)}J=s}return l}function Mc(b,a,c,d){function e(a,c){throw Error("Syntax Error: Token '"+c.text+"' "+a+" at column "+(c.index+1)+" of the expression ["+b+"] starting at ["+b.substring(c.index)+"].");}function g(){if(P.length===0)throw Error("Unexpected end of expression: "+b);return P[0]}function h(a,b,c,d){if(P.length>
+0){var e=P[0],f=e.text;if(f==a||f==b||f==c||f==d||!a&&!b&&!c&&!d)return e}return!1}function f(b,c,d,f){return(b=h(b,c,d,f))?(a&&!b.json&&e("is not valid json",b),P.shift(),b):!1}function j(a){f(a)||e("is unexpected, expecting ["+a+"]",h())}function i(a,b){return function(c,d){return a(c,d,b)}}function k(a,b,c){return function(d,e){return b(d,e,a,c)}}function m(){for(var a=[];;)if(P.length>0&&!h("}",")",";","]")&&a.push(w()),!f(";"))return a.length==1?a[0]:function(b,c){for(var d,e=0;e<a.length;e++){var f=
+a[e];f&&(d=f(b,c))}return d}}function l(){for(var a=f(),b=c(a.text),d=[];;)if(a=f(":"))d.push(G());else{var e=function(a,c,e){for(var e=[e],f=0;f<d.length;f++)e.push(d[f](a,c));return b.apply(a,e)};return function(){return e}}}function t(){for(var a=o(),b;;)if(b=f("||"))a=k(a,b.fn,o());else return a}function o(){var a=p(),b;if(b=f("&&"))a=k(a,b.fn,o());return a}function p(){var a=s(),b;if(b=f("==","!="))a=k(a,b.fn,p());return a}function s(){var a;a=J();for(var b;b=f("+","-");)a=k(a,b.fn,J());if(b=
+f("<",">","<=",">="))a=k(a,b.fn,s());return a}function J(){for(var a=n(),b;b=f("*","/","%");)a=k(a,b.fn,n());return a}function n(){var a;return f("+")?z():(a=f("-"))?k(r,a.fn,n()):(a=f("!"))?i(a.fn,n()):z()}function z(){var a;if(f("("))a=w(),j(")");else if(f("["))a=V();else if(f("{"))a=K();else{var b=f();(a=b.fn)||e("not a primary expression",b)}for(var c;b=f("(","[",".");)b.text==="("?(a=x(a,c),c=null):b.text==="["?(c=a,a=R(a)):b.text==="."?(c=a,a=u(a)):e("IMPOSSIBLE");return a}function V(){var a=
+[];if(g().text!="]"){do a.push(G());while(f(","))}j("]");return function(b,c){for(var d=[],e=0;e<a.length;e++)d.push(a[e](b,c));return d}}function K(){var a=[];if(g().text!="}"){do{var b=f(),b=b.string||b.text;j(":");var c=G();a.push({key:b,value:c})}while(f(","))}j("}");return function(b,c){for(var d={},e=0;e<a.length;e++){var f=a[e],i=f.value(b,c);d[f.key]=i}return d}}var r=I(0),$,P=Kc(b,d),G=function(){var a=t(),c,d;return(d=f("="))?(a.assign||e("implies assignment but ["+b.substring(0,d.index)+
+"] can not be assigned to",d),c=t(),function(b,d){return a.assign(b,c(b,d),d)}):a},x=function(a,b){var c=[];if(g().text!=")"){do c.push(G());while(f(","))}j(")");return function(d,e){for(var f=[],i=b?b(d,e):d,g=0;g<c.length;g++)f.push(c[g](d,e));g=a(d,e)||C;return g.apply?g.apply(i,f):g(f[0],f[1],f[2],f[3],f[4])}},u=function(a){var b=f().text,c=Kb(b,d);return v(function(b,d){return c(a(b,d),d)},{assign:function(c,d,e){return Lb(a(c,e),b,d)}})},R=function(a){var b=G();j("]");return v(function(c,d){var e=
+a(c,d),f=b(c,d),i;if(!e)return q;if((e=e[f])&&e.then){i=e;if(!("$$v"in e))i.$$v=q,i.then(function(a){i.$$v=a});e=e.$$v}return e},{assign:function(c,d,e){return a(c,e)[b(c,e)]=d}})},w=function(){for(var a=G(),b;;)if(b=f("|"))a=k(a,b.fn,l());else return a};a?(G=t,x=u=R=w=function(){e("is not valid json",{text:b,index:0})},$=z()):$=m();P.length!==0&&e("is an unexpected token",P[0]);return $}function Lb(b,a,c){for(var a=a.split("."),d=0;a.length>1;d++){var e=a.shift(),g=b[e];g||(g={},b[e]=g);b=g}return b[a.shift()]=
+c}function gb(b,a,c){if(!a)return b;for(var a=a.split("."),d,e=b,g=a.length,h=0;h<g;h++)d=a[h],b&&(b=(e=b)[d]);return!c&&H(b)?Ua(e,b):b}function Mb(b,a,c,d,e){return function(g,h){var f=h&&h.hasOwnProperty(b)?h:g,j;if(f===null||f===q)return f;if((f=f[b])&&f.then){if(!("$$v"in f))j=f,j.$$v=q,j.then(function(a){j.$$v=a});f=f.$$v}if(!a||f===null||f===q)return f;if((f=f[a])&&f.then){if(!("$$v"in f))j=f,j.$$v=q,j.then(function(a){j.$$v=a});f=f.$$v}if(!c||f===null||f===q)return f;if((f=f[c])&&f.then){if(!("$$v"in
+f))j=f,j.$$v=q,j.then(function(a){j.$$v=a});f=f.$$v}if(!d||f===null||f===q)return f;if((f=f[d])&&f.then){if(!("$$v"in f))j=f,j.$$v=q,j.then(function(a){j.$$v=a});f=f.$$v}if(!e||f===null||f===q)return f;if((f=f[e])&&f.then){if(!("$$v"in f))j=f,j.$$v=q,j.then(function(a){j.$$v=a});f=f.$$v}return f}}function Kb(b,a){if(ib.hasOwnProperty(b))return ib[b];var c=b.split("."),d=c.length,e;if(a)e=d<6?Mb(c[0],c[1],c[2],c[3],c[4]):function(a,b){var e=0,i;do i=Mb(c[e++],c[e++],c[e++],c[e++],c[e++])(a,b),b=q,
+a=i;while(e<d);return i};else{var g="var l, fn, p;\n";n(c,function(a,b){g+="if(s === null || s === undefined) return s;\nl=s;\ns="+(b?"s":'((k&&k.hasOwnProperty("'+a+'"))?k:s)')+'["'+a+'"];\nif (s && s.then) {\n if (!("$$v" in s)) {\n p=s;\n p.$$v = undefined;\n p.then(function(v) {p.$$v=v;});\n}\n s=s.$$v\n}\n'});g+="return s;";e=Function("s","k",g);e.toString=function(){return g}}return ib[b]=e}function Nc(){var b={};this.$get=["$filter","$sniffer",function(a,c){return function(d){switch(typeof d){case "string":return b.hasOwnProperty(d)?
+b[d]:b[d]=Mc(d,!1,a,c.csp);case "function":return d;default:return C}}}]}function Oc(){this.$get=["$rootScope","$exceptionHandler",function(b,a){return Pc(function(a){b.$evalAsync(a)},a)}]}function Pc(b,a){function c(a){return a}function d(a){return h(a)}var e=function(){var f=[],j,i;return i={resolve:function(a){if(f){var c=f;f=q;j=g(a);c.length&&b(function(){for(var a,b=0,d=c.length;b<d;b++)a=c[b],j.then(a[0],a[1])})}},reject:function(a){i.resolve(h(a))},promise:{then:function(b,i){var g=e(),h=
+function(d){try{g.resolve((b||c)(d))}catch(e){a(e),g.reject(e)}},o=function(b){try{g.resolve((i||d)(b))}catch(c){a(c),g.reject(c)}};f?f.push([h,o]):j.then(h,o);return g.promise}}}},g=function(a){return a&&a.then?a:{then:function(c){var d=e();b(function(){d.resolve(c(a))});return d.promise}}},h=function(a){return{then:function(c,i){var g=e();b(function(){g.resolve((i||d)(a))});return g.promise}}};return{defer:e,reject:h,when:function(f,j,i){var k=e(),m,l=function(b){try{return(j||c)(b)}catch(d){return a(d),
+h(d)}},t=function(b){try{return(i||d)(b)}catch(c){return a(c),h(c)}};b(function(){g(f).then(function(a){m||(m=!0,k.resolve(g(a).then(l,t)))},function(a){m||(m=!0,k.resolve(t(a)))})});return k.promise},all:function(a){var b=e(),c=a.length,d=[];c?n(a,function(a,e){g(a).then(function(a){e in d||(d[e]=a,--c||b.resolve(d))},function(a){e in d||b.reject(a)})}):b.resolve(d);return b.promise}}}function Qc(){var b={};this.when=function(a,c){b[a]=v({reloadOnSearch:!0},c);if(a){var d=a[a.length-1]=="/"?a.substr(0,
+a.length-1):a+"/";b[d]={redirectTo:a}}return this};this.otherwise=function(a){this.when(null,a);return this};this.$get=["$rootScope","$location","$routeParams","$q","$injector","$http","$templateCache",function(a,c,d,e,g,h,f){function j(a,b){for(var b="^"+b.replace(/[-\/\\^$*+?.()|[\]{}]/g,"\\$&")+"$",c="",d=[],e={},f=/:(\w+)/g,i,g=0;(i=f.exec(b))!==null;)c+=b.slice(g,i.index),c+="([^\\/]*)",d.push(i[1]),g=f.lastIndex;c+=b.substr(g);var h=a.match(RegExp(c));h&&n(d,function(a,b){e[a]=h[b+1]});return h?
+e:null}function i(){var b=k(),i=t.current;if(b&&i&&b.$route===i.$route&&ga(b.pathParams,i.pathParams)&&!b.reloadOnSearch&&!l)i.params=b.params,U(i.params,d),a.$broadcast("$routeUpdate",i);else if(b||i)l=!1,a.$broadcast("$routeChangeStart",b,i),(t.current=b)&&b.redirectTo&&(A(b.redirectTo)?c.path(m(b.redirectTo,b.params)).search(b.params).replace():c.url(b.redirectTo(b.pathParams,c.path(),c.search())).replace()),e.when(b).then(function(){if(b){var a=[],c=[],d;n(b.resolve||{},function(b,d){a.push(d);
+c.push(A(b)?g.get(b):g.invoke(b))});if(!x(d=b.template))if(x(d=b.templateUrl))d=h.get(d,{cache:f}).then(function(a){return a.data});x(d)&&(a.push("$template"),c.push(d));return e.all(c).then(function(b){var c={};n(b,function(b,d){c[a[d]]=b});return c})}}).then(function(c){if(b==t.current){if(b)b.locals=c,U(b.params,d);a.$broadcast("$routeChangeSuccess",b,i)}},function(c){b==t.current&&a.$broadcast("$routeChangeError",b,i,c)})}function k(){var a,d;n(b,function(b,e){if(!d&&(a=j(c.path(),e)))d=za(b,
+{params:v({},c.search(),a),pathParams:a}),d.$route=b});return d||b[null]&&za(b[null],{params:{},pathParams:{}})}function m(a,b){var c=[];n((a||"").split(":"),function(a,d){if(d==0)c.push(a);else{var e=a.match(/(\w+)(.*)/),f=e[1];c.push(b[f]);c.push(e[2]||"");delete b[f]}});return c.join("")}var l=!1,t={routes:b,reload:function(){l=!0;a.$evalAsync(i)}};a.$on("$locationChangeSuccess",i);return t}]}function Rc(){this.$get=I({})}function Sc(){var b=10;this.digestTtl=function(a){arguments.length&&(b=a);
+return b};this.$get=["$injector","$exceptionHandler","$parse",function(a,c,d){function e(){this.$id=ya();this.$$phase=this.$parent=this.$$watchers=this.$$nextSibling=this.$$prevSibling=this.$$childHead=this.$$childTail=null;this["this"]=this.$root=this;this.$$destroyed=!1;this.$$asyncQueue=[];this.$$listeners={};this.$$isolateBindings={}}function g(a){if(j.$$phase)throw Error(j.$$phase+" already in progress");j.$$phase=a}function h(a,b){var c=d(a);ra(c,b);return c}function f(){}e.prototype={$new:function(a){if(H(a))throw Error("API-CHANGE: Use $controller to instantiate controllers.");
+a?(a=new e,a.$root=this.$root):(a=function(){},a.prototype=this,a=new a,a.$id=ya());a["this"]=a;a.$$listeners={};a.$parent=this;a.$$asyncQueue=[];a.$$watchers=a.$$nextSibling=a.$$childHead=a.$$childTail=null;a.$$prevSibling=this.$$childTail;this.$$childHead?this.$$childTail=this.$$childTail.$$nextSibling=a:this.$$childHead=this.$$childTail=a;return a},$watch:function(a,b,c){var d=h(a,"watch"),e=this.$$watchers,g={fn:b,last:f,get:d,exp:a,eq:!!c};if(!H(b)){var j=h(b||C,"listener");g.fn=function(a,b,
+c){j(c)}}if(!e)e=this.$$watchers=[];e.unshift(g);return function(){Ta(e,g)}},$digest:function(){var a,d,e,h,t,o,p,s=b,n,F=[],z,q;g("$digest");do{p=!1;n=this;do{for(t=n.$$asyncQueue;t.length;)try{n.$eval(t.shift())}catch(K){c(K)}if(h=n.$$watchers)for(o=h.length;o--;)try{if(a=h[o],(d=a.get(n))!==(e=a.last)&&!(a.eq?ga(d,e):typeof d=="number"&&typeof e=="number"&&isNaN(d)&&isNaN(e)))p=!0,a.last=a.eq?U(d):d,a.fn(d,e===f?d:e,n),s<5&&(z=4-s,F[z]||(F[z]=[]),q=H(a.exp)?"fn: "+(a.exp.name||a.exp.toString()):
+a.exp,q+="; newVal: "+da(d)+"; oldVal: "+da(e),F[z].push(q))}catch(r){c(r)}if(!(h=n.$$childHead||n!==this&&n.$$nextSibling))for(;n!==this&&!(h=n.$$nextSibling);)n=n.$parent}while(n=h);if(p&&!s--)throw j.$$phase=null,Error(b+" $digest() iterations reached. Aborting!\nWatchers fired in the last 5 iterations: "+da(F));}while(p||t.length);j.$$phase=null},$destroy:function(){if(!(j==this||this.$$destroyed)){var a=this.$parent;this.$broadcast("$destroy");this.$$destroyed=!0;if(a.$$childHead==this)a.$$childHead=
+this.$$nextSibling;if(a.$$childTail==this)a.$$childTail=this.$$prevSibling;if(this.$$prevSibling)this.$$prevSibling.$$nextSibling=this.$$nextSibling;if(this.$$nextSibling)this.$$nextSibling.$$prevSibling=this.$$prevSibling;this.$parent=this.$$nextSibling=this.$$prevSibling=this.$$childHead=this.$$childTail=null}},$eval:function(a,b){return d(a)(this,b)},$evalAsync:function(a){this.$$asyncQueue.push(a)},$apply:function(a){try{return g("$apply"),this.$eval(a)}catch(b){c(b)}finally{j.$$phase=null;try{j.$digest()}catch(d){throw c(d),
+d;}}},$on:function(a,b){var c=this.$$listeners[a];c||(this.$$listeners[a]=c=[]);c.push(b);return function(){c[Aa(c,b)]=null}},$emit:function(a,b){var d=[],e,f=this,g=!1,h={name:a,targetScope:f,stopPropagation:function(){g=!0},preventDefault:function(){h.defaultPrevented=!0},defaultPrevented:!1},j=[h].concat(ha.call(arguments,1)),n,q;do{e=f.$$listeners[a]||d;h.currentScope=f;n=0;for(q=e.length;n<q;n++)if(e[n])try{if(e[n].apply(null,j),g)return h}catch(z){c(z)}else e.splice(n,1),n--,q--;f=f.$parent}while(f);
+return h},$broadcast:function(a,b){var d=this,e=this,f={name:a,targetScope:this,preventDefault:function(){f.defaultPrevented=!0},defaultPrevented:!1},g=[f].concat(ha.call(arguments,1)),h,j;do{d=e;f.currentScope=d;e=d.$$listeners[a]||[];h=0;for(j=e.length;h<j;h++)if(e[h])try{e[h].apply(null,g)}catch(n){c(n)}else e.splice(h,1),h--,j--;if(!(e=d.$$childHead||d!==this&&d.$$nextSibling))for(;d!==this&&!(e=d.$$nextSibling);)d=d.$parent}while(d=e);return f}};var j=new e;return j}]}function Tc(){this.$get=
+["$window",function(b){var a={},c=E((/android (\d+)/.exec(y(b.navigator.userAgent))||[])[1]);return{history:!(!b.history||!b.history.pushState||c<4),hashchange:"onhashchange"in b&&(!b.document.documentMode||b.document.documentMode>7),hasEvent:function(c){if(c=="input"&&Z==9)return!1;if(w(a[c])){var e=b.document.createElement("div");a[c]="on"+c in e}return a[c]},csp:!1}}]}function Uc(){this.$get=I(X)}function Nb(b){var a={},c,d,e;if(!b)return a;n(b.split("\n"),function(b){e=b.indexOf(":");c=y(O(b.substr(0,
+e)));d=O(b.substr(e+1));c&&(a[c]?a[c]+=", "+d:a[c]=d)});return a}function Ob(b){var a=M(b)?b:q;return function(c){a||(a=Nb(b));return c?a[y(c)]||null:a}}function Pb(b,a,c){if(H(c))return c(b,a);n(c,function(c){b=c(b,a)});return b}function Vc(){var b=/^\s*(\[|\{[^\{])/,a=/[\}\]]\s*$/,c=/^\)\]\}',?\n/,d=this.defaults={transformResponse:[function(d){A(d)&&(d=d.replace(c,""),b.test(d)&&a.test(d)&&(d=ob(d,!0)));return d}],transformRequest:[function(a){return M(a)&&xa.apply(a)!=="[object File]"?da(a):a}],
+headers:{common:{Accept:"application/json, text/plain, */*","X-Requested-With":"XMLHttpRequest"},post:{"Content-Type":"application/json;charset=utf-8"},put:{"Content-Type":"application/json;charset=utf-8"}}},e=this.responseInterceptors=[];this.$get=["$httpBackend","$browser","$cacheFactory","$rootScope","$q","$injector",function(a,b,c,j,i,k){function m(a){function c(a){var b=v({},a,{data:Pb(a.data,a.headers,f)});return 200<=a.status&&a.status<300?b:i.reject(b)}a.method=ma(a.method);var e=a.transformRequest||
+d.transformRequest,f=a.transformResponse||d.transformResponse,g=d.headers,g=v({"X-XSRF-TOKEN":b.cookies()["XSRF-TOKEN"]},g.common,g[y(a.method)],a.headers),e=Pb(a.data,Ob(g),e),j;w(a.data)&&delete g["Content-Type"];j=l(a,e,g);j=j.then(c,c);n(p,function(a){j=a(j)});j.success=function(b){j.then(function(c){b(c.data,c.status,c.headers,a)});return j};j.error=function(b){j.then(null,function(c){b(c.data,c.status,c.headers,a)});return j};return j}function l(b,c,d){function e(a,b,c){n&&(200<=a&&a<300?n.put(q,
+[a,b,Nb(c)]):n.remove(q));f(b,a,c);j.$apply()}function f(a,c,d){c=Math.max(c,0);(200<=c&&c<300?k.resolve:k.reject)({data:a,status:c,headers:Ob(d),config:b})}function h(){var a=Aa(m.pendingRequests,b);a!==-1&&m.pendingRequests.splice(a,1)}var k=i.defer(),l=k.promise,n,p,q=t(b.url,b.params);m.pendingRequests.push(b);l.then(h,h);b.cache&&b.method=="GET"&&(n=M(b.cache)?b.cache:o);if(n)if(p=n.get(q))if(p.then)return p.then(h,h),p;else B(p)?f(p[1],p[0],U(p[2])):f(p,200,{});else n.put(q,l);p||a(b.method,
+q,c,e,d,b.timeout,b.withCredentials);return l}function t(a,b){if(!b)return a;var c=[];fc(b,function(a,b){a==null||a==q||(M(a)&&(a=da(a)),c.push(encodeURIComponent(b)+"="+encodeURIComponent(a)))});return a+(a.indexOf("?")==-1?"?":"&")+c.join("&")}var o=c("$http"),p=[];n(e,function(a){p.push(A(a)?k.get(a):k.invoke(a))});m.pendingRequests=[];(function(a){n(arguments,function(a){m[a]=function(b,c){return m(v(c||{},{method:a,url:b}))}})})("get","delete","head","jsonp");(function(a){n(arguments,function(a){m[a]=
+function(b,c,d){return m(v(d||{},{method:a,url:b,data:c}))}})})("post","put");m.defaults=d;return m}]}function Wc(){this.$get=["$browser","$window","$document",function(b,a,c){return Xc(b,Yc,b.defer,a.angular.callbacks,c[0],a.location.protocol.replace(":",""))}]}function Xc(b,a,c,d,e,g){function h(a,b){var c=e.createElement("script"),d=function(){e.body.removeChild(c);b&&b()};c.type="text/javascript";c.src=a;Z?c.onreadystatechange=function(){/loaded|complete/.test(c.readyState)&&d()}:c.onload=c.onerror=
+d;e.body.appendChild(c)}return function(e,j,i,k,m,l,t){function o(a,c,d,e){c=(j.match(Gb)||["",g])[1]=="file"?d?200:404:c;a(c==1223?204:c,d,e);b.$$completeOutstandingRequest(C)}b.$$incOutstandingRequestCount();j=j||b.url();if(y(e)=="jsonp"){var p="_"+(d.counter++).toString(36);d[p]=function(a){d[p].data=a};h(j.replace("JSON_CALLBACK","angular.callbacks."+p),function(){d[p].data?o(k,200,d[p].data):o(k,-2);delete d[p]})}else{var s=new a;s.open(e,j,!0);n(m,function(a,b){a&&s.setRequestHeader(b,a)});
+var q;s.onreadystatechange=function(){if(s.readyState==4){var a=s.getAllResponseHeaders(),b=["Cache-Control","Content-Language","Content-Type","Expires","Last-Modified","Pragma"];a||(a="",n(b,function(b){var c=s.getResponseHeader(b);c&&(a+=b+": "+c+"\n")}));o(k,q||s.status,s.responseText,a)}};if(t)s.withCredentials=!0;s.send(i||"");l>0&&c(function(){q=-1;s.abort()},l)}}}function Zc(){this.$get=function(){return{id:"en-us",NUMBER_FORMATS:{DECIMAL_SEP:".",GROUP_SEP:",",PATTERNS:[{minInt:1,minFrac:0,
+maxFrac:3,posPre:"",posSuf:"",negPre:"-",negSuf:"",gSize:3,lgSize:3},{minInt:1,minFrac:2,maxFrac:2,posPre:"\u00a4",posSuf:"",negPre:"(\u00a4",negSuf:")",gSize:3,lgSize:3}],CURRENCY_SYM:"$"},DATETIME_FORMATS:{MONTH:"January,February,March,April,May,June,July,August,September,October,November,December".split(","),SHORTMONTH:"Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec".split(","),DAY:"Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday".split(","),SHORTDAY:"Sun,Mon,Tue,Wed,Thu,Fri,Sat".split(","),
+AMPMS:["AM","PM"],medium:"MMM d, y h:mm:ss a","short":"M/d/yy h:mm a",fullDate:"EEEE, MMMM d, y",longDate:"MMMM d, y",mediumDate:"MMM d, y",shortDate:"M/d/yy",mediumTime:"h:mm:ss a",shortTime:"h:mm a"},pluralCat:function(b){return b===1?"one":"other"}}}}function $c(){this.$get=["$rootScope","$browser","$q","$exceptionHandler",function(b,a,c,d){function e(e,f,j){var i=c.defer(),k=i.promise,m=x(j)&&!j,f=a.defer(function(){try{i.resolve(e())}catch(a){i.reject(a),d(a)}m||b.$apply()},f),j=function(){delete g[k.$$timeoutId]};
+k.$$timeoutId=f;g[f]=i;k.then(j,j);return k}var g={};e.cancel=function(b){return b&&b.$$timeoutId in g?(g[b.$$timeoutId].reject("canceled"),a.defer.cancel(b.$$timeoutId)):!1};return e}]}function Qb(b){function a(a,e){return b.factory(a+c,e)}var c="Filter";this.register=a;this.$get=["$injector",function(a){return function(b){return a.get(b+c)}}];a("currency",Rb);a("date",Sb);a("filter",ad);a("json",bd);a("limitTo",cd);a("lowercase",dd);a("number",Tb);a("orderBy",Ub);a("uppercase",ed)}function ad(){return function(b,
+a){if(!B(b))return b;var c=[];c.check=function(a){for(var b=0;b<c.length;b++)if(!c[b](a))return!1;return!0};var d=function(a,b){if(b.charAt(0)==="!")return!d(a,b.substr(1));switch(typeof a){case "boolean":case "number":case "string":return(""+a).toLowerCase().indexOf(b)>-1;case "object":for(var c in a)if(c.charAt(0)!=="$"&&d(a[c],b))return!0;return!1;case "array":for(c=0;c<a.length;c++)if(d(a[c],b))return!0;return!1;default:return!1}};switch(typeof a){case "boolean":case "number":case "string":a=
+{$:a};case "object":for(var e in a)e=="$"?function(){var b=(""+a[e]).toLowerCase();b&&c.push(function(a){return d(a,b)})}():function(){var b=e,f=(""+a[e]).toLowerCase();f&&c.push(function(a){return d(gb(a,b),f)})}();break;case "function":c.push(a);break;default:return b}for(var g=[],h=0;h<b.length;h++){var f=b[h];c.check(f)&&g.push(f)}return g}}function Rb(b){var a=b.NUMBER_FORMATS;return function(b,d){if(w(d))d=a.CURRENCY_SYM;return Vb(b,a.PATTERNS[1],a.GROUP_SEP,a.DECIMAL_SEP,2).replace(/\u00A4/g,
+d)}}function Tb(b){var a=b.NUMBER_FORMATS;return function(b,d){return Vb(b,a.PATTERNS[0],a.GROUP_SEP,a.DECIMAL_SEP,d)}}function Vb(b,a,c,d,e){if(isNaN(b)||!isFinite(b))return"";var g=b<0,b=Math.abs(b),h=b+"",f="",j=[],i=!1;if(h.indexOf("e")!==-1){var k=h.match(/([\d\.]+)e(-?)(\d+)/);k&&k[2]=="-"&&k[3]>e+1?h="0":(f=h,i=!0)}if(!i){h=(h.split(Wb)[1]||"").length;w(e)&&(e=Math.min(Math.max(a.minFrac,h),a.maxFrac));var h=Math.pow(10,e),b=Math.round(b*h)/h,b=(""+b).split(Wb),h=b[0],b=b[1]||"",i=0,k=a.lgSize,
+m=a.gSize;if(h.length>=k+m)for(var i=h.length-k,l=0;l<i;l++)(i-l)%m===0&&l!==0&&(f+=c),f+=h.charAt(l);for(l=i;l<h.length;l++)(h.length-l)%k===0&&l!==0&&(f+=c),f+=h.charAt(l);for(;b.length<e;)b+="0";e&&e!=="0"&&(f+=d+b.substr(0,e))}j.push(g?a.negPre:a.posPre);j.push(f);j.push(g?a.negSuf:a.posSuf);return j.join("")}function jb(b,a,c){var d="";b<0&&(d="-",b=-b);for(b=""+b;b.length<a;)b="0"+b;c&&(b=b.substr(b.length-a));return d+b}function N(b,a,c,d){return function(e){e=e["get"+b]();if(c>0||e>-c)e+=
+c;e===0&&c==-12&&(e=12);return jb(e,a,d)}}function Ka(b,a){return function(c,d){var e=c["get"+b](),g=ma(a?"SHORT"+b:b);return d[g][e]}}function Sb(b){function a(a){var b;if(b=a.match(c)){var a=new Date(0),g=0,h=0;b[9]&&(g=E(b[9]+b[10]),h=E(b[9]+b[11]));a.setUTCFullYear(E(b[1]),E(b[2])-1,E(b[3]));a.setUTCHours(E(b[4]||0)-g,E(b[5]||0)-h,E(b[6]||0),E(b[7]||0))}return a}var c=/^(\d{4})-?(\d\d)-?(\d\d)(?:T(\d\d)(?::?(\d\d)(?::?(\d\d)(?:\.(\d+))?)?)?(Z|([+-])(\d\d):?(\d\d))?)?$/;return function(c,e){var g=
+"",h=[],f,j,e=e||"mediumDate",e=b.DATETIME_FORMATS[e]||e;A(c)&&(c=fd.test(c)?E(c):a(c));Ra(c)&&(c=new Date(c));if(!oa(c))return c;for(;e;)(j=gd.exec(e))?(h=h.concat(ha.call(j,1)),e=h.pop()):(h.push(e),e=null);n(h,function(a){f=hd[a];g+=f?f(c,b.DATETIME_FORMATS):a.replace(/(^'|'$)/g,"").replace(/''/g,"'")});return g}}function bd(){return function(b){return da(b,!0)}}function cd(){return function(b,a){if(!(b instanceof Array))return b;var a=E(a),c=[],d,e;if(!b||!(b instanceof Array))return c;a>b.length?
+a=b.length:a<-b.length&&(a=-b.length);a>0?(d=0,e=a):(d=b.length+a,e=b.length);for(;d<e;d++)c.push(b[d]);return c}}function Ub(b){return function(a,c,d){function e(a,b){return Va(b)?function(b,c){return a(c,b)}:a}if(!B(a))return a;if(!c)return a;for(var c=B(c)?c:[c],c=Sa(c,function(a){var c=!1,d=a||na;if(A(a)){if(a.charAt(0)=="+"||a.charAt(0)=="-")c=a.charAt(0)=="-",a=a.substring(1);d=b(a)}return e(function(a,b){var c;c=d(a);var e=d(b),f=typeof c,g=typeof e;f==g?(f=="string"&&(c=c.toLowerCase()),f==
+"string"&&(e=e.toLowerCase()),c=c===e?0:c<e?-1:1):c=f<g?-1:1;return c},c)}),g=[],h=0;h<a.length;h++)g.push(a[h]);return g.sort(e(function(a,b){for(var d=0;d<c.length;d++){var e=c[d](a,b);if(e!==0)return e}return 0},d))}}function Q(b){H(b)&&(b={link:b});b.restrict=b.restrict||"AC";return I(b)}function Xb(b,a){function c(a,c){c=c?"-"+Za(c,"-"):"";b.removeClass((a?La:Ma)+c).addClass((a?Ma:La)+c)}var d=this,e=b.parent().controller("form")||Na,g=0,h=d.$error={};d.$name=a.name;d.$dirty=!1;d.$pristine=!0;
+d.$valid=!0;d.$invalid=!1;e.$addControl(d);b.addClass(Oa);c(!0);d.$addControl=function(a){a.$name&&!d.hasOwnProperty(a.$name)&&(d[a.$name]=a)};d.$removeControl=function(a){a.$name&&d[a.$name]===a&&delete d[a.$name];n(h,function(b,c){d.$setValidity(c,!0,a)})};d.$setValidity=function(a,b,i){var k=h[a];if(b){if(k&&(Ta(k,i),!k.length)){g--;if(!g)c(b),d.$valid=!0,d.$invalid=!1;h[a]=!1;c(!0,a);e.$setValidity(a,!0,d)}}else{g||c(b);if(k){if(Aa(k,i)!=-1)return}else h[a]=k=[],g++,c(!1,a),e.$setValidity(a,!1,
+d);k.push(i);d.$valid=!1;d.$invalid=!0}};d.$setDirty=function(){b.removeClass(Oa).addClass(Yb);d.$dirty=!0;d.$pristine=!1;e.$setDirty()}}function T(b){return w(b)||b===""||b===null||b!==b}function Pa(b,a,c,d,e,g){var h=function(){var c=O(a.val());d.$viewValue!==c&&b.$apply(function(){d.$setViewValue(c)})};if(e.hasEvent("input"))a.bind("input",h);else{var f;a.bind("keydown",function(a){a=a.keyCode;a===91||15<a&&a<19||37<=a&&a<=40||f||(f=g.defer(function(){h();f=null}))});a.bind("change",h)}d.$render=
+function(){a.val(T(d.$viewValue)?"":d.$viewValue)};var j=c.ngPattern,i=function(a,b){return T(b)||a.test(b)?(d.$setValidity("pattern",!0),b):(d.$setValidity("pattern",!1),q)};j&&(j.match(/^\/(.*)\/$/)?(j=RegExp(j.substr(1,j.length-2)),e=function(a){return i(j,a)}):e=function(a){var c=b.$eval(j);if(!c||!c.test)throw Error("Expected "+j+" to be a RegExp but was "+c);return i(c,a)},d.$formatters.push(e),d.$parsers.push(e));if(c.ngMinlength){var k=E(c.ngMinlength),e=function(a){return!T(a)&&a.length<
+k?(d.$setValidity("minlength",!1),q):(d.$setValidity("minlength",!0),a)};d.$parsers.push(e);d.$formatters.push(e)}if(c.ngMaxlength){var m=E(c.ngMaxlength),c=function(a){return!T(a)&&a.length>m?(d.$setValidity("maxlength",!1),q):(d.$setValidity("maxlength",!0),a)};d.$parsers.push(c);d.$formatters.push(c)}}function kb(b,a){b="ngClass"+b;return Q(function(c,d,e){function g(b){if(a===!0||c.$index%2===a)j&&b!==j&&h(j),f(b);j=b}function h(a){M(a)&&!B(a)&&(a=Sa(a,function(a,b){if(a)return b}));d.removeClass(B(a)?
+a.join(" "):a)}function f(a){M(a)&&!B(a)&&(a=Sa(a,function(a,b){if(a)return b}));a&&d.addClass(B(a)?a.join(" "):a)}var j=q;c.$watch(e[b],g,!0);e.$observe("class",function(){var a=c.$eval(e[b]);g(a,a)});b!=="ngClass"&&c.$watch("$index",function(d,g){var j=d%2;j!==g%2&&(j==a?f(c.$eval(e[b])):h(c.$eval(e[b])))})})}var y=function(b){return A(b)?b.toLowerCase():b},ma=function(b){return A(b)?b.toUpperCase():b},Z=E((/msie (\d+)/.exec(y(navigator.userAgent))||[])[1]),u,ca,ha=[].slice,Qa=[].push,xa=Object.prototype.toString,
+Zb=X.angular||(X.angular={}),ta,fb,aa=["0","0","0"];C.$inject=[];na.$inject=[];fb=Z<9?function(b){b=b.nodeName?b:b[0];return b.scopeName&&b.scopeName!="HTML"?ma(b.scopeName+":"+b.nodeName):b.nodeName}:function(b){return b.nodeName?b.nodeName:b[0].nodeName};var kc=/[A-Z]/g,id={full:"1.0.5",major:1,minor:0,dot:5,codeName:"flatulent-propulsion"},Ca=L.cache={},Ba=L.expando="ng-"+(new Date).getTime(),oc=1,$b=X.document.addEventListener?function(b,a,c){b.addEventListener(a,c,!1)}:function(b,a,c){b.attachEvent("on"+
+a,c)},db=X.document.removeEventListener?function(b,a,c){b.removeEventListener(a,c,!1)}:function(b,a,c){b.detachEvent("on"+a,c)},mc=/([\:\-\_]+(.))/g,nc=/^moz([A-Z])/,va=L.prototype={ready:function(b){function a(){c||(c=!0,b())}var c=!1;this.bind("DOMContentLoaded",a);L(X).bind("load",a)},toString:function(){var b=[];n(this,function(a){b.push(""+a)});return"["+b.join(", ")+"]"},eq:function(b){return b>=0?u(this[b]):u(this[this.length+b])},length:0,push:Qa,sort:[].sort,splice:[].splice},Fa={};n("multiple,selected,checked,disabled,readOnly,required".split(","),
+function(b){Fa[y(b)]=b});var Ab={};n("input,select,option,textarea,button,form".split(","),function(b){Ab[ma(b)]=!0});n({data:vb,inheritedData:Ea,scope:function(b){return Ea(b,"$scope")},controller:yb,injector:function(b){return Ea(b,"$injector")},removeAttr:function(b,a){b.removeAttribute(a)},hasClass:Da,css:function(b,a,c){a=sb(a);if(x(c))b.style[a]=c;else{var d;Z<=8&&(d=b.currentStyle&&b.currentStyle[a],d===""&&(d="auto"));d=d||b.style[a];Z<=8&&(d=d===""?q:d);return d}},attr:function(b,a,c){var d=
+y(a);if(Fa[d])if(x(c))c?(b[a]=!0,b.setAttribute(a,d)):(b[a]=!1,b.removeAttribute(d));else return b[a]||(b.attributes.getNamedItem(a)||C).specified?d:q;else if(x(c))b.setAttribute(a,c);else if(b.getAttribute)return b=b.getAttribute(a,2),b===null?q:b},prop:function(b,a,c){if(x(c))b[a]=c;else return b[a]},text:v(Z<9?function(b,a){if(b.nodeType==1){if(w(a))return b.innerText;b.innerText=a}else{if(w(a))return b.nodeValue;b.nodeValue=a}}:function(b,a){if(w(a))return b.textContent;b.textContent=a},{$dv:""}),
+val:function(b,a){if(w(a))return b.value;b.value=a},html:function(b,a){if(w(a))return b.innerHTML;for(var c=0,d=b.childNodes;c<d.length;c++)sa(d[c]);b.innerHTML=a}},function(b,a){L.prototype[a]=function(a,d){var e,g;if((b.length==2&&b!==Da&&b!==yb?a:d)===q)if(M(a)){for(e=0;e<this.length;e++)if(b===vb)b(this[e],a);else for(g in a)b(this[e],g,a[g]);return this}else{if(this.length)return b(this[0],a,d)}else{for(e=0;e<this.length;e++)b(this[e],a,d);return this}return b.$dv}});n({removeData:tb,dealoc:sa,
+bind:function a(c,d,e){var g=ba(c,"events"),h=ba(c,"handle");g||ba(c,"events",g={});h||ba(c,"handle",h=pc(c,g));n(d.split(" "),function(d){var j=g[d];if(!j){if(d=="mouseenter"||d=="mouseleave"){var i=0;g.mouseenter=[];g.mouseleave=[];a(c,"mouseover",function(a){i++;i==1&&h(a,"mouseenter")});a(c,"mouseout",function(a){i--;i==0&&h(a,"mouseleave")})}else $b(c,d,h),g[d]=[];j=g[d]}j.push(e)})},unbind:ub,replaceWith:function(a,c){var d,e=a.parentNode;sa(a);n(new L(c),function(c){d?e.insertBefore(c,d.nextSibling):
+e.replaceChild(c,a);d=c})},children:function(a){var c=[];n(a.childNodes,function(a){a.nodeType===1&&c.push(a)});return c},contents:function(a){return a.childNodes||[]},append:function(a,c){n(new L(c),function(c){a.nodeType===1&&a.appendChild(c)})},prepend:function(a,c){if(a.nodeType===1){var d=a.firstChild;n(new L(c),function(c){d?a.insertBefore(c,d):(a.appendChild(c),d=c)})}},wrap:function(a,c){var c=u(c)[0],d=a.parentNode;d&&d.replaceChild(c,a);c.appendChild(a)},remove:function(a){sa(a);var c=a.parentNode;
+c&&c.removeChild(a)},after:function(a,c){var d=a,e=a.parentNode;n(new L(c),function(a){e.insertBefore(a,d.nextSibling);d=a})},addClass:xb,removeClass:wb,toggleClass:function(a,c,d){w(d)&&(d=!Da(a,c));(d?xb:wb)(a,c)},parent:function(a){return(a=a.parentNode)&&a.nodeType!==11?a:null},next:function(a){if(a.nextElementSibling)return a.nextElementSibling;for(a=a.nextSibling;a!=null&&a.nodeType!==1;)a=a.nextSibling;return a},find:function(a,c){return a.getElementsByTagName(c)},clone:cb,triggerHandler:function(a,
+c){var d=(ba(a,"events")||{})[c];n(d,function(c){c.call(a,null)})}},function(a,c){L.prototype[c]=function(c,e){for(var g,h=0;h<this.length;h++)g==q?(g=a(this[h],c,e),g!==q&&(g=u(g))):bb(g,a(this[h],c,e));return g==q?this:g}});Ga.prototype={put:function(a,c){this[fa(a)]=c},get:function(a){return this[fa(a)]},remove:function(a){var c=this[a=fa(a)];delete this[a];return c}};eb.prototype={push:function(a,c){var d=this[a=fa(a)];d?d.push(c):this[a]=[c]},shift:function(a){var c=this[a=fa(a)];if(c)return c.length==
+1?(delete this[a],c[0]):c.shift()},peek:function(a){if(a=this[fa(a)])return a[0]}};var rc=/^function\s*[^\(]*\(\s*([^\)]*)\)/m,sc=/,/,tc=/^\s*(_?)(\S+?)\1\s*$/,qc=/((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg,Db="Non-assignable model expression: ";Cb.$inject=["$provide"];var Ac=/^(x[\:\-_]|data[\:\-_])/i,Gb=/^([^:]+):\/\/(\w+:{0,1}\w*@)?([\w\.-]*)(:([0-9]+))?(\/[^\?#]*)?(\?([^#]*))?(#(.*))?$/,ac=/^([^\?#]*)?(\?([^#]*))?(#(.*))?$/,Hc=ac,Hb={http:80,https:443,ftp:21};hb.prototype={$$replace:!1,absUrl:Ia("$$absUrl"),
+url:function(a,c){if(w(a))return this.$$url;var d=ac.exec(a);d[1]&&this.path(decodeURIComponent(d[1]));if(d[2]||d[1])this.search(d[3]||"");this.hash(d[5]||"",c);return this},protocol:Ia("$$protocol"),host:Ia("$$host"),port:Ia("$$port"),path:Jb("$$path",function(a){return a.charAt(0)=="/"?a:"/"+a}),search:function(a,c){if(w(a))return this.$$search;x(c)?c===null?delete this.$$search[a]:this.$$search[a]=c:this.$$search=A(a)?Wa(a):a;this.$$compose();return this},hash:Jb("$$hash",na),replace:function(){this.$$replace=
+!0;return this}};Ha.prototype=za(hb.prototype);Ib.prototype=za(Ha.prototype);var Ja={"null":function(){return null},"true":function(){return!0},"false":function(){return!1},undefined:C,"+":function(a,c,d,e){d=d(a,c);e=e(a,c);return x(d)?x(e)?d+e:d:x(e)?e:q},"-":function(a,c,d,e){d=d(a,c);e=e(a,c);return(x(d)?d:0)-(x(e)?e:0)},"*":function(a,c,d,e){return d(a,c)*e(a,c)},"/":function(a,c,d,e){return d(a,c)/e(a,c)},"%":function(a,c,d,e){return d(a,c)%e(a,c)},"^":function(a,c,d,e){return d(a,c)^e(a,c)},
+"=":C,"==":function(a,c,d,e){return d(a,c)==e(a,c)},"!=":function(a,c,d,e){return d(a,c)!=e(a,c)},"<":function(a,c,d,e){return d(a,c)<e(a,c)},">":function(a,c,d,e){return d(a,c)>e(a,c)},"<=":function(a,c,d,e){return d(a,c)<=e(a,c)},">=":function(a,c,d,e){return d(a,c)>=e(a,c)},"&&":function(a,c,d,e){return d(a,c)&&e(a,c)},"||":function(a,c,d,e){return d(a,c)||e(a,c)},"&":function(a,c,d,e){return d(a,c)&e(a,c)},"|":function(a,c,d,e){return e(a,c)(a,c,d(a,c))},"!":function(a,c,d){return!d(a,c)}},Lc=
+{n:"\n",f:"\u000c",r:"\r",t:"\t",v:"\u000b","'":"'",'"':'"'},ib={},Yc=X.XMLHttpRequest||function(){try{return new ActiveXObject("Msxml2.XMLHTTP.6.0")}catch(a){}try{return new ActiveXObject("Msxml2.XMLHTTP.3.0")}catch(c){}try{return new ActiveXObject("Msxml2.XMLHTTP")}catch(d){}throw Error("This browser does not support XMLHttpRequest.");};Qb.$inject=["$provide"];Rb.$inject=["$locale"];Tb.$inject=["$locale"];var Wb=".",hd={yyyy:N("FullYear",4),yy:N("FullYear",2,0,!0),y:N("FullYear",1),MMMM:Ka("Month"),
+MMM:Ka("Month",!0),MM:N("Month",2,1),M:N("Month",1,1),dd:N("Date",2),d:N("Date",1),HH:N("Hours",2),H:N("Hours",1),hh:N("Hours",2,-12),h:N("Hours",1,-12),mm:N("Minutes",2),m:N("Minutes",1),ss:N("Seconds",2),s:N("Seconds",1),EEEE:Ka("Day"),EEE:Ka("Day",!0),a:function(a,c){return a.getHours()<12?c.AMPMS[0]:c.AMPMS[1]},Z:function(a){var a=-1*a.getTimezoneOffset(),c=a>=0?"+":"";c+=jb(a/60,2)+jb(Math.abs(a%60),2);return c}},gd=/((?:[^yMdHhmsaZE']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d+|H+|h+|m+|s+|a|Z))(.*)/,
+fd=/^\d+$/;Sb.$inject=["$locale"];var dd=I(y),ed=I(ma);Ub.$inject=["$parse"];var jd=I({restrict:"E",compile:function(a,c){Z<=8&&(!c.href&&!c.name&&c.$set("href",""),a.append(Y.createComment("IE fix")));return function(a,c){c.bind("click",function(a){c.attr("href")||a.preventDefault()})}}}),lb={};n(Fa,function(a,c){var d=ea("ng-"+c);lb[d]=function(){return{priority:100,compile:function(){return function(a,g,h){a.$watch(h[d],function(a){h.$set(c,!!a)})}}}}});n(["src","href"],function(a){var c=ea("ng-"+
+a);lb[c]=function(){return{priority:99,link:function(d,e,g){g.$observe(c,function(c){c&&(g.$set(a,c),Z&&e.prop(a,g[a]))})}}}});var Na={$addControl:C,$removeControl:C,$setValidity:C,$setDirty:C};Xb.$inject=["$element","$attrs","$scope"];var Qa=function(a){return["$timeout",function(c){var d={name:"form",restrict:"E",controller:Xb,compile:function(){return{pre:function(a,d,h,f){if(!h.action){var j=function(a){a.preventDefault?a.preventDefault():a.returnValue=!1};$b(d[0],"submit",j);d.bind("$destroy",
+function(){c(function(){db(d[0],"submit",j)},0,!1)})}var i=d.parent().controller("form"),k=h.name||h.ngForm;k&&(a[k]=f);i&&d.bind("$destroy",function(){i.$removeControl(f);k&&(a[k]=q);v(f,Na)})}}}};return a?v(U(d),{restrict:"EAC"}):d}]},kd=Qa(),ld=Qa(!0),md=/^(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?$/,nd=/^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,4}$/,od=/^\s*(\-|\+)?(\d+|(\d*(\.\d*)))\s*$/,bc={text:Pa,number:function(a,c,d,e,g,h){Pa(a,c,d,e,g,h);e.$parsers.push(function(a){var c=
+T(a);return c||od.test(a)?(e.$setValidity("number",!0),a===""?null:c?a:parseFloat(a)):(e.$setValidity("number",!1),q)});e.$formatters.push(function(a){return T(a)?"":""+a});if(d.min){var f=parseFloat(d.min),a=function(a){return!T(a)&&a<f?(e.$setValidity("min",!1),q):(e.$setValidity("min",!0),a)};e.$parsers.push(a);e.$formatters.push(a)}if(d.max){var j=parseFloat(d.max),d=function(a){return!T(a)&&a>j?(e.$setValidity("max",!1),q):(e.$setValidity("max",!0),a)};e.$parsers.push(d);e.$formatters.push(d)}e.$formatters.push(function(a){return T(a)||
+Ra(a)?(e.$setValidity("number",!0),a):(e.$setValidity("number",!1),q)})},url:function(a,c,d,e,g,h){Pa(a,c,d,e,g,h);a=function(a){return T(a)||md.test(a)?(e.$setValidity("url",!0),a):(e.$setValidity("url",!1),q)};e.$formatters.push(a);e.$parsers.push(a)},email:function(a,c,d,e,g,h){Pa(a,c,d,e,g,h);a=function(a){return T(a)||nd.test(a)?(e.$setValidity("email",!0),a):(e.$setValidity("email",!1),q)};e.$formatters.push(a);e.$parsers.push(a)},radio:function(a,c,d,e){w(d.name)&&c.attr("name",ya());c.bind("click",
+function(){c[0].checked&&a.$apply(function(){e.$setViewValue(d.value)})});e.$render=function(){c[0].checked=d.value==e.$viewValue};d.$observe("value",e.$render)},checkbox:function(a,c,d,e){var g=d.ngTrueValue,h=d.ngFalseValue;A(g)||(g=!0);A(h)||(h=!1);c.bind("click",function(){a.$apply(function(){e.$setViewValue(c[0].checked)})});e.$render=function(){c[0].checked=e.$viewValue};e.$formatters.push(function(a){return a===g});e.$parsers.push(function(a){return a?g:h})},hidden:C,button:C,submit:C,reset:C},
+cc=["$browser","$sniffer",function(a,c){return{restrict:"E",require:"?ngModel",link:function(d,e,g,h){h&&(bc[y(g.type)]||bc.text)(d,e,g,h,c,a)}}}],Ma="ng-valid",La="ng-invalid",Oa="ng-pristine",Yb="ng-dirty",pd=["$scope","$exceptionHandler","$attrs","$element","$parse",function(a,c,d,e,g){function h(a,c){c=c?"-"+Za(c,"-"):"";e.removeClass((a?La:Ma)+c).addClass((a?Ma:La)+c)}this.$modelValue=this.$viewValue=Number.NaN;this.$parsers=[];this.$formatters=[];this.$viewChangeListeners=[];this.$pristine=
+!0;this.$dirty=!1;this.$valid=!0;this.$invalid=!1;this.$name=d.name;var f=g(d.ngModel),j=f.assign;if(!j)throw Error(Db+d.ngModel+" ("+qa(e)+")");this.$render=C;var i=e.inheritedData("$formController")||Na,k=0,m=this.$error={};e.addClass(Oa);h(!0);this.$setValidity=function(a,c){if(m[a]!==!c){if(c){if(m[a]&&k--,!k)h(!0),this.$valid=!0,this.$invalid=!1}else h(!1),this.$invalid=!0,this.$valid=!1,k++;m[a]=!c;h(c,a);i.$setValidity(a,c,this)}};this.$setViewValue=function(d){this.$viewValue=d;if(this.$pristine)this.$dirty=
+!0,this.$pristine=!1,e.removeClass(Oa).addClass(Yb),i.$setDirty();n(this.$parsers,function(a){d=a(d)});if(this.$modelValue!==d)this.$modelValue=d,j(a,d),n(this.$viewChangeListeners,function(a){try{a()}catch(d){c(d)}})};var l=this;a.$watch(function(){var c=f(a);if(l.$modelValue!==c){var d=l.$formatters,e=d.length;for(l.$modelValue=c;e--;)c=d[e](c);if(l.$viewValue!==c)l.$viewValue=c,l.$render()}})}],qd=function(){return{require:["ngModel","^?form"],controller:pd,link:function(a,c,d,e){var g=e[0],h=
+e[1]||Na;h.$addControl(g);c.bind("$destroy",function(){h.$removeControl(g)})}}},rd=I({require:"ngModel",link:function(a,c,d,e){e.$viewChangeListeners.push(function(){a.$eval(d.ngChange)})}}),dc=function(){return{require:"?ngModel",link:function(a,c,d,e){if(e){d.required=!0;var g=function(a){if(d.required&&(T(a)||a===!1))e.$setValidity("required",!1);else return e.$setValidity("required",!0),a};e.$formatters.push(g);e.$parsers.unshift(g);d.$observe("required",function(){g(e.$viewValue)})}}}},sd=function(){return{require:"ngModel",
+link:function(a,c,d,e){var g=(a=/\/(.*)\//.exec(d.ngList))&&RegExp(a[1])||d.ngList||",";e.$parsers.push(function(a){var c=[];a&&n(a.split(g),function(a){a&&c.push(O(a))});return c});e.$formatters.push(function(a){return B(a)?a.join(", "):q})}}},td=/^(true|false|\d+)$/,ud=function(){return{priority:100,compile:function(a,c){return td.test(c.ngValue)?function(a,c,g){g.$set("value",a.$eval(g.ngValue))}:function(a,c,g){a.$watch(g.ngValue,function(a){g.$set("value",a,!1)})}}}},vd=Q(function(a,c,d){c.addClass("ng-binding").data("$binding",
+d.ngBind);a.$watch(d.ngBind,function(a){c.text(a==q?"":a)})}),wd=["$interpolate",function(a){return function(c,d,e){c=a(d.attr(e.$attr.ngBindTemplate));d.addClass("ng-binding").data("$binding",c);e.$observe("ngBindTemplate",function(a){d.text(a)})}}],xd=[function(){return function(a,c,d){c.addClass("ng-binding").data("$binding",d.ngBindHtmlUnsafe);a.$watch(d.ngBindHtmlUnsafe,function(a){c.html(a||"")})}}],yd=kb("",!0),zd=kb("Odd",0),Ad=kb("Even",1),Bd=Q({compile:function(a,c){c.$set("ngCloak",q);
+a.removeClass("ng-cloak")}}),Cd=[function(){return{scope:!0,controller:"@"}}],Dd=["$sniffer",function(a){return{priority:1E3,compile:function(){a.csp=!0}}}],ec={};n("click dblclick mousedown mouseup mouseover mouseout mousemove mouseenter mouseleave".split(" "),function(a){var c=ea("ng-"+a);ec[c]=["$parse",function(d){return function(e,g,h){var f=d(h[c]);g.bind(y(a),function(a){e.$apply(function(){f(e,{$event:a})})})}}]});var Ed=Q(function(a,c,d){c.bind("submit",function(){a.$apply(d.ngSubmit)})}),
+Fd=["$http","$templateCache","$anchorScroll","$compile",function(a,c,d,e){return{restrict:"ECA",terminal:!0,compile:function(g,h){var f=h.ngInclude||h.src,j=h.onload||"",i=h.autoscroll;return function(g,h){var l=0,n,o=function(){n&&(n.$destroy(),n=null);h.html("")};g.$watch(f,function(f){var s=++l;f?a.get(f,{cache:c}).success(function(a){s===l&&(n&&n.$destroy(),n=g.$new(),h.html(a),e(h.contents())(n),x(i)&&(!i||g.$eval(i))&&d(),n.$emit("$includeContentLoaded"),g.$eval(j))}).error(function(){s===l&&
+o()}):o()})}}}}],Gd=Q({compile:function(){return{pre:function(a,c,d){a.$eval(d.ngInit)}}}}),Hd=Q({terminal:!0,priority:1E3}),Id=["$locale","$interpolate",function(a,c){var d=/{}/g;return{restrict:"EA",link:function(e,g,h){var f=h.count,j=g.attr(h.$attr.when),i=h.offset||0,k=e.$eval(j),m={},l=c.startSymbol(),t=c.endSymbol();n(k,function(a,e){m[e]=c(a.replace(d,l+f+"-"+i+t))});e.$watch(function(){var c=parseFloat(e.$eval(f));return isNaN(c)?"":(k[c]||(c=a.pluralCat(c-i)),m[c](e,g,!0))},function(a){g.text(a)})}}}],
+Jd=Q({transclude:"element",priority:1E3,terminal:!0,compile:function(a,c,d){return function(a,c,h){var f=h.ngRepeat,h=f.match(/^\s*(.+)\s+in\s+(.*)\s*$/),j,i,k;if(!h)throw Error("Expected ngRepeat in form of '_item_ in _collection_' but got '"+f+"'.");f=h[1];j=h[2];h=f.match(/^(?:([\$\w]+)|\(([\$\w]+)\s*,\s*([\$\w]+)\))$/);if(!h)throw Error("'item' in 'item in collection' should be identifier or (key, value) but got '"+f+"'.");i=h[3]||h[1];k=h[2];var m=new eb;a.$watch(function(a){var e,f,h=a.$eval(j),
+n=c,q=new eb,x,z,u,w,r,v;if(B(h))r=h||[];else{r=[];for(u in h)h.hasOwnProperty(u)&&u.charAt(0)!="$"&&r.push(u);r.sort()}x=r.length;e=0;for(f=r.length;e<f;e++){u=h===r?e:r[e];w=h[u];if(v=m.shift(w)){z=v.scope;q.push(w,v);if(e!==v.index)v.index=e,n.after(v.element);n=v.element}else z=a.$new();z[i]=w;k&&(z[k]=u);z.$index=e;z.$first=e===0;z.$last=e===x-1;z.$middle=!(z.$first||z.$last);v||d(z,function(a){n.after(a);v={scope:z,element:n=a,index:e};q.push(w,v)})}for(u in m)if(m.hasOwnProperty(u))for(r=m[u];r.length;)w=
+r.pop(),w.element.remove(),w.scope.$destroy();m=q})}}}),Kd=Q(function(a,c,d){a.$watch(d.ngShow,function(a){c.css("display",Va(a)?"":"none")})}),Ld=Q(function(a,c,d){a.$watch(d.ngHide,function(a){c.css("display",Va(a)?"none":"")})}),Md=Q(function(a,c,d){a.$watch(d.ngStyle,function(a,d){d&&a!==d&&n(d,function(a,d){c.css(d,"")});a&&c.css(a)},!0)}),Nd=I({restrict:"EA",require:"ngSwitch",controller:["$scope",function(){this.cases={}}],link:function(a,c,d,e){var g,h,f;a.$watch(d.ngSwitch||d.on,function(j){h&&
+(f.$destroy(),h.remove(),h=f=null);if(g=e.cases["!"+j]||e.cases["?"])a.$eval(d.change),f=a.$new(),g(f,function(a){h=a;c.append(a)})})}}),Od=Q({transclude:"element",priority:500,require:"^ngSwitch",compile:function(a,c,d){return function(a,g,h,f){f.cases["!"+c.ngSwitchWhen]=d}}}),Pd=Q({transclude:"element",priority:500,require:"^ngSwitch",compile:function(a,c,d){return function(a,c,h,f){f.cases["?"]=d}}}),Qd=Q({controller:["$transclude","$element",function(a,c){a(function(a){c.append(a)})}]}),Rd=["$http",
+"$templateCache","$route","$anchorScroll","$compile","$controller",function(a,c,d,e,g,h){return{restrict:"ECA",terminal:!0,link:function(a,c,i){function k(){var i=d.current&&d.current.locals,k=i&&i.$template;if(k){c.html(k);m&&(m.$destroy(),m=null);var k=g(c.contents()),n=d.current;m=n.scope=a.$new();if(n.controller)i.$scope=m,i=h(n.controller,i),c.children().data("$ngControllerController",i);k(m);m.$emit("$viewContentLoaded");m.$eval(l);e()}else c.html(""),m&&(m.$destroy(),m=null)}var m,l=i.onload||
+"";a.$on("$routeChangeSuccess",k);k()}}}],Sd=["$templateCache",function(a){return{restrict:"E",terminal:!0,compile:function(c,d){d.type=="text/ng-template"&&a.put(d.id,c[0].text)}}}],Td=I({terminal:!0}),Ud=["$compile","$parse",function(a,c){var d=/^\s*(.*?)(?:\s+as\s+(.*?))?(?:\s+group\s+by\s+(.*))?\s+for\s+(?:([\$\w][\$\w\d]*)|(?:\(\s*([\$\w][\$\w\d]*)\s*,\s*([\$\w][\$\w\d]*)\s*\)))\s+in\s+(.*)$/,e={$setViewValue:C};return{restrict:"E",require:["select","?ngModel"],controller:["$element","$scope",
+"$attrs",function(a,c,d){var j=this,i={},k=e,m;j.databound=d.ngModel;j.init=function(a,c,d){k=a;m=d};j.addOption=function(c){i[c]=!0;k.$viewValue==c&&(a.val(c),m.parent()&&m.remove())};j.removeOption=function(a){this.hasOption(a)&&(delete i[a],k.$viewValue==a&&this.renderUnknownOption(a))};j.renderUnknownOption=function(c){c="? "+fa(c)+" ?";m.val(c);a.prepend(m);a.val(c);m.prop("selected",!0)};j.hasOption=function(a){return i.hasOwnProperty(a)};c.$on("$destroy",function(){j.renderUnknownOption=C})}],
+link:function(e,h,f,j){function i(a,c,d,e){d.$render=function(){var a=d.$viewValue;e.hasOption(a)?(y.parent()&&y.remove(),c.val(a),a===""&&v.prop("selected",!0)):w(a)&&v?c.val(""):e.renderUnknownOption(a)};c.bind("change",function(){a.$apply(function(){y.parent()&&y.remove();d.$setViewValue(c.val())})})}function k(a,c,d){var e;d.$render=function(){var a=new Ga(d.$viewValue);n(c.find("option"),function(c){c.selected=x(a.get(c.value))})};a.$watch(function(){ga(e,d.$viewValue)||(e=U(d.$viewValue),d.$render())});
+c.bind("change",function(){a.$apply(function(){var a=[];n(c.find("option"),function(c){c.selected&&a.push(c.value)});d.$setViewValue(a)})})}function m(e,f,g){function h(){var a={"":[]},c=[""],d,i,p,u,v;p=g.$modelValue;u=t(e)||[];var w=l?mb(u):u,x,y,A;y={};v=!1;var B,E;if(o)v=new Ga(p);else if(p===null||s)a[""].push({selected:p===null,id:"",label:""}),v=!0;for(A=0;x=w.length,A<x;A++){y[k]=u[l?y[l]=w[A]:A];d=m(e,y)||"";if(!(i=a[d]))i=a[d]=[],c.push(d);o?d=v.remove(n(e,y))!=q:(d=p===n(e,y),v=v||d);B=
+j(e,y);B=B===q?"":B;i.push({id:l?w[A]:A,label:B,selected:d})}!o&&!v&&a[""].unshift({id:"?",label:"",selected:!0});y=0;for(w=c.length;y<w;y++){d=c[y];i=a[d];if(r.length<=y)p={element:z.clone().attr("label",d),label:i.label},u=[p],r.push(u),f.append(p.element);else if(u=r[y],p=u[0],p.label!=d)p.element.attr("label",p.label=d);B=null;A=0;for(x=i.length;A<x;A++)if(d=i[A],v=u[A+1]){B=v.element;if(v.label!==d.label)B.text(v.label=d.label);if(v.id!==d.id)B.val(v.id=d.id);if(v.element.selected!==d.selected)B.prop("selected",
+v.selected=d.selected)}else d.id===""&&s?E=s:(E=C.clone()).val(d.id).attr("selected",d.selected).text(d.label),u.push({element:E,label:d.label,id:d.id,selected:d.selected}),B?B.after(E):p.element.append(E),B=E;for(A++;u.length>A;)u.pop().element.remove()}for(;r.length>y;)r.pop()[0].element.remove()}var i;if(!(i=p.match(d)))throw Error("Expected ngOptions in form of '_select_ (as _label_)? for (_key_,)?_value_ in _collection_' but got '"+p+"'.");var j=c(i[2]||i[1]),k=i[4]||i[6],l=i[5],m=c(i[3]||""),
+n=c(i[2]?i[1]:k),t=c(i[7]),r=[[{element:f,label:""}]];s&&(a(s)(e),s.removeClass("ng-scope"),s.remove());f.html("");f.bind("change",function(){e.$apply(function(){var a,c=t(e)||[],d={},h,i,j,m,p,s;if(o){i=[];m=0;for(s=r.length;m<s;m++){a=r[m];j=1;for(p=a.length;j<p;j++)if((h=a[j].element)[0].selected)h=h.val(),l&&(d[l]=h),d[k]=c[h],i.push(n(e,d))}}else h=f.val(),h=="?"?i=q:h==""?i=null:(d[k]=c[h],l&&(d[l]=h),i=n(e,d));g.$setViewValue(i)})});g.$render=h;e.$watch(h)}if(j[1]){for(var l=j[0],t=j[1],o=
+f.multiple,p=f.ngOptions,s=!1,v,C=u(Y.createElement("option")),z=u(Y.createElement("optgroup")),y=C.clone(),j=0,A=h.children(),r=A.length;j<r;j++)if(A[j].value==""){v=s=A.eq(j);break}l.init(t,s,y);if(o&&(f.required||f.ngRequired)){var B=function(a){t.$setValidity("required",!f.required||a&&a.length);return a};t.$parsers.push(B);t.$formatters.unshift(B);f.$observe("required",function(){B(t.$viewValue)})}p?m(e,h,t):o?k(e,h,t):i(e,h,t,l)}}}}],Vd=["$interpolate",function(a){var c={addOption:C,removeOption:C};
+return{restrict:"E",priority:100,compile:function(d,e){if(w(e.value)){var g=a(d.text(),!0);g||e.$set("value",d.text())}return function(a,d,e){var i=d.parent(),k=i.data("$selectController")||i.parent().data("$selectController");k&&k.databound?d.prop("selected",!1):k=c;g?a.$watch(g,function(a,c){e.$set("value",a);a!==c&&k.removeOption(c);k.addOption(a)}):k.addOption(e.value);d.bind("$destroy",function(){k.removeOption(e.value)})}}}}],Wd=I({restrict:"E",terminal:!0});(ca=X.jQuery)?(u=ca,v(ca.fn,{scope:va.scope,
+controller:va.controller,injector:va.injector,inheritedData:va.inheritedData}),ab("remove",!0),ab("empty"),ab("html")):u=L;Zb.element=u;(function(a){v(a,{bootstrap:qb,copy:U,extend:v,equals:ga,element:u,forEach:n,injector:rb,noop:C,bind:Ua,toJson:da,fromJson:ob,identity:na,isUndefined:w,isDefined:x,isString:A,isFunction:H,isObject:M,isNumber:Ra,isElement:gc,isArray:B,version:id,isDate:oa,lowercase:y,uppercase:ma,callbacks:{counter:0}});ta=lc(X);try{ta("ngLocale")}catch(c){ta("ngLocale",[]).provider("$locale",
+Zc)}ta("ng",["ngLocale"],["$provide",function(a){a.provider("$compile",Cb).directive({a:jd,input:cc,textarea:cc,form:kd,script:Sd,select:Ud,style:Wd,option:Vd,ngBind:vd,ngBindHtmlUnsafe:xd,ngBindTemplate:wd,ngClass:yd,ngClassEven:Ad,ngClassOdd:zd,ngCsp:Dd,ngCloak:Bd,ngController:Cd,ngForm:ld,ngHide:Ld,ngInclude:Fd,ngInit:Gd,ngNonBindable:Hd,ngPluralize:Id,ngRepeat:Jd,ngShow:Kd,ngSubmit:Ed,ngStyle:Md,ngSwitch:Nd,ngSwitchWhen:Od,ngSwitchDefault:Pd,ngOptions:Td,ngView:Rd,ngTransclude:Qd,ngModel:qd,ngList:sd,
+ngChange:rd,required:dc,ngRequired:dc,ngValue:ud}).directive(lb).directive(ec);a.provider({$anchorScroll:uc,$browser:wc,$cacheFactory:xc,$controller:Bc,$document:Cc,$exceptionHandler:Dc,$filter:Qb,$interpolate:Ec,$http:Vc,$httpBackend:Wc,$location:Ic,$log:Jc,$parse:Nc,$route:Qc,$routeParams:Rc,$rootScope:Sc,$q:Oc,$sniffer:Tc,$templateCache:yc,$timeout:$c,$window:Uc})}])})(Zb);u(Y).ready(function(){jc(Y,qb)})})(window,document);angular.element(document).find("head").append('<style type="text/css">@charset "UTF-8";[ng\\:cloak],[ng-cloak],[data-ng-cloak],[x-ng-cloak],.ng-cloak,.x-ng-cloak{display:none;}ng\\:form{display:block;}</style>');

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/app/lib/angular/.svn/text-base/version.txt.svn-base
----------------------------------------------------------------------
diff --git a/src/main/ui/app/lib/angular/.svn/text-base/version.txt.svn-base b/src/main/ui/app/lib/angular/.svn/text-base/version.txt.svn-base
new file mode 100755
index 0000000..90a27f9
--- /dev/null
+++ b/src/main/ui/app/lib/angular/.svn/text-base/version.txt.svn-base
@@ -0,0 +1 @@
+1.0.5

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/app/lib/angular/angular-cookies.js
----------------------------------------------------------------------
diff --git a/src/main/ui/app/lib/angular/angular-cookies.js b/src/main/ui/app/lib/angular/angular-cookies.js
new file mode 100755
index 0000000..fbf0acb
--- /dev/null
+++ b/src/main/ui/app/lib/angular/angular-cookies.js
@@ -0,0 +1,183 @@
+/**
+ * @license AngularJS v1.0.5
+ * (c) 2010-2012 Google, Inc. http://angularjs.org
+ * License: MIT
+ */
+(function(window, angular, undefined) {
+'use strict';
+
+/**
+ * @ngdoc overview
+ * @name ngCookies
+ */
+
+
+angular.module('ngCookies', ['ng']).
+  /**
+   * @ngdoc object
+   * @name ngCookies.$cookies
+   * @requires $browser
+   *
+   * @description
+   * Provides read/write access to browser's cookies.
+   *
+   * Only a simple Object is exposed and by adding or removing properties to/from
+   * this object, new cookies are created/deleted at the end of current $eval.
+   *
+   * @example
+   <doc:example>
+     <doc:source>
+       <script>
+         function ExampleController($cookies) {
+           // Retrieving a cookie
+           var favoriteCookie = $cookies.myFavorite;
+           // Setting a cookie
+           $cookies.myFavorite = 'oatmeal';
+         }
+       </script>
+     </doc:source>
+   </doc:example>
+   */
+   factory('$cookies', ['$rootScope', '$browser', function ($rootScope, $browser) {
+      var cookies = {},
+          lastCookies = {},
+          lastBrowserCookies,
+          runEval = false,
+          copy = angular.copy,
+          isUndefined = angular.isUndefined;
+
+      //creates a poller fn that copies all cookies from the $browser to service & inits the service
+      $browser.addPollFn(function() {
+        var currentCookies = $browser.cookies();
+        if (lastBrowserCookies != currentCookies) { //relies on browser.cookies() impl
+          lastBrowserCookies = currentCookies;
+          copy(currentCookies, lastCookies);
+          copy(currentCookies, cookies);
+          if (runEval) $rootScope.$apply();
+        }
+      })();
+
+      runEval = true;
+
+      //at the end of each eval, push cookies
+      //TODO: this should happen before the "delayed" watches fire, because if some cookies are not
+      //      strings or browser refuses to store some cookies, we update the model in the push fn.
+      $rootScope.$watch(push);
+
+      return cookies;
+
+
+      /**
+       * Pushes all the cookies from the service to the browser and verifies if all cookies were stored.
+       */
+      function push() {
+        var name,
+            value,
+            browserCookies,
+            updated;
+
+        //delete any cookies deleted in $cookies
+        for (name in lastCookies) {
+          if (isUndefined(cookies[name])) {
+            $browser.cookies(name, undefined);
+          }
+        }
+
+        //update all cookies updated in $cookies
+        for(name in cookies) {
+          value = cookies[name];
+          if (!angular.isString(value)) {
+            if (angular.isDefined(lastCookies[name])) {
+              cookies[name] = lastCookies[name];
+            } else {
+              delete cookies[name];
+            }
+          } else if (value !== lastCookies[name]) {
+            $browser.cookies(name, value);
+            updated = true;
+          }
+        }
+
+        //verify what was actually stored
+        if (updated){
+          updated = false;
+          browserCookies = $browser.cookies();
+
+          for (name in cookies) {
+            if (cookies[name] !== browserCookies[name]) {
+              //delete or reset all cookies that the browser dropped from $cookies
+              if (isUndefined(browserCookies[name])) {
+                delete cookies[name];
+              } else {
+                cookies[name] = browserCookies[name];
+              }
+              updated = true;
+            }
+          }
+        }
+      }
+    }]).
+
+
+  /**
+   * @ngdoc object
+   * @name ngCookies.$cookieStore
+   * @requires $cookies
+   *
+   * @description
+   * Provides a key-value (string-object) storage, that is backed by session cookies.
+   * Objects put or retrieved from this storage are automatically serialized or
+   * deserialized by angular's toJson/fromJson.
+   * @example
+   */
+   factory('$cookieStore', ['$cookies', function($cookies) {
+
+      return {
+        /**
+         * @ngdoc method
+         * @name ngCookies.$cookieStore#get
+         * @methodOf ngCookies.$cookieStore
+         *
+         * @description
+         * Returns the value of given cookie key
+         *
+         * @param {string} key Id to use for lookup.
+         * @returns {Object} Deserialized cookie value.
+         */
+        get: function(key) {
+          return angular.fromJson($cookies[key]);
+        },
+
+        /**
+         * @ngdoc method
+         * @name ngCookies.$cookieStore#put
+         * @methodOf ngCookies.$cookieStore
+         *
+         * @description
+         * Sets a value for given cookie key
+         *
+         * @param {string} key Id for the `value`.
+         * @param {Object} value Value to be stored.
+         */
+        put: function(key, value) {
+          $cookies[key] = angular.toJson(value);
+        },
+
+        /**
+         * @ngdoc method
+         * @name ngCookies.$cookieStore#remove
+         * @methodOf ngCookies.$cookieStore
+         *
+         * @description
+         * Remove given cookie
+         *
+         * @param {string} key Id of the key-value pair to delete.
+         */
+        remove: function(key) {
+          delete $cookies[key];
+        }
+      };
+
+    }]);
+
+})(window, window.angular);

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/app/lib/angular/angular-cookies.min.js
----------------------------------------------------------------------
diff --git a/src/main/ui/app/lib/angular/angular-cookies.min.js b/src/main/ui/app/lib/angular/angular-cookies.min.js
new file mode 100755
index 0000000..bd82c75
--- /dev/null
+++ b/src/main/ui/app/lib/angular/angular-cookies.min.js
@@ -0,0 +1,7 @@
+/*
+ AngularJS v1.0.5
+ (c) 2010-2012 Google, Inc. http://angularjs.org
+ License: MIT
+*/
+(function(m,f,l){'use strict';f.module("ngCookies",["ng"]).factory("$cookies",["$rootScope","$browser",function(d,c){var b={},g={},h,i=!1,j=f.copy,k=f.isUndefined;c.addPollFn(function(){var a=c.cookies();h!=a&&(h=a,j(a,g),j(a,b),i&&d.$apply())})();i=!0;d.$watch(function(){var a,e,d;for(a in g)k(b[a])&&c.cookies(a,l);for(a in b)e=b[a],f.isString(e)?e!==g[a]&&(c.cookies(a,e),d=!0):f.isDefined(g[a])?b[a]=g[a]:delete b[a];if(d)for(a in e=c.cookies(),b)b[a]!==e[a]&&(k(e[a])?delete b[a]:b[a]=e[a])});return b}]).factory("$cookieStore",
+["$cookies",function(d){return{get:function(c){return f.fromJson(d[c])},put:function(c,b){d[c]=f.toJson(b)},remove:function(c){delete d[c]}}}])})(window,window.angular);


[12/51] [abbrv] [partial] Adding Jinwon's custom RCMET

Posted by jo...@apache.org.
http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/test/lib/angular/.svn/text-base/angular-scenario.js.svn-base
----------------------------------------------------------------------
diff --git a/src/main/ui/test/lib/angular/.svn/text-base/angular-scenario.js.svn-base b/src/main/ui/test/lib/angular/.svn/text-base/angular-scenario.js.svn-base
new file mode 100755
index 0000000..538a799
--- /dev/null
+++ b/src/main/ui/test/lib/angular/.svn/text-base/angular-scenario.js.svn-base
@@ -0,0 +1,26195 @@
+/*!
+ * jQuery JavaScript Library v1.7.2
+ * http://jquery.com/
+ *
+ * Copyright 2011, John Resig
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * Includes Sizzle.js
+ * http://sizzlejs.com/
+ * Copyright 2011, The Dojo Foundation
+ * Released under the MIT, BSD, and GPL Licenses.
+ *
+ * Date: Wed Mar 21 12:46:34 2012 -0700
+ */
+(function( window, undefined ) {
+'use strict';
+
+// Use the correct document accordingly with window argument (sandbox)
+var document = window.document,
+	navigator = window.navigator,
+	location = window.location;
+var jQuery = (function() {
+
+// Define a local copy of jQuery
+var jQuery = function( selector, context ) {
+		// The jQuery object is actually just the init constructor 'enhanced'
+		return new jQuery.fn.init( selector, context, rootjQuery );
+	},
+
+	// Map over jQuery in case of overwrite
+	_jQuery = window.jQuery,
+
+	// Map over the $ in case of overwrite
+	_$ = window.$,
+
+	// A central reference to the root jQuery(document)
+	rootjQuery,
+
+	// A simple way to check for HTML strings or ID strings
+	// Prioritize #id over <tag> to avoid XSS via location.hash (#9521)
+	quickExpr = /^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,
+
+	// Check if a string has a non-whitespace character in it
+	rnotwhite = /\S/,
+
+	// Used for trimming whitespace
+	trimLeft = /^\s+/,
+	trimRight = /\s+$/,
+
+	// Match a standalone tag
+	rsingleTag = /^<(\w+)\s*\/?>(?:<\/\1>)?$/,
+
+	// JSON RegExp
+	rvalidchars = /^[\],:{}\s]*$/,
+	rvalidescape = /\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,
+	rvalidtokens = /"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,
+	rvalidbraces = /(?:^|:|,)(?:\s*\[)+/g,
+
+	// Useragent RegExp
+	rwebkit = /(webkit)[ \/]([\w.]+)/,
+	ropera = /(opera)(?:.*version)?[ \/]([\w.]+)/,
+	rmsie = /(msie) ([\w.]+)/,
+	rmozilla = /(mozilla)(?:.*? rv:([\w.]+))?/,
+
+	// Matches dashed string for camelizing
+	rdashAlpha = /-([a-z]|[0-9])/ig,
+	rmsPrefix = /^-ms-/,
+
+	// Used by jQuery.camelCase as callback to replace()
+	fcamelCase = function( all, letter ) {
+		return ( letter + "" ).toUpperCase();
+	},
+
+	// Keep a UserAgent string for use with jQuery.browser
+	userAgent = navigator.userAgent,
+
+	// For matching the engine and version of the browser
+	browserMatch,
+
+	// The deferred used on DOM ready
+	readyList,
+
+	// The ready event handler
+	DOMContentLoaded,
+
+	// Save a reference to some core methods
+	toString = Object.prototype.toString,
+	hasOwn = Object.prototype.hasOwnProperty,
+	push = Array.prototype.push,
+	slice = Array.prototype.slice,
+	trim = String.prototype.trim,
+	indexOf = Array.prototype.indexOf,
+
+	// [[Class]] -> type pairs
+	class2type = {};
+
+jQuery.fn = jQuery.prototype = {
+	constructor: jQuery,
+	init: function( selector, context, rootjQuery ) {
+		var match, elem, ret, doc;
+
+		// Handle $(""), $(null), or $(undefined)
+		if ( !selector ) {
+			return this;
+		}
+
+		// Handle $(DOMElement)
+		if ( selector.nodeType ) {
+			this.context = this[0] = selector;
+			this.length = 1;
+			return this;
+		}
+
+		// The body element only exists once, optimize finding it
+		if ( selector === "body" && !context && document.body ) {
+			this.context = document;
+			this[0] = document.body;
+			this.selector = selector;
+			this.length = 1;
+			return this;
+		}
+
+		// Handle HTML strings
+		if ( typeof selector === "string" ) {
+			// Are we dealing with HTML string or an ID?
+			if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) {
+				// Assume that strings that start and end with <> are HTML and skip the regex check
+				match = [ null, selector, null ];
+
+			} else {
+				match = quickExpr.exec( selector );
+			}
+
+			// Verify a match, and that no context was specified for #id
+			if ( match && (match[1] || !context) ) {
+
+				// HANDLE: $(html) -> $(array)
+				if ( match[1] ) {
+					context = context instanceof jQuery ? context[0] : context;
+					doc = ( context ? context.ownerDocument || context : document );
+
+					// If a single string is passed in and it's a single tag
+					// just do a createElement and skip the rest
+					ret = rsingleTag.exec( selector );
+
+					if ( ret ) {
+						if ( jQuery.isPlainObject( context ) ) {
+							selector = [ document.createElement( ret[1] ) ];
+							jQuery.fn.attr.call( selector, context, true );
+
+						} else {
+							selector = [ doc.createElement( ret[1] ) ];
+						}
+
+					} else {
+						ret = jQuery.buildFragment( [ match[1] ], [ doc ] );
+						selector = ( ret.cacheable ? jQuery.clone(ret.fragment) : ret.fragment ).childNodes;
+					}
+
+					return jQuery.merge( this, selector );
+
+				// HANDLE: $("#id")
+				} else {
+					elem = document.getElementById( match[2] );
+
+					// Check parentNode to catch when Blackberry 4.6 returns
+					// nodes that are no longer in the document #6963
+					if ( elem && elem.parentNode ) {
+						// Handle the case where IE and Opera return items
+						// by name instead of ID
+						if ( elem.id !== match[2] ) {
+							return rootjQuery.find( selector );
+						}
+
+						// Otherwise, we inject the element directly into the jQuery object
+						this.length = 1;
+						this[0] = elem;
+					}
+
+					this.context = document;
+					this.selector = selector;
+					return this;
+				}
+
+			// HANDLE: $(expr, $(...))
+			} else if ( !context || context.jquery ) {
+				return ( context || rootjQuery ).find( selector );
+
+			// HANDLE: $(expr, context)
+			// (which is just equivalent to: $(context).find(expr)
+			} else {
+				return this.constructor( context ).find( selector );
+			}
+
+		// HANDLE: $(function)
+		// Shortcut for document ready
+		} else if ( jQuery.isFunction( selector ) ) {
+			return rootjQuery.ready( selector );
+		}
+
+		if ( selector.selector !== undefined ) {
+			this.selector = selector.selector;
+			this.context = selector.context;
+		}
+
+		return jQuery.makeArray( selector, this );
+	},
+
+	// Start with an empty selector
+	selector: "",
+
+	// The current version of jQuery being used
+	jquery: "1.7.2",
+
+	// The default length of a jQuery object is 0
+	length: 0,
+
+	// The number of elements contained in the matched element set
+	size: function() {
+		return this.length;
+	},
+
+	toArray: function() {
+		return slice.call( this, 0 );
+	},
+
+	// Get the Nth element in the matched element set OR
+	// Get the whole matched element set as a clean array
+	get: function( num ) {
+		return num == null ?
+
+			// Return a 'clean' array
+			this.toArray() :
+
+			// Return just the object
+			( num < 0 ? this[ this.length + num ] : this[ num ] );
+	},
+
+	// Take an array of elements and push it onto the stack
+	// (returning the new matched element set)
+	pushStack: function( elems, name, selector ) {
+		// Build a new jQuery matched element set
+		var ret = this.constructor();
+
+		if ( jQuery.isArray( elems ) ) {
+			push.apply( ret, elems );
+
+		} else {
+			jQuery.merge( ret, elems );
+		}
+
+		// Add the old object onto the stack (as a reference)
+		ret.prevObject = this;
+
+		ret.context = this.context;
+
+		if ( name === "find" ) {
+			ret.selector = this.selector + ( this.selector ? " " : "" ) + selector;
+		} else if ( name ) {
+			ret.selector = this.selector + "." + name + "(" + selector + ")";
+		}
+
+		// Return the newly-formed element set
+		return ret;
+	},
+
+	// Execute a callback for every element in the matched set.
+	// (You can seed the arguments with an array of args, but this is
+	// only used internally.)
+	each: function( callback, args ) {
+		return jQuery.each( this, callback, args );
+	},
+
+	ready: function( fn ) {
+		// Attach the listeners
+		jQuery.bindReady();
+
+		// Add the callback
+		readyList.add( fn );
+
+		return this;
+	},
+
+	eq: function( i ) {
+		i = +i;
+		return i === -1 ?
+			this.slice( i ) :
+			this.slice( i, i + 1 );
+	},
+
+	first: function() {
+		return this.eq( 0 );
+	},
+
+	last: function() {
+		return this.eq( -1 );
+	},
+
+	slice: function() {
+		return this.pushStack( slice.apply( this, arguments ),
+			"slice", slice.call(arguments).join(",") );
+	},
+
+	map: function( callback ) {
+		return this.pushStack( jQuery.map(this, function( elem, i ) {
+			return callback.call( elem, i, elem );
+		}));
+	},
+
+	end: function() {
+		return this.prevObject || this.constructor(null);
+	},
+
+	// For internal use only.
+	// Behaves like an Array's method, not like a jQuery method.
+	push: push,
+	sort: [].sort,
+	splice: [].splice
+};
+
+// Give the init function the jQuery prototype for later instantiation
+jQuery.fn.init.prototype = jQuery.fn;
+
+jQuery.extend = jQuery.fn.extend = function() {
+	var options, name, src, copy, copyIsArray, clone,
+		target = arguments[0] || {},
+		i = 1,
+		length = arguments.length,
+		deep = false;
+
+	// Handle a deep copy situation
+	if ( typeof target === "boolean" ) {
+		deep = target;
+		target = arguments[1] || {};
+		// skip the boolean and the target
+		i = 2;
+	}
+
+	// Handle case when target is a string or something (possible in deep copy)
+	if ( typeof target !== "object" && !jQuery.isFunction(target) ) {
+		target = {};
+	}
+
+	// extend jQuery itself if only one argument is passed
+	if ( length === i ) {
+		target = this;
+		--i;
+	}
+
+	for ( ; i < length; i++ ) {
+		// Only deal with non-null/undefined values
+		if ( (options = arguments[ i ]) != null ) {
+			// Extend the base object
+			for ( name in options ) {
+				src = target[ name ];
+				copy = options[ name ];
+
+				// Prevent never-ending loop
+				if ( target === copy ) {
+					continue;
+				}
+
+				// Recurse if we're merging plain objects or arrays
+				if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) {
+					if ( copyIsArray ) {
+						copyIsArray = false;
+						clone = src && jQuery.isArray(src) ? src : [];
+
+					} else {
+						clone = src && jQuery.isPlainObject(src) ? src : {};
+					}
+
+					// Never move original objects, clone them
+					target[ name ] = jQuery.extend( deep, clone, copy );
+
+				// Don't bring in undefined values
+				} else if ( copy !== undefined ) {
+					target[ name ] = copy;
+				}
+			}
+		}
+	}
+
+	// Return the modified object
+	return target;
+};
+
+jQuery.extend({
+	noConflict: function( deep ) {
+		if ( window.$ === jQuery ) {
+			window.$ = _$;
+		}
+
+		if ( deep && window.jQuery === jQuery ) {
+			window.jQuery = _jQuery;
+		}
+
+		return jQuery;
+	},
+
+	// Is the DOM ready to be used? Set to true once it occurs.
+	isReady: false,
+
+	// A counter to track how many items to wait for before
+	// the ready event fires. See #6781
+	readyWait: 1,
+
+	// Hold (or release) the ready event
+	holdReady: function( hold ) {
+		if ( hold ) {
+			jQuery.readyWait++;
+		} else {
+			jQuery.ready( true );
+		}
+	},
+
+	// Handle when the DOM is ready
+	ready: function( wait ) {
+		// Either a released hold or an DOMready/load event and not yet ready
+		if ( (wait === true && !--jQuery.readyWait) || (wait !== true && !jQuery.isReady) ) {
+			// Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).
+			if ( !document.body ) {
+				return setTimeout( jQuery.ready, 1 );
+			}
+
+			// Remember that the DOM is ready
+			jQuery.isReady = true;
+
+			// If a normal DOM Ready event fired, decrement, and wait if need be
+			if ( wait !== true && --jQuery.readyWait > 0 ) {
+				return;
+			}
+
+			// If there are functions bound, to execute
+			readyList.fireWith( document, [ jQuery ] );
+
+			// Trigger any bound ready events
+			if ( jQuery.fn.trigger ) {
+				jQuery( document ).trigger( "ready" ).off( "ready" );
+			}
+		}
+	},
+
+	bindReady: function() {
+		if ( readyList ) {
+			return;
+		}
+
+		readyList = jQuery.Callbacks( "once memory" );
+
+		// Catch cases where $(document).ready() is called after the
+		// browser event has already occurred.
+		if ( document.readyState === "complete" ) {
+			// Handle it asynchronously to allow scripts the opportunity to delay ready
+			return setTimeout( jQuery.ready, 1 );
+		}
+
+		// Mozilla, Opera and webkit nightlies currently support this event
+		if ( document.addEventListener ) {
+			// Use the handy event callback
+			document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false );
+
+			// A fallback to window.onload, that will always work
+			window.addEventListener( "load", jQuery.ready, false );
+
+		// If IE event model is used
+		} else if ( document.attachEvent ) {
+			// ensure firing before onload,
+			// maybe late but safe also for iframes
+			document.attachEvent( "onreadystatechange", DOMContentLoaded );
+
+			// A fallback to window.onload, that will always work
+			window.attachEvent( "onload", jQuery.ready );
+
+			// If IE and not a frame
+			// continually check to see if the document is ready
+			var toplevel = false;
+
+			try {
+				toplevel = window.frameElement == null;
+			} catch(e) {}
+
+			if ( document.documentElement.doScroll && toplevel ) {
+				doScrollCheck();
+			}
+		}
+	},
+
+	// See test/unit/core.js for details concerning isFunction.
+	// Since version 1.3, DOM methods and functions like alert
+	// aren't supported. They return false on IE (#2968).
+	isFunction: function( obj ) {
+		return jQuery.type(obj) === "function";
+	},
+
+	isArray: Array.isArray || function( obj ) {
+		return jQuery.type(obj) === "array";
+	},
+
+	isWindow: function( obj ) {
+		return obj != null && obj == obj.window;
+	},
+
+	isNumeric: function( obj ) {
+		return !isNaN( parseFloat(obj) ) && isFinite( obj );
+	},
+
+	type: function( obj ) {
+		return obj == null ?
+			String( obj ) :
+			class2type[ toString.call(obj) ] || "object";
+	},
+
+	isPlainObject: function( obj ) {
+		// Must be an Object.
+		// Because of IE, we also have to check the presence of the constructor property.
+		// Make sure that DOM nodes and window objects don't pass through, as well
+		if ( !obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) {
+			return false;
+		}
+
+		try {
+			// Not own constructor property must be Object
+			if ( obj.constructor &&
+				!hasOwn.call(obj, "constructor") &&
+				!hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) {
+				return false;
+			}
+		} catch ( e ) {
+			// IE8,9 Will throw exceptions on certain host objects #9897
+			return false;
+		}
+
+		// Own properties are enumerated firstly, so to speed up,
+		// if last one is own, then all properties are own.
+
+		var key;
+		for ( key in obj ) {}
+
+		return key === undefined || hasOwn.call( obj, key );
+	},
+
+	isEmptyObject: function( obj ) {
+		for ( var name in obj ) {
+			return false;
+		}
+		return true;
+	},
+
+	error: function( msg ) {
+		throw new Error( msg );
+	},
+
+	parseJSON: function( data ) {
+		if ( typeof data !== "string" || !data ) {
+			return null;
+		}
+
+		// Make sure leading/trailing whitespace is removed (IE can't handle it)
+		data = jQuery.trim( data );
+
+		// Attempt to parse using the native JSON parser first
+		if ( window.JSON && window.JSON.parse ) {
+			return window.JSON.parse( data );
+		}
+
+		// Make sure the incoming data is actual JSON
+		// Logic borrowed from http://json.org/json2.js
+		if ( rvalidchars.test( data.replace( rvalidescape, "@" )
+			.replace( rvalidtokens, "]" )
+			.replace( rvalidbraces, "")) ) {
+
+			return ( new Function( "return " + data ) )();
+
+		}
+		jQuery.error( "Invalid JSON: " + data );
+	},
+
+	// Cross-browser xml parsing
+	parseXML: function( data ) {
+		if ( typeof data !== "string" || !data ) {
+			return null;
+		}
+		var xml, tmp;
+		try {
+			if ( window.DOMParser ) { // Standard
+				tmp = new DOMParser();
+				xml = tmp.parseFromString( data , "text/xml" );
+			} else { // IE
+				xml = new ActiveXObject( "Microsoft.XMLDOM" );
+				xml.async = "false";
+				xml.loadXML( data );
+			}
+		} catch( e ) {
+			xml = undefined;
+		}
+		if ( !xml || !xml.documentElement || xml.getElementsByTagName( "parsererror" ).length ) {
+			jQuery.error( "Invalid XML: " + data );
+		}
+		return xml;
+	},
+
+	noop: function() {},
+
+	// Evaluates a script in a global context
+	// Workarounds based on findings by Jim Driscoll
+	// http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context
+	globalEval: function( data ) {
+		if ( data && rnotwhite.test( data ) ) {
+			// We use execScript on Internet Explorer
+			// We use an anonymous function so that context is window
+			// rather than jQuery in Firefox
+			( window.execScript || function( data ) {
+				window[ "eval" ].call( window, data );
+			} )( data );
+		}
+	},
+
+	// Convert dashed to camelCase; used by the css and data modules
+	// Microsoft forgot to hump their vendor prefix (#9572)
+	camelCase: function( string ) {
+		return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase );
+	},
+
+	nodeName: function( elem, name ) {
+		return elem.nodeName && elem.nodeName.toUpperCase() === name.toUpperCase();
+	},
+
+	// args is for internal usage only
+	each: function( object, callback, args ) {
+		var name, i = 0,
+			length = object.length,
+			isObj = length === undefined || jQuery.isFunction( object );
+
+		if ( args ) {
+			if ( isObj ) {
+				for ( name in object ) {
+					if ( callback.apply( object[ name ], args ) === false ) {
+						break;
+					}
+				}
+			} else {
+				for ( ; i < length; ) {
+					if ( callback.apply( object[ i++ ], args ) === false ) {
+						break;
+					}
+				}
+			}
+
+		// A special, fast, case for the most common use of each
+		} else {
+			if ( isObj ) {
+				for ( name in object ) {
+					if ( callback.call( object[ name ], name, object[ name ] ) === false ) {
+						break;
+					}
+				}
+			} else {
+				for ( ; i < length; ) {
+					if ( callback.call( object[ i ], i, object[ i++ ] ) === false ) {
+						break;
+					}
+				}
+			}
+		}
+
+		return object;
+	},
+
+	// Use native String.trim function wherever possible
+	trim: trim ?
+		function( text ) {
+			return text == null ?
+				"" :
+				trim.call( text );
+		} :
+
+		// Otherwise use our own trimming functionality
+		function( text ) {
+			return text == null ?
+				"" :
+				text.toString().replace( trimLeft, "" ).replace( trimRight, "" );
+		},
+
+	// results is for internal usage only
+	makeArray: function( array, results ) {
+		var ret = results || [];
+
+		if ( array != null ) {
+			// The window, strings (and functions) also have 'length'
+			// Tweaked logic slightly to handle Blackberry 4.7 RegExp issues #6930
+			var type = jQuery.type( array );
+
+			if ( array.length == null || type === "string" || type === "function" || type === "regexp" || jQuery.isWindow( array ) ) {
+				push.call( ret, array );
+			} else {
+				jQuery.merge( ret, array );
+			}
+		}
+
+		return ret;
+	},
+
+	inArray: function( elem, array, i ) {
+		var len;
+
+		if ( array ) {
+			if ( indexOf ) {
+				return indexOf.call( array, elem, i );
+			}
+
+			len = array.length;
+			i = i ? i < 0 ? Math.max( 0, len + i ) : i : 0;
+
+			for ( ; i < len; i++ ) {
+				// Skip accessing in sparse arrays
+				if ( i in array && array[ i ] === elem ) {
+					return i;
+				}
+			}
+		}
+
+		return -1;
+	},
+
+	merge: function( first, second ) {
+		var i = first.length,
+			j = 0;
+
+		if ( typeof second.length === "number" ) {
+			for ( var l = second.length; j < l; j++ ) {
+				first[ i++ ] = second[ j ];
+			}
+
+		} else {
+			while ( second[j] !== undefined ) {
+				first[ i++ ] = second[ j++ ];
+			}
+		}
+
+		first.length = i;
+
+		return first;
+	},
+
+	grep: function( elems, callback, inv ) {
+		var ret = [], retVal;
+		inv = !!inv;
+
+		// Go through the array, only saving the items
+		// that pass the validator function
+		for ( var i = 0, length = elems.length; i < length; i++ ) {
+			retVal = !!callback( elems[ i ], i );
+			if ( inv !== retVal ) {
+				ret.push( elems[ i ] );
+			}
+		}
+
+		return ret;
+	},
+
+	// arg is for internal usage only
+	map: function( elems, callback, arg ) {
+		var value, key, ret = [],
+			i = 0,
+			length = elems.length,
+			// jquery objects are treated as arrays
+			isArray = elems instanceof jQuery || length !== undefined && typeof length === "number" && ( ( length > 0 && elems[ 0 ] && elems[ length -1 ] ) || length === 0 || jQuery.isArray( elems ) ) ;
+
+		// Go through the array, translating each of the items to their
+		if ( isArray ) {
+			for ( ; i < length; i++ ) {
+				value = callback( elems[ i ], i, arg );
+
+				if ( value != null ) {
+					ret[ ret.length ] = value;
+				}
+			}
+
+		// Go through every key on the object,
+		} else {
+			for ( key in elems ) {
+				value = callback( elems[ key ], key, arg );
+
+				if ( value != null ) {
+					ret[ ret.length ] = value;
+				}
+			}
+		}
+
+		// Flatten any nested arrays
+		return ret.concat.apply( [], ret );
+	},
+
+	// A global GUID counter for objects
+	guid: 1,
+
+	// Bind a function to a context, optionally partially applying any
+	// arguments.
+	proxy: function( fn, context ) {
+		if ( typeof context === "string" ) {
+			var tmp = fn[ context ];
+			context = fn;
+			fn = tmp;
+		}
+
+		// Quick check to determine if target is callable, in the spec
+		// this throws a TypeError, but we will just return undefined.
+		if ( !jQuery.isFunction( fn ) ) {
+			return undefined;
+		}
+
+		// Simulated bind
+		var args = slice.call( arguments, 2 ),
+			proxy = function() {
+				return fn.apply( context, args.concat( slice.call( arguments ) ) );
+			};
+
+		// Set the guid of unique handler to the same of original handler, so it can be removed
+		proxy.guid = fn.guid = fn.guid || proxy.guid || jQuery.guid++;
+
+		return proxy;
+	},
+
+	// Mutifunctional method to get and set values to a collection
+	// The value/s can optionally be executed if it's a function
+	access: function( elems, fn, key, value, chainable, emptyGet, pass ) {
+		var exec,
+			bulk = key == null,
+			i = 0,
+			length = elems.length;
+
+		// Sets many values
+		if ( key && typeof key === "object" ) {
+			for ( i in key ) {
+				jQuery.access( elems, fn, i, key[i], 1, emptyGet, value );
+			}
+			chainable = 1;
+
+		// Sets one value
+		} else if ( value !== undefined ) {
+			// Optionally, function values get executed if exec is true
+			exec = pass === undefined && jQuery.isFunction( value );
+
+			if ( bulk ) {
+				// Bulk operations only iterate when executing function values
+				if ( exec ) {
+					exec = fn;
+					fn = function( elem, key, value ) {
+						return exec.call( jQuery( elem ), value );
+					};
+
+				// Otherwise they run against the entire set
+				} else {
+					fn.call( elems, value );
+					fn = null;
+				}
+			}
+
+			if ( fn ) {
+				for (; i < length; i++ ) {
+					fn( elems[i], key, exec ? value.call( elems[i], i, fn( elems[i], key ) ) : value, pass );
+				}
+			}
+
+			chainable = 1;
+		}
+
+		return chainable ?
+			elems :
+
+			// Gets
+			bulk ?
+				fn.call( elems ) :
+				length ? fn( elems[0], key ) : emptyGet;
+	},
+
+	now: function() {
+		return ( new Date() ).getTime();
+	},
+
+	// Use of jQuery.browser is frowned upon.
+	// More details: http://docs.jquery.com/Utilities/jQuery.browser
+	uaMatch: function( ua ) {
+		ua = ua.toLowerCase();
+
+		var match = rwebkit.exec( ua ) ||
+			ropera.exec( ua ) ||
+			rmsie.exec( ua ) ||
+			ua.indexOf("compatible") < 0 && rmozilla.exec( ua ) ||
+			[];
+
+		return { browser: match[1] || "", version: match[2] || "0" };
+	},
+
+	sub: function() {
+		function jQuerySub( selector, context ) {
+			return new jQuerySub.fn.init( selector, context );
+		}
+		jQuery.extend( true, jQuerySub, this );
+		jQuerySub.superclass = this;
+		jQuerySub.fn = jQuerySub.prototype = this();
+		jQuerySub.fn.constructor = jQuerySub;
+		jQuerySub.sub = this.sub;
+		jQuerySub.fn.init = function init( selector, context ) {
+			if ( context && context instanceof jQuery && !(context instanceof jQuerySub) ) {
+				context = jQuerySub( context );
+			}
+
+			return jQuery.fn.init.call( this, selector, context, rootjQuerySub );
+		};
+		jQuerySub.fn.init.prototype = jQuerySub.fn;
+		var rootjQuerySub = jQuerySub(document);
+		return jQuerySub;
+	},
+
+	browser: {}
+});
+
+// Populate the class2type map
+jQuery.each("Boolean Number String Function Array Date RegExp Object".split(" "), function(i, name) {
+	class2type[ "[object " + name + "]" ] = name.toLowerCase();
+});
+
+browserMatch = jQuery.uaMatch( userAgent );
+if ( browserMatch.browser ) {
+	jQuery.browser[ browserMatch.browser ] = true;
+	jQuery.browser.version = browserMatch.version;
+}
+
+// Deprecated, use jQuery.browser.webkit instead
+if ( jQuery.browser.webkit ) {
+	jQuery.browser.safari = true;
+}
+
+// IE doesn't match non-breaking spaces with \s
+if ( rnotwhite.test( "\xA0" ) ) {
+	trimLeft = /^[\s\xA0]+/;
+	trimRight = /[\s\xA0]+$/;
+}
+
+// All jQuery objects should point back to these
+rootjQuery = jQuery(document);
+
+// Cleanup functions for the document ready method
+if ( document.addEventListener ) {
+	DOMContentLoaded = function() {
+		document.removeEventListener( "DOMContentLoaded", DOMContentLoaded, false );
+		jQuery.ready();
+	};
+
+} else if ( document.attachEvent ) {
+	DOMContentLoaded = function() {
+		// Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).
+		if ( document.readyState === "complete" ) {
+			document.detachEvent( "onreadystatechange", DOMContentLoaded );
+			jQuery.ready();
+		}
+	};
+}
+
+// The DOM ready check for Internet Explorer
+function doScrollCheck() {
+	if ( jQuery.isReady ) {
+		return;
+	}
+
+	try {
+		// If IE is used, use the trick by Diego Perini
+		// http://javascript.nwbox.com/IEContentLoaded/
+		document.documentElement.doScroll("left");
+	} catch(e) {
+		setTimeout( doScrollCheck, 1 );
+		return;
+	}
+
+	// and execute any waiting functions
+	jQuery.ready();
+}
+
+return jQuery;
+
+})();
+
+
+// String to Object flags format cache
+var flagsCache = {};
+
+// Convert String-formatted flags into Object-formatted ones and store in cache
+function createFlags( flags ) {
+	var object = flagsCache[ flags ] = {},
+		i, length;
+	flags = flags.split( /\s+/ );
+	for ( i = 0, length = flags.length; i < length; i++ ) {
+		object[ flags[i] ] = true;
+	}
+	return object;
+}
+
+/*
+ * Create a callback list using the following parameters:
+ *
+ *	flags:	an optional list of space-separated flags that will change how
+ *			the callback list behaves
+ *
+ * By default a callback list will act like an event callback list and can be
+ * "fired" multiple times.
+ *
+ * Possible flags:
+ *
+ *	once:			will ensure the callback list can only be fired once (like a Deferred)
+ *
+ *	memory:			will keep track of previous values and will call any callback added
+ *					after the list has been fired right away with the latest "memorized"
+ *					values (like a Deferred)
+ *
+ *	unique:			will ensure a callback can only be added once (no duplicate in the list)
+ *
+ *	stopOnFalse:	interrupt callings when a callback returns false
+ *
+ */
+jQuery.Callbacks = function( flags ) {
+
+	// Convert flags from String-formatted to Object-formatted
+	// (we check in cache first)
+	flags = flags ? ( flagsCache[ flags ] || createFlags( flags ) ) : {};
+
+	var // Actual callback list
+		list = [],
+		// Stack of fire calls for repeatable lists
+		stack = [],
+		// Last fire value (for non-forgettable lists)
+		memory,
+		// Flag to know if list was already fired
+		fired,
+		// Flag to know if list is currently firing
+		firing,
+		// First callback to fire (used internally by add and fireWith)
+		firingStart,
+		// End of the loop when firing
+		firingLength,
+		// Index of currently firing callback (modified by remove if needed)
+		firingIndex,
+		// Add one or several callbacks to the list
+		add = function( args ) {
+			var i,
+				length,
+				elem,
+				type,
+				actual;
+			for ( i = 0, length = args.length; i < length; i++ ) {
+				elem = args[ i ];
+				type = jQuery.type( elem );
+				if ( type === "array" ) {
+					// Inspect recursively
+					add( elem );
+				} else if ( type === "function" ) {
+					// Add if not in unique mode and callback is not in
+					if ( !flags.unique || !self.has( elem ) ) {
+						list.push( elem );
+					}
+				}
+			}
+		},
+		// Fire callbacks
+		fire = function( context, args ) {
+			args = args || [];
+			memory = !flags.memory || [ context, args ];
+			fired = true;
+			firing = true;
+			firingIndex = firingStart || 0;
+			firingStart = 0;
+			firingLength = list.length;
+			for ( ; list && firingIndex < firingLength; firingIndex++ ) {
+				if ( list[ firingIndex ].apply( context, args ) === false && flags.stopOnFalse ) {
+					memory = true; // Mark as halted
+					break;
+				}
+			}
+			firing = false;
+			if ( list ) {
+				if ( !flags.once ) {
+					if ( stack && stack.length ) {
+						memory = stack.shift();
+						self.fireWith( memory[ 0 ], memory[ 1 ] );
+					}
+				} else if ( memory === true ) {
+					self.disable();
+				} else {
+					list = [];
+				}
+			}
+		},
+		// Actual Callbacks object
+		self = {
+			// Add a callback or a collection of callbacks to the list
+			add: function() {
+				if ( list ) {
+					var length = list.length;
+					add( arguments );
+					// Do we need to add the callbacks to the
+					// current firing batch?
+					if ( firing ) {
+						firingLength = list.length;
+					// With memory, if we're not firing then
+					// we should call right away, unless previous
+					// firing was halted (stopOnFalse)
+					} else if ( memory && memory !== true ) {
+						firingStart = length;
+						fire( memory[ 0 ], memory[ 1 ] );
+					}
+				}
+				return this;
+			},
+			// Remove a callback from the list
+			remove: function() {
+				if ( list ) {
+					var args = arguments,
+						argIndex = 0,
+						argLength = args.length;
+					for ( ; argIndex < argLength ; argIndex++ ) {
+						for ( var i = 0; i < list.length; i++ ) {
+							if ( args[ argIndex ] === list[ i ] ) {
+								// Handle firingIndex and firingLength
+								if ( firing ) {
+									if ( i <= firingLength ) {
+										firingLength--;
+										if ( i <= firingIndex ) {
+											firingIndex--;
+										}
+									}
+								}
+								// Remove the element
+								list.splice( i--, 1 );
+								// If we have some unicity property then
+								// we only need to do this once
+								if ( flags.unique ) {
+									break;
+								}
+							}
+						}
+					}
+				}
+				return this;
+			},
+			// Control if a given callback is in the list
+			has: function( fn ) {
+				if ( list ) {
+					var i = 0,
+						length = list.length;
+					for ( ; i < length; i++ ) {
+						if ( fn === list[ i ] ) {
+							return true;
+						}
+					}
+				}
+				return false;
+			},
+			// Remove all callbacks from the list
+			empty: function() {
+				list = [];
+				return this;
+			},
+			// Have the list do nothing anymore
+			disable: function() {
+				list = stack = memory = undefined;
+				return this;
+			},
+			// Is it disabled?
+			disabled: function() {
+				return !list;
+			},
+			// Lock the list in its current state
+			lock: function() {
+				stack = undefined;
+				if ( !memory || memory === true ) {
+					self.disable();
+				}
+				return this;
+			},
+			// Is it locked?
+			locked: function() {
+				return !stack;
+			},
+			// Call all callbacks with the given context and arguments
+			fireWith: function( context, args ) {
+				if ( stack ) {
+					if ( firing ) {
+						if ( !flags.once ) {
+							stack.push( [ context, args ] );
+						}
+					} else if ( !( flags.once && memory ) ) {
+						fire( context, args );
+					}
+				}
+				return this;
+			},
+			// Call all the callbacks with the given arguments
+			fire: function() {
+				self.fireWith( this, arguments );
+				return this;
+			},
+			// To know if the callbacks have already been called at least once
+			fired: function() {
+				return !!fired;
+			}
+		};
+
+	return self;
+};
+
+
+
+
+var // Static reference to slice
+	sliceDeferred = [].slice;
+
+jQuery.extend({
+
+	Deferred: function( func ) {
+		var doneList = jQuery.Callbacks( "once memory" ),
+			failList = jQuery.Callbacks( "once memory" ),
+			progressList = jQuery.Callbacks( "memory" ),
+			state = "pending",
+			lists = {
+				resolve: doneList,
+				reject: failList,
+				notify: progressList
+			},
+			promise = {
+				done: doneList.add,
+				fail: failList.add,
+				progress: progressList.add,
+
+				state: function() {
+					return state;
+				},
+
+				// Deprecated
+				isResolved: doneList.fired,
+				isRejected: failList.fired,
+
+				then: function( doneCallbacks, failCallbacks, progressCallbacks ) {
+					deferred.done( doneCallbacks ).fail( failCallbacks ).progress( progressCallbacks );
+					return this;
+				},
+				always: function() {
+					deferred.done.apply( deferred, arguments ).fail.apply( deferred, arguments );
+					return this;
+				},
+				pipe: function( fnDone, fnFail, fnProgress ) {
+					return jQuery.Deferred(function( newDefer ) {
+						jQuery.each( {
+							done: [ fnDone, "resolve" ],
+							fail: [ fnFail, "reject" ],
+							progress: [ fnProgress, "notify" ]
+						}, function( handler, data ) {
+							var fn = data[ 0 ],
+								action = data[ 1 ],
+								returned;
+							if ( jQuery.isFunction( fn ) ) {
+								deferred[ handler ](function() {
+									returned = fn.apply( this, arguments );
+									if ( returned && jQuery.isFunction( returned.promise ) ) {
+										returned.promise().then( newDefer.resolve, newDefer.reject, newDefer.notify );
+									} else {
+										newDefer[ action + "With" ]( this === deferred ? newDefer : this, [ returned ] );
+									}
+								});
+							} else {
+								deferred[ handler ]( newDefer[ action ] );
+							}
+						});
+					}).promise();
+				},
+				// Get a promise for this deferred
+				// If obj is provided, the promise aspect is added to the object
+				promise: function( obj ) {
+					if ( obj == null ) {
+						obj = promise;
+					} else {
+						for ( var key in promise ) {
+							obj[ key ] = promise[ key ];
+						}
+					}
+					return obj;
+				}
+			},
+			deferred = promise.promise({}),
+			key;
+
+		for ( key in lists ) {
+			deferred[ key ] = lists[ key ].fire;
+			deferred[ key + "With" ] = lists[ key ].fireWith;
+		}
+
+		// Handle state
+		deferred.done( function() {
+			state = "resolved";
+		}, failList.disable, progressList.lock ).fail( function() {
+			state = "rejected";
+		}, doneList.disable, progressList.lock );
+
+		// Call given func if any
+		if ( func ) {
+			func.call( deferred, deferred );
+		}
+
+		// All done!
+		return deferred;
+	},
+
+	// Deferred helper
+	when: function( firstParam ) {
+		var args = sliceDeferred.call( arguments, 0 ),
+			i = 0,
+			length = args.length,
+			pValues = new Array( length ),
+			count = length,
+			pCount = length,
+			deferred = length <= 1 && firstParam && jQuery.isFunction( firstParam.promise ) ?
+				firstParam :
+				jQuery.Deferred(),
+			promise = deferred.promise();
+		function resolveFunc( i ) {
+			return function( value ) {
+				args[ i ] = arguments.length > 1 ? sliceDeferred.call( arguments, 0 ) : value;
+				if ( !( --count ) ) {
+					deferred.resolveWith( deferred, args );
+				}
+			};
+		}
+		function progressFunc( i ) {
+			return function( value ) {
+				pValues[ i ] = arguments.length > 1 ? sliceDeferred.call( arguments, 0 ) : value;
+				deferred.notifyWith( promise, pValues );
+			};
+		}
+		if ( length > 1 ) {
+			for ( ; i < length; i++ ) {
+				if ( args[ i ] && args[ i ].promise && jQuery.isFunction( args[ i ].promise ) ) {
+					args[ i ].promise().then( resolveFunc(i), deferred.reject, progressFunc(i) );
+				} else {
+					--count;
+				}
+			}
+			if ( !count ) {
+				deferred.resolveWith( deferred, args );
+			}
+		} else if ( deferred !== firstParam ) {
+			deferred.resolveWith( deferred, length ? [ firstParam ] : [] );
+		}
+		return promise;
+	}
+});
+
+
+
+
+jQuery.support = (function() {
+
+	var support,
+		all,
+		a,
+		select,
+		opt,
+		input,
+		fragment,
+		tds,
+		events,
+		eventName,
+		i,
+		isSupported,
+		div = document.createElement( "div" ),
+		documentElement = document.documentElement;
+
+	// Preliminary tests
+	div.setAttribute("className", "t");
+	div.innerHTML = "   <link/><table></table><a href='/a' style='top:1px;float:left;opacity:.55;'>a</a><input type='checkbox'/>";
+
+	all = div.getElementsByTagName( "*" );
+	a = div.getElementsByTagName( "a" )[ 0 ];
+
+	// Can't get basic test support
+	if ( !all || !all.length || !a ) {
+		return {};
+	}
+
+	// First batch of supports tests
+	select = document.createElement( "select" );
+	opt = select.appendChild( document.createElement("option") );
+	input = div.getElementsByTagName( "input" )[ 0 ];
+
+	support = {
+		// IE strips leading whitespace when .innerHTML is used
+		leadingWhitespace: ( div.firstChild.nodeType === 3 ),
+
+		// Make sure that tbody elements aren't automatically inserted
+		// IE will insert them into empty tables
+		tbody: !div.getElementsByTagName("tbody").length,
+
+		// Make sure that link elements get serialized correctly by innerHTML
+		// This requires a wrapper element in IE
+		htmlSerialize: !!div.getElementsByTagName("link").length,
+
+		// Get the style information from getAttribute
+		// (IE uses .cssText instead)
+		style: /top/.test( a.getAttribute("style") ),
+
+		// Make sure that URLs aren't manipulated
+		// (IE normalizes it by default)
+		hrefNormalized: ( a.getAttribute("href") === "/a" ),
+
+		// Make sure that element opacity exists
+		// (IE uses filter instead)
+		// Use a regex to work around a WebKit issue. See #5145
+		opacity: /^0.55/.test( a.style.opacity ),
+
+		// Verify style float existence
+		// (IE uses styleFloat instead of cssFloat)
+		cssFloat: !!a.style.cssFloat,
+
+		// Make sure that if no value is specified for a checkbox
+		// that it defaults to "on".
+		// (WebKit defaults to "" instead)
+		checkOn: ( input.value === "on" ),
+
+		// Make sure that a selected-by-default option has a working selected property.
+		// (WebKit defaults to false instead of true, IE too, if it's in an optgroup)
+		optSelected: opt.selected,
+
+		// Test setAttribute on camelCase class. If it works, we need attrFixes when doing get/setAttribute (ie6/7)
+		getSetAttribute: div.className !== "t",
+
+		// Tests for enctype support on a form(#6743)
+		enctype: !!document.createElement("form").enctype,
+
+		// Makes sure cloning an html5 element does not cause problems
+		// Where outerHTML is undefined, this still works
+		html5Clone: document.createElement("nav").cloneNode( true ).outerHTML !== "<:nav></:nav>",
+
+		// Will be defined later
+		submitBubbles: true,
+		changeBubbles: true,
+		focusinBubbles: false,
+		deleteExpando: true,
+		noCloneEvent: true,
+		inlineBlockNeedsLayout: false,
+		shrinkWrapBlocks: false,
+		reliableMarginRight: true,
+		pixelMargin: true
+	};
+
+	// jQuery.boxModel DEPRECATED in 1.3, use jQuery.support.boxModel instead
+	jQuery.boxModel = support.boxModel = (document.compatMode === "CSS1Compat");
+
+	// Make sure checked status is properly cloned
+	input.checked = true;
+	support.noCloneChecked = input.cloneNode( true ).checked;
+
+	// Make sure that the options inside disabled selects aren't marked as disabled
+	// (WebKit marks them as disabled)
+	select.disabled = true;
+	support.optDisabled = !opt.disabled;
+
+	// Test to see if it's possible to delete an expando from an element
+	// Fails in Internet Explorer
+	try {
+		delete div.test;
+	} catch( e ) {
+		support.deleteExpando = false;
+	}
+
+	if ( !div.addEventListener && div.attachEvent && div.fireEvent ) {
+		div.attachEvent( "onclick", function() {
+			// Cloning a node shouldn't copy over any
+			// bound event handlers (IE does this)
+			support.noCloneEvent = false;
+		});
+		div.cloneNode( true ).fireEvent( "onclick" );
+	}
+
+	// Check if a radio maintains its value
+	// after being appended to the DOM
+	input = document.createElement("input");
+	input.value = "t";
+	input.setAttribute("type", "radio");
+	support.radioValue = input.value === "t";
+
+	input.setAttribute("checked", "checked");
+
+	// #11217 - WebKit loses check when the name is after the checked attribute
+	input.setAttribute( "name", "t" );
+
+	div.appendChild( input );
+	fragment = document.createDocumentFragment();
+	fragment.appendChild( div.lastChild );
+
+	// WebKit doesn't clone checked state correctly in fragments
+	support.checkClone = fragment.cloneNode( true ).cloneNode( true ).lastChild.checked;
+
+	// Check if a disconnected checkbox will retain its checked
+	// value of true after appended to the DOM (IE6/7)
+	support.appendChecked = input.checked;
+
+	fragment.removeChild( input );
+	fragment.appendChild( div );
+
+	// Technique from Juriy Zaytsev
+	// http://perfectionkills.com/detecting-event-support-without-browser-sniffing/
+	// We only care about the case where non-standard event systems
+	// are used, namely in IE. Short-circuiting here helps us to
+	// avoid an eval call (in setAttribute) which can cause CSP
+	// to go haywire. See: https://developer.mozilla.org/en/Security/CSP
+	if ( div.attachEvent ) {
+		for ( i in {
+			submit: 1,
+			change: 1,
+			focusin: 1
+		}) {
+			eventName = "on" + i;
+			isSupported = ( eventName in div );
+			if ( !isSupported ) {
+				div.setAttribute( eventName, "return;" );
+				isSupported = ( typeof div[ eventName ] === "function" );
+			}
+			support[ i + "Bubbles" ] = isSupported;
+		}
+	}
+
+	fragment.removeChild( div );
+
+	// Null elements to avoid leaks in IE
+	fragment = select = opt = div = input = null;
+
+	// Run tests that need a body at doc ready
+	jQuery(function() {
+		var container, outer, inner, table, td, offsetSupport,
+			marginDiv, conMarginTop, style, html, positionTopLeftWidthHeight,
+			paddingMarginBorderVisibility, paddingMarginBorder,
+			body = document.getElementsByTagName("body")[0];
+
+		if ( !body ) {
+			// Return for frameset docs that don't have a body
+			return;
+		}
+
+		conMarginTop = 1;
+		paddingMarginBorder = "padding:0;margin:0;border:";
+		positionTopLeftWidthHeight = "position:absolute;top:0;left:0;width:1px;height:1px;";
+		paddingMarginBorderVisibility = paddingMarginBorder + "0;visibility:hidden;";
+		style = "style='" + positionTopLeftWidthHeight + paddingMarginBorder + "5px solid #000;";
+		html = "<div " + style + "display:block;'><div style='" + paddingMarginBorder + "0;display:block;overflow:hidden;'></div></div>" +
+			"<table " + style + "' cellpadding='0' cellspacing='0'>" +
+			"<tr><td></td></tr></table>";
+
+		container = document.createElement("div");
+		container.style.cssText = paddingMarginBorderVisibility + "width:0;height:0;position:static;top:0;margin-top:" + conMarginTop + "px";
+		body.insertBefore( container, body.firstChild );
+
+		// Construct the test element
+		div = document.createElement("div");
+		container.appendChild( div );
+
+		// Check if table cells still have offsetWidth/Height when they are set
+		// to display:none and there are still other visible table cells in a
+		// table row; if so, offsetWidth/Height are not reliable for use when
+		// determining if an element has been hidden directly using
+		// display:none (it is still safe to use offsets if a parent element is
+		// hidden; don safety goggles and see bug #4512 for more information).
+		// (only IE 8 fails this test)
+		div.innerHTML = "<table><tr><td style='" + paddingMarginBorder + "0;display:none'></td><td>t</td></tr></table>";
+		tds = div.getElementsByTagName( "td" );
+		isSupported = ( tds[ 0 ].offsetHeight === 0 );
+
+		tds[ 0 ].style.display = "";
+		tds[ 1 ].style.display = "none";
+
+		// Check if empty table cells still have offsetWidth/Height
+		// (IE <= 8 fail this test)
+		support.reliableHiddenOffsets = isSupported && ( tds[ 0 ].offsetHeight === 0 );
+
+		// Check if div with explicit width and no margin-right incorrectly
+		// gets computed margin-right based on width of container. For more
+		// info see bug #3333
+		// Fails in WebKit before Feb 2011 nightlies
+		// WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right
+		if ( window.getComputedStyle ) {
+			div.innerHTML = "";
+			marginDiv = document.createElement( "div" );
+			marginDiv.style.width = "0";
+			marginDiv.style.marginRight = "0";
+			div.style.width = "2px";
+			div.appendChild( marginDiv );
+			support.reliableMarginRight =
+				( parseInt( ( window.getComputedStyle( marginDiv, null ) || { marginRight: 0 } ).marginRight, 10 ) || 0 ) === 0;
+		}
+
+		if ( typeof div.style.zoom !== "undefined" ) {
+			// Check if natively block-level elements act like inline-block
+			// elements when setting their display to 'inline' and giving
+			// them layout
+			// (IE < 8 does this)
+			div.innerHTML = "";
+			div.style.width = div.style.padding = "1px";
+			div.style.border = 0;
+			div.style.overflow = "hidden";
+			div.style.display = "inline";
+			div.style.zoom = 1;
+			support.inlineBlockNeedsLayout = ( div.offsetWidth === 3 );
+
+			// Check if elements with layout shrink-wrap their children
+			// (IE 6 does this)
+			div.style.display = "block";
+			div.style.overflow = "visible";
+			div.innerHTML = "<div style='width:5px;'></div>";
+			support.shrinkWrapBlocks = ( div.offsetWidth !== 3 );
+		}
+
+		div.style.cssText = positionTopLeftWidthHeight + paddingMarginBorderVisibility;
+		div.innerHTML = html;
+
+		outer = div.firstChild;
+		inner = outer.firstChild;
+		td = outer.nextSibling.firstChild.firstChild;
+
+		offsetSupport = {
+			doesNotAddBorder: ( inner.offsetTop !== 5 ),
+			doesAddBorderForTableAndCells: ( td.offsetTop === 5 )
+		};
+
+		inner.style.position = "fixed";
+		inner.style.top = "20px";
+
+		// safari subtracts parent border width here which is 5px
+		offsetSupport.fixedPosition = ( inner.offsetTop === 20 || inner.offsetTop === 15 );
+		inner.style.position = inner.style.top = "";
+
+		outer.style.overflow = "hidden";
+		outer.style.position = "relative";
+
+		offsetSupport.subtractsBorderForOverflowNotVisible = ( inner.offsetTop === -5 );
+		offsetSupport.doesNotIncludeMarginInBodyOffset = ( body.offsetTop !== conMarginTop );
+
+		if ( window.getComputedStyle ) {
+			div.style.marginTop = "1%";
+			support.pixelMargin = ( window.getComputedStyle( div, null ) || { marginTop: 0 } ).marginTop !== "1%";
+		}
+
+		if ( typeof container.style.zoom !== "undefined" ) {
+			container.style.zoom = 1;
+		}
+
+		body.removeChild( container );
+		marginDiv = div = container = null;
+
+		jQuery.extend( support, offsetSupport );
+	});
+
+	return support;
+})();
+
+
+
+
+var rbrace = /^(?:\{.*\}|\[.*\])$/,
+	rmultiDash = /([A-Z])/g;
+
+jQuery.extend({
+	cache: {},
+
+	// Please use with caution
+	uuid: 0,
+
+	// Unique for each copy of jQuery on the page
+	// Non-digits removed to match rinlinejQuery
+	expando: "jQuery" + ( jQuery.fn.jquery + Math.random() ).replace( /\D/g, "" ),
+
+	// The following elements throw uncatchable exceptions if you
+	// attempt to add expando properties to them.
+	noData: {
+		"embed": true,
+		// Ban all objects except for Flash (which handle expandos)
+		"object": "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",
+		"applet": true
+	},
+
+	hasData: function( elem ) {
+		elem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ];
+		return !!elem && !isEmptyDataObject( elem );
+	},
+
+	data: function( elem, name, data, pvt /* Internal Use Only */ ) {
+		if ( !jQuery.acceptData( elem ) ) {
+			return;
+		}
+
+		var privateCache, thisCache, ret,
+			internalKey = jQuery.expando,
+			getByName = typeof name === "string",
+
+			// We have to handle DOM nodes and JS objects differently because IE6-7
+			// can't GC object references properly across the DOM-JS boundary
+			isNode = elem.nodeType,
+
+			// Only DOM nodes need the global jQuery cache; JS object data is
+			// attached directly to the object so GC can occur automatically
+			cache = isNode ? jQuery.cache : elem,
+
+			// Only defining an ID for JS objects if its cache already exists allows
+			// the code to shortcut on the same path as a DOM node with no cache
+			id = isNode ? elem[ internalKey ] : elem[ internalKey ] && internalKey,
+			isEvents = name === "events";
+
+		// Avoid doing any more work than we need to when trying to get data on an
+		// object that has no data at all
+		if ( (!id || !cache[id] || (!isEvents && !pvt && !cache[id].data)) && getByName && data === undefined ) {
+			return;
+		}
+
+		if ( !id ) {
+			// Only DOM nodes need a new unique ID for each element since their data
+			// ends up in the global cache
+			if ( isNode ) {
+				elem[ internalKey ] = id = ++jQuery.uuid;
+			} else {
+				id = internalKey;
+			}
+		}
+
+		if ( !cache[ id ] ) {
+			cache[ id ] = {};
+
+			// Avoids exposing jQuery metadata on plain JS objects when the object
+			// is serialized using JSON.stringify
+			if ( !isNode ) {
+				cache[ id ].toJSON = jQuery.noop;
+			}
+		}
+
+		// An object can be passed to jQuery.data instead of a key/value pair; this gets
+		// shallow copied over onto the existing cache
+		if ( typeof name === "object" || typeof name === "function" ) {
+			if ( pvt ) {
+				cache[ id ] = jQuery.extend( cache[ id ], name );
+			} else {
+				cache[ id ].data = jQuery.extend( cache[ id ].data, name );
+			}
+		}
+
+		privateCache = thisCache = cache[ id ];
+
+		// jQuery data() is stored in a separate object inside the object's internal data
+		// cache in order to avoid key collisions between internal data and user-defined
+		// data.
+		if ( !pvt ) {
+			if ( !thisCache.data ) {
+				thisCache.data = {};
+			}
+
+			thisCache = thisCache.data;
+		}
+
+		if ( data !== undefined ) {
+			thisCache[ jQuery.camelCase( name ) ] = data;
+		}
+
+		// Users should not attempt to inspect the internal events object using jQuery.data,
+		// it is undocumented and subject to change. But does anyone listen? No.
+		if ( isEvents && !thisCache[ name ] ) {
+			return privateCache.events;
+		}
+
+		// Check for both converted-to-camel and non-converted data property names
+		// If a data property was specified
+		if ( getByName ) {
+
+			// First Try to find as-is property data
+			ret = thisCache[ name ];
+
+			// Test for null|undefined property data
+			if ( ret == null ) {
+
+				// Try to find the camelCased property
+				ret = thisCache[ jQuery.camelCase( name ) ];
+			}
+		} else {
+			ret = thisCache;
+		}
+
+		return ret;
+	},
+
+	removeData: function( elem, name, pvt /* Internal Use Only */ ) {
+		if ( !jQuery.acceptData( elem ) ) {
+			return;
+		}
+
+		var thisCache, i, l,
+
+			// Reference to internal data cache key
+			internalKey = jQuery.expando,
+
+			isNode = elem.nodeType,
+
+			// See jQuery.data for more information
+			cache = isNode ? jQuery.cache : elem,
+
+			// See jQuery.data for more information
+			id = isNode ? elem[ internalKey ] : internalKey;
+
+		// If there is already no cache entry for this object, there is no
+		// purpose in continuing
+		if ( !cache[ id ] ) {
+			return;
+		}
+
+		if ( name ) {
+
+			thisCache = pvt ? cache[ id ] : cache[ id ].data;
+
+			if ( thisCache ) {
+
+				// Support array or space separated string names for data keys
+				if ( !jQuery.isArray( name ) ) {
+
+					// try the string as a key before any manipulation
+					if ( name in thisCache ) {
+						name = [ name ];
+					} else {
+
+						// split the camel cased version by spaces unless a key with the spaces exists
+						name = jQuery.camelCase( name );
+						if ( name in thisCache ) {
+							name = [ name ];
+						} else {
+							name = name.split( " " );
+						}
+					}
+				}
+
+				for ( i = 0, l = name.length; i < l; i++ ) {
+					delete thisCache[ name[i] ];
+				}
+
+				// If there is no data left in the cache, we want to continue
+				// and let the cache object itself get destroyed
+				if ( !( pvt ? isEmptyDataObject : jQuery.isEmptyObject )( thisCache ) ) {
+					return;
+				}
+			}
+		}
+
+		// See jQuery.data for more information
+		if ( !pvt ) {
+			delete cache[ id ].data;
+
+			// Don't destroy the parent cache unless the internal data object
+			// had been the only thing left in it
+			if ( !isEmptyDataObject(cache[ id ]) ) {
+				return;
+			}
+		}
+
+		// Browsers that fail expando deletion also refuse to delete expandos on
+		// the window, but it will allow it on all other JS objects; other browsers
+		// don't care
+		// Ensure that `cache` is not a window object #10080
+		if ( jQuery.support.deleteExpando || !cache.setInterval ) {
+			delete cache[ id ];
+		} else {
+			cache[ id ] = null;
+		}
+
+		// We destroyed the cache and need to eliminate the expando on the node to avoid
+		// false lookups in the cache for entries that no longer exist
+		if ( isNode ) {
+			// IE does not allow us to delete expando properties from nodes,
+			// nor does it have a removeAttribute function on Document nodes;
+			// we must handle all of these cases
+			if ( jQuery.support.deleteExpando ) {
+				delete elem[ internalKey ];
+			} else if ( elem.removeAttribute ) {
+				elem.removeAttribute( internalKey );
+			} else {
+				elem[ internalKey ] = null;
+			}
+		}
+	},
+
+	// For internal use only.
+	_data: function( elem, name, data ) {
+		return jQuery.data( elem, name, data, true );
+	},
+
+	// A method for determining if a DOM node can handle the data expando
+	acceptData: function( elem ) {
+		if ( elem.nodeName ) {
+			var match = jQuery.noData[ elem.nodeName.toLowerCase() ];
+
+			if ( match ) {
+				return !(match === true || elem.getAttribute("classid") !== match);
+			}
+		}
+
+		return true;
+	}
+});
+
+jQuery.fn.extend({
+	data: function( key, value ) {
+		var parts, part, attr, name, l,
+			elem = this[0],
+			i = 0,
+			data = null;
+
+		// Gets all values
+		if ( key === undefined ) {
+			if ( this.length ) {
+				data = jQuery.data( elem );
+
+				if ( elem.nodeType === 1 && !jQuery._data( elem, "parsedAttrs" ) ) {
+					attr = elem.attributes;
+					for ( l = attr.length; i < l; i++ ) {
+						name = attr[i].name;
+
+						if ( name.indexOf( "data-" ) === 0 ) {
+							name = jQuery.camelCase( name.substring(5) );
+
+							dataAttr( elem, name, data[ name ] );
+						}
+					}
+					jQuery._data( elem, "parsedAttrs", true );
+				}
+			}
+
+			return data;
+		}
+
+		// Sets multiple values
+		if ( typeof key === "object" ) {
+			return this.each(function() {
+				jQuery.data( this, key );
+			});
+		}
+
+		parts = key.split( ".", 2 );
+		parts[1] = parts[1] ? "." + parts[1] : "";
+		part = parts[1] + "!";
+
+		return jQuery.access( this, function( value ) {
+
+			if ( value === undefined ) {
+				data = this.triggerHandler( "getData" + part, [ parts[0] ] );
+
+				// Try to fetch any internally stored data first
+				if ( data === undefined && elem ) {
+					data = jQuery.data( elem, key );
+					data = dataAttr( elem, key, data );
+				}
+
+				return data === undefined && parts[1] ?
+					this.data( parts[0] ) :
+					data;
+			}
+
+			parts[1] = value;
+			this.each(function() {
+				var self = jQuery( this );
+
+				self.triggerHandler( "setData" + part, parts );
+				jQuery.data( this, key, value );
+				self.triggerHandler( "changeData" + part, parts );
+			});
+		}, null, value, arguments.length > 1, null, false );
+	},
+
+	removeData: function( key ) {
+		return this.each(function() {
+			jQuery.removeData( this, key );
+		});
+	}
+});
+
+function dataAttr( elem, key, data ) {
+	// If nothing was found internally, try to fetch any
+	// data from the HTML5 data-* attribute
+	if ( data === undefined && elem.nodeType === 1 ) {
+
+		var name = "data-" + key.replace( rmultiDash, "-$1" ).toLowerCase();
+
+		data = elem.getAttribute( name );
+
+		if ( typeof data === "string" ) {
+			try {
+				data = data === "true" ? true :
+				data === "false" ? false :
+				data === "null" ? null :
+				jQuery.isNumeric( data ) ? +data :
+					rbrace.test( data ) ? jQuery.parseJSON( data ) :
+					data;
+			} catch( e ) {}
+
+			// Make sure we set the data so it isn't changed later
+			jQuery.data( elem, key, data );
+
+		} else {
+			data = undefined;
+		}
+	}
+
+	return data;
+}
+
+// checks a cache object for emptiness
+function isEmptyDataObject( obj ) {
+	for ( var name in obj ) {
+
+		// if the public data object is empty, the private is still empty
+		if ( name === "data" && jQuery.isEmptyObject( obj[name] ) ) {
+			continue;
+		}
+		if ( name !== "toJSON" ) {
+			return false;
+		}
+	}
+
+	return true;
+}
+
+
+
+
+function handleQueueMarkDefer( elem, type, src ) {
+	var deferDataKey = type + "defer",
+		queueDataKey = type + "queue",
+		markDataKey = type + "mark",
+		defer = jQuery._data( elem, deferDataKey );
+	if ( defer &&
+		( src === "queue" || !jQuery._data(elem, queueDataKey) ) &&
+		( src === "mark" || !jQuery._data(elem, markDataKey) ) ) {
+		// Give room for hard-coded callbacks to fire first
+		// and eventually mark/queue something else on the element
+		setTimeout( function() {
+			if ( !jQuery._data( elem, queueDataKey ) &&
+				!jQuery._data( elem, markDataKey ) ) {
+				jQuery.removeData( elem, deferDataKey, true );
+				defer.fire();
+			}
+		}, 0 );
+	}
+}
+
+jQuery.extend({
+
+	_mark: function( elem, type ) {
+		if ( elem ) {
+			type = ( type || "fx" ) + "mark";
+			jQuery._data( elem, type, (jQuery._data( elem, type ) || 0) + 1 );
+		}
+	},
+
+	_unmark: function( force, elem, type ) {
+		if ( force !== true ) {
+			type = elem;
+			elem = force;
+			force = false;
+		}
+		if ( elem ) {
+			type = type || "fx";
+			var key = type + "mark",
+				count = force ? 0 : ( (jQuery._data( elem, key ) || 1) - 1 );
+			if ( count ) {
+				jQuery._data( elem, key, count );
+			} else {
+				jQuery.removeData( elem, key, true );
+				handleQueueMarkDefer( elem, type, "mark" );
+			}
+		}
+	},
+
+	queue: function( elem, type, data ) {
+		var q;
+		if ( elem ) {
+			type = ( type || "fx" ) + "queue";
+			q = jQuery._data( elem, type );
+
+			// Speed up dequeue by getting out quickly if this is just a lookup
+			if ( data ) {
+				if ( !q || jQuery.isArray(data) ) {
+					q = jQuery._data( elem, type, jQuery.makeArray(data) );
+				} else {
+					q.push( data );
+				}
+			}
+			return q || [];
+		}
+	},
+
+	dequeue: function( elem, type ) {
+		type = type || "fx";
+
+		var queue = jQuery.queue( elem, type ),
+			fn = queue.shift(),
+			hooks = {};
+
+		// If the fx queue is dequeued, always remove the progress sentinel
+		if ( fn === "inprogress" ) {
+			fn = queue.shift();
+		}
+
+		if ( fn ) {
+			// Add a progress sentinel to prevent the fx queue from being
+			// automatically dequeued
+			if ( type === "fx" ) {
+				queue.unshift( "inprogress" );
+			}
+
+			jQuery._data( elem, type + ".run", hooks );
+			fn.call( elem, function() {
+				jQuery.dequeue( elem, type );
+			}, hooks );
+		}
+
+		if ( !queue.length ) {
+			jQuery.removeData( elem, type + "queue " + type + ".run", true );
+			handleQueueMarkDefer( elem, type, "queue" );
+		}
+	}
+});
+
+jQuery.fn.extend({
+	queue: function( type, data ) {
+		var setter = 2;
+
+		if ( typeof type !== "string" ) {
+			data = type;
+			type = "fx";
+			setter--;
+		}
+
+		if ( arguments.length < setter ) {
+			return jQuery.queue( this[0], type );
+		}
+
+		return data === undefined ?
+			this :
+			this.each(function() {
+				var queue = jQuery.queue( this, type, data );
+
+				if ( type === "fx" && queue[0] !== "inprogress" ) {
+					jQuery.dequeue( this, type );
+				}
+			});
+	},
+	dequeue: function( type ) {
+		return this.each(function() {
+			jQuery.dequeue( this, type );
+		});
+	},
+	// Based off of the plugin by Clint Helfers, with permission.
+	// http://blindsignals.com/index.php/2009/07/jquery-delay/
+	delay: function( time, type ) {
+		time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time;
+		type = type || "fx";
+
+		return this.queue( type, function( next, hooks ) {
+			var timeout = setTimeout( next, time );
+			hooks.stop = function() {
+				clearTimeout( timeout );
+			};
+		});
+	},
+	clearQueue: function( type ) {
+		return this.queue( type || "fx", [] );
+	},
+	// Get a promise resolved when queues of a certain type
+	// are emptied (fx is the type by default)
+	promise: function( type, object ) {
+		if ( typeof type !== "string" ) {
+			object = type;
+			type = undefined;
+		}
+		type = type || "fx";
+		var defer = jQuery.Deferred(),
+			elements = this,
+			i = elements.length,
+			count = 1,
+			deferDataKey = type + "defer",
+			queueDataKey = type + "queue",
+			markDataKey = type + "mark",
+			tmp;
+		function resolve() {
+			if ( !( --count ) ) {
+				defer.resolveWith( elements, [ elements ] );
+			}
+		}
+		while( i-- ) {
+			if (( tmp = jQuery.data( elements[ i ], deferDataKey, undefined, true ) ||
+					( jQuery.data( elements[ i ], queueDataKey, undefined, true ) ||
+						jQuery.data( elements[ i ], markDataKey, undefined, true ) ) &&
+					jQuery.data( elements[ i ], deferDataKey, jQuery.Callbacks( "once memory" ), true ) )) {
+				count++;
+				tmp.add( resolve );
+			}
+		}
+		resolve();
+		return defer.promise( object );
+	}
+});
+
+
+
+
+var rclass = /[\n\t\r]/g,
+	rspace = /\s+/,
+	rreturn = /\r/g,
+	rtype = /^(?:button|input)$/i,
+	rfocusable = /^(?:button|input|object|select|textarea)$/i,
+	rclickable = /^a(?:rea)?$/i,
+	rboolean = /^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i,
+	getSetAttribute = jQuery.support.getSetAttribute,
+	nodeHook, boolHook, fixSpecified;
+
+jQuery.fn.extend({
+	attr: function( name, value ) {
+		return jQuery.access( this, jQuery.attr, name, value, arguments.length > 1 );
+	},
+
+	removeAttr: function( name ) {
+		return this.each(function() {
+			jQuery.removeAttr( this, name );
+		});
+	},
+
+	prop: function( name, value ) {
+		return jQuery.access( this, jQuery.prop, name, value, arguments.length > 1 );
+	},
+
+	removeProp: function( name ) {
+		name = jQuery.propFix[ name ] || name;
+		return this.each(function() {
+			// try/catch handles cases where IE balks (such as removing a property on window)
+			try {
+				this[ name ] = undefined;
+				delete this[ name ];
+			} catch( e ) {}
+		});
+	},
+
+	addClass: function( value ) {
+		var classNames, i, l, elem,
+			setClass, c, cl;
+
+		if ( jQuery.isFunction( value ) ) {
+			return this.each(function( j ) {
+				jQuery( this ).addClass( value.call(this, j, this.className) );
+			});
+		}
+
+		if ( value && typeof value === "string" ) {
+			classNames = value.split( rspace );
+
+			for ( i = 0, l = this.length; i < l; i++ ) {
+				elem = this[ i ];
+
+				if ( elem.nodeType === 1 ) {
+					if ( !elem.className && classNames.length === 1 ) {
+						elem.className = value;
+
+					} else {
+						setClass = " " + elem.className + " ";
+
+						for ( c = 0, cl = classNames.length; c < cl; c++ ) {
+							if ( !~setClass.indexOf( " " + classNames[ c ] + " " ) ) {
+								setClass += classNames[ c ] + " ";
+							}
+						}
+						elem.className = jQuery.trim( setClass );
+					}
+				}
+			}
+		}
+
+		return this;
+	},
+
+	removeClass: function( value ) {
+		var classNames, i, l, elem, className, c, cl;
+
+		if ( jQuery.isFunction( value ) ) {
+			return this.each(function( j ) {
+				jQuery( this ).removeClass( value.call(this, j, this.className) );
+			});
+		}
+
+		if ( (value && typeof value === "string") || value === undefined ) {
+			classNames = ( value || "" ).split( rspace );
+
+			for ( i = 0, l = this.length; i < l; i++ ) {
+				elem = this[ i ];
+
+				if ( elem.nodeType === 1 && elem.className ) {
+					if ( value ) {
+						className = (" " + elem.className + " ").replace( rclass, " " );
+						for ( c = 0, cl = classNames.length; c < cl; c++ ) {
+							className = className.replace(" " + classNames[ c ] + " ", " ");
+						}
+						elem.className = jQuery.trim( className );
+
+					} else {
+						elem.className = "";
+					}
+				}
+			}
+		}
+
+		return this;
+	},
+
+	toggleClass: function( value, stateVal ) {
+		var type = typeof value,
+			isBool = typeof stateVal === "boolean";
+
+		if ( jQuery.isFunction( value ) ) {
+			return this.each(function( i ) {
+				jQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal );
+			});
+		}
+
+		return this.each(function() {
+			if ( type === "string" ) {
+				// toggle individual class names
+				var className,
+					i = 0,
+					self = jQuery( this ),
+					state = stateVal,
+					classNames = value.split( rspace );
+
+				while ( (className = classNames[ i++ ]) ) {
+					// check each className given, space seperated list
+					state = isBool ? state : !self.hasClass( className );
+					self[ state ? "addClass" : "removeClass" ]( className );
+				}
+
+			} else if ( type === "undefined" || type === "boolean" ) {
+				if ( this.className ) {
+					// store className if set
+					jQuery._data( this, "__className__", this.className );
+				}
+
+				// toggle whole className
+				this.className = this.className || value === false ? "" : jQuery._data( this, "__className__" ) || "";
+			}
+		});
+	},
+
+	hasClass: function( selector ) {
+		var className = " " + selector + " ",
+			i = 0,
+			l = this.length;
+		for ( ; i < l; i++ ) {
+			if ( this[i].nodeType === 1 && (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) > -1 ) {
+				return true;
+			}
+		}
+
+		return false;
+	},
+
+	val: function( value ) {
+		var hooks, ret, isFunction,
+			elem = this[0];
+
+		if ( !arguments.length ) {
+			if ( elem ) {
+				hooks = jQuery.valHooks[ elem.type ] || jQuery.valHooks[ elem.nodeName.toLowerCase() ];
+
+				if ( hooks && "get" in hooks && (ret = hooks.get( elem, "value" )) !== undefined ) {
+					return ret;
+				}
+
+				ret = elem.value;
+
+				return typeof ret === "string" ?
+					// handle most common string cases
+					ret.replace(rreturn, "") :
+					// handle cases where value is null/undef or number
+					ret == null ? "" : ret;
+			}
+
+			return;
+		}
+
+		isFunction = jQuery.isFunction( value );
+
+		return this.each(function( i ) {
+			var self = jQuery(this), val;
+
+			if ( this.nodeType !== 1 ) {
+				return;
+			}
+
+			if ( isFunction ) {
+				val = value.call( this, i, self.val() );
+			} else {
+				val = value;
+			}
+
+			// Treat null/undefined as ""; convert numbers to string
+			if ( val == null ) {
+				val = "";
+			} else if ( typeof val === "number" ) {
+				val += "";
+			} else if ( jQuery.isArray( val ) ) {
+				val = jQuery.map(val, function ( value ) {
+					return value == null ? "" : value + "";
+				});
+			}
+
+			hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ];
+
+			// If set returns undefined, fall back to normal setting
+			if ( !hooks || !("set" in hooks) || hooks.set( this, val, "value" ) === undefined ) {
+				this.value = val;
+			}
+		});
+	}
+});
+
+jQuery.extend({
+	valHooks: {
+		option: {
+			get: function( elem ) {
+				// attributes.value is undefined in Blackberry 4.7 but
+				// uses .value. See #6932
+				var val = elem.attributes.value;
+				return !val || val.specified ? elem.value : elem.text;
+			}
+		},
+		select: {
+			get: function( elem ) {
+				var value, i, max, option,
+					index = elem.selectedIndex,
+					values = [],
+					options = elem.options,
+					one = elem.type === "select-one";
+
+				// Nothing was selected
+				if ( index < 0 ) {
+					return null;
+				}
+
+				// Loop through all the selected options
+				i = one ? index : 0;
+				max = one ? index + 1 : options.length;
+				for ( ; i < max; i++ ) {
+					option = options[ i ];
+
+					// Don't return options that are disabled or in a disabled optgroup
+					if ( option.selected && (jQuery.support.optDisabled ? !option.disabled : option.getAttribute("disabled") === null) &&
+							(!option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" )) ) {
+
+						// Get the specific value for the option
+						value = jQuery( option ).val();
+
+						// We don't need an array for one selects
+						if ( one ) {
+							return value;
+						}
+
+						// Multi-Selects return an array
+						values.push( value );
+					}
+				}
+
+				// Fixes Bug #2551 -- select.val() broken in IE after form.reset()
+				if ( one && !values.length && options.length ) {
+					return jQuery( options[ index ] ).val();
+				}
+
+				return values;
+			},
+
+			set: function( elem, value ) {
+				var values = jQuery.makeArray( value );
+
+				jQuery(elem).find("option").each(function() {
+					this.selected = jQuery.inArray( jQuery(this).val(), values ) >= 0;
+				});
+
+				if ( !values.length ) {
+					elem.selectedIndex = -1;
+				}
+				return values;
+			}
+		}
+	},
+
+	attrFn: {
+		val: true,
+		css: true,
+		html: true,
+		text: true,
+		data: true,
+		width: true,
+		height: true,
+		offset: true
+	},
+
+	attr: function( elem, name, value, pass ) {
+		var ret, hooks, notxml,
+			nType = elem.nodeType;
+
+		// don't get/set attributes on text, comment and attribute nodes
+		if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
+			return;
+		}
+
+		if ( pass && name in jQuery.attrFn ) {
+			return jQuery( elem )[ name ]( value );
+		}
+
+		// Fallback to prop when attributes are not supported
+		if ( typeof elem.getAttribute === "undefined" ) {
+			return jQuery.prop( elem, name, value );
+		}
+
+		notxml = nType !== 1 || !jQuery.isXMLDoc( elem );
+
+		// All attributes are lowercase
+		// Grab necessary hook if one is defined
+		if ( notxml ) {
+			name = name.toLowerCase();
+			hooks = jQuery.attrHooks[ name ] || ( rboolean.test( name ) ? boolHook : nodeHook );
+		}
+
+		if ( value !== undefined ) {
+
+			if ( value === null ) {
+				jQuery.removeAttr( elem, name );
+				return;
+
+			} else if ( hooks && "set" in hooks && notxml && (ret = hooks.set( elem, value, name )) !== undefined ) {
+				return ret;
+
+			} else {
+				elem.setAttribute( name, "" + value );
+				return value;
+			}
+
+		} else if ( hooks && "get" in hooks && notxml && (ret = hooks.get( elem, name )) !== null ) {
+			return ret;
+
+		} else {
+
+			ret = elem.getAttribute( name );
+
+			// Non-existent attributes return null, we normalize to undefined
+			return ret === null ?
+				undefined :
+				ret;
+		}
+	},
+
+	removeAttr: function( elem, value ) {
+		var propName, attrNames, name, l, isBool,
+			i = 0;
+
+		if ( value && elem.nodeType === 1 ) {
+			attrNames = value.toLowerCase().split( rspace );
+			l = attrNames.length;
+
+			for ( ; i < l; i++ ) {
+				name = attrNames[ i ];
+
+				if ( name ) {
+					propName = jQuery.propFix[ name ] || name;
+					isBool = rboolean.test( name );
+
+					// See #9699 for explanation of this approach (setting first, then removal)
+					// Do not do this for boolean attributes (see #10870)
+					if ( !isBool ) {
+						jQuery.attr( elem, name, "" );
+					}
+					elem.removeAttribute( getSetAttribute ? name : propName );
+
+					// Set corresponding property to false for boolean attributes
+					if ( isBool && propName in elem ) {
+						elem[ propName ] = false;
+					}
+				}
+			}
+		}
+	},
+
+	attrHooks: {
+		type: {
+			set: function( elem, value ) {
+				// We can't allow the type property to be changed (since it causes problems in IE)
+				if ( rtype.test( elem.nodeName ) && elem.parentNode ) {
+					jQuery.error( "type property can't be changed" );
+				} else if ( !jQuery.support.radioValue && value === "radio" && jQuery.nodeName(elem, "input") ) {
+					// Setting the type on a radio button after the value resets the value in IE6-9
+					// Reset value to it's default in case type is set after value
+					// This is for element creation
+					var val = elem.value;
+					elem.setAttribute( "type", value );
+					if ( val ) {
+						elem.value = val;
+					}
+					return value;
+				}
+			}
+		},
+		// Use the value property for back compat
+		// Use the nodeHook for button elements in IE6/7 (#1954)
+		value: {
+			get: function( elem, name ) {
+				if ( nodeHook && jQuery.nodeName( elem, "button" ) ) {
+					return nodeHook.get( elem, name );
+				}
+				return name in elem ?
+					elem.value :
+					null;
+			},
+			set: function( elem, value, name ) {
+				if ( nodeHook && jQuery.nodeName( elem, "button" ) ) {
+					return nodeHook.set( elem, value, name );
+				}
+				// Does not return so that setAttribute is also used
+				elem.value = value;
+			}
+		}
+	},
+
+	propFix: {
+		tabindex: "tabIndex",
+		readonly: "readOnly",
+		"for": "htmlFor",
+		"class": "className",
+		maxlength: "maxLength",
+		cellspacing: "cellSpacing",
+		cellpadding: "cellPadding",
+		rowspan: "rowSpan",
+		colspan: "colSpan",
+		usemap: "useMap",
+		frameborder: "frameBorder",
+		contenteditable: "contentEditable"
+	},
+
+	prop: function( elem, name, value ) {
+		var ret, hooks, notxml,
+			nType = elem.nodeType;
+
+		// don't get/set properties on text, comment and attribute nodes
+		if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
+			return;
+		}
+
+		notxml = nType !== 1 || !jQuery.isXMLDoc( elem );
+
+		if ( notxml ) {
+			// Fix name and attach hooks
+			name = jQuery.propFix[ name ] || name;
+			hooks = jQuery.propHooks[ name ];
+		}
+
+		if ( value !== undefined ) {
+			if ( hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) {
+				return ret;
+
+			} else {
+				return ( elem[ name ] = value );
+			}
+
+		} else {
+			if ( hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ) {
+				return ret;
+
+			} else {
+				return elem[ name ];
+			}
+		}
+	},
+
+	propHooks: {
+		tabIndex: {
+			get: function( elem ) {
+				// elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set
+				// http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/
+				var attributeNode = elem.getAttributeNode("tabindex");
+
+				return attributeNode && attributeNode.specified ?
+					parseInt( attributeNode.value, 10 ) :
+					rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ?
+						0 :
+						undefined;
+			}
+		}
+	}
+});
+
+// Add the tabIndex propHook to attrHooks for back-compat (different case is intentional)
+jQuery.attrHooks.tabindex = jQuery.propHooks.tabIndex;
+
+// Hook for boolean attributes
+boolHook = {
+	get: function( elem, name ) {
+		// Align boolean attributes with corresponding properties
+		// Fall back to attribute presence where some booleans are not supported
+		var attrNode,
+			property = jQuery.prop( elem, name );
+		return property === true || typeof property !== "boolean" && ( attrNode = elem.getAttributeNode(name) ) && attrNode.nodeValue !== false ?
+			name.toLowerCase() :
+			undefined;
+	},
+	set: function( elem, value, name ) {
+		var propName;
+		if ( value === false ) {
+			// Remove boolean attributes when set to false
+			jQuery.removeAttr( elem, name );
+		} else {
+			// value is true since we know at this point it's type boolean and not false
+			// Set boolean attributes to the same name and set the DOM property
+			propName = jQuery.propFix[ name ] || name;
+			if ( propName in elem ) {
+				// Only set the IDL specifically if it already exists on the element
+				elem[ propName ] = true;
+			}
+
+			elem.setAttribute( name, name.toLowerCase() );
+		}
+		return name;
+	}
+};
+
+// IE6/7 do not support getting/setting some attributes with get/setAttribute
+if ( !getSetAttribute ) {
+
+	fixSpecified = {
+		name: true,
+		id: true,
+		coords: true
+	};
+
+	// Use this for any attribute in IE6/7
+	// This fixes almost every IE6/7 issue
+	nodeHook = jQuery.valHooks.button = {
+		get: function( elem, name ) {
+			var ret;
+			ret = elem.getAttributeNode( name );
+			return ret && ( fixSpecified[ name ] ? ret.nodeValue !== "" : ret.specified ) ?
+				ret.nodeValue :
+				undefined;
+		},
+		set: function( elem, value, name ) {
+			// Set the existing or create a new attribute node
+			var ret = elem.getAttributeNode( name );
+			if ( !ret ) {
+				ret = document.createAttribute( name );
+				elem.setAttributeNode( ret );
+			}
+			return ( ret.nodeValue = value + "" );
+		}
+	};
+
+	// Apply the nodeHook to tabindex
+	jQuery.attrHooks.tabindex.set = nodeHook.set;
+
+	// Set width and height to auto instead of 0 on empty string( Bug #8150 )
+	// This is for removals
+	jQuery.each([ "width", "height" ], function( i, name ) {
+		jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], {
+			set: function( elem, value ) {
+				if ( value === "" ) {
+					elem.setAttribute( name, "auto" );
+					return value;
+				}
+			}
+		});
+	});
+
+	// Set contenteditable to false on removals(#10429)
+	// Setting to empty string throws an error as an invalid value
+	jQuery.attrHooks.contenteditable = {
+		get: nodeHook.get,
+		set: function( elem, value, name ) {
+			if ( value === "" ) {
+				value = "false";
+			}
+			nodeHook.set( elem, value, name );
+		}
+	};
+}
+
+
+// Some attributes require a special call on IE
+if ( !jQuery.support.hrefNormalized ) {
+	jQuery.each([ "href", "src", "width", "height" ], function( i, name ) {
+		jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], {
+			get: function( elem ) {
+				var ret = elem.getAttribute( name, 2 );
+				return ret === null ? undefined : ret;
+			}
+		});
+	});
+}
+
+if ( !jQuery.support.style ) {
+	jQuery.attrHooks.style = {
+		get: function( elem ) {
+			// Return undefined in the case of empty string
+			// Normalize to lowercase since IE uppercases css property names
+			return elem.style.cssText.toLowerCase() || undefined;
+		},
+		set: function( elem, value ) {
+			return ( elem.style.cssText = "" + value );
+		}
+	};
+}
+
+// Safari mis-reports the default selected property of an option
+// Accessing the parent's selectedIndex property fixes it
+if ( !jQuery.support.optSelected ) {
+	jQuery.propHooks.selected = jQuery.extend( jQuery.propHooks.selected, {
+		get: function( elem ) {
+			var parent = elem.parentNode;
+
+			if ( parent ) {
+				parent.selectedIndex;
+
+				// Make sure that it also works with optgroups, see #5701
+				if ( parent.parentNode ) {
+					parent.parentNode.selectedIndex;
+				}
+			}
+			return null;
+		}
+	});
+}
+
+// IE6/7 call enctype encoding
+if ( !jQuery.support.enctype ) {
+	jQuery.propFix.enctype = "encoding";
+}
+
+// Radios and checkboxes getter/setter
+if ( !jQuery.support.checkOn ) {
+	jQuery.each([ "radio", "checkbox" ], function() {
+		jQuery.valHooks[ this ] = {
+			get: function( elem ) {
+				// Handle the case where in Webkit "" is returned instead of "on" if a value isn't specified
+				return elem.getAttribute("value") === null ? "on" : elem.value;
+			}
+		};
+	});
+}
+jQuery.each([ "radio", "checkbox" ], function() {
+	jQuery.valHooks[ this ] = jQuery.extend( jQuery.valHooks[ this ], {
+		set: function( elem, value ) {
+			if ( jQuery.isArray( value ) ) {
+				return ( elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0 );
+			}
+		}
+	});
+});
+
+
+
+
+var rformElems = /^(?:textarea|input|select)$/i,
+	rtypenamespace = /^([^\.]*)?(?:\.(.+))?$/,
+	rhoverHack = /(?:^|\s)hover(\.\S+)?\b/,
+	rkeyEvent = /^key/,
+	rmouseEvent = /^(?:mouse|contextmenu)|click/,
+	rfocusMorph = /^(?:focusinfocus|focusoutblur)$/,
+	rquickIs = /^(\w*)(?:#([\w\-]+))?(?:\.([\w\-]+))?$/,
+	quickParse = function( selector ) {
+		var quick = rquickIs.exec( selector );
+		if ( quick ) {
+			//   0  1    2   3
+			// [ _, tag, id, class ]
+			quick[1] = ( quick[1] || "" ).toLowerCase();
+			quick[3] = quick[3] && new RegExp( "(?:^|\\s)" + quick[3] + "(?:\\s|$)" );
+		}
+		return quick;
+	},
+	quickIs = function( elem, m ) {
+		var attrs = elem.attributes || {};
+		return (
+			(!m[1] || elem.nodeName.toLowerCase() === m[1]) &&
+			(!m[2] || (attrs.id || {}).value === m[2]) &&
+			(!m[3] || m[3].test( (attrs[ "class" ] || {}).value ))
+		);
+	},
+	hoverHack = function( events ) {
+		return jQuery.event.special.hover ? events : events.replace( rhoverHack, "mouseenter$1 mouseleave$1" );
+	};
+
+/*
+ * Helper functions for managing events -- not part of the public interface.
+ * Props to Dean Edwards' addEvent library for many of the ideas.
+ */
+jQuery.event = {
+
+	add: function( elem, types, handler, data, selector ) {
+
+		var elemData, eventHandle, events,
+			t, tns, type, namespaces, handleObj,
+			handleObjIn, quick, handlers, special;
+
+		// Don't attach events to noData or text/comment nodes (allow plain objects tho)
+		if ( elem.nodeType === 3 || elem.nodeType === 8 || !types || !handler || !(elemData = jQuery._data( elem )) ) {
+			return;
+		}
+
+		// Caller can pass in an object of custom data in lieu of the handler
+		if ( handler.handler ) {
+			handleObjIn = handler;
+			handler = handleObjIn.handler;
+			selector = handleObjIn.selector;
+		}
+
+		// Make sure that the handler has a unique ID, used to find/remove it later
+		if ( !handler.guid ) {
+			handler.guid = jQuery.guid++;
+		}
+
+		// Init the element's event structure and main handler, if this is the first
+		events = elemData.events;
+		if ( !events ) {
+			elemData.events = events = {};
+		}
+		eventHandle = elemData.handle;
+		if ( !eventHandle ) {
+			elemData.handle = eventHandle = function( e ) {
+				// Discard the second event of a jQuery.event.trigger() and
+				// when an event is called after a page has unloaded
+				return typeof jQuery !== "undefined" && (!e || jQuery.event.triggered !== e.type) ?
+					jQuery.event.dispatch.apply( eventHandle.elem, arguments ) :
+					undefined;
+			};
+			// Add elem as a property of the handle fn to prevent a memory leak with IE non-native events
+			eventHandle.elem = elem;
+		}
+
+		// Handle multiple events separated by a space
+		// jQuery(...).bind("mouseover mouseout", fn);
+		types = jQuery.trim( hoverHack(types) ).split( " " );
+		for ( t = 0; t < types.length; t++ ) {
+
+			tns = rtypenamespace.exec( types[t] ) || [];
+			type = tns[1];
+			namespaces = ( tns[2] || "" ).split( "." ).sort();
+
+			// If event changes its type, use the special event handlers for the changed type
+			special = jQuery.event.special[ type ] || {};
+
+			// If selector defined, determine special event api type, otherwise given type
+			type = ( selector ? special.delegateType : special.bindType ) || type;
+
+			// Update special based on newly reset type
+			special = jQuery.event.special[ type ] || {};
+
+			// handleObj is passed to all event handlers
+			handleObj = jQuery.extend({
+				type: type,
+				origType: tns[1],
+				data: data,
+				handler: handler,
+				guid: handler.guid,
+				selector: selector,
+				quick: selector && quickParse( selector ),
+				namespace: namespaces.join(".")
+			}, handleObjIn );
+
+			// Init the event handler queue if we're the first
+			handlers = events[ type ];
+			if ( !handlers ) {
+				handlers = events[ type ] = [];
+				handlers.delegateCount = 0;
+
+				// Only use addEventListener/attachEvent if the special events handler returns false
+				if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) {
+					// Bind the global event handler to the element
+					if ( elem.addEventListener ) {
+						elem.addEventListener( type, eventHandle, false );
+
+					} else if ( elem.attachEvent ) {
+						elem.attachEvent( "on" + type, eventHandle );
+					}
+				}
+			}
+
+			if ( special.add ) {
+				special.add.call( elem, handleObj );
+
+				if ( !handleObj.handler.guid ) {
+					handleObj.handler.guid = handler.guid;
+				}
+			}
+
+			// Add to the element's handler list, delegates in front
+			if ( selector ) {
+				handlers.splice( handlers.delegateCount++, 0, handleObj );
+			} else {
+				handlers.push( handleObj );
+			}
+
+			// Keep track of which events have ever been used, for event optimization
+			jQuery.event.global[ type ] = true;
+		}
+
+		// Nullify elem to prevent memory leaks in IE
+		elem = null;
+	},
+
+	global: {},
+
+	// Detach an event or set of events from an element
+	remove: function( elem, types, handler, selector, mappedTypes ) {
+
+		var elemData = jQuery.hasData( elem ) && jQuery._data( elem ),
+			t, tns, type, origType, namespaces, origCount,
+			j, events, special, handle, eventType, handleObj;
+
+		if ( !elemData || !(events = elemData.events) ) {
+			return;
+		}
+
+		// Once for each type.namespace in types; type may be omitted
+		types = jQuery.trim( hoverHack( types || "" ) ).split(" ");
+		for ( t = 0; t < types.length; t++ ) {
+			tns = rtypenamespace.exec( types[t] ) || [];
+			type = origType = tns[1];
+			namespaces = tns[2];
+
+			// Unbind all events (on this namespace, if provided) for the element
+			if ( !type ) {
+				for ( type in events ) {
+					jQuery.event.remove( elem, type + types[ t ], handler, selector, true );
+				}
+				continue;
+			}
+
+			special = jQuery.event.special[ type ] || {};
+			type = ( selector? special.delegateType : special.bindType ) || type;
+			eventType = events[ type ] || [];
+			origCount = eventType.length;
+			namespaces = namespaces ? new RegExp("(^|\\.)" + namespaces.split(".").sort().join("\\.(?:.*\\.)?") + "(\\.|$)") : null;
+
+			// Remove matching events
+			for ( j = 0; j < eventType.length; j++ ) {
+				handleObj = eventType[ j ];
+
+				if ( ( mappedTypes || origType === handleObj.origType ) &&
+					 ( !handler || handler.guid === handleObj.guid ) &&
+					 ( !namespaces || namespaces.test( handleObj.namespace ) ) &&
+					 ( !selector || selector === handleObj.selector || selector === "**" && handleObj.selector ) ) {
+					eventType.splice( j--, 1 );
+
+					if ( handleObj.selector ) {
+						eventType.delegateCount--;
+					}
+					if ( special.remove ) {
+						special.remove.call( elem, handleObj );
+					}
+				}
+			}
+
+			// Remove generic event handler if we removed something and no more handlers exist
+			// (avoids potential for endless recursion during removal of special event handlers)
+			if ( eventType.length === 0 && origCount !== eventType.length ) {
+				if ( !special.teardown || special.teardown.call( elem, namespaces ) === false ) {
+					jQuery.removeEvent( elem, type, elemData.handle );
+				}
+
+				delete events[ type ];
+			}
+		}
+
+		// Remove the expando if it's no longer used
+		if ( jQuery.isEmptyObject( events ) ) {
+			handle = elemData.handle;
+			if ( handle ) {
+				handle.elem = null;
+			}
+
+			// removeData also checks for emptiness and clears the expando if empty
+			// so use it instead of delete
+			jQuery.removeData( elem, [ "events", "handle" ], true );
+		}
+	},
+
+	// Events that are safe to short-circuit if no handlers are attached.
+	// Native DOM events should not be added, they may have inline handlers.
+	customEvent: {
+		"getData": true,
+		"setData": true,
+		"changeData": true
+	},
+
+	trigger: function( event, data, elem, onlyHandlers ) {
+		// Don't do events on text and comment nodes
+		if ( elem && (elem.nodeType === 3 || elem.nodeType === 8) ) {
+			return;
+		}
+
+		// Event object or event type
+		var type = event.type || event,
+			namespaces = [],
+			cache, exclusive, i, cur, old, ontype, special, handle, eventPath, bubbleType;
+
+		// focus/blur morphs to focusin/out; ensure we're not firing them right now
+		if ( rfocusMorph.test( type + jQuery.event.triggered ) ) {
+			return;
+		}
+
+		if ( type.indexOf( "!" ) >= 0 ) {
+			// Exclusive events trigger only for the exact event (no namespaces)
+			type = type.slice(0, -1);
+			exclusive = true;
+		}
+
+		if ( type.indexOf( "." ) >= 0 ) {
+			// Namespaced trigger; create a regexp to match event type in handle()
+			namespaces = type.split(".");
+			type = namespaces.shift();
+			namespaces.sort();
+		}
+
+		if ( (!elem || jQuery.event.customEvent[ type ]) && !jQuery.event.global[ type ] ) {
+			// No jQuery handlers for this event type, and it can't have inline handlers
+			return;
+		}
+
+		// Caller can pass in an Event, Object, or just an event type string
+		event = typeof event === "object" ?
+			// jQuery.Event object
+			event[ jQuery.expando ] ? event :
+			// Object literal
+			new jQuery.Event( type, event ) :
+			// Just the event type (string)
+			new jQuery.Event( type );
+
+		event.type = type;
+		event.isTrigger = true;
+		event.exclusive = exclusive;
+		event.namespace = namespaces.join( "." );
+		event.namespace_re = event.namespace? new RegExp("(^|\\.)" + namespaces.join("\\.(?:.*\\.)?") + "(\\.|$)") : null;
+		ontype = type.indexOf( ":" ) < 0 ? "on" + type : "";
+
+		// Handle a global trigger
+		if ( !elem ) {
+
+			// TODO: Stop taunting the data cache; remove global events and always attach to document
+			cache = jQuery.cache;
+			for ( i in cache ) {
+				if ( cache[ i ].events && cache[ i ].events[ type ] ) {
+					jQuery.event

<TRUNCATED>
http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/test/lib/angular/.svn/text-base/version.txt.svn-base
----------------------------------------------------------------------
diff --git a/src/main/ui/test/lib/angular/.svn/text-base/version.txt.svn-base b/src/main/ui/test/lib/angular/.svn/text-base/version.txt.svn-base
new file mode 100755
index 0000000..90a27f9
--- /dev/null
+++ b/src/main/ui/test/lib/angular/.svn/text-base/version.txt.svn-base
@@ -0,0 +1 @@
+1.0.5


[02/51] [abbrv] [partial] Adding Jinwon's custom RCMET

Posted by jo...@apache.org.
http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/webapp/.svn/text-base/.htaccess.svn-base
----------------------------------------------------------------------
diff --git a/src/main/webapp/.svn/text-base/.htaccess.svn-base b/src/main/webapp/.svn/text-base/.htaccess.svn-base
new file mode 100755
index 0000000..e3a557a
--- /dev/null
+++ b/src/main/webapp/.svn/text-base/.htaccess.svn-base
@@ -0,0 +1,45 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+# Rewrite rules for OODT Balance web applications. 
+#
+# Enable the rewrite engine
+RewriteEngine On
+
+# Make sure that the value for RewriteBase exactly matches the 
+# value for site_root in config.ini. This value should point to the 
+# location (relative to the server's document root) of the 
+# Balance webapp directory (the directory containing config.ini). For
+# example, if the application lives at the server's document root, then
+# RewriteBase should be set to '/'. If, on the other hand, the application
+# has been installed into a subdirectory 'foo' underneath the server's 
+# document root, RewriteBase (and site_root in config.ini) should be set
+# to '/foo/'
+RewriteBase /
+
+# This section forwards all requests to the Balance application's front
+# controller. Unless you are modifying the low-level behavior of the 
+# Balance application framework, there should be no need to make any
+# modifications below this line. -----------------------------------------
+#
+# Send all other non-static requests to the main controller
+RewriteCond %{REQUEST_URI} !/static/(.*)$
+RewriteCond %{REQUEST_URI} !/scripts/(.*)$
+RewriteCond %{REQUEST_URI} !/global/(.*)$
+RewriteCond %{REQUEST_URI} !index\.php/.+$
+RewriteRule ^(.+)$ ./index\.php/$1 [L,NC]
+

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/webapp/.svn/text-base/config.ini.svn-base
----------------------------------------------------------------------
diff --git a/src/main/webapp/.svn/text-base/config.ini.svn-base b/src/main/webapp/.svn/text-base/config.ini.svn-base
new file mode 100755
index 0000000..3d424c7
--- /dev/null
+++ b/src/main/webapp/.svn/text-base/config.ini.svn-base
@@ -0,0 +1,66 @@
+; OODT Balance
+; Web Application Base Framework
+;
+; Application Configuration File. This file should be called 'config.ini' and 
+; should reside in the root directory of your site. This file follows standard
+; ini file conventions. Lines beginning with ';' are comments and are ignored.
+;
+
+[Application Environment]
+
+; site_root
+; If the site lives at the document root of the server, this will be '/'. On
+; the other hand, if the site lives in a sub-directory of the document root, 
+; this will be the full path (starting from the document root) to the root 
+; directory of the site. Always start with a slash (/) and always omit the
+; trailing slash. 
+;
+; examples: 
+;    (document root) http://domain.com/          (site_root: '/')
+;    (subdirectory)  http://domain.com/apps/site (site_root: '/apps/site')
+;
+; Note: The value for site_root should always match the value for 'RewriteBase'
+;       in the .htaccess file located in the site's root directory.
+;
+site_root = /
+
+
+[Application Content]
+
+; views_dir
+; This is the directory inside your site root where your application's views
+; reside. This should be a relative path (./). If you have set things up
+; according to the instructions, the framework will use the location of this 
+; file (config.ini) as the base.
+;
+; Note: The value provided is simply an example. It is up to you to provide
+;       valid paths.
+views_dir = ./views
+
+; header_file_path
+; This is the file that contains a site-wide header code/layout to be included
+; in each view. This should be a relative path (./). If you have set things up
+; according to the instructions, the framework will use the location of this 
+; file (config.ini) as the base.
+;
+; Note: The value provided is simply an example. It is up to you to provide
+;       valid paths.
+header_file_path = ./views/common/header.php
+
+; footer_file_path
+; This is the file that contains a site-wide footer code/layout to be included
+; in each view. This should be a relative path (./). If you have set things up
+; according to the instructions, the framework will use the location of this 
+; file (config.ini) as the base.
+;
+; Note: The value provided is simply an example. It is up to you to provide
+;       valid paths.
+footer_file_path = ./views/common/footer.php
+
+
+[RCMET_CONFIG]
+rcmet_working_directory = /path/to/working/directory
+rcmet_cache_directory   = /path/to/cache/directory
+rcmet_service_url_base  = http://host:port
+rcmet_service_use_curl  = false
+rcmed_query_api_url_base = http://rcmes.jpl.nasa.gov/query-api
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/webapp/.svn/text-base/hooks.php.svn-base
----------------------------------------------------------------------
diff --git a/src/main/webapp/.svn/text-base/hooks.php.svn-base b/src/main/webapp/.svn/text-base/hooks.php.svn-base
new file mode 100755
index 0000000..769cfc0
--- /dev/null
+++ b/src/main/webapp/.svn/text-base/hooks.php.svn-base
@@ -0,0 +1,83 @@
+<?php
+/**
+ * Copyright (c) 2010, California Institute of Technology.
+ * ALL RIGHTS RESERVED. U.S. Government sponsorship acknowledged.
+ * 
+ * $Id$
+ * 
+ * 
+ * OODT Balance
+ * Web Application Base Framework
+ */
+/**
+ * HOOKS.PHP
+ * 
+ * Hooks provide the ability, as the name implies, to hook into various parts of 
+ * the view rendering process and insert customizations. The contents of these 
+ * functions are run at the appropriate time *EVERY* time a view is rendered, i.e.
+ * the content of the hooks is not by default view-specific but rather will be 
+ * applied to all views. (However, there is nothing that prevents developers from 
+ * inserting conditional logic inside a hook that then causes view-specific
+ * them to exhibit view-specific behavior).
+ * 
+ * As an example, consider a hook that adds the amount of time Balance took to render
+ * the page as an inline HTML comment at the bottom of each page after it has been sent:
+ * 
+ * function hook_after_send() {
+ *     $timeStart = $GLOBALS['balance_request_start'];
+ *     $timeNow   = microtime(true);
+ *     $elapsed   = $timeNow - $timeStart;
+ *     echo "<!-- page rendered in {$elapsed} seconds -->";
+ * }
+ * 
+ * 
+ * Take a look at the docblock descriptions of each hook to get a sense of where
+ * in the view rendering process the hook is invoked.
+ * 
+ * @author ahart
+ */
+
+/**
+ * hook_before_header
+ * 
+ * This hook is executed before the contents of the header file are processed.
+ */
+function hook_before_header() {}
+
+/**
+ * hook_before_view
+ * 
+ * This hook is executed before the contents of the main view are processed.
+ */
+function hook_before_view() {}
+
+/**
+ * hook_before_footer
+ * 
+ * This hook is executed before the contents of the footer are processed
+ */
+function hook_before_footer() {}
+
+/**
+ * hook_before_send
+ * 
+ * This hook is after all of the view components (header, view, footer) have been
+ * processed but before the processed results are sent out across the wire to the 
+ * browser. HTTP headers have not yet been sent to the browser.
+ */
+function hook_before_send() {}
+
+/**
+ * hook_after_send
+ * 
+ * This hook is after all of the view components (header, view, footer) have been
+ * processed and sent out across the wire to the browser. It can be used for logging
+ * or analytics purposes, or to append a common trailer to all content.
+ */
+function hook_after_send() {
+	$timeStart = $GLOBALS['balance_request_start'];
+	$timeEnd   = microtime(true);
+	$elapsed   = $timeEnd - $timeStart;
+	
+	echo "\r\n<!-- page rendered in {$elapsed} seconds -->";
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/webapp/.svn/text-base/index.php.svn-base
----------------------------------------------------------------------
diff --git a/src/main/webapp/.svn/text-base/index.php.svn-base b/src/main/webapp/.svn/text-base/index.php.svn-base
new file mode 100755
index 0000000..e02633d
--- /dev/null
+++ b/src/main/webapp/.svn/text-base/index.php.svn-base
@@ -0,0 +1,48 @@
+<?php
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * OODT Balance
+ * Web Application Base Framework
+ *
+ * Front-controller
+ * This file handles the marshalling of requests to the appropriate
+ * application view.
+ *
+ */
+define ("DEBUG", true); // Change this to `false` when no longer debugging
+
+// Application root directory path (should never need to change this)
+define ("HOME",  dirname(__FILE__));
+
+/* Set up application environment ***************************************/
+require_once("Org/Apache/Oodt/Balance/Boot/bootstrap.php");
+
+/* Initialize the application with the settings from config.ini *********/
+$app = $GLOBALS['app'] = App::Create(parse_ini_file(HOME . '/config.ini'));
+
+/* Initialize any globally required modules here ************************/
+// Example:
+// To load a module 'foo', located at ./modules/foo, on every request:
+// App::Get()->loadModule('foo');
+
+/* Generate and send a response to the browser **************************/
+$response = $app->getResponse()->send();
+
+/* Clean up after ourselves *********************************************/
+$app->cleanup();

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/webapp/classes/.svn/all-wcprops
----------------------------------------------------------------------
diff --git a/src/main/webapp/classes/.svn/all-wcprops b/src/main/webapp/classes/.svn/all-wcprops
new file mode 100755
index 0000000..2bf2652
--- /dev/null
+++ b/src/main/webapp/classes/.svn/all-wcprops
@@ -0,0 +1,17 @@
+K 25
+svn:wc:ra_dav:version-url
+V 81
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/webapp/classes
+END
+RCMETWizardTask.class.php
+K 25
+svn:wc:ra_dav:version-url
+V 107
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/webapp/classes/RCMETWizardTask.class.php
+END
+WizardTask.class.php
+K 25
+svn:wc:ra_dav:version-url
+V 102
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/webapp/classes/WizardTask.class.php
+END

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/webapp/classes/.svn/entries
----------------------------------------------------------------------
diff --git a/src/main/webapp/classes/.svn/entries b/src/main/webapp/classes/.svn/entries
new file mode 100755
index 0000000..ed5ba86
--- /dev/null
+++ b/src/main/webapp/classes/.svn/entries
@@ -0,0 +1,96 @@
+10
+
+dir
+1485921
+https://svn.apache.org/repos/asf/incubator/climate/trunk/rcmet/src/main/webapp/classes
+https://svn.apache.org/repos/asf
+
+
+
+2011-12-13T03:57:45.293099Z
+1471825
+mattmann
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+13f79535-47bb-0310-9956-ffa450edef68
+
+RCMETWizardTask.class.php
+file
+
+
+
+
+2013-05-24T10:13:59.000000Z
+be8e652b1c96b429c22fab8350c0c53e
+2011-12-13T03:57:45.293099Z
+1471825
+mattmann
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+3660
+
+WizardTask.class.php
+file
+
+
+
+
+2013-05-24T10:13:59.000000Z
+09fc5b72f6615b9e8f96970f8a1e6edd
+2011-12-13T03:57:45.293099Z
+1471825
+mattmann
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+1327
+

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/webapp/classes/.svn/text-base/RCMETWizardTask.class.php.svn-base
----------------------------------------------------------------------
diff --git a/src/main/webapp/classes/.svn/text-base/RCMETWizardTask.class.php.svn-base b/src/main/webapp/classes/.svn/text-base/RCMETWizardTask.class.php.svn-base
new file mode 100755
index 0000000..6e985f7
--- /dev/null
+++ b/src/main/webapp/classes/.svn/text-base/RCMETWizardTask.class.php.svn-base
@@ -0,0 +1,125 @@
+<?php
+require_once(HOME . '/classes/WizardTask.class.php');
+
+class RCMETWizardTask extends WizardTask {
+	
+	public $modelFilePaths = array();
+	public $modelVars      = array();
+	public $modelBounds    = array();
+	
+	public $modelParameter = '';
+	public $observationalParameter = '';
+	public $observationalParameterId = '';
+	public $observationalDataset   = '';
+	public $observationalDatasetId = '';
+	
+	// Time Range
+	public $rangeStart;
+	public $rangeEnd;
+	
+	// Regrid
+	public $spatialRegridOption;
+	public $temporalRegridOption;
+	
+	// Options
+	public $computeAreaAverages;
+	
+	// Metrics
+	public $metric;
+	
+	// Plot Options	
+	
+	public function dictTemporalRegrid($key) {
+		
+		$dict = array(
+			"full" => "Time mean for full period",
+			"annual" => "Annual Means",
+			"monthly" => "Monthly Means",
+			"daily" => "Daily means (from sub-daily data)"	
+		);
+		return (isset($dict[$key]))
+			? $dict[$key]
+			: false;
+	}
+	
+	public function dictSpatialRegrid($key) {
+		
+		$dict = array(
+			"model" => "Use the model data grid",
+			"obs" => "Use the observational data grid",
+			"regular" => "Monthly Means"	
+		);
+		return (isset($dict[$key]))
+			? $dict[$key]
+			: false;
+	}
+	
+	public function dictMetrics($key) {
+		$dict = array(
+			"bias" => "Bias: mean bias across full time range",
+			"mae"  => "Mean Absolute Error: across full time range",
+			"difference" => "Difference: calculated at each time unit",
+			"acc"  => "Anomaly Correlation",
+			"patcor" => "Pattern Correlation",
+			"pdf" => "Probability Distribution Function similarity score",
+			"rms" => "RMS Error"	
+		);
+		return (isset($dict[$key]))
+			? $dict[$key]
+			: false;
+	}
+	
+	public function getTimeRange($observationalDatasetId) {
+		$dsTimes = array(
+			"1" => array('1989-01-01 00:00:00','2009-12-31 00:00:00'),	// ERA-Interim
+			"2" => array('2002-08-31 00:00:00','2010-01-01 00:00:00'),	// AIRS
+			"3" => array('1998-01-01 00:00:00','2010-01-01 00:00:00'),	// TRMM
+			"4" => array('1948-01-01 00:00:00','2010-01-01 00:00:00'),	// URD
+			"5" => array('2000-02-24 00:00:00','2010-05-30 00:00:00'),	// MODIS
+			"6" => array('1901-01-01 00:00:00','2006-12-01 00:00:00')); // CRU
+		 
+		if (isset($dsTimes[$observationalDatasetId]))
+			return $dsTimes[$observationalDatasetId];
+		else 
+			return false;
+	}
+	
+	public function computeOverlap($modelStart,$modelEnd,$obsStart,$obsEnd) {
+		$mstart = strtotime($modelStart);
+		$mend   = strtotime($modelEnd);
+		$ostart = strtotime($obsStart);
+		$oend   = strtotime($obsEnd);
+		
+		// The "later" of the two start times is the beginning of the overlap
+		$rangeStart = ($mstart > $ostart) ? $mstart : $ostart;
+		
+		// The "earlier" of the two end times is the end of the overlap
+		$rangeEnd   = ($mend < $oend) ? $mend : $oend;
+		
+		// Format the return values
+		return array(date('Y-m-d H:i:s',$rangeStart),
+					 date('Y-m-d H:i:s',$rangeEnd));
+	}
+	
+	
+	
+	public function __construct () {
+		
+		parent::__construct();
+		
+		$this->steps = array(
+			//     URL_NAME             HUMAN_READABLE
+			array("selectModelFiles",   "Select Model Files"),
+			array("selectLatLonVars",   "Select Latitude and Longitude Variables"),
+			array("selectTimeVars",     "Select Time Variable"),
+			array("selectModelVar",     "Select Model Variable"),
+			array("selectObservationalData", "Select Observational Data"),
+			array("selectTimeRange",    "Select Time Range for Calculation"),
+			array("selectRegrid",       "Select Regridding Options"),
+			array("selectOptionalTasks","Select Optional Calculation Tasks"),
+			array("selectMetricOptions","Select Metrics"),
+			array("selectPlotOptions",  "Select Plot Options"),
+			array("generatePlots",      "Generate Plots"),
+		);
+	}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/webapp/classes/.svn/text-base/WizardTask.class.php.svn-base
----------------------------------------------------------------------
diff --git a/src/main/webapp/classes/.svn/text-base/WizardTask.class.php.svn-base b/src/main/webapp/classes/.svn/text-base/WizardTask.class.php.svn-base
new file mode 100755
index 0000000..8de173f
--- /dev/null
+++ b/src/main/webapp/classes/.svn/text-base/WizardTask.class.php.svn-base
@@ -0,0 +1,55 @@
+<?php
+class WizardTask {
+	
+	public $currentStep = '';
+	public $steps = array();
+	
+	public function __construct() {}
+	
+	public function save() {
+		$_SESSION['wizardTask'] = serialize($this);
+	}
+	
+	public function setStep($which) {
+		$this->currentStep = $which;
+	}
+	
+	public function firstStep() {
+		$this->goToStep($this->steps[0][0]);
+	}
+	
+	public function nextStep() {
+		for($i=0;$i<count($this->steps);$i++) {
+			if (strtolower($this->steps[$i][0]) == strtolower($this->currentStep)) {
+				return (isset($this->steps[$i + 1]))
+					? $this->goToStep($this->steps[$i+1][0])
+					: false;
+			}
+		}
+	}
+	
+	public function previousStep($current) {
+		for($i=0;$i<count($this->steps);$i++) {
+			if (strtolower($this->steps[$i]) == strtolower($this->currentStep)) {
+				return (isset($this->steps[$i - 1]))
+					? $this->goToStep($this->steps[$i - 1][0])
+					: false;
+			}
+		}
+	}	
+	
+	protected function goToStep($step) {
+		$this->save();
+		header("Location: " . SITE_ROOT . "/wizard/step/" . $step);
+		exit();
+	}
+	
+	public function showPreviousNextLinks() {
+		for($i=1;$i<count($this->steps);$i++) {
+			if (strtolower($this->steps[$i][0]) == strtolower($this->currentStep)) { 
+				echo "<div class='box nav'>Back to <a href='".SITE_ROOT
+					."/wizard/step/{$this->steps[$i-1][0]}'>{$this->steps[$i-1][1]}</a></div>";
+			}
+		}
+	}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/webapp/classes/RCMETWizardTask.class.php
----------------------------------------------------------------------
diff --git a/src/main/webapp/classes/RCMETWizardTask.class.php b/src/main/webapp/classes/RCMETWizardTask.class.php
new file mode 100755
index 0000000..6e985f7
--- /dev/null
+++ b/src/main/webapp/classes/RCMETWizardTask.class.php
@@ -0,0 +1,125 @@
+<?php
+require_once(HOME . '/classes/WizardTask.class.php');
+
+class RCMETWizardTask extends WizardTask {
+	
+	public $modelFilePaths = array();
+	public $modelVars      = array();
+	public $modelBounds    = array();
+	
+	public $modelParameter = '';
+	public $observationalParameter = '';
+	public $observationalParameterId = '';
+	public $observationalDataset   = '';
+	public $observationalDatasetId = '';
+	
+	// Time Range
+	public $rangeStart;
+	public $rangeEnd;
+	
+	// Regrid
+	public $spatialRegridOption;
+	public $temporalRegridOption;
+	
+	// Options
+	public $computeAreaAverages;
+	
+	// Metrics
+	public $metric;
+	
+	// Plot Options	
+	
+	public function dictTemporalRegrid($key) {
+		
+		$dict = array(
+			"full" => "Time mean for full period",
+			"annual" => "Annual Means",
+			"monthly" => "Monthly Means",
+			"daily" => "Daily means (from sub-daily data)"	
+		);
+		return (isset($dict[$key]))
+			? $dict[$key]
+			: false;
+	}
+	
+	public function dictSpatialRegrid($key) {
+		
+		$dict = array(
+			"model" => "Use the model data grid",
+			"obs" => "Use the observational data grid",
+			"regular" => "Monthly Means"	
+		);
+		return (isset($dict[$key]))
+			? $dict[$key]
+			: false;
+	}
+	
+	public function dictMetrics($key) {
+		$dict = array(
+			"bias" => "Bias: mean bias across full time range",
+			"mae"  => "Mean Absolute Error: across full time range",
+			"difference" => "Difference: calculated at each time unit",
+			"acc"  => "Anomaly Correlation",
+			"patcor" => "Pattern Correlation",
+			"pdf" => "Probability Distribution Function similarity score",
+			"rms" => "RMS Error"	
+		);
+		return (isset($dict[$key]))
+			? $dict[$key]
+			: false;
+	}
+	
+	public function getTimeRange($observationalDatasetId) {
+		$dsTimes = array(
+			"1" => array('1989-01-01 00:00:00','2009-12-31 00:00:00'),	// ERA-Interim
+			"2" => array('2002-08-31 00:00:00','2010-01-01 00:00:00'),	// AIRS
+			"3" => array('1998-01-01 00:00:00','2010-01-01 00:00:00'),	// TRMM
+			"4" => array('1948-01-01 00:00:00','2010-01-01 00:00:00'),	// URD
+			"5" => array('2000-02-24 00:00:00','2010-05-30 00:00:00'),	// MODIS
+			"6" => array('1901-01-01 00:00:00','2006-12-01 00:00:00')); // CRU
+		 
+		if (isset($dsTimes[$observationalDatasetId]))
+			return $dsTimes[$observationalDatasetId];
+		else 
+			return false;
+	}
+	
+	public function computeOverlap($modelStart,$modelEnd,$obsStart,$obsEnd) {
+		$mstart = strtotime($modelStart);
+		$mend   = strtotime($modelEnd);
+		$ostart = strtotime($obsStart);
+		$oend   = strtotime($obsEnd);
+		
+		// The "later" of the two start times is the beginning of the overlap
+		$rangeStart = ($mstart > $ostart) ? $mstart : $ostart;
+		
+		// The "earlier" of the two end times is the end of the overlap
+		$rangeEnd   = ($mend < $oend) ? $mend : $oend;
+		
+		// Format the return values
+		return array(date('Y-m-d H:i:s',$rangeStart),
+					 date('Y-m-d H:i:s',$rangeEnd));
+	}
+	
+	
+	
+	public function __construct () {
+		
+		parent::__construct();
+		
+		$this->steps = array(
+			//     URL_NAME             HUMAN_READABLE
+			array("selectModelFiles",   "Select Model Files"),
+			array("selectLatLonVars",   "Select Latitude and Longitude Variables"),
+			array("selectTimeVars",     "Select Time Variable"),
+			array("selectModelVar",     "Select Model Variable"),
+			array("selectObservationalData", "Select Observational Data"),
+			array("selectTimeRange",    "Select Time Range for Calculation"),
+			array("selectRegrid",       "Select Regridding Options"),
+			array("selectOptionalTasks","Select Optional Calculation Tasks"),
+			array("selectMetricOptions","Select Metrics"),
+			array("selectPlotOptions",  "Select Plot Options"),
+			array("generatePlots",      "Generate Plots"),
+		);
+	}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/webapp/classes/WizardTask.class.php
----------------------------------------------------------------------
diff --git a/src/main/webapp/classes/WizardTask.class.php b/src/main/webapp/classes/WizardTask.class.php
new file mode 100755
index 0000000..8de173f
--- /dev/null
+++ b/src/main/webapp/classes/WizardTask.class.php
@@ -0,0 +1,55 @@
+<?php
+class WizardTask {
+	
+	public $currentStep = '';
+	public $steps = array();
+	
+	public function __construct() {}
+	
+	public function save() {
+		$_SESSION['wizardTask'] = serialize($this);
+	}
+	
+	public function setStep($which) {
+		$this->currentStep = $which;
+	}
+	
+	public function firstStep() {
+		$this->goToStep($this->steps[0][0]);
+	}
+	
+	public function nextStep() {
+		for($i=0;$i<count($this->steps);$i++) {
+			if (strtolower($this->steps[$i][0]) == strtolower($this->currentStep)) {
+				return (isset($this->steps[$i + 1]))
+					? $this->goToStep($this->steps[$i+1][0])
+					: false;
+			}
+		}
+	}
+	
+	public function previousStep($current) {
+		for($i=0;$i<count($this->steps);$i++) {
+			if (strtolower($this->steps[$i]) == strtolower($this->currentStep)) {
+				return (isset($this->steps[$i - 1]))
+					? $this->goToStep($this->steps[$i - 1][0])
+					: false;
+			}
+		}
+	}	
+	
+	protected function goToStep($step) {
+		$this->save();
+		header("Location: " . SITE_ROOT . "/wizard/step/" . $step);
+		exit();
+	}
+	
+	public function showPreviousNextLinks() {
+		for($i=1;$i<count($this->steps);$i++) {
+			if (strtolower($this->steps[$i][0]) == strtolower($this->currentStep)) { 
+				echo "<div class='box nav'>Back to <a href='".SITE_ROOT
+					."/wizard/step/{$this->steps[$i-1][0]}'>{$this->steps[$i-1][1]}</a></div>";
+			}
+		}
+	}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/webapp/config.ini
----------------------------------------------------------------------
diff --git a/src/main/webapp/config.ini b/src/main/webapp/config.ini
new file mode 100755
index 0000000..3d424c7
--- /dev/null
+++ b/src/main/webapp/config.ini
@@ -0,0 +1,66 @@
+; OODT Balance
+; Web Application Base Framework
+;
+; Application Configuration File. This file should be called 'config.ini' and 
+; should reside in the root directory of your site. This file follows standard
+; ini file conventions. Lines beginning with ';' are comments and are ignored.
+;
+
+[Application Environment]
+
+; site_root
+; If the site lives at the document root of the server, this will be '/'. On
+; the other hand, if the site lives in a sub-directory of the document root, 
+; this will be the full path (starting from the document root) to the root 
+; directory of the site. Always start with a slash (/) and always omit the
+; trailing slash. 
+;
+; examples: 
+;    (document root) http://domain.com/          (site_root: '/')
+;    (subdirectory)  http://domain.com/apps/site (site_root: '/apps/site')
+;
+; Note: The value for site_root should always match the value for 'RewriteBase'
+;       in the .htaccess file located in the site's root directory.
+;
+site_root = /
+
+
+[Application Content]
+
+; views_dir
+; This is the directory inside your site root where your application's views
+; reside. This should be a relative path (./). If you have set things up
+; according to the instructions, the framework will use the location of this 
+; file (config.ini) as the base.
+;
+; Note: The value provided is simply an example. It is up to you to provide
+;       valid paths.
+views_dir = ./views
+
+; header_file_path
+; This is the file that contains a site-wide header code/layout to be included
+; in each view. This should be a relative path (./). If you have set things up
+; according to the instructions, the framework will use the location of this 
+; file (config.ini) as the base.
+;
+; Note: The value provided is simply an example. It is up to you to provide
+;       valid paths.
+header_file_path = ./views/common/header.php
+
+; footer_file_path
+; This is the file that contains a site-wide footer code/layout to be included
+; in each view. This should be a relative path (./). If you have set things up
+; according to the instructions, the framework will use the location of this 
+; file (config.ini) as the base.
+;
+; Note: The value provided is simply an example. It is up to you to provide
+;       valid paths.
+footer_file_path = ./views/common/footer.php
+
+
+[RCMET_CONFIG]
+rcmet_working_directory = /path/to/working/directory
+rcmet_cache_directory   = /path/to/cache/directory
+rcmet_service_url_base  = http://host:port
+rcmet_service_use_curl  = false
+rcmed_query_api_url_base = http://rcmes.jpl.nasa.gov/query-api
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/webapp/hooks.php
----------------------------------------------------------------------
diff --git a/src/main/webapp/hooks.php b/src/main/webapp/hooks.php
new file mode 100755
index 0000000..769cfc0
--- /dev/null
+++ b/src/main/webapp/hooks.php
@@ -0,0 +1,83 @@
+<?php
+/**
+ * Copyright (c) 2010, California Institute of Technology.
+ * ALL RIGHTS RESERVED. U.S. Government sponsorship acknowledged.
+ * 
+ * $Id$
+ * 
+ * 
+ * OODT Balance
+ * Web Application Base Framework
+ */
+/**
+ * HOOKS.PHP
+ * 
+ * Hooks provide the ability, as the name implies, to hook into various parts of 
+ * the view rendering process and insert customizations. The contents of these 
+ * functions are run at the appropriate time *EVERY* time a view is rendered, i.e.
+ * the content of the hooks is not by default view-specific but rather will be 
+ * applied to all views. (However, there is nothing that prevents developers from 
+ * inserting conditional logic inside a hook that then causes view-specific
+ * them to exhibit view-specific behavior).
+ * 
+ * As an example, consider a hook that adds the amount of time Balance took to render
+ * the page as an inline HTML comment at the bottom of each page after it has been sent:
+ * 
+ * function hook_after_send() {
+ *     $timeStart = $GLOBALS['balance_request_start'];
+ *     $timeNow   = microtime(true);
+ *     $elapsed   = $timeNow - $timeStart;
+ *     echo "<!-- page rendered in {$elapsed} seconds -->";
+ * }
+ * 
+ * 
+ * Take a look at the docblock descriptions of each hook to get a sense of where
+ * in the view rendering process the hook is invoked.
+ * 
+ * @author ahart
+ */
+
+/**
+ * hook_before_header
+ * 
+ * This hook is executed before the contents of the header file are processed.
+ */
+function hook_before_header() {}
+
+/**
+ * hook_before_view
+ * 
+ * This hook is executed before the contents of the main view are processed.
+ */
+function hook_before_view() {}
+
+/**
+ * hook_before_footer
+ * 
+ * This hook is executed before the contents of the footer are processed
+ */
+function hook_before_footer() {}
+
+/**
+ * hook_before_send
+ * 
+ * This hook is after all of the view components (header, view, footer) have been
+ * processed but before the processed results are sent out across the wire to the 
+ * browser. HTTP headers have not yet been sent to the browser.
+ */
+function hook_before_send() {}
+
+/**
+ * hook_after_send
+ * 
+ * This hook is after all of the view components (header, view, footer) have been
+ * processed and sent out across the wire to the browser. It can be used for logging
+ * or analytics purposes, or to append a common trailer to all content.
+ */
+function hook_after_send() {
+	$timeStart = $GLOBALS['balance_request_start'];
+	$timeEnd   = microtime(true);
+	$elapsed   = $timeEnd - $timeStart;
+	
+	echo "\r\n<!-- page rendered in {$elapsed} seconds -->";
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/webapp/index.php
----------------------------------------------------------------------
diff --git a/src/main/webapp/index.php b/src/main/webapp/index.php
new file mode 100755
index 0000000..e02633d
--- /dev/null
+++ b/src/main/webapp/index.php
@@ -0,0 +1,48 @@
+<?php
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * OODT Balance
+ * Web Application Base Framework
+ *
+ * Front-controller
+ * This file handles the marshalling of requests to the appropriate
+ * application view.
+ *
+ */
+define ("DEBUG", true); // Change this to `false` when no longer debugging
+
+// Application root directory path (should never need to change this)
+define ("HOME",  dirname(__FILE__));
+
+/* Set up application environment ***************************************/
+require_once("Org/Apache/Oodt/Balance/Boot/bootstrap.php");
+
+/* Initialize the application with the settings from config.ini *********/
+$app = $GLOBALS['app'] = App::Create(parse_ini_file(HOME . '/config.ini'));
+
+/* Initialize any globally required modules here ************************/
+// Example:
+// To load a module 'foo', located at ./modules/foo, on every request:
+// App::Get()->loadModule('foo');
+
+/* Generate and send a response to the browser **************************/
+$response = $app->getResponse()->send();
+
+/* Clean up after ourselves *********************************************/
+$app->cleanup();

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/webapp/modules/.svn/all-wcprops
----------------------------------------------------------------------
diff --git a/src/main/webapp/modules/.svn/all-wcprops b/src/main/webapp/modules/.svn/all-wcprops
new file mode 100755
index 0000000..eef8ad5
--- /dev/null
+++ b/src/main/webapp/modules/.svn/all-wcprops
@@ -0,0 +1,5 @@
+K 25
+svn:wc:ra_dav:version-url
+V 81
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/webapp/modules
+END

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/webapp/modules/.svn/entries
----------------------------------------------------------------------
diff --git a/src/main/webapp/modules/.svn/entries b/src/main/webapp/modules/.svn/entries
new file mode 100755
index 0000000..ebc01cf
--- /dev/null
+++ b/src/main/webapp/modules/.svn/entries
@@ -0,0 +1,28 @@
+10
+
+dir
+1485921
+https://svn.apache.org/repos/asf/incubator/climate/trunk/rcmet/src/main/webapp/modules
+https://svn.apache.org/repos/asf
+
+
+
+2011-12-13T03:57:45.293099Z
+1471825
+mattmann
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+13f79535-47bb-0310-9956-ffa450edef68
+

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/webapp/scripts/.svn/all-wcprops
----------------------------------------------------------------------
diff --git a/src/main/webapp/scripts/.svn/all-wcprops b/src/main/webapp/scripts/.svn/all-wcprops
new file mode 100755
index 0000000..b39f422
--- /dev/null
+++ b/src/main/webapp/scripts/.svn/all-wcprops
@@ -0,0 +1,29 @@
+K 25
+svn:wc:ra_dav:version-url
+V 81
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/webapp/scripts
+END
+plotView.php
+K 25
+svn:wc:ra_dav:version-url
+V 94
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/webapp/scripts/plotView.php
+END
+dirlist.php
+K 25
+svn:wc:ra_dav:version-url
+V 93
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/webapp/scripts/dirlist.php
+END
+rcmed.php
+K 25
+svn:wc:ra_dav:version-url
+V 91
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/webapp/scripts/rcmed.php
+END
+plots.php
+K 25
+svn:wc:ra_dav:version-url
+V 91
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/webapp/scripts/plots.php
+END

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/webapp/scripts/.svn/entries
----------------------------------------------------------------------
diff --git a/src/main/webapp/scripts/.svn/entries b/src/main/webapp/scripts/.svn/entries
new file mode 100755
index 0000000..b0bd000
--- /dev/null
+++ b/src/main/webapp/scripts/.svn/entries
@@ -0,0 +1,167 @@
+10
+
+dir
+1485921
+https://svn.apache.org/repos/asf/incubator/climate/trunk/rcmet/src/main/webapp/scripts
+https://svn.apache.org/repos/asf
+
+
+
+2012-11-20T16:20:28.221964Z
+1474523
+ahart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+13f79535-47bb-0310-9956-ffa450edef68
+
+plotView.php
+file
+
+
+
+
+2013-05-24T10:13:58.000000Z
+10b10c5774246a1fec683bdf04c45875
+2011-12-13T03:57:45.293099Z
+1471825
+mattmann
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+209
+
+dirlist.php
+file
+
+
+
+
+2013-05-24T10:13:58.000000Z
+400da9d2b4ea5af6d48779babc88caf0
+2011-12-13T03:57:45.293099Z
+1471825
+mattmann
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+722
+
+rcmed.php
+file
+
+
+
+
+2013-05-24T10:13:58.000000Z
+340f58e12a77b484c101df7b3008fc8d
+2011-12-13T03:57:45.293099Z
+1471825
+mattmann
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+531
+
+widgets
+dir
+
+plots.php
+file
+
+
+
+
+2013-05-24T10:13:58.000000Z
+e53fb128a3081ee148cb5f02dbad9c43
+2012-11-20T16:20:28.221964Z
+1474523
+ahart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+900
+

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/webapp/scripts/.svn/text-base/dirlist.php.svn-base
----------------------------------------------------------------------
diff --git a/src/main/webapp/scripts/.svn/text-base/dirlist.php.svn-base b/src/main/webapp/scripts/.svn/text-base/dirlist.php.svn-base
new file mode 100755
index 0000000..7d8ee39
--- /dev/null
+++ b/src/main/webapp/scripts/.svn/text-base/dirlist.php.svn-base
@@ -0,0 +1,25 @@
+<?php
+if (file_exists($_GET['path'])) {
+	echo json_encode(getDirectoryList($_GET['path']));
+} else {
+	echo json_encode(array());
+}
+
+function getDirectoryList ($directory) {
+    // create an array to hold directory list
+    $results = array();
+    // create a handler for the directory
+    $handler = opendir($directory);
+    // open directory and walk through the filenames
+    while ($file = readdir($handler)) {
+      // if file isn't this directory or its parent, add it to the results
+      if ($file[0] != '.') {
+        $results[] = is_dir($directory . '/' . $file) ? "{$file}/" : $file;
+      }
+    }
+    // tidy up: close the handler
+    closedir($handler);
+    // done!
+    sort($results);
+    return $results;
+}

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/webapp/scripts/.svn/text-base/plotView.php.svn-base
----------------------------------------------------------------------
diff --git a/src/main/webapp/scripts/.svn/text-base/plotView.php.svn-base b/src/main/webapp/scripts/.svn/text-base/plotView.php.svn-base
new file mode 100755
index 0000000..e7d6f34
--- /dev/null
+++ b/src/main/webapp/scripts/.svn/text-base/plotView.php.svn-base
@@ -0,0 +1,13 @@
+<?php
+/**
+ * Serve a .png from the specified path
+ */
+if (isset($_REQUEST['path'])) {
+	
+	$im = imagecreatefrompng($_REQUEST['path']);
+
+	header('Content-type: image/png');
+
+	imagepng($im);
+	imagedestroy($im);
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/webapp/scripts/.svn/text-base/plots.php.svn-base
----------------------------------------------------------------------
diff --git a/src/main/webapp/scripts/.svn/text-base/plots.php.svn-base b/src/main/webapp/scripts/.svn/text-base/plots.php.svn-base
new file mode 100755
index 0000000..e581e91
--- /dev/null
+++ b/src/main/webapp/scripts/.svn/text-base/plots.php.svn-base
@@ -0,0 +1,35 @@
+<?php
+
+switch (strtoupper($_REQUEST['action'])) {
+	
+	case "GENERATE":
+		$url        = App::Get()->settings['rcmet_service_url_base'] . '/rcmes/run/';
+		$postFields = http_build_query($_REQUEST);
+		
+		if (isset(App::Get()->settings['rcmet_service_use_curl']) 
+		   && App::Get()->settings['rcmet_service_use_curl'] == true) {
+		   $ch = curl_init();
+		   curl_setopt($ch,CURLOPT_URL,$url);
+		   curl_setopt($ch,CURLOPT_POST, 1);
+		   curl_setopt($ch,CURLOPT_POSTFIELDS,$postFields);
+		   curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);
+		   $response = curl_exec($ch);
+		   curl_close($ch);
+		} else {
+		  $params = array('http' => array(
+		     'method' => 'POST',
+		     'content' => $postFields));
+		  $ctx = stream_context_create($params);
+		  $fp = @fopen($url, 'rb', false, $ctx);
+		  $response = @stream_get_contents($fp);
+		}
+
+		echo $response;
+		break;
+	default:
+		echo "{}";
+		break;
+	
+}
+
+exit();
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/webapp/scripts/.svn/text-base/rcmed.php.svn-base
----------------------------------------------------------------------
diff --git a/src/main/webapp/scripts/.svn/text-base/rcmed.php.svn-base b/src/main/webapp/scripts/.svn/text-base/rcmed.php.svn-base
new file mode 100755
index 0000000..e081a8e
--- /dev/null
+++ b/src/main/webapp/scripts/.svn/text-base/rcmed.php.svn-base
@@ -0,0 +1,23 @@
+<?php
+
+/***
+ * Fetch various information from the RCMED query API. Serves as a workaround
+ * for cross-domain ajax calls.
+ */
+$action = $_REQUEST['action'];
+
+switch (strtoupper($action)) {
+	case "DATASETS":
+		echo file_get_contents(
+			App::Get()->settings['rcmed_query_api_url_base'] . "/datasets.php");
+		break;	
+	case "PARAMETERS":
+		$dataset = $_REQUEST['dataset'];
+		echo file_get_contents(
+			App::Get()->settings['rcmed_query_api_url_base'] . '/parameters.php?dataset=' . $dataset);
+		break;
+	default:
+		echo "{}";	
+}
+
+exit;
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/webapp/scripts/dirlist.php
----------------------------------------------------------------------
diff --git a/src/main/webapp/scripts/dirlist.php b/src/main/webapp/scripts/dirlist.php
new file mode 100755
index 0000000..7d8ee39
--- /dev/null
+++ b/src/main/webapp/scripts/dirlist.php
@@ -0,0 +1,25 @@
+<?php
+if (file_exists($_GET['path'])) {
+	echo json_encode(getDirectoryList($_GET['path']));
+} else {
+	echo json_encode(array());
+}
+
+function getDirectoryList ($directory) {
+    // create an array to hold directory list
+    $results = array();
+    // create a handler for the directory
+    $handler = opendir($directory);
+    // open directory and walk through the filenames
+    while ($file = readdir($handler)) {
+      // if file isn't this directory or its parent, add it to the results
+      if ($file[0] != '.') {
+        $results[] = is_dir($directory . '/' . $file) ? "{$file}/" : $file;
+      }
+    }
+    // tidy up: close the handler
+    closedir($handler);
+    // done!
+    sort($results);
+    return $results;
+}

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/webapp/scripts/plotView.php
----------------------------------------------------------------------
diff --git a/src/main/webapp/scripts/plotView.php b/src/main/webapp/scripts/plotView.php
new file mode 100755
index 0000000..e7d6f34
--- /dev/null
+++ b/src/main/webapp/scripts/plotView.php
@@ -0,0 +1,13 @@
+<?php
+/**
+ * Serve a .png from the specified path
+ */
+if (isset($_REQUEST['path'])) {
+	
+	$im = imagecreatefrompng($_REQUEST['path']);
+
+	header('Content-type: image/png');
+
+	imagepng($im);
+	imagedestroy($im);
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/webapp/scripts/plots.php
----------------------------------------------------------------------
diff --git a/src/main/webapp/scripts/plots.php b/src/main/webapp/scripts/plots.php
new file mode 100755
index 0000000..e581e91
--- /dev/null
+++ b/src/main/webapp/scripts/plots.php
@@ -0,0 +1,35 @@
+<?php
+
+switch (strtoupper($_REQUEST['action'])) {
+	
+	case "GENERATE":
+		$url        = App::Get()->settings['rcmet_service_url_base'] . '/rcmes/run/';
+		$postFields = http_build_query($_REQUEST);
+		
+		if (isset(App::Get()->settings['rcmet_service_use_curl']) 
+		   && App::Get()->settings['rcmet_service_use_curl'] == true) {
+		   $ch = curl_init();
+		   curl_setopt($ch,CURLOPT_URL,$url);
+		   curl_setopt($ch,CURLOPT_POST, 1);
+		   curl_setopt($ch,CURLOPT_POSTFIELDS,$postFields);
+		   curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);
+		   $response = curl_exec($ch);
+		   curl_close($ch);
+		} else {
+		  $params = array('http' => array(
+		     'method' => 'POST',
+		     'content' => $postFields));
+		  $ctx = stream_context_create($params);
+		  $fp = @fopen($url, 'rb', false, $ctx);
+		  $response = @stream_get_contents($fp);
+		}
+
+		echo $response;
+		break;
+	default:
+		echo "{}";
+		break;
+	
+}
+
+exit();
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/webapp/scripts/rcmed.php
----------------------------------------------------------------------
diff --git a/src/main/webapp/scripts/rcmed.php b/src/main/webapp/scripts/rcmed.php
new file mode 100755
index 0000000..e081a8e
--- /dev/null
+++ b/src/main/webapp/scripts/rcmed.php
@@ -0,0 +1,23 @@
+<?php
+
+/***
+ * Fetch various information from the RCMED query API. Serves as a workaround
+ * for cross-domain ajax calls.
+ */
+$action = $_REQUEST['action'];
+
+switch (strtoupper($action)) {
+	case "DATASETS":
+		echo file_get_contents(
+			App::Get()->settings['rcmed_query_api_url_base'] . "/datasets.php");
+		break;	
+	case "PARAMETERS":
+		$dataset = $_REQUEST['dataset'];
+		echo file_get_contents(
+			App::Get()->settings['rcmed_query_api_url_base'] . '/parameters.php?dataset=' . $dataset);
+		break;
+	default:
+		echo "{}";	
+}
+
+exit;
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/webapp/scripts/widgets/.svn/all-wcprops
----------------------------------------------------------------------
diff --git a/src/main/webapp/scripts/widgets/.svn/all-wcprops b/src/main/webapp/scripts/widgets/.svn/all-wcprops
new file mode 100755
index 0000000..72a0cc9
--- /dev/null
+++ b/src/main/webapp/scripts/widgets/.svn/all-wcprops
@@ -0,0 +1,5 @@
+K 25
+svn:wc:ra_dav:version-url
+V 89
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/webapp/scripts/widgets
+END

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/webapp/scripts/widgets/.svn/entries
----------------------------------------------------------------------
diff --git a/src/main/webapp/scripts/widgets/.svn/entries b/src/main/webapp/scripts/widgets/.svn/entries
new file mode 100755
index 0000000..0753653
--- /dev/null
+++ b/src/main/webapp/scripts/widgets/.svn/entries
@@ -0,0 +1,28 @@
+10
+
+dir
+1485921
+https://svn.apache.org/repos/asf/incubator/climate/trunk/rcmet/src/main/webapp/scripts/widgets
+https://svn.apache.org/repos/asf
+
+
+
+2011-12-13T03:57:45.293099Z
+1471825
+mattmann
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+13f79535-47bb-0310-9956-ffa450edef68
+

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/webapp/static/.svn/all-wcprops
----------------------------------------------------------------------
diff --git a/src/main/webapp/static/.svn/all-wcprops b/src/main/webapp/static/.svn/all-wcprops
new file mode 100755
index 0000000..47eb07f
--- /dev/null
+++ b/src/main/webapp/static/.svn/all-wcprops
@@ -0,0 +1,5 @@
+K 25
+svn:wc:ra_dav:version-url
+V 80
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/webapp/static
+END

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/webapp/static/.svn/entries
----------------------------------------------------------------------
diff --git a/src/main/webapp/static/.svn/entries b/src/main/webapp/static/.svn/entries
new file mode 100755
index 0000000..24a8ce7
--- /dev/null
+++ b/src/main/webapp/static/.svn/entries
@@ -0,0 +1,40 @@
+10
+
+dir
+1485921
+https://svn.apache.org/repos/asf/incubator/climate/trunk/rcmet/src/main/webapp/static
+https://svn.apache.org/repos/asf
+
+
+
+2012-08-30T21:06:35.842635Z
+1473975
+ahart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+13f79535-47bb-0310-9956-ffa450edef68
+
+css
+dir
+
+img
+dir
+
+js
+dir
+
+bootstrap
+dir
+

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/webapp/static/bootstrap/.svn/all-wcprops
----------------------------------------------------------------------
diff --git a/src/main/webapp/static/bootstrap/.svn/all-wcprops b/src/main/webapp/static/bootstrap/.svn/all-wcprops
new file mode 100755
index 0000000..a241075
--- /dev/null
+++ b/src/main/webapp/static/bootstrap/.svn/all-wcprops
@@ -0,0 +1,5 @@
+K 25
+svn:wc:ra_dav:version-url
+V 90
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/webapp/static/bootstrap
+END

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/webapp/static/bootstrap/.svn/entries
----------------------------------------------------------------------
diff --git a/src/main/webapp/static/bootstrap/.svn/entries b/src/main/webapp/static/bootstrap/.svn/entries
new file mode 100755
index 0000000..ac37539
--- /dev/null
+++ b/src/main/webapp/static/bootstrap/.svn/entries
@@ -0,0 +1,37 @@
+10
+
+dir
+1485921
+https://svn.apache.org/repos/asf/incubator/climate/trunk/rcmet/src/main/webapp/static/bootstrap
+https://svn.apache.org/repos/asf
+
+
+
+2012-08-30T16:45:04.524228Z
+1473968
+ahart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+13f79535-47bb-0310-9956-ffa450edef68
+
+css
+dir
+
+img
+dir
+
+js
+dir
+

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/webapp/static/bootstrap/css/.svn/all-wcprops
----------------------------------------------------------------------
diff --git a/src/main/webapp/static/bootstrap/css/.svn/all-wcprops b/src/main/webapp/static/bootstrap/css/.svn/all-wcprops
new file mode 100755
index 0000000..eaca17e
--- /dev/null
+++ b/src/main/webapp/static/bootstrap/css/.svn/all-wcprops
@@ -0,0 +1,29 @@
+K 25
+svn:wc:ra_dav:version-url
+V 94
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/webapp/static/bootstrap/css
+END
+bootstrap-responsive.css
+K 25
+svn:wc:ra_dav:version-url
+V 119
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/webapp/static/bootstrap/css/bootstrap-responsive.css
+END
+bootstrap-responsive.min.css
+K 25
+svn:wc:ra_dav:version-url
+V 123
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/webapp/static/bootstrap/css/bootstrap-responsive.min.css
+END
+bootstrap.css
+K 25
+svn:wc:ra_dav:version-url
+V 108
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/webapp/static/bootstrap/css/bootstrap.css
+END
+bootstrap.min.css
+K 25
+svn:wc:ra_dav:version-url
+V 112
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/webapp/static/bootstrap/css/bootstrap.min.css
+END

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/webapp/static/bootstrap/css/.svn/entries
----------------------------------------------------------------------
diff --git a/src/main/webapp/static/bootstrap/css/.svn/entries b/src/main/webapp/static/bootstrap/css/.svn/entries
new file mode 100755
index 0000000..53cfe24
--- /dev/null
+++ b/src/main/webapp/static/bootstrap/css/.svn/entries
@@ -0,0 +1,164 @@
+10
+
+dir
+1485921
+https://svn.apache.org/repos/asf/incubator/climate/trunk/rcmet/src/main/webapp/static/bootstrap/css
+https://svn.apache.org/repos/asf
+
+
+
+2012-08-30T16:45:04.524228Z
+1473968
+ahart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+13f79535-47bb-0310-9956-ffa450edef68
+
+bootstrap-responsive.css
+file
+
+
+
+
+2013-05-24T10:13:59.000000Z
+034fa29d420e7a5de345fa9743a6e0dc
+2012-08-30T16:45:04.524228Z
+1473968
+ahart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+20470
+
+bootstrap-responsive.min.css
+file
+
+
+
+
+2013-05-24T10:13:59.000000Z
+7a18012520a1ea95142a19602c7e7d5b
+2012-08-30T16:45:04.524228Z
+1473968
+ahart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+15545
+
+bootstrap.css
+file
+
+
+
+
+2013-05-24T10:13:59.000000Z
+0b9b6b1fd516e87b4089aaa3d0e5960b
+2012-08-30T16:45:04.524228Z
+1473968
+ahart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+115072
+
+bootstrap.min.css
+file
+
+
+
+
+2013-05-24T10:13:59.000000Z
+db98b4ff646c20c142172eb838d2fe9b
+2012-08-30T16:45:04.524228Z
+1473968
+ahart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+95583
+

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/webapp/static/bootstrap/css/.svn/text-base/bootstrap-responsive.css.svn-base
----------------------------------------------------------------------
diff --git a/src/main/webapp/static/bootstrap/css/.svn/text-base/bootstrap-responsive.css.svn-base b/src/main/webapp/static/bootstrap/css/.svn/text-base/bootstrap-responsive.css.svn-base
new file mode 100755
index 0000000..daafa91
--- /dev/null
+++ b/src/main/webapp/static/bootstrap/css/.svn/text-base/bootstrap-responsive.css.svn-base
@@ -0,0 +1,1040 @@
+/*!
+ * Bootstrap Responsive v2.1.0
+ *
+ * Copyright 2012 Twitter, Inc
+ * Licensed under the Apache License v2.0
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Designed and built with all the love in the world @twitter by @mdo and @fat.
+ */
+
+.clearfix {
+  *zoom: 1;
+}
+
+.clearfix:before,
+.clearfix:after {
+  display: table;
+  line-height: 0;
+  content: "";
+}
+
+.clearfix:after {
+  clear: both;
+}
+
+.hide-text {
+  font: 0/0 a;
+  color: transparent;
+  text-shadow: none;
+  background-color: transparent;
+  border: 0;
+}
+
+.input-block-level {
+  display: block;
+  width: 100%;
+  min-height: 30px;
+  -webkit-box-sizing: border-box;
+     -moz-box-sizing: border-box;
+          box-sizing: border-box;
+}
+
+.hidden {
+  display: none;
+  visibility: hidden;
+}
+
+.visible-phone {
+  display: none !important;
+}
+
+.visible-tablet {
+  display: none !important;
+}
+
+.hidden-desktop {
+  display: none !important;
+}
+
+.visible-desktop {
+  display: inherit !important;
+}
+
+@media (min-width: 768px) and (max-width: 979px) {
+  .hidden-desktop {
+    display: inherit !important;
+  }
+  .visible-desktop {
+    display: none !important ;
+  }
+  .visible-tablet {
+    display: inherit !important;
+  }
+  .hidden-tablet {
+    display: none !important;
+  }
+}
+
+@media (max-width: 767px) {
+  .hidden-desktop {
+    display: inherit !important;
+  }
+  .visible-desktop {
+    display: none !important;
+  }
+  .visible-phone {
+    display: inherit !important;
+  }
+  .hidden-phone {
+    display: none !important;
+  }
+}
+
+@media (min-width: 1200px) {
+  .row {
+    margin-left: -30px;
+    *zoom: 1;
+  }
+  .row:before,
+  .row:after {
+    display: table;
+    line-height: 0;
+    content: "";
+  }
+  .row:after {
+    clear: both;
+  }
+  [class*="span"] {
+    float: left;
+    margin-left: 30px;
+  }
+  .container,
+  .navbar-static-top .container,
+  .navbar-fixed-top .container,
+  .navbar-fixed-bottom .container {
+    width: 1170px;
+  }
+  .span12 {
+    width: 1170px;
+  }
+  .span11 {
+    width: 1070px;
+  }
+  .span10 {
+    width: 970px;
+  }
+  .span9 {
+    width: 870px;
+  }
+  .span8 {
+    width: 770px;
+  }
+  .span7 {
+    width: 670px;
+  }
+  .span6 {
+    width: 570px;
+  }
+  .span5 {
+    width: 470px;
+  }
+  .span4 {
+    width: 370px;
+  }
+  .span3 {
+    width: 270px;
+  }
+  .span2 {
+    width: 170px;
+  }
+  .span1 {
+    width: 70px;
+  }
+  .offset12 {
+    margin-left: 1230px;
+  }
+  .offset11 {
+    margin-left: 1130px;
+  }
+  .offset10 {
+    margin-left: 1030px;
+  }
+  .offset9 {
+    margin-left: 930px;
+  }
+  .offset8 {
+    margin-left: 830px;
+  }
+  .offset7 {
+    margin-left: 730px;
+  }
+  .offset6 {
+    margin-left: 630px;
+  }
+  .offset5 {
+    margin-left: 530px;
+  }
+  .offset4 {
+    margin-left: 430px;
+  }
+  .offset3 {
+    margin-left: 330px;
+  }
+  .offset2 {
+    margin-left: 230px;
+  }
+  .offset1 {
+    margin-left: 130px;
+  }
+  .row-fluid {
+    width: 100%;
+    *zoom: 1;
+  }
+  .row-fluid:before,
+  .row-fluid:after {
+    display: table;
+    line-height: 0;
+    content: "";
+  }
+  .row-fluid:after {
+    clear: both;
+  }
+  .row-fluid [class*="span"] {
+    display: block;
+    float: left;
+    width: 100%;
+    min-height: 30px;
+    margin-left: 2.564102564102564%;
+    *margin-left: 2.5109110747408616%;
+    -webkit-box-sizing: border-box;
+       -moz-box-sizing: border-box;
+            box-sizing: border-box;
+  }
+  .row-fluid [class*="span"]:first-child {
+    margin-left: 0;
+  }
+  .row-fluid .span12 {
+    width: 100%;
+    *width: 99.94680851063829%;
+  }
+  .row-fluid .span11 {
+    width: 91.45299145299145%;
+    *width: 91.39979996362975%;
+  }
+  .row-fluid .span10 {
+    width: 82.90598290598291%;
+    *width: 82.8527914166212%;
+  }
+  .row-fluid .span9 {
+    width: 74.35897435897436%;
+    *width: 74.30578286961266%;
+  }
+  .row-fluid .span8 {
+    width: 65.81196581196582%;
+    *width: 65.75877432260411%;
+  }
+  .row-fluid .span7 {
+    width: 57.26495726495726%;
+    *width: 57.21176577559556%;
+  }
+  .row-fluid .span6 {
+    width: 48.717948717948715%;
+    *width: 48.664757228587014%;
+  }
+  .row-fluid .span5 {
+    width: 40.17094017094017%;
+    *width: 40.11774868157847%;
+  }
+  .row-fluid .span4 {
+    width: 31.623931623931625%;
+    *width: 31.570740134569924%;
+  }
+  .row-fluid .span3 {
+    width: 23.076923076923077%;
+    *width: 23.023731587561375%;
+  }
+  .row-fluid .span2 {
+    width: 14.52991452991453%;
+    *width: 14.476723040552828%;
+  }
+  .row-fluid .span1 {
+    width: 5.982905982905983%;
+    *width: 5.929714493544281%;
+  }
+  .row-fluid .offset12 {
+    margin-left: 105.12820512820512%;
+    *margin-left: 105.02182214948171%;
+  }
+  .row-fluid .offset12:first-child {
+    margin-left: 102.56410256410257%;
+    *margin-left: 102.45771958537915%;
+  }
+  .row-fluid .offset11 {
+    margin-left: 96.58119658119658%;
+    *margin-left: 96.47481360247316%;
+  }
+  .row-fluid .offset11:first-child {
+    margin-left: 94.01709401709402%;
+    *margin-left: 93.91071103837061%;
+  }
+  .row-fluid .offset10 {
+    margin-left: 88.03418803418803%;
+    *margin-left: 87.92780505546462%;
+  }
+  .row-fluid .offset10:first-child {
+    margin-left: 85.47008547008548%;
+    *margin-left: 85.36370249136206%;
+  }
+  .row-fluid .offset9 {
+    margin-left: 79.48717948717949%;
+    *margin-left: 79.38079650845607%;
+  }
+  .row-fluid .offset9:first-child {
+    margin-left: 76.92307692307693%;
+    *margin-left: 76.81669394435352%;
+  }
+  .row-fluid .offset8 {
+    margin-left: 70.94017094017094%;
+    *margin-left: 70.83378796144753%;
+  }
+  .row-fluid .offset8:first-child {
+    margin-left: 68.37606837606839%;
+    *margin-left: 68.26968539734497%;
+  }
+  .row-fluid .offset7 {
+    margin-left: 62.393162393162385%;
+    *margin-left: 62.28677941443899%;
+  }
+  .row-fluid .offset7:first-child {
+    margin-left: 59.82905982905982%;
+    *margin-left: 59.72267685033642%;
+  }
+  .row-fluid .offset6 {
+    margin-left: 53.84615384615384%;
+    *margin-left: 53.739770867430444%;
+  }
+  .row-fluid .offset6:first-child {
+    margin-left: 51.28205128205128%;
+    *margin-left: 51.175668303327875%;
+  }
+  .row-fluid .offset5 {
+    margin-left: 45.299145299145295%;
+    *margin-left: 45.1927623204219%;
+  }
+  .row-fluid .offset5:first-child {
+    margin-left: 42.73504273504273%;
+    *margin-left: 42.62865975631933%;
+  }
+  .row-fluid .offset4 {
+    margin-left: 36.75213675213675%;
+    *margin-left: 36.645753773413354%;
+  }
+  .row-fluid .offset4:first-child {
+    margin-left: 34.18803418803419%;
+    *margin-left: 34.081651209310785%;
+  }
+  .row-fluid .offset3 {
+    margin-left: 28.205128205128204%;
+    *margin-left: 28.0987452264048%;
+  }
+  .row-fluid .offset3:first-child {
+    margin-left: 25.641025641025642%;
+    *margin-left: 25.53464266230224%;
+  }
+  .row-fluid .offset2 {
+    margin-left: 19.65811965811966%;
+    *margin-left: 19.551736679396257%;
+  }
+  .row-fluid .offset2:first-child {
+    margin-left: 17.094017094017094%;
+    *margin-left: 16.98763411529369%;
+  }
+  .row-fluid .offset1 {
+    margin-left: 11.11111111111111%;
+    *margin-left: 11.004728132387708%;
+  }
+  .row-fluid .offset1:first-child {
+    margin-left: 8.547008547008547%;
+    *margin-left: 8.440625568285142%;
+  }
+  input,
+  textarea,
+  .uneditable-input {
+    margin-left: 0;
+  }
+  .controls-row [class*="span"] + [class*="span"] {
+    margin-left: 30px;
+  }
+  input.span12,
+  textarea.span12,
+  .uneditable-input.span12 {
+    width: 1156px;
+  }
+  input.span11,
+  textarea.span11,
+  .uneditable-input.span11 {
+    width: 1056px;
+  }
+  input.span10,
+  textarea.span10,
+  .uneditable-input.span10 {
+    width: 956px;
+  }
+  input.span9,
+  textarea.span9,
+  .uneditable-input.span9 {
+    width: 856px;
+  }
+  input.span8,
+  textarea.span8,
+  .uneditable-input.span8 {
+    width: 756px;
+  }
+  input.span7,
+  textarea.span7,
+  .uneditable-input.span7 {
+    width: 656px;
+  }
+  input.span6,
+  textarea.span6,
+  .uneditable-input.span6 {
+    width: 556px;
+  }
+  input.span5,
+  textarea.span5,
+  .uneditable-input.span5 {
+    width: 456px;
+  }
+  input.span4,
+  textarea.span4,
+  .uneditable-input.span4 {
+    width: 356px;
+  }
+  input.span3,
+  textarea.span3,
+  .uneditable-input.span3 {
+    width: 256px;
+  }
+  input.span2,
+  textarea.span2,
+  .uneditable-input.span2 {
+    width: 156px;
+  }
+  input.span1,
+  textarea.span1,
+  .uneditable-input.span1 {
+    width: 56px;
+  }
+  .thumbnails {
+    margin-left: -30px;
+  }
+  .thumbnails > li {
+    margin-left: 30px;
+  }
+  .row-fluid .thumbnails {
+    margin-left: 0;
+  }
+}
+
+@media (min-width: 768px) and (max-width: 979px) {
+  .row {
+    margin-left: -20px;
+    *zoom: 1;
+  }
+  .row:before,
+  .row:after {
+    display: table;
+    line-height: 0;
+    content: "";
+  }
+  .row:after {
+    clear: both;
+  }
+  [class*="span"] {
+    float: left;
+    margin-left: 20px;
+  }
+  .container,
+  .navbar-static-top .container,
+  .navbar-fixed-top .container,
+  .navbar-fixed-bottom .container {
+    width: 724px;
+  }
+  .span12 {
+    width: 724px;
+  }
+  .span11 {
+    width: 662px;
+  }
+  .span10 {
+    width: 600px;
+  }
+  .span9 {
+    width: 538px;
+  }
+  .span8 {
+    width: 476px;
+  }
+  .span7 {
+    width: 414px;
+  }
+  .span6 {
+    width: 352px;
+  }
+  .span5 {
+    width: 290px;
+  }
+  .span4 {
+    width: 228px;
+  }
+  .span3 {
+    width: 166px;
+  }
+  .span2 {
+    width: 104px;
+  }
+  .span1 {
+    width: 42px;
+  }
+  .offset12 {
+    margin-left: 764px;
+  }
+  .offset11 {
+    margin-left: 702px;
+  }
+  .offset10 {
+    margin-left: 640px;
+  }
+  .offset9 {
+    margin-left: 578px;
+  }
+  .offset8 {
+    margin-left: 516px;
+  }
+  .offset7 {
+    margin-left: 454px;
+  }
+  .offset6 {
+    margin-left: 392px;
+  }
+  .offset5 {
+    margin-left: 330px;
+  }
+  .offset4 {
+    margin-left: 268px;
+  }
+  .offset3 {
+    margin-left: 206px;
+  }
+  .offset2 {
+    margin-left: 144px;
+  }
+  .offset1 {
+    margin-left: 82px;
+  }
+  .row-fluid {
+    width: 100%;
+    *zoom: 1;
+  }
+  .row-fluid:before,
+  .row-fluid:after {
+    display: table;
+    line-height: 0;
+    content: "";
+  }
+  .row-fluid:after {
+    clear: both;
+  }
+  .row-fluid [class*="span"] {
+    display: block;
+    float: left;
+    width: 100%;
+    min-height: 30px;
+    margin-left: 2.7624309392265194%;
+    *margin-left: 2.709239449864817%;
+    -webkit-box-sizing: border-box;
+       -moz-box-sizing: border-box;
+            box-sizing: border-box;
+  }
+  .row-fluid [class*="span"]:first-child {
+    margin-left: 0;
+  }
+  .row-fluid .span12 {
+    width: 100%;
+    *width: 99.94680851063829%;
+  }
+  .row-fluid .span11 {
+    width: 91.43646408839778%;
+    *width: 91.38327259903608%;
+  }
+  .row-fluid .span10 {
+    width: 82.87292817679558%;
+    *width: 82.81973668743387%;
+  }
+  .row-fluid .span9 {
+    width: 74.30939226519337%;
+    *width: 74.25620077583166%;
+  }
+  .row-fluid .span8 {
+    width: 65.74585635359117%;
+    *width: 65.69266486422946%;
+  }
+  .row-fluid .span7 {
+    width: 57.18232044198895%;
+    *width: 57.12912895262725%;
+  }
+  .row-fluid .span6 {
+    width: 48.61878453038674%;
+    *width: 48.56559304102504%;
+  }
+  .row-fluid .span5 {
+    width: 40.05524861878453%;
+    *width: 40.00205712942283%;
+  }
+  .row-fluid .span4 {
+    width: 31.491712707182323%;
+    *width: 31.43852121782062%;
+  }
+  .row-fluid .span3 {
+    width: 22.92817679558011%;
+    *width: 22.87498530621841%;
+  }
+  .row-fluid .span2 {
+    width: 14.3646408839779%;
+    *width: 14.311449394616199%;
+  }
+  .row-fluid .span1 {
+    width: 5.801104972375691%;
+    *width: 5.747913483013988%;
+  }
+  .row-fluid .offset12 {
+    margin-left: 105.52486187845304%;
+    *margin-left: 105.41847889972962%;
+  }
+  .row-fluid .offset12:first-child {
+    margin-left: 102.76243093922652%;
+    *margin-left: 102.6560479605031%;
+  }
+  .row-fluid .offset11 {
+    margin-left: 96.96132596685082%;
+    *margin-left: 96.8549429881274%;
+  }
+  .row-fluid .offset11:first-child {
+    margin-left: 94.1988950276243%;
+    *margin-left: 94.09251204890089%;
+  }
+  .row-fluid .offset10 {
+    margin-left: 88.39779005524862%;
+    *margin-left: 88.2914070765252%;
+  }
+  .row-fluid .offset10:first-child {
+    margin-left: 85.6353591160221%;
+    *margin-left: 85.52897613729868%;
+  }
+  .row-fluid .offset9 {
+    margin-left: 79.8342541436464%;
+    *margin-left: 79.72787116492299%;
+  }
+  .row-fluid .offset9:first-child {
+    margin-left: 77.07182320441989%;
+    *margin-left: 76.96544022569647%;
+  }
+  .row-fluid .offset8 {
+    margin-left: 71.2707182320442%;
+    *margin-left: 71.16433525332079%;
+  }
+  .row-fluid .offset8:first-child {
+    margin-left: 68.50828729281768%;
+    *margin-left: 68.40190431409427%;
+  }
+  .row-fluid .offset7 {
+    margin-left: 62.70718232044199%;
+    *margin-left: 62.600799341718584%;
+  }
+  .row-fluid .offset7:first-child {
+    margin-left: 59.94475138121547%;
+    *margin-left: 59.838368402492065%;
+  }
+  .row-fluid .offset6 {
+    margin-left: 54.14364640883978%;
+    *margin-left: 54.037263430116376%;
+  }
+  .row-fluid .offset6:first-child {
+    margin-left: 51.38121546961326%;
+    *margin-left: 51.27483249088986%;
+  }
+  .row-fluid .offset5 {
+    margin-left: 45.58011049723757%;
+    *margin-left: 45.47372751851417%;
+  }
+  .row-fluid .offset5:first-child {
+    margin-left: 42.81767955801105%;
+    *margin-left: 42.71129657928765%;
+  }
+  .row-fluid .offset4 {
+    margin-left: 37.01657458563536%;
+    *margin-left: 36.91019160691196%;
+  }
+  .row-fluid .offset4:first-child {
+    margin-left: 34.25414364640884%;
+    *margin-left: 34.14776066768544%;
+  }
+  .row-fluid .offset3 {
+    margin-left: 28.45303867403315%;
+    *margin-left: 28.346655695309746%;
+  }
+  .row-fluid .offset3:first-child {
+    margin-left: 25.69060773480663%;
+    *margin-left: 25.584224756083227%;
+  }
+  .row-fluid .offset2 {
+    margin-left: 19.88950276243094%;
+    *margin-left: 19.783119783707537%;
+  }
+  .row-fluid .offset2:first-child {
+    margin-left: 17.12707182320442%;
+    *margin-left: 17.02068884448102%;
+  }
+  .row-fluid .offset1 {
+    margin-left: 11.32596685082873%;
+    *margin-left: 11.219583872105325%;
+  }
+  .row-fluid .offset1:first-child {
+    margin-left: 8.56353591160221%;
+    *margin-left: 8.457152932878806%;
+  }
+  input,
+  textarea,
+  .uneditable-input {
+    margin-left: 0;
+  }
+  .controls-row [class*="span"] + [class*="span"] {
+    margin-left: 20px;
+  }
+  input.span12,
+  textarea.span12,
+  .uneditable-input.span12 {
+    width: 710px;
+  }
+  input.span11,
+  textarea.span11,
+  .uneditable-input.span11 {
+    width: 648px;
+  }
+  input.span10,
+  textarea.span10,
+  .uneditable-input.span10 {
+    width: 586px;
+  }
+  input.span9,
+  textarea.span9,
+  .uneditable-input.span9 {
+    width: 524px;
+  }
+  input.span8,
+  textarea.span8,
+  .uneditable-input.span8 {
+    width: 462px;
+  }
+  input.span7,
+  textarea.span7,
+  .uneditable-input.span7 {
+    width: 400px;
+  }
+  input.span6,
+  textarea.span6,
+  .uneditable-input.span6 {
+    width: 338px;
+  }
+  input.span5,
+  textarea.span5,
+  .uneditable-input.span5 {
+    width: 276px;
+  }
+  input.span4,
+  textarea.span4,
+  .uneditable-input.span4 {
+    width: 214px;
+  }
+  input.span3,
+  textarea.span3,
+  .uneditable-input.span3 {
+    width: 152px;
+  }
+  input.span2,
+  textarea.span2,
+  .uneditable-input.span2 {
+    width: 90px;
+  }
+  input.span1,
+  textarea.span1,
+  .uneditable-input.span1 {
+    width: 28px;
+  }
+}
+
+@media (max-width: 767px) {
+  body {
+    padding-right: 20px;
+    padding-left: 20px;
+  }
+  .navbar-fixed-top,
+  .navbar-fixed-bottom {
+    margin-right: -20px;
+    margin-left: -20px;
+  }
+  .container-fluid {
+    padding: 0;
+  }
+  .dl-horizontal dt {
+    float: none;
+    width: auto;
+    clear: none;
+    text-align: left;
+  }
+  .dl-horizontal dd {
+    margin-left: 0;
+  }
+  .container {
+    width: auto;
+  }
+  .row-fluid {
+    width: 100%;
+  }
+  .row,
+  .thumbnails {
+    margin-left: 0;
+  }
+  .thumbnails > li {
+    float: none;
+    margin-left: 0;
+  }
+  [class*="span"],
+  .row-fluid [class*="span"] {
+    display: block;
+    float: none;
+    width: auto;
+    margin-left: 0;
+  }
+  .span12,
+  .row-fluid .span12 {
+    width: 100%;
+    -webkit-box-sizing: border-box;
+       -moz-box-sizing: border-box;
+            box-sizing: border-box;
+  }
+  .input-large,
+  .input-xlarge,
+  .input-xxlarge,
+  input[class*="span"],
+  select[class*="span"],
+  textarea[class*="span"],
+  .uneditable-input {
+    display: block;
+    width: 100%;
+    min-height: 30px;
+    -webkit-box-sizing: border-box;
+       -moz-box-sizing: border-box;
+            box-sizing: border-box;
+  }
+  .input-prepend input,
+  .input-append input,
+  .input-prepend input[class*="span"],
+  .input-append input[class*="span"] {
+    display: inline-block;
+    width: auto;
+  }
+  .modal {
+    position: fixed;
+    top: 20px;
+    right: 20px;
+    left: 20px;
+    width: auto;
+    margin: 0;
+  }
+  .modal.fade.in {
+    top: auto;
+  }
+}
+
+@media (max-width: 480px) {
+  .nav-collapse {
+    -webkit-transform: translate3d(0, 0, 0);
+  }
+  .page-header h1 small {
+    display: block;
+    line-height: 20px;
+  }
+  input[type="checkbox"],
+  input[type="radio"] {
+    border: 1px solid #ccc;
+  }
+  .form-horizontal .control-group > label {
+    float: none;
+    width: auto;
+    padding-top: 0;
+    text-align: left;
+  }
+  .form-horizontal .controls {
+    margin-left: 0;
+  }
+  .form-horizontal .control-list {
+    padding-top: 0;
+  }
+  .form-horizontal .form-actions {
+    padding-right: 10px;
+    padding-left: 10px;
+  }
+  .modal {
+    top: 10px;
+    right: 10px;
+    left: 10px;
+  }
+  .modal-header .close {
+    padding: 10px;
+    margin: -10px;
+  }
+  .carousel-caption {
+    position: static;
+  }
+}
+
+@media (max-width: 979px) {
+  body {
+    padding-top: 0;
+  }
+  .navbar-fixed-top,
+  .navbar-fixed-bottom {
+    position: static;
+  }
+  .navbar-fixed-top {
+    margin-bottom: 20px;
+  }
+  .navbar-fixed-bottom {
+    margin-top: 20px;
+  }
+  .navbar-fixed-top .navbar-inner,
+  .navbar-fixed-bottom .navbar-inner {
+    padding: 5px;
+  }
+  .navbar .container {
+    width: auto;
+    padding: 0;
+  }
+  .navbar .brand {
+    padding-right: 10px;
+    padding-left: 10px;
+    margin: 0 0 0 -5px;
+  }
+  .nav-collapse {
+    clear: both;
+  }
+  .nav-collapse .nav {
+    float: none;
+    margin: 0 0 10px;
+  }
+  .nav-collapse .nav > li {
+    float: none;
+  }
+  .nav-collapse .nav > li > a {
+    margin-bottom: 2px;
+  }
+  .nav-collapse .nav > .divider-vertical {
+    display: none;
+  }
+  .nav-collapse .nav .nav-header {
+    color: #555555;
+    text-shadow: none;
+  }
+  .nav-collapse .nav > li > a,
+  .nav-collapse .dropdown-menu a {
+    padding: 9px 15px;
+    font-weight: bold;
+    color: #555555;
+    -webkit-border-radius: 3px;
+       -moz-border-radius: 3px;
+            border-radius: 3px;
+  }
+  .nav-collapse .btn {
+    padding: 4px 10px 4px;
+    font-weight: normal;
+    -webkit-border-radius: 4px;
+       -moz-border-radius: 4px;
+            border-radius: 4px;
+  }
+  .nav-collapse .dropdown-menu li + li a {
+    margin-bottom: 2px;
+  }
+  .nav-collapse .nav > li > a:hover,
+  .nav-collapse .dropdown-menu a:hover {
+    background-color: #f2f2f2;
+  }
+  .navbar-inverse .nav-collapse .nav > li > a:hover,
+  .navbar-inverse .nav-collapse .dropdown-menu a:hover {
+    background-color: #111111;
+  }
+  .nav-collapse.in .btn-group {
+    padding: 0;
+    margin-top: 5px;
+  }
+  .nav-collapse .dropdown-menu {
+    position: static;
+    top: auto;
+    left: auto;
+    display: block;
+    float: none;
+    max-width: none;
+    padding: 0;
+    margin: 0 15px;
+    background-color: transparent;
+    border: none;
+    -webkit-border-radius: 0;
+       -moz-border-radius: 0;
+            border-radius: 0;
+    -webkit-box-shadow: none;
+       -moz-box-shadow: none;
+            box-shadow: none;
+  }
+  .nav-collapse .dropdown-menu:before,
+  .nav-collapse .dropdown-menu:after {
+    display: none;
+  }
+  .nav-collapse .dropdown-menu .divider {
+    display: none;
+  }
+  .nav-collapse .navbar-form,
+  .nav-collapse .navbar-search {
+    float: none;
+    padding: 10px 15px;
+    margin: 10px 0;
+    border-top: 1px solid #f2f2f2;
+    border-bottom: 1px solid #f2f2f2;
+    -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1);
+       -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1);
+            box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1);
+  }
+  .navbar .nav-collapse .nav.pull-right {
+    float: none;
+    margin-left: 0;
+  }
+  .nav-collapse,
+  .nav-collapse.collapse {
+    height: 0;
+    overflow: hidden;
+  }
+  .navbar .btn-navbar {
+    display: block;
+  }
+  .navbar-static .navbar-inner {
+    padding-right: 10px;
+    padding-left: 10px;
+  }
+}
+
+@media (min-width: 980px) {
+  .nav-collapse.collapse {
+    height: auto !important;
+    overflow: visible !important;
+  }
+}


[21/51] [abbrv] [partial] Adding Jinwon's custom RCMET

Posted by jo...@apache.org.
http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/app/js/leaflet.js
----------------------------------------------------------------------
diff --git a/src/main/ui/app/js/leaflet.js b/src/main/ui/app/js/leaflet.js
new file mode 100755
index 0000000..4875188
--- /dev/null
+++ b/src/main/ui/app/js/leaflet.js
@@ -0,0 +1,8 @@
+/*
+ Leaflet, a JavaScript library for mobile-friendly interactive maps. http://leafletjs.com
+ (c) 2010-2013, Vladimir Agafonkin, CloudMade
+*/
+(function(t,e,i){var n,o;typeof exports!=i+""?n=exports:(o=t.L,n={},n.noConflict=function(){return t.L=o,this},t.L=n),n.version="0.5",n.Util={extend:function(t){var e,i,n,o,s=Array.prototype.slice.call(arguments,1);for(i=0,n=s.length;n>i;i++){o=s[i]||{};for(e in o)o.hasOwnProperty(e)&&(t[e]=o[e])}return t},bind:function(t,e){var i=arguments.length>2?Array.prototype.slice.call(arguments,2):null;return function(){return t.apply(e,i||arguments)}},stamp:function(){var t=0,e="_leaflet_id";return function(i){return i[e]=i[e]||++t,i[e]}}(),limitExecByInterval:function(t,e,n){var o,s;return function a(){var r=arguments;return o?(s=!0,i):(o=!0,setTimeout(function(){o=!1,s&&(a.apply(n,r),s=!1)},e),t.apply(n,r),i)}},falseFn:function(){return!1},formatNum:function(t,e){var i=Math.pow(10,e||5);return Math.round(t*i)/i},splitWords:function(t){return t.replace(/^\s+|\s+$/g,"").split(/\s+/)},setOptions:function(t,e){return t.options=n.extend({},t.options,e),t.options},getParamString:function(t,e){v
 ar i=[];for(var n in t)t.hasOwnProperty(n)&&i.push(n+"="+t[n]);return(e&&-1!==e.indexOf("?")?"&":"?")+i.join("&")},template:function(t,e){return t.replace(/\{ *([\w_]+) *\}/g,function(t,i){var n=e[i];if(!e.hasOwnProperty(i))throw Error("No value provided for variable "+t);return n})},isArray:function(t){return"[object Array]"===Object.prototype.toString.call(t)},emptyImageUrl:"data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs="},function(){function e(e){var i,n,o=["webkit","moz","o","ms"];for(i=0;o.length>i&&!n;i++)n=t[o[i]+e];return n}function o(e){var i=+new Date,n=Math.max(0,16-(i-s));return s=i+n,t.setTimeout(e,n)}var s=0,a=t.requestAnimationFrame||e("RequestAnimationFrame")||o,r=t.cancelAnimationFrame||e("CancelAnimationFrame")||e("CancelRequestAnimationFrame")||function(e){t.clearTimeout(e)};n.Util.requestAnimFrame=function(e,s,r,h){return e=n.bind(e,s),r&&a===o?(e(),i):a.call(t,e,h)},n.Util.cancelAnimFrame=function(e){e&&r.call(t,e)}}(),n.extend=n.Util.extend,n.bind=n
 .Util.bind,n.stamp=n.Util.stamp,n.setOptions=n.Util.setOptions,n.Class=function(){},n.Class.extend=function(t){var e=function(){this.initialize&&this.initialize.apply(this,arguments),this._initHooks&&this.callInitHooks()},i=function(){};i.prototype=this.prototype;var o=new i;o.constructor=e,e.prototype=o;for(var s in this)this.hasOwnProperty(s)&&"prototype"!==s&&(e[s]=this[s]);t.statics&&(n.extend(e,t.statics),delete t.statics),t.includes&&(n.Util.extend.apply(null,[o].concat(t.includes)),delete t.includes),t.options&&o.options&&(t.options=n.extend({},o.options,t.options)),n.extend(o,t),o._initHooks=[];var a=this;return o.callInitHooks=function(){if(!this._initHooksCalled){a.prototype.callInitHooks&&a.prototype.callInitHooks.call(this),this._initHooksCalled=!0;for(var t=0,e=o._initHooks.length;e>t;t++)o._initHooks[t].call(this)}},e},n.Class.include=function(t){n.extend(this.prototype,t)},n.Class.mergeOptions=function(t){n.extend(this.prototype.options,t)},n.Class.addInitHook=functio
 n(t){var e=Array.prototype.slice.call(arguments,1),i="function"==typeof t?t:function(){this[t].apply(this,e)};this.prototype._initHooks=this.prototype._initHooks||[],this.prototype._initHooks.push(i)};var s="_leaflet_events";n.Mixin={},n.Mixin.Events={addEventListener:function(t,e,i){var o,a,r,h=this[s]=this[s]||{};if("object"==typeof t){for(o in t)t.hasOwnProperty(o)&&this.addEventListener(o,t[o],e);return this}for(t=n.Util.splitWords(t),a=0,r=t.length;r>a;a++)h[t[a]]=h[t[a]]||[],h[t[a]].push({action:e,context:i||this});return this},hasEventListeners:function(t){return s in this&&t in this[s]&&this[s][t].length>0},removeEventListener:function(t,e,i){var o,a,r,h,l,u=this[s];if("object"==typeof t){for(o in t)t.hasOwnProperty(o)&&this.removeEventListener(o,t[o],e);return this}for(t=n.Util.splitWords(t),a=0,r=t.length;r>a;a++)if(this.hasEventListeners(t[a]))for(h=u[t[a]],l=h.length-1;l>=0;l--)e&&h[l].action!==e||i&&h[l].context!==i||h.splice(l,1);return this},fireEvent:function(t,e){if
 (!this.hasEventListeners(t))return this;for(var i=n.extend({type:t,target:this},e),o=this[s][t].slice(),a=0,r=o.length;r>a;a++)o[a].action.call(o[a].context||this,i);return this}},n.Mixin.Events.on=n.Mixin.Events.addEventListener,n.Mixin.Events.off=n.Mixin.Events.removeEventListener,n.Mixin.Events.fire=n.Mixin.Events.fireEvent,function(){var o=!!t.ActiveXObject,s=o&&!t.XMLHttpRequest,a=o&&!e.querySelector,r=navigator.userAgent.toLowerCase(),h=-1!==r.indexOf("webkit"),l=-1!==r.indexOf("chrome"),u=-1!==r.indexOf("android"),c=-1!==r.search("android [23]"),_=typeof orientation!=i+"",d=t.navigator&&t.navigator.msPointerEnabled&&t.navigator.msMaxTouchPoints,p="devicePixelRatio"in t&&t.devicePixelRatio>1||"matchMedia"in t&&t.matchMedia("(min-resolution:144dpi)")&&t.matchMedia("(min-resolution:144dpi)").matches,m=e.documentElement,f=o&&"transition"in m.style,g="WebKitCSSMatrix"in t&&"m11"in new t.WebKitCSSMatrix,v="MozPerspective"in m.style,y="OTransition"in m.style,L=!t.L_DISABLE_3D&&(f||g
 ||v||y),P=!t.L_NO_TOUCH&&function(){var t="ontouchstart";if(d||t in m)return!0;var i=e.createElement("div"),n=!1;return i.setAttribute?(i.setAttribute(t,"return;"),"function"==typeof i[t]&&(n=!0),i.removeAttribute(t),i=null,n):!1}();n.Browser={ie:o,ie6:s,ie7:a,webkit:h,android:u,android23:c,chrome:l,ie3d:f,webkit3d:g,gecko3d:v,opera3d:y,any3d:L,mobile:_,mobileWebkit:_&&h,mobileWebkit3d:_&&g,mobileOpera:_&&t.opera,touch:P,msTouch:d,retina:p}}(),n.Point=function(t,e,i){this.x=i?Math.round(t):t,this.y=i?Math.round(e):e},n.Point.prototype={clone:function(){return new n.Point(this.x,this.y)},add:function(t){return this.clone()._add(n.point(t))},_add:function(t){return this.x+=t.x,this.y+=t.y,this},subtract:function(t){return this.clone()._subtract(n.point(t))},_subtract:function(t){return this.x-=t.x,this.y-=t.y,this},divideBy:function(t){return this.clone()._divideBy(t)},_divideBy:function(t){return this.x/=t,this.y/=t,this},multiplyBy:function(t){return this.clone()._multiplyBy(t)},_mu
 ltiplyBy:function(t){return this.x*=t,this.y*=t,this},round:function(){return this.clone()._round()},_round:function(){return this.x=Math.round(this.x),this.y=Math.round(this.y),this},floor:function(){return this.clone()._floor()},_floor:function(){return this.x=Math.floor(this.x),this.y=Math.floor(this.y),this},distanceTo:function(t){t=n.point(t);var e=t.x-this.x,i=t.y-this.y;return Math.sqrt(e*e+i*i)},equals:function(t){return t.x===this.x&&t.y===this.y},toString:function(){return"Point("+n.Util.formatNum(this.x)+", "+n.Util.formatNum(this.y)+")"}},n.point=function(t,e,i){return t instanceof n.Point?t:n.Util.isArray(t)?new n.Point(t[0],t[1]):isNaN(t)?t:new n.Point(t,e,i)},n.Bounds=function(t,e){if(t)for(var i=e?[t,e]:t,n=0,o=i.length;o>n;n++)this.extend(i[n])},n.Bounds.prototype={extend:function(t){return t=n.point(t),this.min||this.max?(this.min.x=Math.min(t.x,this.min.x),this.max.x=Math.max(t.x,this.max.x),this.min.y=Math.min(t.y,this.min.y),this.max.y=Math.max(t.y,this.max.y)):
 (this.min=t.clone(),this.max=t.clone()),this},getCenter:function(t){return new n.Point((this.min.x+this.max.x)/2,(this.min.y+this.max.y)/2,t)},getBottomLeft:function(){return new n.Point(this.min.x,this.max.y)},getTopRight:function(){return new n.Point(this.max.x,this.min.y)},getSize:function(){return this.max.subtract(this.min)},contains:function(t){var e,i;return t="number"==typeof t[0]||t instanceof n.Point?n.point(t):n.bounds(t),t instanceof n.Bounds?(e=t.min,i=t.max):e=i=t,e.x>=this.min.x&&i.x<=this.max.x&&e.y>=this.min.y&&i.y<=this.max.y},intersects:function(t){t=n.bounds(t);var e=this.min,i=this.max,o=t.min,s=t.max,a=s.x>=e.x&&o.x<=i.x,r=s.y>=e.y&&o.y<=i.y;return a&&r},isValid:function(){return!(!this.min||!this.max)}},n.bounds=function(t,e){return!t||t instanceof n.Bounds?t:new n.Bounds(t,e)},n.Transformation=function(t,e,i,n){this._a=t,this._b=e,this._c=i,this._d=n},n.Transformation.prototype={transform:function(t,e){return this._transform(t.clone(),e)},_transform:function(
 t,e){return e=e||1,t.x=e*(this._a*t.x+this._b),t.y=e*(this._c*t.y+this._d),t},untransform:function(t,e){return e=e||1,new n.Point((t.x/e-this._b)/this._a,(t.y/e-this._d)/this._c)}},n.DomUtil={get:function(t){return"string"==typeof t?e.getElementById(t):t},getStyle:function(t,i){var n=t.style[i];if(!n&&t.currentStyle&&(n=t.currentStyle[i]),(!n||"auto"===n)&&e.defaultView){var o=e.defaultView.getComputedStyle(t,null);n=o?o[i]:null}return"auto"===n?null:n},getViewportOffset:function(t){var i,o=0,s=0,a=t,r=e.body,h=n.Browser.ie7;do{if(o+=a.offsetTop||0,s+=a.offsetLeft||0,o+=parseInt(n.DomUtil.getStyle(a,"borderTopWidth"),10)||0,s+=parseInt(n.DomUtil.getStyle(a,"borderLeftWidth"),10)||0,i=n.DomUtil.getStyle(a,"position"),a.offsetParent===r&&"absolute"===i)break;if("fixed"===i){o+=r.scrollTop||0,s+=r.scrollLeft||0;break}a=a.offsetParent}while(a);a=t;do{if(a===r)break;o-=a.scrollTop||0,s-=a.scrollLeft||0,n.DomUtil.documentIsLtr()||!n.Browser.webkit&&!h||(s+=a.scrollWidth-a.clientWidth,h&&"
 hidden"!==n.DomUtil.getStyle(a,"overflow-y")&&"hidden"!==n.DomUtil.getStyle(a,"overflow")&&(s+=17)),a=a.parentNode}while(a);return new n.Point(s,o)},documentIsLtr:function(){return n.DomUtil._docIsLtrCached||(n.DomUtil._docIsLtrCached=!0,n.DomUtil._docIsLtr="ltr"===n.DomUtil.getStyle(e.body,"direction")),n.DomUtil._docIsLtr},create:function(t,i,n){var o=e.createElement(t);return o.className=i,n&&n.appendChild(o),o},disableTextSelection:function(){e.selection&&e.selection.empty&&e.selection.empty(),this._onselectstart||(this._onselectstart=e.onselectstart||null,e.onselectstart=n.Util.falseFn)},enableTextSelection:function(){e.onselectstart===n.Util.falseFn&&(e.onselectstart=this._onselectstart,this._onselectstart=null)},hasClass:function(t,e){return t.className.length>0&&RegExp("(^|\\s)"+e+"(\\s|$)").test(t.className)},addClass:function(t,e){n.DomUtil.hasClass(t,e)||(t.className+=(t.className?" ":"")+e)},removeClass:function(t,e){function i(t,i){return i===e?"":t}t.className=t.classN
 ame.replace(/(\S+)\s*/g,i).replace(/(^\s+|\s+$)/,"")},setOpacity:function(t,e){if("opacity"in t.style)t.style.opacity=e;else if("filter"in t.style){var i=!1,n="DXImageTransform.Microsoft.Alpha";try{i=t.filters.item(n)}catch(o){}e=Math.round(100*e),i?(i.Enabled=100!==e,i.Opacity=e):t.style.filter+=" progid:"+n+"(opacity="+e+")"}},testProp:function(t){for(var i=e.documentElement.style,n=0;t.length>n;n++)if(t[n]in i)return t[n];return!1},getTranslateString:function(t){var e=n.Browser.webkit3d,i="translate"+(e?"3d":"")+"(",o=(e?",0":"")+")";return i+t.x+"px,"+t.y+"px"+o},getScaleString:function(t,e){var i=n.DomUtil.getTranslateString(e.add(e.multiplyBy(-1*t))),o=" scale("+t+") ";return i+o},setPosition:function(t,e,i){t._leaflet_pos=e,!i&&n.Browser.any3d?(t.style[n.DomUtil.TRANSFORM]=n.DomUtil.getTranslateString(e),n.Browser.mobileWebkit3d&&(t.style.WebkitBackfaceVisibility="hidden")):(t.style.left=e.x+"px",t.style.top=e.y+"px")},getPosition:function(t){return t._leaflet_pos}},n.DomUtil
 .TRANSFORM=n.DomUtil.testProp(["transform","WebkitTransform","OTransform","MozTransform","msTransform"]),n.DomUtil.TRANSITION=n.DomUtil.testProp(["webkitTransition","transition","OTransition","MozTransition","msTransition"]),n.DomUtil.TRANSITION_END="webkitTransition"===n.DomUtil.TRANSITION||"OTransition"===n.DomUtil.TRANSITION?n.DomUtil.TRANSITION+"End":"transitionend",n.LatLng=function(t,e){var i=parseFloat(t),n=parseFloat(e);if(isNaN(i)||isNaN(n))throw Error("Invalid LatLng object: ("+t+", "+e+")");this.lat=i,this.lng=n},n.extend(n.LatLng,{DEG_TO_RAD:Math.PI/180,RAD_TO_DEG:180/Math.PI,MAX_MARGIN:1e-9}),n.LatLng.prototype={equals:function(t){if(!t)return!1;t=n.latLng(t);var e=Math.max(Math.abs(this.lat-t.lat),Math.abs(this.lng-t.lng));return n.LatLng.MAX_MARGIN>=e},toString:function(t){return"LatLng("+n.Util.formatNum(this.lat,t)+", "+n.Util.formatNum(this.lng,t)+")"},distanceTo:function(t){t=n.latLng(t);var e=6378137,i=n.LatLng.DEG_TO_RAD,o=(t.lat-this.lat)*i,s=(t.lng-this.lng)*i
 ,a=this.lat*i,r=t.lat*i,h=Math.sin(o/2),l=Math.sin(s/2),u=h*h+l*l*Math.cos(a)*Math.cos(r);return 2*e*Math.atan2(Math.sqrt(u),Math.sqrt(1-u))},wrap:function(t,e){var i=this.lng;return t=t||-180,e=e||180,i=(i+e)%(e-t)+(t>i||i===e?e:t),new n.LatLng(this.lat,i)}},n.latLng=function(t,e){return t instanceof n.LatLng?t:n.Util.isArray(t)?new n.LatLng(t[0],t[1]):isNaN(t)?t:new n.LatLng(t,e)},n.LatLngBounds=function(t,e){if(t)for(var i=e?[t,e]:t,n=0,o=i.length;o>n;n++)this.extend(i[n])},n.LatLngBounds.prototype={extend:function(t){return t="number"==typeof t[0]||"string"==typeof t[0]||t instanceof n.LatLng?n.latLng(t):n.latLngBounds(t),t instanceof n.LatLng?this._southWest||this._northEast?(this._southWest.lat=Math.min(t.lat,this._southWest.lat),this._southWest.lng=Math.min(t.lng,this._southWest.lng),this._northEast.lat=Math.max(t.lat,this._northEast.lat),this._northEast.lng=Math.max(t.lng,this._northEast.lng)):(this._southWest=new n.LatLng(t.lat,t.lng),this._northEast=new n.LatLng(t.lat,t.ln
 g)):t instanceof n.LatLngBounds&&(this.extend(t._southWest),this.extend(t._northEast)),this},pad:function(t){var e=this._southWest,i=this._northEast,o=Math.abs(e.lat-i.lat)*t,s=Math.abs(e.lng-i.lng)*t;return new n.LatLngBounds(new n.LatLng(e.lat-o,e.lng-s),new n.LatLng(i.lat+o,i.lng+s))},getCenter:function(){return new n.LatLng((this._southWest.lat+this._northEast.lat)/2,(this._southWest.lng+this._northEast.lng)/2)},getSouthWest:function(){return this._southWest},getNorthEast:function(){return this._northEast},getNorthWest:function(){return new n.LatLng(this._northEast.lat,this._southWest.lng)},getSouthEast:function(){return new n.LatLng(this._southWest.lat,this._northEast.lng)},contains:function(t){t="number"==typeof t[0]||t instanceof n.LatLng?n.latLng(t):n.latLngBounds(t);var e,i,o=this._southWest,s=this._northEast;return t instanceof n.LatLngBounds?(e=t.getSouthWest(),i=t.getNorthEast()):e=i=t,e.lat>=o.lat&&i.lat<=s.lat&&e.lng>=o.lng&&i.lng<=s.lng},intersects:function(t){t=n.lat
 LngBounds(t);var e=this._southWest,i=this._northEast,o=t.getSouthWest(),s=t.getNorthEast(),a=s.lat>=e.lat&&o.lat<=i.lat,r=s.lng>=e.lng&&o.lng<=i.lng;return a&&r},toBBoxString:function(){var t=this._southWest,e=this._northEast;return[t.lng,t.lat,e.lng,e.lat].join(",")},equals:function(t){return t?(t=n.latLngBounds(t),this._southWest.equals(t.getSouthWest())&&this._northEast.equals(t.getNorthEast())):!1},isValid:function(){return!(!this._southWest||!this._northEast)}},n.latLngBounds=function(t,e){return!t||t instanceof n.LatLngBounds?t:new n.LatLngBounds(t,e)},n.Projection={},n.Projection.SphericalMercator={MAX_LATITUDE:85.0511287798,project:function(t){var e=n.LatLng.DEG_TO_RAD,i=this.MAX_LATITUDE,o=Math.max(Math.min(i,t.lat),-i),s=t.lng*e,a=o*e;return a=Math.log(Math.tan(Math.PI/4+a/2)),new n.Point(s,a)},unproject:function(t){var e=n.LatLng.RAD_TO_DEG,i=t.x*e,o=(2*Math.atan(Math.exp(t.y))-Math.PI/2)*e;return new n.LatLng(o,i)}},n.Projection.LonLat={project:function(t){return new n.P
 oint(t.lng,t.lat)},unproject:function(t){return new n.LatLng(t.y,t.x)}},n.CRS={latLngToPoint:function(t,e){var i=this.projection.project(t),n=this.scale(e);return this.transformation._transform(i,n)},pointToLatLng:function(t,e){var i=this.scale(e),n=this.transformation.untransform(t,i);return this.projection.unproject(n)},project:function(t){return this.projection.project(t)},scale:function(t){return 256*Math.pow(2,t)}},n.CRS.Simple=n.extend({},n.CRS,{projection:n.Projection.LonLat,transformation:new n.Transformation(1,0,-1,0),scale:function(t){return Math.pow(2,t)}}),n.CRS.EPSG3857=n.extend({},n.CRS,{code:"EPSG:3857",projection:n.Projection.SphericalMercator,transformation:new n.Transformation(.5/Math.PI,.5,-.5/Math.PI,.5),project:function(t){var e=this.projection.project(t),i=6378137;return e.multiplyBy(i)}}),n.CRS.EPSG900913=n.extend({},n.CRS.EPSG3857,{code:"EPSG:900913"}),n.CRS.EPSG4326=n.extend({},n.CRS,{code:"EPSG:4326",projection:n.Projection.LonLat,transformation:new n.Trans
 formation(1/360,.5,-1/360,.5)}),n.Map=n.Class.extend({includes:n.Mixin.Events,options:{crs:n.CRS.EPSG3857,fadeAnimation:n.DomUtil.TRANSITION&&!n.Browser.android23,trackResize:!0,markerZoomAnimation:n.DomUtil.TRANSITION&&n.Browser.any3d},initialize:function(t,e){e=n.setOptions(this,e),this._initContainer(t),this._initLayout(),this.callInitHooks(),this._initEvents(),e.maxBounds&&this.setMaxBounds(e.maxBounds),e.center&&e.zoom!==i&&this.setView(n.latLng(e.center),e.zoom,!0),this._initLayers(e.layers)},setView:function(t,e){return this._resetView(n.latLng(t),this._limitZoom(e)),this},setZoom:function(t){return this.setView(this.getCenter(),t)},zoomIn:function(t){return this.setZoom(this._zoom+(t||1))},zoomOut:function(t){return this.setZoom(this._zoom-(t||1))},fitBounds:function(t){var e=this.getBoundsZoom(t);return this.setView(n.latLngBounds(t).getCenter(),e)},fitWorld:function(){var t=new n.LatLng(-60,-170),e=new n.LatLng(85,179);return this.fitBounds(new n.LatLngBounds(t,e))},panTo:
 function(t){return this.setView(t,this._zoom)},panBy:function(t){return this.fire("movestart"),this._rawPanBy(n.point(t)),this.fire("move"),this.fire("moveend")},setMaxBounds:function(t){if(t=n.latLngBounds(t),this.options.maxBounds=t,!t)return this._boundsMinZoom=null,this;var e=this.getBoundsZoom(t,!0);return this._boundsMinZoom=e,this._loaded&&(e>this._zoom?this.setView(t.getCenter(),e):this.panInsideBounds(t)),this},panInsideBounds:function(t){t=n.latLngBounds(t);var e=this.getBounds(),i=this.project(e.getSouthWest()),o=this.project(e.getNorthEast()),s=this.project(t.getSouthWest()),a=this.project(t.getNorthEast()),r=0,h=0;return o.y<a.y&&(h=a.y-o.y),o.x>a.x&&(r=a.x-o.x),i.y>s.y&&(h=s.y-i.y),i.x<s.x&&(r=s.x-i.x),this.panBy(new n.Point(r,h,!0))},addLayer:function(t){var e=n.stamp(t);return this._layers[e]?this:(this._layers[e]=t,!t.options||isNaN(t.options.maxZoom)&&isNaN(t.options.minZoom)||(this._zoomBoundLayers[e]=t,this._updateZoomLevels()),this.options.zoomAnimation&&n.TileL
 ayer&&t instanceof n.TileLayer&&(this._tileLayersNum++,this._tileLayersToLoad++,t.on("load",this._onTileLayerLoad,this)),this.whenReady(function(){t.onAdd(this),this.fire("layeradd",{layer:t})},this),this)},removeLayer:function(t){var e=n.stamp(t);if(this._layers[e])return t.onRemove(this),delete this._layers[e],this._zoomBoundLayers[e]&&(delete this._zoomBoundLayers[e],this._updateZoomLevels()),this.options.zoomAnimation&&n.TileLayer&&t instanceof n.TileLayer&&(this._tileLayersNum--,this._tileLayersToLoad--,t.off("load",this._onTileLayerLoad,this)),this.fire("layerremove",{layer:t})},hasLayer:function(t){var e=n.stamp(t);return this._layers.hasOwnProperty(e)},invalidateSize:function(t){var e=this.getSize();if(this._sizeChanged=!0,this.options.maxBounds&&this.setMaxBounds(this.options.maxBounds),!this._loaded)return this;var i=e._subtract(this.getSize())._divideBy(2)._round();return t===!0?this.panBy(i):(this._rawPanBy(i),this.fire("move"),clearTimeout(this._sizeTimer),this._sizeTim
 er=setTimeout(n.bind(this.fire,this,"moveend"),200)),this},addHandler:function(t,e){return e?(this[t]=new e(this),this.options[t]&&this[t].enable(),this):i},getCenter:function(){return this.layerPointToLatLng(this._getCenterLayerPoint())},getZoom:function(){return this._zoom},getBounds:function(){var t=this.getPixelBounds(),e=this.unproject(t.getBottomLeft()),i=this.unproject(t.getTopRight());return new n.LatLngBounds(e,i)},getMinZoom:function(){var t=this.options.minZoom||0,e=this._layersMinZoom||0,i=this._boundsMinZoom||0;return Math.max(t,e,i)},getMaxZoom:function(){var t=this.options.maxZoom===i?1/0:this.options.maxZoom,e=this._layersMaxZoom===i?1/0:this._layersMaxZoom;return Math.min(t,e)},getBoundsZoom:function(t,e){t=n.latLngBounds(t);var i,o,s,a=this.getSize(),r=this.options.minZoom||0,h=this.getMaxZoom(),l=t.getNorthEast(),u=t.getSouthWest(),c=!0;e&&r--;do r++,o=this.project(l,r),s=this.project(u,r),i=new n.Point(Math.abs(o.x-s.x),Math.abs(s.y-o.y)),c=e?i.x<a.x||i.y<a.y:i.x
 <=a.x&&i.y<=a.y;while(c&&h>=r);return c&&e?null:e?r:r-1},getSize:function(){return(!this._size||this._sizeChanged)&&(this._size=new n.Point(this._container.clientWidth,this._container.clientHeight),this._sizeChanged=!1),this._size.clone()},getPixelBounds:function(){var t=this._getTopLeftPoint();return new n.Bounds(t,t.add(this.getSize()))},getPixelOrigin:function(){return this._initialTopLeftPoint},getPanes:function(){return this._panes},getContainer:function(){return this._container},getZoomScale:function(t){var e=this.options.crs;return e.scale(t)/e.scale(this._zoom)},getScaleZoom:function(t){return this._zoom+Math.log(t)/Math.LN2},project:function(t,e){return e=e===i?this._zoom:e,this.options.crs.latLngToPoint(n.latLng(t),e)},unproject:function(t,e){return e=e===i?this._zoom:e,this.options.crs.pointToLatLng(n.point(t),e)},layerPointToLatLng:function(t){var e=n.point(t).add(this._initialTopLeftPoint);return this.unproject(e)},latLngToLayerPoint:function(t){var e=this.project(n.lat
 Lng(t))._round();return e._subtract(this._initialTopLeftPoint)},containerPointToLayerPoint:function(t){return n.point(t).subtract(this._getMapPanePos())},layerPointToContainerPoint:function(t){return n.point(t).add(this._getMapPanePos())},containerPointToLatLng:function(t){var e=this.containerPointToLayerPoint(n.point(t));return this.layerPointToLatLng(e)},latLngToContainerPoint:function(t){return this.layerPointToContainerPoint(this.latLngToLayerPoint(n.latLng(t)))},mouseEventToContainerPoint:function(t){return n.DomEvent.getMousePosition(t,this._container)},mouseEventToLayerPoint:function(t){return this.containerPointToLayerPoint(this.mouseEventToContainerPoint(t))},mouseEventToLatLng:function(t){return this.layerPointToLatLng(this.mouseEventToLayerPoint(t))},_initContainer:function(t){var e=this._container=n.DomUtil.get(t);if(e._leaflet)throw Error("Map container is already initialized.");e._leaflet=!0},_initLayout:function(){var t=this._container;n.DomUtil.addClass(t,"leaflet-co
 ntainer"),n.Browser.touch&&n.DomUtil.addClass(t,"leaflet-touch"),this.options.fadeAnimation&&n.DomUtil.addClass(t,"leaflet-fade-anim");var e=n.DomUtil.getStyle(t,"position");"absolute"!==e&&"relative"!==e&&"fixed"!==e&&(t.style.position="relative"),this._initPanes(),this._initControlPos&&this._initControlPos()},_initPanes:function(){var t=this._panes={};this._mapPane=t.mapPane=this._createPane("leaflet-map-pane",this._container),this._tilePane=t.tilePane=this._createPane("leaflet-tile-pane",this._mapPane),t.objectsPane=this._createPane("leaflet-objects-pane",this._mapPane),t.shadowPane=this._createPane("leaflet-shadow-pane"),t.overlayPane=this._createPane("leaflet-overlay-pane"),t.markerPane=this._createPane("leaflet-marker-pane"),t.popupPane=this._createPane("leaflet-popup-pane");var e=" leaflet-zoom-hide";this.options.markerZoomAnimation||(n.DomUtil.addClass(t.markerPane,e),n.DomUtil.addClass(t.shadowPane,e),n.DomUtil.addClass(t.popupPane,e))},_createPane:function(t,e){return n.Do
 mUtil.create("div",t,e||this._panes.objectsPane)},_initLayers:function(t){t=t?n.Util.isArray(t)?t:[t]:[],this._layers={},this._zoomBoundLayers={},this._tileLayersNum=0;var e,i;for(e=0,i=t.length;i>e;e++)this.addLayer(t[e])},_resetView:function(t,e,i,o){var s=this._zoom!==e;o||(this.fire("movestart"),s&&this.fire("zoomstart")),this._zoom=e,this._initialTopLeftPoint=this._getNewTopLeftPoint(t),i?this._initialTopLeftPoint._add(this._getMapPanePos()):n.DomUtil.setPosition(this._mapPane,new n.Point(0,0)),this._tileLayersToLoad=this._tileLayersNum;var a=!this._loaded;this._loaded=!0,this.fire("viewreset",{hard:!i}),this.fire("move"),(s||o)&&this.fire("zoomend"),this.fire("moveend",{hard:!i}),a&&this.fire("load")},_rawPanBy:function(t){n.DomUtil.setPosition(this._mapPane,this._getMapPanePos().subtract(t))},_updateZoomLevels:function(){var t,e=1/0,n=-1/0;for(t in this._zoomBoundLayers)if(this._zoomBoundLayers.hasOwnProperty(t)){var o=this._zoomBoundLayers[t];isNaN(o.options.minZoom)||(e=Mat
 h.min(e,o.options.minZoom)),isNaN(o.options.maxZoom)||(n=Math.max(n,o.options.maxZoom))}t===i?this._layersMaxZoom=this._layersMinZoom=i:(this._layersMaxZoom=n,this._layersMinZoom=e)},_initEvents:function(){if(n.DomEvent){n.DomEvent.on(this._container,"click",this._onMouseClick,this);var e,i,o=["dblclick","mousedown","mouseup","mouseenter","mouseleave","mousemove","contextmenu"];for(e=0,i=o.length;i>e;e++)n.DomEvent.on(this._container,o[e],this._fireMouseEvent,this);this.options.trackResize&&n.DomEvent.on(t,"resize",this._onResize,this)}},_onResize:function(){n.Util.cancelAnimFrame(this._resizeRequest),this._resizeRequest=n.Util.requestAnimFrame(this.invalidateSize,this,!1,this._container)},_onMouseClick:function(t){!this._loaded||this.dragging&&this.dragging.moved()||(this.fire("preclick"),this._fireMouseEvent(t))},_fireMouseEvent:function(t){if(this._loaded){var e=t.type;if(e="mouseenter"===e?"mouseover":"mouseleave"===e?"mouseout":e,this.hasEventListeners(e)){"contextmenu"===e&&n.
 DomEvent.preventDefault(t);var i=this.mouseEventToContainerPoint(t),o=this.containerPointToLayerPoint(i),s=this.layerPointToLatLng(o);this.fire(e,{latlng:s,layerPoint:o,containerPoint:i,originalEvent:t})}}},_onTileLayerLoad:function(){this._tileLayersToLoad--,this._tileLayersNum&&!this._tileLayersToLoad&&this._tileBg&&(clearTimeout(this._clearTileBgTimer),this._clearTileBgTimer=setTimeout(n.bind(this._clearTileBg,this),500))},whenReady:function(t,e){return this._loaded?t.call(e||this,this):this.on("load",t,e),this},_getMapPanePos:function(){return n.DomUtil.getPosition(this._mapPane)},_getTopLeftPoint:function(){if(!this._loaded)throw Error("Set map center and zoom first.");return this._initialTopLeftPoint.subtract(this._getMapPanePos())},_getNewTopLeftPoint:function(t,e){var i=this.getSize()._divideBy(2);return this.project(t,e)._subtract(i)._round()},_latLngToNewLayerPoint:function(t,e,i){var n=this._getNewTopLeftPoint(i,e).add(this._getMapPanePos());return this.project(t,e)._subt
 ract(n)},_getCenterLayerPoint:function(){return this.containerPointToLayerPoint(this.getSize()._divideBy(2))},_getCenterOffset:function(t){return this.latLngToLayerPoint(t).subtract(this._getCenterLayerPoint())},_limitZoom:function(t){var e=this.getMinZoom(),i=this.getMaxZoom();return Math.max(e,Math.min(i,t))}}),n.map=function(t,e){return new n.Map(t,e)},n.Projection.Mercator={MAX_LATITUDE:85.0840591556,R_MINOR:6356752.3142,R_MAJOR:6378137,project:function(t){var e=n.LatLng.DEG_TO_RAD,i=this.MAX_LATITUDE,o=Math.max(Math.min(i,t.lat),-i),s=this.R_MAJOR,a=this.R_MINOR,r=t.lng*e*s,h=o*e,l=a/s,u=Math.sqrt(1-l*l),c=u*Math.sin(h);c=Math.pow((1-c)/(1+c),.5*u);var _=Math.tan(.5*(.5*Math.PI-h))/c;return h=-a*Math.log(_),new n.Point(r,h)},unproject:function(t){for(var e,i=n.LatLng.RAD_TO_DEG,o=this.R_MAJOR,s=this.R_MINOR,a=t.x*i/o,r=s/o,h=Math.sqrt(1-r*r),l=Math.exp(-t.y/s),u=Math.PI/2-2*Math.atan(l),c=15,_=1e-7,d=c,p=.1;Math.abs(p)>_&&--d>0;)e=h*Math.sin(u),p=Math.PI/2-2*Math.atan(l*Math.po
 w((1-e)/(1+e),.5*h))-u,u+=p;return new n.LatLng(u*i,a)}},n.CRS.EPSG3395=n.extend({},n.CRS,{code:"EPSG:3395",projection:n.Projection.Mercator,transformation:function(){var t=n.Projection.Mercator,e=t.R_MAJOR,i=t.R_MINOR;return new n.Transformation(.5/(Math.PI*e),.5,-.5/(Math.PI*i),.5)}()}),n.TileLayer=n.Class.extend({includes:n.Mixin.Events,options:{minZoom:0,maxZoom:18,tileSize:256,subdomains:"abc",errorTileUrl:"",attribution:"",zoomOffset:0,opacity:1,unloadInvisibleTiles:n.Browser.mobile,updateWhenIdle:n.Browser.mobile},initialize:function(t,e){e=n.setOptions(this,e),e.detectRetina&&n.Browser.retina&&e.maxZoom>0&&(e.tileSize=Math.floor(e.tileSize/2),e.zoomOffset++,e.minZoom>0&&e.minZoom--,this.options.maxZoom--),this._url=t;var i=this.options.subdomains;"string"==typeof i&&(this.options.subdomains=i.split(""))},onAdd:function(t){this._map=t,this._initContainer(),this._createTileProto(),t.on({viewreset:this._resetCallback,moveend:this._update},this),this.options.updateWhenIdle||(thi
 s._limitedUpdate=n.Util.limitExecByInterval(this._update,150,this),t.on("move",this._limitedUpdate,this)),this._reset(),this._update()},addTo:function(t){return t.addLayer(this),this},onRemove:function(t){this._container.parentNode.removeChild(this._container),t.off({viewreset:this._resetCallback,moveend:this._update},this),this.options.updateWhenIdle||t.off("move",this._limitedUpdate,this),this._container=null,this._map=null},bringToFront:function(){var t=this._map._panes.tilePane;return this._container&&(t.appendChild(this._container),this._setAutoZIndex(t,Math.max)),this},bringToBack:function(){var t=this._map._panes.tilePane;return this._container&&(t.insertBefore(this._container,t.firstChild),this._setAutoZIndex(t,Math.min)),this},getAttribution:function(){return this.options.attribution},setOpacity:function(t){return this.options.opacity=t,this._map&&this._updateOpacity(),this},setZIndex:function(t){return this.options.zIndex=t,this._updateZIndex(),this},setUrl:function(t,e){r
 eturn this._url=t,e||this.redraw(),this},redraw:function(){return this._map&&(this._map._panes.tilePane.empty=!1,this._reset(!0),this._update()),this},_updateZIndex:function(){this._container&&this.options.zIndex!==i&&(this._container.style.zIndex=this.options.zIndex)},_setAutoZIndex:function(t,e){var i,n,o,s=t.children,a=-e(1/0,-1/0);for(n=0,o=s.length;o>n;n++)s[n]!==this._container&&(i=parseInt(s[n].style.zIndex,10),isNaN(i)||(a=e(a,i)));this.options.zIndex=this._container.style.zIndex=(isFinite(a)?a:0)+e(1,-1)},_updateOpacity:function(){n.DomUtil.setOpacity(this._container,this.options.opacity);var t,e=this._tiles;if(n.Browser.webkit)for(t in e)e.hasOwnProperty(t)&&(e[t].style.webkitTransform+=" translate(0,0)")},_initContainer:function(){var t=this._map._panes.tilePane;(!this._container||t.empty)&&(this._container=n.DomUtil.create("div","leaflet-layer"),this._updateZIndex(),t.appendChild(this._container),1>this.options.opacity&&this._updateOpacity())},_resetCallback:function(t){
 this._reset(t.hard)},_reset:function(t){var e=this._tiles;for(var i in e)e.hasOwnProperty(i)&&this.fire("tileunload",{tile:e[i]});this._tiles={},this._tilesToLoad=0,this.options.reuseTiles&&(this._unusedTiles=[]),t&&this._container&&(this._container.innerHTML=""),this._initContainer()},_update:function(){if(this._map){var t=this._map.getPixelBounds(),e=this._map.getZoom(),i=this.options.tileSize;if(!(e>this.options.maxZoom||this.options.minZoom>e)){var o=new n.Point(Math.floor(t.min.x/i),Math.floor(t.min.y/i)),s=new n.Point(Math.floor(t.max.x/i),Math.floor(t.max.y/i)),a=new n.Bounds(o,s);this._addTilesFromCenterOut(a),(this.options.unloadInvisibleTiles||this.options.reuseTiles)&&this._removeOtherTiles(a)}}},_addTilesFromCenterOut:function(t){var i,o,s,a=[],r=t.getCenter();for(i=t.min.y;t.max.y>=i;i++)for(o=t.min.x;t.max.x>=o;o++)s=new n.Point(o,i),this._tileShouldBeLoaded(s)&&a.push(s);var h=a.length;if(0!==h){a.sort(function(t,e){return t.distanceTo(r)-e.distanceTo(r)});var l=e.cre
 ateDocumentFragment();for(this._tilesToLoad||this.fire("loading"),this._tilesToLoad+=h,o=0;h>o;o++)this._addTile(a[o],l);this._container.appendChild(l)}},_tileShouldBeLoaded:function(t){if(t.x+":"+t.y in this._tiles)return!1;if(!this.options.continuousWorld){var e=this._getWrapTileNum();if(this.options.noWrap&&(0>t.x||t.x>=e)||0>t.y||t.y>=e)return!1}return!0},_removeOtherTiles:function(t){var e,i,n,o;for(o in this._tiles)this._tiles.hasOwnProperty(o)&&(e=o.split(":"),i=parseInt(e[0],10),n=parseInt(e[1],10),(t.min.x>i||i>t.max.x||t.min.y>n||n>t.max.y)&&this._removeTile(o))},_removeTile:function(t){var e=this._tiles[t];this.fire("tileunload",{tile:e,url:e.src}),this.options.reuseTiles?(n.DomUtil.removeClass(e,"leaflet-tile-loaded"),this._unusedTiles.push(e)):e.parentNode===this._container&&this._container.removeChild(e),n.Browser.android||(e.src=n.Util.emptyImageUrl),delete this._tiles[t]},_addTile:function(t,e){var i=this._getTilePos(t),o=this._getTile();n.DomUtil.setPosition(o,i,n.B
 rowser.chrome||n.Browser.android23),this._tiles[t.x+":"+t.y]=o,this._loadTile(o,t),o.parentNode!==this._container&&e.appendChild(o)
+},_getZoomForUrl:function(){var t=this.options,e=this._map.getZoom();return t.zoomReverse&&(e=t.maxZoom-e),e+t.zoomOffset},_getTilePos:function(t){var e=this._map.getPixelOrigin(),i=this.options.tileSize;return t.multiplyBy(i).subtract(e)},getTileUrl:function(t){return this._adjustTilePoint(t),n.Util.template(this._url,n.extend({s:this._getSubdomain(t),z:this._getZoomForUrl(),x:t.x,y:t.y},this.options))},_getWrapTileNum:function(){return Math.pow(2,this._getZoomForUrl())},_adjustTilePoint:function(t){var e=this._getWrapTileNum();this.options.continuousWorld||this.options.noWrap||(t.x=(t.x%e+e)%e),this.options.tms&&(t.y=e-t.y-1)},_getSubdomain:function(t){var e=(t.x+t.y)%this.options.subdomains.length;return this.options.subdomains[e]},_createTileProto:function(){var t=this._tileImg=n.DomUtil.create("img","leaflet-tile");t.style.width=t.style.height=this.options.tileSize+"px",t.galleryimg="no"},_getTile:function(){if(this.options.reuseTiles&&this._unusedTiles.length>0){var t=this._un
 usedTiles.pop();return this._resetTile(t),t}return this._createTile()},_resetTile:function(){},_createTile:function(){var t=this._tileImg.cloneNode(!1);return t.onselectstart=t.onmousemove=n.Util.falseFn,t},_loadTile:function(t,e){t._layer=this,t.onload=this._tileOnLoad,t.onerror=this._tileOnError,t.src=this.getTileUrl(e)},_tileLoaded:function(){this._tilesToLoad--,this._tilesToLoad||this.fire("load")},_tileOnLoad:function(){var t=this._layer;this.src!==n.Util.emptyImageUrl&&(n.DomUtil.addClass(this,"leaflet-tile-loaded"),t.fire("tileload",{tile:this,url:this.src})),t._tileLoaded()},_tileOnError:function(){var t=this._layer;t.fire("tileerror",{tile:this,url:this.src});var e=t.options.errorTileUrl;e&&(this.src=e),t._tileLoaded()}}),n.tileLayer=function(t,e){return new n.TileLayer(t,e)},n.TileLayer.WMS=n.TileLayer.extend({defaultWmsParams:{service:"WMS",request:"GetMap",version:"1.1.1",layers:"",styles:"",format:"image/jpeg",transparent:!1},initialize:function(t,e){this._url=t;var i=n
 .extend({},this.defaultWmsParams);i.width=i.height=e.detectRetina&&n.Browser.retina?2*this.options.tileSize:this.options.tileSize;for(var o in e)this.options.hasOwnProperty(o)||(i[o]=e[o]);this.wmsParams=i,n.setOptions(this,e)},onAdd:function(t){var e=parseFloat(this.wmsParams.version)>=1.3?"crs":"srs";this.wmsParams[e]=t.options.crs.code,n.TileLayer.prototype.onAdd.call(this,t)},getTileUrl:function(t,e){this._adjustTilePoint(t);var i=this._map,o=i.options.crs,s=this.options.tileSize,a=t.multiplyBy(s),r=a.add(new n.Point(s,s)),h=o.project(i.unproject(a,e)),l=o.project(i.unproject(r,e)),u=[h.x,l.y,l.x,h.y].join(","),c=n.Util.template(this._url,{s:this._getSubdomain(t)});return c+n.Util.getParamString(this.wmsParams,c)+"&bbox="+u},setParams:function(t,e){return n.extend(this.wmsParams,t),e||this.redraw(),this}}),n.tileLayer.wms=function(t,e){return new n.TileLayer.WMS(t,e)},n.TileLayer.Canvas=n.TileLayer.extend({options:{async:!1},initialize:function(t){n.setOptions(this,t)},redraw:fu
 nction(){var t=this._tiles;for(var e in t)t.hasOwnProperty(e)&&this._redrawTile(t[e])},_redrawTile:function(t){this.drawTile(t,t._tilePoint,this._map._zoom)},_createTileProto:function(){var t=this._canvasProto=n.DomUtil.create("canvas","leaflet-tile");t.width=t.height=this.options.tileSize},_createTile:function(){var t=this._canvasProto.cloneNode(!1);return t.onselectstart=t.onmousemove=n.Util.falseFn,t},_loadTile:function(t,e){t._layer=this,t._tilePoint=e,this._redrawTile(t),this.options.async||this.tileDrawn(t)},drawTile:function(){},tileDrawn:function(t){this._tileOnLoad.call(t)}}),n.tileLayer.canvas=function(t){return new n.TileLayer.Canvas(t)},n.ImageOverlay=n.Class.extend({includes:n.Mixin.Events,options:{opacity:1},initialize:function(t,e,i){this._url=t,this._bounds=n.latLngBounds(e),n.setOptions(this,i)},onAdd:function(t){this._map=t,this._image||this._initImage(),t._panes.overlayPane.appendChild(this._image),t.on("viewreset",this._reset,this),t.options.zoomAnimation&&n.Brow
 ser.any3d&&t.on("zoomanim",this._animateZoom,this),this._reset()},onRemove:function(t){t.getPanes().overlayPane.removeChild(this._image),t.off("viewreset",this._reset,this),t.options.zoomAnimation&&t.off("zoomanim",this._animateZoom,this)},addTo:function(t){return t.addLayer(this),this},setOpacity:function(t){return this.options.opacity=t,this._updateOpacity(),this},bringToFront:function(){return this._image&&this._map._panes.overlayPane.appendChild(this._image),this},bringToBack:function(){var t=this._map._panes.overlayPane;return this._image&&t.insertBefore(this._image,t.firstChild),this},_initImage:function(){this._image=n.DomUtil.create("img","leaflet-image-layer"),this._map.options.zoomAnimation&&n.Browser.any3d?n.DomUtil.addClass(this._image,"leaflet-zoom-animated"):n.DomUtil.addClass(this._image,"leaflet-zoom-hide"),this._updateOpacity(),n.extend(this._image,{galleryimg:"no",onselectstart:n.Util.falseFn,onmousemove:n.Util.falseFn,onload:n.bind(this._onImageLoad,this),src:this
 ._url})},_animateZoom:function(t){var e=this._map,i=this._image,o=e.getZoomScale(t.zoom),s=this._bounds.getNorthWest(),a=this._bounds.getSouthEast(),r=e._latLngToNewLayerPoint(s,t.zoom,t.center),h=e._latLngToNewLayerPoint(a,t.zoom,t.center)._subtract(r),l=r._add(h._multiplyBy(.5*(1-1/o)));i.style[n.DomUtil.TRANSFORM]=n.DomUtil.getTranslateString(l)+" scale("+o+") "},_reset:function(){var t=this._image,e=this._map.latLngToLayerPoint(this._bounds.getNorthWest()),i=this._map.latLngToLayerPoint(this._bounds.getSouthEast())._subtract(e);n.DomUtil.setPosition(t,e),t.style.width=i.x+"px",t.style.height=i.y+"px"},_onImageLoad:function(){this.fire("load")},_updateOpacity:function(){n.DomUtil.setOpacity(this._image,this.options.opacity)}}),n.imageOverlay=function(t,e,i){return new n.ImageOverlay(t,e,i)},n.Icon=n.Class.extend({options:{className:""},initialize:function(t){n.setOptions(this,t)},createIcon:function(){return this._createIcon("icon")},createShadow:function(){return this._createIco
 n("shadow")},_createIcon:function(t){var e=this._getIconUrl(t);if(!e){if("icon"===t)throw Error("iconUrl not set in Icon options (see the docs).");return null}var i=this._createImg(e);return this._setIconStyles(i,t),i},_setIconStyles:function(t,e){var i,o=this.options,s=n.point(o[e+"Size"]);i="shadow"===e?n.point(o.shadowAnchor||o.iconAnchor):n.point(o.iconAnchor),!i&&s&&(i=s.divideBy(2,!0)),t.className="leaflet-marker-"+e+" "+o.className,i&&(t.style.marginLeft=-i.x+"px",t.style.marginTop=-i.y+"px"),s&&(t.style.width=s.x+"px",t.style.height=s.y+"px")},_createImg:function(t){var i;return n.Browser.ie6?(i=e.createElement("div"),i.style.filter='progid:DXImageTransform.Microsoft.AlphaImageLoader(src="'+t+'")'):(i=e.createElement("img"),i.src=t),i},_getIconUrl:function(t){return n.Browser.retina&&this.options[t+"RetinaUrl"]?this.options[t+"RetinaUrl"]:this.options[t+"Url"]}}),n.icon=function(t){return new n.Icon(t)},n.Icon.Default=n.Icon.extend({options:{iconSize:new n.Point(25,41),iconA
 nchor:new n.Point(12,41),popupAnchor:new n.Point(1,-34),shadowSize:new n.Point(41,41)},_getIconUrl:function(t){var e=t+"Url";if(this.options[e])return this.options[e];n.Browser.retina&&"icon"===t&&(t+="@2x");var i=n.Icon.Default.imagePath;if(!i)throw Error("Couldn't autodetect L.Icon.Default.imagePath, set it manually.");return i+"/marker-"+t+".png"}}),n.Icon.Default.imagePath=function(){var t,i,n,o,s=e.getElementsByTagName("script"),a=/\/?leaflet[\-\._]?([\w\-\._]*)\.js\??/;for(t=0,i=s.length;i>t;t++)if(n=s[t].src,o=n.match(a))return n.split(a)[0]+"/images"}(),n.Marker=n.Class.extend({includes:n.Mixin.Events,options:{icon:new n.Icon.Default,title:"",clickable:!0,draggable:!1,zIndexOffset:0,opacity:1,riseOnHover:!1,riseOffset:250},initialize:function(t,e){n.setOptions(this,e),this._latlng=n.latLng(t)},onAdd:function(t){this._map=t,t.on("viewreset",this.update,this),this._initIcon(),this.update(),t.options.zoomAnimation&&t.options.markerZoomAnimation&&t.on("zoomanim",this._animateZoo
 m,this)},addTo:function(t){return t.addLayer(this),this},onRemove:function(t){this._removeIcon(),this.fire("remove"),t.off({viewreset:this.update,zoomanim:this._animateZoom},this),this._map=null},getLatLng:function(){return this._latlng},setLatLng:function(t){return this._latlng=n.latLng(t),this.update(),this.fire("move",{latlng:this._latlng})},setZIndexOffset:function(t){return this.options.zIndexOffset=t,this.update(),this},setIcon:function(t){return this._map&&this._removeIcon(),this.options.icon=t,this._map&&(this._initIcon(),this.update()),this},update:function(){if(this._icon){var t=this._map.latLngToLayerPoint(this._latlng).round();this._setPos(t)}return this},_initIcon:function(){var t=this.options,e=this._map,i=e.options.zoomAnimation&&e.options.markerZoomAnimation,o=i?"leaflet-zoom-animated":"leaflet-zoom-hide",s=!1;this._icon||(this._icon=t.icon.createIcon(),t.title&&(this._icon.title=t.title),this._initInteraction(),s=1>this.options.opacity,n.DomUtil.addClass(this._icon,
 o),t.riseOnHover&&n.DomEvent.on(this._icon,"mouseover",this._bringToFront,this).on(this._icon,"mouseout",this._resetZIndex,this)),this._shadow||(this._shadow=t.icon.createShadow(),this._shadow&&(n.DomUtil.addClass(this._shadow,o),s=1>this.options.opacity)),s&&this._updateOpacity();var a=this._map._panes;a.markerPane.appendChild(this._icon),this._shadow&&a.shadowPane.appendChild(this._shadow)},_removeIcon:function(){var t=this._map._panes;this.options.riseOnHover&&n.DomEvent.off(this._icon,"mouseover",this._bringToFront).off(this._icon,"mouseout",this._resetZIndex),t.markerPane.removeChild(this._icon),this._shadow&&t.shadowPane.removeChild(this._shadow),this._icon=this._shadow=null},_setPos:function(t){n.DomUtil.setPosition(this._icon,t),this._shadow&&n.DomUtil.setPosition(this._shadow,t),this._zIndex=t.y+this.options.zIndexOffset,this._resetZIndex()},_updateZIndex:function(t){this._icon.style.zIndex=this._zIndex+t},_animateZoom:function(t){var e=this._map._latLngToNewLayerPoint(this
 ._latlng,t.zoom,t.center);this._setPos(e)},_initInteraction:function(){if(this.options.clickable){var t=this._icon,e=["dblclick","mousedown","mouseover","mouseout","contextmenu"];n.DomUtil.addClass(t,"leaflet-clickable"),n.DomEvent.on(t,"click",this._onMouseClick,this);for(var i=0;e.length>i;i++)n.DomEvent.on(t,e[i],this._fireMouseEvent,this);n.Handler.MarkerDrag&&(this.dragging=new n.Handler.MarkerDrag(this),this.options.draggable&&this.dragging.enable())}},_onMouseClick:function(t){var e=this.dragging&&this.dragging.moved();(this.hasEventListeners(t.type)||e)&&n.DomEvent.stopPropagation(t),e||(this.dragging&&this.dragging._enabled||!this._map.dragging||!this._map.dragging.moved())&&this.fire(t.type,{originalEvent:t})},_fireMouseEvent:function(t){this.fire(t.type,{originalEvent:t}),"contextmenu"===t.type&&this.hasEventListeners(t.type)&&n.DomEvent.preventDefault(t),"mousedown"!==t.type&&n.DomEvent.stopPropagation(t)},setOpacity:function(t){this.options.opacity=t,this._map&&this._up
 dateOpacity()},_updateOpacity:function(){n.DomUtil.setOpacity(this._icon,this.options.opacity),this._shadow&&n.DomUtil.setOpacity(this._shadow,this.options.opacity)},_bringToFront:function(){this._updateZIndex(this.options.riseOffset)},_resetZIndex:function(){this._updateZIndex(0)}}),n.marker=function(t,e){return new n.Marker(t,e)},n.DivIcon=n.Icon.extend({options:{iconSize:new n.Point(12,12),className:"leaflet-div-icon"},createIcon:function(){var t=e.createElement("div"),i=this.options;return i.html&&(t.innerHTML=i.html),i.bgPos&&(t.style.backgroundPosition=-i.bgPos.x+"px "+-i.bgPos.y+"px"),this._setIconStyles(t,"icon"),t},createShadow:function(){return null}}),n.divIcon=function(t){return new n.DivIcon(t)},n.Map.mergeOptions({closePopupOnClick:!0}),n.Popup=n.Class.extend({includes:n.Mixin.Events,options:{minWidth:50,maxWidth:300,maxHeight:null,autoPan:!0,closeButton:!0,offset:new n.Point(0,6),autoPanPadding:new n.Point(5,5),className:"",zoomAnimation:!0},initialize:function(t,e){n
 .setOptions(this,t),this._source=e,this._animated=n.Browser.any3d&&this.options.zoomAnimation},onAdd:function(t){this._map=t,this._container||this._initLayout(),this._updateContent();var e=t.options.fadeAnimation;e&&n.DomUtil.setOpacity(this._container,0),t._panes.popupPane.appendChild(this._container),t.on("viewreset",this._updatePosition,this),this._animated&&t.on("zoomanim",this._zoomAnimation,this),t.options.closePopupOnClick&&t.on("preclick",this._close,this),this._update(),e&&n.DomUtil.setOpacity(this._container,1)},addTo:function(t){return t.addLayer(this),this},openOn:function(t){return t.openPopup(this),this},onRemove:function(t){t._panes.popupPane.removeChild(this._container),n.Util.falseFn(this._container.offsetWidth),t.off({viewreset:this._updatePosition,preclick:this._close,zoomanim:this._zoomAnimation},this),t.options.fadeAnimation&&n.DomUtil.setOpacity(this._container,0),this._map=null},setLatLng:function(t){return this._latlng=n.latLng(t),this._update(),this},setCont
 ent:function(t){return this._content=t,this._update(),this},_close:function(){var t=this._map;t&&(t._popup=null,t.removeLayer(this).fire("popupclose",{popup:this}))},_initLayout:function(){var t,e="leaflet-popup",i=e+" "+this.options.className+" leaflet-zoom-"+(this._animated?"animated":"hide"),o=this._container=n.DomUtil.create("div",i);this.options.closeButton&&(t=this._closeButton=n.DomUtil.create("a",e+"-close-button",o),t.href="#close",t.innerHTML="&#215;",n.DomEvent.on(t,"click",this._onCloseButtonClick,this));var s=this._wrapper=n.DomUtil.create("div",e+"-content-wrapper",o);n.DomEvent.disableClickPropagation(s),this._contentNode=n.DomUtil.create("div",e+"-content",s),n.DomEvent.on(this._contentNode,"mousewheel",n.DomEvent.stopPropagation),this._tipContainer=n.DomUtil.create("div",e+"-tip-container",o),this._tip=n.DomUtil.create("div",e+"-tip",this._tipContainer)},_update:function(){this._map&&(this._container.style.visibility="hidden",this._updateContent(),this._updateLayout
 (),this._updatePosition(),this._container.style.visibility="",this._adjustPan())},_updateContent:function(){if(this._content){if("string"==typeof this._content)this._contentNode.innerHTML=this._content;else{for(;this._contentNode.hasChildNodes();)this._contentNode.removeChild(this._contentNode.firstChild);this._contentNode.appendChild(this._content)}this.fire("contentupdate")}},_updateLayout:function(){var t=this._contentNode,e=t.style;e.width="",e.whiteSpace="nowrap";var i=t.offsetWidth;i=Math.min(i,this.options.maxWidth),i=Math.max(i,this.options.minWidth),e.width=i+1+"px",e.whiteSpace="",e.height="";var o=t.offsetHeight,s=this.options.maxHeight,a="leaflet-popup-scrolled";s&&o>s?(e.height=s+"px",n.DomUtil.addClass(t,a)):n.DomUtil.removeClass(t,a),this._containerWidth=this._container.offsetWidth},_updatePosition:function(){if(this._map){var t=this._map.latLngToLayerPoint(this._latlng),e=this._animated,i=this.options.offset;e&&n.DomUtil.setPosition(this._container,t),this._container
 Bottom=-i.y-(e?0:t.y),this._containerLeft=-Math.round(this._containerWidth/2)+i.x+(e?0:t.x),this._container.style.bottom=this._containerBottom+"px",this._container.style.left=this._containerLeft+"px"}},_zoomAnimation:function(t){var e=this._map._latLngToNewLayerPoint(this._latlng,t.zoom,t.center);n.DomUtil.setPosition(this._container,e)},_adjustPan:function(){if(this.options.autoPan){var t=this._map,e=this._container.offsetHeight,i=this._containerWidth,o=new n.Point(this._containerLeft,-e-this._containerBottom);this._animated&&o._add(n.DomUtil.getPosition(this._container));var s=t.layerPointToContainerPoint(o),a=this.options.autoPanPadding,r=t.getSize(),h=0,l=0;0>s.x&&(h=s.x-a.x),s.x+i>r.x&&(h=s.x+i-r.x+a.x),0>s.y&&(l=s.y-a.y),s.y+e>r.y&&(l=s.y+e-r.y+a.y),(h||l)&&t.panBy(new n.Point(h,l))}},_onCloseButtonClick:function(t){this._close(),n.DomEvent.stop(t)}}),n.popup=function(t,e){return new n.Popup(t,e)},n.Marker.include({openPopup:function(){return this._popup&&this._map&&(this._pop
 up.setLatLng(this._latlng),this._map.openPopup(this._popup)),this},closePopup:function(){return this._popup&&this._popup._close(),this},bindPopup:function(t,e){var i=n.point(this.options.icon.options.popupAnchor)||new n.Point(0,0);return i=i.add(n.Popup.prototype.options.offset),e&&e.offset&&(i=i.add(e.offset)),e=n.extend({offset:i},e),this._popup||this.on("click",this.openPopup,this).on("remove",this.closePopup,this).on("move",this._movePopup,this),this._popup=new n.Popup(e,this).setContent(t),this},unbindPopup:function(){return this._popup&&(this._popup=null,this.off("click",this.openPopup).off("remove",this.closePopup).off("move",this._movePopup)),this},_movePopup:function(t){this._popup.setLatLng(t.latlng)}}),n.Map.include({openPopup:function(t){return this.closePopup(),this._popup=t,this.addLayer(t).fire("popupopen",{popup:this._popup})},closePopup:function(){return this._popup&&this._popup._close(),this}}),n.LayerGroup=n.Class.extend({initialize:function(t){this._layers={};var
  e,i;if(t)for(e=0,i=t.length;i>e;e++)this.addLayer(t[e])},addLayer:function(t){var e=n.stamp(t);return this._layers[e]=t,this._map&&this._map.addLayer(t),this},removeLayer:function(t){var e=n.stamp(t);return delete this._layers[e],this._map&&this._map.removeLayer(t),this},clearLayers:function(){return this.eachLayer(this.removeLayer,this),this},invoke:function(t){var e,i,n=Array.prototype.slice.call(arguments,1);for(e in this._layers)this._layers.hasOwnProperty(e)&&(i=this._layers[e],i[t]&&i[t].apply(i,n));return this},onAdd:function(t){this._map=t,this.eachLayer(t.addLayer,t)},onRemove:function(t){this.eachLayer(t.removeLayer,t),this._map=null},addTo:function(t){return t.addLayer(this),this},eachLayer:function(t,e){for(var i in this._layers)this._layers.hasOwnProperty(i)&&t.call(e,this._layers[i])},setZIndex:function(t){return this.invoke("setZIndex",t)}}),n.layerGroup=function(t){return new n.LayerGroup(t)},n.FeatureGroup=n.LayerGroup.extend({includes:n.Mixin.Events,statics:{EVENT
 S:"click dblclick mouseover mouseout mousemove contextmenu"},addLayer:function(t){return this._layers[n.stamp(t)]?this:(t.on(n.FeatureGroup.EVENTS,this._propagateEvent,this),n.LayerGroup.prototype.addLayer.call(this,t),this._popupContent&&t.bindPopup&&t.bindPopup(this._popupContent,this._popupOptions),this.fire("layeradd",{layer:t}))},removeLayer:function(t){return t.off(n.FeatureGroup.EVENTS,this._propagateEvent,this),n.LayerGroup.prototype.removeLayer.call(this,t),this._popupContent&&this.invoke("unbindPopup"),this.fire("layerremove",{layer:t})},bindPopup:function(t,e){return this._popupContent=t,this._popupOptions=e,this.invoke("bindPopup",t,e)},setStyle:function(t){return this.invoke("setStyle",t)},bringToFront:function(){return this.invoke("bringToFront")},bringToBack:function(){return this.invoke("bringToBack")},getBounds:function(){var t=new n.LatLngBounds;return this.eachLayer(function(e){t.extend(e instanceof n.Marker?e.getLatLng():e.getBounds())}),t},_propagateEvent:functi
 on(t){t.layer=t.target,t.target=this,this.fire(t.type,t)}}),n.featureGroup=function(t){return new n.FeatureGroup(t)},n.Path=n.Class.extend({includes:[n.Mixin.Events],statics:{CLIP_PADDING:n.Browser.mobile?Math.max(0,Math.min(.5,(1280/Math.max(t.innerWidth,t.innerHeight)-1)/2)):.5},options:{stroke:!0,color:"#0033ff",dashArray:null,weight:5,opacity:.5,fill:!1,fillColor:null,fillOpacity:.2,clickable:!0},initialize:function(t){n.setOptions(this,t)},onAdd:function(t){this._map=t,this._container||(this._initElements(),this._initEvents()),this.projectLatlngs(),this._updatePath(),this._container&&this._map._pathRoot.appendChild(this._container),this.fire("add"),t.on({viewreset:this.projectLatlngs,moveend:this._updatePath},this)},addTo:function(t){return t.addLayer(this),this},onRemove:function(t){t._pathRoot.removeChild(this._container),this.fire("remove"),this._map=null,n.Browser.vml&&(this._container=null,this._stroke=null,this._fill=null),t.off({viewreset:this.projectLatlngs,moveend:this
 ._updatePath},this)},projectLatlngs:function(){},setStyle:function(t){return n.setOptions(this,t),this._container&&this._updateStyle(),this},redraw:function(){return this._map&&(this.projectLatlngs(),this._updatePath()),this}}),n.Map.include({_updatePathViewport:function(){var t=n.Path.CLIP_PADDING,e=this.getSize(),i=n.DomUtil.getPosition(this._mapPane),o=i.multiplyBy(-1)._subtract(e.multiplyBy(t)._round()),s=o.add(e.multiplyBy(1+2*t)._round());this._pathViewport=new n.Bounds(o,s)}}),n.Path.SVG_NS="http://www.w3.org/2000/svg",n.Browser.svg=!(!e.createElementNS||!e.createElementNS(n.Path.SVG_NS,"svg").createSVGRect),n.Path=n.Path.extend({statics:{SVG:n.Browser.svg},bringToFront:function(){var t=this._map._pathRoot,e=this._container;return e&&t.lastChild!==e&&t.appendChild(e),this},bringToBack:function(){var t=this._map._pathRoot,e=this._container,i=t.firstChild;return e&&i!==e&&t.insertBefore(e,i),this},getPathString:function(){},_createElement:function(t){return e.createElementNS(n.
 Path.SVG_NS,t)},_initElements:function(){this._map._initPathRoot(),this._initPath(),this._initStyle()},_initPath:function(){this._container=this._createElement("g"),this._path=this._createElement("path"),this._container.appendChild(this._path)},_initStyle:function(){this.options.stroke&&(this._path.setAttribute("stroke-linejoin","round"),this._path.setAttribute("stroke-linecap","round")),this.options.fill&&this._path.setAttribute("fill-rule","evenodd"),this._updateStyle()},_updateStyle:function(){this.options.stroke?(this._path.setAttribute("stroke",this.options.color),this._path.setAttribute("stroke-opacity",this.options.opacity),this._path.setAttribute("stroke-width",this.options.weight),this.options.dashArray?this._path.setAttribute("stroke-dasharray",this.options.dashArray):this._path.removeAttribute("stroke-dasharray")):this._path.setAttribute("stroke","none"),this.options.fill?(this._path.setAttribute("fill",this.options.fillColor||this.options.color),this._path.setAttribute("
 fill-opacity",this.options.fillOpacity)):this._path.setAttribute("fill","none")},_updatePath:function(){var t=this.getPathString();t||(t="M0 0"),this._path.setAttribute("d",t)},_initEvents:function(){if(this.options.clickable){(n.Browser.svg||!n.Browser.vml)&&this._path.setAttribute("class","leaflet-clickable"),n.DomEvent.on(this._container,"click",this._onMouseClick,this);for(var t=["dblclick","mousedown","mouseover","mouseout","mousemove","contextmenu"],e=0;t.length>e;e++)n.DomEvent.on(this._container,t[e],this._fireMouseEvent,this)}},_onMouseClick:function(t){this._map.dragging&&this._map.dragging.moved()||this._fireMouseEvent(t)},_fireMouseEvent:function(t){if(this.hasEventListeners(t.type)){var e=this._map,i=e.mouseEventToContainerPoint(t),o=e.containerPointToLayerPoint(i),s=e.layerPointToLatLng(o);this.fire(t.type,{latlng:s,layerPoint:o,containerPoint:i,originalEvent:t}),"contextmenu"===t.type&&n.DomEvent.preventDefault(t),"mousemove"!==t.type&&n.DomEvent.stopPropagation(t)}}}
 ),n.Map.include({_initPathRoot:function(){this._pathRoot||(this._pathRoot=n.Path.prototype._createElement("svg"),this._panes.overlayPane.appendChild(this._pathRoot),this.options.zoomAnimation&&n.Browser.any3d?(this._pathRoot.setAttribute("class"," leaflet-zoom-animated"),this.on({zoomanim:this._animatePathZoom,zoomend:this._endPathZoom})):this._pathRoot.setAttribute("class"," leaflet-zoom-hide"),this.on("moveend",this._updateSvgViewport),this._updateSvgViewport())},_animatePathZoom:function(t){var e=this.getZoomScale(t.zoom),i=this._getCenterOffset(t.center)._multiplyBy(-e)._add(this._pathViewport.min);this._pathRoot.style[n.DomUtil.TRANSFORM]=n.DomUtil.getTranslateString(i)+" scale("+e+") ",this._pathZooming=!0},_endPathZoom:function(){this._pathZooming=!1},_updateSvgViewport:function(){if(!this._pathZooming){this._updatePathViewport();var t=this._pathViewport,e=t.min,i=t.max,o=i.x-e.x,s=i.y-e.y,a=this._pathRoot,r=this._panes.overlayPane;n.Browser.mobileWebkit&&r.removeChild(a),n.D
 omUtil.setPosition(a,e),a.setAttribute("width",o),a.setAttribute("height",s),a.setAttribute("viewBox",[e.x,e.y,o,s].join(" ")),n.Browser.mobileWebkit&&r.appendChild(a)}}}),n.Path.include({bindPopup:function(t,e){return(!this._popup||e)&&(this._popup=new n.Popup(e,this)),this._popup.setContent(t),this._popupHandlersAdded||(this.on("click",this._openPopup,this).on("remove",this.closePopup,this),this._popupHandlersAdded=!0),this},unbindPopup:function(){return this._popup&&(this._popup=null,this.off("click",this._openPopup).off("remove",this.closePopup),this._popupHandlersAdded=!1),this},openPopup:function(t){return this._popup&&(t=t||this._latlng||this._latlngs[Math.floor(this._latlngs.length/2)],this._openPopup({latlng:t})),this},closePopup:function(){return this._popup&&this._popup._close(),this},_openPopup:function(t){this._popup.setLatLng(t.latlng),this._map.openPopup(this._popup)}}),n.Browser.vml=!n.Browser.svg&&function(){try{var t=e.createElement("div");t.innerHTML='<v:shape adj
 ="1"/>';var i=t.firstChild;return i.style.behavior="url(#default#VML)",i&&"object"==typeof i.adj}catch(n){return!1}}(),n.Path=n.Browser.svg||!n.Browser.vml?n.Path:n.Path.extend({statics:{VML:!0,CLIP_PADDING:.02},_createElement:function(){try{return e.namespaces.add("lvml","urn:schemas-microsoft-com:vml"),function(t){return e.createElement("<lvml:"+t+' class="lvml">')}}catch(t){return function(t){return e.createElement("<"+t+' xmlns="urn:schemas-microsoft.com:vml" class="lvml">')}}}(),_initPath:function(){var t=this._container=this._createElement("shape");n.DomUtil.addClass(t,"leaflet-vml-shape"),this.options.clickable&&n.DomUtil.addClass(t,"leaflet-clickable"),t.coordsize="1 1",this._path=this._createElement("path"),t.appendChild(this._path),this._map._pathRoot.appendChild(t)},_initStyle:function(){this._updateStyle()},_updateStyle:function(){var t=this._stroke,e=this._fill,i=this.options,n=this._container;n.stroked=i.stroke,n.filled=i.fill,i.stroke?(t||(t=this._stroke=this._createE
 lement("stroke"),t.endcap="round",n.appendChild(t)),t.weight=i.weight+"px",t.color=i.color,t.opacity=i.opacity,t.dashStyle=i.dashArray?i.dashArray instanceof Array?i.dashArray.join(" "):i.dashArray.replace(/ *, */g," "):""):t&&(n.removeChild(t),this._stroke=null),i.fill?(e||(e=this._fill=this._createElement("fill"),n.appendChild(e)),e.color=i.fillColor||i.color,e.opacity=i.fillOpacity):e&&(n.removeChild(e),this._fill=null)},_updatePath:function(){var t=this._container.style;t.display="none",this._path.v=this.getPathString()+" ",t.display=""}}),n.Map.include(n.Browser.svg||!n.Browser.vml?{}:{_initPathRoot:function(){if(!this._pathRoot){var t=this._pathRoot=e.createElement("div");t.className="leaflet-vml-container",this._panes.overlayPane.appendChild(t),this.on("moveend",this._updatePathViewport),this._updatePathViewport()}}}),n.Browser.canvas=function(){return!!e.createElement("canvas").getContext}(),n.Path=n.Path.SVG&&!t.L_PREFER_CANVAS||!n.Browser.canvas?n.Path:n.Path.extend({stati
 cs:{CANVAS:!0,SVG:!1},redraw:function(){return this._map&&(this.projectLatlngs(),this._requestUpdate()),this},setStyle:function(t){return n.setOptions(this,t),this._map&&(this._updateStyle(),this._requestUpdate()),this},onRemove:function(t){t.off("viewreset",this.projectLatlngs,this).off("moveend",this._updatePath,this),this.options.clickable&&this._map.off("click",this._onClick,this),this._requestUpdate(),this._map=null},_requestUpdate:function(){this._map&&!n.Path._updateRequest&&(n.Path._updateRequest=n.Util.requestAnimFrame(this._fireMapMoveEnd,this._map))},_fireMapMoveEnd:function(){n.Path._updateRequest=null,this.fire("moveend")},_initElements:function(){this._map._initPathRoot(),this._ctx=this._map._canvasCtx},_updateStyle:function(){var t=this.options;t.stroke&&(this._ctx.lineWidth=t.weight,this._ctx.strokeStyle=t.color),t.fill&&(this._ctx.fillStyle=t.fillColor||t.color)},_drawPath:function(){var t,e,i,o,s,a;for(this._ctx.beginPath(),t=0,i=this._parts.length;i>t;t++){for(e=0
 ,o=this._parts[t].length;o>e;e++)s=this._parts[t][e],a=(0===e?"move":"line")+"To",this._ctx[a](s.x,s.y);this instanceof n.Polygon&&this._ctx.closePath()}},_checkIfEmpty:function(){return!this._parts.length},_updatePath:function(){if(!this._checkIfEmpty()){var t=this._ctx,e=this.options;this._drawPath(),t.save(),this._updateStyle(),e.fill&&(t.globalAlpha=e.fillOpacity,t.fill()),e.stroke&&(t.globalAlpha=e.opacity,t.stroke()),t.restore()}},_initEvents:function(){this.options.clickable&&this._map.on("click",this._onClick,this)},_onClick:function(t){this._containsPoint(t.layerPoint)&&this.fire("click",{latlng:t.latlng,layerPoint:t.layerPoint,containerPoint:t.containerPoint,originalEvent:t})}}),n.Map.include(n.Path.SVG&&!t.L_PREFER_CANVAS||!n.Browser.canvas?{}:{_initPathRoot:function(){var t,i=this._pathRoot;i||(i=this._pathRoot=e.createElement("canvas"),i.style.position="absolute",t=this._canvasCtx=i.getContext("2d"),t.lineCap="round",t.lineJoin="round",this._panes.overlayPane.appendChil
 d(i),this.options.zoomAnimation&&(this._pathRoot.className="leaflet-zoom-animated",this.on("zoomanim",this._animatePathZoom),this.on("zoomend",this._endPathZoom)),this.on("moveend",this._updateCanvasViewport),this._updateCanvasViewport())},_updateCanvasViewport:function(){if(!this._pathZooming){this._updatePathViewport();var t=this._pathViewport,e=t.min,i=t.max.subtract(e),o=this._pathRoot;n.DomUtil.setPosition(o,e),o.width=i.x,o.height=i.y,o.getContext("2d").translate(-e.x,-e.y)}}}),n.LineUtil={simplify:function(t,e){if(!e||!t.length)return t.slice();var i=e*e;return t=this._reducePoints(t,i),t=this._simplifyDP(t,i)},pointToSegmentDistance:function(t,e,i){return Math.sqrt(this._sqClosestPointOnSegment(t,e,i,!0))},closestPointOnSegment:function(t,e,i){return this._sqClosestPointOnSegment(t,e,i)},_simplifyDP:function(t,e){var n=t.length,o=typeof Uint8Array!=i+""?Uint8Array:Array,s=new o(n);s[0]=s[n-1]=1,this._simplifyDPStep(t,s,e,0,n-1);var a,r=[];for(a=0;n>a;a++)s[a]&&r.push(t[a]);r
 eturn r},_simplifyDPStep:function(t,e,i,n,o){var s,a,r,h=0;for(a=n+1;o-1>=a;a++)r=this._sqClosestPointOnSegment(t[a],t[n],t[o],!0),r>h&&(s=a,h=r);h>i&&(e[s]=1,this._simplifyDPStep(t,e,i,n,s),this._simplifyDPStep(t,e,i,s,o))},_reducePoints:function(t,e){for(var i=[t[0]],n=1,o=0,s=t.length;s>n;n++)this._sqDist(t[n],t[o])>e&&(i.push(t[n]),o=n);return s-1>o&&i.push(t[s-1]),i},clipSegment:function(t,e,i,n){var o,s,a,r=n?this._lastCode:this._getBitCode(t,i),h=this._getBitCode(e,i);for(this._lastCode=h;;){if(!(r|h))return[t,e];if(r&h)return!1;o=r||h,s=this._getEdgeIntersection(t,e,o,i),a=this._getBitCode(s,i),o===r?(t=s,r=a):(e=s,h=a)}},_getEdgeIntersection:function(t,e,o,s){var a=e.x-t.x,r=e.y-t.y,h=s.min,l=s.max;return 8&o?new n.Point(t.x+a*(l.y-t.y)/r,l.y):4&o?new n.Point(t.x+a*(h.y-t.y)/r,h.y):2&o?new n.Point(l.x,t.y+r*(l.x-t.x)/a):1&o?new n.Point(h.x,t.y+r*(h.x-t.x)/a):i},_getBitCode:function(t,e){var i=0;return t.x<e.min.x?i|=1:t.x>e.max.x&&(i|=2),t.y<e.min.y?i|=4:t.y>e.max.y&&(i|=8)
 ,i},_sqDist:function(t,e){var i=e.x-t.x,n=e.y-t.y;return i*i+n*n},_sqClosestPointOnSegment:function(t,e,i,o){var s,a=e.x,r=e.y,h=i.x-a,l=i.y-r,u=h*h+l*l;return u>0&&(s=((t.x-a)*h+(t.y-r)*l)/u,s>1?(a=i.x,r=i.y):s>0&&(a+=h*s,r+=l*s)),h=t.x-a,l=t.y-r,o?h*h+l*l:new n.Point(a,r)}},n.Polyline=n.Path.extend({initialize:function(t,e){n.Path.prototype.initialize.call(this,e),this._latlngs=this._convertLatLngs(t)},options:{smoothFactor:1,noClip:!1},projectLatlngs:function(){this._originalPoints=[];for(var t=0,e=this._latlngs.length;e>t;t++)this._originalPoints[t]=this._map.latLngToLayerPoint(this._latlngs[t])},getPathString:function(){for(var t=0,e=this._parts.length,i="";e>t;t++)i+=this._getPathPartStr(this._parts[t]);return i},getLatLngs:function(){return this._latlngs},setLatLngs:function(t){return this._latlngs=this._convertLatLngs(t),this.redraw()},addLatLng:function(t){return this._latlngs.push(n.latLng(t)),this.redraw()},spliceLatLngs:function(){var t=[].splice.apply(this._latlngs,argu
 ments);return this._convertLatLngs(this._latlngs),this.redraw(),t},closestLayerPoint:function(t){for(var e,i,o=1/0,s=this._parts,a=null,r=0,h=s.length;h>r;r++)for(var l=s[r],u=1,c=l.length;c>u;u++){e=l[u-1],i=l[u];
+var _=n.LineUtil._sqClosestPointOnSegment(t,e,i,!0);o>_&&(o=_,a=n.LineUtil._sqClosestPointOnSegment(t,e,i))}return a&&(a.distance=Math.sqrt(o)),a},getBounds:function(){var t,e,i=new n.LatLngBounds,o=this.getLatLngs();for(t=0,e=o.length;e>t;t++)i.extend(o[t]);return i},_convertLatLngs:function(t){var e,i;for(e=0,i=t.length;i>e;e++){if(n.Util.isArray(t[e])&&"number"!=typeof t[e][0])return;t[e]=n.latLng(t[e])}return t},_initEvents:function(){n.Path.prototype._initEvents.call(this)},_getPathPartStr:function(t){for(var e,i=n.Path.VML,o=0,s=t.length,a="";s>o;o++)e=t[o],i&&e._round(),a+=(o?"L":"M")+e.x+" "+e.y;return a},_clipPoints:function(){var t,e,o,s=this._originalPoints,a=s.length;if(this.options.noClip)return this._parts=[s],i;this._parts=[];var r=this._parts,h=this._map._pathViewport,l=n.LineUtil;for(t=0,e=0;a-1>t;t++)o=l.clipSegment(s[t],s[t+1],h,t),o&&(r[e]=r[e]||[],r[e].push(o[0]),(o[1]!==s[t+1]||t===a-2)&&(r[e].push(o[1]),e++))},_simplifyPoints:function(){for(var t=this._parts,e
 =n.LineUtil,i=0,o=t.length;o>i;i++)t[i]=e.simplify(t[i],this.options.smoothFactor)},_updatePath:function(){this._map&&(this._clipPoints(),this._simplifyPoints(),n.Path.prototype._updatePath.call(this))}}),n.polyline=function(t,e){return new n.Polyline(t,e)},n.PolyUtil={},n.PolyUtil.clipPolygon=function(t,e){var i,o,s,a,r,h,l,u,c,_=[1,4,2,8],d=n.LineUtil;for(o=0,l=t.length;l>o;o++)t[o]._code=d._getBitCode(t[o],e);for(a=0;4>a;a++){for(u=_[a],i=[],o=0,l=t.length,s=l-1;l>o;s=o++)r=t[o],h=t[s],r._code&u?h._code&u||(c=d._getEdgeIntersection(h,r,u,e),c._code=d._getBitCode(c,e),i.push(c)):(h._code&u&&(c=d._getEdgeIntersection(h,r,u,e),c._code=d._getBitCode(c,e),i.push(c)),i.push(r));t=i}return t},n.Polygon=n.Polyline.extend({options:{fill:!0},initialize:function(t,e){n.Polyline.prototype.initialize.call(this,t,e),t&&n.Util.isArray(t[0])&&"number"!=typeof t[0][0]&&(this._latlngs=this._convertLatLngs(t[0]),this._holes=t.slice(1))},projectLatlngs:function(){if(n.Polyline.prototype.projectLatln
 gs.call(this),this._holePoints=[],this._holes){var t,e,i,o;for(t=0,i=this._holes.length;i>t;t++)for(this._holePoints[t]=[],e=0,o=this._holes[t].length;o>e;e++)this._holePoints[t][e]=this._map.latLngToLayerPoint(this._holes[t][e])}},_clipPoints:function(){var t=this._originalPoints,e=[];if(this._parts=[t].concat(this._holePoints),!this.options.noClip){for(var i=0,o=this._parts.length;o>i;i++){var s=n.PolyUtil.clipPolygon(this._parts[i],this._map._pathViewport);s.length&&e.push(s)}this._parts=e}},_getPathPartStr:function(t){var e=n.Polyline.prototype._getPathPartStr.call(this,t);return e+(n.Browser.svg?"z":"x")}}),n.polygon=function(t,e){return new n.Polygon(t,e)},function(){function t(t){return n.FeatureGroup.extend({initialize:function(t,e){this._layers={},this._options=e,this.setLatLngs(t)},setLatLngs:function(e){var i=0,n=e.length;for(this.eachLayer(function(t){n>i?t.setLatLngs(e[i++]):this.removeLayer(t)},this);n>i;)this.addLayer(new t(e[i++],this._options));return this}})}n.Mult
 iPolyline=t(n.Polyline),n.MultiPolygon=t(n.Polygon),n.multiPolyline=function(t,e){return new n.MultiPolyline(t,e)},n.multiPolygon=function(t,e){return new n.MultiPolygon(t,e)}}(),n.Rectangle=n.Polygon.extend({initialize:function(t,e){n.Polygon.prototype.initialize.call(this,this._boundsToLatLngs(t),e)},setBounds:function(t){this.setLatLngs(this._boundsToLatLngs(t))},_boundsToLatLngs:function(t){return t=n.latLngBounds(t),[t.getSouthWest(),t.getNorthWest(),t.getNorthEast(),t.getSouthEast()]}}),n.rectangle=function(t,e){return new n.Rectangle(t,e)},n.Circle=n.Path.extend({initialize:function(t,e,i){n.Path.prototype.initialize.call(this,i),this._latlng=n.latLng(t),this._mRadius=e},options:{fill:!0},setLatLng:function(t){return this._latlng=n.latLng(t),this.redraw()},setRadius:function(t){return this._mRadius=t,this.redraw()},projectLatlngs:function(){var t=this._getLngRadius(),e=new n.LatLng(this._latlng.lat,this._latlng.lng-t),i=this._map.latLngToLayerPoint(e);this._point=this._map.la
 tLngToLayerPoint(this._latlng),this._radius=Math.max(Math.round(this._point.x-i.x),1)},getBounds:function(){var t=this._getLngRadius(),e=360*(this._mRadius/40075017),i=this._latlng,o=new n.LatLng(i.lat-e,i.lng-t),s=new n.LatLng(i.lat+e,i.lng+t);return new n.LatLngBounds(o,s)},getLatLng:function(){return this._latlng},getPathString:function(){var t=this._point,e=this._radius;return this._checkIfEmpty()?"":n.Browser.svg?"M"+t.x+","+(t.y-e)+"A"+e+","+e+",0,1,1,"+(t.x-.1)+","+(t.y-e)+" z":(t._round(),e=Math.round(e),"AL "+t.x+","+t.y+" "+e+","+e+" 0,"+23592600)},getRadius:function(){return this._mRadius},_getLatRadius:function(){return 360*(this._mRadius/40075017)},_getLngRadius:function(){return this._getLatRadius()/Math.cos(n.LatLng.DEG_TO_RAD*this._latlng.lat)},_checkIfEmpty:function(){if(!this._map)return!1;var t=this._map._pathViewport,e=this._radius,i=this._point;return i.x-e>t.max.x||i.y-e>t.max.y||i.x+e<t.min.x||i.y+e<t.min.y}}),n.circle=function(t,e,i){return new n.Circle(t,e,i
 )},n.CircleMarker=n.Circle.extend({options:{radius:10,weight:2},initialize:function(t,e){n.Circle.prototype.initialize.call(this,t,null,e),this._radius=this.options.radius},projectLatlngs:function(){this._point=this._map.latLngToLayerPoint(this._latlng)},_updateStyle:function(){n.Circle.prototype._updateStyle.call(this),this.setRadius(this.options.radius)},setRadius:function(t){return this._radius=t,this.redraw()}}),n.circleMarker=function(t,e){return new n.CircleMarker(t,e)},n.Polyline.include(n.Path.CANVAS?{_containsPoint:function(t,e){var i,o,s,a,r,h,l,u=this.options.weight/2;for(n.Browser.touch&&(u+=10),i=0,a=this._parts.length;a>i;i++)for(l=this._parts[i],o=0,r=l.length,s=r-1;r>o;s=o++)if((e||0!==o)&&(h=n.LineUtil.pointToSegmentDistance(t,l[s],l[o]),u>=h))return!0;return!1}}:{}),n.Polygon.include(n.Path.CANVAS?{_containsPoint:function(t){var e,i,o,s,a,r,h,l,u=!1;if(n.Polyline.prototype._containsPoint.call(this,t,!0))return!0;for(s=0,h=this._parts.length;h>s;s++)for(e=this._part
 s[s],a=0,l=e.length,r=l-1;l>a;r=a++)i=e[a],o=e[r],i.y>t.y!=o.y>t.y&&t.x<(o.x-i.x)*(t.y-i.y)/(o.y-i.y)+i.x&&(u=!u);return u}}:{}),n.Circle.include(n.Path.CANVAS?{_drawPath:function(){var t=this._point;this._ctx.beginPath(),this._ctx.arc(t.x,t.y,this._radius,0,2*Math.PI,!1)},_containsPoint:function(t){var e=this._point,i=this.options.stroke?this.options.weight/2:0;return t.distanceTo(e)<=this._radius+i}}:{}),n.GeoJSON=n.FeatureGroup.extend({initialize:function(t,e){n.setOptions(this,e),this._layers={},t&&this.addData(t)},addData:function(t){var e,i,o=n.Util.isArray(t)?t:t.features;if(o){for(e=0,i=o.length;i>e;e++)(o[e].geometries||o[e].geometry)&&this.addData(o[e]);return this}var s=this.options;if(!s.filter||s.filter(t)){var a=n.GeoJSON.geometryToLayer(t,s.pointToLayer);return a.feature=t,a.defaultOptions=a.options,this.resetStyle(a),s.onEachFeature&&s.onEachFeature(t,a),this.addLayer(a)}},resetStyle:function(t){var e=this.options.style;e&&(n.Util.extend(t.options,t.defaultOptions),t
 his._setLayerStyle(t,e))},setStyle:function(t){this.eachLayer(function(e){this._setLayerStyle(e,t)},this)},_setLayerStyle:function(t,e){"function"==typeof e&&(e=e(t.feature)),t.setStyle&&t.setStyle(e)}}),n.extend(n.GeoJSON,{geometryToLayer:function(t,e){var i,o,s,a,r,h="Feature"===t.type?t.geometry:t,l=h.coordinates,u=[];switch(h.type){case"Point":return i=this.coordsToLatLng(l),e?e(t,i):new n.Marker(i);case"MultiPoint":for(s=0,a=l.length;a>s;s++)i=this.coordsToLatLng(l[s]),r=e?e(t,i):new n.Marker(i),u.push(r);return new n.FeatureGroup(u);case"LineString":return o=this.coordsToLatLngs(l),new n.Polyline(o);case"Polygon":return o=this.coordsToLatLngs(l,1),new n.Polygon(o);case"MultiLineString":return o=this.coordsToLatLngs(l,1),new n.MultiPolyline(o);case"MultiPolygon":return o=this.coordsToLatLngs(l,2),new n.MultiPolygon(o);case"GeometryCollection":for(s=0,a=h.geometries.length;a>s;s++)r=this.geometryToLayer({geometry:h.geometries[s],type:"Feature",properties:t.properties},e),u.push(
 r);return new n.FeatureGroup(u);default:throw Error("Invalid GeoJSON object.")}},coordsToLatLng:function(t,e){var i=parseFloat(t[e?0:1]),o=parseFloat(t[e?1:0]);return new n.LatLng(i,o)},coordsToLatLngs:function(t,e,i){var n,o,s,a=[];for(o=0,s=t.length;s>o;o++)n=e?this.coordsToLatLngs(t[o],e-1,i):this.coordsToLatLng(t[o],i),a.push(n);return a}}),n.geoJson=function(t,e){return new n.GeoJSON(t,e)},n.DomEvent={addListener:function(t,e,o,s){var a,r,h,l=n.stamp(o),u="_leaflet_"+e+l;return t[u]?this:(a=function(e){return o.call(s||t,e||n.DomEvent._getEvent())},n.Browser.msTouch&&0===e.indexOf("touch")?this.addMsTouchListener(t,e,a,l):(n.Browser.touch&&"dblclick"===e&&this.addDoubleTapListener&&this.addDoubleTapListener(t,a,l),"addEventListener"in t?"mousewheel"===e?(t.addEventListener("DOMMouseScroll",a,!1),t.addEventListener(e,a,!1)):"mouseenter"===e||"mouseleave"===e?(r=a,h="mouseenter"===e?"mouseover":"mouseout",a=function(e){return n.DomEvent._checkMouse(t,e)?r(e):i},t.addEventListener
 (h,a,!1)):t.addEventListener(e,a,!1):"attachEvent"in t&&t.attachEvent("on"+e,a),t[u]=a,this))},removeListener:function(t,e,i){var o=n.stamp(i),s="_leaflet_"+e+o,a=t[s];if(a)return n.Browser.msTouch&&0===e.indexOf("touch")?this.removeMsTouchListener(t,e,o):n.Browser.touch&&"dblclick"===e&&this.removeDoubleTapListener?this.removeDoubleTapListener(t,o):"removeEventListener"in t?"mousewheel"===e?(t.removeEventListener("DOMMouseScroll",a,!1),t.removeEventListener(e,a,!1)):"mouseenter"===e||"mouseleave"===e?t.removeEventListener("mouseenter"===e?"mouseover":"mouseout",a,!1):t.removeEventListener(e,a,!1):"detachEvent"in t&&t.detachEvent("on"+e,a),t[s]=null,this},stopPropagation:function(t){return t.stopPropagation?t.stopPropagation():t.cancelBubble=!0,this},disableClickPropagation:function(t){for(var e=n.DomEvent.stopPropagation,i=n.Draggable.START.length-1;i>=0;i--)n.DomEvent.addListener(t,n.Draggable.START[i],e);return n.DomEvent.addListener(t,"click",e).addListener(t,"dblclick",e)},prev
 entDefault:function(t){return t.preventDefault?t.preventDefault():t.returnValue=!1,this},stop:function(t){return n.DomEvent.preventDefault(t).stopPropagation(t)},getMousePosition:function(t,i){var o=e.body,s=e.documentElement,a=t.pageX?t.pageX:t.clientX+o.scrollLeft+s.scrollLeft,r=t.pageY?t.pageY:t.clientY+o.scrollTop+s.scrollTop,h=new n.Point(a,r);return i?h._subtract(n.DomUtil.getViewportOffset(i)):h},getWheelDelta:function(t){var e=0;return t.wheelDelta&&(e=t.wheelDelta/120),t.detail&&(e=-t.detail/3),e},_checkMouse:function(t,e){var i=e.relatedTarget;if(!i)return!0;try{for(;i&&i!==t;)i=i.parentNode}catch(n){return!1}return i!==t},_getEvent:function(){var e=t.event;if(!e)for(var i=arguments.callee.caller;i&&(e=i.arguments[0],!e||t.Event!==e.constructor);)i=i.caller;return e}},n.DomEvent.on=n.DomEvent.addListener,n.DomEvent.off=n.DomEvent.removeListener,n.Draggable=n.Class.extend({includes:n.Mixin.Events,statics:{START:n.Browser.touch?["touchstart","mousedown"]:["mousedown"],END:{m
 ousedown:"mouseup",touchstart:"touchend",MSPointerDown:"touchend"},MOVE:{mousedown:"mousemove",touchstart:"touchmove",MSPointerDown:"touchmove"},TAP_TOLERANCE:15},initialize:function(t,e,i){this._element=t,this._dragStartTarget=e||t,this._longPress=i&&!n.Browser.msTouch},enable:function(){if(!this._enabled){for(var t=n.Draggable.START.length-1;t>=0;t--)n.DomEvent.on(this._dragStartTarget,n.Draggable.START[t],this._onDown,this);this._enabled=!0}},disable:function(){if(this._enabled){for(var t=n.Draggable.START.length-1;t>=0;t--)n.DomEvent.off(this._dragStartTarget,n.Draggable.START[t],this._onDown,this);this._enabled=!1,this._moved=!1}},_onDown:function(t){if(!(!n.Browser.touch&&t.shiftKey||1!==t.which&&1!==t.button&&!t.touches||(n.DomEvent.preventDefault(t),n.DomEvent.stopPropagation(t),n.Draggable._disabled))){if(this._simulateClick=!0,t.touches&&t.touches.length>1)return this._simulateClick=!1,clearTimeout(this._longPressTimeout),i;var o=t.touches&&1===t.touches.length?t.touches[0
 ]:t,s=o.target;n.Browser.touch&&"a"===s.tagName.toLowerCase()&&n.DomUtil.addClass(s,"leaflet-active"),this._moved=!1,this._moving||(this._startPoint=new n.Point(o.clientX,o.clientY),this._startPos=this._newPos=n.DomUtil.getPosition(this._element),t.touches&&1===t.touches.length&&n.Browser.touch&&this._longPress&&(this._longPressTimeout=setTimeout(n.bind(function(){var t=this._newPos&&this._newPos.distanceTo(this._startPos)||0;n.Draggable.TAP_TOLERANCE>t&&(this._simulateClick=!1,this._onUp(),this._simulateEvent("contextmenu",o))},this),1e3)),n.DomEvent.on(e,n.Draggable.MOVE[t.type],this._onMove,this),n.DomEvent.on(e,n.Draggable.END[t.type],this._onUp,this))}},_onMove:function(t){if(!(t.touches&&t.touches.length>1)){var e=t.touches&&1===t.touches.length?t.touches[0]:t,i=new n.Point(e.clientX,e.clientY),o=i.subtract(this._startPoint);(o.x||o.y)&&(n.DomEvent.preventDefault(t),this._moved||(this.fire("dragstart"),this._moved=!0,this._startPos=n.DomUtil.getPosition(this._element).subtract
 (o),n.Browser.touch||(n.DomUtil.disableTextSelection(),this._setMovingCursor())),this._newPos=this._startPos.add(o),this._moving=!0,n.Util.cancelAnimFrame(this._animRequest),this._animRequest=n.Util.requestAnimFrame(this._updatePosition,this,!0,this._dragStartTarget))}},_updatePosition:function(){this.fire("predrag"),n.DomUtil.setPosition(this._element,this._newPos),this.fire("drag")},_onUp:function(t){var i;if(clearTimeout(this._longPressTimeout),this._simulateClick&&t.changedTouches){var o=t.changedTouches[0],s=o.target,a=this._newPos&&this._newPos.distanceTo(this._startPos)||0;"a"===s.tagName.toLowerCase()&&n.DomUtil.removeClass(s,"leaflet-active"),n.Draggable.TAP_TOLERANCE>a&&(i=o)}n.Browser.touch||(n.DomUtil.enableTextSelection(),this._restoreCursor());for(var r in n.Draggable.MOVE)n.Draggable.MOVE.hasOwnProperty(r)&&(n.DomEvent.off(e,n.Draggable.MOVE[r],this._onMove),n.DomEvent.off(e,n.Draggable.END[r],this._onUp));this._moved&&(n.Util.cancelAnimFrame(this._animRequest),this.f
 ire("dragend")),this._moving=!1,i&&(this._moved=!1,this._simulateEvent("click",i))},_setMovingCursor:function(){n.DomUtil.addClass(e.body,"leaflet-dragging")},_restoreCursor:function(){n.DomUtil.removeClass(e.body,"leaflet-dragging")},_simulateEvent:function(i,n){var o=e.createEvent("MouseEvents");o.initMouseEvent(i,!0,!0,t,1,n.screenX,n.screenY,n.clientX,n.clientY,!1,!1,!1,!1,0,null),n.target.dispatchEvent(o)}}),n.Handler=n.Class.extend({initialize:function(t){this._map=t},enable:function(){this._enabled||(this._enabled=!0,this.addHooks())},disable:function(){this._enabled&&(this._enabled=!1,this.removeHooks())},enabled:function(){return!!this._enabled}}),n.Map.mergeOptions({dragging:!0,inertia:!n.Browser.android23,inertiaDeceleration:3400,inertiaMaxSpeed:1/0,inertiaThreshold:n.Browser.touch?32:18,easeLinearity:.25,longPress:!0,worldCopyJump:!1}),n.Map.Drag=n.Handler.extend({addHooks:function(){if(!this._draggable){var t=this._map;this._draggable=new n.Draggable(t._mapPane,t._conta
 iner,t.options.longPress),this._draggable.on({dragstart:this._onDragStart,drag:this._onDrag,dragend:this._onDragEnd},this),t.options.worldCopyJump&&(this._draggable.on("predrag",this._onPreDrag,this),t.on("viewreset",this._onViewReset,this))}this._draggable.enable()},removeHooks:function(){this._draggable.disable()},moved:function(){return this._draggable&&this._draggable._moved},_onDragStart:function(){var t=this._map;t._panAnim&&t._panAnim.stop(),t.fire("movestart").fire("dragstart"),t.options.inertia&&(this._positions=[],this._times=[])},_onDrag:function(){if(this._map.options.inertia){var t=this._lastTime=+new Date,e=this._lastPos=this._draggable._newPos;this._positions.push(e),this._times.push(t),t-this._times[0]>200&&(this._positions.shift(),this._times.shift())}this._map.fire("move").fire("drag")},_onViewReset:function(){var t=this._map.getSize()._divideBy(2),e=this._map.latLngToLayerPoint(new n.LatLng(0,0));this._initialWorldOffset=e.subtract(t).x,this._worldWidth=this._map.
 project(new n.LatLng(0,180)).x},_onPreDrag:function(){var t=this._worldWidth,e=Math.round(t/2),i=this._initialWorldOffset,n=this._draggable._newPos.x,o=(n-e+i)%t+e-i,s=(n+e+i)%t-e-i,a=Math.abs(o+i)<Math.abs(s+i)?o:s;this._draggable._newPos.x=a},_onDragEnd:function(){var t=this._map,e=t.options,i=+new Date-this._lastTime,o=!e.inertia||i>e.inertiaThreshold||!this._positions[0];if(o)t.fire("moveend");else{var s=this._lastPos.subtract(this._positions[0]),a=(this._lastTime+i-this._times[0])/1e3,r=e.easeLinearity,h=s.multiplyBy(r/a),l=h.distanceTo(new n.Point(0,0)),u=Math.min(e.inertiaMaxSpeed,l),c=h.multiplyBy(u/l),_=u/(e.inertiaDeceleration*r),d=c.multiplyBy(-_/2).round();n.Util.requestAnimFrame(function(){t.panBy(d,_,r)})}t.fire("dragend"),e.maxBounds&&n.Util.requestAnimFrame(this._panInsideMaxBounds,t,!0,t._container)},_panInsideMaxBounds:function(){this.panInsideBounds(this.options.maxBounds)}}),n.Map.addInitHook("addHandler","dragging",n.Map.Drag),n.Map.mergeOptions({doubleClickZoom
 :!0}),n.Map.DoubleClickZoom=n.Handler.extend({addHooks:function(){this._map.on("dblclick",this._onDoubleClick)},removeHooks:function(){this._map.off("dblclick",this._onDoubleClick)},_onDoubleClick:function(t){this.setView(t.latlng,this._zoom+1)}}),n.Map.addInitHook("addHandler","doubleClickZoom",n.Map.DoubleClickZoom),n.Map.mergeOptions({scrollWheelZoom:!0}),n.Map.ScrollWheelZoom=n.Handler.extend({addHooks:function(){n.DomEvent.on(this._map._container,"mousewheel",this._onWheelScroll,this),this._delta=0},removeHooks:function(){n.DomEvent.off(this._map._container,"mousewheel",this._onWheelScroll)},_onWheelScroll:function(t){var e=n.DomEvent.getWheelDelta(t);this._delta+=e,this._lastMousePos=this._map.mouseEventToContainerPoint(t),this._startTime||(this._startTime=+new Date);var i=Math.max(40-(+new Date-this._startTime),0);clearTimeout(this._timer),this._timer=setTimeout(n.bind(this._performZoom,this),i),n.DomEvent.preventDefault(t),n.DomEvent.stopPropagation(t)},_performZoom:function
 (){var t=this._map,e=this._delta,i=t.getZoom();if(e=e>0?Math.ceil(e):Math.round(e),e=Math.max(Math.min(e,4),-4),e=t._limitZoom(i+e)-i,this._delta=0,this._startTime=null,e){var n=i+e,o=this._getCenterForScrollWheelZoom(n);t.setView(o,n)}},_getCenterForScrollWheelZoom:function(t){var e=this._map,i=e.getZoomScale(t),n=e.getSize()._divideBy(2),o=this._lastMousePos._subtract(n)._multiplyBy(1-1/i),s=e._getTopLeftPoint()._add(n)._add(o);return e.unproject(s)}}),n.Map.addInitHook("addHandler","scrollWheelZoom",n.Map.ScrollWheelZoom),n.extend(n.DomEvent,{_touchstart:n.Browser.msTouch?"MSPointerDown":"touchstart",_touchend:n.Browser.msTouch?"MSPointerUp":"touchend",addDoubleTapListener:function(t,i,o){function s(t){var e;if(n.Browser.msTouch?(p.push(t.pointerId),e=p.length):e=t.touches.length,!(e>1)){var i=Date.now(),o=i-(r||i);h=t.touches?t.touches[0]:t,l=o>0&&u>=o,r=i}}function a(t){if(n.Browser.msTouch){var e=p.indexOf(t.pointerId);if(-1===e)return;p.splice(e,1)}if(l){if(n.Browser.msTouch)
 {var o,s={};for(var a in h)o=h[a],s[a]="function"==typeof o?o.bind(h):o;h=s}h.type="dblclick",i(h),r=null}}var r,h,l=!1,u=250,c="_leaflet_",_=this._touchstart,d=this._touchend,p=[];t[c+_+o]=s,t[c+d+o]=a;var m=n.Browser.msTouch?e.documentElement:t;return t.addEventListener(_,s,!1),m.addEventListener(d,a,!1),n.Browser.msTouch&&m.addEventListener("MSPointerCancel",a,!1),this},removeDoubleTapListener:function(t,i){var o="_leaflet_";return t.removeEventListener(this._touchstart,t[o+this._touchstart+i],!1),(n.Browser.msTouch?e.documentElement:t).removeEventListener(this._touchend,t[o+this._touchend+i],!1),n.Browser.msTouch&&e.documentElement.removeEventListener("MSPointerCancel",t[o+this._touchend+i],!1),this}}),n.extend(n.DomEvent,{_msTouches:[],_msDocumentListener:!1,addMsTouchListener:function(t,e,i,n){switch(e){case"touchstart":return this.addMsTouchListenerStart(t,e,i,n);case"touchend":return this.addMsTouchListenerEnd(t,e,i,n);case"touchmove":return this.addMsTouchListenerMove(t,e,i
 ,n);default:throw"Unknown touch event type"}},addMsTouchListenerStart:function(t,i,n,o){var s="_leaflet_",a=this._msTouches,r=function(t){for(var e=!1,i=0;a.length>i;i++)if(a[i].pointerId===t.pointerId){e=!0;break}e||a.push(t),t.touches=a.slice(),t.changedTouches=[t],n(t)};if(t[s+"touchstart"+o]=r,t.addEventListener("MSPointerDown",r,!1),!this._msDocumentListener){var h=function(t){for(var e=0;a.length>e;e++)if(a[e].pointerId===t.pointerId){a.splice(e,1);break}};e.documentElement.addEventListener("MSPointerUp",h,!1),e.documentElement.addEventListener("MSPointerCancel",h,!1),this._msDocumentListener=!0}return this},addMsTouchListenerMove:function(t,e,i,n){function o(t){if(t.pointerType!==t.MSPOINTER_TYPE_MOUSE||0!==t.buttons){for(var e=0;a.length>e;e++)if(a[e].pointerId===t.pointerId){a[e]=t;break}t.touches=a.slice(),t.changedTouches=[t],i(t)}}var s="_leaflet_",a=this._msTouches;return t[s+"touchmove"+n]=o,t.addEventListener("MSPointerMove",o,!1),this},addMsTouchListenerEnd:function(
 t,e,i,n){var o="_leaflet_",s=this._msTouches,a=function(t){for(var e=0;s.length>e;e++)if(s[e].pointerId===t.pointerId){s.splice(e,1);break}t.touches=s.slice(),t.changedTouches=[t],i(t)};return t[o+"touchend"+n]=a,t.addEventListener("MSPointerUp",a,!1),t.addEventListener("MSPointerCancel",a,!1),this},removeMsTouchListener:function(t,e,i){var n="_leaflet_",o=t[n+e+i];switch(e){case"touchstart":t.removeEventListener("MSPointerDown",o,!1);break;case"touchmove":t.removeEventListener("MSPointerMove",o,!1);break;case"touchend":t.removeEventListener("MSPointerUp",o,!1),t.removeEventListener("MSPointerCancel",o,!1)}return this}}),n.Map.mergeOptions({touchZoom:n.Browser.touch&&!n.Browser.android23}),n.Map.TouchZoom=n.Handler.extend({addHooks:function(){n.DomEvent.on(this._map._container,"touchstart",this._onTouchStart,this)},removeHooks:function(){n.DomEvent.off(this._map._container,"touchstart",this._onTouchStart,this)},_onTouchStart:function(t){var i=this._map;if(t.touches&&2===t.touches.le
 ngth&&!i._animatingZoom&&!this._zooming){var o=i.mouseEventToLayerPoint(t.touches[0]),s=i.mouseEventToLayerPoint(t.touches[1]),a=i._getCenterLayerPoint();this._startCenter=o.add(s)._divideBy(2),this._startDist=o.distanceTo(s),this._moved=!1,this._zooming=!0,this._centerOffset=a.subtract(this._startCenter),i._panAnim&&i._panAnim.stop(),n.DomEvent.on(e,"touchmove",this._onTouchMove,this).on(e,"touchend",this._onTouchEnd,this),n.DomEvent.preventDefault(t)}},_onTouchMove:function(t){if(t.touches&&2===t.touches.length){var e=this._map,i=e.mouseEventToLayerPoint(t.touches[0]),o=e.mouseEventToLayerPoint(t.touches[1]);this._scale=i.distanceTo(o)/this._startDist,this._delta=i._add(o)._divideBy(2)._subtract(this._startCenter),1!==this._scale&&(this._moved||(n.DomUtil.addClass(e._mapPane,"leaflet-zoom-anim leaflet-touching"),e.fire("movestart").fire("zoomstart")._prepareTileBg(),this._moved=!0),n.Util.cancelAnimFrame(this._animRequest),this._animRequest=n.Util.requestAnimFrame(this._updateOnMo
 ve,this,!0,this._map._container),n.DomEvent.preventDefault(t))}},_updateOnMove:function(){var t=this._map,e=this._getScaleOrigin(),i=t.layerPointToLatLng(e);t.fire("zoomanim",{center:i,zoom:t.getScaleZoom(this._scale)}),t._tileBg.style[n.DomUtil.TRANSFORM]=n.DomUtil.getTranslateString(this._delta)+" "+n.DomUtil.getScaleString(this._scale,this._startCenter)},_onTouchEnd:function(){if(this._moved&&this._zooming){var t=this._map;this._zooming=!1,n.DomUtil.removeClass(t._mapPane,"leaflet-touching"),n.DomEvent.off(e,"touchmove",this._onTouchMove).off(e,"touchend",this._onTouchEnd);var i=this._getScaleOrigin(),o=t.layerPointToLatLng(i),s=t.getZoom(),a=t.getScaleZoom(this._scale)-s,r=a>0?Math.ceil(a):Math.floor(a),h=t._limitZoom(s+r);t.fire("zoomanim",{center:o,zoom:h}),t._runAnimation(o,h,t.getZoomScale(h)/this._scale,i,!0)}},_getScaleOrigin:function(){var t=this._centerOffset.subtract(this._delta).divideBy(this._scale);return this._startCenter.add(t)}}),n.Map.addInitHook("addHandler","to
 uchZoom",n.Map.TouchZoom),n.Map.mergeOptions({boxZoom:!0}),n.Map.BoxZoom=n.Handler.extend({initialize:function(t){this._map=t,this._container=t._container,this._pane=t._panes.overlayPane},addHooks:function(){n.DomEvent.on(this._container,"mousedown",this._onMouseDown,this)},removeHooks:function(){n.DomEvent.off(this._container,"mousedown",this._onMouseDown)},_onMouseDown:function(t){return!t.shiftKey||1!==t.which&&1!==t.button?!1:(n.DomUtil.disableTextSelection(),this._startLayerPoint=this._map.mouseEventToLayerPoint(t),this._box=n.DomUtil.create("div","leaflet-zoom-box",this._pane),n.DomUtil.setPosition(this._box,this._startLayerPoint),this._container.style.cursor="crosshair",n.DomEvent.on(e,"mousemove",this._onMouseMove,this).on(e,"mouseup",this._onMouseUp,this).preventDefault(t),this._map.fire("boxzoomstart"),i)},_onMouseMove:function(t){var e=this._startLayerPoint,i=this._box,o=this._map.

<TRUNCATED>

[32/51] [abbrv] [partial] Adding Jinwon's custom RCMET

Posted by jo...@apache.org.
http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/app/css/font-awesome.min.css
----------------------------------------------------------------------
diff --git a/src/main/ui/app/css/font-awesome.min.css b/src/main/ui/app/css/font-awesome.min.css
new file mode 100755
index 0000000..d4e45b3
--- /dev/null
+++ b/src/main/ui/app/css/font-awesome.min.css
@@ -0,0 +1,33 @@
+/*!
+ *  Font Awesome 3.0.2
+ *  the iconic font designed for use with Twitter Bootstrap
+ *  -------------------------------------------------------
+ *  The full suite of pictographic icons, examples, and documentation
+ *  can be found at: http://fortawesome.github.com/Font-Awesome/
+ *
+ *  License
+ *  -------------------------------------------------------
+ *  - The Font Awesome font is licensed under the SIL Open Font License - http://scripts.sil.org/OFL
+ *  - Font Awesome CSS, LESS, and SASS files are licensed under the MIT License -
+ *    http://opensource.org/licenses/mit-license.html
+ *  - The Font Awesome pictograms are licensed under the CC BY 3.0 License - http://creativecommons.org/licenses/by/3.0/
+ *  - Attribution is no longer required in Font Awesome 3.0, but much appreciated:
+ *    "Font Awesome by Dave Gandy - http://fortawesome.github.com/Font-Awesome"
+
+ *  Contact
+ *  -------------------------------------------------------
+ *  Email: dave@davegandy.com
+ *  Twitter: http://twitter.com/fortaweso_me
+ *  Work: Lead Product Designer @ http://kyruus.com
+ */
+
+@font-face{
+  font-family:'FontAwesome';
+  src:url('../font/fontawesome-webfont.eot?v=3.0.1');
+  src:url('../font/fontawesome-webfont.eot?#iefix&v=3.0.1') format('embedded-opentype'),
+  url('../font/fontawesome-webfont.woff?v=3.0.1') format('woff'),
+  url('../font/fontawesome-webfont.ttf?v=3.0.1') format('truetype');
+  font-weight:normal;
+  font-style:normal }
+
+[class^="icon-"],[class*=" icon-"]{font-family:FontAwesome;font-weight:normal;font-style:normal;text-decoration:inherit;-webkit-font-smoothing:antialiased;display:inline;width:auto;height:auto;line-height:normal;vertical-align:baseline;background-image:none;background-position:0 0;background-repeat:repeat;margin-top:0}.icon-white,.nav-pills>.active>a>[class^="icon-"],.nav-pills>.active>a>[class*=" icon-"],.nav-list>.active>a>[class^="icon-"],.nav-list>.active>a>[class*=" icon-"],.navbar-inverse .nav>.active>a>[class^="icon-"],.navbar-inverse .nav>.active>a>[class*=" icon-"],.dropdown-menu>li>a:hover>[class^="icon-"],.dropdown-menu>li>a:hover>[class*=" icon-"],.dropdown-menu>.active>a>[class^="icon-"],.dropdown-menu>.active>a>[class*=" icon-"],.dropdown-submenu:hover>a>[class^="icon-"],.dropdown-submenu:hover>a>[class*=" icon-"]{background-image:none}[class^="icon-"]:before,[class*=" icon-"]:before{text-decoration:inherit;display:inline-block;speak:none}a [class^="icon-"],a [class*="
  icon-"]{display:inline-block}.icon-large:before{vertical-align:-10%;font-size:1.3333333333333333em}.btn [class^="icon-"],.nav [class^="icon-"],.btn [class*=" icon-"],.nav [class*=" icon-"]{display:inline}.btn [class^="icon-"].icon-large,.nav [class^="icon-"].icon-large,.btn [class*=" icon-"].icon-large,.nav [class*=" icon-"].icon-large{line-height:.9em}.btn [class^="icon-"].icon-spin,.nav [class^="icon-"].icon-spin,.btn [class*=" icon-"].icon-spin,.nav [class*=" icon-"].icon-spin{display:inline-block}.nav-tabs [class^="icon-"],.nav-pills [class^="icon-"],.nav-tabs [class*=" icon-"],.nav-pills [class*=" icon-"],.nav-tabs [class^="icon-"].icon-large,.nav-pills [class^="icon-"].icon-large,.nav-tabs [class*=" icon-"].icon-large,.nav-pills [class*=" icon-"].icon-large{line-height:.9em}li [class^="icon-"],.nav li [class^="icon-"],li [class*=" icon-"],.nav li [class*=" icon-"]{display:inline-block;width:1.25em;text-align:center}li [class^="icon-"].icon-large,.nav li [class^="icon-"].icon-
 large,li [class*=" icon-"].icon-large,.nav li [class*=" icon-"].icon-large{width:1.5625em}ul.icons{list-style-type:none;text-indent:-0.75em}ul.icons li [class^="icon-"],ul.icons li [class*=" icon-"]{width:.75em}.icon-muted{color:#eee}.icon-border{border:solid 1px #eee;padding:.2em .25em .15em;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}.icon-2x{font-size:2em}.icon-2x.icon-border{border-width:2px;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.icon-3x{font-size:3em}.icon-3x.icon-border{border-width:3px;-webkit-border-radius:5px;-moz-border-radius:5px;border-radius:5px}.icon-4x{font-size:4em}.icon-4x.icon-border{border-width:4px;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px}.pull-right{float:right}.pull-left{float:left}[class^="icon-"].pull-left,[class*=" icon-"].pull-left{margin-right:.3em}[class^="icon-"].pull-right,[class*=" icon-"].pull-right{margin-left:.3em}.btn [class^="icon-"].pull-left.icon-2x,.btn [class*=" icon
 -"].pull-left.icon-2x,.btn [class^="icon-"].pull-right.icon-2x,.btn [class*=" icon-"].pull-right.icon-2x{margin-top:.18em}.btn [class^="icon-"].icon-spin.icon-large,.btn [class*=" icon-"].icon-spin.icon-large{line-height:.8em}.btn.btn-small [class^="icon-"].pull-left.icon-2x,.btn.btn-small [class*=" icon-"].pull-left.icon-2x,.btn.btn-small [class^="icon-"].pull-right.icon-2x,.btn.btn-small [class*=" icon-"].pull-right.icon-2x{margin-top:.25em}.btn.btn-large [class^="icon-"],.btn.btn-large [class*=" icon-"]{margin-top:0}.btn.btn-large [class^="icon-"].pull-left.icon-2x,.btn.btn-large [class*=" icon-"].pull-left.icon-2x,.btn.btn-large [class^="icon-"].pull-right.icon-2x,.btn.btn-large [class*=" icon-"].pull-right.icon-2x{margin-top:.05em}.btn.btn-large [class^="icon-"].pull-left.icon-2x,.btn.btn-large [class*=" icon-"].pull-left.icon-2x{margin-right:.2em}.btn.btn-large [class^="icon-"].pull-right.icon-2x,.btn.btn-large [class*=" icon-"].pull-right.icon-2x{margin-left:.2em}.icon-spin{d
 isplay:inline-block;-moz-animation:spin 2s infinite linear;-o-animation:spin 2s infinite linear;-webkit-animation:spin 2s infinite linear;animation:spin 2s infinite linear}@-moz-keyframes spin{0%{-moz-transform:rotate(0deg)}100%{-moz-transform:rotate(359deg)}}@-webkit-keyframes spin{0%{-webkit-transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg)}}@-o-keyframes spin{0%{-o-transform:rotate(0deg)}100%{-o-transform:rotate(359deg)}}@-ms-keyframes spin{0%{-ms-transform:rotate(0deg)}100%{-ms-transform:rotate(359deg)}}@keyframes spin{0%{transform:rotate(0deg)}100%{transform:rotate(359deg)}}@-moz-document url-prefix(){.icon-spin{height:.9em}.btn .icon-spin{height:auto}.icon-spin.icon-large{height:1.25em}.btn .icon-spin.icon-large{height:.75em}}.icon-glass:before{content:"\f000"}.icon-music:before{content:"\f001"}.icon-search:before{content:"\f002"}.icon-envelope:before{content:"\f003"}.icon-heart:before{content:"\f004"}.icon-star:before{content:"\f005"}.icon-star-empty:before{content
 :"\f006"}.icon-user:before{content:"\f007"}.icon-film:before{content:"\f008"}.icon-th-large:before{content:"\f009"}.icon-th:before{content:"\f00a"}.icon-th-list:before{content:"\f00b"}.icon-ok:before{content:"\f00c"}.icon-remove:before{content:"\f00d"}.icon-zoom-in:before{content:"\f00e"}.icon-zoom-out:before{content:"\f010"}.icon-off:before{content:"\f011"}.icon-signal:before{content:"\f012"}.icon-cog:before{content:"\f013"}.icon-trash:before{content:"\f014"}.icon-home:before{content:"\f015"}.icon-file:before{content:"\f016"}.icon-time:before{content:"\f017"}.icon-road:before{content:"\f018"}.icon-download-alt:before{content:"\f019"}.icon-download:before{content:"\f01a"}.icon-upload:before{content:"\f01b"}.icon-inbox:before{content:"\f01c"}.icon-play-circle:before{content:"\f01d"}.icon-repeat:before{content:"\f01e"}.icon-refresh:before{content:"\f021"}.icon-list-alt:before{content:"\f022"}.icon-lock:before{content:"\f023"}.icon-flag:before{content:"\f024"}.icon-headphones:before{co
 ntent:"\f025"}.icon-volume-off:before{content:"\f026"}.icon-volume-down:before{content:"\f027"}.icon-volume-up:before{content:"\f028"}.icon-qrcode:before{content:"\f029"}.icon-barcode:before{content:"\f02a"}.icon-tag:before{content:"\f02b"}.icon-tags:before{content:"\f02c"}.icon-book:before{content:"\f02d"}.icon-bookmark:before{content:"\f02e"}.icon-print:before{content:"\f02f"}.icon-camera:before{content:"\f030"}.icon-font:before{content:"\f031"}.icon-bold:before{content:"\f032"}.icon-italic:before{content:"\f033"}.icon-text-height:before{content:"\f034"}.icon-text-width:before{content:"\f035"}.icon-align-left:before{content:"\f036"}.icon-align-center:before{content:"\f037"}.icon-align-right:before{content:"\f038"}.icon-align-justify:before{content:"\f039"}.icon-list:before{content:"\f03a"}.icon-indent-left:before{content:"\f03b"}.icon-indent-right:before{content:"\f03c"}.icon-facetime-video:before{content:"\f03d"}.icon-picture:before{content:"\f03e"}.icon-pencil:before{content:"\f
 040"}.icon-map-marker:before{content:"\f041"}.icon-adjust:before{content:"\f042"}.icon-tint:before{content:"\f043"}.icon-edit:before{content:"\f044"}.icon-share:before{content:"\f045"}.icon-check:before{content:"\f046"}.icon-move:before{content:"\f047"}.icon-step-backward:before{content:"\f048"}.icon-fast-backward:before{content:"\f049"}.icon-backward:before{content:"\f04a"}.icon-play:before{content:"\f04b"}.icon-pause:before{content:"\f04c"}.icon-stop:before{content:"\f04d"}.icon-forward:before{content:"\f04e"}.icon-fast-forward:before{content:"\f050"}.icon-step-forward:before{content:"\f051"}.icon-eject:before{content:"\f052"}.icon-chevron-left:before{content:"\f053"}.icon-chevron-right:before{content:"\f054"}.icon-plus-sign:before{content:"\f055"}.icon-minus-sign:before{content:"\f056"}.icon-remove-sign:before{content:"\f057"}.icon-ok-sign:before{content:"\f058"}.icon-question-sign:before{content:"\f059"}.icon-info-sign:before{content:"\f05a"}.icon-screenshot:before{content:"\f05
 b"}.icon-remove-circle:before{content:"\f05c"}.icon-ok-circle:before{content:"\f05d"}.icon-ban-circle:before{content:"\f05e"}.icon-arrow-left:before{content:"\f060"}.icon-arrow-right:before{content:"\f061"}.icon-arrow-up:before{content:"\f062"}.icon-arrow-down:before{content:"\f063"}.icon-share-alt:before{content:"\f064"}.icon-resize-full:before{content:"\f065"}.icon-resize-small:before{content:"\f066"}.icon-plus:before{content:"\f067"}.icon-minus:before{content:"\f068"}.icon-asterisk:before{content:"\f069"}.icon-exclamation-sign:before{content:"\f06a"}.icon-gift:before{content:"\f06b"}.icon-leaf:before{content:"\f06c"}.icon-fire:before{content:"\f06d"}.icon-eye-open:before{content:"\f06e"}.icon-eye-close:before{content:"\f070"}.icon-warning-sign:before{content:"\f071"}.icon-plane:before{content:"\f072"}.icon-calendar:before{content:"\f073"}.icon-random:before{content:"\f074"}.icon-comment:before{content:"\f075"}.icon-magnet:before{content:"\f076"}.icon-chevron-up:before{content:"\f
 077"}.icon-chevron-down:before{content:"\f078"}.icon-retweet:before{content:"\f079"}.icon-shopping-cart:before{content:"\f07a"}.icon-folder-close:before{content:"\f07b"}.icon-folder-open:before{content:"\f07c"}.icon-resize-vertical:before{content:"\f07d"}.icon-resize-horizontal:before{content:"\f07e"}.icon-bar-chart:before{content:"\f080"}.icon-twitter-sign:before{content:"\f081"}.icon-facebook-sign:before{content:"\f082"}.icon-camera-retro:before{content:"\f083"}.icon-key:before{content:"\f084"}.icon-cogs:before{content:"\f085"}.icon-comments:before{content:"\f086"}.icon-thumbs-up:before{content:"\f087"}.icon-thumbs-down:before{content:"\f088"}.icon-star-half:before{content:"\f089"}.icon-heart-empty:before{content:"\f08a"}.icon-signout:before{content:"\f08b"}.icon-linkedin-sign:before{content:"\f08c"}.icon-pushpin:before{content:"\f08d"}.icon-external-link:before{content:"\f08e"}.icon-signin:before{content:"\f090"}.icon-trophy:before{content:"\f091"}.icon-github-sign:before{content
 :"\f092"}.icon-upload-alt:before{content:"\f093"}.icon-lemon:before{content:"\f094"}.icon-phone:before{content:"\f095"}.icon-check-empty:before{content:"\f096"}.icon-bookmark-empty:before{content:"\f097"}.icon-phone-sign:before{content:"\f098"}.icon-twitter:before{content:"\f099"}.icon-facebook:before{content:"\f09a"}.icon-github:before{content:"\f09b"}.icon-unlock:before{content:"\f09c"}.icon-credit-card:before{content:"\f09d"}.icon-rss:before{content:"\f09e"}.icon-hdd:before{content:"\f0a0"}.icon-bullhorn:before{content:"\f0a1"}.icon-bell:before{content:"\f0a2"}.icon-certificate:before{content:"\f0a3"}.icon-hand-right:before{content:"\f0a4"}.icon-hand-left:before{content:"\f0a5"}.icon-hand-up:before{content:"\f0a6"}.icon-hand-down:before{content:"\f0a7"}.icon-circle-arrow-left:before{content:"\f0a8"}.icon-circle-arrow-right:before{content:"\f0a9"}.icon-circle-arrow-up:before{content:"\f0aa"}.icon-circle-arrow-down:before{content:"\f0ab"}.icon-globe:before{content:"\f0ac"}.icon-wre
 nch:before{content:"\f0ad"}.icon-tasks:before{content:"\f0ae"}.icon-filter:before{content:"\f0b0"}.icon-briefcase:before{content:"\f0b1"}.icon-fullscreen:before{content:"\f0b2"}.icon-group:before{content:"\f0c0"}.icon-link:before{content:"\f0c1"}.icon-cloud:before{content:"\f0c2"}.icon-beaker:before{content:"\f0c3"}.icon-cut:before{content:"\f0c4"}.icon-copy:before{content:"\f0c5"}.icon-paper-clip:before{content:"\f0c6"}.icon-save:before{content:"\f0c7"}.icon-sign-blank:before{content:"\f0c8"}.icon-reorder:before{content:"\f0c9"}.icon-list-ul:before{content:"\f0ca"}.icon-list-ol:before{content:"\f0cb"}.icon-strikethrough:before{content:"\f0cc"}.icon-underline:before{content:"\f0cd"}.icon-table:before{content:"\f0ce"}.icon-magic:before{content:"\f0d0"}.icon-truck:before{content:"\f0d1"}.icon-pinterest:before{content:"\f0d2"}.icon-pinterest-sign:before{content:"\f0d3"}.icon-google-plus-sign:before{content:"\f0d4"}.icon-google-plus:before{content:"\f0d5"}.icon-money:before{content:"\f0
 d6"}.icon-caret-down:before{content:"\f0d7"}.icon-caret-up:before{content:"\f0d8"}.icon-caret-left:before{content:"\f0d9"}.icon-caret-right:before{content:"\f0da"}.icon-columns:before{content:"\f0db"}.icon-sort:before{content:"\f0dc"}.icon-sort-down:before{content:"\f0dd"}.icon-sort-up:before{content:"\f0de"}.icon-envelope-alt:before{content:"\f0e0"}.icon-linkedin:before{content:"\f0e1"}.icon-undo:before{content:"\f0e2"}.icon-legal:before{content:"\f0e3"}.icon-dashboard:before{content:"\f0e4"}.icon-comment-alt:before{content:"\f0e5"}.icon-comments-alt:before{content:"\f0e6"}.icon-bolt:before{content:"\f0e7"}.icon-sitemap:before{content:"\f0e8"}.icon-umbrella:before{content:"\f0e9"}.icon-paste:before{content:"\f0ea"}.icon-lightbulb:before{content:"\f0eb"}.icon-exchange:before{content:"\f0ec"}.icon-cloud-download:before{content:"\f0ed"}.icon-cloud-upload:before{content:"\f0ee"}.icon-user-md:before{content:"\f0f0"}.icon-stethoscope:before{content:"\f0f1"}.icon-suitcase:before{content:"
 \f0f2"}.icon-bell-alt:before{content:"\f0f3"}.icon-coffee:before{content:"\f0f4"}.icon-food:before{content:"\f0f5"}.icon-file-alt:before{content:"\f0f6"}.icon-building:before{content:"\f0f7"}.icon-hospital:before{content:"\f0f8"}.icon-ambulance:before{content:"\f0f9"}.icon-medkit:before{content:"\f0fa"}.icon-fighter-jet:before{content:"\f0fb"}.icon-beer:before{content:"\f0fc"}.icon-h-sign:before{content:"\f0fd"}.icon-plus-sign-alt:before{content:"\f0fe"}.icon-double-angle-left:before{content:"\f100"}.icon-double-angle-right:before{content:"\f101"}.icon-double-angle-up:before{content:"\f102"}.icon-double-angle-down:before{content:"\f103"}.icon-angle-left:before{content:"\f104"}.icon-angle-right:before{content:"\f105"}.icon-angle-up:before{content:"\f106"}.icon-angle-down:before{content:"\f107"}.icon-desktop:before{content:"\f108"}.icon-laptop:before{content:"\f109"}.icon-tablet:before{content:"\f10a"}.icon-mobile-phone:before{content:"\f10b"}.icon-circle-blank:before{content:"\f10c"}
 .icon-quote-left:before{content:"\f10d"}.icon-quote-right:before{content:"\f10e"}.icon-spinner:before{content:"\f110"}.icon-circle:before{content:"\f111"}.icon-reply:before{content:"\f112"}.icon-github-alt:before{content:"\f113"}.icon-folder-close-alt:before{content:"\f114"}.icon-folder-open-alt:before{content:"\f115"}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/app/css/jasny-bootstrap-responsive.min.css
----------------------------------------------------------------------
diff --git a/src/main/ui/app/css/jasny-bootstrap-responsive.min.css b/src/main/ui/app/css/jasny-bootstrap-responsive.min.css
new file mode 100755
index 0000000..0d43d71
--- /dev/null
+++ b/src/main/ui/app/css/jasny-bootstrap-responsive.min.css
@@ -0,0 +1,9 @@
+/*!
+ * Jasny Bootstrap Responsive Extensions j3
+ *
+ * Copyright 2012 Jasny BV
+ * Licensed under the Apache License v2.0
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Extended with pride by @ArnoldDaniels of jasny.net
+ */.clearfix{*zoom:1}.clearfix:before,.clearfix:after{display:table;line-height:0;content:""}.clearfix:after{clear:both}.hide-text{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.input-block-level{display:block;width:100%;min-height:30px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.container-semifluid{max-width:1170px}@media(min-width:768px) and (max-width:979px){.row-desktop.row-fluid{width:100%}.row-desktop.row{margin-left:0}.row-desktop>[class*="span"],.row-desktop>[class*="span"]{display:block;float:none;width:auto;margin:0}}@media(max-width:767px){.table-responsive tr{display:block;padding:8px}.table-bordered.table-responsive tr{border:1px solid #DDD;border-top:0;border-right:0}.table-responsive td,.table-responsive th{display:block;padding:0;font-weight:normal;border:0}.table-responsive th{font-style:italic}.responsive-strong{font-weight:bold}.responsive-em{font-style:italic}.responsive-soft{color:#999}}@m
 edia(max-width:480px){.form-horizontal .controls,.form-horizontal .well .controls,.small-labels .controls{margin-left:0}}@media(max-width:768px){.form-horizontal .form-actions{padding-left:18px}}@media(min-width:768px) and (max-width:979px){.form-horizontal .control-label{width:100px}.form-horizontal .controls{margin-left:110px}.form-horizontal .form-actions{padding-left:110px}.form-horizontal .well .control-label{width:80px}.form-horizontal .well .controls{margin-left:90px}.small-labels .control-group>label{width:50px}.small-labels .controls{margin-left:60px}.small-labels .form-actions{padding-left:60px}}@media(min-width:1200px){.small-labels .control-group>label{width:80px}.small-labels .controls{margin-left:100px}.small-labels .form-actions{padding-left:100px}}@media(max-width:480px){.page-alert{position:static;width:auto}.page-alert .alert{width:auto;margin-left:0;border-top-width:1px;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}body>.page-alert{position:st
 atic}}@media(min-width:1200px){.page-alert .alert{width:700px;margin-left:-375px}}

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/app/css/jasny-bootstrap.min.css
----------------------------------------------------------------------
diff --git a/src/main/ui/app/css/jasny-bootstrap.min.css b/src/main/ui/app/css/jasny-bootstrap.min.css
new file mode 100755
index 0000000..1862711
--- /dev/null
+++ b/src/main/ui/app/css/jasny-bootstrap.min.css
@@ -0,0 +1,9 @@
+/*!
+ * Jasny Bootstrap Extensions j3
+ *
+ * Copyright 2012 Jasny BV
+ * Licensed under the Apache License v2.0
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Extended with pride by @ArnoldDaniels of jasny.net
+ */.clearfix{*zoom:1}.clearfix:before,.clearfix:after{display:table;line-height:0;content:""}.clearfix:after{clear:both}.hide-text{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.input-block-level{display:block;width:100%;min-height:30px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.container-semifluid{max-width:940px;padding-right:20px;padding-left:20px;margin-right:auto;margin-left:auto;*zoom:1}.container-semifluid:before,.container-semifluid:after{display:table;line-height:0;content:""}.container-semifluid:after{clear:both}form>*:last-child{margin-bottom:0}label input[type="image"],label input[type="checkbox"],label input[type="radio"]{vertical-align:middle}select{padding-left:2px}.small-labels .control-group>label{width:70px}.small-labels .controls{margin-left:80px}.small-labels .form-actions{padding-left:80px}.form-vertical .form-horizontal .control-group>label{text-align:left}.form-horizontal .form-vertical
  .control-group>label{float:none;padding-top:0;text-align:left}.form-horizontal .form-vertical .controls{margin-left:0}.form-horizontal .form-vertical.form-actions,.form-horizontal .form-vertical .form-actions{padding-left:20px}.control-group .control-group{margin-bottom:0}.form-horizontal .well .control-label{width:120px}.form-horizontal .well .controls{margin-left:140px}form .well>*:last-child{margin-bottom:0}.editor{width:100%;height:100px;padding:5px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.uneditable-textarea.editor-html{padding:5px 3px 5px 5px;white-space:normal}textarea.editor-html{visibility:hidden}.uneditable-input,.uneditable-textarea{display:inline-block;padding:4px 3px 4px 5px;font-size:14px;line-height:20px;color:#555;cursor:not-allowed;background-color:#fff;border:1px solid #eee;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,0.025);-webkit-box-shadow:inset 0 1px 1px
  rgba(0,0,0,0.075);-moz-box-shadow:inset 0 1px 2px rgba(0,0,0,0.025);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 2px rgba(0,0,0,0.025);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.uneditable-input{height:20px;overflow:hidden;white-space:pre}.uneditable-textarea{overflow-x:hidden;overflow-y:auto;white-space:pre-wrap}select[disabled],textarea[disabled],input[type="text"][disabled],input[type="password"][disabled],input[type="datetime"][disabled],input[type="datetime-local"][disabled],input[type="date"][disabled],input[type="month"][disabled],input[type="time"][disabled],input[type="week"][disabled],input[type="number"][disabled],input[type="email"][disabled],input[type="url"][disabled],input[type="search"][disabled]{color:#999}.uneditable-input.disabled,.uneditable-textarea.disabled{color:#999;cursor:not-allowed;background-color:#f5f5f5;border-color:#ddd}textarea,.uneditable-textarea{height:60px}textarea[rows="1"],.uneditable-textarea[rows="1"]{height:40p
 x}textarea[rows="2"],.uneditable-textarea[rows="2"]{height:60px}textarea[rows="3"],.uneditable-textarea[rows="3"]{height:80px}textarea[rows="4"],.uneditable-textarea[rows="4"]{height:100px}textarea[rows="5"],.uneditable-textarea[rows="5"]{height:120px}textarea[rows="6"],.uneditable-textarea[rows="6"]{height:140px}textarea[rows="7"],.uneditable-textarea[rows="7"]{height:160px}textarea[rows="8"],.uneditable-textarea[rows="8"]{height:180px}textarea[rows="9"],.uneditable-textarea[rows="9"]{height:200px}textarea[rows="10"],.uneditable-textarea[rows="10"]{height:220px}textarea[rows="11"],.uneditable-textarea[rows="11"]{height:240px}textarea[rows="12"],.uneditable-textarea[rows="12"]{height:260px}textarea[rows="13"],.uneditable-textarea[rows="13"]{height:280px}textarea[rows="14"],.uneditable-textarea[rows="14"]{height:300px}textarea[rows="15"],.uneditable-textarea[rows="15"]{height:320px}textarea[rows="16"],.uneditable-textarea[rows="16"]{height:340px}textarea[rows="17"],.uneditable-textar
 ea[rows="17"]{height:360px}textarea[rows="18"],.uneditable-textarea[rows="18"]{height:380px}textarea[rows="19"],.uneditable-textarea[rows="19"]{height:400px}textarea[rows="20"],.uneditable-textarea[rows="20"]{height:420px}textarea[rows="21"],.uneditable-textarea[rows="21"]{height:440px}textarea[rows="22"],.uneditable-textarea[rows="22"]{height:460px}textarea[rows="23"],.uneditable-textarea[rows="23"]{height:480px}textarea[rows="24"],.uneditable-textarea[rows="24"]{height:500px}textarea[rows="25"],.uneditable-textarea[rows="25"]{height:520px}textarea[rows="26"],.uneditable-textarea[rows="26"]{height:540px}textarea[rows="27"],.uneditable-textarea[rows="27"]{height:560px}textarea[rows="28"],.uneditable-textarea[rows="28"]{height:580px}textarea[rows="29"],.uneditable-textarea[rows="29"]{height:600px}textarea[rows="30"],.uneditable-textarea[rows="30"]{height:620px}textarea[rows="35"],.uneditable-textarea[rows="35"]{height:720px}textarea[rows="40"],.uneditable-textarea[rows="40"]{height:8
 20px}textarea[rows="45"],.uneditable-textarea[rows="45"]{height:920px}textarea[rows="50"],.uneditable-textarea[rows="50"]{height:1020px}textarea[rows="55"],.uneditable-textarea[rows="55"]{height:1120px}textarea[rows="60"],.uneditable-textarea[rows="60"]{height:1220px}textarea[rows="65"],.uneditable-textarea[rows="65"]{height:1320px}textarea[rows="70"],.uneditable-textarea[rows="70"]{height:1420px}textarea[rows="75"],.uneditable-textarea[rows="75"]{height:1520px}textarea[rows="80"],.uneditable-textarea[rows="80"]{height:1620px}textarea[rows="85"],.uneditable-textarea[rows="85"]{height:1720px}textarea[rows="90"],.uneditable-textarea[rows="90"]{height:1820px}textarea[rows="95"],.uneditable-textarea[rows="95"]{height:1920px}textarea[rows="100"],.uneditable-textarea[rows="100"]{height:2020px}.uneditable-textarea{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.uneditable-input[class*="span"],.uneditable-textarea[class*="span"],.row-fluid .uneditable-input[c
 lass*="span"],.row-fluid .uneditable-textarea[class*="span"]{float:none;margin-left:0}.input-append .uneditable-input,.input-prepend .uneditable-input{vertical-align:top}.input-append .uneditable-input[class*="span"],.input-prepend .uneditable-input[class*="span"]{display:inline-block}.uneditable-form input[disabled],.uneditable-form textarea[disabled],.uneditable-form select[disabled]{cursor:auto}.uneditable-form .uneditable-input,.uneditable-form .uneditable-textarea{cursor:text}.uneditable-form .form-actions{background-color:transparent}.header-actions{padding:0 20px;line-height:36px}.table-actions{padding-bottom:20px;*zoom:1}.table-actions:before,.table-actions:after{display:table;line-height:0;content:""}.table-actions:after{clear:both}tr.rowlink td{cursor:pointer}tr.rowlink td.nolink{cursor:auto}.table tbody tr.rowlink:hover td{background-color:#cfcfcf}a.rowlink{font:inherit;color:inherit;text-decoration:inherit}.act{display:inline;padding:0;font-weight:bold;color:#555;backgro
 und:inherit;border:0;-webkit-transition:text-shadow .1s linear;-moz-transition:text-shadow .1s linear;-o-transition:text-shadow .1s linear;transition:text-shadow .1s linear}.act:hover{color:#333;text-decoration:none;text-shadow:1px 1px 3px rgba(85,85,85,0.5)}.act-primary{color:#006dcc}.act-primary:hover{color:#04c;text-shadow:1px 1px 3px rgba(0,109,204,0.5)}.act-info{color:#49afcd}.act-info:hover{color:#2f96b4;text-shadow:1px 1px 3px rgba(75,175,206,0.5)}.act-success{color:#51a351}.act-success:hover{color:#468847;text-shadow:1px 1px 3px rgba(81,164,81,0.5)}.act-warning{color:#c09853}.act-warning:hover{color:#f89406;text-shadow:1px 1px 3px rgba(192,152,84,0.5)}.act-danger{color:#b94a48}.act-danger:hover{color:#bd362f;text-shadow:1px 1px 3px rgba(185,72,70,0.5)}.act.disabled,.act[disabled]{color:#aaa;cursor:not-allowed}.act.disabled:hover,.act[disabled]:hover{color:#aaa;text-shadow:none}.form-actions .act{line-height:30px}@font-face{font-family:IconicStroke;font-weight:normal;src:url(
 ../font/iconic_stroke.eot);src:local('IconicStroke'),url(../font/iconic_stroke.eot?#iefix) format('embedded-opentype'),url(../font/iconic_stroke.woff) format('woff'),url(../font/iconic_stroke.ttf) format('truetype'),url(../font/iconic_stroke.svg#iconic) format('svg'),url(../font/iconic_stroke.otf) format('opentype')}@font-face{font-family:IconicFill;font-weight:normal;src:url(../font/iconic_fill.eot);src:local('IconicFill'),url(../font/iconic_fill.eot?#iefix) format('embedded-opentype'),url(../font/iconic_fill.woff) format('woff'),url(../font/iconic_fill.ttf) format('truetype'),url(../font/iconic_fill.svg#iconic) format('svg'),url(../font/iconic_fill.otf) format('opentype')}@media screen,print{[class*="iconic-"]{font-style:inherit;font-weight:normal;vertical-align:bottom}[class*="iconic-"]:before{display:inline-block;width:1em;font-family:IconicFill;font-size:.9em;text-align:center;vertical-align:middle;content:""}.iconic-stroke:before{font-family:IconicStroke}.iconic-hash:before{co
 ntent:'\23'}.iconic-question-mark:before{content:'\3f'}.iconic-at:before{content:'\40'}.iconic-pilcrow:before{content:'\b6'}.iconic-info:before{content:'\2139'}.iconic-arrow-left:before{content:'\2190'}.iconic-arrow-up:before{content:'\2191'}.iconic-arrow-right:before{content:'\2192'}.iconic-arrow-down:before{content:'\2193'}.iconic-home:before{content:'\2302'}.iconic-sun:before{content:'\2600'}.iconic-cloud:before{content:'\2601'}.iconic-umbrella:before{content:'\2602'}.iconic-star:before{content:'\2605'}.iconic-moon:before{content:'\263e'}.iconic-heart:before{content:'\2764'}.iconic-cog:before{content:'\2699'}.iconic-bolt:before{content:'\26a1'}.iconic-key:before{content:'\26bf'}.iconic-rain:before{content:'\26c6'}.iconic-denied:before{content:'\26d4'}.iconic-mail:before{content:'\2709'}.iconic-pen:before{content:'\270e'}.iconic-x:before{content:'\2717'}.iconic-o-x:before{content:'\2718'}.iconic-check:before{content:'\2713'}.iconic-o-check:before{content:'\2714'}.iconic-left-quote
 :before{content:'\275d'}.iconic-right-quote:before{content:'\275e'}.iconic-plus:before{content:'\2795'}.iconic-minus:before{content:'\2796'}.iconic-curved-arrow:before{content:'\2935'}.iconic-document-alt:before{content:'\e000'}.iconic-calendar:before{content:'\e001'}.iconic-map-pin-alt:before{content:'\e002'}.iconic-comment-alt1:before{content:'\e003'}.iconic-comment-alt2:before{content:'\e004'}.iconic-pen-alt:before{content:'\e005'}.iconic-pen-alt2:before{content:'\e006'}.iconic-chat-alt:before{content:'\e007'}.iconic-o-plus:before{content:'\e008'}.iconic-o-minus:before{content:'\e009'}.iconic-bars-alt:before{content:'\e00a'}.iconic-book-alt:before{content:'\e00b'}.iconic-aperture-alt:before{content:'\e00c'}.iconic-beaker-alt:before{content:'\e010'}.iconic-left-quote-alt:before{content:'\e011'}.iconic-right-quote-alt:before{content:'\e012'}.iconic-o-arrow-left:before{content:'\e013'}.iconic-o-arrow-up:before{content:'\e014'}.iconic-o-arrow-right:before{content:'\e015'}.iconic-o-ar
 row-down:before{content:'\e016'}.iconic-o-arrow-left-alt:before{content:'\e017'}.iconic-o-arrow-up-alt:before{content:'\e018'}.iconic-o-arrow-right-alt:before{content:'\e019'}.iconic-o-arrow-down-alt:before{content:'\e01a'}.iconic-brush:before{content:'\e01b'}.iconic-brush-alt:before{content:'\e01c'}.iconic-eyedropper:before{content:'\e01e'}.iconic-layers:before{content:'\e01f'}.iconic-layers-alt:before{content:'\e020'}.iconic-compass:before{content:'\e021'}.iconic-award:before{content:'\e022'}.iconic-beaker:before{content:'\e023'}.iconic-steering-wheel:before{content:'\e024'}.iconic-eye:before{content:'\e025'}.iconic-aperture:before{content:'\e026'}.iconic-image:before{content:'\e027'}.iconic-chart:before{content:'\e028'}.iconic-chart-alt:before{content:'\e029'}.iconic-target:before{content:'\e02a'}.iconic-tag:before{content:'\e02b'}.iconic-rss:before{content:'\e02c'}.iconic-rss-alt:before{content:'\e02d'}.iconic-share:before{content:'\e02e'}.iconic-undo:before{content:'\e02f'}.ico
 nic-reload:before{content:'\e030'}.iconic-reload-alt:before{content:'\e031'}.iconic-loop:before{content:'\e032'}.iconic-loop-alt:before{content:'\e033'}.iconic-back-forth:before{content:'\e034'}.iconic-back-forth-alt:before{content:'\e035'}.iconic-spin:before{content:'\e036'}.iconic-spin-alt:before{content:'\e037'}.iconic-move-horizontal:before{content:'\e038'}.iconic-move-horizontal-alt:before{content:'\e039'}.iconic-o-move-horizontal:before{content:'\e03a'}.iconic-move-vertical:before{content:'\e03b'}.iconic-move-vertical-alt:before{content:'\e03c'}.iconic-o-move-vertical:before{content:'\e03d'}.iconic-move:before{content:'\e03e'}.iconic-move-alt:before{content:'\e03f'}.iconic-o-move:before{content:'\e040'}.iconic-transfer:before{content:'\e041'}.iconic-download:before{content:'\e042'}.iconic-upload:before{content:'\e043'}.iconic-cloud-download:before{content:'\e044'}.iconic-cloud-upload:before{content:'\e045'}.iconic-fork:before{content:'\e046'}.iconic-play:before{content:'\e047'
 }.iconic-o-play:before{content:'\e048'}.iconic-pause:before{content:'\e049'}.iconic-stop:before{content:'\e04a'}.iconic-eject:before{content:'\e04b'}.iconic-first:before{content:'\e04c'}.iconic-last:before{content:'\e04d'}.iconic-fullscreen:before{content:'\e04e'}.iconic-fullscreen-alt:before{content:'\e04f'}.iconic-fullscreen-exit:before{content:'\e050'}.iconic-fullscreen-exit-alt:before{content:'\e051'}.iconic-equalizer:before{content:'\e052'}.iconic-article:before{content:'\e053'}.iconic-read-more:before{content:'\e054'}.iconic-list:before{content:'\e055'}.iconic-list-nested:before{content:'\e056'}.iconic-cursor:before{content:'\e057'}.iconic-dial:before{content:'\e058'}.iconic-new-window:before{content:'\e059'}.iconic-trash:before{content:'\e05a'}.iconic-battery-half:before{content:'\e05b'}.iconic-battery-empty:before{content:'\e05c'}.iconic-battery-charging:before{content:'\e05d'}.iconic-chat:before{content:'\e05e'}.iconic-mic:before{content:'\e05f'}.iconic-movie:before{content
 :'\e060'}.iconic-headphones:before{content:'\e061'}.iconic-user:before{content:'\e062'}.iconic-lightbulb:before{content:'\e063'}.iconic-cd:before{content:'\e064'}.iconic-folder:before{content:'\e065'}.iconic-document:before{content:'\e066'}.iconic-pin:before{content:'\e067'}.iconic-map-pin:before{content:'\e068'}.iconic-book:before{content:'\e069'}.iconic-book-alt2:before{content:'\e06a'}.iconic-box:before{content:'\e06b'}.iconic-calendar-alt:before{content:'\e06c'}.iconic-comment:before{content:'\e06d'}.iconic-iphone:before{content:'\e06e'}.iconic-bars:before{content:'\e06f'}.iconic-camera:before{content:'\e070'}.iconic-volume-mute:before{content:'\e071'}.iconic-volume:before{content:'\e072'}.iconic-battery-full:before{content:'\e073'}.iconic-magnifying-glass:before{content:'\e074'}.iconic-lock:before{content:'\e075'}.iconic-unlock:before{content:'\e076'}.iconic-link:before{content:'\e077'}.iconic-wrench:before{content:'\e078'}.iconic-clock:before{content:'\e079'}.iconic-sun-stroke
 :before{font-family:IconicStroke;content:'\2600'}.iconic-moon-stroke:before{font-family:IconicStroke;content:'\263e'}.iconic-star-stroke:before{font-family:IconicStroke;content:'\2605'}.iconic-heart-stroke:before{font-family:IconicStroke;content:'\2764'}.iconic-key-stroke:before{font-family:IconicStroke;content:'\26bf'}.iconic-document-alt-stroke:before{font-family:IconicStroke;content:'\e000'}.iconic-comment-alt1-stroke:before{font-family:IconicStroke;content:'\e003'}.iconic-comment-alt2-stroke:before{font-family:IconicStroke;content:'\e004'}.iconic-pen-alt-stroke:before{font-family:IconicStroke;content:'\e005'}.iconic-chat-alt-stroke:before{font-family:IconicStroke;content:'\e007'}.iconic-award-stroke:before{font-family:IconicStroke;content:'\e022'}.iconic-tag-stroke:before{font-family:IconicStroke;content:'\e02b'}.iconic-trash-stroke:before{font-family:IconicStroke;content:'\e05a'}.iconic-folder-stroke:before{font-family:IconicStroke;content:'\e065'}.iconic-document-stroke:before
 {font-family:IconicStroke;content:'\e066'}.iconic-map-pin-stroke:before{font-family:IconicStroke;content:'\e068'}.iconic-calendar-alt-stroke:before{font-family:IconicStroke;content:'\e06c'}.iconic-comment-stroke:before{font-family:IconicStroke;content:'\e06d'}.iconic-lock-stroke:before{font-family:IconicStroke;content:'\e075'}.iconic-unlock-stroke:before{font-family:IconicStroke;content:'\e076'}}.page-alert{position:absolute;top:0;left:50%;z-index:1020;width:0}.page-alert .alert{width:550px;margin-left:-300px;border-top-width:0;-webkit-border-radius:0 0 4px 4px;-moz-border-radius:0 0 4px 4px;border-radius:0 0 4px 4px}.navbar-fixed-top+.page-alert{top:40px}body>.page-alert{position:fixed}.btn-file{position:relative;overflow:hidden;vertical-align:middle}.btn-file>input{position:absolute;top:0;right:0;margin:0;font-size:23px;cursor:pointer;opacity:0;filter:alpha(opacity=0);transform:translate(-300px,0) scale(4);direction:ltr}.fileupload{margin-bottom:9px}.fileupload .uneditable-input{d
 isplay:inline-block;margin-bottom:0;vertical-align:middle;cursor:text}.fileupload .thumbnail{display:inline-block;margin-bottom:5px;overflow:hidden;text-align:center;vertical-align:middle}.fileupload .thumbnail>img{display:inline-block;max-height:100%;vertical-align:middle}.fileupload .btn{vertical-align:middle}.fileupload-exists .fileupload-new,.fileupload-new .fileupload-exists{display:none}.fileupload-inline .fileupload-controls{display:inline}.fileupload-new .input-append .btn-file{-webkit-border-radius:0 3px 3px 0;-moz-border-radius:0 3px 3px 0;border-radius:0 3px 3px 0}.thumbnail-borderless .thumbnail{padding:0;border:0;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none}.fileupload-new.thumbnail-borderless .thumbnail{border:1px solid #ddd}.control-group.warning .fileupload .uneditable-input{color:#a47e3c;border-color:#a47e3c}.control-group.warning .fileupload .fileupload-preview{color:#a47e3c}.control-group
 .warning .fileupload .thumbnail{border-color:#a47e3c}.control-group.error .fileupload .uneditable-input{color:#b94a48;border-color:#b94a48}.control-group.error .fileupload .fileupload-preview{color:#b94a48}.control-group.error .fileupload .thumbnail{border-color:#b94a48}.control-group.success .fileupload .uneditable-input{color:#468847;border-color:#468847}.control-group.success .fileupload .fileupload-preview{color:#468847}.control-group.success .fileupload .thumbnail{border-color:#468847}.nav-tabs>li>a,.nav-pills>li>a{outline:0}.nav-tabs>li.disabled>a{color:#ccc;cursor:not-allowed}.tabbable{border-color:#ddd;border-style:solid;border-width:0;*zoom:1}.tabbable:before,.tabbable:after{display:table;line-height:0;content:""}.tabbable:after{clear:both}.tabbable>.nav-tabs{margin:0}.tab-content{padding:18px 0 0 0;overflow:auto;border-color:#ddd;border-style:solid;border-width:0}.tabbable-bordered{-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.tabbable-bordered>.tab-c
 ontent{padding:20px 20px 10px 20px;border-width:0 1px 1px 1px;-webkit-border-radius:0 0 4px 4px;-moz-border-radius:0 0 4px 4px;border-radius:0 0 4px 4px}body>.container.tabbable>.nav-tabs{padding-top:15px}.tabs-below>.tab-content{padding:0 0 10px 0}.tabs-below.tabbable-bordered>.tab-content{padding:20px 20px 10px 20px;border-width:1px 1px 0 1px;-webkit-border-radius:4px 4px 0 0;-moz-border-radius:4px 4px 0 0;border-radius:4px 4px 0 0}body>.container.tabs-below.tabbable-bodered>.tab-content{border-top-width:0;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.tabs-left,.tabs-right{margin-bottom:20px}.tabs-left>.nav-tabs,.tabs-right>.nav-tabs{position:relative;z-index:1;margin-bottom:0}.tabs-left>.tab-content,.tabs-right>.tab-content{overflow:hidden}.tabs-left>.nav-tabs{left:1px}.tabs-left>.nav-tabs>.active>a,.tabs-left>.nav-tabs>.active>a:hover{border-color:#ddd transparent #ddd #ddd;*border-right-color:#fff}.tabs-left>.tab-content{padding:0 0 0 19px;border-left-width:1px}
 .tabs-left.tabbable-bordered{border-width:0 1px 0 0}.tabs-left.tabbable-bordered>.tab-content{padding:20px 20px 10px 20px;border-width:1px 0 1px 1px;-webkit-border-radius:0 4px 4px 0;-moz-border-radius:0 4px 4px 0;border-radius:0 4px 4px 0}body>.container.tabs-left.tabbable-bodered>.tab-content{border-top-width:0;-webkit-border-radius:0 0 4px 0;-moz-border-radius:0 0 4px 0;border-radius:0 0 4px 0}.tabs-right>.nav-tabs{right:1px}.tabs-right>.nav-tabs>.active>a,.tabs-right>.nav-tabs>.active>a:hover{border-color:#ddd #ddd #ddd transparent;*border-left-color:#fff}.tabs-right>.tab-content{padding:0 19px 0 0;border-right-width:1px}.tabs-right.tabbable-bordered{border-width:0 0 0 1px}.tabs-right.tabbable-bordered>.tab-content{padding:20px 20px 10px 20px;border-width:1px 1px 1px 0;-webkit-border-radius:4px 0 0 4px;-moz-border-radius:4px 0 0 4px;border-radius:4px 0 0 4px}body>.container.tabs-right.tabbable-bodered>.tab-content{border-top-width:0;-webkit-border-radius:0 0 0 4px;-moz-border-ra
 dius:0 0 0 4px;border-radius:0 0 0 4px}

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/app/font/.svn/all-wcprops
----------------------------------------------------------------------
diff --git a/src/main/ui/app/font/.svn/all-wcprops b/src/main/ui/app/font/.svn/all-wcprops
new file mode 100755
index 0000000..2925d03
--- /dev/null
+++ b/src/main/ui/app/font/.svn/all-wcprops
@@ -0,0 +1,35 @@
+K 25
+svn:wc:ra_dav:version-url
+V 78
+/repos/asf/!svn/ver/1480068/incubator/climate/trunk/rcmet/src/main/ui/app/font
+END
+fontawesome-webfont.eot
+K 25
+svn:wc:ra_dav:version-url
+V 102
+/repos/asf/!svn/ver/1480068/incubator/climate/trunk/rcmet/src/main/ui/app/font/fontawesome-webfont.eot
+END
+fontawesome-webfont.ttf
+K 25
+svn:wc:ra_dav:version-url
+V 102
+/repos/asf/!svn/ver/1480068/incubator/climate/trunk/rcmet/src/main/ui/app/font/fontawesome-webfont.ttf
+END
+fontawesome-webfont.svg
+K 25
+svn:wc:ra_dav:version-url
+V 102
+/repos/asf/!svn/ver/1480068/incubator/climate/trunk/rcmet/src/main/ui/app/font/fontawesome-webfont.svg
+END
+fontawesome-webfont.woff
+K 25
+svn:wc:ra_dav:version-url
+V 103
+/repos/asf/!svn/ver/1480068/incubator/climate/trunk/rcmet/src/main/ui/app/font/fontawesome-webfont.woff
+END
+FontAwesome.otf
+K 25
+svn:wc:ra_dav:version-url
+V 94
+/repos/asf/!svn/ver/1480068/incubator/climate/trunk/rcmet/src/main/ui/app/font/FontAwesome.otf
+END

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/app/font/.svn/entries
----------------------------------------------------------------------
diff --git a/src/main/ui/app/font/.svn/entries b/src/main/ui/app/font/.svn/entries
new file mode 100755
index 0000000..37d1d60
--- /dev/null
+++ b/src/main/ui/app/font/.svn/entries
@@ -0,0 +1,198 @@
+10
+
+dir
+1485921
+https://svn.apache.org/repos/asf/incubator/climate/trunk/rcmet/src/main/ui/app/font
+https://svn.apache.org/repos/asf
+
+
+
+2013-05-07T20:50:17.582309Z
+1480068
+joyce
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+13f79535-47bb-0310-9956-ffa450edef68
+
+fontawesome-webfont.eot
+file
+
+
+
+
+2013-05-24T10:13:56.000000Z
+455808250694e5760bd92b3ce1f070b6
+2013-05-07T20:50:17.582309Z
+1480068
+joyce
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+25395
+
+fontawesome-webfont.ttf
+file
+
+
+
+
+2013-05-24T10:13:56.000000Z
+bb72c5142ae2ae4ca0f9c0653a09871c
+2013-05-07T20:50:17.582309Z
+1480068
+joyce
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+55096
+
+fontawesome-webfont.svg
+file
+
+
+
+
+2013-05-24T10:13:56.000000Z
+b8e4dbe6872f049283c54da9d94a7b7a
+2013-05-07T20:50:17.582309Z
+1480068
+joyce
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+138488
+
+fontawesome-webfont.woff
+file
+
+
+
+
+2013-05-24T10:13:56.000000Z
+21f212f94a9db6a0e3847c921842aa19
+2013-05-07T20:50:17.582309Z
+1480068
+joyce
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+29380
+
+FontAwesome.otf
+file
+
+
+
+
+2013-05-24T10:13:56.000000Z
+59dc59981f8221f5409f1abbca3fd077
+2013-05-07T20:50:17.582309Z
+1480068
+joyce
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+48748
+

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/app/font/.svn/prop-base/FontAwesome.otf.svn-base
----------------------------------------------------------------------
diff --git a/src/main/ui/app/font/.svn/prop-base/FontAwesome.otf.svn-base b/src/main/ui/app/font/.svn/prop-base/FontAwesome.otf.svn-base
new file mode 100755
index 0000000..dbc918b
--- /dev/null
+++ b/src/main/ui/app/font/.svn/prop-base/FontAwesome.otf.svn-base
@@ -0,0 +1,9 @@
+K 14
+svn:executable
+V 1
+*
+K 13
+svn:mime-type
+V 24
+application/octet-stream
+END

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/app/font/.svn/prop-base/fontawesome-webfont.eot.svn-base
----------------------------------------------------------------------
diff --git a/src/main/ui/app/font/.svn/prop-base/fontawesome-webfont.eot.svn-base b/src/main/ui/app/font/.svn/prop-base/fontawesome-webfont.eot.svn-base
new file mode 100755
index 0000000..dbc918b
--- /dev/null
+++ b/src/main/ui/app/font/.svn/prop-base/fontawesome-webfont.eot.svn-base
@@ -0,0 +1,9 @@
+K 14
+svn:executable
+V 1
+*
+K 13
+svn:mime-type
+V 24
+application/octet-stream
+END

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/app/font/.svn/prop-base/fontawesome-webfont.svg.svn-base
----------------------------------------------------------------------
diff --git a/src/main/ui/app/font/.svn/prop-base/fontawesome-webfont.svg.svn-base b/src/main/ui/app/font/.svn/prop-base/fontawesome-webfont.svg.svn-base
new file mode 100755
index 0000000..869ac71
--- /dev/null
+++ b/src/main/ui/app/font/.svn/prop-base/fontawesome-webfont.svg.svn-base
@@ -0,0 +1,5 @@
+K 14
+svn:executable
+V 1
+*
+END

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/app/font/.svn/prop-base/fontawesome-webfont.ttf.svn-base
----------------------------------------------------------------------
diff --git a/src/main/ui/app/font/.svn/prop-base/fontawesome-webfont.ttf.svn-base b/src/main/ui/app/font/.svn/prop-base/fontawesome-webfont.ttf.svn-base
new file mode 100755
index 0000000..dbc918b
--- /dev/null
+++ b/src/main/ui/app/font/.svn/prop-base/fontawesome-webfont.ttf.svn-base
@@ -0,0 +1,9 @@
+K 14
+svn:executable
+V 1
+*
+K 13
+svn:mime-type
+V 24
+application/octet-stream
+END

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/app/font/.svn/prop-base/fontawesome-webfont.woff.svn-base
----------------------------------------------------------------------
diff --git a/src/main/ui/app/font/.svn/prop-base/fontawesome-webfont.woff.svn-base b/src/main/ui/app/font/.svn/prop-base/fontawesome-webfont.woff.svn-base
new file mode 100755
index 0000000..dbc918b
--- /dev/null
+++ b/src/main/ui/app/font/.svn/prop-base/fontawesome-webfont.woff.svn-base
@@ -0,0 +1,9 @@
+K 14
+svn:executable
+V 1
+*
+K 13
+svn:mime-type
+V 24
+application/octet-stream
+END

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/app/font/.svn/text-base/FontAwesome.otf.svn-base
----------------------------------------------------------------------
diff --git a/src/main/ui/app/font/.svn/text-base/FontAwesome.otf.svn-base b/src/main/ui/app/font/.svn/text-base/FontAwesome.otf.svn-base
new file mode 100755
index 0000000..64049bf
Binary files /dev/null and b/src/main/ui/app/font/.svn/text-base/FontAwesome.otf.svn-base differ

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/app/font/.svn/text-base/fontawesome-webfont.eot.svn-base
----------------------------------------------------------------------
diff --git a/src/main/ui/app/font/.svn/text-base/fontawesome-webfont.eot.svn-base b/src/main/ui/app/font/.svn/text-base/fontawesome-webfont.eot.svn-base
new file mode 100755
index 0000000..7d81019
Binary files /dev/null and b/src/main/ui/app/font/.svn/text-base/fontawesome-webfont.eot.svn-base differ


[20/51] [abbrv] [partial] Adding Jinwon's custom RCMET

Posted by jo...@apache.org.
http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/app/js/services.js
----------------------------------------------------------------------
diff --git a/src/main/ui/app/js/services.js b/src/main/ui/app/js/services.js
new file mode 100755
index 0000000..334d543
--- /dev/null
+++ b/src/main/ui/app/js/services.js
@@ -0,0 +1,9 @@
+'use strict';
+
+/* Services */
+
+
+// Demonstrate how to register services
+// In this case it is a simple value service.
+angular.module('myApp.services', []).
+  value('version', '0.1');

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/app/lib/.svn/all-wcprops
----------------------------------------------------------------------
diff --git a/src/main/ui/app/lib/.svn/all-wcprops b/src/main/ui/app/lib/.svn/all-wcprops
new file mode 100755
index 0000000..a9b41b7
--- /dev/null
+++ b/src/main/ui/app/lib/.svn/all-wcprops
@@ -0,0 +1,5 @@
+K 25
+svn:wc:ra_dav:version-url
+V 77
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/ui/app/lib
+END

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/app/lib/.svn/entries
----------------------------------------------------------------------
diff --git a/src/main/ui/app/lib/.svn/entries b/src/main/ui/app/lib/.svn/entries
new file mode 100755
index 0000000..cecbedd
--- /dev/null
+++ b/src/main/ui/app/lib/.svn/entries
@@ -0,0 +1,31 @@
+10
+
+dir
+1485921
+https://svn.apache.org/repos/asf/incubator/climate/trunk/rcmet/src/main/ui/app/lib
+https://svn.apache.org/repos/asf
+
+
+
+2013-03-13T02:34:30.834306Z
+1475137
+mjjoyce
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+13f79535-47bb-0310-9956-ffa450edef68
+
+angular
+dir
+

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/app/lib/angular/.svn/all-wcprops
----------------------------------------------------------------------
diff --git a/src/main/ui/app/lib/angular/.svn/all-wcprops b/src/main/ui/app/lib/angular/.svn/all-wcprops
new file mode 100755
index 0000000..f5b4b9c
--- /dev/null
+++ b/src/main/ui/app/lib/angular/.svn/all-wcprops
@@ -0,0 +1,71 @@
+K 25
+svn:wc:ra_dav:version-url
+V 85
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/ui/app/lib/angular
+END
+angular-cookies.min.js
+K 25
+svn:wc:ra_dav:version-url
+V 108
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/ui/app/lib/angular/angular-cookies.min.js
+END
+version.txt
+K 25
+svn:wc:ra_dav:version-url
+V 97
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/ui/app/lib/angular/version.txt
+END
+angular.js
+K 25
+svn:wc:ra_dav:version-url
+V 96
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/ui/app/lib/angular/angular.js
+END
+angular.min.js
+K 25
+svn:wc:ra_dav:version-url
+V 100
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/ui/app/lib/angular/angular.min.js
+END
+angular-loader.js
+K 25
+svn:wc:ra_dav:version-url
+V 103
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/ui/app/lib/angular/angular-loader.js
+END
+angular-sanitize.js
+K 25
+svn:wc:ra_dav:version-url
+V 105
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/ui/app/lib/angular/angular-sanitize.js
+END
+angular-resource.js
+K 25
+svn:wc:ra_dav:version-url
+V 105
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/ui/app/lib/angular/angular-resource.js
+END
+angular-loader.min.js
+K 25
+svn:wc:ra_dav:version-url
+V 107
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/ui/app/lib/angular/angular-loader.min.js
+END
+angular-sanitize.min.js
+K 25
+svn:wc:ra_dav:version-url
+V 109
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/ui/app/lib/angular/angular-sanitize.min.js
+END
+angular-resource.min.js
+K 25
+svn:wc:ra_dav:version-url
+V 109
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/ui/app/lib/angular/angular-resource.min.js
+END
+angular-cookies.js
+K 25
+svn:wc:ra_dav:version-url
+V 104
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/ui/app/lib/angular/angular-cookies.js
+END

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/app/lib/angular/.svn/entries
----------------------------------------------------------------------
diff --git a/src/main/ui/app/lib/angular/.svn/entries b/src/main/ui/app/lib/angular/.svn/entries
new file mode 100755
index 0000000..d47478a
--- /dev/null
+++ b/src/main/ui/app/lib/angular/.svn/entries
@@ -0,0 +1,402 @@
+10
+
+dir
+1485921
+https://svn.apache.org/repos/asf/incubator/climate/trunk/rcmet/src/main/ui/app/lib/angular
+https://svn.apache.org/repos/asf
+
+
+
+2013-03-13T02:34:30.834306Z
+1475137
+mjjoyce
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+13f79535-47bb-0310-9956-ffa450edef68
+
+angular-cookies.min.js
+file
+
+
+
+
+2013-05-24T10:13:56.000000Z
+1e2ba4a796d14e19bc25394fae2b7253
+2013-03-13T02:34:30.834306Z
+1475137
+mjjoyce
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+792
+
+version.txt
+file
+
+
+
+
+2013-05-24T10:13:56.000000Z
+34cd1f67e8156bf27ba489aacd9acb1f
+2013-03-13T02:34:30.834306Z
+1475137
+mjjoyce
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+6
+
+angular.js
+file
+
+
+
+
+2013-05-24T10:13:56.000000Z
+b7d6c5dad5732e73c8191b9f248f91eb
+2013-03-13T02:34:30.834306Z
+1475137
+mjjoyce
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+488868
+
+angular.min.js
+file
+
+
+
+
+2013-05-24T10:13:56.000000Z
+32916703df7b29666deb89284e6ebc50
+2013-03-13T02:34:30.834306Z
+1475137
+mjjoyce
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+80008
+
+angular-loader.js
+file
+
+
+
+
+2013-05-24T10:13:56.000000Z
+10ee9e506267e7afee5f70609a99f034
+2013-03-13T02:34:30.834306Z
+1475137
+mjjoyce
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+9096
+
+angular-sanitize.js
+file
+
+
+
+
+2013-05-24T10:13:56.000000Z
+a85362d3adb16a52eaedc3bb464f6a2b
+2013-03-13T02:34:30.834306Z
+1475137
+mjjoyce
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+17442
+
+angular-resource.js
+file
+
+
+
+
+2013-05-24T10:13:56.000000Z
+01b692edff4ca8375522e71047f59074
+2013-03-13T02:34:30.834306Z
+1475137
+mjjoyce
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+16767
+
+angular-loader.min.js
+file
+
+
+
+
+2013-05-24T10:13:57.000000Z
+b040d6a7f758f72fe96ebc7f648ce7f0
+2013-03-13T02:34:30.834306Z
+1475137
+mjjoyce
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+881
+
+angular-sanitize.min.js
+file
+
+
+
+
+2013-05-24T10:13:57.000000Z
+73bf459c20031b9f0b1bd19de24c1ef9
+2013-03-13T02:34:30.834306Z
+1475137
+mjjoyce
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+3883
+
+angular-resource.min.js
+file
+
+
+
+
+2013-05-24T10:13:57.000000Z
+e40335b59115eb510467e952e1b79211
+2013-03-13T02:34:30.834306Z
+1475137
+mjjoyce
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+2571
+
+angular-cookies.js
+file
+
+
+
+
+2013-05-24T10:13:57.000000Z
+3755c4726c7dff9667c59f828620c6c2
+2013-03-13T02:34:30.834306Z
+1475137
+mjjoyce
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+5168
+

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/app/lib/angular/.svn/prop-base/angular-cookies.js.svn-base
----------------------------------------------------------------------
diff --git a/src/main/ui/app/lib/angular/.svn/prop-base/angular-cookies.js.svn-base b/src/main/ui/app/lib/angular/.svn/prop-base/angular-cookies.js.svn-base
new file mode 100755
index 0000000..869ac71
--- /dev/null
+++ b/src/main/ui/app/lib/angular/.svn/prop-base/angular-cookies.js.svn-base
@@ -0,0 +1,5 @@
+K 14
+svn:executable
+V 1
+*
+END

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/app/lib/angular/.svn/prop-base/angular-cookies.min.js.svn-base
----------------------------------------------------------------------
diff --git a/src/main/ui/app/lib/angular/.svn/prop-base/angular-cookies.min.js.svn-base b/src/main/ui/app/lib/angular/.svn/prop-base/angular-cookies.min.js.svn-base
new file mode 100755
index 0000000..869ac71
--- /dev/null
+++ b/src/main/ui/app/lib/angular/.svn/prop-base/angular-cookies.min.js.svn-base
@@ -0,0 +1,5 @@
+K 14
+svn:executable
+V 1
+*
+END

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/app/lib/angular/.svn/prop-base/angular-loader.js.svn-base
----------------------------------------------------------------------
diff --git a/src/main/ui/app/lib/angular/.svn/prop-base/angular-loader.js.svn-base b/src/main/ui/app/lib/angular/.svn/prop-base/angular-loader.js.svn-base
new file mode 100755
index 0000000..869ac71
--- /dev/null
+++ b/src/main/ui/app/lib/angular/.svn/prop-base/angular-loader.js.svn-base
@@ -0,0 +1,5 @@
+K 14
+svn:executable
+V 1
+*
+END

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/app/lib/angular/.svn/prop-base/angular-loader.min.js.svn-base
----------------------------------------------------------------------
diff --git a/src/main/ui/app/lib/angular/.svn/prop-base/angular-loader.min.js.svn-base b/src/main/ui/app/lib/angular/.svn/prop-base/angular-loader.min.js.svn-base
new file mode 100755
index 0000000..869ac71
--- /dev/null
+++ b/src/main/ui/app/lib/angular/.svn/prop-base/angular-loader.min.js.svn-base
@@ -0,0 +1,5 @@
+K 14
+svn:executable
+V 1
+*
+END

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/app/lib/angular/.svn/prop-base/angular-resource.js.svn-base
----------------------------------------------------------------------
diff --git a/src/main/ui/app/lib/angular/.svn/prop-base/angular-resource.js.svn-base b/src/main/ui/app/lib/angular/.svn/prop-base/angular-resource.js.svn-base
new file mode 100755
index 0000000..869ac71
--- /dev/null
+++ b/src/main/ui/app/lib/angular/.svn/prop-base/angular-resource.js.svn-base
@@ -0,0 +1,5 @@
+K 14
+svn:executable
+V 1
+*
+END

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/app/lib/angular/.svn/prop-base/angular-resource.min.js.svn-base
----------------------------------------------------------------------
diff --git a/src/main/ui/app/lib/angular/.svn/prop-base/angular-resource.min.js.svn-base b/src/main/ui/app/lib/angular/.svn/prop-base/angular-resource.min.js.svn-base
new file mode 100755
index 0000000..869ac71
--- /dev/null
+++ b/src/main/ui/app/lib/angular/.svn/prop-base/angular-resource.min.js.svn-base
@@ -0,0 +1,5 @@
+K 14
+svn:executable
+V 1
+*
+END

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/app/lib/angular/.svn/prop-base/angular-sanitize.js.svn-base
----------------------------------------------------------------------
diff --git a/src/main/ui/app/lib/angular/.svn/prop-base/angular-sanitize.js.svn-base b/src/main/ui/app/lib/angular/.svn/prop-base/angular-sanitize.js.svn-base
new file mode 100755
index 0000000..869ac71
--- /dev/null
+++ b/src/main/ui/app/lib/angular/.svn/prop-base/angular-sanitize.js.svn-base
@@ -0,0 +1,5 @@
+K 14
+svn:executable
+V 1
+*
+END

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/app/lib/angular/.svn/prop-base/angular-sanitize.min.js.svn-base
----------------------------------------------------------------------
diff --git a/src/main/ui/app/lib/angular/.svn/prop-base/angular-sanitize.min.js.svn-base b/src/main/ui/app/lib/angular/.svn/prop-base/angular-sanitize.min.js.svn-base
new file mode 100755
index 0000000..869ac71
--- /dev/null
+++ b/src/main/ui/app/lib/angular/.svn/prop-base/angular-sanitize.min.js.svn-base
@@ -0,0 +1,5 @@
+K 14
+svn:executable
+V 1
+*
+END

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/app/lib/angular/.svn/prop-base/angular.js.svn-base
----------------------------------------------------------------------
diff --git a/src/main/ui/app/lib/angular/.svn/prop-base/angular.js.svn-base b/src/main/ui/app/lib/angular/.svn/prop-base/angular.js.svn-base
new file mode 100755
index 0000000..869ac71
--- /dev/null
+++ b/src/main/ui/app/lib/angular/.svn/prop-base/angular.js.svn-base
@@ -0,0 +1,5 @@
+K 14
+svn:executable
+V 1
+*
+END

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/app/lib/angular/.svn/prop-base/angular.min.js.svn-base
----------------------------------------------------------------------
diff --git a/src/main/ui/app/lib/angular/.svn/prop-base/angular.min.js.svn-base b/src/main/ui/app/lib/angular/.svn/prop-base/angular.min.js.svn-base
new file mode 100755
index 0000000..869ac71
--- /dev/null
+++ b/src/main/ui/app/lib/angular/.svn/prop-base/angular.min.js.svn-base
@@ -0,0 +1,5 @@
+K 14
+svn:executable
+V 1
+*
+END

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/app/lib/angular/.svn/prop-base/version.txt.svn-base
----------------------------------------------------------------------
diff --git a/src/main/ui/app/lib/angular/.svn/prop-base/version.txt.svn-base b/src/main/ui/app/lib/angular/.svn/prop-base/version.txt.svn-base
new file mode 100755
index 0000000..869ac71
--- /dev/null
+++ b/src/main/ui/app/lib/angular/.svn/prop-base/version.txt.svn-base
@@ -0,0 +1,5 @@
+K 14
+svn:executable
+V 1
+*
+END

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/app/lib/angular/.svn/text-base/angular-cookies.js.svn-base
----------------------------------------------------------------------
diff --git a/src/main/ui/app/lib/angular/.svn/text-base/angular-cookies.js.svn-base b/src/main/ui/app/lib/angular/.svn/text-base/angular-cookies.js.svn-base
new file mode 100755
index 0000000..fbf0acb
--- /dev/null
+++ b/src/main/ui/app/lib/angular/.svn/text-base/angular-cookies.js.svn-base
@@ -0,0 +1,183 @@
+/**
+ * @license AngularJS v1.0.5
+ * (c) 2010-2012 Google, Inc. http://angularjs.org
+ * License: MIT
+ */
+(function(window, angular, undefined) {
+'use strict';
+
+/**
+ * @ngdoc overview
+ * @name ngCookies
+ */
+
+
+angular.module('ngCookies', ['ng']).
+  /**
+   * @ngdoc object
+   * @name ngCookies.$cookies
+   * @requires $browser
+   *
+   * @description
+   * Provides read/write access to browser's cookies.
+   *
+   * Only a simple Object is exposed and by adding or removing properties to/from
+   * this object, new cookies are created/deleted at the end of current $eval.
+   *
+   * @example
+   <doc:example>
+     <doc:source>
+       <script>
+         function ExampleController($cookies) {
+           // Retrieving a cookie
+           var favoriteCookie = $cookies.myFavorite;
+           // Setting a cookie
+           $cookies.myFavorite = 'oatmeal';
+         }
+       </script>
+     </doc:source>
+   </doc:example>
+   */
+   factory('$cookies', ['$rootScope', '$browser', function ($rootScope, $browser) {
+      var cookies = {},
+          lastCookies = {},
+          lastBrowserCookies,
+          runEval = false,
+          copy = angular.copy,
+          isUndefined = angular.isUndefined;
+
+      //creates a poller fn that copies all cookies from the $browser to service & inits the service
+      $browser.addPollFn(function() {
+        var currentCookies = $browser.cookies();
+        if (lastBrowserCookies != currentCookies) { //relies on browser.cookies() impl
+          lastBrowserCookies = currentCookies;
+          copy(currentCookies, lastCookies);
+          copy(currentCookies, cookies);
+          if (runEval) $rootScope.$apply();
+        }
+      })();
+
+      runEval = true;
+
+      //at the end of each eval, push cookies
+      //TODO: this should happen before the "delayed" watches fire, because if some cookies are not
+      //      strings or browser refuses to store some cookies, we update the model in the push fn.
+      $rootScope.$watch(push);
+
+      return cookies;
+
+
+      /**
+       * Pushes all the cookies from the service to the browser and verifies if all cookies were stored.
+       */
+      function push() {
+        var name,
+            value,
+            browserCookies,
+            updated;
+
+        //delete any cookies deleted in $cookies
+        for (name in lastCookies) {
+          if (isUndefined(cookies[name])) {
+            $browser.cookies(name, undefined);
+          }
+        }
+
+        //update all cookies updated in $cookies
+        for(name in cookies) {
+          value = cookies[name];
+          if (!angular.isString(value)) {
+            if (angular.isDefined(lastCookies[name])) {
+              cookies[name] = lastCookies[name];
+            } else {
+              delete cookies[name];
+            }
+          } else if (value !== lastCookies[name]) {
+            $browser.cookies(name, value);
+            updated = true;
+          }
+        }
+
+        //verify what was actually stored
+        if (updated){
+          updated = false;
+          browserCookies = $browser.cookies();
+
+          for (name in cookies) {
+            if (cookies[name] !== browserCookies[name]) {
+              //delete or reset all cookies that the browser dropped from $cookies
+              if (isUndefined(browserCookies[name])) {
+                delete cookies[name];
+              } else {
+                cookies[name] = browserCookies[name];
+              }
+              updated = true;
+            }
+          }
+        }
+      }
+    }]).
+
+
+  /**
+   * @ngdoc object
+   * @name ngCookies.$cookieStore
+   * @requires $cookies
+   *
+   * @description
+   * Provides a key-value (string-object) storage, that is backed by session cookies.
+   * Objects put or retrieved from this storage are automatically serialized or
+   * deserialized by angular's toJson/fromJson.
+   * @example
+   */
+   factory('$cookieStore', ['$cookies', function($cookies) {
+
+      return {
+        /**
+         * @ngdoc method
+         * @name ngCookies.$cookieStore#get
+         * @methodOf ngCookies.$cookieStore
+         *
+         * @description
+         * Returns the value of given cookie key
+         *
+         * @param {string} key Id to use for lookup.
+         * @returns {Object} Deserialized cookie value.
+         */
+        get: function(key) {
+          return angular.fromJson($cookies[key]);
+        },
+
+        /**
+         * @ngdoc method
+         * @name ngCookies.$cookieStore#put
+         * @methodOf ngCookies.$cookieStore
+         *
+         * @description
+         * Sets a value for given cookie key
+         *
+         * @param {string} key Id for the `value`.
+         * @param {Object} value Value to be stored.
+         */
+        put: function(key, value) {
+          $cookies[key] = angular.toJson(value);
+        },
+
+        /**
+         * @ngdoc method
+         * @name ngCookies.$cookieStore#remove
+         * @methodOf ngCookies.$cookieStore
+         *
+         * @description
+         * Remove given cookie
+         *
+         * @param {string} key Id of the key-value pair to delete.
+         */
+        remove: function(key) {
+          delete $cookies[key];
+        }
+      };
+
+    }]);
+
+})(window, window.angular);

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/app/lib/angular/.svn/text-base/angular-cookies.min.js.svn-base
----------------------------------------------------------------------
diff --git a/src/main/ui/app/lib/angular/.svn/text-base/angular-cookies.min.js.svn-base b/src/main/ui/app/lib/angular/.svn/text-base/angular-cookies.min.js.svn-base
new file mode 100755
index 0000000..bd82c75
--- /dev/null
+++ b/src/main/ui/app/lib/angular/.svn/text-base/angular-cookies.min.js.svn-base
@@ -0,0 +1,7 @@
+/*
+ AngularJS v1.0.5
+ (c) 2010-2012 Google, Inc. http://angularjs.org
+ License: MIT
+*/
+(function(m,f,l){'use strict';f.module("ngCookies",["ng"]).factory("$cookies",["$rootScope","$browser",function(d,c){var b={},g={},h,i=!1,j=f.copy,k=f.isUndefined;c.addPollFn(function(){var a=c.cookies();h!=a&&(h=a,j(a,g),j(a,b),i&&d.$apply())})();i=!0;d.$watch(function(){var a,e,d;for(a in g)k(b[a])&&c.cookies(a,l);for(a in b)e=b[a],f.isString(e)?e!==g[a]&&(c.cookies(a,e),d=!0):f.isDefined(g[a])?b[a]=g[a]:delete b[a];if(d)for(a in e=c.cookies(),b)b[a]!==e[a]&&(k(e[a])?delete b[a]:b[a]=e[a])});return b}]).factory("$cookieStore",
+["$cookies",function(d){return{get:function(c){return f.fromJson(d[c])},put:function(c,b){d[c]=f.toJson(b)},remove:function(c){delete d[c]}}}])})(window,window.angular);

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/app/lib/angular/.svn/text-base/angular-loader.js.svn-base
----------------------------------------------------------------------
diff --git a/src/main/ui/app/lib/angular/.svn/text-base/angular-loader.js.svn-base b/src/main/ui/app/lib/angular/.svn/text-base/angular-loader.js.svn-base
new file mode 100755
index 0000000..c4325dc
--- /dev/null
+++ b/src/main/ui/app/lib/angular/.svn/text-base/angular-loader.js.svn-base
@@ -0,0 +1,276 @@
+/**
+ * @license AngularJS v1.0.5
+ * (c) 2010-2012 Google, Inc. http://angularjs.org
+ * License: MIT
+ */
+
+(
+
+/**
+ * @ngdoc interface
+ * @name angular.Module
+ * @description
+ *
+ * Interface for configuring angular {@link angular.module modules}.
+ */
+
+function setupModuleLoader(window) {
+
+  function ensure(obj, name, factory) {
+    return obj[name] || (obj[name] = factory());
+  }
+
+  return ensure(ensure(window, 'angular', Object), 'module', function() {
+    /** @type {Object.<string, angular.Module>} */
+    var modules = {};
+
+    /**
+     * @ngdoc function
+     * @name angular.module
+     * @description
+     *
+     * The `angular.module` is a global place for creating and registering Angular modules. All
+     * modules (angular core or 3rd party) that should be available to an application must be
+     * registered using this mechanism.
+     *
+     *
+     * # Module
+     *
+     * A module is a collocation of services, directives, filters, and configuration information. Module
+     * is used to configure the {@link AUTO.$injector $injector}.
+     *
+     * <pre>
+     * // Create a new module
+     * var myModule = angular.module('myModule', []);
+     *
+     * // register a new service
+     * myModule.value('appName', 'MyCoolApp');
+     *
+     * // configure existing services inside initialization blocks.
+     * myModule.config(function($locationProvider) {
+'use strict';
+     *   // Configure existing providers
+     *   $locationProvider.hashPrefix('!');
+     * });
+     * </pre>
+     *
+     * Then you can create an injector and load your modules like this:
+     *
+     * <pre>
+     * var injector = angular.injector(['ng', 'MyModule'])
+     * </pre>
+     *
+     * However it's more likely that you'll just use
+     * {@link ng.directive:ngApp ngApp} or
+     * {@link angular.bootstrap} to simplify this process for you.
+     *
+     * @param {!string} name The name of the module to create or retrieve.
+     * @param {Array.<string>=} requires If specified then new module is being created. If unspecified then the
+     *        the module is being retrieved for further configuration.
+     * @param {Function} configFn Optional configuration function for the module. Same as
+     *        {@link angular.Module#config Module#config()}.
+     * @returns {module} new module with the {@link angular.Module} api.
+     */
+    return function module(name, requires, configFn) {
+      if (requires && modules.hasOwnProperty(name)) {
+        modules[name] = null;
+      }
+      return ensure(modules, name, function() {
+        if (!requires) {
+          throw Error('No module: ' + name);
+        }
+
+        /** @type {!Array.<Array.<*>>} */
+        var invokeQueue = [];
+
+        /** @type {!Array.<Function>} */
+        var runBlocks = [];
+
+        var config = invokeLater('$injector', 'invoke');
+
+        /** @type {angular.Module} */
+        var moduleInstance = {
+          // Private state
+          _invokeQueue: invokeQueue,
+          _runBlocks: runBlocks,
+
+          /**
+           * @ngdoc property
+           * @name angular.Module#requires
+           * @propertyOf angular.Module
+           * @returns {Array.<string>} List of module names which must be loaded before this module.
+           * @description
+           * Holds the list of modules which the injector will load before the current module is loaded.
+           */
+          requires: requires,
+
+          /**
+           * @ngdoc property
+           * @name angular.Module#name
+           * @propertyOf angular.Module
+           * @returns {string} Name of the module.
+           * @description
+           */
+          name: name,
+
+
+          /**
+           * @ngdoc method
+           * @name angular.Module#provider
+           * @methodOf angular.Module
+           * @param {string} name service name
+           * @param {Function} providerType Construction function for creating new instance of the service.
+           * @description
+           * See {@link AUTO.$provide#provider $provide.provider()}.
+           */
+          provider: invokeLater('$provide', 'provider'),
+
+          /**
+           * @ngdoc method
+           * @name angular.Module#factory
+           * @methodOf angular.Module
+           * @param {string} name service name
+           * @param {Function} providerFunction Function for creating new instance of the service.
+           * @description
+           * See {@link AUTO.$provide#factory $provide.factory()}.
+           */
+          factory: invokeLater('$provide', 'factory'),
+
+          /**
+           * @ngdoc method
+           * @name angular.Module#service
+           * @methodOf angular.Module
+           * @param {string} name service name
+           * @param {Function} constructor A constructor function that will be instantiated.
+           * @description
+           * See {@link AUTO.$provide#service $provide.service()}.
+           */
+          service: invokeLater('$provide', 'service'),
+
+          /**
+           * @ngdoc method
+           * @name angular.Module#value
+           * @methodOf angular.Module
+           * @param {string} name service name
+           * @param {*} object Service instance object.
+           * @description
+           * See {@link AUTO.$provide#value $provide.value()}.
+           */
+          value: invokeLater('$provide', 'value'),
+
+          /**
+           * @ngdoc method
+           * @name angular.Module#constant
+           * @methodOf angular.Module
+           * @param {string} name constant name
+           * @param {*} object Constant value.
+           * @description
+           * Because the constant are fixed, they get applied before other provide methods.
+           * See {@link AUTO.$provide#constant $provide.constant()}.
+           */
+          constant: invokeLater('$provide', 'constant', 'unshift'),
+
+          /**
+           * @ngdoc method
+           * @name angular.Module#filter
+           * @methodOf angular.Module
+           * @param {string} name Filter name.
+           * @param {Function} filterFactory Factory function for creating new instance of filter.
+           * @description
+           * See {@link ng.$filterProvider#register $filterProvider.register()}.
+           */
+          filter: invokeLater('$filterProvider', 'register'),
+
+          /**
+           * @ngdoc method
+           * @name angular.Module#controller
+           * @methodOf angular.Module
+           * @param {string} name Controller name.
+           * @param {Function} constructor Controller constructor function.
+           * @description
+           * See {@link ng.$controllerProvider#register $controllerProvider.register()}.
+           */
+          controller: invokeLater('$controllerProvider', 'register'),
+
+          /**
+           * @ngdoc method
+           * @name angular.Module#directive
+           * @methodOf angular.Module
+           * @param {string} name directive name
+           * @param {Function} directiveFactory Factory function for creating new instance of
+           * directives.
+           * @description
+           * See {@link ng.$compileProvider#directive $compileProvider.directive()}.
+           */
+          directive: invokeLater('$compileProvider', 'directive'),
+
+          /**
+           * @ngdoc method
+           * @name angular.Module#config
+           * @methodOf angular.Module
+           * @param {Function} configFn Execute this function on module load. Useful for service
+           *    configuration.
+           * @description
+           * Use this method to register work which needs to be performed on module loading.
+           */
+          config: config,
+
+          /**
+           * @ngdoc method
+           * @name angular.Module#run
+           * @methodOf angular.Module
+           * @param {Function} initializationFn Execute this function after injector creation.
+           *    Useful for application initialization.
+           * @description
+           * Use this method to register work which should be performed when the injector is done
+           * loading all modules.
+           */
+          run: function(block) {
+            runBlocks.push(block);
+            return this;
+          }
+        };
+
+        if (configFn) {
+          config(configFn);
+        }
+
+        return  moduleInstance;
+
+        /**
+         * @param {string} provider
+         * @param {string} method
+         * @param {String=} insertMethod
+         * @returns {angular.Module}
+         */
+        function invokeLater(provider, method, insertMethod) {
+          return function() {
+            invokeQueue[insertMethod || 'push']([provider, method, arguments]);
+            return moduleInstance;
+          }
+        }
+      });
+    };
+  });
+
+}
+)(window);
+
+/**
+ * Closure compiler type information
+ *
+ * @typedef { {
+ *   requires: !Array.<string>,
+ *   invokeQueue: !Array.<Array.<*>>,
+ *
+ *   service: function(string, Function):angular.Module,
+ *   factory: function(string, Function):angular.Module,
+ *   value: function(string, *):angular.Module,
+ *
+ *   filter: function(string, Function):angular.Module,
+ *
+ *   init: function(Function):angular.Module
+ * } }
+ */
+angular.Module;
+

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/app/lib/angular/.svn/text-base/angular-loader.min.js.svn-base
----------------------------------------------------------------------
diff --git a/src/main/ui/app/lib/angular/.svn/text-base/angular-loader.min.js.svn-base b/src/main/ui/app/lib/angular/.svn/text-base/angular-loader.min.js.svn-base
new file mode 100755
index 0000000..a264fbe
--- /dev/null
+++ b/src/main/ui/app/lib/angular/.svn/text-base/angular-loader.min.js.svn-base
@@ -0,0 +1,7 @@
+/*
+ AngularJS v1.0.5
+ (c) 2010-2012 Google, Inc. http://angularjs.org
+ License: MIT
+*/
+(function(i){'use strict';function d(c,b,e){return c[b]||(c[b]=e())}return d(d(i,"angular",Object),"module",function(){var c={};return function(b,e,f){e&&c.hasOwnProperty(b)&&(c[b]=null);return d(c,b,function(){function a(a,b,d){return function(){c[d||"push"]([a,b,arguments]);return g}}if(!e)throw Error("No module: "+b);var c=[],d=[],h=a("$injector","invoke"),g={_invokeQueue:c,_runBlocks:d,requires:e,name:b,provider:a("$provide","provider"),factory:a("$provide","factory"),service:a("$provide","service"),
+value:a("$provide","value"),constant:a("$provide","constant","unshift"),filter:a("$filterProvider","register"),controller:a("$controllerProvider","register"),directive:a("$compileProvider","directive"),config:h,run:function(a){d.push(a);return this}};f&&h(f);return g})}})})(window);

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/app/lib/angular/.svn/text-base/angular-resource.js.svn-base
----------------------------------------------------------------------
diff --git a/src/main/ui/app/lib/angular/.svn/text-base/angular-resource.js.svn-base b/src/main/ui/app/lib/angular/.svn/text-base/angular-resource.js.svn-base
new file mode 100755
index 0000000..a74c483
--- /dev/null
+++ b/src/main/ui/app/lib/angular/.svn/text-base/angular-resource.js.svn-base
@@ -0,0 +1,445 @@
+/**
+ * @license AngularJS v1.0.5
+ * (c) 2010-2012 Google, Inc. http://angularjs.org
+ * License: MIT
+ */
+(function(window, angular, undefined) {
+'use strict';
+
+/**
+ * @ngdoc overview
+ * @name ngResource
+ * @description
+ */
+
+/**
+ * @ngdoc object
+ * @name ngResource.$resource
+ * @requires $http
+ *
+ * @description
+ * A factory which creates a resource object that lets you interact with
+ * [RESTful](http://en.wikipedia.org/wiki/Representational_State_Transfer) server-side data sources.
+ *
+ * The returned resource object has action methods which provide high-level behaviors without
+ * the need to interact with the low level {@link ng.$http $http} service.
+ *
+ * @param {string} url A parameterized URL template with parameters prefixed by `:` as in
+ *   `/user/:username`. If you are using a URL with a port number (e.g. 
+ *   `http://example.com:8080/api`), you'll need to escape the colon character before the port
+ *   number, like this: `$resource('http://example.com\\:8080/api')`.
+ *
+ * @param {Object=} paramDefaults Default values for `url` parameters. These can be overridden in
+ *   `actions` methods.
+ *
+ *   Each key value in the parameter object is first bound to url template if present and then any
+ *   excess keys are appended to the url search query after the `?`.
+ *
+ *   Given a template `/path/:verb` and parameter `{verb:'greet', salutation:'Hello'}` results in
+ *   URL `/path/greet?salutation=Hello`.
+ *
+ *   If the parameter value is prefixed with `@` then the value of that parameter is extracted from
+ *   the data object (useful for non-GET operations).
+ *
+ * @param {Object.<Object>=} actions Hash with declaration of custom action that should extend the
+ *   default set of resource actions. The declaration should be created in the following format:
+ *
+ *       {action1: {method:?, params:?, isArray:?},
+ *        action2: {method:?, params:?, isArray:?},
+ *        ...}
+ *
+ *   Where:
+ *
+ *   - `action` – {string} – The name of action. This name becomes the name of the method on your
+ *     resource object.
+ *   - `method` – {string} – HTTP request method. Valid methods are: `GET`, `POST`, `PUT`, `DELETE`,
+ *     and `JSONP`
+ *   - `params` – {object=} – Optional set of pre-bound parameters for this action.
+ *   - isArray – {boolean=} – If true then the returned object for this action is an array, see
+ *     `returns` section.
+ *
+ * @returns {Object} A resource "class" object with methods for the default set of resource actions
+ *   optionally extended with custom `actions`. The default set contains these actions:
+ *
+ *       { 'get':    {method:'GET'},
+ *         'save':   {method:'POST'},
+ *         'query':  {method:'GET', isArray:true},
+ *         'remove': {method:'DELETE'},
+ *         'delete': {method:'DELETE'} };
+ *
+ *   Calling these methods invoke an {@link ng.$http} with the specified http method,
+ *   destination and parameters. When the data is returned from the server then the object is an
+ *   instance of the resource class. The actions `save`, `remove` and `delete` are available on it
+ *   as  methods with the `$` prefix. This allows you to easily perform CRUD operations (create,
+ *   read, update, delete) on server-side data like this:
+ *   <pre>
+        var User = $resource('/user/:userId', {userId:'@id'});
+        var user = User.get({userId:123}, function() {
+          user.abc = true;
+          user.$save();
+        });
+     </pre>
+ *
+ *   It is important to realize that invoking a $resource object method immediately returns an
+ *   empty reference (object or array depending on `isArray`). Once the data is returned from the
+ *   server the existing reference is populated with the actual data. This is a useful trick since
+ *   usually the resource is assigned to a model which is then rendered by the view. Having an empty
+ *   object results in no rendering, once the data arrives from the server then the object is
+ *   populated with the data and the view automatically re-renders itself showing the new data. This
+ *   means that in most case one never has to write a callback function for the action methods.
+ *
+ *   The action methods on the class object or instance object can be invoked with the following
+ *   parameters:
+ *
+ *   - HTTP GET "class" actions: `Resource.action([parameters], [success], [error])`
+ *   - non-GET "class" actions: `Resource.action([parameters], postData, [success], [error])`
+ *   - non-GET instance actions:  `instance.$action([parameters], [success], [error])`
+ *
+ *
+ * @example
+ *
+ * # Credit card resource
+ *
+ * <pre>
+     // Define CreditCard class
+     var CreditCard = $resource('/user/:userId/card/:cardId',
+      {userId:123, cardId:'@id'}, {
+       charge: {method:'POST', params:{charge:true}}
+      });
+
+     // We can retrieve a collection from the server
+     var cards = CreditCard.query(function() {
+       // GET: /user/123/card
+       // server returns: [ {id:456, number:'1234', name:'Smith'} ];
+
+       var card = cards[0];
+       // each item is an instance of CreditCard
+       expect(card instanceof CreditCard).toEqual(true);
+       card.name = "J. Smith";
+       // non GET methods are mapped onto the instances
+       card.$save();
+       // POST: /user/123/card/456 {id:456, number:'1234', name:'J. Smith'}
+       // server returns: {id:456, number:'1234', name: 'J. Smith'};
+
+       // our custom method is mapped as well.
+       card.$charge({amount:9.99});
+       // POST: /user/123/card/456?amount=9.99&charge=true {id:456, number:'1234', name:'J. Smith'}
+     });
+
+     // we can create an instance as well
+     var newCard = new CreditCard({number:'0123'});
+     newCard.name = "Mike Smith";
+     newCard.$save();
+     // POST: /user/123/card {number:'0123', name:'Mike Smith'}
+     // server returns: {id:789, number:'01234', name: 'Mike Smith'};
+     expect(newCard.id).toEqual(789);
+ * </pre>
+ *
+ * The object returned from this function execution is a resource "class" which has "static" method
+ * for each action in the definition.
+ *
+ * Calling these methods invoke `$http` on the `url` template with the given `method` and `params`.
+ * When the data is returned from the server then the object is an instance of the resource type and
+ * all of the non-GET methods are available with `$` prefix. This allows you to easily support CRUD
+ * operations (create, read, update, delete) on server-side data.
+
+   <pre>
+     var User = $resource('/user/:userId', {userId:'@id'});
+     var user = User.get({userId:123}, function() {
+       user.abc = true;
+       user.$save();
+     });
+   </pre>
+ *
+ * It's worth noting that the success callback for `get`, `query` and other method gets passed
+ * in the response that came from the server as well as $http header getter function, so one
+ * could rewrite the above example and get access to http headers as:
+ *
+   <pre>
+     var User = $resource('/user/:userId', {userId:'@id'});
+     User.get({userId:123}, function(u, getResponseHeaders){
+       u.abc = true;
+       u.$save(function(u, putResponseHeaders) {
+         //u => saved user object
+         //putResponseHeaders => $http header getter
+       });
+     });
+   </pre>
+
+ * # Buzz client
+
+   Let's look at what a buzz client created with the `$resource` service looks like:
+    <doc:example>
+      <doc:source jsfiddle="false">
+       <script>
+         function BuzzController($resource) {
+           this.userId = 'googlebuzz';
+           this.Activity = $resource(
+             'https://www.googleapis.com/buzz/v1/activities/:userId/:visibility/:activityId/:comments',
+             {alt:'json', callback:'JSON_CALLBACK'},
+             {get:{method:'JSONP', params:{visibility:'@self'}}, replies: {method:'JSONP', params:{visibility:'@self', comments:'@comments'}}}
+           );
+         }
+
+         BuzzController.prototype = {
+           fetch: function() {
+             this.activities = this.Activity.get({userId:this.userId});
+           },
+           expandReplies: function(activity) {
+             activity.replies = this.Activity.replies({userId:this.userId, activityId:activity.id});
+           }
+         };
+         BuzzController.$inject = ['$resource'];
+       </script>
+
+       <div ng-controller="BuzzController">
+         <input ng-model="userId"/>
+         <button ng-click="fetch()">fetch</button>
+         <hr/>
+         <div ng-repeat="item in activities.data.items">
+           <h1 style="font-size: 15px;">
+             <img src="{{item.actor.thumbnailUrl}}" style="max-height:30px;max-width:30px;"/>
+             <a href="{{item.actor.profileUrl}}">{{item.actor.name}}</a>
+             <a href ng-click="expandReplies(item)" style="float: right;">Expand replies: {{item.links.replies[0].count}}</a>
+           </h1>
+           {{item.object.content | html}}
+           <div ng-repeat="reply in item.replies.data.items" style="margin-left: 20px;">
+             <img src="{{reply.actor.thumbnailUrl}}" style="max-height:30px;max-width:30px;"/>
+             <a href="{{reply.actor.profileUrl}}">{{reply.actor.name}}</a>: {{reply.content | html}}
+           </div>
+         </div>
+       </div>
+      </doc:source>
+      <doc:scenario>
+      </doc:scenario>
+    </doc:example>
+ */
+angular.module('ngResource', ['ng']).
+  factory('$resource', ['$http', '$parse', function($http, $parse) {
+    var DEFAULT_ACTIONS = {
+      'get':    {method:'GET'},
+      'save':   {method:'POST'},
+      'query':  {method:'GET', isArray:true},
+      'remove': {method:'DELETE'},
+      'delete': {method:'DELETE'}
+    };
+    var noop = angular.noop,
+        forEach = angular.forEach,
+        extend = angular.extend,
+        copy = angular.copy,
+        isFunction = angular.isFunction,
+        getter = function(obj, path) {
+          return $parse(path)(obj);
+        };
+
+    /**
+     * We need our custom method because encodeURIComponent is too aggressive and doesn't follow
+     * http://www.ietf.org/rfc/rfc3986.txt with regards to the character set (pchar) allowed in path
+     * segments:
+     *    segment       = *pchar
+     *    pchar         = unreserved / pct-encoded / sub-delims / ":" / "@"
+     *    pct-encoded   = "%" HEXDIG HEXDIG
+     *    unreserved    = ALPHA / DIGIT / "-" / "." / "_" / "~"
+     *    sub-delims    = "!" / "$" / "&" / "'" / "(" / ")"
+     *                     / "*" / "+" / "," / ";" / "="
+     */
+    function encodeUriSegment(val) {
+      return encodeUriQuery(val, true).
+        replace(/%26/gi, '&').
+        replace(/%3D/gi, '=').
+        replace(/%2B/gi, '+');
+    }
+
+
+    /**
+     * This method is intended for encoding *key* or *value* parts of query component. We need a custom
+     * method becuase encodeURIComponent is too agressive and encodes stuff that doesn't have to be
+     * encoded per http://tools.ietf.org/html/rfc3986:
+     *    query       = *( pchar / "/" / "?" )
+     *    pchar         = unreserved / pct-encoded / sub-delims / ":" / "@"
+     *    unreserved    = ALPHA / DIGIT / "-" / "." / "_" / "~"
+     *    pct-encoded   = "%" HEXDIG HEXDIG
+     *    sub-delims    = "!" / "$" / "&" / "'" / "(" / ")"
+     *                     / "*" / "+" / "," / ";" / "="
+     */
+    function encodeUriQuery(val, pctEncodeSpaces) {
+      return encodeURIComponent(val).
+        replace(/%40/gi, '@').
+        replace(/%3A/gi, ':').
+        replace(/%24/g, '$').
+        replace(/%2C/gi, ',').
+        replace((pctEncodeSpaces ? null : /%20/g), '+');
+    }
+
+    function Route(template, defaults) {
+      this.template = template = template + '#';
+      this.defaults = defaults || {};
+      var urlParams = this.urlParams = {};
+      forEach(template.split(/\W/), function(param){
+        if (param && (new RegExp("(^|[^\\\\]):" + param + "\\W").test(template))) {
+          urlParams[param] = true;
+        }
+      });
+      this.template = template.replace(/\\:/g, ':');
+    }
+
+    Route.prototype = {
+      url: function(params) {
+        var self = this,
+            url = this.template,
+            val,
+            encodedVal;
+
+        params = params || {};
+        forEach(this.urlParams, function(_, urlParam){
+          val = params.hasOwnProperty(urlParam) ? params[urlParam] : self.defaults[urlParam];
+          if (angular.isDefined(val) && val !== null) {
+            encodedVal = encodeUriSegment(val);
+            url = url.replace(new RegExp(":" + urlParam + "(\\W)", "g"), encodedVal + "$1");
+          } else {
+            url = url.replace(new RegExp("(\/?):" + urlParam + "(\\W)", "g"), function(match,
+                leadingSlashes, tail) {
+              if (tail.charAt(0) == '/') {
+                return tail;
+              } else {
+                return leadingSlashes + tail;
+              }
+            });
+          }
+        });
+        url = url.replace(/\/?#$/, '');
+        var query = [];
+        forEach(params, function(value, key){
+          if (!self.urlParams[key]) {
+            query.push(encodeUriQuery(key) + '=' + encodeUriQuery(value));
+          }
+        });
+        query.sort();
+        url = url.replace(/\/*$/, '');
+        return url + (query.length ? '?' + query.join('&') : '');
+      }
+    };
+
+
+    function ResourceFactory(url, paramDefaults, actions) {
+      var route = new Route(url);
+
+      actions = extend({}, DEFAULT_ACTIONS, actions);
+
+      function extractParams(data, actionParams){
+        var ids = {};
+        actionParams = extend({}, paramDefaults, actionParams);
+        forEach(actionParams, function(value, key){
+          ids[key] = value.charAt && value.charAt(0) == '@' ? getter(data, value.substr(1)) : value;
+        });
+        return ids;
+      }
+
+      function Resource(value){
+        copy(value || {}, this);
+      }
+
+      forEach(actions, function(action, name) {
+        action.method = angular.uppercase(action.method);
+        var hasBody = action.method == 'POST' || action.method == 'PUT' || action.method == 'PATCH';
+        Resource[name] = function(a1, a2, a3, a4) {
+          var params = {};
+          var data;
+          var success = noop;
+          var error = null;
+          switch(arguments.length) {
+          case 4:
+            error = a4;
+            success = a3;
+            //fallthrough
+          case 3:
+          case 2:
+            if (isFunction(a2)) {
+              if (isFunction(a1)) {
+                success = a1;
+                error = a2;
+                break;
+              }
+
+              success = a2;
+              error = a3;
+              //fallthrough
+            } else {
+              params = a1;
+              data = a2;
+              success = a3;
+              break;
+            }
+          case 1:
+            if (isFunction(a1)) success = a1;
+            else if (hasBody) data = a1;
+            else params = a1;
+            break;
+          case 0: break;
+          default:
+            throw "Expected between 0-4 arguments [params, data, success, error], got " +
+              arguments.length + " arguments.";
+          }
+
+          var value = this instanceof Resource ? this : (action.isArray ? [] : new Resource(data));
+          $http({
+            method: action.method,
+            url: route.url(extend({}, extractParams(data, action.params || {}), params)),
+            data: data
+          }).then(function(response) {
+              var data = response.data;
+
+              if (data) {
+                if (action.isArray) {
+                  value.length = 0;
+                  forEach(data, function(item) {
+                    value.push(new Resource(item));
+                  });
+                } else {
+                  copy(data, value);
+                }
+              }
+              (success||noop)(value, response.headers);
+            }, error);
+
+          return value;
+        };
+
+
+        Resource.prototype['$' + name] = function(a1, a2, a3) {
+          var params = extractParams(this),
+              success = noop,
+              error;
+
+          switch(arguments.length) {
+          case 3: params = a1; success = a2; error = a3; break;
+          case 2:
+          case 1:
+            if (isFunction(a1)) {
+              success = a1;
+              error = a2;
+            } else {
+              params = a1;
+              success = a2 || noop;
+            }
+          case 0: break;
+          default:
+            throw "Expected between 1-3 arguments [params, success, error], got " +
+              arguments.length + " arguments.";
+          }
+          var data = hasBody ? this : undefined;
+          Resource[name].call(this, params, data, success, error);
+        };
+      });
+
+      Resource.bind = function(additionalParamDefaults){
+        return ResourceFactory(url, extend({}, paramDefaults, additionalParamDefaults), actions);
+      };
+
+      return Resource;
+    }
+
+    return ResourceFactory;
+  }]);
+
+})(window, window.angular);

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/app/lib/angular/.svn/text-base/angular-resource.min.js.svn-base
----------------------------------------------------------------------
diff --git a/src/main/ui/app/lib/angular/.svn/text-base/angular-resource.min.js.svn-base b/src/main/ui/app/lib/angular/.svn/text-base/angular-resource.min.js.svn-base
new file mode 100755
index 0000000..f37559c
--- /dev/null
+++ b/src/main/ui/app/lib/angular/.svn/text-base/angular-resource.min.js.svn-base
@@ -0,0 +1,10 @@
+/*
+ AngularJS v1.0.5
+ (c) 2010-2012 Google, Inc. http://angularjs.org
+ License: MIT
+*/
+(function(C,d,w){'use strict';d.module("ngResource",["ng"]).factory("$resource",["$http","$parse",function(x,y){function s(b,e){return encodeURIComponent(b).replace(/%40/gi,"@").replace(/%3A/gi,":").replace(/%24/g,"$").replace(/%2C/gi,",").replace(e?null:/%20/g,"+")}function t(b,e){this.template=b+="#";this.defaults=e||{};var a=this.urlParams={};h(b.split(/\W/),function(f){f&&RegExp("(^|[^\\\\]):"+f+"\\W").test(b)&&(a[f]=!0)});this.template=b.replace(/\\:/g,":")}function u(b,e,a){function f(m,a){var b=
+{},a=o({},e,a);h(a,function(a,z){var c;a.charAt&&a.charAt(0)=="@"?(c=a.substr(1),c=y(c)(m)):c=a;b[z]=c});return b}function g(a){v(a||{},this)}var k=new t(b),a=o({},A,a);h(a,function(a,b){a.method=d.uppercase(a.method);var e=a.method=="POST"||a.method=="PUT"||a.method=="PATCH";g[b]=function(b,c,d,B){var j={},i,l=p,q=null;switch(arguments.length){case 4:q=B,l=d;case 3:case 2:if(r(c)){if(r(b)){l=b;q=c;break}l=c;q=d}else{j=b;i=c;l=d;break}case 1:r(b)?l=b:e?i=b:j=b;break;case 0:break;default:throw"Expected between 0-4 arguments [params, data, success, error], got "+
+arguments.length+" arguments.";}var n=this instanceof g?this:a.isArray?[]:new g(i);x({method:a.method,url:k.url(o({},f(i,a.params||{}),j)),data:i}).then(function(b){var c=b.data;if(c)a.isArray?(n.length=0,h(c,function(a){n.push(new g(a))})):v(c,n);(l||p)(n,b.headers)},q);return n};g.prototype["$"+b]=function(a,d,h){var m=f(this),j=p,i;switch(arguments.length){case 3:m=a;j=d;i=h;break;case 2:case 1:r(a)?(j=a,i=d):(m=a,j=d||p);case 0:break;default:throw"Expected between 1-3 arguments [params, success, error], got "+
+arguments.length+" arguments.";}g[b].call(this,m,e?this:w,j,i)}});g.bind=function(d){return u(b,o({},e,d),a)};return g}var A={get:{method:"GET"},save:{method:"POST"},query:{method:"GET",isArray:!0},remove:{method:"DELETE"},"delete":{method:"DELETE"}},p=d.noop,h=d.forEach,o=d.extend,v=d.copy,r=d.isFunction;t.prototype={url:function(b){var e=this,a=this.template,f,g,b=b||{};h(this.urlParams,function(h,c){f=b.hasOwnProperty(c)?b[c]:e.defaults[c];d.isDefined(f)&&f!==null?(g=s(f,!0).replace(/%26/gi,"&").replace(/%3D/gi,
+"=").replace(/%2B/gi,"+"),a=a.replace(RegExp(":"+c+"(\\W)","g"),g+"$1")):a=a.replace(RegExp("(/?):"+c+"(\\W)","g"),function(a,b,c){return c.charAt(0)=="/"?c:b+c})});var a=a.replace(/\/?#$/,""),k=[];h(b,function(a,b){e.urlParams[b]||k.push(s(b)+"="+s(a))});k.sort();a=a.replace(/\/*$/,"");return a+(k.length?"?"+k.join("&"):"")}};return u}])})(window,window.angular);

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/app/lib/angular/.svn/text-base/angular-sanitize.js.svn-base
----------------------------------------------------------------------
diff --git a/src/main/ui/app/lib/angular/.svn/text-base/angular-sanitize.js.svn-base b/src/main/ui/app/lib/angular/.svn/text-base/angular-sanitize.js.svn-base
new file mode 100755
index 0000000..39e72bf
--- /dev/null
+++ b/src/main/ui/app/lib/angular/.svn/text-base/angular-sanitize.js.svn-base
@@ -0,0 +1,535 @@
+/**
+ * @license AngularJS v1.0.5
+ * (c) 2010-2012 Google, Inc. http://angularjs.org
+ * License: MIT
+ */
+(function(window, angular, undefined) {
+'use strict';
+
+/**
+ * @ngdoc overview
+ * @name ngSanitize
+ * @description
+ */
+
+/*
+ * HTML Parser By Misko Hevery (misko@hevery.com)
+ * based on:  HTML Parser By John Resig (ejohn.org)
+ * Original code by Erik Arvidsson, Mozilla Public License
+ * http://erik.eae.net/simplehtmlparser/simplehtmlparser.js
+ *
+ * // Use like so:
+ * htmlParser(htmlString, {
+ *     start: function(tag, attrs, unary) {},
+ *     end: function(tag) {},
+ *     chars: function(text) {},
+ *     comment: function(text) {}
+ * });
+ *
+ */
+
+
+/**
+ * @ngdoc service
+ * @name ngSanitize.$sanitize
+ * @function
+ *
+ * @description
+ *   The input is sanitized by parsing the html into tokens. All safe tokens (from a whitelist) are
+ *   then serialized back to properly escaped html string. This means that no unsafe input can make
+ *   it into the returned string, however, since our parser is more strict than a typical browser
+ *   parser, it's possible that some obscure input, which would be recognized as valid HTML by a
+ *   browser, won't make it through the sanitizer.
+ *
+ * @param {string} html Html input.
+ * @returns {string} Sanitized html.
+ *
+ * @example
+   <doc:example module="ngSanitize">
+     <doc:source>
+       <script>
+         function Ctrl($scope) {
+           $scope.snippet =
+             '<p style="color:blue">an html\n' +
+             '<em onmouseover="this.textContent=\'PWN3D!\'">click here</em>\n' +
+             'snippet</p>';
+         }
+       </script>
+       <div ng-controller="Ctrl">
+          Snippet: <textarea ng-model="snippet" cols="60" rows="3"></textarea>
+           <table>
+             <tr>
+               <td>Filter</td>
+               <td>Source</td>
+               <td>Rendered</td>
+             </tr>
+             <tr id="html-filter">
+               <td>html filter</td>
+               <td>
+                 <pre>&lt;div ng-bind-html="snippet"&gt;<br/>&lt;/div&gt;</pre>
+               </td>
+               <td>
+                 <div ng-bind-html="snippet"></div>
+               </td>
+             </tr>
+             <tr id="escaped-html">
+               <td>no filter</td>
+               <td><pre>&lt;div ng-bind="snippet"&gt;<br/>&lt;/div&gt;</pre></td>
+               <td><div ng-bind="snippet"></div></td>
+             </tr>
+             <tr id="html-unsafe-filter">
+               <td>unsafe html filter</td>
+               <td><pre>&lt;div ng-bind-html-unsafe="snippet"&gt;<br/>&lt;/div&gt;</pre></td>
+               <td><div ng-bind-html-unsafe="snippet"></div></td>
+             </tr>
+           </table>
+         </div>
+     </doc:source>
+     <doc:scenario>
+       it('should sanitize the html snippet ', function() {
+         expect(using('#html-filter').element('div').html()).
+           toBe('<p>an html\n<em>click here</em>\nsnippet</p>');
+       });
+
+       it('should escape snippet without any filter', function() {
+         expect(using('#escaped-html').element('div').html()).
+           toBe("&lt;p style=\"color:blue\"&gt;an html\n" +
+                "&lt;em onmouseover=\"this.textContent='PWN3D!'\"&gt;click here&lt;/em&gt;\n" +
+                "snippet&lt;/p&gt;");
+       });
+
+       it('should inline raw snippet if filtered as unsafe', function() {
+         expect(using('#html-unsafe-filter').element("div").html()).
+           toBe("<p style=\"color:blue\">an html\n" +
+                "<em onmouseover=\"this.textContent='PWN3D!'\">click here</em>\n" +
+                "snippet</p>");
+       });
+
+       it('should update', function() {
+         input('snippet').enter('new <b>text</b>');
+         expect(using('#html-filter').binding('snippet')).toBe('new <b>text</b>');
+         expect(using('#escaped-html').element('div').html()).toBe("new &lt;b&gt;text&lt;/b&gt;");
+         expect(using('#html-unsafe-filter').binding("snippet")).toBe('new <b>text</b>');
+       });
+     </doc:scenario>
+   </doc:example>
+ */
+var $sanitize = function(html) {
+  var buf = [];
+    htmlParser(html, htmlSanitizeWriter(buf));
+    return buf.join('');
+};
+
+
+// Regular Expressions for parsing tags and attributes
+var START_TAG_REGEXP = /^<\s*([\w:-]+)((?:\s+[\w:-]+(?:\s*=\s*(?:(?:"[^"]*")|(?:'[^']*')|[^>\s]+))?)*)\s*(\/?)\s*>/,
+  END_TAG_REGEXP = /^<\s*\/\s*([\w:-]+)[^>]*>/,
+  ATTR_REGEXP = /([\w:-]+)(?:\s*=\s*(?:(?:"((?:[^"])*)")|(?:'((?:[^'])*)')|([^>\s]+)))?/g,
+  BEGIN_TAG_REGEXP = /^</,
+  BEGING_END_TAGE_REGEXP = /^<\s*\//,
+  COMMENT_REGEXP = /<!--(.*?)-->/g,
+  CDATA_REGEXP = /<!\[CDATA\[(.*?)]]>/g,
+  URI_REGEXP = /^((ftp|https?):\/\/|mailto:|#)/,
+  NON_ALPHANUMERIC_REGEXP = /([^\#-~| |!])/g; // Match everything outside of normal chars and " (quote character)
+
+
+// Good source of info about elements and attributes
+// http://dev.w3.org/html5/spec/Overview.html#semantics
+// http://simon.html5.org/html-elements
+
+// Safe Void Elements - HTML5
+// http://dev.w3.org/html5/spec/Overview.html#void-elements
+var voidElements = makeMap("area,br,col,hr,img,wbr");
+
+// Elements that you can, intentionally, leave open (and which close themselves)
+// http://dev.w3.org/html5/spec/Overview.html#optional-tags
+var optionalEndTagBlockElements = makeMap("colgroup,dd,dt,li,p,tbody,td,tfoot,th,thead,tr"),
+    optionalEndTagInlineElements = makeMap("rp,rt"),
+    optionalEndTagElements = angular.extend({}, optionalEndTagInlineElements, optionalEndTagBlockElements);
+
+// Safe Block Elements - HTML5
+var blockElements = angular.extend({}, optionalEndTagBlockElements, makeMap("address,article,aside," +
+        "blockquote,caption,center,del,dir,div,dl,figure,figcaption,footer,h1,h2,h3,h4,h5,h6," +
+        "header,hgroup,hr,ins,map,menu,nav,ol,pre,script,section,table,ul"));
+
+// Inline Elements - HTML5
+var inlineElements = angular.extend({}, optionalEndTagInlineElements, makeMap("a,abbr,acronym,b,bdi,bdo," +
+        "big,br,cite,code,del,dfn,em,font,i,img,ins,kbd,label,map,mark,q,ruby,rp,rt,s,samp,small," +
+        "span,strike,strong,sub,sup,time,tt,u,var"));
+
+
+// Special Elements (can contain anything)
+var specialElements = makeMap("script,style");
+
+var validElements = angular.extend({}, voidElements, blockElements, inlineElements, optionalEndTagElements);
+
+//Attributes that have href and hence need to be sanitized
+var uriAttrs = makeMap("background,cite,href,longdesc,src,usemap");
+var validAttrs = angular.extend({}, uriAttrs, makeMap(
+    'abbr,align,alt,axis,bgcolor,border,cellpadding,cellspacing,class,clear,'+
+    'color,cols,colspan,compact,coords,dir,face,headers,height,hreflang,hspace,'+
+    'ismap,lang,language,nohref,nowrap,rel,rev,rows,rowspan,rules,'+
+    'scope,scrolling,shape,span,start,summary,target,title,type,'+
+    'valign,value,vspace,width'));
+
+function makeMap(str) {
+  var obj = {}, items = str.split(','), i;
+  for (i = 0; i < items.length; i++) obj[items[i]] = true;
+  return obj;
+}
+
+
+/**
+ * @example
+ * htmlParser(htmlString, {
+ *     start: function(tag, attrs, unary) {},
+ *     end: function(tag) {},
+ *     chars: function(text) {},
+ *     comment: function(text) {}
+ * });
+ *
+ * @param {string} html string
+ * @param {object} handler
+ */
+function htmlParser( html, handler ) {
+  var index, chars, match, stack = [], last = html;
+  stack.last = function() { return stack[ stack.length - 1 ]; };
+
+  while ( html ) {
+    chars = true;
+
+    // Make sure we're not in a script or style element
+    if ( !stack.last() || !specialElements[ stack.last() ] ) {
+
+      // Comment
+      if ( html.indexOf("<!--") === 0 ) {
+        index = html.indexOf("-->");
+
+        if ( index >= 0 ) {
+          if (handler.comment) handler.comment( html.substring( 4, index ) );
+          html = html.substring( index + 3 );
+          chars = false;
+        }
+
+      // end tag
+      } else if ( BEGING_END_TAGE_REGEXP.test(html) ) {
+        match = html.match( END_TAG_REGEXP );
+
+        if ( match ) {
+          html = html.substring( match[0].length );
+          match[0].replace( END_TAG_REGEXP, parseEndTag );
+          chars = false;
+        }
+
+      // start tag
+      } else if ( BEGIN_TAG_REGEXP.test(html) ) {
+        match = html.match( START_TAG_REGEXP );
+
+        if ( match ) {
+          html = html.substring( match[0].length );
+          match[0].replace( START_TAG_REGEXP, parseStartTag );
+          chars = false;
+        }
+      }
+
+      if ( chars ) {
+        index = html.indexOf("<");
+
+        var text = index < 0 ? html : html.substring( 0, index );
+        html = index < 0 ? "" : html.substring( index );
+
+        if (handler.chars) handler.chars( decodeEntities(text) );
+      }
+
+    } else {
+      html = html.replace(new RegExp("(.*)<\\s*\\/\\s*" + stack.last() + "[^>]*>", 'i'), function(all, text){
+        text = text.
+          replace(COMMENT_REGEXP, "$1").
+          replace(CDATA_REGEXP, "$1");
+
+        if (handler.chars) handler.chars( decodeEntities(text) );
+
+        return "";
+      });
+
+      parseEndTag( "", stack.last() );
+    }
+
+    if ( html == last ) {
+      throw "Parse Error: " + html;
+    }
+    last = html;
+  }
+
+  // Clean up any remaining tags
+  parseEndTag();
+
+  function parseStartTag( tag, tagName, rest, unary ) {
+    tagName = angular.lowercase(tagName);
+    if ( blockElements[ tagName ] ) {
+      while ( stack.last() && inlineElements[ stack.last() ] ) {
+        parseEndTag( "", stack.last() );
+      }
+    }
+
+    if ( optionalEndTagElements[ tagName ] && stack.last() == tagName ) {
+      parseEndTag( "", tagName );
+    }
+
+    unary = voidElements[ tagName ] || !!unary;
+
+    if ( !unary )
+      stack.push( tagName );
+
+    var attrs = {};
+
+    rest.replace(ATTR_REGEXP, function(match, name, doubleQuotedValue, singleQoutedValue, unqoutedValue) {
+      var value = doubleQuotedValue
+        || singleQoutedValue
+        || unqoutedValue
+        || '';
+
+      attrs[name] = decodeEntities(value);
+    });
+    if (handler.start) handler.start( tagName, attrs, unary );
+  }
+
+  function parseEndTag( tag, tagName ) {
+    var pos = 0, i;
+    tagName = angular.lowercase(tagName);
+    if ( tagName )
+      // Find the closest opened tag of the same type
+      for ( pos = stack.length - 1; pos >= 0; pos-- )
+        if ( stack[ pos ] == tagName )
+          break;
+
+    if ( pos >= 0 ) {
+      // Close all the open elements, up the stack
+      for ( i = stack.length - 1; i >= pos; i-- )
+        if (handler.end) handler.end( stack[ i ] );
+
+      // Remove the open elements from the stack
+      stack.length = pos;
+    }
+  }
+}
+
+/**
+ * decodes all entities into regular string
+ * @param value
+ * @returns {string} A string with decoded entities.
+ */
+var hiddenPre=document.createElement("pre");
+function decodeEntities(value) {
+  hiddenPre.innerHTML=value.replace(/</g,"&lt;");
+  return hiddenPre.innerText || hiddenPre.textContent || '';
+}
+
+/**
+ * Escapes all potentially dangerous characters, so that the
+ * resulting string can be safely inserted into attribute or
+ * element text.
+ * @param value
+ * @returns escaped text
+ */
+function encodeEntities(value) {
+  return value.
+    replace(/&/g, '&amp;').
+    replace(NON_ALPHANUMERIC_REGEXP, function(value){
+      return '&#' + value.charCodeAt(0) + ';';
+    }).
+    replace(/</g, '&lt;').
+    replace(/>/g, '&gt;');
+}
+
+/**
+ * create an HTML/XML writer which writes to buffer
+ * @param {Array} buf use buf.jain('') to get out sanitized html string
+ * @returns {object} in the form of {
+ *     start: function(tag, attrs, unary) {},
+ *     end: function(tag) {},
+ *     chars: function(text) {},
+ *     comment: function(text) {}
+ * }
+ */
+function htmlSanitizeWriter(buf){
+  var ignore = false;
+  var out = angular.bind(buf, buf.push);
+  return {
+    start: function(tag, attrs, unary){
+      tag = angular.lowercase(tag);
+      if (!ignore && specialElements[tag]) {
+        ignore = tag;
+      }
+      if (!ignore && validElements[tag] == true) {
+        out('<');
+        out(tag);
+        angular.forEach(attrs, function(value, key){
+          var lkey=angular.lowercase(key);
+          if (validAttrs[lkey]==true && (uriAttrs[lkey]!==true || value.match(URI_REGEXP))) {
+            out(' ');
+            out(key);
+            out('="');
+            out(encodeEntities(value));
+            out('"');
+          }
+        });
+        out(unary ? '/>' : '>');
+      }
+    },
+    end: function(tag){
+        tag = angular.lowercase(tag);
+        if (!ignore && validElements[tag] == true) {
+          out('</');
+          out(tag);
+          out('>');
+        }
+        if (tag == ignore) {
+          ignore = false;
+        }
+      },
+    chars: function(chars){
+        if (!ignore) {
+          out(encodeEntities(chars));
+        }
+      }
+  };
+}
+
+
+// define ngSanitize module and register $sanitize service
+angular.module('ngSanitize', []).value('$sanitize', $sanitize);
+
+/**
+ * @ngdoc directive
+ * @name ngSanitize.directive:ngBindHtml
+ *
+ * @description
+ * Creates a binding that will sanitize the result of evaluating the `expression` with the
+ * {@link ngSanitize.$sanitize $sanitize} service and innerHTML the result into the current element.
+ *
+ * See {@link ngSanitize.$sanitize $sanitize} docs for examples.
+ *
+ * @element ANY
+ * @param {expression} ngBindHtml {@link guide/expression Expression} to evaluate.
+ */
+angular.module('ngSanitize').directive('ngBindHtml', ['$sanitize', function($sanitize) {
+  return function(scope, element, attr) {
+    element.addClass('ng-binding').data('$binding', attr.ngBindHtml);
+    scope.$watch(attr.ngBindHtml, function ngBindHtmlWatchAction(value) {
+      value = $sanitize(value);
+      element.html(value || '');
+    });
+  };
+}]);
+/**
+ * @ngdoc filter
+ * @name ngSanitize.filter:linky
+ * @function
+ *
+ * @description
+ *   Finds links in text input and turns them into html links. Supports http/https/ftp/mailto and
+ *   plain email address links.
+ *
+ * @param {string} text Input text.
+ * @returns {string} Html-linkified text.
+ *
+ * @usage
+   <span ng-bind-html="linky_expression | linky"></span>
+ *
+ * @example
+   <doc:example module="ngSanitize">
+     <doc:source>
+       <script>
+         function Ctrl($scope) {
+           $scope.snippet =
+             'Pretty text with some links:\n'+
+             'http://angularjs.org/,\n'+
+             'mailto:us@somewhere.org,\n'+
+             'another@somewhere.org,\n'+
+             'and one more: ftp://127.0.0.1/.';
+         }
+       </script>
+       <div ng-controller="Ctrl">
+       Snippet: <textarea ng-model="snippet" cols="60" rows="3"></textarea>
+       <table>
+         <tr>
+           <td>Filter</td>
+           <td>Source</td>
+           <td>Rendered</td>
+         </tr>
+         <tr id="linky-filter">
+           <td>linky filter</td>
+           <td>
+             <pre>&lt;div ng-bind-html="snippet | linky"&gt;<br>&lt;/div&gt;</pre>
+           </td>
+           <td>
+             <div ng-bind-html="snippet | linky"></div>
+           </td>
+         </tr>
+         <tr id="escaped-html">
+           <td>no filter</td>
+           <td><pre>&lt;div ng-bind="snippet"&gt;<br>&lt;/div&gt;</pre></td>
+           <td><div ng-bind="snippet"></div></td>
+         </tr>
+       </table>
+     </doc:source>
+     <doc:scenario>
+       it('should linkify the snippet with urls', function() {
+         expect(using('#linky-filter').binding('snippet | linky')).
+           toBe('Pretty text with some links:&#10;' +
+                '<a href="http://angularjs.org/">http://angularjs.org/</a>,&#10;' +
+                '<a href="mailto:us@somewhere.org">us@somewhere.org</a>,&#10;' +
+                '<a href="mailto:another@somewhere.org">another@somewhere.org</a>,&#10;' +
+                'and one more: <a href="ftp://127.0.0.1/">ftp://127.0.0.1/</a>.');
+       });
+
+       it ('should not linkify snippet without the linky filter', function() {
+         expect(using('#escaped-html').binding('snippet')).
+           toBe("Pretty text with some links:\n" +
+                "http://angularjs.org/,\n" +
+                "mailto:us@somewhere.org,\n" +
+                "another@somewhere.org,\n" +
+                "and one more: ftp://127.0.0.1/.");
+       });
+
+       it('should update', function() {
+         input('snippet').enter('new http://link.');
+         expect(using('#linky-filter').binding('snippet | linky')).
+           toBe('new <a href="http://link">http://link</a>.');
+         expect(using('#escaped-html').binding('snippet')).toBe('new http://link.');
+       });
+     </doc:scenario>
+   </doc:example>
+ */
+angular.module('ngSanitize').filter('linky', function() {
+  var LINKY_URL_REGEXP = /((ftp|https?):\/\/|(mailto:)?[A-Za-z0-9._%+-]+@)\S*[^\s\.\;\,\(\)\{\}\<\>]/,
+      MAILTO_REGEXP = /^mailto:/;
+
+  return function(text) {
+    if (!text) return text;
+    var match;
+    var raw = text;
+    var html = [];
+    // TODO(vojta): use $sanitize instead
+    var writer = htmlSanitizeWriter(html);
+    var url;
+    var i;
+    while ((match = raw.match(LINKY_URL_REGEXP))) {
+      // We can not end in these as they are sometimes found at the end of the sentence
+      url = match[0];
+      // if we did not match ftp/http/mailto then assume mailto
+      if (match[2] == match[3]) url = 'mailto:' + url;
+      i = match.index;
+      writer.chars(raw.substr(0, i));
+      writer.start('a', {href:url});
+      writer.chars(match[0].replace(MAILTO_REGEXP, ''));
+      writer.end('a');
+      raw = raw.substring(i + match[0].length);
+    }
+    writer.chars(raw);
+    return html.join('');
+  };
+});
+
+})(window, window.angular);

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/app/lib/angular/.svn/text-base/angular-sanitize.min.js.svn-base
----------------------------------------------------------------------
diff --git a/src/main/ui/app/lib/angular/.svn/text-base/angular-sanitize.min.js.svn-base b/src/main/ui/app/lib/angular/.svn/text-base/angular-sanitize.min.js.svn-base
new file mode 100755
index 0000000..212a90a
--- /dev/null
+++ b/src/main/ui/app/lib/angular/.svn/text-base/angular-sanitize.min.js.svn-base
@@ -0,0 +1,13 @@
+/*
+ AngularJS v1.0.5
+ (c) 2010-2012 Google, Inc. http://angularjs.org
+ License: MIT
+*/
+(function(I,g){'use strict';function i(a){var d={},a=a.split(","),b;for(b=0;b<a.length;b++)d[a[b]]=!0;return d}function z(a,d){function b(a,b,c,h){b=g.lowercase(b);if(m[b])for(;f.last()&&n[f.last()];)e("",f.last());o[b]&&f.last()==b&&e("",b);(h=p[b]||!!h)||f.push(b);var j={};c.replace(A,function(a,b,d,e,c){j[b]=k(d||e||c||"")});d.start&&d.start(b,j,h)}function e(a,b){var e=0,c;if(b=g.lowercase(b))for(e=f.length-1;e>=0;e--)if(f[e]==b)break;if(e>=0){for(c=f.length-1;c>=e;c--)d.end&&d.end(f[c]);f.length=
+e}}var c,h,f=[],j=a;for(f.last=function(){return f[f.length-1]};a;){h=!0;if(!f.last()||!q[f.last()]){if(a.indexOf("<\!--")===0)c=a.indexOf("--\>"),c>=0&&(d.comment&&d.comment(a.substring(4,c)),a=a.substring(c+3),h=!1);else if(B.test(a)){if(c=a.match(r))a=a.substring(c[0].length),c[0].replace(r,e),h=!1}else if(C.test(a)&&(c=a.match(s)))a=a.substring(c[0].length),c[0].replace(s,b),h=!1;h&&(c=a.indexOf("<"),h=c<0?a:a.substring(0,c),a=c<0?"":a.substring(c),d.chars&&d.chars(k(h)))}else a=a.replace(RegExp("(.*)<\\s*\\/\\s*"+
+f.last()+"[^>]*>","i"),function(b,a){a=a.replace(D,"$1").replace(E,"$1");d.chars&&d.chars(k(a));return""}),e("",f.last());if(a==j)throw"Parse Error: "+a;j=a}e()}function k(a){l.innerHTML=a.replace(/</g,"&lt;");return l.innerText||l.textContent||""}function t(a){return a.replace(/&/g,"&amp;").replace(F,function(a){return"&#"+a.charCodeAt(0)+";"}).replace(/</g,"&lt;").replace(/>/g,"&gt;")}function u(a){var d=!1,b=g.bind(a,a.push);return{start:function(a,c,h){a=g.lowercase(a);!d&&q[a]&&(d=a);!d&&v[a]==
+!0&&(b("<"),b(a),g.forEach(c,function(a,c){var e=g.lowercase(c);if(G[e]==!0&&(w[e]!==!0||a.match(H)))b(" "),b(c),b('="'),b(t(a)),b('"')}),b(h?"/>":">"))},end:function(a){a=g.lowercase(a);!d&&v[a]==!0&&(b("</"),b(a),b(">"));a==d&&(d=!1)},chars:function(a){d||b(t(a))}}}var s=/^<\s*([\w:-]+)((?:\s+[\w:-]+(?:\s*=\s*(?:(?:"[^"]*")|(?:'[^']*')|[^>\s]+))?)*)\s*(\/?)\s*>/,r=/^<\s*\/\s*([\w:-]+)[^>]*>/,A=/([\w:-]+)(?:\s*=\s*(?:(?:"((?:[^"])*)")|(?:'((?:[^'])*)')|([^>\s]+)))?/g,C=/^</,B=/^<\s*\//,D=/<\!--(.*?)--\>/g,
+E=/<!\[CDATA\[(.*?)]]\>/g,H=/^((ftp|https?):\/\/|mailto:|#)/,F=/([^\#-~| |!])/g,p=i("area,br,col,hr,img,wbr"),x=i("colgroup,dd,dt,li,p,tbody,td,tfoot,th,thead,tr"),y=i("rp,rt"),o=g.extend({},y,x),m=g.extend({},x,i("address,article,aside,blockquote,caption,center,del,dir,div,dl,figure,figcaption,footer,h1,h2,h3,h4,h5,h6,header,hgroup,hr,ins,map,menu,nav,ol,pre,script,section,table,ul")),n=g.extend({},y,i("a,abbr,acronym,b,bdi,bdo,big,br,cite,code,del,dfn,em,font,i,img,ins,kbd,label,map,mark,q,ruby,rp,rt,s,samp,small,span,strike,strong,sub,sup,time,tt,u,var")),
+q=i("script,style"),v=g.extend({},p,m,n,o),w=i("background,cite,href,longdesc,src,usemap"),G=g.extend({},w,i("abbr,align,alt,axis,bgcolor,border,cellpadding,cellspacing,class,clear,color,cols,colspan,compact,coords,dir,face,headers,height,hreflang,hspace,ismap,lang,language,nohref,nowrap,rel,rev,rows,rowspan,rules,scope,scrolling,shape,span,start,summary,target,title,type,valign,value,vspace,width")),l=document.createElement("pre");g.module("ngSanitize",[]).value("$sanitize",function(a){var d=[];
+z(a,u(d));return d.join("")});g.module("ngSanitize").directive("ngBindHtml",["$sanitize",function(a){return function(d,b,e){b.addClass("ng-binding").data("$binding",e.ngBindHtml);d.$watch(e.ngBindHtml,function(c){c=a(c);b.html(c||"")})}}]);g.module("ngSanitize").filter("linky",function(){var a=/((ftp|https?):\/\/|(mailto:)?[A-Za-z0-9._%+-]+@)\S*[^\s\.\;\,\(\)\{\}\<\>]/,d=/^mailto:/;return function(b){if(!b)return b;for(var e=b,c=[],h=u(c),f,g;b=e.match(a);)f=b[0],b[2]==b[3]&&(f="mailto:"+f),g=b.index,
+h.chars(e.substr(0,g)),h.start("a",{href:f}),h.chars(b[0].replace(d,"")),h.end("a"),e=e.substring(g+b[0].length);h.chars(e);return c.join("")}})})(window,window.angular);


[33/51] [abbrv] [partial] Adding Jinwon's custom RCMET

Posted by jo...@apache.org.
http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/app/css/bootstrap.min.css
----------------------------------------------------------------------
diff --git a/src/main/ui/app/css/bootstrap.min.css b/src/main/ui/app/css/bootstrap.min.css
new file mode 100755
index 0000000..c10c7f4
--- /dev/null
+++ b/src/main/ui/app/css/bootstrap.min.css
@@ -0,0 +1,9 @@
+/*!
+ * Bootstrap v2.3.1
+ *
+ * Copyright 2012 Twitter, Inc
+ * Licensed under the Apache License v2.0
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Designed and built with all the love in the world @twitter by @mdo and @fat.
+ */.clearfix{*zoom:1}.clearfix:before,.clearfix:after{display:table;line-height:0;content:""}.clearfix:after{clear:both}.hide-text{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.input-block-level{display:block;width:100%;min-height:30px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}article,aside,details,figcaption,figure,footer,header,hgroup,nav,section{display:block}audio,canvas,video{display:inline-block;*display:inline;*zoom:1}audio:not([controls]){display:none}html{font-size:100%;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%}a:focus{outline:thin dotted #333;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}a:hover,a:active{outline:0}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sup{top:-0.5em}sub{bottom:-0.25em}img{width:auto\9;height:auto;max-width:100%;vertical-align:middle;border:0;-ms-interpolation-mode:bicubic}#map_canvas img,.google-maps img{max-widt
 h:none}button,input,select,textarea{margin:0;font-size:100%;vertical-align:middle}button,input{*overflow:visible;line-height:normal}button::-moz-focus-inner,input::-moz-focus-inner{padding:0;border:0}button,html input[type="button"],input[type="reset"],input[type="submit"]{cursor:pointer;-webkit-appearance:button}label,select,button,input[type="button"],input[type="reset"],input[type="submit"],input[type="radio"],input[type="checkbox"]{cursor:pointer}input[type="search"]{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;-webkit-appearance:textfield}input[type="search"]::-webkit-search-decoration,input[type="search"]::-webkit-search-cancel-button{-webkit-appearance:none}textarea{overflow:auto;vertical-align:top}@media print{*{color:#000!important;text-shadow:none!important;background:transparent!important;box-shadow:none!important}a,a:visited{text-decoration:underline}a[href]:after{content:" (" attr(href) ")"}abbr[title]:after{content:" (" attr(title) 
 ")"}.ir a:after,a[href^="javascript:"]:after,a[href^="#"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100%!important}@page{margin:.5cm}p,h2,h3{orphans:3;widows:3}h2,h3{page-break-after:avoid}}body{margin:0;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;line-height:20px;color:#333;background-color:#fff}a{color:#08c;text-decoration:none}a:hover,a:focus{color:#005580;text-decoration:underline}.img-rounded{-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px}.img-polaroid{padding:4px;background-color:#fff;border:1px solid #ccc;border:1px solid rgba(0,0,0,0.2);-webkit-box-shadow:0 1px 3px rgba(0,0,0,0.1);-moz-box-shadow:0 1px 3px rgba(0,0,0,0.1);box-shadow:0 1px 3px rgba(0,0,0,0.1)}.img-circle{-webkit-border-radius:500px;-moz-border-radius:500px;border-radius:500px}.row{margin-left:-20px;*zoom:1}.row:before,.row:after{display:table;line-hei
 ght:0;content:""}.row:after{clear:both}[class*="span"]{float:left;min-height:1px;margin-left:20px}.container,.navbar-static-top .container,.navbar-fixed-top .container,.navbar-fixed-bottom .container{width:940px}.span12{width:940px}.span11{width:860px}.span10{width:780px}.span9{width:700px}.span8{width:620px}.span7{width:540px}.span6{width:460px}.span5{width:380px}.span4{width:300px}.span3{width:220px}.span2{width:140px}.span1{width:60px}.offset12{margin-left:980px}.offset11{margin-left:900px}.offset10{margin-left:820px}.offset9{margin-left:740px}.offset8{margin-left:660px}.offset7{margin-left:580px}.offset6{margin-left:500px}.offset5{margin-left:420px}.offset4{margin-left:340px}.offset3{margin-left:260px}.offset2{margin-left:180px}.offset1{margin-left:100px}.row-fluid{width:100%;*zoom:1}.row-fluid:before,.row-fluid:after{display:table;line-height:0;content:""}.row-fluid:after{clear:both}.row-fluid [class*="span"]{display:block;float:left;width:100%;min-height:30px;margin-left:2.127
 659574468085%;*margin-left:2.074468085106383%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.row-fluid [class*="span"]:first-child{margin-left:0}.row-fluid .controls-row [class*="span"]+[class*="span"]{margin-left:2.127659574468085%}.row-fluid .span12{width:100%;*width:99.94680851063829%}.row-fluid .span11{width:91.48936170212765%;*width:91.43617021276594%}.row-fluid .span10{width:82.97872340425532%;*width:82.92553191489361%}.row-fluid .span9{width:74.46808510638297%;*width:74.41489361702126%}.row-fluid .span8{width:65.95744680851064%;*width:65.90425531914893%}.row-fluid .span7{width:57.44680851063829%;*width:57.39361702127659%}.row-fluid .span6{width:48.93617021276595%;*width:48.88297872340425%}.row-fluid .span5{width:40.42553191489362%;*width:40.37234042553192%}.row-fluid .span4{width:31.914893617021278%;*width:31.861702127659576%}.row-fluid .span3{width:23.404255319148934%;*width:23.351063829787233%}.row-fluid .span2{width:14.893617021276595%;*wid
 th:14.840425531914894%}.row-fluid .span1{width:6.382978723404255%;*width:6.329787234042553%}.row-fluid .offset12{margin-left:104.25531914893617%;*margin-left:104.14893617021275%}.row-fluid .offset12:first-child{margin-left:102.12765957446808%;*margin-left:102.02127659574467%}.row-fluid .offset11{margin-left:95.74468085106382%;*margin-left:95.6382978723404%}.row-fluid .offset11:first-child{margin-left:93.61702127659574%;*margin-left:93.51063829787232%}.row-fluid .offset10{margin-left:87.23404255319149%;*margin-left:87.12765957446807%}.row-fluid .offset10:first-child{margin-left:85.1063829787234%;*margin-left:84.99999999999999%}.row-fluid .offset9{margin-left:78.72340425531914%;*margin-left:78.61702127659572%}.row-fluid .offset9:first-child{margin-left:76.59574468085106%;*margin-left:76.48936170212764%}.row-fluid .offset8{margin-left:70.2127659574468%;*margin-left:70.10638297872339%}.row-fluid .offset8:first-child{margin-left:68.08510638297872%;*margin-left:67.9787234042553%}.row-flui
 d .offset7{margin-left:61.70212765957446%;*margin-left:61.59574468085106%}.row-fluid .offset7:first-child{margin-left:59.574468085106375%;*margin-left:59.46808510638297%}.row-fluid .offset6{margin-left:53.191489361702125%;*margin-left:53.085106382978715%}.row-fluid .offset6:first-child{margin-left:51.063829787234035%;*margin-left:50.95744680851063%}.row-fluid .offset5{margin-left:44.68085106382979%;*margin-left:44.57446808510638%}.row-fluid .offset5:first-child{margin-left:42.5531914893617%;*margin-left:42.4468085106383%}.row-fluid .offset4{margin-left:36.170212765957444%;*margin-left:36.06382978723405%}.row-fluid .offset4:first-child{margin-left:34.04255319148936%;*margin-left:33.93617021276596%}.row-fluid .offset3{margin-left:27.659574468085104%;*margin-left:27.5531914893617%}.row-fluid .offset3:first-child{margin-left:25.53191489361702%;*margin-left:25.425531914893618%}.row-fluid .offset2{margin-left:19.148936170212764%;*margin-left:19.04255319148936%}.row-fluid .offset2:first-ch
 ild{margin-left:17.02127659574468%;*margin-left:16.914893617021278%}.row-fluid .offset1{margin-left:10.638297872340425%;*margin-left:10.53191489361702%}.row-fluid .offset1:first-child{margin-left:8.51063829787234%;*margin-left:8.404255319148938%}[class*="span"].hide,.row-fluid [class*="span"].hide{display:none}[class*="span"].pull-right,.row-fluid [class*="span"].pull-right{float:right}.container{margin-right:auto;margin-left:auto;*zoom:1}.container:before,.container:after{display:table;line-height:0;content:""}.container:after{clear:both}.container-fluid{padding-right:20px;padding-left:20px;*zoom:1}.container-fluid:before,.container-fluid:after{display:table;line-height:0;content:""}.container-fluid:after{clear:both}p{margin:0 0 10px}.lead{margin-bottom:20px;font-size:21px;font-weight:200;line-height:30px}small{font-size:85%}strong{font-weight:bold}em{font-style:italic}cite{font-style:normal}.muted{color:#999}a.muted:hover,a.muted:focus{color:#808080}.text-warning{color:#c09853}a.t
 ext-warning:hover,a.text-warning:focus{color:#a47e3c}.text-error{color:#b94a48}a.text-error:hover,a.text-error:focus{color:#953b39}.text-info{color:#3a87ad}a.text-info:hover,a.text-info:focus{color:#2d6987}.text-success{color:#468847}a.text-success:hover,a.text-success:focus{color:#356635}.text-left{text-align:left}.text-right{text-align:right}.text-center{text-align:center}h1,h2,h3,h4,h5,h6{margin:10px 0;font-family:inherit;font-weight:bold;line-height:20px;color:inherit;text-rendering:optimizelegibility}h1 small,h2 small,h3 small,h4 small,h5 small,h6 small{font-weight:normal;line-height:1;color:#999}h1,h2,h3{line-height:40px}h1{font-size:38.5px}h2{font-size:31.5px}h3{font-size:24.5px}h4{font-size:17.5px}h5{font-size:14px}h6{font-size:11.9px}h1 small{font-size:24.5px}h2 small{font-size:17.5px}h3 small{font-size:14px}h4 small{font-size:14px}.page-header{padding-bottom:9px;margin:20px 0 30px;border-bottom:1px solid #eee}ul,ol{padding:0;margin:0 0 10px 25px}ul ul,ul ol,ol ol,ol ul{mar
 gin-bottom:0}li{line-height:20px}ul.unstyled,ol.unstyled{margin-left:0;list-style:none}ul.inline,ol.inline{margin-left:0;list-style:none}ul.inline>li,ol.inline>li{display:inline-block;*display:inline;padding-right:5px;padding-left:5px;*zoom:1}dl{margin-bottom:20px}dt,dd{line-height:20px}dt{font-weight:bold}dd{margin-left:10px}.dl-horizontal{*zoom:1}.dl-horizontal:before,.dl-horizontal:after{display:table;line-height:0;content:""}.dl-horizontal:after{clear:both}.dl-horizontal dt{float:left;width:160px;overflow:hidden;clear:left;text-align:right;text-overflow:ellipsis;white-space:nowrap}.dl-horizontal dd{margin-left:180px}hr{margin:20px 0;border:0;border-top:1px solid #eee;border-bottom:1px solid #fff}abbr[title],abbr[data-original-title]{cursor:help;border-bottom:1px dotted #999}abbr.initialism{font-size:90%;text-transform:uppercase}blockquote{padding:0 0 0 15px;margin:0 0 20px;border-left:5px solid #eee}blockquote p{margin-bottom:0;font-size:17.5px;font-weight:300;line-height:1.25}b
 lockquote small{display:block;line-height:20px;color:#999}blockquote small:before{content:'\2014 \00A0'}blockquote.pull-right{float:right;padding-right:15px;padding-left:0;border-right:5px solid #eee;border-left:0}blockquote.pull-right p,blockquote.pull-right small{text-align:right}blockquote.pull-right small:before{content:''}blockquote.pull-right small:after{content:'\00A0 \2014'}q:before,q:after,blockquote:before,blockquote:after{content:""}address{display:block;margin-bottom:20px;font-style:normal;line-height:20px}code,pre{padding:0 3px 2px;font-family:Monaco,Menlo,Consolas,"Courier New",monospace;font-size:12px;color:#333;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}code{padding:2px 4px;color:#d14;white-space:nowrap;background-color:#f7f7f9;border:1px solid #e1e1e8}pre{display:block;padding:9.5px;margin:0 0 10px;font-size:13px;line-height:20px;word-break:break-all;word-wrap:break-word;white-space:pre;white-space:pre-wrap;background-color:#f5f5f5;border:1px
  solid #ccc;border:1px solid rgba(0,0,0,0.15);-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}pre.prettyprint{margin-bottom:20px}pre code{padding:0;color:inherit;white-space:pre;white-space:pre-wrap;background-color:transparent;border:0}.pre-scrollable{max-height:340px;overflow-y:scroll}form{margin:0 0 20px}fieldset{padding:0;margin:0;border:0}legend{display:block;width:100%;padding:0;margin-bottom:20px;font-size:21px;line-height:40px;color:#333;border:0;border-bottom:1px solid #e5e5e5}legend small{font-size:15px;color:#999}label,input,button,select,textarea{font-size:14px;font-weight:normal;line-height:20px}input,button,select,textarea{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif}label{display:block;margin-bottom:5px}select,textarea,input[type="text"],input[type="password"],input[type="datetime"],input[type="datetime-local"],input[type="date"],input[type="month"],input[type="time"],input[type="week"],input[type="number"],input[type="email"],input[type=
 "url"],input[type="search"],input[type="tel"],input[type="color"],.uneditable-input{display:inline-block;height:20px;padding:4px 6px;margin-bottom:10px;font-size:14px;line-height:20px;color:#555;vertical-align:middle;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}input,textarea,.uneditable-input{width:206px}textarea{height:auto}textarea,input[type="text"],input[type="password"],input[type="datetime"],input[type="datetime-local"],input[type="date"],input[type="month"],input[type="time"],input[type="week"],input[type="number"],input[type="email"],input[type="url"],input[type="search"],input[type="tel"],input[type="color"],.uneditable-input{background-color:#fff;border:1px solid #ccc;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-webkit-transition:border linear .2s,box-shadow linear .2s;-moz-transition:border linear .2s,box-shadow linear .2s;-o-transition:border lin
 ear .2s,box-shadow linear .2s;transition:border linear .2s,box-shadow linear .2s}textarea:focus,input[type="text"]:focus,input[type="password"]:focus,input[type="datetime"]:focus,input[type="datetime-local"]:focus,input[type="date"]:focus,input[type="month"]:focus,input[type="time"]:focus,input[type="week"]:focus,input[type="number"]:focus,input[type="email"]:focus,input[type="url"]:focus,input[type="search"]:focus,input[type="tel"]:focus,input[type="color"]:focus,.uneditable-input:focus{border-color:rgba(82,168,236,0.8);outline:0;outline:thin dotted \9;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 8px rgba(82,168,236,0.6);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 8px rgba(82,168,236,0.6);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 8px rgba(82,168,236,0.6)}input[type="radio"],input[type="checkbox"]{margin:4px 0 0;margin-top:1px \9;*margin-top:0;line-height:normal}input[type="file"],input[type="image"],input[type="submit"],input[type="reset"],input[type="b
 utton"],input[type="radio"],input[type="checkbox"]{width:auto}select,input[type="file"]{height:30px;*margin-top:4px;line-height:30px}select{width:220px;background-color:#fff;border:1px solid #ccc}select[multiple],select[size]{height:auto}select:focus,input[type="file"]:focus,input[type="radio"]:focus,input[type="checkbox"]:focus{outline:thin dotted #333;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.uneditable-input,.uneditable-textarea{color:#999;cursor:not-allowed;background-color:#fcfcfc;border-color:#ccc;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,0.025);-moz-box-shadow:inset 0 1px 2px rgba(0,0,0,0.025);box-shadow:inset 0 1px 2px rgba(0,0,0,0.025)}.uneditable-input{overflow:hidden;white-space:nowrap}.uneditable-textarea{width:auto;height:auto}input:-moz-placeholder,textarea:-moz-placeholder{color:#999}input:-ms-input-placeholder,textarea:-ms-input-placeholder{color:#999}input::-webkit-input-placeholder,textarea::-webkit-input-placeholder{color:#999}.radio,.chec
 kbox{min-height:20px;padding-left:20px}.radio input[type="radio"],.checkbox input[type="checkbox"]{float:left;margin-left:-20px}.controls>.radio:first-child,.controls>.checkbox:first-child{padding-top:5px}.radio.inline,.checkbox.inline{display:inline-block;padding-top:5px;margin-bottom:0;vertical-align:middle}.radio.inline+.radio.inline,.checkbox.inline+.checkbox.inline{margin-left:10px}.input-mini{width:60px}.input-small{width:90px}.input-medium{width:150px}.input-large{width:210px}.input-xlarge{width:270px}.input-xxlarge{width:530px}input[class*="span"],select[class*="span"],textarea[class*="span"],.uneditable-input[class*="span"],.row-fluid input[class*="span"],.row-fluid select[class*="span"],.row-fluid textarea[class*="span"],.row-fluid .uneditable-input[class*="span"]{float:none;margin-left:0}.input-append input[class*="span"],.input-append .uneditable-input[class*="span"],.input-prepend input[class*="span"],.input-prepend .uneditable-input[class*="span"],.row-fluid input[clas
 s*="span"],.row-fluid select[class*="span"],.row-fluid textarea[class*="span"],.row-fluid .uneditable-input[class*="span"],.row-fluid .input-prepend [class*="span"],.row-fluid .input-append [class*="span"]{display:inline-block}input,textarea,.uneditable-input{margin-left:0}.controls-row [class*="span"]+[class*="span"]{margin-left:20px}input.span12,textarea.span12,.uneditable-input.span12{width:926px}input.span11,textarea.span11,.uneditable-input.span11{width:846px}input.span10,textarea.span10,.uneditable-input.span10{width:766px}input.span9,textarea.span9,.uneditable-input.span9{width:686px}input.span8,textarea.span8,.uneditable-input.span8{width:606px}input.span7,textarea.span7,.uneditable-input.span7{width:526px}input.span6,textarea.span6,.uneditable-input.span6{width:446px}input.span5,textarea.span5,.uneditable-input.span5{width:366px}input.span4,textarea.span4,.uneditable-input.span4{width:286px}input.span3,textarea.span3,.uneditable-input.span3{width:206px}input.span2,textarea.
 span2,.uneditable-input.span2{width:126px}input.span1,textarea.span1,.uneditable-input.span1{width:46px}.controls-row{*zoom:1}.controls-row:before,.controls-row:after{display:table;line-height:0;content:""}.controls-row:after{clear:both}.controls-row [class*="span"],.row-fluid .controls-row [class*="span"]{float:left}.controls-row .checkbox[class*="span"],.controls-row .radio[class*="span"]{padding-top:5px}input[disabled],select[disabled],textarea[disabled],input[readonly],select[readonly],textarea[readonly]{cursor:not-allowed;background-color:#eee}input[type="radio"][disabled],input[type="checkbox"][disabled],input[type="radio"][readonly],input[type="checkbox"][readonly]{background-color:transparent}.control-group.warning .control-label,.control-group.warning .help-block,.control-group.warning .help-inline{color:#c09853}.control-group.warning .checkbox,.control-group.warning .radio,.control-group.warning input,.control-group.warning select,.control-group.warning textarea{color:#c09
 853}.control-group.warning input,.control-group.warning select,.control-group.warning textarea{border-color:#c09853;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.control-group.warning input:focus,.control-group.warning select:focus,.control-group.warning textarea:focus{border-color:#a47e3c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #dbc59e;-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #dbc59e;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #dbc59e}.control-group.warning .input-prepend .add-on,.control-group.warning .input-append .add-on{color:#c09853;background-color:#fcf8e3;border-color:#c09853}.control-group.error .control-label,.control-group.error .help-block,.control-group.error .help-inline{color:#b94a48}.control-group.error .checkbox,.control-group.error .radio,.control-group.error input,.control-group.error select,.control-group.error text
 area{color:#b94a48}.control-group.error input,.control-group.error select,.control-group.error textarea{border-color:#b94a48;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.control-group.error input:focus,.control-group.error select:focus,.control-group.error textarea:focus{border-color:#953b39;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #d59392;-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #d59392;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #d59392}.control-group.error .input-prepend .add-on,.control-group.error .input-append .add-on{color:#b94a48;background-color:#f2dede;border-color:#b94a48}.control-group.success .control-label,.control-group.success .help-block,.control-group.success .help-inline{color:#468847}.control-group.success .checkbox,.control-group.success .radio,.control-group.success input,.control-group.success select,.control-gro
 up.success textarea{color:#468847}.control-group.success input,.control-group.success select,.control-group.success textarea{border-color:#468847;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.control-group.success input:focus,.control-group.success select:focus,.control-group.success textarea:focus{border-color:#356635;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #7aba7b;-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #7aba7b;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #7aba7b}.control-group.success .input-prepend .add-on,.control-group.success .input-append .add-on{color:#468847;background-color:#dff0d8;border-color:#468847}.control-group.info .control-label,.control-group.info .help-block,.control-group.info .help-inline{color:#3a87ad}.control-group.info .checkbox,.control-group.info .radio,.control-group.info input,.control-group.info select,.c
 ontrol-group.info textarea{color:#3a87ad}.control-group.info input,.control-group.info select,.control-group.info textarea{border-color:#3a87ad;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.control-group.info input:focus,.control-group.info select:focus,.control-group.info textarea:focus{border-color:#2d6987;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #7ab5d3;-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #7ab5d3;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #7ab5d3}.control-group.info .input-prepend .add-on,.control-group.info .input-append .add-on{color:#3a87ad;background-color:#d9edf7;border-color:#3a87ad}input:focus:invalid,textarea:focus:invalid,select:focus:invalid{color:#b94a48;border-color:#ee5f5b}input:focus:invalid:focus,textarea:focus:invalid:focus,select:focus:invalid:focus{border-color:#e9322d;-webkit-box-shadow:0 0 6px #f8b9b7;-moz-b
 ox-shadow:0 0 6px #f8b9b7;box-shadow:0 0 6px #f8b9b7}.form-actions{padding:19px 20px 20px;margin-top:20px;margin-bottom:20px;background-color:#f5f5f5;border-top:1px solid #e5e5e5;*zoom:1}.form-actions:before,.form-actions:after{display:table;line-height:0;content:""}.form-actions:after{clear:both}.help-block,.help-inline{color:#595959}.help-block{display:block;margin-bottom:10px}.help-inline{display:inline-block;*display:inline;padding-left:5px;vertical-align:middle;*zoom:1}.input-append,.input-prepend{display:inline-block;margin-bottom:10px;font-size:0;white-space:nowrap;vertical-align:middle}.input-append input,.input-prepend input,.input-append select,.input-prepend select,.input-append .uneditable-input,.input-prepend .uneditable-input,.input-append .dropdown-menu,.input-prepend .dropdown-menu,.input-append .popover,.input-prepend .popover{font-size:14px}.input-append input,.input-prepend input,.input-append select,.input-prepend select,.input-append .uneditable-input,.input-pre
 pend .uneditable-input{position:relative;margin-bottom:0;*margin-left:0;vertical-align:top;-webkit-border-radius:0 4px 4px 0;-moz-border-radius:0 4px 4px 0;border-radius:0 4px 4px 0}.input-append input:focus,.input-prepend input:focus,.input-append select:focus,.input-prepend select:focus,.input-append .uneditable-input:focus,.input-prepend .uneditable-input:focus{z-index:2}.input-append .add-on,.input-prepend .add-on{display:inline-block;width:auto;height:20px;min-width:16px;padding:4px 5px;font-size:14px;font-weight:normal;line-height:20px;text-align:center;text-shadow:0 1px 0 #fff;background-color:#eee;border:1px solid #ccc}.input-append .add-on,.input-prepend .add-on,.input-append .btn,.input-prepend .btn,.input-append .btn-group>.dropdown-toggle,.input-prepend .btn-group>.dropdown-toggle{vertical-align:top;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.input-append .active,.input-prepend .active{background-color:#a9dba9;border-color:#46a546}.input-prepend .add-on
 ,.input-prepend .btn{margin-right:-1px}.input-prepend .add-on:first-child,.input-prepend .btn:first-child{-webkit-border-radius:4px 0 0 4px;-moz-border-radius:4px 0 0 4px;border-radius:4px 0 0 4px}.input-append input,.input-append select,.input-append .uneditable-input{-webkit-border-radius:4px 0 0 4px;-moz-border-radius:4px 0 0 4px;border-radius:4px 0 0 4px}.input-append input+.btn-group .btn:last-child,.input-append select+.btn-group .btn:last-child,.input-append .uneditable-input+.btn-group .btn:last-child{-webkit-border-radius:0 4px 4px 0;-moz-border-radius:0 4px 4px 0;border-radius:0 4px 4px 0}.input-append .add-on,.input-append .btn,.input-append .btn-group{margin-left:-1px}.input-append .add-on:last-child,.input-append .btn:last-child,.input-append .btn-group:last-child>.dropdown-toggle{-webkit-border-radius:0 4px 4px 0;-moz-border-radius:0 4px 4px 0;border-radius:0 4px 4px 0}.input-prepend.input-append input,.input-prepend.input-append select,.input-prepend.input-append .une
 ditable-input{-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.input-prepend.input-append input+.btn-group .btn,.input-prepend.input-append select+.btn-group .btn,.input-prepend.input-append .uneditable-input+.btn-group .btn{-webkit-border-radius:0 4px 4px 0;-moz-border-radius:0 4px 4px 0;border-radius:0 4px 4px 0}.input-prepend.input-append .add-on:first-child,.input-prepend.input-append .btn:first-child{margin-right:-1px;-webkit-border-radius:4px 0 0 4px;-moz-border-radius:4px 0 0 4px;border-radius:4px 0 0 4px}.input-prepend.input-append .add-on:last-child,.input-prepend.input-append .btn:last-child{margin-left:-1px;-webkit-border-radius:0 4px 4px 0;-moz-border-radius:0 4px 4px 0;border-radius:0 4px 4px 0}.input-prepend.input-append .btn-group:first-child{margin-left:0}input.search-query{padding-right:14px;padding-right:4px \9;padding-left:14px;padding-left:4px \9;margin-bottom:0;-webkit-border-radius:15px;-moz-border-radius:15px;border-radius:15px}.form-search .input
 -append .search-query,.form-search .input-prepend .search-query{-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.form-search .input-append .search-query{-webkit-border-radius:14px 0 0 14px;-moz-border-radius:14px 0 0 14px;border-radius:14px 0 0 14px}.form-search .input-append .btn{-webkit-border-radius:0 14px 14px 0;-moz-border-radius:0 14px 14px 0;border-radius:0 14px 14px 0}.form-search .input-prepend .search-query{-webkit-border-radius:0 14px 14px 0;-moz-border-radius:0 14px 14px 0;border-radius:0 14px 14px 0}.form-search .input-prepend .btn{-webkit-border-radius:14px 0 0 14px;-moz-border-radius:14px 0 0 14px;border-radius:14px 0 0 14px}.form-search input,.form-inline input,.form-horizontal input,.form-search textarea,.form-inline textarea,.form-horizontal textarea,.form-search select,.form-inline select,.form-horizontal select,.form-search .help-inline,.form-inline .help-inline,.form-horizontal .help-inline,.form-search .uneditable-input,.form-inline .uneditable-inp
 ut,.form-horizontal .uneditable-input,.form-search .input-prepend,.form-inline .input-prepend,.form-horizontal .input-prepend,.form-search .input-append,.form-inline .input-append,.form-horizontal .input-append{display:inline-block;*display:inline;margin-bottom:0;vertical-align:middle;*zoom:1}.form-search .hide,.form-inline .hide,.form-horizontal .hide{display:none}.form-search label,.form-inline label,.form-search .btn-group,.form-inline .btn-group{display:inline-block}.form-search .input-append,.form-inline .input-append,.form-search .input-prepend,.form-inline .input-prepend{margin-bottom:0}.form-search .radio,.form-search .checkbox,.form-inline .radio,.form-inline .checkbox{padding-left:0;margin-bottom:0;vertical-align:middle}.form-search .radio input[type="radio"],.form-search .checkbox input[type="checkbox"],.form-inline .radio input[type="radio"],.form-inline .checkbox input[type="checkbox"]{float:left;margin-right:3px;margin-left:0}.control-group{margin-bottom:10px}legend+.c
 ontrol-group{margin-top:20px;-webkit-margin-top-collapse:separate}.form-horizontal .control-group{margin-bottom:20px;*zoom:1}.form-horizontal .control-group:before,.form-horizontal .control-group:after{display:table;line-height:0;content:""}.form-horizontal .control-group:after{clear:both}.form-horizontal .control-label{float:left;width:160px;padding-top:5px;text-align:right}.form-horizontal .controls{*display:inline-block;*padding-left:20px;margin-left:180px;*margin-left:0}.form-horizontal .controls:first-child{*padding-left:180px}.form-horizontal .help-block{margin-bottom:0}.form-horizontal input+.help-block,.form-horizontal select+.help-block,.form-horizontal textarea+.help-block,.form-horizontal .uneditable-input+.help-block,.form-horizontal .input-prepend+.help-block,.form-horizontal .input-append+.help-block{margin-top:10px}.form-horizontal .form-actions{padding-left:180px}table{max-width:100%;background-color:transparent;border-collapse:collapse;border-spacing:0}.table{width:
 100%;margin-bottom:20px}.table th,.table td{padding:8px;line-height:20px;text-align:left;vertical-align:top;border-top:1px solid #ddd}.table th{font-weight:bold}.table thead th{vertical-align:bottom}.table caption+thead tr:first-child th,.table caption+thead tr:first-child td,.table colgroup+thead tr:first-child th,.table colgroup+thead tr:first-child td,.table thead:first-child tr:first-child th,.table thead:first-child tr:first-child td{border-top:0}.table tbody+tbody{border-top:2px solid #ddd}.table .table{background-color:#fff}.table-condensed th,.table-condensed td{padding:4px 5px}.table-bordered{border:1px solid #ddd;border-collapse:separate;*border-collapse:collapse;border-left:0;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.table-bordered th,.table-bordered td{border-left:1px solid #ddd}.table-bordered caption+thead tr:first-child th,.table-bordered caption+tbody tr:first-child th,.table-bordered caption+tbody tr:first-child td,.table-bordered colgroup+
 thead tr:first-child th,.table-bordered colgroup+tbody tr:first-child th,.table-bordered colgroup+tbody tr:first-child td,.table-bordered thead:first-child tr:first-child th,.table-bordered tbody:first-child tr:first-child th,.table-bordered tbody:first-child tr:first-child td{border-top:0}.table-bordered thead:first-child tr:first-child>th:first-child,.table-bordered tbody:first-child tr:first-child>td:first-child,.table-bordered tbody:first-child tr:first-child>th:first-child{-webkit-border-top-left-radius:4px;border-top-left-radius:4px;-moz-border-radius-topleft:4px}.table-bordered thead:first-child tr:first-child>th:last-child,.table-bordered tbody:first-child tr:first-child>td:last-child,.table-bordered tbody:first-child tr:first-child>th:last-child{-webkit-border-top-right-radius:4px;border-top-right-radius:4px;-moz-border-radius-topright:4px}.table-bordered thead:last-child tr:last-child>th:first-child,.table-bordered tbody:last-child tr:last-child>td:first-child,.table-borde
 red tbody:last-child tr:last-child>th:first-child,.table-bordered tfoot:last-child tr:last-child>td:first-child,.table-bordered tfoot:last-child tr:last-child>th:first-child{-webkit-border-bottom-left-radius:4px;border-bottom-left-radius:4px;-moz-border-radius-bottomleft:4px}.table-bordered thead:last-child tr:last-child>th:last-child,.table-bordered tbody:last-child tr:last-child>td:last-child,.table-bordered tbody:last-child tr:last-child>th:last-child,.table-bordered tfoot:last-child tr:last-child>td:last-child,.table-bordered tfoot:last-child tr:last-child>th:last-child{-webkit-border-bottom-right-radius:4px;border-bottom-right-radius:4px;-moz-border-radius-bottomright:4px}.table-bordered tfoot+tbody:last-child tr:last-child td:first-child{-webkit-border-bottom-left-radius:0;border-bottom-left-radius:0;-moz-border-radius-bottomleft:0}.table-bordered tfoot+tbody:last-child tr:last-child td:last-child{-webkit-border-bottom-right-radius:0;border-bottom-right-radius:0;-moz-border-ra
 dius-bottomright:0}.table-bordered caption+thead tr:first-child th:first-child,.table-bordered caption+tbody tr:first-child td:first-child,.table-bordered colgroup+thead tr:first-child th:first-child,.table-bordered colgroup+tbody tr:first-child td:first-child{-webkit-border-top-left-radius:4px;border-top-left-radius:4px;-moz-border-radius-topleft:4px}.table-bordered caption+thead tr:first-child th:last-child,.table-bordered caption+tbody tr:first-child td:last-child,.table-bordered colgroup+thead tr:first-child th:last-child,.table-bordered colgroup+tbody tr:first-child td:last-child{-webkit-border-top-right-radius:4px;border-top-right-radius:4px;-moz-border-radius-topright:4px}.table-striped tbody>tr:nth-child(odd)>td,.table-striped tbody>tr:nth-child(odd)>th{background-color:#f9f9f9}.table-hover tbody tr:hover>td,.table-hover tbody tr:hover>th{background-color:#f5f5f5}table td[class*="span"],table th[class*="span"],.row-fluid table td[class*="span"],.row-fluid table th[class*="sp
 an"]{display:table-cell;float:none;margin-left:0}.table td.span1,.table th.span1{float:none;width:44px;margin-left:0}.table td.span2,.table th.span2{float:none;width:124px;margin-left:0}.table td.span3,.table th.span3{float:none;width:204px;margin-left:0}.table td.span4,.table th.span4{float:none;width:284px;margin-left:0}.table td.span5,.table th.span5{float:none;width:364px;margin-left:0}.table td.span6,.table th.span6{float:none;width:444px;margin-left:0}.table td.span7,.table th.span7{float:none;width:524px;margin-left:0}.table td.span8,.table th.span8{float:none;width:604px;margin-left:0}.table td.span9,.table th.span9{float:none;width:684px;margin-left:0}.table td.span10,.table th.span10{float:none;width:764px;margin-left:0}.table td.span11,.table th.span11{float:none;width:844px;margin-left:0}.table td.span12,.table th.span12{float:none;width:924px;margin-left:0}.table tbody tr.success>td{background-color:#dff0d8}.table tbody tr.error>td{background-color:#f2dede}.table tbody 
 tr.warning>td{background-color:#fcf8e3}.table tbody tr.info>td{background-color:#d9edf7}.table-hover tbody tr.success:hover>td{background-color:#d0e9c6}.table-hover tbody tr.error:hover>td{background-color:#ebcccc}.table-hover tbody tr.warning:hover>td{background-color:#faf2cc}.table-hover tbody tr.info:hover>td{background-color:#c4e3f3}[class^="icon-"],[class*=" icon-"]{display:inline-block;width:14px;height:14px;margin-top:1px;*margin-right:.3em;line-height:14px;vertical-align:text-top;background-image:url("../img/glyphicons-halflings.png");background-position:14px 14px;background-repeat:no-repeat}.icon-white,.nav-pills>.active>a>[class^="icon-"],.nav-pills>.active>a>[class*=" icon-"],.nav-list>.active>a>[class^="icon-"],.nav-list>.active>a>[class*=" icon-"],.navbar-inverse .nav>.active>a>[class^="icon-"],.navbar-inverse .nav>.active>a>[class*=" icon-"],.dropdown-menu>li>a:hover>[class^="icon-"],.dropdown-menu>li>a:focus>[class^="icon-"],.dropdown-menu>li>a:hover>[class*=" icon-"]
 ,.dropdown-menu>li>a:focus>[class*=" icon-"],.dropdown-menu>.active>a>[class^="icon-"],.dropdown-menu>.active>a>[class*=" icon-"],.dropdown-submenu:hover>a>[class^="icon-"],.dropdown-submenu:focus>a>[class^="icon-"],.dropdown-submenu:hover>a>[class*=" icon-"],.dropdown-submenu:focus>a>[class*=" icon-"]{background-image:url("../img/glyphicons-halflings-white.png")}.icon-glass{background-position:0 0}.icon-music{background-position:-24px 0}.icon-search{background-position:-48px 0}.icon-envelope{background-position:-72px 0}.icon-heart{background-position:-96px 0}.icon-star{background-position:-120px 0}.icon-star-empty{background-position:-144px 0}.icon-user{background-position:-168px 0}.icon-film{background-position:-192px 0}.icon-th-large{background-position:-216px 0}.icon-th{background-position:-240px 0}.icon-th-list{background-position:-264px 0}.icon-ok{background-position:-288px 0}.icon-remove{background-position:-312px 0}.icon-zoom-in{background-position:-336px 0}.icon-zoom-out{ba
 ckground-position:-360px 0}.icon-off{background-position:-384px 0}.icon-signal{background-position:-408px 0}.icon-cog{background-position:-432px 0}.icon-trash{background-position:-456px 0}.icon-home{background-position:0 -24px}.icon-file{background-position:-24px -24px}.icon-time{background-position:-48px -24px}.icon-road{background-position:-72px -24px}.icon-download-alt{background-position:-96px -24px}.icon-download{background-position:-120px -24px}.icon-upload{background-position:-144px -24px}.icon-inbox{background-position:-168px -24px}.icon-play-circle{background-position:-192px -24px}.icon-repeat{background-position:-216px -24px}.icon-refresh{background-position:-240px -24px}.icon-list-alt{background-position:-264px -24px}.icon-lock{background-position:-287px -24px}.icon-flag{background-position:-312px -24px}.icon-headphones{background-position:-336px -24px}.icon-volume-off{background-position:-360px -24px}.icon-volume-down{background-position:-384px -24px}.icon-volume-up{back
 ground-position:-408px -24px}.icon-qrcode{background-position:-432px -24px}.icon-barcode{background-position:-456px -24px}.icon-tag{background-position:0 -48px}.icon-tags{background-position:-25px -48px}.icon-book{background-position:-48px -48px}.icon-bookmark{background-position:-72px -48px}.icon-print{background-position:-96px -48px}.icon-camera{background-position:-120px -48px}.icon-font{background-position:-144px -48px}.icon-bold{background-position:-167px -48px}.icon-italic{background-position:-192px -48px}.icon-text-height{background-position:-216px -48px}.icon-text-width{background-position:-240px -48px}.icon-align-left{background-position:-264px -48px}.icon-align-center{background-position:-288px -48px}.icon-align-right{background-position:-312px -48px}.icon-align-justify{background-position:-336px -48px}.icon-list{background-position:-360px -48px}.icon-indent-left{background-position:-384px -48px}.icon-indent-right{background-position:-408px -48px}.icon-facetime-video{backg
 round-position:-432px -48px}.icon-picture{background-position:-456px -48px}.icon-pencil{background-position:0 -72px}.icon-map-marker{background-position:-24px -72px}.icon-adjust{background-position:-48px -72px}.icon-tint{background-position:-72px -72px}.icon-edit{background-position:-96px -72px}.icon-share{background-position:-120px -72px}.icon-check{background-position:-144px -72px}.icon-move{background-position:-168px -72px}.icon-step-backward{background-position:-192px -72px}.icon-fast-backward{background-position:-216px -72px}.icon-backward{background-position:-240px -72px}.icon-play{background-position:-264px -72px}.icon-pause{background-position:-288px -72px}.icon-stop{background-position:-312px -72px}.icon-forward{background-position:-336px -72px}.icon-fast-forward{background-position:-360px -72px}.icon-step-forward{background-position:-384px -72px}.icon-eject{background-position:-408px -72px}.icon-chevron-left{background-position:-432px -72px}.icon-chevron-right{background-p
 osition:-456px -72px}.icon-plus-sign{background-position:0 -96px}.icon-minus-sign{background-position:-24px -96px}.icon-remove-sign{background-position:-48px -96px}.icon-ok-sign{background-position:-72px -96px}.icon-question-sign{background-position:-96px -96px}.icon-info-sign{background-position:-120px -96px}.icon-screenshot{background-position:-144px -96px}.icon-remove-circle{background-position:-168px -96px}.icon-ok-circle{background-position:-192px -96px}.icon-ban-circle{background-position:-216px -96px}.icon-arrow-left{background-position:-240px -96px}.icon-arrow-right{background-position:-264px -96px}.icon-arrow-up{background-position:-289px -96px}.icon-arrow-down{background-position:-312px -96px}.icon-share-alt{background-position:-336px -96px}.icon-resize-full{background-position:-360px -96px}.icon-resize-small{background-position:-384px -96px}.icon-plus{background-position:-408px -96px}.icon-minus{background-position:-433px -96px}.icon-asterisk{background-position:-456px -9
 6px}.icon-exclamation-sign{background-position:0 -120px}.icon-gift{background-position:-24px -120px}.icon-leaf{background-position:-48px -120px}.icon-fire{background-position:-72px -120px}.icon-eye-open{background-position:-96px -120px}.icon-eye-close{background-position:-120px -120px}.icon-warning-sign{background-position:-144px -120px}.icon-plane{background-position:-168px -120px}.icon-calendar{background-position:-192px -120px}.icon-random{width:16px;background-position:-216px -120px}.icon-comment{background-position:-240px -120px}.icon-magnet{background-position:-264px -120px}.icon-chevron-up{background-position:-288px -120px}.icon-chevron-down{background-position:-313px -119px}.icon-retweet{background-position:-336px -120px}.icon-shopping-cart{background-position:-360px -120px}.icon-folder-close{width:16px;background-position:-384px -120px}.icon-folder-open{width:16px;background-position:-408px -120px}.icon-resize-vertical{background-position:-432px -119px}.icon-resize-horizont
 al{background-position:-456px -118px}.icon-hdd{background-position:0 -144px}.icon-bullhorn{background-position:-24px -144px}.icon-bell{background-position:-48px -144px}.icon-certificate{background-position:-72px -144px}.icon-thumbs-up{background-position:-96px -144px}.icon-thumbs-down{background-position:-120px -144px}.icon-hand-right{background-position:-144px -144px}.icon-hand-left{background-position:-168px -144px}.icon-hand-up{background-position:-192px -144px}.icon-hand-down{background-position:-216px -144px}.icon-circle-arrow-right{background-position:-240px -144px}.icon-circle-arrow-left{background-position:-264px -144px}.icon-circle-arrow-up{background-position:-288px -144px}.icon-circle-arrow-down{background-position:-312px -144px}.icon-globe{background-position:-336px -144px}.icon-wrench{background-position:-360px -144px}.icon-tasks{background-position:-384px -144px}.icon-filter{background-position:-408px -144px}.icon-briefcase{background-position:-432px -144px}.icon-fulls
 creen{background-position:-456px -144px}.dropup,.dropdown{position:relative}.dropdown-toggle{*margin-bottom:-3px}.dropdown-toggle:active,.open .dropdown-toggle{outline:0}.caret{display:inline-block;width:0;height:0;vertical-align:top;border-top:4px solid #000;border-right:4px solid transparent;border-left:4px solid transparent;content:""}.dropdown .caret{margin-top:8px;margin-left:2px}.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;float:left;min-width:160px;padding:5px 0;margin:2px 0 0;list-style:none;background-color:#fff;border:1px solid #ccc;border:1px solid rgba(0,0,0,0.2);*border-right-width:2px;*border-bottom-width:2px;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;-webkit-box-shadow:0 5px 10px rgba(0,0,0,0.2);-moz-box-shadow:0 5px 10px rgba(0,0,0,0.2);box-shadow:0 5px 10px rgba(0,0,0,0.2);-webkit-background-clip:padding-box;-moz-background-clip:padding;background-clip:padding-box}.dropdown-menu.pull-right{right:0;left:auto}.drop
 down-menu .divider{*width:100%;height:1px;margin:9px 1px;*margin:-5px 0 5px;overflow:hidden;background-color:#e5e5e5;border-bottom:1px solid #fff}.dropdown-menu>li>a{display:block;padding:3px 20px;clear:both;font-weight:normal;line-height:20px;color:#333;white-space:nowrap}.dropdown-menu>li>a:hover,.dropdown-menu>li>a:focus,.dropdown-submenu:hover>a,.dropdown-submenu:focus>a{color:#fff;text-decoration:none;background-color:#0081c2;background-image:-moz-linear-gradient(top,#08c,#0077b3);background-image:-webkit-gradient(linear,0 0,0 100%,from(#08c),to(#0077b3));background-image:-webkit-linear-gradient(top,#08c,#0077b3);background-image:-o-linear-gradient(top,#08c,#0077b3);background-image:linear-gradient(to bottom,#08c,#0077b3);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc',endColorstr='#ff0077b3',GradientType=0)}.dropdown-menu>.active>a,.dropdown-menu>.active>a:hover,.dropdown-menu>.active>a:focus{color:#fff;text-decoration:non
 e;background-color:#0081c2;background-image:-moz-linear-gradient(top,#08c,#0077b3);background-image:-webkit-gradient(linear,0 0,0 100%,from(#08c),to(#0077b3));background-image:-webkit-linear-gradient(top,#08c,#0077b3);background-image:-o-linear-gradient(top,#08c,#0077b3);background-image:linear-gradient(to bottom,#08c,#0077b3);background-repeat:repeat-x;outline:0;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc',endColorstr='#ff0077b3',GradientType=0)}.dropdown-menu>.disabled>a,.dropdown-menu>.disabled>a:hover,.dropdown-menu>.disabled>a:focus{color:#999}.dropdown-menu>.disabled>a:hover,.dropdown-menu>.disabled>a:focus{text-decoration:none;cursor:default;background-color:transparent;background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.open{*z-index:1000}.open>.dropdown-menu{display:block}.pull-right>.dropdown-menu{right:0;left:auto}.dropup .caret,.navbar-fixed-bottom .dropdown .caret{border-top:0;border-bottom:4px solid #00
 0;content:""}.dropup .dropdown-menu,.navbar-fixed-bottom .dropdown .dropdown-menu{top:auto;bottom:100%;margin-bottom:1px}.dropdown-submenu{position:relative}.dropdown-submenu>.dropdown-menu{top:0;left:100%;margin-top:-6px;margin-left:-1px;-webkit-border-radius:0 6px 6px 6px;-moz-border-radius:0 6px 6px 6px;border-radius:0 6px 6px 6px}.dropdown-submenu:hover>.dropdown-menu{display:block}.dropup .dropdown-submenu>.dropdown-menu{top:auto;bottom:0;margin-top:0;margin-bottom:-2px;-webkit-border-radius:5px 5px 5px 0;-moz-border-radius:5px 5px 5px 0;border-radius:5px 5px 5px 0}.dropdown-submenu>a:after{display:block;float:right;width:0;height:0;margin-top:5px;margin-right:-10px;border-color:transparent;border-left-color:#ccc;border-style:solid;border-width:5px 0 5px 5px;content:" "}.dropdown-submenu:hover>a:after{border-left-color:#fff}.dropdown-submenu.pull-left{float:none}.dropdown-submenu.pull-left>.dropdown-menu{left:-100%;margin-left:10px;-webkit-border-radius:6px 0 6px 6px;-moz-borde
 r-radius:6px 0 6px 6px;border-radius:6px 0 6px 6px}.dropdown .dropdown-menu .nav-header{padding-right:20px;padding-left:20px}.typeahead{z-index:1051;margin-top:2px;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.well{min-height:20px;padding:19px;margin-bottom:20px;background-color:#f5f5f5;border:1px solid #e3e3e3;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.05);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.05);box-shadow:inset 0 1px 1px rgba(0,0,0,0.05)}.well blockquote{border-color:#ddd;border-color:rgba(0,0,0,0.15)}.well-large{padding:24px;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px}.well-small{padding:9px;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}.fade{opacity:0;-webkit-transition:opacity .15s linear;-moz-transition:opacity .15s linear;-o-transition:opacity .15s linear;transition:opacity .15s linear}.fade.in{opacity:1}.collapse{position:relative
 ;height:0;overflow:hidden;-webkit-transition:height .35s ease;-moz-transition:height .35s ease;-o-transition:height .35s ease;transition:height .35s ease}.collapse.in{height:auto}.close{float:right;font-size:20px;font-weight:bold;line-height:20px;color:#000;text-shadow:0 1px 0 #fff;opacity:.2;filter:alpha(opacity=20)}.close:hover,.close:focus{color:#000;text-decoration:none;cursor:pointer;opacity:.4;filter:alpha(opacity=40)}button.close{padding:0;cursor:pointer;background:transparent;border:0;-webkit-appearance:none}.btn{display:inline-block;*display:inline;padding:4px 12px;margin-bottom:0;*margin-left:.3em;font-size:14px;line-height:20px;color:#333;text-align:center;text-shadow:0 1px 1px rgba(255,255,255,0.75);vertical-align:middle;cursor:pointer;background-color:#f5f5f5;*background-color:#e6e6e6;background-image:-moz-linear-gradient(top,#fff,#e6e6e6);background-image:-webkit-gradient(linear,0 0,0 100%,from(#fff),to(#e6e6e6));background-image:-webkit-linear-gradient(top,#fff,#e6e6e
 6);background-image:-o-linear-gradient(top,#fff,#e6e6e6);background-image:linear-gradient(to bottom,#fff,#e6e6e6);background-repeat:repeat-x;border:1px solid #ccc;*border:0;border-color:#e6e6e6 #e6e6e6 #bfbfbf;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);border-bottom-color:#b3b3b3;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff',endColorstr='#ffe6e6e6',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);*zoom:1;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05);-moz-box-shadow:inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05);box-shadow:inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05)}.btn:hover,.btn:focus,.btn:active,.btn.active,.btn.disabled,.btn[disabled]{color:#333;background-color:#e6e6e6;*background-color:#d9d9d9}.btn:active,.btn.active{background-color:#ccc \9}.btn:first-child{*ma
 rgin-left:0}.btn:hover,.btn:focus{color:#333;text-decoration:none;background-position:0 -15px;-webkit-transition:background-position .1s linear;-moz-transition:background-position .1s linear;-o-transition:background-position .1s linear;transition:background-position .1s linear}.btn:focus{outline:thin dotted #333;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.btn.active,.btn:active{background-image:none;outline:0;-webkit-box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05);-moz-box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05);box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05)}.btn.disabled,.btn[disabled]{cursor:default;background-image:none;opacity:.65;filter:alpha(opacity=65);-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none}.btn-large{padding:11px 19px;font-size:17.5px;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px}.btn-large [class^="icon-"],.btn-large [class*=" icon-"]{margi
 n-top:4px}.btn-small{padding:2px 10px;font-size:11.9px;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}.btn-small [class^="icon-"],.btn-small [class*=" icon-"]{margin-top:0}.btn-mini [class^="icon-"],.btn-mini [class*=" icon-"]{margin-top:-1px}.btn-mini{padding:0 6px;font-size:10.5px;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}.btn-block{display:block;width:100%;padding-right:0;padding-left:0;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.btn-block+.btn-block{margin-top:5px}input[type="submit"].btn-block,input[type="reset"].btn-block,input[type="button"].btn-block{width:100%}.btn-primary.active,.btn-warning.active,.btn-danger.active,.btn-success.active,.btn-info.active,.btn-inverse.active{color:rgba(255,255,255,0.75)}.btn-primary{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#006dcc;*background-color:#04c;background-image:-moz-linear-gradient(top,#08c,#04c);background-image:-webkit-gradien
 t(linear,0 0,0 100%,from(#08c),to(#04c));background-image:-webkit-linear-gradient(top,#08c,#04c);background-image:-o-linear-gradient(top,#08c,#04c);background-image:linear-gradient(to bottom,#08c,#04c);background-repeat:repeat-x;border-color:#04c #04c #002a80;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc',endColorstr='#ff0044cc',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.btn-primary:hover,.btn-primary:focus,.btn-primary:active,.btn-primary.active,.btn-primary.disabled,.btn-primary[disabled]{color:#fff;background-color:#04c;*background-color:#003bb3}.btn-primary:active,.btn-primary.active{background-color:#039 \9}.btn-warning{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#faa732;*background-color:#f89406;background-image:-moz-linear-gradient(top,#fbb450,#f89406);background-image:-webkit-gradient(linear,0 0,0 100%,from(#fbb450),to(#f8940
 6));background-image:-webkit-linear-gradient(top,#fbb450,#f89406);background-image:-o-linear-gradient(top,#fbb450,#f89406);background-image:linear-gradient(to bottom,#fbb450,#f89406);background-repeat:repeat-x;border-color:#f89406 #f89406 #ad6704;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450',endColorstr='#fff89406',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.btn-warning:hover,.btn-warning:focus,.btn-warning:active,.btn-warning.active,.btn-warning.disabled,.btn-warning[disabled]{color:#fff;background-color:#f89406;*background-color:#df8505}.btn-warning:active,.btn-warning.active{background-color:#c67605 \9}.btn-danger{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#da4f49;*background-color:#bd362f;background-image:-moz-linear-gradient(top,#ee5f5b,#bd362f);background-image:-webkit-gradient(linear,0 0,0 100%,from(#ee5f5b),to(#bd362f));back
 ground-image:-webkit-linear-gradient(top,#ee5f5b,#bd362f);background-image:-o-linear-gradient(top,#ee5f5b,#bd362f);background-image:linear-gradient(to bottom,#ee5f5b,#bd362f);background-repeat:repeat-x;border-color:#bd362f #bd362f #802420;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b',endColorstr='#ffbd362f',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.btn-danger:hover,.btn-danger:focus,.btn-danger:active,.btn-danger.active,.btn-danger.disabled,.btn-danger[disabled]{color:#fff;background-color:#bd362f;*background-color:#a9302a}.btn-danger:active,.btn-danger.active{background-color:#942a25 \9}.btn-success{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#5bb75b;*background-color:#51a351;background-image:-moz-linear-gradient(top,#62c462,#51a351);background-image:-webkit-gradient(linear,0 0,0 100%,from(#62c462),to(#51a351));background-image:-w
 ebkit-linear-gradient(top,#62c462,#51a351);background-image:-o-linear-gradient(top,#62c462,#51a351);background-image:linear-gradient(to bottom,#62c462,#51a351);background-repeat:repeat-x;border-color:#51a351 #51a351 #387038;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462',endColorstr='#ff51a351',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.btn-success:hover,.btn-success:focus,.btn-success:active,.btn-success.active,.btn-success.disabled,.btn-success[disabled]{color:#fff;background-color:#51a351;*background-color:#499249}.btn-success:active,.btn-success.active{background-color:#408140 \9}.btn-info{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#49afcd;*background-color:#2f96b4;background-image:-moz-linear-gradient(top,#5bc0de,#2f96b4);background-image:-webkit-gradient(linear,0 0,0 100%,from(#5bc0de),to(#2f96b4));background-image:-webkit-line
 ar-gradient(top,#5bc0de,#2f96b4);background-image:-o-linear-gradient(top,#5bc0de,#2f96b4);background-image:linear-gradient(to bottom,#5bc0de,#2f96b4);background-repeat:repeat-x;border-color:#2f96b4 #2f96b4 #1f6377;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de',endColorstr='#ff2f96b4',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.btn-info:hover,.btn-info:focus,.btn-info:active,.btn-info.active,.btn-info.disabled,.btn-info[disabled]{color:#fff;background-color:#2f96b4;*background-color:#2a85a0}.btn-info:active,.btn-info.active{background-color:#24748c \9}.btn-inverse{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#363636;*background-color:#222;background-image:-moz-linear-gradient(top,#444,#222);background-image:-webkit-gradient(linear,0 0,0 100%,from(#444),to(#222));background-image:-webkit-linear-gradient(top,#444,#222);background-image:-o
 -linear-gradient(top,#444,#222);background-image:linear-gradient(to bottom,#444,#222);background-repeat:repeat-x;border-color:#222 #222 #000;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff444444',endColorstr='#ff222222',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.btn-inverse:hover,.btn-inverse:focus,.btn-inverse:active,.btn-inverse.active,.btn-inverse.disabled,.btn-inverse[disabled]{color:#fff;background-color:#222;*background-color:#151515}.btn-inverse:active,.btn-inverse.active{background-color:#080808 \9}button.btn,input[type="submit"].btn{*padding-top:3px;*padding-bottom:3px}button.btn::-moz-focus-inner,input[type="submit"].btn::-moz-focus-inner{padding:0;border:0}button.btn.btn-large,input[type="submit"].btn.btn-large{*padding-top:7px;*padding-bottom:7px}button.btn.btn-small,input[type="submit"].btn.btn-small{*padding-top:3px;*padding-bottom:3px}button.btn.bt
 n-mini,input[type="submit"].btn.btn-mini{*padding-top:1px;*padding-bottom:1px}.btn-link,.btn-link:active,.btn-link[disabled]{background-color:transparent;background-image:none;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none}.btn-link{color:#08c;cursor:pointer;border-color:transparent;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.btn-link:hover,.btn-link:focus{color:#005580;text-decoration:underline;background-color:transparent}.btn-link[disabled]:hover,.btn-link[disabled]:focus{color:#333;text-decoration:none}.btn-group{position:relative;display:inline-block;*display:inline;*margin-left:.3em;font-size:0;white-space:nowrap;vertical-align:middle;*zoom:1}.btn-group:first-child{*margin-left:0}.btn-group+.btn-group{margin-left:5px}.btn-toolbar{margin-top:10px;margin-bottom:10px;font-size:0}.btn-toolbar>.btn+.btn,.btn-toolbar>.btn-group+.btn,.btn-toolbar>.btn+.btn-group{margin-left:5px}.btn-group>.btn{position:relative;-webkit-border-radius:0;-moz-border-radiu
 s:0;border-radius:0}.btn-group>.btn+.btn{margin-left:-1px}.btn-group>.btn,.btn-group>.dropdown-menu,.btn-group>.popover{font-size:14px}.btn-group>.btn-mini{font-size:10.5px}.btn-group>.btn-small{font-size:11.9px}.btn-group>.btn-large{font-size:17.5px}.btn-group>.btn:first-child{margin-left:0;-webkit-border-bottom-left-radius:4px;border-bottom-left-radius:4px;-webkit-border-top-left-radius:4px;border-top-left-radius:4px;-moz-border-radius-bottomleft:4px;-moz-border-radius-topleft:4px}.btn-group>.btn:last-child,.btn-group>.dropdown-toggle{-webkit-border-top-right-radius:4px;border-top-right-radius:4px;-webkit-border-bottom-right-radius:4px;border-bottom-right-radius:4px;-moz-border-radius-topright:4px;-moz-border-radius-bottomright:4px}.btn-group>.btn.large:first-child{margin-left:0;-webkit-border-bottom-left-radius:6px;border-bottom-left-radius:6px;-webkit-border-top-left-radius:6px;border-top-left-radius:6px;-moz-border-radius-bottomleft:6px;-moz-border-radius-topleft:6px}.btn-group
 >.btn.large:last-child,.btn-group>.large.dropdown-toggle{-webkit-border-top-right-radius:6px;border-top-right-radius:6px;-webkit-border-bottom-right-radius:6px;border-bottom-right-radius:6px;-moz-border-radius-topright:6px;-moz-border-radius-bottomright:6px}.btn-group>.btn:hover,.btn-group>.btn:focus,.btn-group>.btn:active,.btn-group>.btn.active{z-index:2}.btn-group .dropdown-toggle:active,.btn-group.open .dropdown-toggle{outline:0}.btn-group>.btn+.dropdown-toggle{*padding-top:5px;padding-right:8px;*padding-bottom:5px;padding-left:8px;-webkit-box-shadow:inset 1px 0 0 rgba(255,255,255,0.125),inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05);-moz-box-shadow:inset 1px 0 0 rgba(255,255,255,0.125),inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05);box-shadow:inset 1px 0 0 rgba(255,255,255,0.125),inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05)}.btn-group>.btn-mini+.dropdown-toggle{*padding-top:2px;padding-right:5px;*padding-bottom:2px;padding-left:5
 px}.btn-group>.btn-small+.dropdown-toggle{*padding-top:5px;*padding-bottom:4px}.btn-group>.btn-large+.dropdown-toggle{*padding-top:7px;padding-right:12px;*padding-bottom:7px;padding-left:12px}.btn-group.open .dropdown-toggle{background-image:none;-webkit-box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05);-moz-box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05);box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05)}.btn-group.open .btn.dropdown-toggle{background-color:#e6e6e6}.btn-group.open .btn-primary.dropdown-toggle{background-color:#04c}.btn-group.open .btn-warning.dropdown-toggle{background-color:#f89406}.btn-group.open .btn-danger.dropdown-toggle{background-color:#bd362f}.btn-group.open .btn-success.dropdown-toggle{background-color:#51a351}.btn-group.open .btn-info.dropdown-toggle{background-color:#2f96b4}.btn-group.open .btn-inverse.dropdown-toggle{background-color:#222}.btn .caret{margin-top:8px;margin-left:0}.btn-large 
 .caret{margin-top:6px}.btn-large .caret{border-top-width:5px;border-right-width:5px;border-left-width:5px}.btn-mini .caret,.btn-small .caret{margin-top:8px}.dropup .btn-large .caret{border-bottom-width:5px}.btn-primary .caret,.btn-warning .caret,.btn-danger .caret,.btn-info .caret,.btn-success .caret,.btn-inverse .caret{border-top-color:#fff;border-bottom-color:#fff}.btn-group-vertical{display:inline-block;*display:inline;*zoom:1}.btn-group-vertical>.btn{display:block;float:none;max-width:100%;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.btn-group-vertical>.btn+.btn{margin-top:-1px;margin-left:0}.btn-group-vertical>.btn:first-child{-webkit-border-radius:4px 4px 0 0;-moz-border-radius:4px 4px 0 0;border-radius:4px 4px 0 0}.btn-group-vertical>.btn:last-child{-webkit-border-radius:0 0 4px 4px;-moz-border-radius:0 0 4px 4px;border-radius:0 0 4px 4px}.btn-group-vertical>.btn-large:first-child{-webkit-border-radius:6px 6px 0 0;-moz-border-radius:6px 6px 0 0;border-radius:
 6px 6px 0 0}.btn-group-vertical>.btn-large:last-child{-webkit-border-radius:0 0 6px 6px;-moz-border-radius:0 0 6px 6px;border-radius:0 0 6px 6px}.alert{padding:8px 35px 8px 14px;margin-bottom:20px;text-shadow:0 1px 0 rgba(255,255,255,0.5);background-color:#fcf8e3;border:1px solid #fbeed5;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.alert,.alert h4{color:#c09853}.alert h4{margin:0}.alert .close{position:relative;top:-2px;right:-21px;line-height:20px}.alert-success{color:#468847;background-color:#dff0d8;border-color:#d6e9c6}.alert-success h4{color:#468847}.alert-danger,.alert-error{color:#b94a48;background-color:#f2dede;border-color:#eed3d7}.alert-danger h4,.alert-error h4{color:#b94a48}.alert-info{color:#3a87ad;background-color:#d9edf7;border-color:#bce8f1}.alert-info h4{color:#3a87ad}.alert-block{padding-top:14px;padding-bottom:14px}.alert-block>p,.alert-block>ul{margin-bottom:0}.alert-block p+p{margin-top:5px}.nav{margin-bottom:20px;margin-left:0;list-style:n
 one}.nav>li>a{display:block}.nav>li>a:hover,.nav>li>a:focus{text-decoration:none;background-color:#eee}.nav>li>a>img{max-width:none}.nav>.pull-right{float:right}.nav-header{display:block;padding:3px 15px;font-size:11px;font-weight:bold;line-height:20px;color:#999;text-shadow:0 1px 0 rgba(255,255,255,0.5);text-transform:uppercase}.nav li+.nav-header{margin-top:9px}.nav-list{padding-right:15px;padding-left:15px;margin-bottom:0}.nav-list>li>a,.nav-list .nav-header{margin-right:-15px;margin-left:-15px;text-shadow:0 1px 0 rgba(255,255,255,0.5)}.nav-list>li>a{padding:3px 15px}.nav-list>.active>a,.nav-list>.active>a:hover,.nav-list>.active>a:focus{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.2);background-color:#08c}.nav-list [class^="icon-"],.nav-list [class*=" icon-"]{margin-right:2px}.nav-list .divider{*width:100%;height:1px;margin:9px 1px;*margin:-5px 0 5px;overflow:hidden;background-color:#e5e5e5;border-bottom:1px solid #fff}.nav-tabs,.nav-pills{*zoom:1}.nav-tabs:before,.nav-pills:bef
 ore,.nav-tabs:after,.nav-pills:after{display:table;line-height:0;content:""}.nav-tabs:after,.nav-pills:after{clear:both}.nav-tabs>li,.nav-pills>li{float:left}.nav-tabs>li>a,.nav-pills>li>a{padding-right:12px;padding-left:12px;margin-right:2px;line-height:14px}.nav-tabs{border-bottom:1px solid #ddd}.nav-tabs>li{margin-bottom:-1px}.nav-tabs>li>a{padding-top:8px;padding-bottom:8px;line-height:20px;border:1px solid transparent;-webkit-border-radius:4px 4px 0 0;-moz-border-radius:4px 4px 0 0;border-radius:4px 4px 0 0}.nav-tabs>li>a:hover,.nav-tabs>li>a:focus{border-color:#eee #eee #ddd}.nav-tabs>.active>a,.nav-tabs>.active>a:hover,.nav-tabs>.active>a:focus{color:#555;cursor:default;background-color:#fff;border:1px solid #ddd;border-bottom-color:transparent}.nav-pills>li>a{padding-top:8px;padding-bottom:8px;margin-top:2px;margin-bottom:2px;-webkit-border-radius:5px;-moz-border-radius:5px;border-radius:5px}.nav-pills>.active>a,.nav-pills>.active>a:hover,.nav-pills>.active>a:focus{color:#ff
 f;background-color:#08c}.nav-stacked>li{float:none}.nav-stacked>li>a{margin-right:0}.nav-tabs.nav-stacked{border-bottom:0}.nav-tabs.nav-stacked>li>a{border:1px solid #ddd;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.nav-tabs.nav-stacked>li:first-child>a{-webkit-border-top-right-radius:4px;border-top-right-radius:4px;-webkit-border-top-left-radius:4px;border-top-left-radius:4px;-moz-border-radius-topright:4px;-moz-border-radius-topleft:4px}.nav-tabs.nav-stacked>li:last-child>a{-webkit-border-bottom-right-radius:4px;border-bottom-right-radius:4px;-webkit-border-bottom-left-radius:4px;border-bottom-left-radius:4px;-moz-border-radius-bottomright:4px;-moz-border-radius-bottomleft:4px}.nav-tabs.nav-stacked>li>a:hover,.nav-tabs.nav-stacked>li>a:focus{z-index:2;border-color:#ddd}.nav-pills.nav-stacked>li>a{margin-bottom:3px}.nav-pills.nav-stacked>li:last-child>a{margin-bottom:1px}.nav-tabs .dropdown-menu{-webkit-border-radius:0 0 6px 6px;-moz-border-radius:0 0 6px 6px;borde
 r-radius:0 0 6px 6px}.nav-pills .dropdown-menu{-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px}.nav .dropdown-toggle .caret{margin-top:6px;border-top-color:#08c;border-bottom-color:#08c}.nav .dropdown-toggle:hover .caret,.nav .dropdown-toggle:focus .caret{border-top-color:#005580;border-bottom-color:#005580}.nav-tabs .dropdown-toggle .caret{margin-top:8px}.nav .active .dropdown-toggle .caret{border-top-color:#fff;border-bottom-color:#fff}.nav-tabs .active .dropdown-toggle .caret{border-top-color:#555;border-bottom-color:#555}.nav>.dropdown.active>a:hover,.nav>.dropdown.active>a:focus{cursor:pointer}.nav-tabs .open .dropdown-toggle,.nav-pills .open .dropdown-toggle,.nav>li.dropdown.open.active>a:hover,.nav>li.dropdown.open.active>a:focus{color:#fff;background-color:#999;border-color:#999}.nav li.dropdown.open .caret,.nav li.dropdown.open.active .caret,.nav li.dropdown.open a:hover .caret,.nav li.dropdown.open a:focus .caret{border-top-color:#fff;border-bottom-color
 :#fff;opacity:1;filter:alpha(opacity=100)}.tabs-stacked .open>a:hover,.tabs-stacked .open>a:focus{border-color:#999}.tabbable{*zoom:1}.tabbable:before,.tabbable:after{display:table;line-height:0;content:""}.tabbable:after{clear:both}.tab-content{overflow:auto}.tabs-below>.nav-tabs,.tabs-right>.nav-tabs,.tabs-left>.nav-tabs{border-bottom:0}.tab-content>.tab-pane,.pill-content>.pill-pane{display:none}.tab-content>.active,.pill-content>.active{display:block}.tabs-below>.nav-tabs{border-top:1px solid #ddd}.tabs-below>.nav-tabs>li{margin-top:-1px;margin-bottom:0}.tabs-below>.nav-tabs>li>a{-webkit-border-radius:0 0 4px 4px;-moz-border-radius:0 0 4px 4px;border-radius:0 0 4px 4px}.tabs-below>.nav-tabs>li>a:hover,.tabs-below>.nav-tabs>li>a:focus{border-top-color:#ddd;border-bottom-color:transparent}.tabs-below>.nav-tabs>.active>a,.tabs-below>.nav-tabs>.active>a:hover,.tabs-below>.nav-tabs>.active>a:focus{border-color:transparent #ddd #ddd #ddd}.tabs-left>.nav-tabs>li,.tabs-right>.nav-tabs>l
 i{float:none}.tabs-left>.nav-tabs>li>a,.tabs-right>.nav-tabs>li>a{min-width:74px;margin-right:0;margin-bottom:3px}.tabs-left>.nav-tabs{float:left;margin-right:19px;border-right:1px solid #ddd}.tabs-left>.nav-tabs>li>a{margin-right:-1px;-webkit-border-radius:4px 0 0 4px;-moz-border-radius:4px 0 0 4px;border-radius:4px 0 0 4px}.tabs-left>.nav-tabs>li>a:hover,.tabs-left>.nav-tabs>li>a:focus{border-color:#eee #ddd #eee #eee}.tabs-left>.nav-tabs .active>a,.tabs-left>.nav-tabs .active>a:hover,.tabs-left>.nav-tabs .active>a:focus{border-color:#ddd transparent #ddd #ddd;*border-right-color:#fff}.tabs-right>.nav-tabs{float:right;margin-left:19px;border-left:1px solid #ddd}.tabs-right>.nav-tabs>li>a{margin-left:-1px;-webkit-border-radius:0 4px 4px 0;-moz-border-radius:0 4px 4px 0;border-radius:0 4px 4px 0}.tabs-right>.nav-tabs>li>a:hover,.tabs-right>.nav-tabs>li>a:focus{border-color:#eee #eee #eee #ddd}.tabs-right>.nav-tabs .active>a,.tabs-right>.nav-tabs .active>a:hover,.tabs-right>.nav-tabs
  .active>a:focus{border-color:#ddd #ddd #ddd transparent;*border-left-color:#fff}.nav>.disabled>a{color:#999}.nav>.disabled>a:hover,.nav>.disabled>a:focus{text-decoration:none;cursor:default;background-color:transparent}.navbar{*position:relative;*z-index:2;margin-bottom:20px;overflow:visible}.navbar-inner{min-height:40px;padding-right:20px;padding-left:20px;background-color:#fafafa;background-image:-moz-linear-gradient(top,#fff,#f2f2f2);background-image:-webkit-gradient(linear,0 0,0 100%,from(#fff),to(#f2f2f2));background-image:-webkit-linear-gradient(top,#fff,#f2f2f2);background-image:-o-linear-gradient(top,#fff,#f2f2f2);background-image:linear-gradient(to bottom,#fff,#f2f2f2);background-repeat:repeat-x;border:1px solid #d4d4d4;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff',endColorstr='#fff2f2f2',GradientType=0);*zoom:1;-webkit-box-shadow:0 1px 4px rgba(0,0,0,0.065);-moz-box-shadow:0 1
 px 4px rgba(0,0,0,0.065);box-shadow:0 1px 4px rgba(0,0,0,0.065)}.navbar-inner:before,.navbar-inner:after{display:table;line-height:0;content:""}.navbar-inner:after{clear:both}.navbar .container{width:auto}.nav-collapse.collapse{height:auto;overflow:visible}.navbar .brand{display:block;float:left;padding:10px 20px 10px;margin-left:-20px;font-size:20px;font-weight:200;color:#777;text-shadow:0 1px 0 #fff}.navbar .brand:hover,.navbar .brand:focus{text-decoration:none}.navbar-text{margin-bottom:0;line-height:40px;color:#777}.navbar-link{color:#777}.navbar-link:hover,.navbar-link:focus{color:#333}.navbar .divider-vertical{height:40px;margin:0 9px;border-right:1px solid #fff;border-left:1px solid #f2f2f2}.navbar .btn,.navbar .btn-group{margin-top:5px}.navbar .btn-group .btn,.navbar .input-prepend .btn,.navbar .input-append .btn,.navbar .input-prepend .btn-group,.navbar .input-append .btn-group{margin-top:0}.navbar-form{margin-bottom:0;*zoom:1}.navbar-form:before,.navbar-form:after{display:
 table;line-height:0;content:""}.navbar-form:after{clear:both}.navbar-form input,.navbar-form select,.navbar-form .radio,.navbar-form .checkbox{margin-top:5px}.navbar-form input,.navbar-form select,.navbar-form .btn{display:inline-block;margin-bottom:0}.navbar-form input[type="image"],.navbar-form input[type="checkbox"],.navbar-form input[type="radio"]{margin-top:3px}.navbar-form .input-append,.navbar-form .input-prepend{margin-top:5px;white-space:nowrap}.navbar-form .input-append input,.navbar-form .input-prepend input{margin-top:0}.navbar-search{position:relative;float:left;margin-top:5px;margin-bottom:0}.navbar-search .search-query{padding:4px 14px;margin-bottom:0;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:13px;font-weight:normal;line-height:1;-webkit-border-radius:15px;-moz-border-radius:15px;border-radius:15px}.navbar-static-top{position:static;margin-bottom:0}.navbar-static-top .navbar-inner{-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.na
 vbar-fixed-top,.navbar-fixed-bottom{position:fixed;right:0;left:0;z-index:1030;margin-bottom:0}.navbar-fixed-top .navbar-inner,.navbar-static-top .navbar-inner{border-width:0 0 1px}.navbar-fixed-bottom .navbar-inner{border-width:1px 0 0}.navbar-fixed-top .navbar-inner,.navbar-fixed-bottom .navbar-inner{padding-right:0;padding-left:0;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.navbar-static-top .container,.navbar-fixed-top .container,.navbar-fixed-bottom .container{width:940px}.navbar-fixed-top{top:0}.navbar-fixed-top .navbar-inner,.navbar-static-top .navbar-inner{-webkit-box-shadow:0 1px 10px rgba(0,0,0,0.1);-moz-box-shadow:0 1px 10px rgba(0,0,0,0.1);box-shadow:0 1px 10px rgba(0,0,0,0.1)}.navbar-fixed-bottom{bottom:0}.navbar-fixed-bottom .navbar-inner{-webkit-box-shadow:0 -1px 10px rgba(0,0,0,0.1);-moz-box-shadow:0 -1px 10px rgba(0,0,0,0.1);box-shadow:0 -1px 10px rgba(0,0,0,0.1)}.navbar .nav{position:relative;left:0;display:block;float:left;margin:0 10px 0 0}.navba
 r .nav.pull-right{float:right;margin-right:0}.navbar .nav>li{float:left}.navbar .nav>li>a{float:none;padding:10px 15px 10px;color:#777;text-decoration:none;text-shadow:0 1px 0 #fff}.navbar .nav .dropdown-toggle .caret{margin-top:8px}.navbar .nav>li>a:focus,.navbar .nav>li>a:hover{color:#333;text-decoration:none;background-color:transparent}.navbar .nav>.active>a,.navbar .nav>.active>a:hover,.navbar .nav>.active>a:focus{color:#555;text-decoration:none;background-color:#e5e5e5;-webkit-box-shadow:inset 0 3px 8px rgba(0,0,0,0.125);-moz-box-shadow:inset 0 3px 8px rgba(0,0,0,0.125);box-shadow:inset 0 3px 8px rgba(0,0,0,0.125)}.navbar .btn-navbar{display:none;float:right;padding:7px 10px;margin-right:5px;margin-left:5px;color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#ededed;*background-color:#e5e5e5;background-image:-moz-linear-gradient(top,#f2f2f2,#e5e5e5);background-image:-webkit-gradient(linear,0 0,0 100%,from(#f2f2f2),to(#e5e5e5));background-image:-webkit-linear-grad
 ient(top,#f2f2f2,#e5e5e5);background-image:-o-linear-gradient(top,#f2f2f2,#e5e5e5);background-image:linear-gradient(to bottom,#f2f2f2,#e5e5e5);background-repeat:repeat-x;border-color:#e5e5e5 #e5e5e5 #bfbfbf;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2f2f2',endColorstr='#ffe5e5e5',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.075);-moz-box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.075);box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.075)}.navbar .btn-navbar:hover,.navbar .btn-navbar:focus,.navbar .btn-navbar:active,.navbar .btn-navbar.active,.navbar .btn-navbar.disabled,.navbar .btn-navbar[disabled]{color:#fff;background-color:#e5e5e5;*background-color:#d9d9d9}.navbar .btn-navbar:active,.navbar .btn-navbar.active{background-color
 :#ccc \9}.navbar .btn-navbar .icon-bar{display:block;width:18px;height:2px;background-color:#f5f5f5;-webkit-border-radius:1px;-moz-border-radius:1px;border-radius:1px;-webkit-box-shadow:0 1px 0 rgba(0,0,0,0.25);-moz-box-shadow:0 1px 0 rgba(0,0,0,0.25);box-shadow:0 1px 0 rgba(0,0,0,0.25)}.btn-navbar .icon-bar+.icon-bar{margin-top:3px}.navbar .nav>li>.dropdown-menu:before{position:absolute;top:-7px;left:9px;display:inline-block;border-right:7px solid transparent;border-bottom:7px solid #ccc;border-left:7px solid transparent;border-bottom-color:rgba(0,0,0,0.2);content:''}.navbar .nav>li>.dropdown-menu:after{position:absolute;top:-6px;left:10px;display:inline-block;border-right:6px solid transparent;border-bottom:6px solid #fff;border-left:6px solid transparent;content:''}.navbar-fixed-bottom .nav>li>.dropdown-menu:before{top:auto;bottom:-7px;border-top:7px solid #ccc;border-bottom:0;border-top-color:rgba(0,0,0,0.2)}.navbar-fixed-bottom .nav>li>.dropdown-menu:after{top:auto;bottom:-6px;
 border-top:6px solid #fff;border-bottom:0}.navbar .nav li.dropdown>a:hover .caret,.navbar .nav li.dropdown>a:focus .caret{border-top-color:#333;border-bottom-color:#333}.navbar .nav li.dropdown.open>.dropdown-toggle,.navbar .nav li.dropdown.active>.dropdown-toggle,.navbar .nav li.dropdown.open.active>.dropdown-toggle{color:#555;background-color:#e5e5e5}.navbar .nav li.dropdown>.dropdown-toggle .caret{border-top-color:#777;border-bottom-color:#777}.navbar .nav li.dropdown.open>.dropdown-toggle .caret,.navbar .nav li.dropdown.active>.dropdown-toggle .caret,.navbar .nav li.dropdown.open.active>.dropdown-toggle .caret{border-top-color:#555;border-bottom-color:#555}.navbar .pull-right>li>.dropdown-menu,.navbar .nav>li>.dropdown-menu.pull-right{right:0;left:auto}.navbar .pull-right>li>.dropdown-menu:before,.navbar .nav>li>.dropdown-menu.pull-right:before{right:12px;left:auto}.navbar .pull-right>li>.dropdown-menu:after,.navbar .nav>li>.dropdown-menu.pull-right:after{right:13px;left:auto}.n
 avbar .pull-right>li>.dropdown-menu .dropdown-menu,.navbar .nav>li>.dropdown-menu.pull-right .dropdown-menu{right:100%;left:auto;margin-right:-1px;margin-left:0;-webkit-border-radius:6px 0 6px 6px;-moz-border-radius:6px 0 6px 6px;border-radius:6px 0 6px 6px}.navbar-inverse .navbar-inner{background-color:#1b1b1b;background-image:-moz-linear-gradient(top,#222,#111);background-image:-webkit-gradient(linear,0 0,0 100%,from(#222),to(#111));background-image:-webkit-linear-gradient(top,#222,#111);background-image:-o-linear-gradient(top,#222,#111);background-image:linear-gradient(to bottom,#222,#111);background-repeat:repeat-x;border-color:#252525;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff222222',endColorstr='#ff111111',GradientType=0)}.navbar-inverse .brand,.navbar-inverse .nav>li>a{color:#999;text-shadow:0 -1px 0 rgba(0,0,0,0.25)}.navbar-inverse .brand:hover,.navbar-inverse .nav>li>a:hover,.navbar-inverse .brand:focus,.navbar-inverse .nav>li>a:focus{color:#fff}.n
 avbar-inverse .brand{color:#999}.navbar-inverse .navbar-text{color:#999}.navbar-inverse .nav>li>a:focus,.navbar-inverse .nav>li>a:hover{color:#fff;background-color:transparent}.navbar-inverse .nav .active>a,.navbar-inverse .nav .active>a:hover,.navbar-inverse .nav .active>a:focus{color:#fff;background-color:#111}.navbar-inverse .navbar-link{color:#999}.navbar-inverse .navbar-link:hover,.navbar-inverse .navbar-link:focus{color:#fff}.navbar-inverse .divider-vertical{border-right-color:#222;border-left-color:#111}.navbar-inverse .nav li.dropdown.open>.dropdown-toggle,.navbar-inverse .nav li.dropdown.active>.dropdown-toggle,.navbar-inverse .nav li.dropdown.open.active>.dropdown-toggle{color:#fff;background-color:#111}.navbar-inverse .nav li.dropdown>a:hover .caret,.navbar-inverse .nav li.dropdown>a:focus .caret{border-top-color:#fff;border-bottom-color:#fff}.navbar-inverse .nav li.dropdown>.dropdown-toggle .caret{border-top-color:#999;border-bottom-color:#999}.navbar-inverse .nav li.dro
 pdown.open>.dropdown-toggle .caret,.navbar-inverse .nav li.dropdown.active>.dropdown-toggle .caret,.navbar-inverse .nav li.dropdown.open.active>.dropdown-toggle .caret{border-top-color:#fff;border-bottom-color:#fff}.navbar-inverse .navbar-search .search-query{color:#fff;background-color:#515151;border-color:#111;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,0.1),0 1px 0 rgba(255,255,255,0.15);-moz-box-shadow:inset 0 1px 2px rgba(0,0,0,0.1),0 1px 0 rgba(255,255,255,0.15);box-shadow:inset 0 1px 2px rgba(0,0,0,0.1),0 1px 0 rgba(255,255,255,0.15);-webkit-transition:none;-moz-transition:none;-o-transition:none;transition:none}.navbar-inverse .navbar-search .search-query:-moz-placeholder{color:#ccc}.navbar-inverse .navbar-search .search-query:-ms-input-placeholder{color:#ccc}.navbar-inverse .navbar-search .search-query::-webkit-input-placeholder{color:#ccc}.navbar-inverse .navbar-search .search-query:focus,.navbar-inverse .navbar-search .search-query.focused{padding:5px 15px;color:#333;te
 xt-shadow:0 1px 0 #fff;background-color:#fff;border:0;outline:0;-webkit-box-shadow:0 0 3px rgba(0,0,0,0.15);-moz-box-shadow:0 0 3px rgba(0,0,0,0.15);box-shadow:0 0 3px rgba(0,0,0,0.15)}.navbar-inverse .btn-navbar{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#0e0e0e;*background-color:#040404;background-image:-moz-linear-gradient(top,#151515,#040404);background-image:-webkit-gradient(linear,0 0,0 100%,from(#151515),to(#040404));background-image:-webkit-linear-gradient(top,#151515,#040404);background-image:-o-linear-gradient(top,#151515,#040404);background-image:linear-gradient(to bottom,#151515,#040404);background-repeat:repeat-x;border-color:#040404 #040404 #000;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff151515',endColorstr='#ff040404',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.navbar-inverse .btn-navbar:hover,.navbar-inverse .btn-navbar:f
 ocus,.navbar-inverse .btn-navbar:active,.navbar-inverse .btn-navbar.active,.navbar-inverse .btn-navbar.disabled,.navbar-inverse .btn-navbar[disabled]{color:#fff;background-color:#040404;*background-color:#000}.navbar-inverse .btn-navbar:active,.navbar-inverse .btn-navbar.active{background-color:#000 \9}.breadcrumb{padding:8px 15px;margin:0 0 20px;list-style:none;background-color:#f5f5f5;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.breadcrumb>li{display:inline-block;*display:inline;text-shadow:0 1px 0 #fff;*zoom:1}.breadcrumb>li>.divider{padding:0 5px;color:#ccc}.breadcrumb>.active{color:#999}.pagination{margin:20px 0}.pagination ul{display:inline-block;*display:inline;margin-bottom:0;margin-left:0;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;*zoom:1;-webkit-box-shadow:0 1px 2px rgba(0,0,0,0.05);-moz-box-shadow:0 1px 2px rgba(0,0,0,0.05);box-shadow:0 1px 2px rgba(0,0,0,0.05)}.pagination ul>li{display:inline}.pagination ul>li>a,.pagination 
 ul>li>span{float:left;padding:4px 12px;line-height:20px;text-decoration:none;background-color:#fff;border:1px solid #ddd;border-left-width:0}.pagination ul>li>a:hover,.pagination ul>li>a:focus,.pagination ul>.active>a,.pagination ul>.active>span{background-color:#f5f5f5}.pagination ul>.active>a,.pagination ul>.active>span{color:#999;cursor:default}.pagination ul>.disabled>span,.pagination ul>.disabled>a,.pagination ul>.disabled>a:hover,.pagination ul>.disabled>a:focus{color:#999;cursor:default;background-color:transparent}.pagination ul>li:first-child>a,.pagination ul>li:first-child>span{border-left-width:1px;-webkit-border-bottom-left-radius:4px;border-bottom-left-radius:4px;-webkit-border-top-left-radius:4px;border-top-left-radius:4px;-moz-border-radius-bottomleft:4px;-moz-border-radius-topleft:4px}.pagination ul>li:last-child>a,.pagination ul>li:last-child>span{-webkit-border-top-right-radius:4px;border-top-right-radius:4px;-webkit-border-bottom-right-radius:4px;border-bottom-rig
 ht-radius:4px;-moz-border-radius-topright:4px;-moz-border-radius-bottomright:4px}.pagination-centered{text-align:center}.pagination-right{text-align:right}.pagination-large ul>li>a,.pagination-large ul>li>span{padding:11px 19px;font-size:17.5px}.pagination-large ul>li:first-child>a,.pagination-large ul>li:first-child>span{-webkit-border-bottom-left-radius:6px;border-bottom-left-radius:6px;-webkit-border-top-left-radius:6px;border-top-left-radius:6px;-moz-border-radius-bottomleft:6px;-moz-border-radius-topleft:6px}.pagination-large ul>li:last-child>a,.pagination-large ul>li:last-child>span{-webkit-border-top-right-radius:6px;border-top-right-radius:6px;-webkit-border-bottom-right-radius:6px;border-bottom-right-radius:6px;-moz-border-radius-topright:6px;-moz-border-radius-bottomright:6px}.pagination-mini ul>li:first-child>a,.pagination-small ul>li:first-child>a,.pagination-mini ul>li:first-child>span,.pagination-small ul>li:first-child>span{-webkit-border-bottom-left-radius:3px;border
 -bottom-left-radius:3px;-webkit-border-top-left-radius:3px;border-top-left-radius:3px;-moz-border-radius-bottomleft:3px;-moz-border-radius-topleft:3px}.pagination-mini ul>li:last-child>a,.pagination-small ul>li:last-child>a,.pagination-mini ul>li:last-child>span,.pagination-small ul>li:last-child>span{-webkit-border-top-right-radius:3px;border-top-right-radius:3px;-webkit-border-bottom-right-radius:3px;border-bottom-right-radius:3px;-moz-border-radius-topright:3px;-moz-border-radius-bottomright:3px}.pagination-small ul>li>a,.pagination-small ul>li>span{padding:2px 10px;font-size:11.9px}.pagination-mini ul>li>a,.pagination-mini ul>li>span{padding:0 6px;font-size:10.5px}.pager{margin:20px 0;text-align:center;list-style:none;*zoom:1}.pager:before,.pager:after{display:table;line-height:0;content:""}.pager:after{clear:both}.pager li{display:inline}.pager li>a,.pager li>span{display:inline-block;padding:5px 14px;background-color:#fff;border:1px solid #ddd;-webkit-border-radius:15px;-moz-b
 order-radius:15px;border-radius:15px}.pager li>a:hover,.pager li>a:focus{text-decoration:none;background-color:#f5f5f5}.pager .next>a,.pager .next>span{float:right}.pager .previous>a,.pager .previous>span{float:left}.pager .disabled>a,.pager .disabled>a:hover,.pager .disabled>a:focus,.pager .disabled>span{color:#999;cursor:default;background-color:#fff}.modal-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040;background-color:#000}.modal-backdrop.fade{opacity:0}.modal-backdrop,.modal-backdrop.fade.in{opacity:.8;filter:alpha(opacity=80)}.modal{position:fixed;top:10%;left:50%;z-index:1050;width:560px;margin-left:-280px;background-color:#fff;border:1px solid #999;border:1px solid rgba(0,0,0,0.3);*border:1px solid #999;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;outline:0;-webkit-box-shadow:0 3px 7px rgba(0,0,0,0.3);-moz-box-shadow:0 3px 7px rgba(0,0,0,0.3);box-shadow:0 3px 7px rgba(0,0,0,0.3);-webkit-background-clip:padding-box;-moz-background-cli
 p:padding-box;background-clip:padding-box}.modal.fade{top:-25%;-webkit-transition:opacity .3s linear,top .3s ease-out;-moz-transition:opacity .3s linear,top .3s ease-out;-o-transition:opacity .3s linear,top .3s ease-out;transition:opacity .3s linear,top .3s ease-out}.modal.fade.in{top:10%}.modal-header{padding:9px 15px;border-bottom:1px solid #eee}.modal-header .close{margin-top:2px}.modal-header h3{margin:0;line-height:30px}.modal-body{position:relative;max-height:400px;padding:15px;overflow-y:auto}.modal-form{margin-bottom:0}.modal-footer{padding:14px 15px 15px;margin-bottom:0;text-align:right;background-color:#f5f5f5;border-top:1px solid #ddd;-webkit-border-radius:0 0 6px 6px;-moz-border-radius:0 0 6px 6px;border-radius:0 0 6px 6px;*zoom:1;-webkit-box-shadow:inset 0 1px 0 #fff;-moz-box-shadow:inset 0 1px 0 #fff;box-shadow:inset 0 1px 0 #fff}.modal-footer:before,.modal-footer:after{display:table;line-height:0;content:""}.modal-footer:after{clear:both}.modal-footer .btn+.btn{margin
 -bottom:0;margin-left:5px}.modal-footer .btn-group .btn+.btn{margin-left:-1px}.modal-footer .btn-block+.btn-block{margin-left:0}.tooltip{position:absolute;z-index:1030;display:block;font-size:11px;line-height:1.4;opacity:0;filter:alpha(opacity=0);visibility:visible}.tooltip.in{opacity:.8;filter:alpha(opacity=80)}.tooltip.top{padding:5px 0;margin-top:-3px}.tooltip.right{padding:0 5px;margin-left:3px}.tooltip.bottom{padding:5px 0;margin-top:3px}.tooltip.left{padding:0 5px;margin-left:-3px}.tooltip-inner{max-width:200px;padding:8px;color:#fff;text-align:center;text-decoration:none;background-color:#000;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.tooltip-arrow{position:absolute;width:0;height:0;border-color:transparent;border-style:solid}.tooltip.top .tooltip-arrow{bottom:0;left:50%;margin-left:-5px;border-top-color:#000;border-width:5px 5px 0}.tooltip.right .tooltip-arrow{top:50%;left:0;margin-top:-5px;border-right-color:#000;border-width:5px 5px 5px 0}.tooltip.
 left .tooltip-arrow{top:50%;right:0;margin-top:-5px;border-left-color:#000;border-width:5px 0 5px 5px}.tooltip.bottom .tooltip-arrow{top:0;left:50%;margin-left:-5px;border-bottom-color:#000;border-width:0 5px 5px}.popover{position:absolute;top:0;left:0;z-index:1010;display:none;max-width:276px;padding:1px;text-align:left;white-space:normal;background-color:#fff;border:1px solid #ccc;border:1px solid rgba(0,0,0,0.2);-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;-webkit-box-shadow:0 5px 10px rgba(0,0,0,0.2);-moz-box-shadow:0 5px 10px rgba(0,0,0,0.2);box-shadow:0 5px 10px rgba(0,0,0,0.2);-webkit-background-clip:padding-box;-moz-background-clip:padding;background-clip:padding-box}.popover.top{margin-top:-10px}.popover.right{margin-left:10px}.popover.bottom{margin-top:10px}.popover.left{margin-left:-10px}.popover-title{padding:8px 14px;margin:0;font-size:14px;font-weight:normal;line-height:18px;background-color:#f7f7f7;border-bottom:1px solid #ebebeb;-webkit-border-r
 adius:5px 5px 0 0;-moz-border-radius:5px 5px 0 0;border-radius:5px 5px 0 0}.popover-title:empty{display:none}.popover-content{padding:9px 

<TRUNCATED>

[15/51] [abbrv] [partial] Adding Jinwon's custom RCMET

Posted by jo...@apache.org.
http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/app/lib/angular/angular.min.js
----------------------------------------------------------------------
diff --git a/src/main/ui/app/lib/angular/angular.min.js b/src/main/ui/app/lib/angular/angular.min.js
new file mode 100755
index 0000000..07ea01c
--- /dev/null
+++ b/src/main/ui/app/lib/angular/angular.min.js
@@ -0,0 +1,161 @@
+/*
+ AngularJS v1.0.5
+ (c) 2010-2012 Google, Inc. http://angularjs.org
+ License: MIT
+*/
+(function(X,Y,q){'use strict';function n(b,a,c){var d;if(b)if(H(b))for(d in b)d!="prototype"&&d!="length"&&d!="name"&&b.hasOwnProperty(d)&&a.call(c,b[d],d);else if(b.forEach&&b.forEach!==n)b.forEach(a,c);else if(!b||typeof b.length!=="number"?0:typeof b.hasOwnProperty!="function"&&typeof b.constructor!="function"||b instanceof L||ca&&b instanceof ca||xa.call(b)!=="[object Object]"||typeof b.callee==="function")for(d=0;d<b.length;d++)a.call(c,b[d],d);else for(d in b)b.hasOwnProperty(d)&&a.call(c,b[d],
+d);return b}function mb(b){var a=[],c;for(c in b)b.hasOwnProperty(c)&&a.push(c);return a.sort()}function fc(b,a,c){for(var d=mb(b),e=0;e<d.length;e++)a.call(c,b[d[e]],d[e]);return d}function nb(b){return function(a,c){b(c,a)}}function ya(){for(var b=aa.length,a;b;){b--;a=aa[b].charCodeAt(0);if(a==57)return aa[b]="A",aa.join("");if(a==90)aa[b]="0";else return aa[b]=String.fromCharCode(a+1),aa.join("")}aa.unshift("0");return aa.join("")}function v(b){n(arguments,function(a){a!==b&&n(a,function(a,d){b[d]=
+a})});return b}function E(b){return parseInt(b,10)}function za(b,a){return v(new (v(function(){},{prototype:b})),a)}function C(){}function na(b){return b}function I(b){return function(){return b}}function w(b){return typeof b=="undefined"}function x(b){return typeof b!="undefined"}function M(b){return b!=null&&typeof b=="object"}function A(b){return typeof b=="string"}function Ra(b){return typeof b=="number"}function oa(b){return xa.apply(b)=="[object Date]"}function B(b){return xa.apply(b)=="[object Array]"}
+function H(b){return typeof b=="function"}function pa(b){return b&&b.document&&b.location&&b.alert&&b.setInterval}function O(b){return A(b)?b.replace(/^\s*/,"").replace(/\s*$/,""):b}function gc(b){return b&&(b.nodeName||b.bind&&b.find)}function Sa(b,a,c){var d=[];n(b,function(b,g,h){d.push(a.call(c,b,g,h))});return d}function Aa(b,a){if(b.indexOf)return b.indexOf(a);for(var c=0;c<b.length;c++)if(a===b[c])return c;return-1}function Ta(b,a){var c=Aa(b,a);c>=0&&b.splice(c,1);return a}function U(b,a){if(pa(b)||
+b&&b.$evalAsync&&b.$watch)throw Error("Can't copy Window or Scope");if(a){if(b===a)throw Error("Can't copy equivalent objects or arrays");if(B(b))for(var c=a.length=0;c<b.length;c++)a.push(U(b[c]));else for(c in n(a,function(b,c){delete a[c]}),b)a[c]=U(b[c])}else(a=b)&&(B(b)?a=U(b,[]):oa(b)?a=new Date(b.getTime()):M(b)&&(a=U(b,{})));return a}function hc(b,a){var a=a||{},c;for(c in b)b.hasOwnProperty(c)&&c.substr(0,2)!=="$$"&&(a[c]=b[c]);return a}function ga(b,a){if(b===a)return!0;if(b===null||a===
+null)return!1;if(b!==b&&a!==a)return!0;var c=typeof b,d;if(c==typeof a&&c=="object")if(B(b)){if((c=b.length)==a.length){for(d=0;d<c;d++)if(!ga(b[d],a[d]))return!1;return!0}}else if(oa(b))return oa(a)&&b.getTime()==a.getTime();else{if(b&&b.$evalAsync&&b.$watch||a&&a.$evalAsync&&a.$watch||pa(b)||pa(a))return!1;c={};for(d in b)if(!(d.charAt(0)==="$"||H(b[d]))){if(!ga(b[d],a[d]))return!1;c[d]=!0}for(d in a)if(!c[d]&&d.charAt(0)!=="$"&&a[d]!==q&&!H(a[d]))return!1;return!0}return!1}function Ua(b,a){var c=
+arguments.length>2?ha.call(arguments,2):[];return H(a)&&!(a instanceof RegExp)?c.length?function(){return arguments.length?a.apply(b,c.concat(ha.call(arguments,0))):a.apply(b,c)}:function(){return arguments.length?a.apply(b,arguments):a.call(b)}:a}function ic(b,a){var c=a;/^\$+/.test(b)?c=q:pa(a)?c="$WINDOW":a&&Y===a?c="$DOCUMENT":a&&a.$evalAsync&&a.$watch&&(c="$SCOPE");return c}function da(b,a){return JSON.stringify(b,ic,a?"  ":null)}function ob(b){return A(b)?JSON.parse(b):b}function Va(b){b&&b.length!==
+0?(b=y(""+b),b=!(b=="f"||b=="0"||b=="false"||b=="no"||b=="n"||b=="[]")):b=!1;return b}function qa(b){b=u(b).clone();try{b.html("")}catch(a){}var c=u("<div>").append(b).html();try{return b[0].nodeType===3?y(c):c.match(/^(<[^>]+>)/)[1].replace(/^<([\w\-]+)/,function(a,b){return"<"+y(b)})}catch(d){return y(c)}}function Wa(b){var a={},c,d;n((b||"").split("&"),function(b){b&&(c=b.split("="),d=decodeURIComponent(c[0]),a[d]=x(c[1])?decodeURIComponent(c[1]):!0)});return a}function pb(b){var a=[];n(b,function(b,
+d){a.push(Xa(d,!0)+(b===!0?"":"="+Xa(b,!0)))});return a.length?a.join("&"):""}function Ya(b){return Xa(b,!0).replace(/%26/gi,"&").replace(/%3D/gi,"=").replace(/%2B/gi,"+")}function Xa(b,a){return encodeURIComponent(b).replace(/%40/gi,"@").replace(/%3A/gi,":").replace(/%24/g,"$").replace(/%2C/gi,",").replace(a?null:/%20/g,"+")}function jc(b,a){function c(a){a&&d.push(a)}var d=[b],e,g,h=["ng:app","ng-app","x-ng-app","data-ng-app"],f=/\sng[:\-]app(:\s*([\w\d_]+);?)?\s/;n(h,function(a){h[a]=!0;c(Y.getElementById(a));
+a=a.replace(":","\\:");b.querySelectorAll&&(n(b.querySelectorAll("."+a),c),n(b.querySelectorAll("."+a+"\\:"),c),n(b.querySelectorAll("["+a+"]"),c))});n(d,function(a){if(!e){var b=f.exec(" "+a.className+" ");b?(e=a,g=(b[2]||"").replace(/\s+/g,",")):n(a.attributes,function(b){if(!e&&h[b.name])e=a,g=b.value})}});e&&a(e,g?[g]:[])}function qb(b,a){b=u(b);a=a||[];a.unshift(["$provide",function(a){a.value("$rootElement",b)}]);a.unshift("ng");var c=rb(a);c.invoke(["$rootScope","$rootElement","$compile","$injector",
+function(a,b,c,h){a.$apply(function(){b.data("$injector",h);c(b)(a)})}]);return c}function Za(b,a){a=a||"_";return b.replace(kc,function(b,d){return(d?a:"")+b.toLowerCase()})}function $a(b,a,c){if(!b)throw Error("Argument '"+(a||"?")+"' is "+(c||"required"));return b}function ra(b,a,c){c&&B(b)&&(b=b[b.length-1]);$a(H(b),a,"not a function, got "+(b&&typeof b=="object"?b.constructor.name||"Object":typeof b));return b}function lc(b){function a(a,b,e){return a[b]||(a[b]=e())}return a(a(b,"angular",Object),
+"module",function(){var b={};return function(d,e,g){e&&b.hasOwnProperty(d)&&(b[d]=null);return a(b,d,function(){function a(c,d,e){return function(){b[e||"push"]([c,d,arguments]);return k}}if(!e)throw Error("No module: "+d);var b=[],c=[],i=a("$injector","invoke"),k={_invokeQueue:b,_runBlocks:c,requires:e,name:d,provider:a("$provide","provider"),factory:a("$provide","factory"),service:a("$provide","service"),value:a("$provide","value"),constant:a("$provide","constant","unshift"),filter:a("$filterProvider",
+"register"),controller:a("$controllerProvider","register"),directive:a("$compileProvider","directive"),config:i,run:function(a){c.push(a);return this}};g&&i(g);return k})}})}function sb(b){return b.replace(mc,function(a,b,d,e){return e?d.toUpperCase():d}).replace(nc,"Moz$1")}function ab(b,a){function c(){var e;for(var b=[this],c=a,h,f,j,i,k,m;b.length;){h=b.shift();f=0;for(j=h.length;f<j;f++){i=u(h[f]);c?i.triggerHandler("$destroy"):c=!c;k=0;for(e=(m=i.children()).length,i=e;k<i;k++)b.push(ca(m[k]))}}return d.apply(this,
+arguments)}var d=ca.fn[b],d=d.$original||d;c.$original=d;ca.fn[b]=c}function L(b){if(b instanceof L)return b;if(!(this instanceof L)){if(A(b)&&b.charAt(0)!="<")throw Error("selectors not implemented");return new L(b)}if(A(b)){var a=Y.createElement("div");a.innerHTML="<div>&#160;</div>"+b;a.removeChild(a.firstChild);bb(this,a.childNodes);this.remove()}else bb(this,b)}function cb(b){return b.cloneNode(!0)}function sa(b){tb(b);for(var a=0,b=b.childNodes||[];a<b.length;a++)sa(b[a])}function ub(b,a,c){var d=
+ba(b,"events");ba(b,"handle")&&(w(a)?n(d,function(a,c){db(b,c,a);delete d[c]}):w(c)?(db(b,a,d[a]),delete d[a]):Ta(d[a],c))}function tb(b){var a=b[Ba],c=Ca[a];c&&(c.handle&&(c.events.$destroy&&c.handle({},"$destroy"),ub(b)),delete Ca[a],b[Ba]=q)}function ba(b,a,c){var d=b[Ba],d=Ca[d||-1];if(x(c))d||(b[Ba]=d=++oc,d=Ca[d]={}),d[a]=c;else return d&&d[a]}function vb(b,a,c){var d=ba(b,"data"),e=x(c),g=!e&&x(a),h=g&&!M(a);!d&&!h&&ba(b,"data",d={});if(e)d[a]=c;else if(g)if(h)return d&&d[a];else v(d,a);else return d}
+function Da(b,a){return(" "+b.className+" ").replace(/[\n\t]/g," ").indexOf(" "+a+" ")>-1}function wb(b,a){a&&n(a.split(" "),function(a){b.className=O((" "+b.className+" ").replace(/[\n\t]/g," ").replace(" "+O(a)+" "," "))})}function xb(b,a){a&&n(a.split(" "),function(a){if(!Da(b,a))b.className=O(b.className+" "+O(a))})}function bb(b,a){if(a)for(var a=!a.nodeName&&x(a.length)&&!pa(a)?a:[a],c=0;c<a.length;c++)b.push(a[c])}function yb(b,a){return Ea(b,"$"+(a||"ngController")+"Controller")}function Ea(b,
+a,c){b=u(b);for(b[0].nodeType==9&&(b=b.find("html"));b.length;){if(c=b.data(a))return c;b=b.parent()}}function zb(b,a){var c=Fa[a.toLowerCase()];return c&&Ab[b.nodeName]&&c}function pc(b,a){var c=function(c,e){if(!c.preventDefault)c.preventDefault=function(){c.returnValue=!1};if(!c.stopPropagation)c.stopPropagation=function(){c.cancelBubble=!0};if(!c.target)c.target=c.srcElement||Y;if(w(c.defaultPrevented)){var g=c.preventDefault;c.preventDefault=function(){c.defaultPrevented=!0;g.call(c)};c.defaultPrevented=
+!1}c.isDefaultPrevented=function(){return c.defaultPrevented};n(a[e||c.type],function(a){a.call(b,c)});Z<=8?(c.preventDefault=null,c.stopPropagation=null,c.isDefaultPrevented=null):(delete c.preventDefault,delete c.stopPropagation,delete c.isDefaultPrevented)};c.elem=b;return c}function fa(b){var a=typeof b,c;if(a=="object"&&b!==null)if(typeof(c=b.$$hashKey)=="function")c=b.$$hashKey();else{if(c===q)c=b.$$hashKey=ya()}else c=b;return a+":"+c}function Ga(b){n(b,this.put,this)}function eb(){}function Bb(b){var a,
+c;if(typeof b=="function"){if(!(a=b.$inject))a=[],c=b.toString().replace(qc,""),c=c.match(rc),n(c[1].split(sc),function(b){b.replace(tc,function(b,c,d){a.push(d)})}),b.$inject=a}else B(b)?(c=b.length-1,ra(b[c],"fn"),a=b.slice(0,c)):ra(b,"fn",!0);return a}function rb(b){function a(a){return function(b,c){if(M(b))n(b,nb(a));else return a(b,c)}}function c(a,b){if(H(b)||B(b))b=m.instantiate(b);if(!b.$get)throw Error("Provider "+a+" must define $get factory method.");return k[a+f]=b}function d(a,b){return c(a,
+{$get:b})}function e(a){var b=[];n(a,function(a){if(!i.get(a))if(i.put(a,!0),A(a)){var c=ta(a);b=b.concat(e(c.requires)).concat(c._runBlocks);try{for(var d=c._invokeQueue,c=0,f=d.length;c<f;c++){var g=d[c],h=g[0]=="$injector"?m:m.get(g[0]);h[g[1]].apply(h,g[2])}}catch(j){throw j.message&&(j.message+=" from "+a),j;}}else if(H(a))try{b.push(m.invoke(a))}catch(o){throw o.message&&(o.message+=" from "+a),o;}else if(B(a))try{b.push(m.invoke(a))}catch(k){throw k.message&&(k.message+=" from "+String(a[a.length-
+1])),k;}else ra(a,"module")});return b}function g(a,b){function c(d){if(typeof d!=="string")throw Error("Service name expected");if(a.hasOwnProperty(d)){if(a[d]===h)throw Error("Circular dependency: "+j.join(" <- "));return a[d]}else try{return j.unshift(d),a[d]=h,a[d]=b(d)}finally{j.shift()}}function d(a,b,e){var f=[],i=Bb(a),g,h,j;h=0;for(g=i.length;h<g;h++)j=i[h],f.push(e&&e.hasOwnProperty(j)?e[j]:c(j));a.$inject||(a=a[g]);switch(b?-1:f.length){case 0:return a();case 1:return a(f[0]);case 2:return a(f[0],
+f[1]);case 3:return a(f[0],f[1],f[2]);case 4:return a(f[0],f[1],f[2],f[3]);case 5:return a(f[0],f[1],f[2],f[3],f[4]);case 6:return a(f[0],f[1],f[2],f[3],f[4],f[5]);case 7:return a(f[0],f[1],f[2],f[3],f[4],f[5],f[6]);case 8:return a(f[0],f[1],f[2],f[3],f[4],f[5],f[6],f[7]);case 9:return a(f[0],f[1],f[2],f[3],f[4],f[5],f[6],f[7],f[8]);case 10:return a(f[0],f[1],f[2],f[3],f[4],f[5],f[6],f[7],f[8],f[9]);default:return a.apply(b,f)}}return{invoke:d,instantiate:function(a,b){var c=function(){},e;c.prototype=
+(B(a)?a[a.length-1]:a).prototype;c=new c;e=d(a,c,b);return M(e)?e:c},get:c,annotate:Bb}}var h={},f="Provider",j=[],i=new Ga,k={$provide:{provider:a(c),factory:a(d),service:a(function(a,b){return d(a,["$injector",function(a){return a.instantiate(b)}])}),value:a(function(a,b){return d(a,I(b))}),constant:a(function(a,b){k[a]=b;l[a]=b}),decorator:function(a,b){var c=m.get(a+f),d=c.$get;c.$get=function(){var a=t.invoke(d,c);return t.invoke(b,null,{$delegate:a})}}}},m=g(k,function(){throw Error("Unknown provider: "+
+j.join(" <- "));}),l={},t=l.$injector=g(l,function(a){a=m.get(a+f);return t.invoke(a.$get,a)});n(e(b),function(a){t.invoke(a||C)});return t}function uc(){var b=!0;this.disableAutoScrolling=function(){b=!1};this.$get=["$window","$location","$rootScope",function(a,c,d){function e(a){var b=null;n(a,function(a){!b&&y(a.nodeName)==="a"&&(b=a)});return b}function g(){var b=c.hash(),d;b?(d=h.getElementById(b))?d.scrollIntoView():(d=e(h.getElementsByName(b)))?d.scrollIntoView():b==="top"&&a.scrollTo(0,0):
+a.scrollTo(0,0)}var h=a.document;b&&d.$watch(function(){return c.hash()},function(){d.$evalAsync(g)});return g}]}function vc(b,a,c,d){function e(a){try{a.apply(null,ha.call(arguments,1))}finally{if(o--,o===0)for(;p.length;)try{p.pop()()}catch(b){c.error(b)}}}function g(a,b){(function R(){n(s,function(a){a()});J=b(R,a)})()}function h(){F!=f.url()&&(F=f.url(),n(V,function(a){a(f.url())}))}var f=this,j=a[0],i=b.location,k=b.history,m=b.setTimeout,l=b.clearTimeout,t={};f.isMock=!1;var o=0,p=[];f.$$completeOutstandingRequest=
+e;f.$$incOutstandingRequestCount=function(){o++};f.notifyWhenNoOutstandingRequests=function(a){n(s,function(a){a()});o===0?a():p.push(a)};var s=[],J;f.addPollFn=function(a){w(J)&&g(100,m);s.push(a);return a};var F=i.href,z=a.find("base");f.url=function(a,b){if(a){if(F!=a)return F=a,d.history?b?k.replaceState(null,"",a):(k.pushState(null,"",a),z.attr("href",z.attr("href"))):b?i.replace(a):i.href=a,f}else return i.href.replace(/%27/g,"'")};var V=[],K=!1;f.onUrlChange=function(a){K||(d.history&&u(b).bind("popstate",
+h),d.hashchange?u(b).bind("hashchange",h):f.addPollFn(h),K=!0);V.push(a);return a};f.baseHref=function(){var a=z.attr("href");return a?a.replace(/^https?\:\/\/[^\/]*/,""):""};var r={},$="",P=f.baseHref();f.cookies=function(a,b){var d,e,f,i;if(a)if(b===q)j.cookie=escape(a)+"=;path="+P+";expires=Thu, 01 Jan 1970 00:00:00 GMT";else{if(A(b))d=(j.cookie=escape(a)+"="+escape(b)+";path="+P).length+1,d>4096&&c.warn("Cookie '"+a+"' possibly not set or overflowed because it was too large ("+d+" > 4096 bytes)!")}else{if(j.cookie!==
+$){$=j.cookie;d=$.split("; ");r={};for(f=0;f<d.length;f++)e=d[f],i=e.indexOf("="),i>0&&(r[unescape(e.substring(0,i))]=unescape(e.substring(i+1)))}return r}};f.defer=function(a,b){var c;o++;c=m(function(){delete t[c];e(a)},b||0);t[c]=!0;return c};f.defer.cancel=function(a){return t[a]?(delete t[a],l(a),e(C),!0):!1}}function wc(){this.$get=["$window","$log","$sniffer","$document",function(b,a,c,d){return new vc(b,d,a,c)}]}function xc(){this.$get=function(){function b(b,d){function e(a){if(a!=m){if(l){if(l==
+a)l=a.n}else l=a;g(a.n,a.p);g(a,m);m=a;m.n=null}}function g(a,b){if(a!=b){if(a)a.p=b;if(b)b.n=a}}if(b in a)throw Error("cacheId "+b+" taken");var h=0,f=v({},d,{id:b}),j={},i=d&&d.capacity||Number.MAX_VALUE,k={},m=null,l=null;return a[b]={put:function(a,b){var c=k[a]||(k[a]={key:a});e(c);w(b)||(a in j||h++,j[a]=b,h>i&&this.remove(l.key))},get:function(a){var b=k[a];if(b)return e(b),j[a]},remove:function(a){var b=k[a];if(b){if(b==m)m=b.p;if(b==l)l=b.n;g(b.n,b.p);delete k[a];delete j[a];h--}},removeAll:function(){j=
+{};h=0;k={};m=l=null},destroy:function(){k=f=j=null;delete a[b]},info:function(){return v({},f,{size:h})}}}var a={};b.info=function(){var b={};n(a,function(a,e){b[e]=a.info()});return b};b.get=function(b){return a[b]};return b}}function yc(){this.$get=["$cacheFactory",function(b){return b("templates")}]}function Cb(b){var a={},c="Directive",d=/^\s*directive\:\s*([\d\w\-_]+)\s+(.*)$/,e=/(([\d\w\-_]+)(?:\:([^;]+))?;?)/,g="Template must have exactly one root element. was: ",h=/^\s*(https?|ftp|mailto):/;
+this.directive=function j(d,e){A(d)?($a(e,"directive"),a.hasOwnProperty(d)||(a[d]=[],b.factory(d+c,["$injector","$exceptionHandler",function(b,c){var e=[];n(a[d],function(a){try{var g=b.invoke(a);if(H(g))g={compile:I(g)};else if(!g.compile&&g.link)g.compile=I(g.link);g.priority=g.priority||0;g.name=g.name||d;g.require=g.require||g.controller&&g.name;g.restrict=g.restrict||"A";e.push(g)}catch(h){c(h)}});return e}])),a[d].push(e)):n(d,nb(j));return this};this.urlSanitizationWhitelist=function(a){return x(a)?
+(h=a,this):h};this.$get=["$injector","$interpolate","$exceptionHandler","$http","$templateCache","$parse","$controller","$rootScope","$document",function(b,i,k,m,l,t,o,p,s){function J(a,b,c){a instanceof u||(a=u(a));n(a,function(b,c){b.nodeType==3&&b.nodeValue.match(/\S+/)&&(a[c]=u(b).wrap("<span></span>").parent()[0])});var d=z(a,b,a,c);return function(b,c){$a(b,"scope");for(var e=c?va.clone.call(a):a,g=0,i=e.length;g<i;g++){var h=e[g];(h.nodeType==1||h.nodeType==9)&&e.eq(g).data("$scope",b)}F(e,
+"ng-scope");c&&c(e,b);d&&d(b,e,e);return e}}function F(a,b){try{a.addClass(b)}catch(c){}}function z(a,b,c,d){function e(a,c,d,i){var h,j,k,o,l,m,t,s=[];l=0;for(m=c.length;l<m;l++)s.push(c[l]);t=l=0;for(m=g.length;l<m;t++)j=s[t],c=g[l++],h=g[l++],c?(c.scope?(k=a.$new(M(c.scope)),u(j).data("$scope",k)):k=a,(o=c.transclude)||!i&&b?c(h,k,j,d,function(b){return function(c){var d=a.$new();d.$$transcluded=!0;return b(d,c).bind("$destroy",Ua(d,d.$destroy))}}(o||b)):c(h,k,j,q,i)):h&&h(a,j.childNodes,q,i)}
+for(var g=[],i,h,j,k=0;k<a.length;k++)h=new ia,i=V(a[k],[],h,d),h=(i=i.length?K(i,a[k],h,b,c):null)&&i.terminal||!a[k].childNodes.length?null:z(a[k].childNodes,i?i.transclude:b),g.push(i),g.push(h),j=j||i||h;return j?e:null}function V(a,b,c,i){var g=c.$attr,h;switch(a.nodeType){case 1:r(b,ea(fb(a).toLowerCase()),"E",i);var j,k,l;h=a.attributes;for(var o=0,m=h&&h.length;o<m;o++)if(j=h[o],j.specified)k=j.name,l=ea(k.toLowerCase()),g[l]=k,c[l]=j=O(Z&&k=="href"?decodeURIComponent(a.getAttribute(k,2)):
+j.value),zb(a,l)&&(c[l]=!0),R(a,b,j,l),r(b,l,"A",i);a=a.className;if(A(a)&&a!=="")for(;h=e.exec(a);)l=ea(h[2]),r(b,l,"C",i)&&(c[l]=O(h[3])),a=a.substr(h.index+h[0].length);break;case 3:x(b,a.nodeValue);break;case 8:try{if(h=d.exec(a.nodeValue))l=ea(h[1]),r(b,l,"M",i)&&(c[l]=O(h[2]))}catch(t){}}b.sort(G);return b}function K(a,b,c,d,e){function i(a,b){if(a)a.require=r.require,m.push(a);if(b)b.require=r.require,s.push(b)}function h(a,b){var c,d="data",e=!1;if(A(a)){for(;(c=a.charAt(0))=="^"||c=="?";)a=
+a.substr(1),c=="^"&&(d="inheritedData"),e=e||c=="?";c=b[d]("$"+a+"Controller");if(!c&&!e)throw Error("No controller: "+a);}else B(a)&&(c=[],n(a,function(a){c.push(h(a,b))}));return c}function j(a,d,e,i,g){var l,p,r,D,F;l=b===e?c:hc(c,new ia(u(e),c.$attr));p=l.$$element;if(K){var J=/^\s*([@=&])\s*(\w*)\s*$/,ja=d.$parent||d;n(K.scope,function(a,b){var c=a.match(J)||[],e=c[2]||b,c=c[1],i,g,h;d.$$isolateBindings[b]=c+e;switch(c){case "@":l.$observe(e,function(a){d[b]=a});l.$$observers[e].$$scope=ja;break;
+case "=":g=t(l[e]);h=g.assign||function(){i=d[b]=g(ja);throw Error(Db+l[e]+" (directive: "+K.name+")");};i=d[b]=g(ja);d.$watch(function(){var a=g(ja);a!==d[b]&&(a!==i?i=d[b]=a:h(ja,a=i=d[b]));return a});break;case "&":g=t(l[e]);d[b]=function(a){return g(ja,a)};break;default:throw Error("Invalid isolate scope definition for directive "+K.name+": "+a);}})}x&&n(x,function(a){var b={$scope:d,$element:p,$attrs:l,$transclude:g};F=a.controller;F=="@"&&(F=l[a.name]);p.data("$"+a.name+"Controller",o(F,b))});
+i=0;for(r=m.length;i<r;i++)try{D=m[i],D(d,p,l,D.require&&h(D.require,p))}catch(z){k(z,qa(p))}a&&a(d,e.childNodes,q,g);i=0;for(r=s.length;i<r;i++)try{D=s[i],D(d,p,l,D.require&&h(D.require,p))}catch(zc){k(zc,qa(p))}}for(var l=-Number.MAX_VALUE,m=[],s=[],p=null,K=null,z=null,D=c.$$element=u(b),r,G,S,ka,R=d,x,w,W,v=0,y=a.length;v<y;v++){r=a[v];S=q;if(l>r.priority)break;if(W=r.scope)ua("isolated scope",K,r,D),M(W)&&(F(D,"ng-isolate-scope"),K=r),F(D,"ng-scope"),p=p||r;G=r.name;if(W=r.controller)x=x||{},
+ua("'"+G+"' controller",x[G],r,D),x[G]=r;if(W=r.transclude)ua("transclusion",ka,r,D),ka=r,l=r.priority,W=="element"?(S=u(b),D=c.$$element=u(Y.createComment(" "+G+": "+c[G]+" ")),b=D[0],C(e,u(S[0]),b),R=J(S,d,l)):(S=u(cb(b)).contents(),D.html(""),R=J(S,d));if(W=r.template)if(ua("template",z,r,D),z=r,W=Eb(W),r.replace){S=u("<div>"+O(W)+"</div>").contents();b=S[0];if(S.length!=1||b.nodeType!==1)throw Error(g+W);C(e,D,b);G={$attr:{}};a=a.concat(V(b,a.splice(v+1,a.length-(v+1)),G));$(c,G);y=a.length}else D.html(W);
+if(r.templateUrl)ua("template",z,r,D),z=r,j=P(a.splice(v,a.length-v),j,D,c,e,r.replace,R),y=a.length;else if(r.compile)try{w=r.compile(D,c,R),H(w)?i(null,w):w&&i(w.pre,w.post)}catch(E){k(E,qa(D))}if(r.terminal)j.terminal=!0,l=Math.max(l,r.priority)}j.scope=p&&p.scope;j.transclude=ka&&R;return j}function r(d,e,i,g){var h=!1;if(a.hasOwnProperty(e))for(var l,e=b.get(e+c),o=0,m=e.length;o<m;o++)try{if(l=e[o],(g===q||g>l.priority)&&l.restrict.indexOf(i)!=-1)d.push(l),h=!0}catch(t){k(t)}return h}function $(a,
+b){var c=b.$attr,d=a.$attr,e=a.$$element;n(a,function(d,e){e.charAt(0)!="$"&&(b[e]&&(d+=(e==="style"?";":" ")+b[e]),a.$set(e,d,!0,c[e]))});n(b,function(b,i){i=="class"?(F(e,b),a["class"]=(a["class"]?a["class"]+" ":"")+b):i=="style"?e.attr("style",e.attr("style")+";"+b):i.charAt(0)!="$"&&!a.hasOwnProperty(i)&&(a[i]=b,d[i]=c[i])})}function P(a,b,c,d,e,i,h){var j=[],k,o,t=c[0],s=a.shift(),p=v({},s,{controller:null,templateUrl:null,transclude:null,scope:null});c.html("");m.get(s.templateUrl,{cache:l}).success(function(l){var m,
+s,l=Eb(l);if(i){s=u("<div>"+O(l)+"</div>").contents();m=s[0];if(s.length!=1||m.nodeType!==1)throw Error(g+l);l={$attr:{}};C(e,c,m);V(m,a,l);$(d,l)}else m=t,c.html(l);a.unshift(p);k=K(a,m,d,h);for(o=z(c.contents(),h);j.length;){var ia=j.pop(),l=j.pop();s=j.pop();var r=j.pop(),D=m;s!==t&&(D=cb(m),C(l,u(s),D));k(function(){b(o,r,D,e,ia)},r,D,e,ia)}j=null}).error(function(a,b,c,d){throw Error("Failed to load template: "+d.url);});return function(a,c,d,e,i){j?(j.push(c),j.push(d),j.push(e),j.push(i)):
+k(function(){b(o,c,d,e,i)},c,d,e,i)}}function G(a,b){return b.priority-a.priority}function ua(a,b,c,d){if(b)throw Error("Multiple directives ["+b.name+", "+c.name+"] asking for "+a+" on: "+qa(d));}function x(a,b){var c=i(b,!0);c&&a.push({priority:0,compile:I(function(a,b){var d=b.parent(),e=d.data("$binding")||[];e.push(c);F(d.data("$binding",e),"ng-binding");a.$watch(c,function(a){b[0].nodeValue=a})})})}function R(a,b,c,d){var e=i(c,!0);e&&b.push({priority:100,compile:I(function(a,b,c){b=c.$$observers||
+(c.$$observers={});d==="class"&&(e=i(c[d],!0));c[d]=q;(b[d]||(b[d]=[])).$$inter=!0;(c.$$observers&&c.$$observers[d].$$scope||a).$watch(e,function(a){c.$set(d,a)})})})}function C(a,b,c){var d=b[0],e=d.parentNode,i,g;if(a){i=0;for(g=a.length;i<g;i++)if(a[i]==d){a[i]=c;break}}e&&e.replaceChild(c,d);c[u.expando]=d[u.expando];b[0]=c}var ia=function(a,b){this.$$element=a;this.$attr=b||{}};ia.prototype={$normalize:ea,$set:function(a,b,c,d){var e=zb(this.$$element[0],a),i=this.$$observers;e&&(this.$$element.prop(a,
+b),d=e);this[a]=b;d?this.$attr[a]=d:(d=this.$attr[a])||(this.$attr[a]=d=Za(a,"-"));if(fb(this.$$element[0])==="A"&&a==="href")D.setAttribute("href",b),e=D.href,e.match(h)||(this[a]=b="unsafe:"+e);c!==!1&&(b===null||b===q?this.$$element.removeAttr(d):this.$$element.attr(d,b));i&&n(i[a],function(a){try{a(b)}catch(c){k(c)}})},$observe:function(a,b){var c=this,d=c.$$observers||(c.$$observers={}),e=d[a]||(d[a]=[]);e.push(b);p.$evalAsync(function(){e.$$inter||b(c[a])});return b}};var D=s[0].createElement("a"),
+S=i.startSymbol(),ka=i.endSymbol(),Eb=S=="{{"||ka=="}}"?na:function(a){return a.replace(/\{\{/g,S).replace(/}}/g,ka)};return J}]}function ea(b){return sb(b.replace(Ac,""))}function Bc(){var b={};this.register=function(a,c){M(a)?v(b,a):b[a]=c};this.$get=["$injector","$window",function(a,c){return function(d,e){if(A(d)){var g=d,d=b.hasOwnProperty(g)?b[g]:gb(e.$scope,g,!0)||gb(c,g,!0);ra(d,g,!0)}return a.instantiate(d,e)}}]}function Cc(){this.$get=["$window",function(b){return u(b.document)}]}function Dc(){this.$get=
+["$log",function(b){return function(a,c){b.error.apply(b,arguments)}}]}function Ec(){var b="{{",a="}}";this.startSymbol=function(a){return a?(b=a,this):b};this.endSymbol=function(b){return b?(a=b,this):a};this.$get=["$parse",function(c){function d(d,f){for(var j,i,k=0,m=[],l=d.length,t=!1,o=[];k<l;)(j=d.indexOf(b,k))!=-1&&(i=d.indexOf(a,j+e))!=-1?(k!=j&&m.push(d.substring(k,j)),m.push(k=c(t=d.substring(j+e,i))),k.exp=t,k=i+g,t=!0):(k!=l&&m.push(d.substring(k)),k=l);if(!(l=m.length))m.push(""),l=1;
+if(!f||t)return o.length=l,k=function(a){for(var b=0,c=l,d;b<c;b++){if(typeof(d=m[b])=="function")d=d(a),d==null||d==q?d="":typeof d!="string"&&(d=da(d));o[b]=d}return o.join("")},k.exp=d,k.parts=m,k}var e=b.length,g=a.length;d.startSymbol=function(){return b};d.endSymbol=function(){return a};return d}]}function Fb(b){for(var b=b.split("/"),a=b.length;a--;)b[a]=Ya(b[a]);return b.join("/")}function wa(b,a){var c=Gb.exec(b),c={protocol:c[1],host:c[3],port:E(c[5])||Hb[c[1]]||null,path:c[6]||"/",search:c[8],
+hash:c[10]};if(a)a.$$protocol=c.protocol,a.$$host=c.host,a.$$port=c.port;return c}function la(b,a,c){return b+"://"+a+(c==Hb[b]?"":":"+c)}function Fc(b,a,c){var d=wa(b);return decodeURIComponent(d.path)!=a||w(d.hash)||d.hash.indexOf(c)!==0?b:la(d.protocol,d.host,d.port)+a.substr(0,a.lastIndexOf("/"))+d.hash.substr(c.length)}function Gc(b,a,c){var d=wa(b);if(decodeURIComponent(d.path)==a)return b;else{var e=d.search&&"?"+d.search||"",g=d.hash&&"#"+d.hash||"",h=a.substr(0,a.lastIndexOf("/")),f=d.path.substr(h.length);
+if(d.path.indexOf(h)!==0)throw Error('Invalid url "'+b+'", missing path prefix "'+h+'" !');return la(d.protocol,d.host,d.port)+a+"#"+c+f+e+g}}function hb(b,a,c){a=a||"";this.$$parse=function(b){var c=wa(b,this);if(c.path.indexOf(a)!==0)throw Error('Invalid url "'+b+'", missing path prefix "'+a+'" !');this.$$path=decodeURIComponent(c.path.substr(a.length));this.$$search=Wa(c.search);this.$$hash=c.hash&&decodeURIComponent(c.hash)||"";this.$$compose()};this.$$compose=function(){var b=pb(this.$$search),
+c=this.$$hash?"#"+Ya(this.$$hash):"";this.$$url=Fb(this.$$path)+(b?"?"+b:"")+c;this.$$absUrl=la(this.$$protocol,this.$$host,this.$$port)+a+this.$$url};this.$$rewriteAppUrl=function(a){if(a.indexOf(c)==0)return a};this.$$parse(b)}function Ha(b,a,c){var d;this.$$parse=function(b){var c=wa(b,this);if(c.hash&&c.hash.indexOf(a)!==0)throw Error('Invalid url "'+b+'", missing hash prefix "'+a+'" !');d=c.path+(c.search?"?"+c.search:"");c=Hc.exec((c.hash||"").substr(a.length));this.$$path=c[1]?(c[1].charAt(0)==
+"/"?"":"/")+decodeURIComponent(c[1]):"";this.$$search=Wa(c[3]);this.$$hash=c[5]&&decodeURIComponent(c[5])||"";this.$$compose()};this.$$compose=function(){var b=pb(this.$$search),c=this.$$hash?"#"+Ya(this.$$hash):"";this.$$url=Fb(this.$$path)+(b?"?"+b:"")+c;this.$$absUrl=la(this.$$protocol,this.$$host,this.$$port)+d+(this.$$url?"#"+a+this.$$url:"")};this.$$rewriteAppUrl=function(a){if(a.indexOf(c)==0)return a};this.$$parse(b)}function Ib(b,a,c,d){Ha.apply(this,arguments);this.$$rewriteAppUrl=function(b){if(b.indexOf(c)==
+0)return c+d+"#"+a+b.substr(c.length)}}function Ia(b){return function(){return this[b]}}function Jb(b,a){return function(c){if(w(c))return this[b];this[b]=a(c);this.$$compose();return this}}function Ic(){var b="",a=!1;this.hashPrefix=function(a){return x(a)?(b=a,this):b};this.html5Mode=function(b){return x(b)?(a=b,this):a};this.$get=["$rootScope","$browser","$sniffer","$rootElement",function(c,d,e,g){function h(a){c.$broadcast("$locationChangeSuccess",f.absUrl(),a)}var f,j,i,k=d.url(),m=wa(k);a?(j=
+d.baseHref()||"/",i=j.substr(0,j.lastIndexOf("/")),m=la(m.protocol,m.host,m.port)+i+"/",f=e.history?new hb(Fc(k,j,b),i,m):new Ib(Gc(k,j,b),b,m,j.substr(i.length+1))):(m=la(m.protocol,m.host,m.port)+(m.path||"")+(m.search?"?"+m.search:"")+"#"+b+"/",f=new Ha(k,b,m));g.bind("click",function(a){if(!a.ctrlKey&&!(a.metaKey||a.which==2)){for(var b=u(a.target);y(b[0].nodeName)!=="a";)if(b[0]===g[0]||!(b=b.parent())[0])return;var d=b.prop("href"),e=f.$$rewriteAppUrl(d);d&&!b.attr("target")&&e&&(f.$$parse(e),
+c.$apply(),a.preventDefault(),X.angular["ff-684208-preventDefault"]=!0)}});f.absUrl()!=k&&d.url(f.absUrl(),!0);d.onUrlChange(function(a){f.absUrl()!=a&&(c.$evalAsync(function(){var b=f.absUrl();f.$$parse(a);h(b)}),c.$$phase||c.$digest())});var l=0;c.$watch(function(){var a=d.url(),b=f.$$replace;if(!l||a!=f.absUrl())l++,c.$evalAsync(function(){c.$broadcast("$locationChangeStart",f.absUrl(),a).defaultPrevented?f.$$parse(a):(d.url(f.absUrl(),b),h(a))});f.$$replace=!1;return l});return f}]}function Jc(){this.$get=
+["$window",function(b){function a(a){a instanceof Error&&(a.stack?a=a.message&&a.stack.indexOf(a.message)===-1?"Error: "+a.message+"\n"+a.stack:a.stack:a.sourceURL&&(a=a.message+"\n"+a.sourceURL+":"+a.line));return a}function c(c){var e=b.console||{},g=e[c]||e.log||C;return g.apply?function(){var b=[];n(arguments,function(c){b.push(a(c))});return g.apply(e,b)}:function(a,b){g(a,b)}}return{log:c("log"),warn:c("warn"),info:c("info"),error:c("error")}}]}function Kc(b,a){function c(a){return a.indexOf(s)!=
+-1}function d(){return o+1<b.length?b.charAt(o+1):!1}function e(a){return"0"<=a&&a<="9"}function g(a){return a==" "||a=="\r"||a=="\t"||a=="\n"||a=="\u000b"||a=="\u00a0"}function h(a){return"a"<=a&&a<="z"||"A"<=a&&a<="Z"||"_"==a||a=="$"}function f(a){return a=="-"||a=="+"||e(a)}function j(a,c,d){d=d||o;throw Error("Lexer Error: "+a+" at column"+(x(c)?"s "+c+"-"+o+" ["+b.substring(c,d)+"]":" "+d)+" in expression ["+b+"].");}function i(){for(var a="",c=o;o<b.length;){var i=y(b.charAt(o));if(i=="."||
+e(i))a+=i;else{var g=d();if(i=="e"&&f(g))a+=i;else if(f(i)&&g&&e(g)&&a.charAt(a.length-1)=="e")a+=i;else if(f(i)&&(!g||!e(g))&&a.charAt(a.length-1)=="e")j("Invalid exponent");else break}o++}a*=1;l.push({index:c,text:a,json:!0,fn:function(){return a}})}function k(){for(var c="",d=o,f,i,j;o<b.length;){var k=b.charAt(o);if(k=="."||h(k)||e(k))k=="."&&(f=o),c+=k;else break;o++}if(f)for(i=o;i<b.length;){k=b.charAt(i);if(k=="("){j=c.substr(f-d+1);c=c.substr(0,f-d);o=i;break}if(g(k))i++;else break}d={index:d,
+text:c};if(Ja.hasOwnProperty(c))d.fn=d.json=Ja[c];else{var m=Kb(c,a);d.fn=v(function(a,b){return m(a,b)},{assign:function(a,b){return Lb(a,c,b)}})}l.push(d);j&&(l.push({index:f,text:".",json:!1}),l.push({index:f+1,text:j,json:!1}))}function m(a){var c=o;o++;for(var d="",e=a,f=!1;o<b.length;){var i=b.charAt(o);e+=i;if(f)i=="u"?(i=b.substring(o+1,o+5),i.match(/[\da-f]{4}/i)||j("Invalid unicode escape [\\u"+i+"]"),o+=4,d+=String.fromCharCode(parseInt(i,16))):(f=Lc[i],d+=f?f:i),f=!1;else if(i=="\\")f=
+!0;else if(i==a){o++;l.push({index:c,text:e,string:d,json:!0,fn:function(){return d}});return}else d+=i;o++}j("Unterminated quote",c)}for(var l=[],t,o=0,p=[],s,J=":";o<b.length;){s=b.charAt(o);if(c("\"'"))m(s);else if(e(s)||c(".")&&e(d()))i();else if(h(s)){if(k(),"{,".indexOf(J)!=-1&&p[0]=="{"&&(t=l[l.length-1]))t.json=t.text.indexOf(".")==-1}else if(c("(){}[].,;:"))l.push({index:o,text:s,json:":[,".indexOf(J)!=-1&&c("{[")||c("}]:,")}),c("{[")&&p.unshift(s),c("}]")&&p.shift(),o++;else if(g(s)){o++;
+continue}else{var n=s+d(),z=Ja[s],V=Ja[n];V?(l.push({index:o,text:n,fn:V}),o+=2):z?(l.push({index:o,text:s,fn:z,json:"[,:".indexOf(J)!=-1&&c("+-")}),o+=1):j("Unexpected next character ",o,o+1)}J=s}return l}function Mc(b,a,c,d){function e(a,c){throw Error("Syntax Error: Token '"+c.text+"' "+a+" at column "+(c.index+1)+" of the expression ["+b+"] starting at ["+b.substring(c.index)+"].");}function g(){if(P.length===0)throw Error("Unexpected end of expression: "+b);return P[0]}function h(a,b,c,d){if(P.length>
+0){var e=P[0],f=e.text;if(f==a||f==b||f==c||f==d||!a&&!b&&!c&&!d)return e}return!1}function f(b,c,d,f){return(b=h(b,c,d,f))?(a&&!b.json&&e("is not valid json",b),P.shift(),b):!1}function j(a){f(a)||e("is unexpected, expecting ["+a+"]",h())}function i(a,b){return function(c,d){return a(c,d,b)}}function k(a,b,c){return function(d,e){return b(d,e,a,c)}}function m(){for(var a=[];;)if(P.length>0&&!h("}",")",";","]")&&a.push(w()),!f(";"))return a.length==1?a[0]:function(b,c){for(var d,e=0;e<a.length;e++){var f=
+a[e];f&&(d=f(b,c))}return d}}function l(){for(var a=f(),b=c(a.text),d=[];;)if(a=f(":"))d.push(G());else{var e=function(a,c,e){for(var e=[e],f=0;f<d.length;f++)e.push(d[f](a,c));return b.apply(a,e)};return function(){return e}}}function t(){for(var a=o(),b;;)if(b=f("||"))a=k(a,b.fn,o());else return a}function o(){var a=p(),b;if(b=f("&&"))a=k(a,b.fn,o());return a}function p(){var a=s(),b;if(b=f("==","!="))a=k(a,b.fn,p());return a}function s(){var a;a=J();for(var b;b=f("+","-");)a=k(a,b.fn,J());if(b=
+f("<",">","<=",">="))a=k(a,b.fn,s());return a}function J(){for(var a=n(),b;b=f("*","/","%");)a=k(a,b.fn,n());return a}function n(){var a;return f("+")?z():(a=f("-"))?k(r,a.fn,n()):(a=f("!"))?i(a.fn,n()):z()}function z(){var a;if(f("("))a=w(),j(")");else if(f("["))a=V();else if(f("{"))a=K();else{var b=f();(a=b.fn)||e("not a primary expression",b)}for(var c;b=f("(","[",".");)b.text==="("?(a=x(a,c),c=null):b.text==="["?(c=a,a=R(a)):b.text==="."?(c=a,a=u(a)):e("IMPOSSIBLE");return a}function V(){var a=
+[];if(g().text!="]"){do a.push(G());while(f(","))}j("]");return function(b,c){for(var d=[],e=0;e<a.length;e++)d.push(a[e](b,c));return d}}function K(){var a=[];if(g().text!="}"){do{var b=f(),b=b.string||b.text;j(":");var c=G();a.push({key:b,value:c})}while(f(","))}j("}");return function(b,c){for(var d={},e=0;e<a.length;e++){var f=a[e],i=f.value(b,c);d[f.key]=i}return d}}var r=I(0),$,P=Kc(b,d),G=function(){var a=t(),c,d;return(d=f("="))?(a.assign||e("implies assignment but ["+b.substring(0,d.index)+
+"] can not be assigned to",d),c=t(),function(b,d){return a.assign(b,c(b,d),d)}):a},x=function(a,b){var c=[];if(g().text!=")"){do c.push(G());while(f(","))}j(")");return function(d,e){for(var f=[],i=b?b(d,e):d,g=0;g<c.length;g++)f.push(c[g](d,e));g=a(d,e)||C;return g.apply?g.apply(i,f):g(f[0],f[1],f[2],f[3],f[4])}},u=function(a){var b=f().text,c=Kb(b,d);return v(function(b,d){return c(a(b,d),d)},{assign:function(c,d,e){return Lb(a(c,e),b,d)}})},R=function(a){var b=G();j("]");return v(function(c,d){var e=
+a(c,d),f=b(c,d),i;if(!e)return q;if((e=e[f])&&e.then){i=e;if(!("$$v"in e))i.$$v=q,i.then(function(a){i.$$v=a});e=e.$$v}return e},{assign:function(c,d,e){return a(c,e)[b(c,e)]=d}})},w=function(){for(var a=G(),b;;)if(b=f("|"))a=k(a,b.fn,l());else return a};a?(G=t,x=u=R=w=function(){e("is not valid json",{text:b,index:0})},$=z()):$=m();P.length!==0&&e("is an unexpected token",P[0]);return $}function Lb(b,a,c){for(var a=a.split("."),d=0;a.length>1;d++){var e=a.shift(),g=b[e];g||(g={},b[e]=g);b=g}return b[a.shift()]=
+c}function gb(b,a,c){if(!a)return b;for(var a=a.split("."),d,e=b,g=a.length,h=0;h<g;h++)d=a[h],b&&(b=(e=b)[d]);return!c&&H(b)?Ua(e,b):b}function Mb(b,a,c,d,e){return function(g,h){var f=h&&h.hasOwnProperty(b)?h:g,j;if(f===null||f===q)return f;if((f=f[b])&&f.then){if(!("$$v"in f))j=f,j.$$v=q,j.then(function(a){j.$$v=a});f=f.$$v}if(!a||f===null||f===q)return f;if((f=f[a])&&f.then){if(!("$$v"in f))j=f,j.$$v=q,j.then(function(a){j.$$v=a});f=f.$$v}if(!c||f===null||f===q)return f;if((f=f[c])&&f.then){if(!("$$v"in
+f))j=f,j.$$v=q,j.then(function(a){j.$$v=a});f=f.$$v}if(!d||f===null||f===q)return f;if((f=f[d])&&f.then){if(!("$$v"in f))j=f,j.$$v=q,j.then(function(a){j.$$v=a});f=f.$$v}if(!e||f===null||f===q)return f;if((f=f[e])&&f.then){if(!("$$v"in f))j=f,j.$$v=q,j.then(function(a){j.$$v=a});f=f.$$v}return f}}function Kb(b,a){if(ib.hasOwnProperty(b))return ib[b];var c=b.split("."),d=c.length,e;if(a)e=d<6?Mb(c[0],c[1],c[2],c[3],c[4]):function(a,b){var e=0,i;do i=Mb(c[e++],c[e++],c[e++],c[e++],c[e++])(a,b),b=q,
+a=i;while(e<d);return i};else{var g="var l, fn, p;\n";n(c,function(a,b){g+="if(s === null || s === undefined) return s;\nl=s;\ns="+(b?"s":'((k&&k.hasOwnProperty("'+a+'"))?k:s)')+'["'+a+'"];\nif (s && s.then) {\n if (!("$$v" in s)) {\n p=s;\n p.$$v = undefined;\n p.then(function(v) {p.$$v=v;});\n}\n s=s.$$v\n}\n'});g+="return s;";e=Function("s","k",g);e.toString=function(){return g}}return ib[b]=e}function Nc(){var b={};this.$get=["$filter","$sniffer",function(a,c){return function(d){switch(typeof d){case "string":return b.hasOwnProperty(d)?
+b[d]:b[d]=Mc(d,!1,a,c.csp);case "function":return d;default:return C}}}]}function Oc(){this.$get=["$rootScope","$exceptionHandler",function(b,a){return Pc(function(a){b.$evalAsync(a)},a)}]}function Pc(b,a){function c(a){return a}function d(a){return h(a)}var e=function(){var f=[],j,i;return i={resolve:function(a){if(f){var c=f;f=q;j=g(a);c.length&&b(function(){for(var a,b=0,d=c.length;b<d;b++)a=c[b],j.then(a[0],a[1])})}},reject:function(a){i.resolve(h(a))},promise:{then:function(b,i){var g=e(),h=
+function(d){try{g.resolve((b||c)(d))}catch(e){a(e),g.reject(e)}},o=function(b){try{g.resolve((i||d)(b))}catch(c){a(c),g.reject(c)}};f?f.push([h,o]):j.then(h,o);return g.promise}}}},g=function(a){return a&&a.then?a:{then:function(c){var d=e();b(function(){d.resolve(c(a))});return d.promise}}},h=function(a){return{then:function(c,i){var g=e();b(function(){g.resolve((i||d)(a))});return g.promise}}};return{defer:e,reject:h,when:function(f,j,i){var k=e(),m,l=function(b){try{return(j||c)(b)}catch(d){return a(d),
+h(d)}},t=function(b){try{return(i||d)(b)}catch(c){return a(c),h(c)}};b(function(){g(f).then(function(a){m||(m=!0,k.resolve(g(a).then(l,t)))},function(a){m||(m=!0,k.resolve(t(a)))})});return k.promise},all:function(a){var b=e(),c=a.length,d=[];c?n(a,function(a,e){g(a).then(function(a){e in d||(d[e]=a,--c||b.resolve(d))},function(a){e in d||b.reject(a)})}):b.resolve(d);return b.promise}}}function Qc(){var b={};this.when=function(a,c){b[a]=v({reloadOnSearch:!0},c);if(a){var d=a[a.length-1]=="/"?a.substr(0,
+a.length-1):a+"/";b[d]={redirectTo:a}}return this};this.otherwise=function(a){this.when(null,a);return this};this.$get=["$rootScope","$location","$routeParams","$q","$injector","$http","$templateCache",function(a,c,d,e,g,h,f){function j(a,b){for(var b="^"+b.replace(/[-\/\\^$*+?.()|[\]{}]/g,"\\$&")+"$",c="",d=[],e={},f=/:(\w+)/g,i,g=0;(i=f.exec(b))!==null;)c+=b.slice(g,i.index),c+="([^\\/]*)",d.push(i[1]),g=f.lastIndex;c+=b.substr(g);var h=a.match(RegExp(c));h&&n(d,function(a,b){e[a]=h[b+1]});return h?
+e:null}function i(){var b=k(),i=t.current;if(b&&i&&b.$route===i.$route&&ga(b.pathParams,i.pathParams)&&!b.reloadOnSearch&&!l)i.params=b.params,U(i.params,d),a.$broadcast("$routeUpdate",i);else if(b||i)l=!1,a.$broadcast("$routeChangeStart",b,i),(t.current=b)&&b.redirectTo&&(A(b.redirectTo)?c.path(m(b.redirectTo,b.params)).search(b.params).replace():c.url(b.redirectTo(b.pathParams,c.path(),c.search())).replace()),e.when(b).then(function(){if(b){var a=[],c=[],d;n(b.resolve||{},function(b,d){a.push(d);
+c.push(A(b)?g.get(b):g.invoke(b))});if(!x(d=b.template))if(x(d=b.templateUrl))d=h.get(d,{cache:f}).then(function(a){return a.data});x(d)&&(a.push("$template"),c.push(d));return e.all(c).then(function(b){var c={};n(b,function(b,d){c[a[d]]=b});return c})}}).then(function(c){if(b==t.current){if(b)b.locals=c,U(b.params,d);a.$broadcast("$routeChangeSuccess",b,i)}},function(c){b==t.current&&a.$broadcast("$routeChangeError",b,i,c)})}function k(){var a,d;n(b,function(b,e){if(!d&&(a=j(c.path(),e)))d=za(b,
+{params:v({},c.search(),a),pathParams:a}),d.$route=b});return d||b[null]&&za(b[null],{params:{},pathParams:{}})}function m(a,b){var c=[];n((a||"").split(":"),function(a,d){if(d==0)c.push(a);else{var e=a.match(/(\w+)(.*)/),f=e[1];c.push(b[f]);c.push(e[2]||"");delete b[f]}});return c.join("")}var l=!1,t={routes:b,reload:function(){l=!0;a.$evalAsync(i)}};a.$on("$locationChangeSuccess",i);return t}]}function Rc(){this.$get=I({})}function Sc(){var b=10;this.digestTtl=function(a){arguments.length&&(b=a);
+return b};this.$get=["$injector","$exceptionHandler","$parse",function(a,c,d){function e(){this.$id=ya();this.$$phase=this.$parent=this.$$watchers=this.$$nextSibling=this.$$prevSibling=this.$$childHead=this.$$childTail=null;this["this"]=this.$root=this;this.$$destroyed=!1;this.$$asyncQueue=[];this.$$listeners={};this.$$isolateBindings={}}function g(a){if(j.$$phase)throw Error(j.$$phase+" already in progress");j.$$phase=a}function h(a,b){var c=d(a);ra(c,b);return c}function f(){}e.prototype={$new:function(a){if(H(a))throw Error("API-CHANGE: Use $controller to instantiate controllers.");
+a?(a=new e,a.$root=this.$root):(a=function(){},a.prototype=this,a=new a,a.$id=ya());a["this"]=a;a.$$listeners={};a.$parent=this;a.$$asyncQueue=[];a.$$watchers=a.$$nextSibling=a.$$childHead=a.$$childTail=null;a.$$prevSibling=this.$$childTail;this.$$childHead?this.$$childTail=this.$$childTail.$$nextSibling=a:this.$$childHead=this.$$childTail=a;return a},$watch:function(a,b,c){var d=h(a,"watch"),e=this.$$watchers,g={fn:b,last:f,get:d,exp:a,eq:!!c};if(!H(b)){var j=h(b||C,"listener");g.fn=function(a,b,
+c){j(c)}}if(!e)e=this.$$watchers=[];e.unshift(g);return function(){Ta(e,g)}},$digest:function(){var a,d,e,h,t,o,p,s=b,n,F=[],z,q;g("$digest");do{p=!1;n=this;do{for(t=n.$$asyncQueue;t.length;)try{n.$eval(t.shift())}catch(K){c(K)}if(h=n.$$watchers)for(o=h.length;o--;)try{if(a=h[o],(d=a.get(n))!==(e=a.last)&&!(a.eq?ga(d,e):typeof d=="number"&&typeof e=="number"&&isNaN(d)&&isNaN(e)))p=!0,a.last=a.eq?U(d):d,a.fn(d,e===f?d:e,n),s<5&&(z=4-s,F[z]||(F[z]=[]),q=H(a.exp)?"fn: "+(a.exp.name||a.exp.toString()):
+a.exp,q+="; newVal: "+da(d)+"; oldVal: "+da(e),F[z].push(q))}catch(r){c(r)}if(!(h=n.$$childHead||n!==this&&n.$$nextSibling))for(;n!==this&&!(h=n.$$nextSibling);)n=n.$parent}while(n=h);if(p&&!s--)throw j.$$phase=null,Error(b+" $digest() iterations reached. Aborting!\nWatchers fired in the last 5 iterations: "+da(F));}while(p||t.length);j.$$phase=null},$destroy:function(){if(!(j==this||this.$$destroyed)){var a=this.$parent;this.$broadcast("$destroy");this.$$destroyed=!0;if(a.$$childHead==this)a.$$childHead=
+this.$$nextSibling;if(a.$$childTail==this)a.$$childTail=this.$$prevSibling;if(this.$$prevSibling)this.$$prevSibling.$$nextSibling=this.$$nextSibling;if(this.$$nextSibling)this.$$nextSibling.$$prevSibling=this.$$prevSibling;this.$parent=this.$$nextSibling=this.$$prevSibling=this.$$childHead=this.$$childTail=null}},$eval:function(a,b){return d(a)(this,b)},$evalAsync:function(a){this.$$asyncQueue.push(a)},$apply:function(a){try{return g("$apply"),this.$eval(a)}catch(b){c(b)}finally{j.$$phase=null;try{j.$digest()}catch(d){throw c(d),
+d;}}},$on:function(a,b){var c=this.$$listeners[a];c||(this.$$listeners[a]=c=[]);c.push(b);return function(){c[Aa(c,b)]=null}},$emit:function(a,b){var d=[],e,f=this,g=!1,h={name:a,targetScope:f,stopPropagation:function(){g=!0},preventDefault:function(){h.defaultPrevented=!0},defaultPrevented:!1},j=[h].concat(ha.call(arguments,1)),n,q;do{e=f.$$listeners[a]||d;h.currentScope=f;n=0;for(q=e.length;n<q;n++)if(e[n])try{if(e[n].apply(null,j),g)return h}catch(z){c(z)}else e.splice(n,1),n--,q--;f=f.$parent}while(f);
+return h},$broadcast:function(a,b){var d=this,e=this,f={name:a,targetScope:this,preventDefault:function(){f.defaultPrevented=!0},defaultPrevented:!1},g=[f].concat(ha.call(arguments,1)),h,j;do{d=e;f.currentScope=d;e=d.$$listeners[a]||[];h=0;for(j=e.length;h<j;h++)if(e[h])try{e[h].apply(null,g)}catch(n){c(n)}else e.splice(h,1),h--,j--;if(!(e=d.$$childHead||d!==this&&d.$$nextSibling))for(;d!==this&&!(e=d.$$nextSibling);)d=d.$parent}while(d=e);return f}};var j=new e;return j}]}function Tc(){this.$get=
+["$window",function(b){var a={},c=E((/android (\d+)/.exec(y(b.navigator.userAgent))||[])[1]);return{history:!(!b.history||!b.history.pushState||c<4),hashchange:"onhashchange"in b&&(!b.document.documentMode||b.document.documentMode>7),hasEvent:function(c){if(c=="input"&&Z==9)return!1;if(w(a[c])){var e=b.document.createElement("div");a[c]="on"+c in e}return a[c]},csp:!1}}]}function Uc(){this.$get=I(X)}function Nb(b){var a={},c,d,e;if(!b)return a;n(b.split("\n"),function(b){e=b.indexOf(":");c=y(O(b.substr(0,
+e)));d=O(b.substr(e+1));c&&(a[c]?a[c]+=", "+d:a[c]=d)});return a}function Ob(b){var a=M(b)?b:q;return function(c){a||(a=Nb(b));return c?a[y(c)]||null:a}}function Pb(b,a,c){if(H(c))return c(b,a);n(c,function(c){b=c(b,a)});return b}function Vc(){var b=/^\s*(\[|\{[^\{])/,a=/[\}\]]\s*$/,c=/^\)\]\}',?\n/,d=this.defaults={transformResponse:[function(d){A(d)&&(d=d.replace(c,""),b.test(d)&&a.test(d)&&(d=ob(d,!0)));return d}],transformRequest:[function(a){return M(a)&&xa.apply(a)!=="[object File]"?da(a):a}],
+headers:{common:{Accept:"application/json, text/plain, */*","X-Requested-With":"XMLHttpRequest"},post:{"Content-Type":"application/json;charset=utf-8"},put:{"Content-Type":"application/json;charset=utf-8"}}},e=this.responseInterceptors=[];this.$get=["$httpBackend","$browser","$cacheFactory","$rootScope","$q","$injector",function(a,b,c,j,i,k){function m(a){function c(a){var b=v({},a,{data:Pb(a.data,a.headers,f)});return 200<=a.status&&a.status<300?b:i.reject(b)}a.method=ma(a.method);var e=a.transformRequest||
+d.transformRequest,f=a.transformResponse||d.transformResponse,g=d.headers,g=v({"X-XSRF-TOKEN":b.cookies()["XSRF-TOKEN"]},g.common,g[y(a.method)],a.headers),e=Pb(a.data,Ob(g),e),j;w(a.data)&&delete g["Content-Type"];j=l(a,e,g);j=j.then(c,c);n(p,function(a){j=a(j)});j.success=function(b){j.then(function(c){b(c.data,c.status,c.headers,a)});return j};j.error=function(b){j.then(null,function(c){b(c.data,c.status,c.headers,a)});return j};return j}function l(b,c,d){function e(a,b,c){n&&(200<=a&&a<300?n.put(q,
+[a,b,Nb(c)]):n.remove(q));f(b,a,c);j.$apply()}function f(a,c,d){c=Math.max(c,0);(200<=c&&c<300?k.resolve:k.reject)({data:a,status:c,headers:Ob(d),config:b})}function h(){var a=Aa(m.pendingRequests,b);a!==-1&&m.pendingRequests.splice(a,1)}var k=i.defer(),l=k.promise,n,p,q=t(b.url,b.params);m.pendingRequests.push(b);l.then(h,h);b.cache&&b.method=="GET"&&(n=M(b.cache)?b.cache:o);if(n)if(p=n.get(q))if(p.then)return p.then(h,h),p;else B(p)?f(p[1],p[0],U(p[2])):f(p,200,{});else n.put(q,l);p||a(b.method,
+q,c,e,d,b.timeout,b.withCredentials);return l}function t(a,b){if(!b)return a;var c=[];fc(b,function(a,b){a==null||a==q||(M(a)&&(a=da(a)),c.push(encodeURIComponent(b)+"="+encodeURIComponent(a)))});return a+(a.indexOf("?")==-1?"?":"&")+c.join("&")}var o=c("$http"),p=[];n(e,function(a){p.push(A(a)?k.get(a):k.invoke(a))});m.pendingRequests=[];(function(a){n(arguments,function(a){m[a]=function(b,c){return m(v(c||{},{method:a,url:b}))}})})("get","delete","head","jsonp");(function(a){n(arguments,function(a){m[a]=
+function(b,c,d){return m(v(d||{},{method:a,url:b,data:c}))}})})("post","put");m.defaults=d;return m}]}function Wc(){this.$get=["$browser","$window","$document",function(b,a,c){return Xc(b,Yc,b.defer,a.angular.callbacks,c[0],a.location.protocol.replace(":",""))}]}function Xc(b,a,c,d,e,g){function h(a,b){var c=e.createElement("script"),d=function(){e.body.removeChild(c);b&&b()};c.type="text/javascript";c.src=a;Z?c.onreadystatechange=function(){/loaded|complete/.test(c.readyState)&&d()}:c.onload=c.onerror=
+d;e.body.appendChild(c)}return function(e,j,i,k,m,l,t){function o(a,c,d,e){c=(j.match(Gb)||["",g])[1]=="file"?d?200:404:c;a(c==1223?204:c,d,e);b.$$completeOutstandingRequest(C)}b.$$incOutstandingRequestCount();j=j||b.url();if(y(e)=="jsonp"){var p="_"+(d.counter++).toString(36);d[p]=function(a){d[p].data=a};h(j.replace("JSON_CALLBACK","angular.callbacks."+p),function(){d[p].data?o(k,200,d[p].data):o(k,-2);delete d[p]})}else{var s=new a;s.open(e,j,!0);n(m,function(a,b){a&&s.setRequestHeader(b,a)});
+var q;s.onreadystatechange=function(){if(s.readyState==4){var a=s.getAllResponseHeaders(),b=["Cache-Control","Content-Language","Content-Type","Expires","Last-Modified","Pragma"];a||(a="",n(b,function(b){var c=s.getResponseHeader(b);c&&(a+=b+": "+c+"\n")}));o(k,q||s.status,s.responseText,a)}};if(t)s.withCredentials=!0;s.send(i||"");l>0&&c(function(){q=-1;s.abort()},l)}}}function Zc(){this.$get=function(){return{id:"en-us",NUMBER_FORMATS:{DECIMAL_SEP:".",GROUP_SEP:",",PATTERNS:[{minInt:1,minFrac:0,
+maxFrac:3,posPre:"",posSuf:"",negPre:"-",negSuf:"",gSize:3,lgSize:3},{minInt:1,minFrac:2,maxFrac:2,posPre:"\u00a4",posSuf:"",negPre:"(\u00a4",negSuf:")",gSize:3,lgSize:3}],CURRENCY_SYM:"$"},DATETIME_FORMATS:{MONTH:"January,February,March,April,May,June,July,August,September,October,November,December".split(","),SHORTMONTH:"Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec".split(","),DAY:"Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday".split(","),SHORTDAY:"Sun,Mon,Tue,Wed,Thu,Fri,Sat".split(","),
+AMPMS:["AM","PM"],medium:"MMM d, y h:mm:ss a","short":"M/d/yy h:mm a",fullDate:"EEEE, MMMM d, y",longDate:"MMMM d, y",mediumDate:"MMM d, y",shortDate:"M/d/yy",mediumTime:"h:mm:ss a",shortTime:"h:mm a"},pluralCat:function(b){return b===1?"one":"other"}}}}function $c(){this.$get=["$rootScope","$browser","$q","$exceptionHandler",function(b,a,c,d){function e(e,f,j){var i=c.defer(),k=i.promise,m=x(j)&&!j,f=a.defer(function(){try{i.resolve(e())}catch(a){i.reject(a),d(a)}m||b.$apply()},f),j=function(){delete g[k.$$timeoutId]};
+k.$$timeoutId=f;g[f]=i;k.then(j,j);return k}var g={};e.cancel=function(b){return b&&b.$$timeoutId in g?(g[b.$$timeoutId].reject("canceled"),a.defer.cancel(b.$$timeoutId)):!1};return e}]}function Qb(b){function a(a,e){return b.factory(a+c,e)}var c="Filter";this.register=a;this.$get=["$injector",function(a){return function(b){return a.get(b+c)}}];a("currency",Rb);a("date",Sb);a("filter",ad);a("json",bd);a("limitTo",cd);a("lowercase",dd);a("number",Tb);a("orderBy",Ub);a("uppercase",ed)}function ad(){return function(b,
+a){if(!B(b))return b;var c=[];c.check=function(a){for(var b=0;b<c.length;b++)if(!c[b](a))return!1;return!0};var d=function(a,b){if(b.charAt(0)==="!")return!d(a,b.substr(1));switch(typeof a){case "boolean":case "number":case "string":return(""+a).toLowerCase().indexOf(b)>-1;case "object":for(var c in a)if(c.charAt(0)!=="$"&&d(a[c],b))return!0;return!1;case "array":for(c=0;c<a.length;c++)if(d(a[c],b))return!0;return!1;default:return!1}};switch(typeof a){case "boolean":case "number":case "string":a=
+{$:a};case "object":for(var e in a)e=="$"?function(){var b=(""+a[e]).toLowerCase();b&&c.push(function(a){return d(a,b)})}():function(){var b=e,f=(""+a[e]).toLowerCase();f&&c.push(function(a){return d(gb(a,b),f)})}();break;case "function":c.push(a);break;default:return b}for(var g=[],h=0;h<b.length;h++){var f=b[h];c.check(f)&&g.push(f)}return g}}function Rb(b){var a=b.NUMBER_FORMATS;return function(b,d){if(w(d))d=a.CURRENCY_SYM;return Vb(b,a.PATTERNS[1],a.GROUP_SEP,a.DECIMAL_SEP,2).replace(/\u00A4/g,
+d)}}function Tb(b){var a=b.NUMBER_FORMATS;return function(b,d){return Vb(b,a.PATTERNS[0],a.GROUP_SEP,a.DECIMAL_SEP,d)}}function Vb(b,a,c,d,e){if(isNaN(b)||!isFinite(b))return"";var g=b<0,b=Math.abs(b),h=b+"",f="",j=[],i=!1;if(h.indexOf("e")!==-1){var k=h.match(/([\d\.]+)e(-?)(\d+)/);k&&k[2]=="-"&&k[3]>e+1?h="0":(f=h,i=!0)}if(!i){h=(h.split(Wb)[1]||"").length;w(e)&&(e=Math.min(Math.max(a.minFrac,h),a.maxFrac));var h=Math.pow(10,e),b=Math.round(b*h)/h,b=(""+b).split(Wb),h=b[0],b=b[1]||"",i=0,k=a.lgSize,
+m=a.gSize;if(h.length>=k+m)for(var i=h.length-k,l=0;l<i;l++)(i-l)%m===0&&l!==0&&(f+=c),f+=h.charAt(l);for(l=i;l<h.length;l++)(h.length-l)%k===0&&l!==0&&(f+=c),f+=h.charAt(l);for(;b.length<e;)b+="0";e&&e!=="0"&&(f+=d+b.substr(0,e))}j.push(g?a.negPre:a.posPre);j.push(f);j.push(g?a.negSuf:a.posSuf);return j.join("")}function jb(b,a,c){var d="";b<0&&(d="-",b=-b);for(b=""+b;b.length<a;)b="0"+b;c&&(b=b.substr(b.length-a));return d+b}function N(b,a,c,d){return function(e){e=e["get"+b]();if(c>0||e>-c)e+=
+c;e===0&&c==-12&&(e=12);return jb(e,a,d)}}function Ka(b,a){return function(c,d){var e=c["get"+b](),g=ma(a?"SHORT"+b:b);return d[g][e]}}function Sb(b){function a(a){var b;if(b=a.match(c)){var a=new Date(0),g=0,h=0;b[9]&&(g=E(b[9]+b[10]),h=E(b[9]+b[11]));a.setUTCFullYear(E(b[1]),E(b[2])-1,E(b[3]));a.setUTCHours(E(b[4]||0)-g,E(b[5]||0)-h,E(b[6]||0),E(b[7]||0))}return a}var c=/^(\d{4})-?(\d\d)-?(\d\d)(?:T(\d\d)(?::?(\d\d)(?::?(\d\d)(?:\.(\d+))?)?)?(Z|([+-])(\d\d):?(\d\d))?)?$/;return function(c,e){var g=
+"",h=[],f,j,e=e||"mediumDate",e=b.DATETIME_FORMATS[e]||e;A(c)&&(c=fd.test(c)?E(c):a(c));Ra(c)&&(c=new Date(c));if(!oa(c))return c;for(;e;)(j=gd.exec(e))?(h=h.concat(ha.call(j,1)),e=h.pop()):(h.push(e),e=null);n(h,function(a){f=hd[a];g+=f?f(c,b.DATETIME_FORMATS):a.replace(/(^'|'$)/g,"").replace(/''/g,"'")});return g}}function bd(){return function(b){return da(b,!0)}}function cd(){return function(b,a){if(!(b instanceof Array))return b;var a=E(a),c=[],d,e;if(!b||!(b instanceof Array))return c;a>b.length?
+a=b.length:a<-b.length&&(a=-b.length);a>0?(d=0,e=a):(d=b.length+a,e=b.length);for(;d<e;d++)c.push(b[d]);return c}}function Ub(b){return function(a,c,d){function e(a,b){return Va(b)?function(b,c){return a(c,b)}:a}if(!B(a))return a;if(!c)return a;for(var c=B(c)?c:[c],c=Sa(c,function(a){var c=!1,d=a||na;if(A(a)){if(a.charAt(0)=="+"||a.charAt(0)=="-")c=a.charAt(0)=="-",a=a.substring(1);d=b(a)}return e(function(a,b){var c;c=d(a);var e=d(b),f=typeof c,g=typeof e;f==g?(f=="string"&&(c=c.toLowerCase()),f==
+"string"&&(e=e.toLowerCase()),c=c===e?0:c<e?-1:1):c=f<g?-1:1;return c},c)}),g=[],h=0;h<a.length;h++)g.push(a[h]);return g.sort(e(function(a,b){for(var d=0;d<c.length;d++){var e=c[d](a,b);if(e!==0)return e}return 0},d))}}function Q(b){H(b)&&(b={link:b});b.restrict=b.restrict||"AC";return I(b)}function Xb(b,a){function c(a,c){c=c?"-"+Za(c,"-"):"";b.removeClass((a?La:Ma)+c).addClass((a?Ma:La)+c)}var d=this,e=b.parent().controller("form")||Na,g=0,h=d.$error={};d.$name=a.name;d.$dirty=!1;d.$pristine=!0;
+d.$valid=!0;d.$invalid=!1;e.$addControl(d);b.addClass(Oa);c(!0);d.$addControl=function(a){a.$name&&!d.hasOwnProperty(a.$name)&&(d[a.$name]=a)};d.$removeControl=function(a){a.$name&&d[a.$name]===a&&delete d[a.$name];n(h,function(b,c){d.$setValidity(c,!0,a)})};d.$setValidity=function(a,b,i){var k=h[a];if(b){if(k&&(Ta(k,i),!k.length)){g--;if(!g)c(b),d.$valid=!0,d.$invalid=!1;h[a]=!1;c(!0,a);e.$setValidity(a,!0,d)}}else{g||c(b);if(k){if(Aa(k,i)!=-1)return}else h[a]=k=[],g++,c(!1,a),e.$setValidity(a,!1,
+d);k.push(i);d.$valid=!1;d.$invalid=!0}};d.$setDirty=function(){b.removeClass(Oa).addClass(Yb);d.$dirty=!0;d.$pristine=!1;e.$setDirty()}}function T(b){return w(b)||b===""||b===null||b!==b}function Pa(b,a,c,d,e,g){var h=function(){var c=O(a.val());d.$viewValue!==c&&b.$apply(function(){d.$setViewValue(c)})};if(e.hasEvent("input"))a.bind("input",h);else{var f;a.bind("keydown",function(a){a=a.keyCode;a===91||15<a&&a<19||37<=a&&a<=40||f||(f=g.defer(function(){h();f=null}))});a.bind("change",h)}d.$render=
+function(){a.val(T(d.$viewValue)?"":d.$viewValue)};var j=c.ngPattern,i=function(a,b){return T(b)||a.test(b)?(d.$setValidity("pattern",!0),b):(d.$setValidity("pattern",!1),q)};j&&(j.match(/^\/(.*)\/$/)?(j=RegExp(j.substr(1,j.length-2)),e=function(a){return i(j,a)}):e=function(a){var c=b.$eval(j);if(!c||!c.test)throw Error("Expected "+j+" to be a RegExp but was "+c);return i(c,a)},d.$formatters.push(e),d.$parsers.push(e));if(c.ngMinlength){var k=E(c.ngMinlength),e=function(a){return!T(a)&&a.length<
+k?(d.$setValidity("minlength",!1),q):(d.$setValidity("minlength",!0),a)};d.$parsers.push(e);d.$formatters.push(e)}if(c.ngMaxlength){var m=E(c.ngMaxlength),c=function(a){return!T(a)&&a.length>m?(d.$setValidity("maxlength",!1),q):(d.$setValidity("maxlength",!0),a)};d.$parsers.push(c);d.$formatters.push(c)}}function kb(b,a){b="ngClass"+b;return Q(function(c,d,e){function g(b){if(a===!0||c.$index%2===a)j&&b!==j&&h(j),f(b);j=b}function h(a){M(a)&&!B(a)&&(a=Sa(a,function(a,b){if(a)return b}));d.removeClass(B(a)?
+a.join(" "):a)}function f(a){M(a)&&!B(a)&&(a=Sa(a,function(a,b){if(a)return b}));a&&d.addClass(B(a)?a.join(" "):a)}var j=q;c.$watch(e[b],g,!0);e.$observe("class",function(){var a=c.$eval(e[b]);g(a,a)});b!=="ngClass"&&c.$watch("$index",function(d,g){var j=d%2;j!==g%2&&(j==a?f(c.$eval(e[b])):h(c.$eval(e[b])))})})}var y=function(b){return A(b)?b.toLowerCase():b},ma=function(b){return A(b)?b.toUpperCase():b},Z=E((/msie (\d+)/.exec(y(navigator.userAgent))||[])[1]),u,ca,ha=[].slice,Qa=[].push,xa=Object.prototype.toString,
+Zb=X.angular||(X.angular={}),ta,fb,aa=["0","0","0"];C.$inject=[];na.$inject=[];fb=Z<9?function(b){b=b.nodeName?b:b[0];return b.scopeName&&b.scopeName!="HTML"?ma(b.scopeName+":"+b.nodeName):b.nodeName}:function(b){return b.nodeName?b.nodeName:b[0].nodeName};var kc=/[A-Z]/g,id={full:"1.0.5",major:1,minor:0,dot:5,codeName:"flatulent-propulsion"},Ca=L.cache={},Ba=L.expando="ng-"+(new Date).getTime(),oc=1,$b=X.document.addEventListener?function(b,a,c){b.addEventListener(a,c,!1)}:function(b,a,c){b.attachEvent("on"+
+a,c)},db=X.document.removeEventListener?function(b,a,c){b.removeEventListener(a,c,!1)}:function(b,a,c){b.detachEvent("on"+a,c)},mc=/([\:\-\_]+(.))/g,nc=/^moz([A-Z])/,va=L.prototype={ready:function(b){function a(){c||(c=!0,b())}var c=!1;this.bind("DOMContentLoaded",a);L(X).bind("load",a)},toString:function(){var b=[];n(this,function(a){b.push(""+a)});return"["+b.join(", ")+"]"},eq:function(b){return b>=0?u(this[b]):u(this[this.length+b])},length:0,push:Qa,sort:[].sort,splice:[].splice},Fa={};n("multiple,selected,checked,disabled,readOnly,required".split(","),
+function(b){Fa[y(b)]=b});var Ab={};n("input,select,option,textarea,button,form".split(","),function(b){Ab[ma(b)]=!0});n({data:vb,inheritedData:Ea,scope:function(b){return Ea(b,"$scope")},controller:yb,injector:function(b){return Ea(b,"$injector")},removeAttr:function(b,a){b.removeAttribute(a)},hasClass:Da,css:function(b,a,c){a=sb(a);if(x(c))b.style[a]=c;else{var d;Z<=8&&(d=b.currentStyle&&b.currentStyle[a],d===""&&(d="auto"));d=d||b.style[a];Z<=8&&(d=d===""?q:d);return d}},attr:function(b,a,c){var d=
+y(a);if(Fa[d])if(x(c))c?(b[a]=!0,b.setAttribute(a,d)):(b[a]=!1,b.removeAttribute(d));else return b[a]||(b.attributes.getNamedItem(a)||C).specified?d:q;else if(x(c))b.setAttribute(a,c);else if(b.getAttribute)return b=b.getAttribute(a,2),b===null?q:b},prop:function(b,a,c){if(x(c))b[a]=c;else return b[a]},text:v(Z<9?function(b,a){if(b.nodeType==1){if(w(a))return b.innerText;b.innerText=a}else{if(w(a))return b.nodeValue;b.nodeValue=a}}:function(b,a){if(w(a))return b.textContent;b.textContent=a},{$dv:""}),
+val:function(b,a){if(w(a))return b.value;b.value=a},html:function(b,a){if(w(a))return b.innerHTML;for(var c=0,d=b.childNodes;c<d.length;c++)sa(d[c]);b.innerHTML=a}},function(b,a){L.prototype[a]=function(a,d){var e,g;if((b.length==2&&b!==Da&&b!==yb?a:d)===q)if(M(a)){for(e=0;e<this.length;e++)if(b===vb)b(this[e],a);else for(g in a)b(this[e],g,a[g]);return this}else{if(this.length)return b(this[0],a,d)}else{for(e=0;e<this.length;e++)b(this[e],a,d);return this}return b.$dv}});n({removeData:tb,dealoc:sa,
+bind:function a(c,d,e){var g=ba(c,"events"),h=ba(c,"handle");g||ba(c,"events",g={});h||ba(c,"handle",h=pc(c,g));n(d.split(" "),function(d){var j=g[d];if(!j){if(d=="mouseenter"||d=="mouseleave"){var i=0;g.mouseenter=[];g.mouseleave=[];a(c,"mouseover",function(a){i++;i==1&&h(a,"mouseenter")});a(c,"mouseout",function(a){i--;i==0&&h(a,"mouseleave")})}else $b(c,d,h),g[d]=[];j=g[d]}j.push(e)})},unbind:ub,replaceWith:function(a,c){var d,e=a.parentNode;sa(a);n(new L(c),function(c){d?e.insertBefore(c,d.nextSibling):
+e.replaceChild(c,a);d=c})},children:function(a){var c=[];n(a.childNodes,function(a){a.nodeType===1&&c.push(a)});return c},contents:function(a){return a.childNodes||[]},append:function(a,c){n(new L(c),function(c){a.nodeType===1&&a.appendChild(c)})},prepend:function(a,c){if(a.nodeType===1){var d=a.firstChild;n(new L(c),function(c){d?a.insertBefore(c,d):(a.appendChild(c),d=c)})}},wrap:function(a,c){var c=u(c)[0],d=a.parentNode;d&&d.replaceChild(c,a);c.appendChild(a)},remove:function(a){sa(a);var c=a.parentNode;
+c&&c.removeChild(a)},after:function(a,c){var d=a,e=a.parentNode;n(new L(c),function(a){e.insertBefore(a,d.nextSibling);d=a})},addClass:xb,removeClass:wb,toggleClass:function(a,c,d){w(d)&&(d=!Da(a,c));(d?xb:wb)(a,c)},parent:function(a){return(a=a.parentNode)&&a.nodeType!==11?a:null},next:function(a){if(a.nextElementSibling)return a.nextElementSibling;for(a=a.nextSibling;a!=null&&a.nodeType!==1;)a=a.nextSibling;return a},find:function(a,c){return a.getElementsByTagName(c)},clone:cb,triggerHandler:function(a,
+c){var d=(ba(a,"events")||{})[c];n(d,function(c){c.call(a,null)})}},function(a,c){L.prototype[c]=function(c,e){for(var g,h=0;h<this.length;h++)g==q?(g=a(this[h],c,e),g!==q&&(g=u(g))):bb(g,a(this[h],c,e));return g==q?this:g}});Ga.prototype={put:function(a,c){this[fa(a)]=c},get:function(a){return this[fa(a)]},remove:function(a){var c=this[a=fa(a)];delete this[a];return c}};eb.prototype={push:function(a,c){var d=this[a=fa(a)];d?d.push(c):this[a]=[c]},shift:function(a){var c=this[a=fa(a)];if(c)return c.length==
+1?(delete this[a],c[0]):c.shift()},peek:function(a){if(a=this[fa(a)])return a[0]}};var rc=/^function\s*[^\(]*\(\s*([^\)]*)\)/m,sc=/,/,tc=/^\s*(_?)(\S+?)\1\s*$/,qc=/((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg,Db="Non-assignable model expression: ";Cb.$inject=["$provide"];var Ac=/^(x[\:\-_]|data[\:\-_])/i,Gb=/^([^:]+):\/\/(\w+:{0,1}\w*@)?([\w\.-]*)(:([0-9]+))?(\/[^\?#]*)?(\?([^#]*))?(#(.*))?$/,ac=/^([^\?#]*)?(\?([^#]*))?(#(.*))?$/,Hc=ac,Hb={http:80,https:443,ftp:21};hb.prototype={$$replace:!1,absUrl:Ia("$$absUrl"),
+url:function(a,c){if(w(a))return this.$$url;var d=ac.exec(a);d[1]&&this.path(decodeURIComponent(d[1]));if(d[2]||d[1])this.search(d[3]||"");this.hash(d[5]||"",c);return this},protocol:Ia("$$protocol"),host:Ia("$$host"),port:Ia("$$port"),path:Jb("$$path",function(a){return a.charAt(0)=="/"?a:"/"+a}),search:function(a,c){if(w(a))return this.$$search;x(c)?c===null?delete this.$$search[a]:this.$$search[a]=c:this.$$search=A(a)?Wa(a):a;this.$$compose();return this},hash:Jb("$$hash",na),replace:function(){this.$$replace=
+!0;return this}};Ha.prototype=za(hb.prototype);Ib.prototype=za(Ha.prototype);var Ja={"null":function(){return null},"true":function(){return!0},"false":function(){return!1},undefined:C,"+":function(a,c,d,e){d=d(a,c);e=e(a,c);return x(d)?x(e)?d+e:d:x(e)?e:q},"-":function(a,c,d,e){d=d(a,c);e=e(a,c);return(x(d)?d:0)-(x(e)?e:0)},"*":function(a,c,d,e){return d(a,c)*e(a,c)},"/":function(a,c,d,e){return d(a,c)/e(a,c)},"%":function(a,c,d,e){return d(a,c)%e(a,c)},"^":function(a,c,d,e){return d(a,c)^e(a,c)},
+"=":C,"==":function(a,c,d,e){return d(a,c)==e(a,c)},"!=":function(a,c,d,e){return d(a,c)!=e(a,c)},"<":function(a,c,d,e){return d(a,c)<e(a,c)},">":function(a,c,d,e){return d(a,c)>e(a,c)},"<=":function(a,c,d,e){return d(a,c)<=e(a,c)},">=":function(a,c,d,e){return d(a,c)>=e(a,c)},"&&":function(a,c,d,e){return d(a,c)&&e(a,c)},"||":function(a,c,d,e){return d(a,c)||e(a,c)},"&":function(a,c,d,e){return d(a,c)&e(a,c)},"|":function(a,c,d,e){return e(a,c)(a,c,d(a,c))},"!":function(a,c,d){return!d(a,c)}},Lc=
+{n:"\n",f:"\u000c",r:"\r",t:"\t",v:"\u000b","'":"'",'"':'"'},ib={},Yc=X.XMLHttpRequest||function(){try{return new ActiveXObject("Msxml2.XMLHTTP.6.0")}catch(a){}try{return new ActiveXObject("Msxml2.XMLHTTP.3.0")}catch(c){}try{return new ActiveXObject("Msxml2.XMLHTTP")}catch(d){}throw Error("This browser does not support XMLHttpRequest.");};Qb.$inject=["$provide"];Rb.$inject=["$locale"];Tb.$inject=["$locale"];var Wb=".",hd={yyyy:N("FullYear",4),yy:N("FullYear",2,0,!0),y:N("FullYear",1),MMMM:Ka("Month"),
+MMM:Ka("Month",!0),MM:N("Month",2,1),M:N("Month",1,1),dd:N("Date",2),d:N("Date",1),HH:N("Hours",2),H:N("Hours",1),hh:N("Hours",2,-12),h:N("Hours",1,-12),mm:N("Minutes",2),m:N("Minutes",1),ss:N("Seconds",2),s:N("Seconds",1),EEEE:Ka("Day"),EEE:Ka("Day",!0),a:function(a,c){return a.getHours()<12?c.AMPMS[0]:c.AMPMS[1]},Z:function(a){var a=-1*a.getTimezoneOffset(),c=a>=0?"+":"";c+=jb(a/60,2)+jb(Math.abs(a%60),2);return c}},gd=/((?:[^yMdHhmsaZE']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d+|H+|h+|m+|s+|a|Z))(.*)/,
+fd=/^\d+$/;Sb.$inject=["$locale"];var dd=I(y),ed=I(ma);Ub.$inject=["$parse"];var jd=I({restrict:"E",compile:function(a,c){Z<=8&&(!c.href&&!c.name&&c.$set("href",""),a.append(Y.createComment("IE fix")));return function(a,c){c.bind("click",function(a){c.attr("href")||a.preventDefault()})}}}),lb={};n(Fa,function(a,c){var d=ea("ng-"+c);lb[d]=function(){return{priority:100,compile:function(){return function(a,g,h){a.$watch(h[d],function(a){h.$set(c,!!a)})}}}}});n(["src","href"],function(a){var c=ea("ng-"+
+a);lb[c]=function(){return{priority:99,link:function(d,e,g){g.$observe(c,function(c){c&&(g.$set(a,c),Z&&e.prop(a,g[a]))})}}}});var Na={$addControl:C,$removeControl:C,$setValidity:C,$setDirty:C};Xb.$inject=["$element","$attrs","$scope"];var Qa=function(a){return["$timeout",function(c){var d={name:"form",restrict:"E",controller:Xb,compile:function(){return{pre:function(a,d,h,f){if(!h.action){var j=function(a){a.preventDefault?a.preventDefault():a.returnValue=!1};$b(d[0],"submit",j);d.bind("$destroy",
+function(){c(function(){db(d[0],"submit",j)},0,!1)})}var i=d.parent().controller("form"),k=h.name||h.ngForm;k&&(a[k]=f);i&&d.bind("$destroy",function(){i.$removeControl(f);k&&(a[k]=q);v(f,Na)})}}}};return a?v(U(d),{restrict:"EAC"}):d}]},kd=Qa(),ld=Qa(!0),md=/^(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?$/,nd=/^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,4}$/,od=/^\s*(\-|\+)?(\d+|(\d*(\.\d*)))\s*$/,bc={text:Pa,number:function(a,c,d,e,g,h){Pa(a,c,d,e,g,h);e.$parsers.push(function(a){var c=
+T(a);return c||od.test(a)?(e.$setValidity("number",!0),a===""?null:c?a:parseFloat(a)):(e.$setValidity("number",!1),q)});e.$formatters.push(function(a){return T(a)?"":""+a});if(d.min){var f=parseFloat(d.min),a=function(a){return!T(a)&&a<f?(e.$setValidity("min",!1),q):(e.$setValidity("min",!0),a)};e.$parsers.push(a);e.$formatters.push(a)}if(d.max){var j=parseFloat(d.max),d=function(a){return!T(a)&&a>j?(e.$setValidity("max",!1),q):(e.$setValidity("max",!0),a)};e.$parsers.push(d);e.$formatters.push(d)}e.$formatters.push(function(a){return T(a)||
+Ra(a)?(e.$setValidity("number",!0),a):(e.$setValidity("number",!1),q)})},url:function(a,c,d,e,g,h){Pa(a,c,d,e,g,h);a=function(a){return T(a)||md.test(a)?(e.$setValidity("url",!0),a):(e.$setValidity("url",!1),q)};e.$formatters.push(a);e.$parsers.push(a)},email:function(a,c,d,e,g,h){Pa(a,c,d,e,g,h);a=function(a){return T(a)||nd.test(a)?(e.$setValidity("email",!0),a):(e.$setValidity("email",!1),q)};e.$formatters.push(a);e.$parsers.push(a)},radio:function(a,c,d,e){w(d.name)&&c.attr("name",ya());c.bind("click",
+function(){c[0].checked&&a.$apply(function(){e.$setViewValue(d.value)})});e.$render=function(){c[0].checked=d.value==e.$viewValue};d.$observe("value",e.$render)},checkbox:function(a,c,d,e){var g=d.ngTrueValue,h=d.ngFalseValue;A(g)||(g=!0);A(h)||(h=!1);c.bind("click",function(){a.$apply(function(){e.$setViewValue(c[0].checked)})});e.$render=function(){c[0].checked=e.$viewValue};e.$formatters.push(function(a){return a===g});e.$parsers.push(function(a){return a?g:h})},hidden:C,button:C,submit:C,reset:C},
+cc=["$browser","$sniffer",function(a,c){return{restrict:"E",require:"?ngModel",link:function(d,e,g,h){h&&(bc[y(g.type)]||bc.text)(d,e,g,h,c,a)}}}],Ma="ng-valid",La="ng-invalid",Oa="ng-pristine",Yb="ng-dirty",pd=["$scope","$exceptionHandler","$attrs","$element","$parse",function(a,c,d,e,g){function h(a,c){c=c?"-"+Za(c,"-"):"";e.removeClass((a?La:Ma)+c).addClass((a?Ma:La)+c)}this.$modelValue=this.$viewValue=Number.NaN;this.$parsers=[];this.$formatters=[];this.$viewChangeListeners=[];this.$pristine=
+!0;this.$dirty=!1;this.$valid=!0;this.$invalid=!1;this.$name=d.name;var f=g(d.ngModel),j=f.assign;if(!j)throw Error(Db+d.ngModel+" ("+qa(e)+")");this.$render=C;var i=e.inheritedData("$formController")||Na,k=0,m=this.$error={};e.addClass(Oa);h(!0);this.$setValidity=function(a,c){if(m[a]!==!c){if(c){if(m[a]&&k--,!k)h(!0),this.$valid=!0,this.$invalid=!1}else h(!1),this.$invalid=!0,this.$valid=!1,k++;m[a]=!c;h(c,a);i.$setValidity(a,c,this)}};this.$setViewValue=function(d){this.$viewValue=d;if(this.$pristine)this.$dirty=
+!0,this.$pristine=!1,e.removeClass(Oa).addClass(Yb),i.$setDirty();n(this.$parsers,function(a){d=a(d)});if(this.$modelValue!==d)this.$modelValue=d,j(a,d),n(this.$viewChangeListeners,function(a){try{a()}catch(d){c(d)}})};var l=this;a.$watch(function(){var c=f(a);if(l.$modelValue!==c){var d=l.$formatters,e=d.length;for(l.$modelValue=c;e--;)c=d[e](c);if(l.$viewValue!==c)l.$viewValue=c,l.$render()}})}],qd=function(){return{require:["ngModel","^?form"],controller:pd,link:function(a,c,d,e){var g=e[0],h=
+e[1]||Na;h.$addControl(g);c.bind("$destroy",function(){h.$removeControl(g)})}}},rd=I({require:"ngModel",link:function(a,c,d,e){e.$viewChangeListeners.push(function(){a.$eval(d.ngChange)})}}),dc=function(){return{require:"?ngModel",link:function(a,c,d,e){if(e){d.required=!0;var g=function(a){if(d.required&&(T(a)||a===!1))e.$setValidity("required",!1);else return e.$setValidity("required",!0),a};e.$formatters.push(g);e.$parsers.unshift(g);d.$observe("required",function(){g(e.$viewValue)})}}}},sd=function(){return{require:"ngModel",
+link:function(a,c,d,e){var g=(a=/\/(.*)\//.exec(d.ngList))&&RegExp(a[1])||d.ngList||",";e.$parsers.push(function(a){var c=[];a&&n(a.split(g),function(a){a&&c.push(O(a))});return c});e.$formatters.push(function(a){return B(a)?a.join(", "):q})}}},td=/^(true|false|\d+)$/,ud=function(){return{priority:100,compile:function(a,c){return td.test(c.ngValue)?function(a,c,g){g.$set("value",a.$eval(g.ngValue))}:function(a,c,g){a.$watch(g.ngValue,function(a){g.$set("value",a,!1)})}}}},vd=Q(function(a,c,d){c.addClass("ng-binding").data("$binding",
+d.ngBind);a.$watch(d.ngBind,function(a){c.text(a==q?"":a)})}),wd=["$interpolate",function(a){return function(c,d,e){c=a(d.attr(e.$attr.ngBindTemplate));d.addClass("ng-binding").data("$binding",c);e.$observe("ngBindTemplate",function(a){d.text(a)})}}],xd=[function(){return function(a,c,d){c.addClass("ng-binding").data("$binding",d.ngBindHtmlUnsafe);a.$watch(d.ngBindHtmlUnsafe,function(a){c.html(a||"")})}}],yd=kb("",!0),zd=kb("Odd",0),Ad=kb("Even",1),Bd=Q({compile:function(a,c){c.$set("ngCloak",q);
+a.removeClass("ng-cloak")}}),Cd=[function(){return{scope:!0,controller:"@"}}],Dd=["$sniffer",function(a){return{priority:1E3,compile:function(){a.csp=!0}}}],ec={};n("click dblclick mousedown mouseup mouseover mouseout mousemove mouseenter mouseleave".split(" "),function(a){var c=ea("ng-"+a);ec[c]=["$parse",function(d){return function(e,g,h){var f=d(h[c]);g.bind(y(a),function(a){e.$apply(function(){f(e,{$event:a})})})}}]});var Ed=Q(function(a,c,d){c.bind("submit",function(){a.$apply(d.ngSubmit)})}),
+Fd=["$http","$templateCache","$anchorScroll","$compile",function(a,c,d,e){return{restrict:"ECA",terminal:!0,compile:function(g,h){var f=h.ngInclude||h.src,j=h.onload||"",i=h.autoscroll;return function(g,h){var l=0,n,o=function(){n&&(n.$destroy(),n=null);h.html("")};g.$watch(f,function(f){var s=++l;f?a.get(f,{cache:c}).success(function(a){s===l&&(n&&n.$destroy(),n=g.$new(),h.html(a),e(h.contents())(n),x(i)&&(!i||g.$eval(i))&&d(),n.$emit("$includeContentLoaded"),g.$eval(j))}).error(function(){s===l&&
+o()}):o()})}}}}],Gd=Q({compile:function(){return{pre:function(a,c,d){a.$eval(d.ngInit)}}}}),Hd=Q({terminal:!0,priority:1E3}),Id=["$locale","$interpolate",function(a,c){var d=/{}/g;return{restrict:"EA",link:function(e,g,h){var f=h.count,j=g.attr(h.$attr.when),i=h.offset||0,k=e.$eval(j),m={},l=c.startSymbol(),t=c.endSymbol();n(k,function(a,e){m[e]=c(a.replace(d,l+f+"-"+i+t))});e.$watch(function(){var c=parseFloat(e.$eval(f));return isNaN(c)?"":(k[c]||(c=a.pluralCat(c-i)),m[c](e,g,!0))},function(a){g.text(a)})}}}],
+Jd=Q({transclude:"element",priority:1E3,terminal:!0,compile:function(a,c,d){return function(a,c,h){var f=h.ngRepeat,h=f.match(/^\s*(.+)\s+in\s+(.*)\s*$/),j,i,k;if(!h)throw Error("Expected ngRepeat in form of '_item_ in _collection_' but got '"+f+"'.");f=h[1];j=h[2];h=f.match(/^(?:([\$\w]+)|\(([\$\w]+)\s*,\s*([\$\w]+)\))$/);if(!h)throw Error("'item' in 'item in collection' should be identifier or (key, value) but got '"+f+"'.");i=h[3]||h[1];k=h[2];var m=new eb;a.$watch(function(a){var e,f,h=a.$eval(j),
+n=c,q=new eb,x,z,u,w,r,v;if(B(h))r=h||[];else{r=[];for(u in h)h.hasOwnProperty(u)&&u.charAt(0)!="$"&&r.push(u);r.sort()}x=r.length;e=0;for(f=r.length;e<f;e++){u=h===r?e:r[e];w=h[u];if(v=m.shift(w)){z=v.scope;q.push(w,v);if(e!==v.index)v.index=e,n.after(v.element);n=v.element}else z=a.$new();z[i]=w;k&&(z[k]=u);z.$index=e;z.$first=e===0;z.$last=e===x-1;z.$middle=!(z.$first||z.$last);v||d(z,function(a){n.after(a);v={scope:z,element:n=a,index:e};q.push(w,v)})}for(u in m)if(m.hasOwnProperty(u))for(r=m[u];r.length;)w=
+r.pop(),w.element.remove(),w.scope.$destroy();m=q})}}}),Kd=Q(function(a,c,d){a.$watch(d.ngShow,function(a){c.css("display",Va(a)?"":"none")})}),Ld=Q(function(a,c,d){a.$watch(d.ngHide,function(a){c.css("display",Va(a)?"none":"")})}),Md=Q(function(a,c,d){a.$watch(d.ngStyle,function(a,d){d&&a!==d&&n(d,function(a,d){c.css(d,"")});a&&c.css(a)},!0)}),Nd=I({restrict:"EA",require:"ngSwitch",controller:["$scope",function(){this.cases={}}],link:function(a,c,d,e){var g,h,f;a.$watch(d.ngSwitch||d.on,function(j){h&&
+(f.$destroy(),h.remove(),h=f=null);if(g=e.cases["!"+j]||e.cases["?"])a.$eval(d.change),f=a.$new(),g(f,function(a){h=a;c.append(a)})})}}),Od=Q({transclude:"element",priority:500,require:"^ngSwitch",compile:function(a,c,d){return function(a,g,h,f){f.cases["!"+c.ngSwitchWhen]=d}}}),Pd=Q({transclude:"element",priority:500,require:"^ngSwitch",compile:function(a,c,d){return function(a,c,h,f){f.cases["?"]=d}}}),Qd=Q({controller:["$transclude","$element",function(a,c){a(function(a){c.append(a)})}]}),Rd=["$http",
+"$templateCache","$route","$anchorScroll","$compile","$controller",function(a,c,d,e,g,h){return{restrict:"ECA",terminal:!0,link:function(a,c,i){function k(){var i=d.current&&d.current.locals,k=i&&i.$template;if(k){c.html(k);m&&(m.$destroy(),m=null);var k=g(c.contents()),n=d.current;m=n.scope=a.$new();if(n.controller)i.$scope=m,i=h(n.controller,i),c.children().data("$ngControllerController",i);k(m);m.$emit("$viewContentLoaded");m.$eval(l);e()}else c.html(""),m&&(m.$destroy(),m=null)}var m,l=i.onload||
+"";a.$on("$routeChangeSuccess",k);k()}}}],Sd=["$templateCache",function(a){return{restrict:"E",terminal:!0,compile:function(c,d){d.type=="text/ng-template"&&a.put(d.id,c[0].text)}}}],Td=I({terminal:!0}),Ud=["$compile","$parse",function(a,c){var d=/^\s*(.*?)(?:\s+as\s+(.*?))?(?:\s+group\s+by\s+(.*))?\s+for\s+(?:([\$\w][\$\w\d]*)|(?:\(\s*([\$\w][\$\w\d]*)\s*,\s*([\$\w][\$\w\d]*)\s*\)))\s+in\s+(.*)$/,e={$setViewValue:C};return{restrict:"E",require:["select","?ngModel"],controller:["$element","$scope",
+"$attrs",function(a,c,d){var j=this,i={},k=e,m;j.databound=d.ngModel;j.init=function(a,c,d){k=a;m=d};j.addOption=function(c){i[c]=!0;k.$viewValue==c&&(a.val(c),m.parent()&&m.remove())};j.removeOption=function(a){this.hasOption(a)&&(delete i[a],k.$viewValue==a&&this.renderUnknownOption(a))};j.renderUnknownOption=function(c){c="? "+fa(c)+" ?";m.val(c);a.prepend(m);a.val(c);m.prop("selected",!0)};j.hasOption=function(a){return i.hasOwnProperty(a)};c.$on("$destroy",function(){j.renderUnknownOption=C})}],
+link:function(e,h,f,j){function i(a,c,d,e){d.$render=function(){var a=d.$viewValue;e.hasOption(a)?(y.parent()&&y.remove(),c.val(a),a===""&&v.prop("selected",!0)):w(a)&&v?c.val(""):e.renderUnknownOption(a)};c.bind("change",function(){a.$apply(function(){y.parent()&&y.remove();d.$setViewValue(c.val())})})}function k(a,c,d){var e;d.$render=function(){var a=new Ga(d.$viewValue);n(c.find("option"),function(c){c.selected=x(a.get(c.value))})};a.$watch(function(){ga(e,d.$viewValue)||(e=U(d.$viewValue),d.$render())});
+c.bind("change",function(){a.$apply(function(){var a=[];n(c.find("option"),function(c){c.selected&&a.push(c.value)});d.$setViewValue(a)})})}function m(e,f,g){function h(){var a={"":[]},c=[""],d,i,p,u,v;p=g.$modelValue;u=t(e)||[];var w=l?mb(u):u,x,y,A;y={};v=!1;var B,E;if(o)v=new Ga(p);else if(p===null||s)a[""].push({selected:p===null,id:"",label:""}),v=!0;for(A=0;x=w.length,A<x;A++){y[k]=u[l?y[l]=w[A]:A];d=m(e,y)||"";if(!(i=a[d]))i=a[d]=[],c.push(d);o?d=v.remove(n(e,y))!=q:(d=p===n(e,y),v=v||d);B=
+j(e,y);B=B===q?"":B;i.push({id:l?w[A]:A,label:B,selected:d})}!o&&!v&&a[""].unshift({id:"?",label:"",selected:!0});y=0;for(w=c.length;y<w;y++){d=c[y];i=a[d];if(r.length<=y)p={element:z.clone().attr("label",d),label:i.label},u=[p],r.push(u),f.append(p.element);else if(u=r[y],p=u[0],p.label!=d)p.element.attr("label",p.label=d);B=null;A=0;for(x=i.length;A<x;A++)if(d=i[A],v=u[A+1]){B=v.element;if(v.label!==d.label)B.text(v.label=d.label);if(v.id!==d.id)B.val(v.id=d.id);if(v.element.selected!==d.selected)B.prop("selected",
+v.selected=d.selected)}else d.id===""&&s?E=s:(E=C.clone()).val(d.id).attr("selected",d.selected).text(d.label),u.push({element:E,label:d.label,id:d.id,selected:d.selected}),B?B.after(E):p.element.append(E),B=E;for(A++;u.length>A;)u.pop().element.remove()}for(;r.length>y;)r.pop()[0].element.remove()}var i;if(!(i=p.match(d)))throw Error("Expected ngOptions in form of '_select_ (as _label_)? for (_key_,)?_value_ in _collection_' but got '"+p+"'.");var j=c(i[2]||i[1]),k=i[4]||i[6],l=i[5],m=c(i[3]||""),
+n=c(i[2]?i[1]:k),t=c(i[7]),r=[[{element:f,label:""}]];s&&(a(s)(e),s.removeClass("ng-scope"),s.remove());f.html("");f.bind("change",function(){e.$apply(function(){var a,c=t(e)||[],d={},h,i,j,m,p,s;if(o){i=[];m=0;for(s=r.length;m<s;m++){a=r[m];j=1;for(p=a.length;j<p;j++)if((h=a[j].element)[0].selected)h=h.val(),l&&(d[l]=h),d[k]=c[h],i.push(n(e,d))}}else h=f.val(),h=="?"?i=q:h==""?i=null:(d[k]=c[h],l&&(d[l]=h),i=n(e,d));g.$setViewValue(i)})});g.$render=h;e.$watch(h)}if(j[1]){for(var l=j[0],t=j[1],o=
+f.multiple,p=f.ngOptions,s=!1,v,C=u(Y.createElement("option")),z=u(Y.createElement("optgroup")),y=C.clone(),j=0,A=h.children(),r=A.length;j<r;j++)if(A[j].value==""){v=s=A.eq(j);break}l.init(t,s,y);if(o&&(f.required||f.ngRequired)){var B=function(a){t.$setValidity("required",!f.required||a&&a.length);return a};t.$parsers.push(B);t.$formatters.unshift(B);f.$observe("required",function(){B(t.$viewValue)})}p?m(e,h,t):o?k(e,h,t):i(e,h,t,l)}}}}],Vd=["$interpolate",function(a){var c={addOption:C,removeOption:C};
+return{restrict:"E",priority:100,compile:function(d,e){if(w(e.value)){var g=a(d.text(),!0);g||e.$set("value",d.text())}return function(a,d,e){var i=d.parent(),k=i.data("$selectController")||i.parent().data("$selectController");k&&k.databound?d.prop("selected",!1):k=c;g?a.$watch(g,function(a,c){e.$set("value",a);a!==c&&k.removeOption(c);k.addOption(a)}):k.addOption(e.value);d.bind("$destroy",function(){k.removeOption(e.value)})}}}}],Wd=I({restrict:"E",terminal:!0});(ca=X.jQuery)?(u=ca,v(ca.fn,{scope:va.scope,
+controller:va.controller,injector:va.injector,inheritedData:va.inheritedData}),ab("remove",!0),ab("empty"),ab("html")):u=L;Zb.element=u;(function(a){v(a,{bootstrap:qb,copy:U,extend:v,equals:ga,element:u,forEach:n,injector:rb,noop:C,bind:Ua,toJson:da,fromJson:ob,identity:na,isUndefined:w,isDefined:x,isString:A,isFunction:H,isObject:M,isNumber:Ra,isElement:gc,isArray:B,version:id,isDate:oa,lowercase:y,uppercase:ma,callbacks:{counter:0}});ta=lc(X);try{ta("ngLocale")}catch(c){ta("ngLocale",[]).provider("$locale",
+Zc)}ta("ng",["ngLocale"],["$provide",function(a){a.provider("$compile",Cb).directive({a:jd,input:cc,textarea:cc,form:kd,script:Sd,select:Ud,style:Wd,option:Vd,ngBind:vd,ngBindHtmlUnsafe:xd,ngBindTemplate:wd,ngClass:yd,ngClassEven:Ad,ngClassOdd:zd,ngCsp:Dd,ngCloak:Bd,ngController:Cd,ngForm:ld,ngHide:Ld,ngInclude:Fd,ngInit:Gd,ngNonBindable:Hd,ngPluralize:Id,ngRepeat:Jd,ngShow:Kd,ngSubmit:Ed,ngStyle:Md,ngSwitch:Nd,ngSwitchWhen:Od,ngSwitchDefault:Pd,ngOptions:Td,ngView:Rd,ngTransclude:Qd,ngModel:qd,ngList:sd,
+ngChange:rd,required:dc,ngRequired:dc,ngValue:ud}).directive(lb).directive(ec);a.provider({$anchorScroll:uc,$browser:wc,$cacheFactory:xc,$controller:Bc,$document:Cc,$exceptionHandler:Dc,$filter:Qb,$interpolate:Ec,$http:Vc,$httpBackend:Wc,$location:Ic,$log:Jc,$parse:Nc,$route:Qc,$routeParams:Rc,$rootScope:Sc,$q:Oc,$sniffer:Tc,$templateCache:yc,$timeout:$c,$window:Uc})}])})(Zb);u(Y).ready(function(){jc(Y,qb)})})(window,document);angular.element(document).find("head").append('<style type="text/css">@charset "UTF-8";[ng\\:cloak],[ng-cloak],[data-ng-cloak],[x-ng-cloak],.ng-cloak,.x-ng-cloak{display:none;}ng\\:form{display:block;}</style>');

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/app/lib/angular/version.txt
----------------------------------------------------------------------
diff --git a/src/main/ui/app/lib/angular/version.txt b/src/main/ui/app/lib/angular/version.txt
new file mode 100755
index 0000000..90a27f9
--- /dev/null
+++ b/src/main/ui/app/lib/angular/version.txt
@@ -0,0 +1 @@
+1.0.5

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/app/partials/.svn/all-wcprops
----------------------------------------------------------------------
diff --git a/src/main/ui/app/partials/.svn/all-wcprops b/src/main/ui/app/partials/.svn/all-wcprops
new file mode 100755
index 0000000..cc80c35
--- /dev/null
+++ b/src/main/ui/app/partials/.svn/all-wcprops
@@ -0,0 +1,35 @@
+K 25
+svn:wc:ra_dav:version-url
+V 82
+/repos/asf/!svn/ver/1483170/incubator/climate/trunk/rcmet/src/main/ui/app/partials
+END
+partial1.html
+K 25
+svn:wc:ra_dav:version-url
+V 96
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/ui/app/partials/partial1.html
+END
+partial2.html
+K 25
+svn:wc:ra_dav:version-url
+V 96
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/ui/app/partials/partial2.html
+END
+modelSelect.html
+K 25
+svn:wc:ra_dav:version-url
+V 99
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/ui/app/partials/modelSelect.html
+END
+selectRcmed.html
+K 25
+svn:wc:ra_dav:version-url
+V 99
+/repos/asf/!svn/ver/1483170/incubator/climate/trunk/rcmet/src/main/ui/app/partials/selectRcmed.html
+END
+selectObservation.html
+K 25
+svn:wc:ra_dav:version-url
+V 105
+/repos/asf/!svn/ver/1483170/incubator/climate/trunk/rcmet/src/main/ui/app/partials/selectObservation.html
+END

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/app/partials/.svn/entries
----------------------------------------------------------------------
diff --git a/src/main/ui/app/partials/.svn/entries b/src/main/ui/app/partials/.svn/entries
new file mode 100755
index 0000000..3db4455
--- /dev/null
+++ b/src/main/ui/app/partials/.svn/entries
@@ -0,0 +1,198 @@
+10
+
+dir
+1485921
+https://svn.apache.org/repos/asf/incubator/climate/trunk/rcmet/src/main/ui/app/partials
+https://svn.apache.org/repos/asf
+
+
+
+2013-05-16T03:01:30.003406Z
+1483170
+joyce
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+13f79535-47bb-0310-9956-ffa450edef68
+
+partial1.html
+file
+
+
+
+
+2013-05-24T10:13:56.000000Z
+910834e4cb45f50ab20300659fb20a0c
+2013-03-13T02:34:30.834306Z
+1475137
+mjjoyce
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+39
+
+partial2.html
+file
+
+
+
+
+2013-05-24T10:13:56.000000Z
+e328baafc58bbd2ddd3c6a95f5d0d10d
+2013-03-13T02:34:30.834306Z
+1475137
+mjjoyce
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+138
+
+modelSelect.html
+file
+
+
+
+
+2013-05-24T10:13:56.000000Z
+9495978e9deca60be2e3bc5014922213
+2013-03-13T02:34:43.098970Z
+1475143
+mjjoyce
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+2372
+
+selectRcmed.html
+file
+
+
+
+
+2013-05-24T10:13:56.000000Z
+56a580e4fb249f9b5b6c5bf9789a0199
+2013-05-16T03:01:30.003406Z
+1483170
+joyce
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+1038
+
+selectObservation.html
+file
+
+
+
+
+2013-05-24T10:13:56.000000Z
+65544e29c26a57b442f9cf418a05a650
+2013-05-16T03:01:30.003406Z
+1483170
+joyce
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+1552
+

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/app/partials/.svn/prop-base/partial1.html.svn-base
----------------------------------------------------------------------
diff --git a/src/main/ui/app/partials/.svn/prop-base/partial1.html.svn-base b/src/main/ui/app/partials/.svn/prop-base/partial1.html.svn-base
new file mode 100755
index 0000000..869ac71
--- /dev/null
+++ b/src/main/ui/app/partials/.svn/prop-base/partial1.html.svn-base
@@ -0,0 +1,5 @@
+K 14
+svn:executable
+V 1
+*
+END

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/app/partials/.svn/prop-base/partial2.html.svn-base
----------------------------------------------------------------------
diff --git a/src/main/ui/app/partials/.svn/prop-base/partial2.html.svn-base b/src/main/ui/app/partials/.svn/prop-base/partial2.html.svn-base
new file mode 100755
index 0000000..869ac71
--- /dev/null
+++ b/src/main/ui/app/partials/.svn/prop-base/partial2.html.svn-base
@@ -0,0 +1,5 @@
+K 14
+svn:executable
+V 1
+*
+END

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/app/partials/.svn/text-base/modelSelect.html.svn-base
----------------------------------------------------------------------
diff --git a/src/main/ui/app/partials/.svn/text-base/modelSelect.html.svn-base b/src/main/ui/app/partials/.svn/text-base/modelSelect.html.svn-base
new file mode 100755
index 0000000..49a7dec
--- /dev/null
+++ b/src/main/ui/app/partials/.svn/text-base/modelSelect.html.svn-base
@@ -0,0 +1,67 @@
+<div class="container">
+  <div class="row">
+    <div class="span10 offset1 columns">
+      <div class="row">
+        <div class="span10">
+          <center>
+            <form id="modelSelectorForm">
+              <input type="file" name="modelSelector">
+            </form>
+          </center>
+        </div>
+      </div>
+      <div class="row">
+        <div class="span10 offset2">
+          <form class="form-horizontal" id="parameterSelectorForm">
+            <div class="control-group">
+              <label class="control-label" for="paramSelect">Parameter Value</label>
+              <div class="controls">
+                <select id="paramSelect">
+                  <option ng-repeat="param in modelParameters">
+                    {{param.text}}
+                  </option>
+                </select>
+              </div>
+            </div>
+            <div class="control-group">
+              <label class="control-label" for="latSelect">Latitude Variable</label>
+              <div class="controls">
+                <select id="latSelect">
+                  <option ng-repeat="lat in latVariables">
+                    {{lat.text}}
+                  </option>
+                </select>
+              </div>
+            </div>
+            <div class="control-group">
+              <label class="control-label" for="lonSelect">Longitude Variable</label>
+              <div class"controls">
+                <select id="lonSelect">
+                  <option ng-repeat="lon in lonVariables">
+                    {{lon.text}}
+                  </option>
+                </select>
+              </div>
+            </div>
+            <div class="control-group">
+              <label class="control-label" for="dateTimeSelect">Date/Time Variable</label>
+              <div class="controls">
+                <select id="dateTimeSelect">
+                  <option ng-repeat="dateTime in dateTimeVariables">
+                    {{dateTime.text}}
+                  </option>
+                </select>
+              </div>
+            </div>
+            <div class="control-group">
+              <div class="controls">
+                <button type="submit" class="btn btn-warn">Cancel</button>
+                <button type="submit" class="btn">Add Model</button>
+              </div>
+            </div>
+          </form>
+        </div>
+      </div>
+    </div>
+  </div>
+</div>

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/app/partials/.svn/text-base/partial1.html.svn-base
----------------------------------------------------------------------
diff --git a/src/main/ui/app/partials/.svn/text-base/partial1.html.svn-base b/src/main/ui/app/partials/.svn/text-base/partial1.html.svn-base
new file mode 100755
index 0000000..89459a6
--- /dev/null
+++ b/src/main/ui/app/partials/.svn/text-base/partial1.html.svn-base
@@ -0,0 +1 @@
+<p>This is the partial for view 1.</p>

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/app/partials/.svn/text-base/partial2.html.svn-base
----------------------------------------------------------------------
diff --git a/src/main/ui/app/partials/.svn/text-base/partial2.html.svn-base b/src/main/ui/app/partials/.svn/text-base/partial2.html.svn-base
new file mode 100755
index 0000000..b6503ee
--- /dev/null
+++ b/src/main/ui/app/partials/.svn/text-base/partial2.html.svn-base
@@ -0,0 +1,5 @@
+<p>This is the partial for view 2.</p>
+<p>
+  Showing of 'interpolate' filter:
+  {{ 'Current version is v%VERSION%.' | interpolate }}
+</p>


[22/51] [abbrv] [partial] Adding Jinwon's custom RCMET

Posted by jo...@apache.org.
http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/app/js/jquery-1.9.1.min.js
----------------------------------------------------------------------
diff --git a/src/main/ui/app/js/jquery-1.9.1.min.js b/src/main/ui/app/js/jquery-1.9.1.min.js
new file mode 100755
index 0000000..006e953
--- /dev/null
+++ b/src/main/ui/app/js/jquery-1.9.1.min.js
@@ -0,0 +1,5 @@
+/*! jQuery v1.9.1 | (c) 2005, 2012 jQuery Foundation, Inc. | jquery.org/license
+//@ sourceMappingURL=jquery.min.map
+*/(function(e,t){var n,r,i=typeof t,o=e.document,a=e.location,s=e.jQuery,u=e.$,l={},c=[],p="1.9.1",f=c.concat,d=c.push,h=c.slice,g=c.indexOf,m=l.toString,y=l.hasOwnProperty,v=p.trim,b=function(e,t){return new b.fn.init(e,t,r)},x=/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source,w=/\S+/g,T=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,N=/^(?:(<[\w\W]+>)[^>]*|#([\w-]*))$/,C=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,k=/^[\],:{}\s]*$/,E=/(?:^|:|,)(?:\s*\[)+/g,S=/\\(?:["\\\/bfnrt]|u[\da-fA-F]{4})/g,A=/"[^"\\\r\n]*"|true|false|null|-?(?:\d+\.|)\d+(?:[eE][+-]?\d+|)/g,j=/^-ms-/,D=/-([\da-z])/gi,L=function(e,t){return t.toUpperCase()},H=function(e){(o.addEventListener||"load"===e.type||"complete"===o.readyState)&&(q(),b.ready())},q=function(){o.addEventListener?(o.removeEventListener("DOMContentLoaded",H,!1),e.removeEventListener("load",H,!1)):(o.detachEvent("onreadystatechange",H),e.detachEvent("onload",H))};b.fn=b.prototype={jquery:p,constructor:b,init:function(e,n,r){var i,a;if(!e)return this;if("string"==typeof e)
 {if(i="<"===e.charAt(0)&&">"===e.charAt(e.length-1)&&e.length>=3?[null,e,null]:N.exec(e),!i||!i[1]&&n)return!n||n.jquery?(n||r).find(e):this.constructor(n).find(e);if(i[1]){if(n=n instanceof b?n[0]:n,b.merge(this,b.parseHTML(i[1],n&&n.nodeType?n.ownerDocument||n:o,!0)),C.test(i[1])&&b.isPlainObject(n))for(i in n)b.isFunction(this[i])?this[i](n[i]):this.attr(i,n[i]);return this}if(a=o.getElementById(i[2]),a&&a.parentNode){if(a.id!==i[2])return r.find(e);this.length=1,this[0]=a}return this.context=o,this.selector=e,this}return e.nodeType?(this.context=this[0]=e,this.length=1,this):b.isFunction(e)?r.ready(e):(e.selector!==t&&(this.selector=e.selector,this.context=e.context),b.makeArray(e,this))},selector:"",length:0,size:function(){return this.length},toArray:function(){return h.call(this)},get:function(e){return null==e?this.toArray():0>e?this[this.length+e]:this[e]},pushStack:function(e){var t=b.merge(this.constructor(),e);return t.prevObject=this,t.context=this.context,t},each:funct
 ion(e,t){return b.each(this,e,t)},ready:function(e){return b.ready.promise().done(e),this},slice:function(){return this.pushStack(h.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(e){var t=this.length,n=+e+(0>e?t:0);return this.pushStack(n>=0&&t>n?[this[n]]:[])},map:function(e){return this.pushStack(b.map(this,function(t,n){return e.call(t,n,t)}))},end:function(){return this.prevObject||this.constructor(null)},push:d,sort:[].sort,splice:[].splice},b.fn.init.prototype=b.fn,b.extend=b.fn.extend=function(){var e,n,r,i,o,a,s=arguments[0]||{},u=1,l=arguments.length,c=!1;for("boolean"==typeof s&&(c=s,s=arguments[1]||{},u=2),"object"==typeof s||b.isFunction(s)||(s={}),l===u&&(s=this,--u);l>u;u++)if(null!=(o=arguments[u]))for(i in o)e=s[i],r=o[i],s!==r&&(c&&r&&(b.isPlainObject(r)||(n=b.isArray(r)))?(n?(n=!1,a=e&&b.isArray(e)?e:[]):a=e&&b.isPlainObject(e)?e:{},s[i]=b.extend(c,a,r)):r!==t&&(s[i]=r));return s},b.extend({noConflict:fun
 ction(t){return e.$===b&&(e.$=u),t&&e.jQuery===b&&(e.jQuery=s),b},isReady:!1,readyWait:1,holdReady:function(e){e?b.readyWait++:b.ready(!0)},ready:function(e){if(e===!0?!--b.readyWait:!b.isReady){if(!o.body)return setTimeout(b.ready);b.isReady=!0,e!==!0&&--b.readyWait>0||(n.resolveWith(o,[b]),b.fn.trigger&&b(o).trigger("ready").off("ready"))}},isFunction:function(e){return"function"===b.type(e)},isArray:Array.isArray||function(e){return"array"===b.type(e)},isWindow:function(e){return null!=e&&e==e.window},isNumeric:function(e){return!isNaN(parseFloat(e))&&isFinite(e)},type:function(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?l[m.call(e)]||"object":typeof e},isPlainObject:function(e){if(!e||"object"!==b.type(e)||e.nodeType||b.isWindow(e))return!1;try{if(e.constructor&&!y.call(e,"constructor")&&!y.call(e.constructor.prototype,"isPrototypeOf"))return!1}catch(n){return!1}var r;for(r in e);return r===t||y.call(e,r)},isEmptyObject:function(e){var t;for(t in e)return!1;r
 eturn!0},error:function(e){throw Error(e)},parseHTML:function(e,t,n){if(!e||"string"!=typeof e)return null;"boolean"==typeof t&&(n=t,t=!1),t=t||o;var r=C.exec(e),i=!n&&[];return r?[t.createElement(r[1])]:(r=b.buildFragment([e],t,i),i&&b(i).remove(),b.merge([],r.childNodes))},parseJSON:function(n){return e.JSON&&e.JSON.parse?e.JSON.parse(n):null===n?n:"string"==typeof n&&(n=b.trim(n),n&&k.test(n.replace(S,"@").replace(A,"]").replace(E,"")))?Function("return "+n)():(b.error("Invalid JSON: "+n),t)},parseXML:function(n){var r,i;if(!n||"string"!=typeof n)return null;try{e.DOMParser?(i=new DOMParser,r=i.parseFromString(n,"text/xml")):(r=new ActiveXObject("Microsoft.XMLDOM"),r.async="false",r.loadXML(n))}catch(o){r=t}return r&&r.documentElement&&!r.getElementsByTagName("parsererror").length||b.error("Invalid XML: "+n),r},noop:function(){},globalEval:function(t){t&&b.trim(t)&&(e.execScript||function(t){e.eval.call(e,t)})(t)},camelCase:function(e){return e.replace(j,"ms-").replace(D,L)},node
 Name:function(e,t){return e.nodeName&&e.nodeName.toLowerCase()===t.toLowerCase()},each:function(e,t,n){var r,i=0,o=e.length,a=M(e);if(n){if(a){for(;o>i;i++)if(r=t.apply(e[i],n),r===!1)break}else for(i in e)if(r=t.apply(e[i],n),r===!1)break}else if(a){for(;o>i;i++)if(r=t.call(e[i],i,e[i]),r===!1)break}else for(i in e)if(r=t.call(e[i],i,e[i]),r===!1)break;return e},trim:v&&!v.call("\ufeff\u00a0")?function(e){return null==e?"":v.call(e)}:function(e){return null==e?"":(e+"").replace(T,"")},makeArray:function(e,t){var n=t||[];return null!=e&&(M(Object(e))?b.merge(n,"string"==typeof e?[e]:e):d.call(n,e)),n},inArray:function(e,t,n){var r;if(t){if(g)return g.call(t,e,n);for(r=t.length,n=n?0>n?Math.max(0,r+n):n:0;r>n;n++)if(n in t&&t[n]===e)return n}return-1},merge:function(e,n){var r=n.length,i=e.length,o=0;if("number"==typeof r)for(;r>o;o++)e[i++]=n[o];else while(n[o]!==t)e[i++]=n[o++];return e.length=i,e},grep:function(e,t,n){var r,i=[],o=0,a=e.length;for(n=!!n;a>o;o++)r=!!t(e[o],o),n!==r
 &&i.push(e[o]);return i},map:function(e,t,n){var r,i=0,o=e.length,a=M(e),s=[];if(a)for(;o>i;i++)r=t(e[i],i,n),null!=r&&(s[s.length]=r);else for(i in e)r=t(e[i],i,n),null!=r&&(s[s.length]=r);return f.apply([],s)},guid:1,proxy:function(e,n){var r,i,o;return"string"==typeof n&&(o=e[n],n=e,e=o),b.isFunction(e)?(r=h.call(arguments,2),i=function(){return e.apply(n||this,r.concat(h.call(arguments)))},i.guid=e.guid=e.guid||b.guid++,i):t},access:function(e,n,r,i,o,a,s){var u=0,l=e.length,c=null==r;if("object"===b.type(r)){o=!0;for(u in r)b.access(e,n,u,r[u],!0,a,s)}else if(i!==t&&(o=!0,b.isFunction(i)||(s=!0),c&&(s?(n.call(e,i),n=null):(c=n,n=function(e,t,n){return c.call(b(e),n)})),n))for(;l>u;u++)n(e[u],r,s?i:i.call(e[u],u,n(e[u],r)));return o?e:c?n.call(e):l?n(e[0],r):a},now:function(){return(new Date).getTime()}}),b.ready.promise=function(t){if(!n)if(n=b.Deferred(),"complete"===o.readyState)setTimeout(b.ready);else if(o.addEventListener)o.addEventListener("DOMContentLoaded",H,!1),e.addEv
 entListener("load",H,!1);else{o.attachEvent("onreadystatechange",H),e.attachEvent("onload",H);var r=!1;try{r=null==e.frameElement&&o.documentElement}catch(i){}r&&r.doScroll&&function a(){if(!b.isReady){try{r.doScroll("left")}catch(e){return setTimeout(a,50)}q(),b.ready()}}()}return n.promise(t)},b.each("Boolean Number String Function Array Date RegExp Object Error".split(" "),function(e,t){l["[object "+t+"]"]=t.toLowerCase()});function M(e){var t=e.length,n=b.type(e);return b.isWindow(e)?!1:1===e.nodeType&&t?!0:"array"===n||"function"!==n&&(0===t||"number"==typeof t&&t>0&&t-1 in e)}r=b(o);var _={};function F(e){var t=_[e]={};return b.each(e.match(w)||[],function(e,n){t[n]=!0}),t}b.Callbacks=function(e){e="string"==typeof e?_[e]||F(e):b.extend({},e);var n,r,i,o,a,s,u=[],l=!e.once&&[],c=function(t){for(r=e.memory&&t,i=!0,a=s||0,s=0,o=u.length,n=!0;u&&o>a;a++)if(u[a].apply(t[0],t[1])===!1&&e.stopOnFalse){r=!1;break}n=!1,u&&(l?l.length&&c(l.shift()):r?u=[]:p.disable())},p={add:function(
 ){if(u){var t=u.length;(function i(t){b.each(t,function(t,n){var r=b.type(n);"function"===r?e.unique&&p.has(n)||u.push(n):n&&n.length&&"string"!==r&&i(n)})})(arguments),n?o=u.length:r&&(s=t,c(r))}return this},remove:function(){return u&&b.each(arguments,function(e,t){var r;while((r=b.inArray(t,u,r))>-1)u.splice(r,1),n&&(o>=r&&o--,a>=r&&a--)}),this},has:function(e){return e?b.inArray(e,u)>-1:!(!u||!u.length)},empty:function(){return u=[],this},disable:function(){return u=l=r=t,this},disabled:function(){return!u},lock:function(){return l=t,r||p.disable(),this},locked:function(){return!l},fireWith:function(e,t){return t=t||[],t=[e,t.slice?t.slice():t],!u||i&&!l||(n?l.push(t):c(t)),this},fire:function(){return p.fireWith(this,arguments),this},fired:function(){return!!i}};return p},b.extend({Deferred:function(e){var t=[["resolve","done",b.Callbacks("once memory"),"resolved"],["reject","fail",b.Callbacks("once memory"),"rejected"],["notify","progress",b.Callbacks("memory")]],n="pending",r
 ={state:function(){return n},always:function(){return i.done(arguments).fail(arguments),this},then:function(){var e=arguments;return b.Deferred(function(n){b.each(t,function(t,o){var a=o[0],s=b.isFunction(e[t])&&e[t];i[o[1]](function(){var e=s&&s.apply(this,arguments);e&&b.isFunction(e.promise)?e.promise().done(n.resolve).fail(n.reject).progress(n.notify):n[a+"With"](this===r?n.promise():this,s?[e]:arguments)})}),e=null}).promise()},promise:function(e){return null!=e?b.extend(e,r):r}},i={};return r.pipe=r.then,b.each(t,function(e,o){var a=o[2],s=o[3];r[o[1]]=a.add,s&&a.add(function(){n=s},t[1^e][2].disable,t[2][2].lock),i[o[0]]=function(){return i[o[0]+"With"](this===i?r:this,arguments),this},i[o[0]+"With"]=a.fireWith}),r.promise(i),e&&e.call(i,i),i},when:function(e){var t=0,n=h.call(arguments),r=n.length,i=1!==r||e&&b.isFunction(e.promise)?r:0,o=1===i?e:b.Deferred(),a=function(e,t,n){return function(r){t[e]=this,n[e]=arguments.length>1?h.call(arguments):r,n===s?o.notifyWith(t,n):--
 i||o.resolveWith(t,n)}},s,u,l;if(r>1)for(s=Array(r),u=Array(r),l=Array(r);r>t;t++)n[t]&&b.isFunction(n[t].promise)?n[t].promise().done(a(t,l,n)).fail(o.reject).progress(a(t,u,s)):--i;return i||o.resolveWith(l,n),o.promise()}}),b.support=function(){var t,n,r,a,s,u,l,c,p,f,d=o.createElement("div");if(d.setAttribute("className","t"),d.innerHTML="  <link/><table></table><a href='/a'>a</a><input type='checkbox'/>",n=d.getElementsByTagName("*"),r=d.getElementsByTagName("a")[0],!n||!r||!n.length)return{};s=o.createElement("select"),l=s.appendChild(o.createElement("option")),a=d.getElementsByTagName("input")[0],r.style.cssText="top:1px;float:left;opacity:.5",t={getSetAttribute:"t"!==d.className,leadingWhitespace:3===d.firstChild.nodeType,tbody:!d.getElementsByTagName("tbody").length,htmlSerialize:!!d.getElementsByTagName("link").length,style:/top/.test(r.getAttribute("style")),hrefNormalized:"/a"===r.getAttribute("href"),opacity:/^0.5/.test(r.style.opacity),cssFloat:!!r.style.cssFloat,check
 On:!!a.value,optSelected:l.selected,enctype:!!o.createElement("form").enctype,html5Clone:"<:nav></:nav>"!==o.createElement("nav").cloneNode(!0).outerHTML,boxModel:"CSS1Compat"===o.compatMode,deleteExpando:!0,noCloneEvent:!0,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableMarginRight:!0,boxSizingReliable:!0,pixelPosition:!1},a.checked=!0,t.noCloneChecked=a.cloneNode(!0).checked,s.disabled=!0,t.optDisabled=!l.disabled;try{delete d.test}catch(h){t.deleteExpando=!1}a=o.createElement("input"),a.setAttribute("value",""),t.input=""===a.getAttribute("value"),a.value="t",a.setAttribute("type","radio"),t.radioValue="t"===a.value,a.setAttribute("checked","t"),a.setAttribute("name","t"),u=o.createDocumentFragment(),u.appendChild(a),t.appendChecked=a.checked,t.checkClone=u.cloneNode(!0).cloneNode(!0).lastChild.checked,d.attachEvent&&(d.attachEvent("onclick",function(){t.noCloneEvent=!1}),d.cloneNode(!0).click());for(f in{submit:!0,change:!0,focusin:!0})d.setAttribute(c="on"+f,"t"),t[f+"Bub
 bles"]=c in e||d.attributes[c].expando===!1;return d.style.backgroundClip="content-box",d.cloneNode(!0).style.backgroundClip="",t.clearCloneStyle="content-box"===d.style.backgroundClip,b(function(){var n,r,a,s="padding:0;margin:0;border:0;display:block;box-sizing:content-box;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;",u=o.getElementsByTagName("body")[0];u&&(n=o.createElement("div"),n.style.cssText="border:0;width:0;height:0;position:absolute;top:0;left:-9999px;margin-top:1px",u.appendChild(n).appendChild(d),d.innerHTML="<table><tr><td></td><td>t</td></tr></table>",a=d.getElementsByTagName("td"),a[0].style.cssText="padding:0;margin:0;border:0;display:none",p=0===a[0].offsetHeight,a[0].style.display="",a[1].style.display="none",t.reliableHiddenOffsets=p&&0===a[0].offsetHeight,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
 %;",t.boxSizing=4===d.offsetWidth,t.doesNotIncludeMarginInBodyOffset=1!==u.offsetTop,e.getComputedStyle&&(t.pixelPosition="1%"!==(e.getComputedStyle(d,null)||{}).top,t.boxSizingReliable="4px"===(e.getComputedStyle(d,null)||{width:"4px"}).width,r=d.appendChild(o.createElement("div")),r.style.cssText=d.style.cssText=s,r.style.marginRight=r.style.width="0",d.style.width="1px",t.reliableMarginRight=!parseFloat((e.getComputedStyle(r,null)||{}).marginRight)),typeof d.style.zoom!==i&&(d.innerHTML="",d.style.cssText=s+"width:1px;padding:1px;display:inline;zoom:1",t.inlineBlockNeedsLayout=3===d.offsetWidth,d.style.display="block",d.innerHTML="<div></div>",d.firstChild.style.width="5px",t.shrinkWrapBlocks=3!==d.offsetWidth,t.inlineBlockNeedsLayout&&(u.style.zoom=1)),u.removeChild(n),n=d=a=r=null)}),n=s=u=l=r=a=null,t}();var O=/(?:\{[\s\S]*\}|\[[\s\S]*\])$/,B=/([A-Z])/g;function P(e,n,r,i){if(b.acceptData(e)){var o,a,s=b.expando,u="string"==typeof n,l=e.nodeType,p=l?b.cache:e,f=l?e[s]:e[s]&&s;
 if(f&&p[f]&&(i||p[f].data)||!u||r!==t)return f||(l?e[s]=f=c.pop()||b.guid++:f=s),p[f]||(p[f]={},l||(p[f].toJSON=b.noop)),("object"==typeof n||"function"==typeof n)&&(i?p[f]=b.extend(p[f],n):p[f].data=b.extend(p[f].data,n)),o=p[f],i||(o.data||(o.data={}),o=o.data),r!==t&&(o[b.camelCase(n)]=r),u?(a=o[n],null==a&&(a=o[b.camelCase(n)])):a=o,a}}function R(e,t,n){if(b.acceptData(e)){var r,i,o,a=e.nodeType,s=a?b.cache:e,u=a?e[b.expando]:b.expando;if(s[u]){if(t&&(o=n?s[u]:s[u].data)){b.isArray(t)?t=t.concat(b.map(t,b.camelCase)):t in o?t=[t]:(t=b.camelCase(t),t=t in o?[t]:t.split(" "));for(r=0,i=t.length;i>r;r++)delete o[t[r]];if(!(n?$:b.isEmptyObject)(o))return}(n||(delete s[u].data,$(s[u])))&&(a?b.cleanData([e],!0):b.support.deleteExpando||s!=s.window?delete s[u]:s[u]=null)}}}b.extend({cache:{},expando:"jQuery"+(p+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(e){return e=e.nodeType?b.cache[e[b.expando]]:e[
 b.expando],!!e&&!$(e)},data:function(e,t,n){return P(e,t,n)},removeData:function(e,t){return R(e,t)},_data:function(e,t,n){return P(e,t,n,!0)},_removeData:function(e,t){return R(e,t,!0)},acceptData:function(e){if(e.nodeType&&1!==e.nodeType&&9!==e.nodeType)return!1;var t=e.nodeName&&b.noData[e.nodeName.toLowerCase()];return!t||t!==!0&&e.getAttribute("classid")===t}}),b.fn.extend({data:function(e,n){var r,i,o=this[0],a=0,s=null;if(e===t){if(this.length&&(s=b.data(o),1===o.nodeType&&!b._data(o,"parsedAttrs"))){for(r=o.attributes;r.length>a;a++)i=r[a].name,i.indexOf("data-")||(i=b.camelCase(i.slice(5)),W(o,i,s[i]));b._data(o,"parsedAttrs",!0)}return s}return"object"==typeof e?this.each(function(){b.data(this,e)}):b.access(this,function(n){return n===t?o?W(o,e,b.data(o,e)):null:(this.each(function(){b.data(this,e,n)}),t)},null,n,arguments.length>1,null,!0)},removeData:function(e){return this.each(function(){b.removeData(this,e)})}});function W(e,n,r){if(r===t&&1===e.nodeType){var i="data
 -"+n.replace(B,"-$1").toLowerCase();if(r=e.getAttribute(i),"string"==typeof r){try{r="true"===r?!0:"false"===r?!1:"null"===r?null:+r+""===r?+r:O.test(r)?b.parseJSON(r):r}catch(o){}b.data(e,n,r)}else r=t}return r}function $(e){var t;for(t in e)if(("data"!==t||!b.isEmptyObject(e[t]))&&"toJSON"!==t)return!1;return!0}b.extend({queue:function(e,n,r){var i;return e?(n=(n||"fx")+"queue",i=b._data(e,n),r&&(!i||b.isArray(r)?i=b._data(e,n,b.makeArray(r)):i.push(r)),i||[]):t},dequeue:function(e,t){t=t||"fx";var n=b.queue(e,t),r=n.length,i=n.shift(),o=b._queueHooks(e,t),a=function(){b.dequeue(e,t)};"inprogress"===i&&(i=n.shift(),r--),o.cur=i,i&&("fx"===t&&n.unshift("inprogress"),delete o.stop,i.call(e,a,o)),!r&&o&&o.empty.fire()},_queueHooks:function(e,t){var n=t+"queueHooks";return b._data(e,n)||b._data(e,n,{empty:b.Callbacks("once memory").add(function(){b._removeData(e,t+"queue"),b._removeData(e,n)})})}}),b.fn.extend({queue:function(e,n){var r=2;return"string"!=typeof e&&(n=e,e="fx",r--),r>a
 rguments.length?b.queue(this[0],e):n===t?this:this.each(function(){var t=b.queue(this,e,n);b._queueHooks(this,e),"fx"===e&&"inprogress"!==t[0]&&b.dequeue(this,e)})},dequeue:function(e){return this.each(function(){b.dequeue(this,e)})},delay:function(e,t){return e=b.fx?b.fx.speeds[e]||e:e,t=t||"fx",this.queue(t,function(t,n){var r=setTimeout(t,e);n.stop=function(){clearTimeout(r)}})},clearQueue:function(e){return this.queue(e||"fx",[])},promise:function(e,n){var r,i=1,o=b.Deferred(),a=this,s=this.length,u=function(){--i||o.resolveWith(a,[a])};"string"!=typeof e&&(n=e,e=t),e=e||"fx";while(s--)r=b._data(a[s],e+"queueHooks"),r&&r.empty&&(i++,r.empty.add(u));return u(),o.promise(n)}});var I,z,X=/[\t\r\n]/g,U=/\r/g,V=/^(?:input|select|textarea|button|object)$/i,Y=/^(?:a|area)$/i,J=/^(?:checked|selected|autofocus|autoplay|async|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped)$/i,G=/^(?:checked|selected)$/i,Q=b.support.getSetAttribute,K=b.support.input;b.fn.extend(
 {attr:function(e,t){return b.access(this,b.attr,e,t,arguments.length>1)},removeAttr:function(e){return this.each(function(){b.removeAttr(this,e)})},prop:function(e,t){return b.access(this,b.prop,e,t,arguments.length>1)},removeProp:function(e){return e=b.propFix[e]||e,this.each(function(){try{this[e]=t,delete this[e]}catch(n){}})},addClass:function(e){var t,n,r,i,o,a=0,s=this.length,u="string"==typeof e&&e;if(b.isFunction(e))return this.each(function(t){b(this).addClass(e.call(this,t,this.className))});if(u)for(t=(e||"").match(w)||[];s>a;a++)if(n=this[a],r=1===n.nodeType&&(n.className?(" "+n.className+" ").replace(X," "):" ")){o=0;while(i=t[o++])0>r.indexOf(" "+i+" ")&&(r+=i+" ");n.className=b.trim(r)}return this},removeClass:function(e){var t,n,r,i,o,a=0,s=this.length,u=0===arguments.length||"string"==typeof e&&e;if(b.isFunction(e))return this.each(function(t){b(this).removeClass(e.call(this,t,this.className))});if(u)for(t=(e||"").match(w)||[];s>a;a++)if(n=this[a],r=1===n.nodeType&&
 (n.className?(" "+n.className+" ").replace(X," "):"")){o=0;while(i=t[o++])while(r.indexOf(" "+i+" ")>=0)r=r.replace(" "+i+" "," ");n.className=e?b.trim(r):""}return this},toggleClass:function(e,t){var n=typeof e,r="boolean"==typeof t;return b.isFunction(e)?this.each(function(n){b(this).toggleClass(e.call(this,n,this.className,t),t)}):this.each(function(){if("string"===n){var o,a=0,s=b(this),u=t,l=e.match(w)||[];while(o=l[a++])u=r?u:!s.hasClass(o),s[u?"addClass":"removeClass"](o)}else(n===i||"boolean"===n)&&(this.className&&b._data(this,"__className__",this.className),this.className=this.className||e===!1?"":b._data(this,"__className__")||"")})},hasClass:function(e){var t=" "+e+" ",n=0,r=this.length;for(;r>n;n++)if(1===this[n].nodeType&&(" "+this[n].className+" ").replace(X," ").indexOf(t)>=0)return!0;return!1},val:function(e){var n,r,i,o=this[0];{if(arguments.length)return i=b.isFunction(e),this.each(function(n){var o,a=b(this);1===this.nodeType&&(o=i?e.call(this,n,a.val()):e,null==
 o?o="":"number"==typeof o?o+="":b.isArray(o)&&(o=b.map(o,function(e){return null==e?"":e+""})),r=b.valHooks[this.type]||b.valHooks[this.nodeName.toLowerCase()],r&&"set"in r&&r.set(this,o,"value")!==t||(this.value=o))});if(o)return r=b.valHooks[o.type]||b.valHooks[o.nodeName.toLowerCase()],r&&"get"in r&&(n=r.get(o,"value"))!==t?n:(n=o.value,"string"==typeof n?n.replace(U,""):null==n?"":n)}}}),b.extend({valHooks:{option:{get:function(e){var t=e.attributes.value;return!t||t.specified?e.value:e.text}},select:{get:function(e){var t,n,r=e.options,i=e.selectedIndex,o="select-one"===e.type||0>i,a=o?null:[],s=o?i+1:r.length,u=0>i?s:o?i:0;for(;s>u;u++)if(n=r[u],!(!n.selected&&u!==i||(b.support.optDisabled?n.disabled:null!==n.getAttribute("disabled"))||n.parentNode.disabled&&b.nodeName(n.parentNode,"optgroup"))){if(t=b(n).val(),o)return t;a.push(t)}return a},set:function(e,t){var n=b.makeArray(t);return b(e).find("option").each(function(){this.selected=b.inArray(b(this).val(),n)>=0}),n.length|
 |(e.selectedIndex=-1),n}}},attr:function(e,n,r){var o,a,s,u=e.nodeType;if(e&&3!==u&&8!==u&&2!==u)return typeof e.getAttribute===i?b.prop(e,n,r):(a=1!==u||!b.isXMLDoc(e),a&&(n=n.toLowerCase(),o=b.attrHooks[n]||(J.test(n)?z:I)),r===t?o&&a&&"get"in o&&null!==(s=o.get(e,n))?s:(typeof e.getAttribute!==i&&(s=e.getAttribute(n)),null==s?t:s):null!==r?o&&a&&"set"in o&&(s=o.set(e,r,n))!==t?s:(e.setAttribute(n,r+""),r):(b.removeAttr(e,n),t))},removeAttr:function(e,t){var n,r,i=0,o=t&&t.match(w);if(o&&1===e.nodeType)while(n=o[i++])r=b.propFix[n]||n,J.test(n)?!Q&&G.test(n)?e[b.camelCase("default-"+n)]=e[r]=!1:e[r]=!1:b.attr(e,n,""),e.removeAttribute(Q?n:r)},attrHooks:{type:{set:function(e,t){if(!b.support.radioValue&&"radio"===t&&b.nodeName(e,"input")){var n=e.value;return e.setAttribute("type",t),n&&(e.value=n),t}}}},propFix:{tabindex:"tabIndex",readonly:"readOnly","for":"htmlFor","class":"className",maxlength:"maxLength",cellspacing:"cellSpacing",cellpadding:"cellPadding",rowspan:"rowSpan",col
 span:"colSpan",usemap:"useMap",frameborder:"frameBorder",contenteditable:"contentEditable"},prop:function(e,n,r){var i,o,a,s=e.nodeType;if(e&&3!==s&&8!==s&&2!==s)return a=1!==s||!b.isXMLDoc(e),a&&(n=b.propFix[n]||n,o=b.propHooks[n]),r!==t?o&&"set"in o&&(i=o.set(e,r,n))!==t?i:e[n]=r:o&&"get"in o&&null!==(i=o.get(e,n))?i:e[n]},propHooks:{tabIndex:{get:function(e){var n=e.getAttributeNode("tabindex");return n&&n.specified?parseInt(n.value,10):V.test(e.nodeName)||Y.test(e.nodeName)&&e.href?0:t}}}}),z={get:function(e,n){var r=b.prop(e,n),i="boolean"==typeof r&&e.getAttribute(n),o="boolean"==typeof r?K&&Q?null!=i:G.test(n)?e[b.camelCase("default-"+n)]:!!i:e.getAttributeNode(n);return o&&o.value!==!1?n.toLowerCase():t},set:function(e,t,n){return t===!1?b.removeAttr(e,n):K&&Q||!G.test(n)?e.setAttribute(!Q&&b.propFix[n]||n,n):e[b.camelCase("default-"+n)]=e[n]=!0,n}},K&&Q||(b.attrHooks.value={get:function(e,n){var r=e.getAttributeNode(n);return b.nodeName(e,"input")?e.defaultValue:r&&r.specif
 ied?r.value:t},set:function(e,n,r){return b.nodeName(e,"input")?(e.defaultValue=n,t):I&&I.set(e,n,r)}}),Q||(I=b.valHooks.button={get:function(e,n){var r=e.getAttributeNode(n);return r&&("id"===n||"name"===n||"coords"===n?""!==r.value:r.specified)?r.value:t},set:function(e,n,r){var i=e.getAttributeNode(r);return i||e.setAttributeNode(i=e.ownerDocument.createAttribute(r)),i.value=n+="","value"===r||n===e.getAttribute(r)?n:t}},b.attrHooks.contenteditable={get:I.get,set:function(e,t,n){I.set(e,""===t?!1:t,n)}},b.each(["width","height"],function(e,n){b.attrHooks[n]=b.extend(b.attrHooks[n],{set:function(e,r){return""===r?(e.setAttribute(n,"auto"),r):t}})})),b.support.hrefNormalized||(b.each(["href","src","width","height"],function(e,n){b.attrHooks[n]=b.extend(b.attrHooks[n],{get:function(e){var r=e.getAttribute(n,2);return null==r?t:r}})}),b.each(["href","src"],function(e,t){b.propHooks[t]={get:function(e){return e.getAttribute(t,4)}}})),b.support.style||(b.attrHooks.style={get:function(e
 ){return e.style.cssText||t},set:function(e,t){return e.style.cssText=t+""}}),b.support.optSelected||(b.propHooks.selected=b.extend(b.propHooks.selected,{get:function(e){var t=e.parentNode;return t&&(t.selectedIndex,t.parentNode&&t.parentNode.selectedIndex),null}})),b.support.enctype||(b.propFix.enctype="encoding"),b.support.checkOn||b.each(["radio","checkbox"],function(){b.valHooks[this]={get:function(e){return null===e.getAttribute("value")?"on":e.value}}}),b.each(["radio","checkbox"],function(){b.valHooks[this]=b.extend(b.valHooks[this],{set:function(e,n){return b.isArray(n)?e.checked=b.inArray(b(e).val(),n)>=0:t}})});var Z=/^(?:input|select|textarea)$/i,et=/^key/,tt=/^(?:mouse|contextmenu)|click/,nt=/^(?:focusinfocus|focusoutblur)$/,rt=/^([^.]*)(?:\.(.+)|)$/;function it(){return!0}function ot(){return!1}b.event={global:{},add:function(e,n,r,o,a){var s,u,l,c,p,f,d,h,g,m,y,v=b._data(e);if(v){r.handler&&(c=r,r=c.handler,a=c.selector),r.guid||(r.guid=b.guid++),(u=v.events)||(u=v.eve
 nts={}),(f=v.handle)||(f=v.handle=function(e){return typeof b===i||e&&b.event.triggered===e.type?t:b.event.dispatch.apply(f.elem,arguments)},f.elem=e),n=(n||"").match(w)||[""],l=n.length;while(l--)s=rt.exec(n[l])||[],g=y=s[1],m=(s[2]||"").split(".").sort(),p=b.event.special[g]||{},g=(a?p.delegateType:p.bindType)||g,p=b.event.special[g]||{},d=b.extend({type:g,origType:y,data:o,handler:r,guid:r.guid,selector:a,needsContext:a&&b.expr.match.needsContext.test(a),namespace:m.join(".")},c),(h=u[g])||(h=u[g]=[],h.delegateCount=0,p.setup&&p.setup.call(e,o,m,f)!==!1||(e.addEventListener?e.addEventListener(g,f,!1):e.attachEvent&&e.attachEvent("on"+g,f))),p.add&&(p.add.call(e,d),d.handler.guid||(d.handler.guid=r.guid)),a?h.splice(h.delegateCount++,0,d):h.push(d),b.event.global[g]=!0;e=null}},remove:function(e,t,n,r,i){var o,a,s,u,l,c,p,f,d,h,g,m=b.hasData(e)&&b._data(e);if(m&&(c=m.events)){t=(t||"").match(w)||[""],l=t.length;while(l--)if(s=rt.exec(t[l])||[],d=g=s[1],h=(s[2]||"").split(".").sort
 (),d){p=b.event.special[d]||{},d=(r?p.delegateType:p.bindType)||d,f=c[d]||[],s=s[2]&&RegExp("(^|\\.)"+h.join("\\.(?:.*\\.|)")+"(\\.|$)"),u=o=f.length;while(o--)a=f[o],!i&&g!==a.origType||n&&n.guid!==a.guid||s&&!s.test(a.namespace)||r&&r!==a.selector&&("**"!==r||!a.selector)||(f.splice(o,1),a.selector&&f.delegateCount--,p.remove&&p.remove.call(e,a));u&&!f.length&&(p.teardown&&p.teardown.call(e,h,m.handle)!==!1||b.removeEvent(e,d,m.handle),delete c[d])}else for(d in c)b.event.remove(e,d+t[l],n,r,!0);b.isEmptyObject(c)&&(delete m.handle,b._removeData(e,"events"))}},trigger:function(n,r,i,a){var s,u,l,c,p,f,d,h=[i||o],g=y.call(n,"type")?n.type:n,m=y.call(n,"namespace")?n.namespace.split("."):[];if(l=f=i=i||o,3!==i.nodeType&&8!==i.nodeType&&!nt.test(g+b.event.triggered)&&(g.indexOf(".")>=0&&(m=g.split("."),g=m.shift(),m.sort()),u=0>g.indexOf(":")&&"on"+g,n=n[b.expando]?n:new b.Event(g,"object"==typeof n&&n),n.isTrigger=!0,n.namespace=m.join("."),n.namespace_re=n.namespace?RegExp("(^|\\.)
 "+m.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,n.result=t,n.target||(n.target=i),r=null==r?[n]:b.makeArray(r,[n]),p=b.event.special[g]||{},a||!p.trigger||p.trigger.apply(i,r)!==!1)){if(!a&&!p.noBubble&&!b.isWindow(i)){for(c=p.delegateType||g,nt.test(c+g)||(l=l.parentNode);l;l=l.parentNode)h.push(l),f=l;f===(i.ownerDocument||o)&&h.push(f.defaultView||f.parentWindow||e)}d=0;while((l=h[d++])&&!n.isPropagationStopped())n.type=d>1?c:p.bindType||g,s=(b._data(l,"events")||{})[n.type]&&b._data(l,"handle"),s&&s.apply(l,r),s=u&&l[u],s&&b.acceptData(l)&&s.apply&&s.apply(l,r)===!1&&n.preventDefault();if(n.type=g,!(a||n.isDefaultPrevented()||p._default&&p._default.apply(i.ownerDocument,r)!==!1||"click"===g&&b.nodeName(i,"a")||!b.acceptData(i)||!u||!i[g]||b.isWindow(i))){f=i[u],f&&(i[u]=null),b.event.triggered=g;try{i[g]()}catch(v){}b.event.triggered=t,f&&(i[u]=f)}return n.result}},dispatch:function(e){e=b.event.fix(e);var n,r,i,o,a,s=[],u=h.call(arguments),l=(b._data(this,"events")||{})[e.type]||[],c
 =b.event.special[e.type]||{};if(u[0]=e,e.delegateTarget=this,!c.preDispatch||c.preDispatch.call(this,e)!==!1){s=b.event.handlers.call(this,e,l),n=0;while((o=s[n++])&&!e.isPropagationStopped()){e.currentTarget=o.elem,a=0;while((i=o.handlers[a++])&&!e.isImmediatePropagationStopped())(!e.namespace_re||e.namespace_re.test(i.namespace))&&(e.handleObj=i,e.data=i.data,r=((b.event.special[i.origType]||{}).handle||i.handler).apply(o.elem,u),r!==t&&(e.result=r)===!1&&(e.preventDefault(),e.stopPropagation()))}return c.postDispatch&&c.postDispatch.call(this,e),e.result}},handlers:function(e,n){var r,i,o,a,s=[],u=n.delegateCount,l=e.target;if(u&&l.nodeType&&(!e.button||"click"!==e.type))for(;l!=this;l=l.parentNode||this)if(1===l.nodeType&&(l.disabled!==!0||"click"!==e.type)){for(o=[],a=0;u>a;a++)i=n[a],r=i.selector+" ",o[r]===t&&(o[r]=i.needsContext?b(r,this).index(l)>=0:b.find(r,this,null,[l]).length),o[r]&&o.push(i);o.length&&s.push({elem:l,handlers:o})}return n.length>u&&s.push({elem:this,han
 dlers:n.slice(u)}),s},fix:function(e){if(e[b.expando])return e;var t,n,r,i=e.type,a=e,s=this.fixHooks[i];s||(this.fixHooks[i]=s=tt.test(i)?this.mouseHooks:et.test(i)?this.keyHooks:{}),r=s.props?this.props.concat(s.props):this.props,e=new b.Event(a),t=r.length;while(t--)n=r[t],e[n]=a[n];return e.target||(e.target=a.srcElement||o),3===e.target.nodeType&&(e.target=e.target.parentNode),e.metaKey=!!e.metaKey,s.filter?s.filter(e,a):e},props:"altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),fixHooks:{},keyHooks:{props:"char charCode key keyCode".split(" "),filter:function(e,t){return null==e.which&&(e.which=null!=t.charCode?t.charCode:t.keyCode),e}},mouseHooks:{props:"button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),filter:function(e,n){var r,i,a,s=n.button,u=n.fromElement;return null==e.pageX&&null!=n.clientX&&(i=e.target.ownerDocument||o,a=i.documen
 tElement,r=i.body,e.pageX=n.clientX+(a&&a.scrollLeft||r&&r.scrollLeft||0)-(a&&a.clientLeft||r&&r.clientLeft||0),e.pageY=n.clientY+(a&&a.scrollTop||r&&r.scrollTop||0)-(a&&a.clientTop||r&&r.clientTop||0)),!e.relatedTarget&&u&&(e.relatedTarget=u===e.target?n.toElement:u),e.which||s===t||(e.which=1&s?1:2&s?3:4&s?2:0),e}},special:{load:{noBubble:!0},click:{trigger:function(){return b.nodeName(this,"input")&&"checkbox"===this.type&&this.click?(this.click(),!1):t}},focus:{trigger:function(){if(this!==o.activeElement&&this.focus)try{return this.focus(),!1}catch(e){}},delegateType:"focusin"},blur:{trigger:function(){return this===o.activeElement&&this.blur?(this.blur(),!1):t},delegateType:"focusout"},beforeunload:{postDispatch:function(e){e.result!==t&&(e.originalEvent.returnValue=e.result)}}},simulate:function(e,t,n,r){var i=b.extend(new b.Event,n,{type:e,isSimulated:!0,originalEvent:{}});r?b.event.trigger(i,null,t):b.event.dispatch.call(t,i),i.isDefaultPrevented()&&n.preventDefault()}},b.r
 emoveEvent=o.removeEventListener?function(e,t,n){e.removeEventListener&&e.removeEventListener(t,n,!1)}:function(e,t,n){var r="on"+t;e.detachEvent&&(typeof e[r]===i&&(e[r]=null),e.detachEvent(r,n))},b.Event=function(e,n){return this instanceof b.Event?(e&&e.type?(this.originalEvent=e,this.type=e.type,this.isDefaultPrevented=e.defaultPrevented||e.returnValue===!1||e.getPreventDefault&&e.getPreventDefault()?it:ot):this.type=e,n&&b.extend(this,n),this.timeStamp=e&&e.timeStamp||b.now(),this[b.expando]=!0,t):new b.Event(e,n)},b.Event.prototype={isDefaultPrevented:ot,isPropagationStopped:ot,isImmediatePropagationStopped:ot,preventDefault:function(){var e=this.originalEvent;this.isDefaultPrevented=it,e&&(e.preventDefault?e.preventDefault():e.returnValue=!1)},stopPropagation:function(){var e=this.originalEvent;this.isPropagationStopped=it,e&&(e.stopPropagation&&e.stopPropagation(),e.cancelBubble=!0)},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=it,this.stopPropagati
 on()}},b.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(e,t){b.event.special[e]={delegateType:t,bindType:t,handle:function(e){var n,r=this,i=e.relatedTarget,o=e.handleObj;
+return(!i||i!==r&&!b.contains(r,i))&&(e.type=o.origType,n=o.handler.apply(this,arguments),e.type=t),n}}}),b.support.submitBubbles||(b.event.special.submit={setup:function(){return b.nodeName(this,"form")?!1:(b.event.add(this,"click._submit keypress._submit",function(e){var n=e.target,r=b.nodeName(n,"input")||b.nodeName(n,"button")?n.form:t;r&&!b._data(r,"submitBubbles")&&(b.event.add(r,"submit._submit",function(e){e._submit_bubble=!0}),b._data(r,"submitBubbles",!0))}),t)},postDispatch:function(e){e._submit_bubble&&(delete e._submit_bubble,this.parentNode&&!e.isTrigger&&b.event.simulate("submit",this.parentNode,e,!0))},teardown:function(){return b.nodeName(this,"form")?!1:(b.event.remove(this,"._submit"),t)}}),b.support.changeBubbles||(b.event.special.change={setup:function(){return Z.test(this.nodeName)?(("checkbox"===this.type||"radio"===this.type)&&(b.event.add(this,"propertychange._change",function(e){"checked"===e.originalEvent.propertyName&&(this._just_changed=!0)}),b.event.add
 (this,"click._change",function(e){this._just_changed&&!e.isTrigger&&(this._just_changed=!1),b.event.simulate("change",this,e,!0)})),!1):(b.event.add(this,"beforeactivate._change",function(e){var t=e.target;Z.test(t.nodeName)&&!b._data(t,"changeBubbles")&&(b.event.add(t,"change._change",function(e){!this.parentNode||e.isSimulated||e.isTrigger||b.event.simulate("change",this.parentNode,e,!0)}),b._data(t,"changeBubbles",!0))}),t)},handle:function(e){var n=e.target;return this!==n||e.isSimulated||e.isTrigger||"radio"!==n.type&&"checkbox"!==n.type?e.handleObj.handler.apply(this,arguments):t},teardown:function(){return b.event.remove(this,"._change"),!Z.test(this.nodeName)}}),b.support.focusinBubbles||b.each({focus:"focusin",blur:"focusout"},function(e,t){var n=0,r=function(e){b.event.simulate(t,e.target,b.event.fix(e),!0)};b.event.special[t]={setup:function(){0===n++&&o.addEventListener(e,r,!0)},teardown:function(){0===--n&&o.removeEventListener(e,r,!0)}}}),b.fn.extend({on:function(e,n,r
 ,i,o){var a,s;if("object"==typeof e){"string"!=typeof n&&(r=r||n,n=t);for(a in e)this.on(a,n,r,e[a],o);return this}if(null==r&&null==i?(i=n,r=n=t):null==i&&("string"==typeof n?(i=r,r=t):(i=r,r=n,n=t)),i===!1)i=ot;else if(!i)return this;return 1===o&&(s=i,i=function(e){return b().off(e),s.apply(this,arguments)},i.guid=s.guid||(s.guid=b.guid++)),this.each(function(){b.event.add(this,e,i,r,n)})},one:function(e,t,n,r){return this.on(e,t,n,r,1)},off:function(e,n,r){var i,o;if(e&&e.preventDefault&&e.handleObj)return i=e.handleObj,b(e.delegateTarget).off(i.namespace?i.origType+"."+i.namespace:i.origType,i.selector,i.handler),this;if("object"==typeof e){for(o in e)this.off(o,n,e[o]);return this}return(n===!1||"function"==typeof n)&&(r=n,n=t),r===!1&&(r=ot),this.each(function(){b.event.remove(this,e,r,n)})},bind:function(e,t,n){return this.on(e,null,t,n)},unbind:function(e,t){return this.off(e,null,t)},delegate:function(e,t,n,r){return this.on(t,e,n,r)},undelegate:function(e,t,n){return 1===
 arguments.length?this.off(e,"**"):this.off(t,e||"**",n)},trigger:function(e,t){return this.each(function(){b.event.trigger(e,t,this)})},triggerHandler:function(e,n){var r=this[0];return r?b.event.trigger(e,n,r,!0):t}}),function(e,t){var n,r,i,o,a,s,u,l,c,p,f,d,h,g,m,y,v,x="sizzle"+-new Date,w=e.document,T={},N=0,C=0,k=it(),E=it(),S=it(),A=typeof t,j=1<<31,D=[],L=D.pop,H=D.push,q=D.slice,M=D.indexOf||function(e){var t=0,n=this.length;for(;n>t;t++)if(this[t]===e)return t;return-1},_="[\\x20\\t\\r\\n\\f]",F="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",O=F.replace("w","w#"),B="([*^$|!~]?=)",P="\\["+_+"*("+F+")"+_+"*(?:"+B+_+"*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|("+O+")|)|)"+_+"*\\]",R=":("+F+")(?:\\(((['\"])((?:\\\\.|[^\\\\])*?)\\3|((?:\\\\.|[^\\\\()[\\]]|"+P.replace(3,8)+")*)|.*)\\)|)",W=RegExp("^"+_+"+|((?:^|[^\\\\])(?:\\\\.)*)"+_+"+$","g"),$=RegExp("^"+_+"*,"+_+"*"),I=RegExp("^"+_+"*([\\x20\\t\\r\\n\\f>+~])"+_+"*"),z=RegExp(R),X=RegExp("^"+O+"$"),U={ID:RegExp("^#("+F+")"),CLASS:RegExp("^\\.("+F
 +")"),NAME:RegExp("^\\[name=['\"]?("+F+")['\"]?\\]"),TAG:RegExp("^("+F.replace("w","w*")+")"),ATTR:RegExp("^"+P),PSEUDO:RegExp("^"+R),CHILD:RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+_+"*(even|odd|(([+-]|)(\\d*)n|)"+_+"*(?:([+-]|)"+_+"*(\\d+)|))"+_+"*\\)|)","i"),needsContext:RegExp("^"+_+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+_+"*((?:-\\d)?\\d*)"+_+"*\\)|)(?=[^-]|$)","i")},V=/[\x20\t\r\n\f]*[+~]/,Y=/^[^{]+\{\s*\[native code/,J=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,G=/^(?:input|select|textarea|button)$/i,Q=/^h\d$/i,K=/'|\\/g,Z=/\=[\x20\t\r\n\f]*([^'"\]]*)[\x20\t\r\n\f]*\]/g,et=/\\([\da-fA-F]{1,6}[\x20\t\r\n\f]?|.)/g,tt=function(e,t){var n="0x"+t-65536;return n!==n?t:0>n?String.fromCharCode(n+65536):String.fromCharCode(55296|n>>10,56320|1023&n)};try{q.call(w.documentElement.childNodes,0)[0].nodeType}catch(nt){q=function(e){var t,n=[];while(t=this[e++])n.push(t);return n}}function rt(e){return Y.test(e+"")}function it(){var e,t=[];return e=function(n,r){re
 turn t.push(n+=" ")>i.cacheLength&&delete e[t.shift()],e[n]=r}}function ot(e){return e[x]=!0,e}function at(e){var t=p.createElement("div");try{return e(t)}catch(n){return!1}finally{t=null}}function st(e,t,n,r){var i,o,a,s,u,l,f,g,m,v;if((t?t.ownerDocument||t:w)!==p&&c(t),t=t||p,n=n||[],!e||"string"!=typeof e)return n;if(1!==(s=t.nodeType)&&9!==s)return[];if(!d&&!r){if(i=J.exec(e))if(a=i[1]){if(9===s){if(o=t.getElementById(a),!o||!o.parentNode)return n;if(o.id===a)return n.push(o),n}else if(t.ownerDocument&&(o=t.ownerDocument.getElementById(a))&&y(t,o)&&o.id===a)return n.push(o),n}else{if(i[2])return H.apply(n,q.call(t.getElementsByTagName(e),0)),n;if((a=i[3])&&T.getByClassName&&t.getElementsByClassName)return H.apply(n,q.call(t.getElementsByClassName(a),0)),n}if(T.qsa&&!h.test(e)){if(f=!0,g=x,m=t,v=9===s&&e,1===s&&"object"!==t.nodeName.toLowerCase()){l=ft(e),(f=t.getAttribute("id"))?g=f.replace(K,"\\$&"):t.setAttribute("id",g),g="[id='"+g+"'] ",u=l.length;while(u--)l[u]=g+dt(l[u]);m
 =V.test(e)&&t.parentNode||t,v=l.join(",")}if(v)try{return H.apply(n,q.call(m.querySelectorAll(v),0)),n}catch(b){}finally{f||t.removeAttribute("id")}}}return wt(e.replace(W,"$1"),t,n,r)}a=st.isXML=function(e){var t=e&&(e.ownerDocument||e).documentElement;return t?"HTML"!==t.nodeName:!1},c=st.setDocument=function(e){var n=e?e.ownerDocument||e:w;return n!==p&&9===n.nodeType&&n.documentElement?(p=n,f=n.documentElement,d=a(n),T.tagNameNoComments=at(function(e){return e.appendChild(n.createComment("")),!e.getElementsByTagName("*").length}),T.attributes=at(function(e){e.innerHTML="<select></select>";var t=typeof e.lastChild.getAttribute("multiple");return"boolean"!==t&&"string"!==t}),T.getByClassName=at(function(e){return e.innerHTML="<div class='hidden e'></div><div class='hidden'></div>",e.getElementsByClassName&&e.getElementsByClassName("e").length?(e.lastChild.className="e",2===e.getElementsByClassName("e").length):!1}),T.getByName=at(function(e){e.id=x+0,e.innerHTML="<a name='"+x+"'><
 /a><div name='"+x+"'></div>",f.insertBefore(e,f.firstChild);var t=n.getElementsByName&&n.getElementsByName(x).length===2+n.getElementsByName(x+0).length;return T.getIdNotName=!n.getElementById(x),f.removeChild(e),t}),i.attrHandle=at(function(e){return e.innerHTML="<a href='#'></a>",e.firstChild&&typeof e.firstChild.getAttribute!==A&&"#"===e.firstChild.getAttribute("href")})?{}:{href:function(e){return e.getAttribute("href",2)},type:function(e){return e.getAttribute("type")}},T.getIdNotName?(i.find.ID=function(e,t){if(typeof t.getElementById!==A&&!d){var n=t.getElementById(e);return n&&n.parentNode?[n]:[]}},i.filter.ID=function(e){var t=e.replace(et,tt);return function(e){return e.getAttribute("id")===t}}):(i.find.ID=function(e,n){if(typeof n.getElementById!==A&&!d){var r=n.getElementById(e);return r?r.id===e||typeof r.getAttributeNode!==A&&r.getAttributeNode("id").value===e?[r]:t:[]}},i.filter.ID=function(e){var t=e.replace(et,tt);return function(e){var n=typeof e.getAttributeNode!=
 =A&&e.getAttributeNode("id");return n&&n.value===t}}),i.find.TAG=T.tagNameNoComments?function(e,n){return typeof n.getElementsByTagName!==A?n.getElementsByTagName(e):t}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},i.find.NAME=T.getByName&&function(e,n){return typeof n.getElementsByName!==A?n.getElementsByName(name):t},i.find.CLASS=T.getByClassName&&function(e,n){return typeof n.getElementsByClassName===A||d?t:n.getElementsByClassName(e)},g=[],h=[":focus"],(T.qsa=rt(n.querySelectorAll))&&(at(function(e){e.innerHTML="<select><option selected=''></option></select>",e.querySelectorAll("[selected]").length||h.push("\\["+_+"*(?:checked|disabled|ismap|multiple|readonly|selected|value)"),e.querySelectorAll(":checked").length||h.push(":checked")}),at(function(e){e.innerHTML="<input type='hidden' i=''/>",e.querySelectorAll("[i^='']").length&&h.push("[*^$]="+_+"*(?:\"\"|'')"),e.querySelectorAll(":enabled").leng
 th||h.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),h.push(",.*:")})),(T.matchesSelector=rt(m=f.matchesSelector||f.mozMatchesSelector||f.webkitMatchesSelector||f.oMatchesSelector||f.msMatchesSelector))&&at(function(e){T.disconnectedMatch=m.call(e,"div"),m.call(e,"[s!='']:x"),g.push("!=",R)}),h=RegExp(h.join("|")),g=RegExp(g.join("|")),y=rt(f.contains)||f.compareDocumentPosition?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},v=f.compareDocumentPosition?function(e,t){var r;return e===t?(u=!0,0):(r=t.compareDocumentPosition&&e.compareDocumentPosition&&e.compareDocumentPosition(t))?1&r||e.parentNode&&11===e.parentNode.nodeType?e===n||y(w,e)?-1:t===n||y(w,t)?1:0:4&r?-1:1:e.compareDocumentPosition?-1:1}:function(e,t){var r,i=0,o=e.parentNode,a=t.parentNode,s=[e],l
 =[t];if(e===t)return u=!0,0;if(!o||!a)return e===n?-1:t===n?1:o?-1:a?1:0;if(o===a)return ut(e,t);r=e;while(r=r.parentNode)s.unshift(r);r=t;while(r=r.parentNode)l.unshift(r);while(s[i]===l[i])i++;return i?ut(s[i],l[i]):s[i]===w?-1:l[i]===w?1:0},u=!1,[0,0].sort(v),T.detectDuplicates=u,p):p},st.matches=function(e,t){return st(e,null,null,t)},st.matchesSelector=function(e,t){if((e.ownerDocument||e)!==p&&c(e),t=t.replace(Z,"='$1']"),!(!T.matchesSelector||d||g&&g.test(t)||h.test(t)))try{var n=m.call(e,t);if(n||T.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(r){}return st(t,p,null,[e]).length>0},st.contains=function(e,t){return(e.ownerDocument||e)!==p&&c(e),y(e,t)},st.attr=function(e,t){var n;return(e.ownerDocument||e)!==p&&c(e),d||(t=t.toLowerCase()),(n=i.attrHandle[t])?n(e):d||T.attributes?e.getAttribute(t):((n=e.getAttributeNode(t))||e.getAttribute(t))&&e[t]===!0?t:n&&n.specified?n.value:null},st.error=function(e){throw Error("Syntax error, unrecognized expressi
 on: "+e)},st.uniqueSort=function(e){var t,n=[],r=1,i=0;if(u=!T.detectDuplicates,e.sort(v),u){for(;t=e[r];r++)t===e[r-1]&&(i=n.push(r));while(i--)e.splice(n[i],1)}return e};function ut(e,t){var n=t&&e,r=n&&(~t.sourceIndex||j)-(~e.sourceIndex||j);if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function lt(e){return function(t){var n=t.nodeName.toLowerCase();return"input"===n&&t.type===e}}function ct(e){return function(t){var n=t.nodeName.toLowerCase();return("input"===n||"button"===n)&&t.type===e}}function pt(e){return ot(function(t){return t=+t,ot(function(n,r){var i,o=e([],n.length,t),a=o.length;while(a--)n[i=o[a]]&&(n[i]=!(r[i]=n[i]))})})}o=st.getText=function(e){var t,n="",r=0,i=e.nodeType;if(i){if(1===i||9===i||11===i){if("string"==typeof e.textContent)return e.textContent;for(e=e.firstChild;e;e=e.nextSibling)n+=o(e)}else if(3===i||4===i)return e.nodeValue}else for(;t=e[r];r++)n+=o(t);return n},i=st.selectors={cacheLength:50,createPseudo:ot,match:U,find:{
 },relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(et,tt),e[3]=(e[4]||e[5]||"").replace(et,tt),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||st.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&st.error(e[0]),e},PSEUDO:function(e){var t,n=!e[5]&&e[2];return U.CHILD.test(e[0])?null:(e[4]?e[2]=e[4]:n&&z.test(n)&&(t=ft(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){return"*"===e?function(){return!0}:(e=e.replace(et,tt).toLowerCase(),function(t){return t.nodeName&&t.nodeName.toLowerCase()===e})},CLASS:function(e){var t=k[e+" "];return t||(t=RegExp("(^|"+_+")"+e+"("+_+"|$)"))&&k(e,function(e){return t.test(e.className||typeof e.getAttr
 ibute!==A&&e.getAttribute("class")||"")})},ATTR:function(e,t,n){return function(r){var i=st.attr(r,e);return null==i?"!="===t:t?(i+="","="===t?i===n:"!="===t?i!==n:"^="===t?n&&0===i.indexOf(n):"*="===t?n&&i.indexOf(n)>-1:"$="===t?n&&i.slice(-n.length)===n:"~="===t?(" "+i+" ").indexOf(n)>-1:"|="===t?i===n||i.slice(0,n.length+1)===n+"-":!1):!0}},CHILD:function(e,t,n,r,i){var o="nth"!==e.slice(0,3),a="last"!==e.slice(-4),s="of-type"===t;return 1===r&&0===i?function(e){return!!e.parentNode}:function(t,n,u){var l,c,p,f,d,h,g=o!==a?"nextSibling":"previousSibling",m=t.parentNode,y=s&&t.nodeName.toLowerCase(),v=!u&&!s;if(m){if(o){while(g){p=t;while(p=p[g])if(s?p.nodeName.toLowerCase()===y:1===p.nodeType)return!1;h=g="only"===e&&!h&&"nextSibling"}return!0}if(h=[a?m.firstChild:m.lastChild],a&&v){c=m[x]||(m[x]={}),l=c[e]||[],d=l[0]===N&&l[1],f=l[0]===N&&l[2],p=d&&m.childNodes[d];while(p=++d&&p&&p[g]||(f=d=0)||h.pop())if(1===p.nodeType&&++f&&p===t){c[e]=[N,d,f];break}}else if(v&&(l=(t[x]||(t[x]
 ={}))[e])&&l[0]===N)f=l[1];else while(p=++d&&p&&p[g]||(f=d=0)||h.pop())if((s?p.nodeName.toLowerCase()===y:1===p.nodeType)&&++f&&(v&&((p[x]||(p[x]={}))[e]=[N,f]),p===t))break;return f-=i,f===r||0===f%r&&f/r>=0}}},PSEUDO:function(e,t){var n,r=i.pseudos[e]||i.setFilters[e.toLowerCase()]||st.error("unsupported pseudo: "+e);return r[x]?r(t):r.length>1?(n=[e,e,"",t],i.setFilters.hasOwnProperty(e.toLowerCase())?ot(function(e,n){var i,o=r(e,t),a=o.length;while(a--)i=M.call(e,o[a]),e[i]=!(n[i]=o[a])}):function(e){return r(e,0,n)}):r}},pseudos:{not:ot(function(e){var t=[],n=[],r=s(e.replace(W,"$1"));return r[x]?ot(function(e,t,n,i){var o,a=r(e,null,i,[]),s=e.length;while(s--)(o=a[s])&&(e[s]=!(t[s]=o))}):function(e,i,o){return t[0]=e,r(t,null,o,n),!n.pop()}}),has:ot(function(e){return function(t){return st(e,t).length>0}}),contains:ot(function(e){return function(t){return(t.textContent||t.innerText||o(t)).indexOf(e)>-1}}),lang:ot(function(e){return X.test(e||"")||st.error("unsupported lang: "+
 e),e=e.replace(et,tt).toLowerCase(),function(t){var n;do if(n=d?t.getAttribute("xml:lang")||t.getAttribute("lang"):t.lang)return n=n.toLowerCase(),n===e||0===n.indexOf(e+"-");while((t=t.parentNode)&&1===t.nodeType);return!1}}),target:function(t){var n=e.location&&e.location.hash;return n&&n.slice(1)===t.id},root:function(e){return e===f},focus:function(e){return e===p.activeElement&&(!p.hasFocus||p.hasFocus())&&!!(e.type||e.href||~e.tabIndex)},enabled:function(e){return e.disabled===!1},disabled:function(e){return e.disabled===!0},checked:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&!!e.checked||"option"===t&&!!e.selected},selected:function(e){return e.parentNode&&e.parentNode.selectedIndex,e.selected===!0},empty:function(e){for(e=e.firstChild;e;e=e.nextSibling)if(e.nodeName>"@"||3===e.nodeType||4===e.nodeType)return!1;return!0},parent:function(e){return!i.pseudos.empty(e)},header:function(e){return Q.test(e.nodeName)},input:function(e){return G.test(e.nodeName)},bu
 tton:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&"button"===e.type||"button"===t},text:function(e){var t;return"input"===e.nodeName.toLowerCase()&&"text"===e.type&&(null==(t=e.getAttribute("type"))||t.toLowerCase()===e.type)},first:pt(function(){return[0]}),last:pt(function(e,t){return[t-1]}),eq:pt(function(e,t,n){return[0>n?n+t:n]}),even:pt(function(e,t){var n=0;for(;t>n;n+=2)e.push(n);return e}),odd:pt(function(e,t){var n=1;for(;t>n;n+=2)e.push(n);return e}),lt:pt(function(e,t,n){var r=0>n?n+t:n;for(;--r>=0;)e.push(r);return e}),gt:pt(function(e,t,n){var r=0>n?n+t:n;for(;t>++r;)e.push(r);return e})}};for(n in{radio:!0,checkbox:!0,file:!0,password:!0,image:!0})i.pseudos[n]=lt(n);for(n in{submit:!0,reset:!0})i.pseudos[n]=ct(n);function ft(e,t){var n,r,o,a,s,u,l,c=E[e+" "];if(c)return t?0:c.slice(0);s=e,u=[],l=i.preFilter;while(s){(!n||(r=$.exec(s)))&&(r&&(s=s.slice(r[0].length)||s),u.push(o=[])),n=!1,(r=I.exec(s))&&(n=r.shift(),o.push({value:n,type:r[0].replace(W,"
  ")}),s=s.slice(n.length));for(a in i.filter)!(r=U[a].exec(s))||l[a]&&!(r=l[a](r))||(n=r.shift(),o.push({value:n,type:a,matches:r}),s=s.slice(n.length));if(!n)break}return t?s.length:s?st.error(e):E(e,u).slice(0)}function dt(e){var t=0,n=e.length,r="";for(;n>t;t++)r+=e[t].value;return r}function ht(e,t,n){var i=t.dir,o=n&&"parentNode"===i,a=C++;return t.first?function(t,n,r){while(t=t[i])if(1===t.nodeType||o)return e(t,n,r)}:function(t,n,s){var u,l,c,p=N+" "+a;if(s){while(t=t[i])if((1===t.nodeType||o)&&e(t,n,s))return!0}else while(t=t[i])if(1===t.nodeType||o)if(c=t[x]||(t[x]={}),(l=c[i])&&l[0]===p){if((u=l[1])===!0||u===r)return u===!0}else if(l=c[i]=[p],l[1]=e(t,n,s)||r,l[1]===!0)return!0}}function gt(e){return e.length>1?function(t,n,r){var i=e.length;while(i--)if(!e[i](t,n,r))return!1;return!0}:e[0]}function mt(e,t,n,r,i){var o,a=[],s=0,u=e.length,l=null!=t;for(;u>s;s++)(o=e[s])&&(!n||n(o,r,i))&&(a.push(o),l&&t.push(s));return a}function yt(e,t,n,r,i,o){return r&&!r[x]&&(r=yt(r))
 ,i&&!i[x]&&(i=yt(i,o)),ot(function(o,a,s,u){var l,c,p,f=[],d=[],h=a.length,g=o||xt(t||"*",s.nodeType?[s]:s,[]),m=!e||!o&&t?g:mt(g,f,e,s,u),y=n?i||(o?e:h||r)?[]:a:m;if(n&&n(m,y,s,u),r){l=mt(y,d),r(l,[],s,u),c=l.length;while(c--)(p=l[c])&&(y[d[c]]=!(m[d[c]]=p))}if(o){if(i||e){if(i){l=[],c=y.length;while(c--)(p=y[c])&&l.push(m[c]=p);i(null,y=[],l,u)}c=y.length;while(c--)(p=y[c])&&(l=i?M.call(o,p):f[c])>-1&&(o[l]=!(a[l]=p))}}else y=mt(y===a?y.splice(h,y.length):y),i?i(null,a,y,u):H.apply(a,y)})}function vt(e){var t,n,r,o=e.length,a=i.relative[e[0].type],s=a||i.relative[" "],u=a?1:0,c=ht(function(e){return e===t},s,!0),p=ht(function(e){return M.call(t,e)>-1},s,!0),f=[function(e,n,r){return!a&&(r||n!==l)||((t=n).nodeType?c(e,n,r):p(e,n,r))}];for(;o>u;u++)if(n=i.relative[e[u].type])f=[ht(gt(f),n)];else{if(n=i.filter[e[u].type].apply(null,e[u].matches),n[x]){for(r=++u;o>r;r++)if(i.relative[e[r].type])break;return yt(u>1&&gt(f),u>1&&dt(e.slice(0,u-1)).replace(W,"$1"),n,r>u&&vt(e.slice(u,r)),
 o>r&&vt(e=e.slice(r)),o>r&&dt(e))}f.push(n)}return gt(f)}function bt(e,t){var n=0,o=t.length>0,a=e.length>0,s=function(s,u,c,f,d){var h,g,m,y=[],v=0,b="0",x=s&&[],w=null!=d,T=l,C=s||a&&i.find.TAG("*",d&&u.parentNode||u),k=N+=null==T?1:Math.random()||.1;for(w&&(l=u!==p&&u,r=n);null!=(h=C[b]);b++){if(a&&h){g=0;while(m=e[g++])if(m(h,u,c)){f.push(h);break}w&&(N=k,r=++n)}o&&((h=!m&&h)&&v--,s&&x.push(h))}if(v+=b,o&&b!==v){g=0;while(m=t[g++])m(x,y,u,c);if(s){if(v>0)while(b--)x[b]||y[b]||(y[b]=L.call(f));y=mt(y)}H.apply(f,y),w&&!s&&y.length>0&&v+t.length>1&&st.uniqueSort(f)}return w&&(N=k,l=T),x};return o?ot(s):s}s=st.compile=function(e,t){var n,r=[],i=[],o=S[e+" "];if(!o){t||(t=ft(e)),n=t.length;while(n--)o=vt(t[n]),o[x]?r.push(o):i.push(o);o=S(e,bt(i,r))}return o};function xt(e,t,n){var r=0,i=t.length;for(;i>r;r++)st(e,t[r],n);return n}function wt(e,t,n,r){var o,a,u,l,c,p=ft(e);if(!r&&1===p.length){if(a=p[0]=p[0].slice(0),a.length>2&&"ID"===(u=a[0]).type&&9===t.nodeType&&!d&&i.relative[a[
 1].type]){if(t=i.find.ID(u.matches[0].replace(et,tt),t)[0],!t)return n;e=e.slice(a.shift().value.length)}o=U.needsContext.test(e)?0:a.length;while(o--){if(u=a[o],i.relative[l=u.type])break;if((c=i.find[l])&&(r=c(u.matches[0].replace(et,tt),V.test(a[0].type)&&t.parentNode||t))){if(a.splice(o,1),e=r.length&&dt(a),!e)return H.apply(n,q.call(r,0)),n;break}}}return s(e,p)(r,t,d,n,V.test(e)),n}i.pseudos.nth=i.pseudos.eq;function Tt(){}i.filters=Tt.prototype=i.pseudos,i.setFilters=new Tt,c(),st.attr=b.attr,b.find=st,b.expr=st.selectors,b.expr[":"]=b.expr.pseudos,b.unique=st.uniqueSort,b.text=st.getText,b.isXMLDoc=st.isXML,b.contains=st.contains}(e);var at=/Until$/,st=/^(?:parents|prev(?:Until|All))/,ut=/^.[^:#\[\.,]*$/,lt=b.expr.match.needsContext,ct={children:!0,contents:!0,next:!0,prev:!0};b.fn.extend({find:function(e){var t,n,r,i=this.length;if("string"!=typeof e)return r=this,this.pushStack(b(e).filter(function(){for(t=0;i>t;t++)if(b.contains(r[t],this))return!0}));for(n=[],t=0;i>t;t++
 )b.find(e,this[t],n);return n=this.pushStack(i>1?b.unique(n):n),n.selector=(this.selector?this.selector+" ":"")+e,n},has:function(e){var t,n=b(e,this),r=n.length;return this.filter(function(){for(t=0;r>t;t++)if(b.contains(this,n[t]))return!0})},not:function(e){return this.pushStack(ft(this,e,!1))},filter:function(e){return this.pushStack(ft(this,e,!0))},is:function(e){return!!e&&("string"==typeof e?lt.test(e)?b(e,this.context).index(this[0])>=0:b.filter(e,this).length>0:this.filter(e).length>0)},closest:function(e,t){var n,r=0,i=this.length,o=[],a=lt.test(e)||"string"!=typeof e?b(e,t||this.context):0;for(;i>r;r++){n=this[r];while(n&&n.ownerDocument&&n!==t&&11!==n.nodeType){if(a?a.index(n)>-1:b.find.matchesSelector(n,e)){o.push(n);break}n=n.parentNode}}return this.pushStack(o.length>1?b.unique(o):o)},index:function(e){return e?"string"==typeof e?b.inArray(this[0],b(e)):b.inArray(e.jquery?e[0]:e,this):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(e,t){var 
 n="string"==typeof e?b(e,t):b.makeArray(e&&e.nodeType?[e]:e),r=b.merge(this.get(),n);return this.pushStack(b.unique(r))},addBack:function(e){return this.add(null==e?this.prevObject:this.prevObject.filter(e))}}),b.fn.andSelf=b.fn.addBack;function pt(e,t){do e=e[t];while(e&&1!==e.nodeType);return e}b.each({parent:function(e){var t=e.parentNode;return t&&11!==t.nodeType?t:null},parents:function(e){return b.dir(e,"parentNode")},parentsUntil:function(e,t,n){return b.dir(e,"parentNode",n)},next:function(e){return pt(e,"nextSibling")},prev:function(e){return pt(e,"previousSibling")},nextAll:function(e){return b.dir(e,"nextSibling")},prevAll:function(e){return b.dir(e,"previousSibling")},nextUntil:function(e,t,n){return b.dir(e,"nextSibling",n)},prevUntil:function(e,t,n){return b.dir(e,"previousSibling",n)},siblings:function(e){return b.sibling((e.parentNode||{}).firstChild,e)},children:function(e){return b.sibling(e.firstChild)},contents:function(e){return b.nodeName(e,"iframe")?e.contentD
 ocument||e.contentWindow.document:b.merge([],e.childNodes)}},function(e,t){b.fn[e]=function(n,r){var i=b.map(this,t,n);return at.test(e)||(r=n),r&&"string"==typeof r&&(i=b.filter(r,i)),i=this.length>1&&!ct[e]?b.unique(i):i,this.length>1&&st.test(e)&&(i=i.reverse()),this.pushStack(i)}}),b.extend({filter:function(e,t,n){return n&&(e=":not("+e+")"),1===t.length?b.find.matchesSelector(t[0],e)?[t[0]]:[]:b.find.matches(e,t)},dir:function(e,n,r){var i=[],o=e[n];while(o&&9!==o.nodeType&&(r===t||1!==o.nodeType||!b(o).is(r)))1===o.nodeType&&i.push(o),o=o[n];return i},sibling:function(e,t){var n=[];for(;e;e=e.nextSibling)1===e.nodeType&&e!==t&&n.push(e);return n}});function ft(e,t,n){if(t=t||0,b.isFunction(t))return b.grep(e,function(e,r){var i=!!t.call(e,r,e);return i===n});if(t.nodeType)return b.grep(e,function(e){return e===t===n});if("string"==typeof t){var r=b.grep(e,function(e){return 1===e.nodeType});if(ut.test(t))return b.filter(t,r,!n);t=b.filter(t,r)}return b.grep(e,function(e){retur
 n b.inArray(e,t)>=0===n})}function dt(e){var t=ht.split("|"),n=e.createDocumentFragment();if(n.createElement)while(t.length)n.createElement(t.pop());return n}var ht="abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",gt=/ jQuery\d+="(?:null|\d+)"/g,mt=RegExp("<(?:"+ht+")[\\s/>]","i"),yt=/^\s+/,vt=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,bt=/<([\w:]+)/,xt=/<tbody/i,wt=/<|&#?\w+;/,Tt=/<(?:script|style|link)/i,Nt=/^(?:checkbox|radio)$/i,Ct=/checked\s*(?:[^=]|=\s*.checked.)/i,kt=/^$|\/(?:java|ecma)script/i,Et=/^true\/(.*)/,St=/^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g,At={option:[1,"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],area:[1,"<map>","</map>"],param:[1,"<object>","</object>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></tab
 le>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],_default:b.support.htmlSerialize?[0,"",""]:[1,"X<div>","</div>"]},jt=dt(o),Dt=jt.appendChild(o.createElement("div"));At.optgroup=At.option,At.tbody=At.tfoot=At.colgroup=At.caption=At.thead,At.th=At.td,b.fn.extend({text:function(e){return b.access(this,function(e){return e===t?b.text(this):this.empty().append((this[0]&&this[0].ownerDocument||o).createTextNode(e))},null,e,arguments.length)},wrapAll:function(e){if(b.isFunction(e))return this.each(function(t){b(this).wrapAll(e.call(this,t))});if(this[0]){var t=b(e,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&t.insertBefore(this[0]),t.map(function(){var e=this;while(e.firstChild&&1===e.firstChild.nodeType)e=e.firstChild;return e}).append(this)}return this},wrapInner:function(e){return b.isFunction(e)?this.each(function(t){b(this).wrapInner(e.call(this,t))}):this.each(function(){var t=b(this),n=t.contents();n.length?n.wrapAll(e):t.append(e)})},wrap:function(e){var t=b
 .isFunction(e);return this.each(function(n){b(this).wrapAll(t?e.call(this,n):e)})},unwrap:function(){return this.parent().each(function(){b.nodeName(this,"body")||b(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(e){(1===this.nodeType||11===this.nodeType||9===this.nodeType)&&this.appendChild(e)})},prepend:function(){return this.domManip(arguments,!0,function(e){(1===this.nodeType||11===this.nodeType||9===this.nodeType)&&this.insertBefore(e,this.firstChild)})},before:function(){return this.domManip(arguments,!1,function(e){this.parentNode&&this.parentNode.insertBefore(e,this)})},after:function(){return this.domManip(arguments,!1,function(e){this.parentNode&&this.parentNode.insertBefore(e,this.nextSibling)})},remove:function(e,t){var n,r=0;for(;null!=(n=this[r]);r++)(!e||b.filter(e,[n]).length>0)&&(t||1!==n.nodeType||b.cleanData(Ot(n)),n.parentNode&&(t&&b.contains(n.ownerDocument,n)&&Mt(Ot(n,"script")),n.parentNode.removeChild(n
 )));return this},empty:function(){var e,t=0;for(;null!=(e=this[t]);t++){1===e.nodeType&&b.cleanData(Ot(e,!1));while(e.firstChild)e.removeChild(e.firstChild);e.options&&b.nodeName(e,"select")&&(e.options.length=0)}return this},clone:function(e,t){return e=null==e?!1:e,t=null==t?e:t,this.map(function(){return b.clone(this,e,t)})},html:function(e){return b.access(this,function(e){var n=this[0]||{},r=0,i=this.length;if(e===t)return 1===n.nodeType?n.innerHTML.replace(gt,""):t;if(!("string"!=typeof e||Tt.test(e)||!b.support.htmlSerialize&&mt.test(e)||!b.support.leadingWhitespace&&yt.test(e)||At[(bt.exec(e)||["",""])[1].toLowerCase()])){e=e.replace(vt,"<$1></$2>");try{for(;i>r;r++)n=this[r]||{},1===n.nodeType&&(b.cleanData(Ot(n,!1)),n.innerHTML=e);n=0}catch(o){}}n&&this.empty().append(e)},null,e,arguments.length)},replaceWith:function(e){var t=b.isFunction(e);return t||"string"==typeof e||(e=b(e).not(this).detach()),this.domManip([e],!0,function(e){var t=this.nextSibling,n=this.parentNode;
 n&&(b(this).remove(),n.insertBefore(e,t))})},detach:function(e){return this.remove(e,!0)},domManip:function(e,n,r){e=f.apply([],e);var i,o,a,s,u,l,c=0,p=this.length,d=this,h=p-1,g=e[0],m=b.isFunction(g);if(m||!(1>=p||"string"!=typeof g||b.support.checkClone)&&Ct.test(g))return this.each(function(i){var o=d.eq(i);m&&(e[0]=g.call(this,i,n?o.html():t)),o.domManip(e,n,r)});if(p&&(l=b.buildFragment(e,this[0].ownerDocument,!1,this),i=l.firstChild,1===l.childNodes.length&&(l=i),i)){for(n=n&&b.nodeName(i,"tr"),s=b.map(Ot(l,"script"),Ht),a=s.length;p>c;c++)o=l,c!==h&&(o=b.clone(o,!0,!0),a&&b.merge(s,Ot(o,"script"))),r.call(n&&b.nodeName(this[c],"table")?Lt(this[c],"tbody"):this[c],o,c);if(a)for(u=s[s.length-1].ownerDocument,b.map(s,qt),c=0;a>c;c++)o=s[c],kt.test(o.type||"")&&!b._data(o,"globalEval")&&b.contains(u,o)&&(o.src?b.ajax({url:o.src,type:"GET",dataType:"script",async:!1,global:!1,"throws":!0}):b.globalEval((o.text||o.textContent||o.innerHTML||"").replace(St,"")));l=i=null}return thi
 s}});function Lt(e,t){return e.getElementsByTagName(t)[0]||e.appendChild(e.ownerDocument.createElement(t))}function Ht(e){var t=e.getAttributeNode("type");return e.type=(t&&t.specified)+"/"+e.type,e}function qt(e){var t=Et.exec(e.type);return t?e.type=t[1]:e.removeAttribute("type"),e}function Mt(e,t){var n,r=0;for(;null!=(n=e[r]);r++)b._data(n,"globalEval",!t||b._data(t[r],"globalEval"))}function _t(e,t){if(1===t.nodeType&&b.hasData(e)){var n,r,i,o=b._data(e),a=b._data(t,o),s=o.events;if(s){delete a.handle,a.events={};for(n in s)for(r=0,i=s[n].length;i>r;r++)b.event.add(t,n,s[n][r])}a.data&&(a.data=b.extend({},a.data))}}function Ft(e,t){var n,r,i;if(1===t.nodeType){if(n=t.nodeName.toLowerCase(),!b.support.noCloneEvent&&t[b.expando]){i=b._data(t);for(r in i.events)b.removeEvent(t,r,i.handle);t.removeAttribute(b.expando)}"script"===n&&t.text!==e.text?(Ht(t).text=e.text,qt(t)):"object"===n?(t.parentNode&&(t.outerHTML=e.outerHTML),b.support.html5Clone&&e.innerHTML&&!b.trim(t.innerHTML)&
 &(t.innerHTML=e.innerHTML)):"input"===n&&Nt.test(e.type)?(t.defaultChecked=t.checked=e.checked,t.value!==e.value&&(t.value=e.value)):"option"===n?t.defaultSelected=t.selected=e.defaultSelected:("input"===n||"textarea"===n)&&(t.defaultValue=e.defaultValue)}}b.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(e,t){b.fn[e]=function(e){var n,r=0,i=[],o=b(e),a=o.length-1;for(;a>=r;r++)n=r===a?this:this.clone(!0),b(o[r])[t](n),d.apply(i,n.get());return this.pushStack(i)}});function Ot(e,n){var r,o,a=0,s=typeof e.getElementsByTagName!==i?e.getElementsByTagName(n||"*"):typeof e.querySelectorAll!==i?e.querySelectorAll(n||"*"):t;if(!s)for(s=[],r=e.childNodes||e;null!=(o=r[a]);a++)!n||b.nodeName(o,n)?s.push(o):b.merge(s,Ot(o,n));return n===t||n&&b.nodeName(e,n)?b.merge([e],s):s}function Bt(e){Nt.test(e.type)&&(e.defaultChecked=e.checked)}b.extend({clone:function(e,t,n){var r,i,o,a,s,u=b.contains(e.ownerDocument,e);if(b.supp
 ort.html5Clone||b.isXMLDoc(e)||!mt.test("<"+e.nodeName+">")?o=e.cloneNode(!0):(Dt.innerHTML=e.outerHTML,Dt.removeChild(o=Dt.firstChild)),!(b.support.noCloneEvent&&b.support.noCloneChecked||1!==e.nodeType&&11!==e.nodeType||b.isXMLDoc(e)))for(r=Ot(o),s=Ot(e),a=0;null!=(i=s[a]);++a)r[a]&&Ft(i,r[a]);if(t)if(n)for(s=s||Ot(e),r=r||Ot(o),a=0;null!=(i=s[a]);a++)_t(i,r[a]);else _t(e,o);return r=Ot(o,"script"),r.length>0&&Mt(r,!u&&Ot(e,"script")),r=s=i=null,o},buildFragment:function(e,t,n,r){var i,o,a,s,u,l,c,p=e.length,f=dt(t),d=[],h=0;for(;p>h;h++)if(o=e[h],o||0===o)if("object"===b.type(o))b.merge(d,o.nodeType?[o]:o);else if(wt.test(o)){s=s||f.appendChild(t.createElement("div")),u=(bt.exec(o)||["",""])[1].toLowerCase(),c=At[u]||At._default,s.innerHTML=c[1]+o.replace(vt,"<$1></$2>")+c[2],i=c[0];while(i--)s=s.lastChild;if(!b.support.leadingWhitespace&&yt.test(o)&&d.push(t.createTextNode(yt.exec(o)[0])),!b.support.tbody){o="table"!==u||xt.test(o)?"<table>"!==c[1]||xt.test(o)?0:s:s.firstChild,i
 =o&&o.childNodes.length;while(i--)b.nodeName(l=o.childNodes[i],"tbody")&&!l.childNodes.length&&o.removeChild(l)
+}b.merge(d,s.childNodes),s.textContent="";while(s.firstChild)s.removeChild(s.firstChild);s=f.lastChild}else d.push(t.createTextNode(o));s&&f.removeChild(s),b.support.appendChecked||b.grep(Ot(d,"input"),Bt),h=0;while(o=d[h++])if((!r||-1===b.inArray(o,r))&&(a=b.contains(o.ownerDocument,o),s=Ot(f.appendChild(o),"script"),a&&Mt(s),n)){i=0;while(o=s[i++])kt.test(o.type||"")&&n.push(o)}return s=null,f},cleanData:function(e,t){var n,r,o,a,s=0,u=b.expando,l=b.cache,p=b.support.deleteExpando,f=b.event.special;for(;null!=(n=e[s]);s++)if((t||b.acceptData(n))&&(o=n[u],a=o&&l[o])){if(a.events)for(r in a.events)f[r]?b.event.remove(n,r):b.removeEvent(n,r,a.handle);l[o]&&(delete l[o],p?delete n[u]:typeof n.removeAttribute!==i?n.removeAttribute(u):n[u]=null,c.push(o))}}});var Pt,Rt,Wt,$t=/alpha\([^)]*\)/i,It=/opacity\s*=\s*([^)]*)/,zt=/^(top|right|bottom|left)$/,Xt=/^(none|table(?!-c[ea]).+)/,Ut=/^margin/,Vt=RegExp("^("+x+")(.*)$","i"),Yt=RegExp("^("+x+")(?!px)[a-z%]+$","i"),Jt=RegExp("^([+-])=("+x+
 ")","i"),Gt={BODY:"block"},Qt={position:"absolute",visibility:"hidden",display:"block"},Kt={letterSpacing:0,fontWeight:400},Zt=["Top","Right","Bottom","Left"],en=["Webkit","O","Moz","ms"];function tn(e,t){if(t in e)return t;var n=t.charAt(0).toUpperCase()+t.slice(1),r=t,i=en.length;while(i--)if(t=en[i]+n,t in e)return t;return r}function nn(e,t){return e=t||e,"none"===b.css(e,"display")||!b.contains(e.ownerDocument,e)}function rn(e,t){var n,r,i,o=[],a=0,s=e.length;for(;s>a;a++)r=e[a],r.style&&(o[a]=b._data(r,"olddisplay"),n=r.style.display,t?(o[a]||"none"!==n||(r.style.display=""),""===r.style.display&&nn(r)&&(o[a]=b._data(r,"olddisplay",un(r.nodeName)))):o[a]||(i=nn(r),(n&&"none"!==n||!i)&&b._data(r,"olddisplay",i?n:b.css(r,"display"))));for(a=0;s>a;a++)r=e[a],r.style&&(t&&"none"!==r.style.display&&""!==r.style.display||(r.style.display=t?o[a]||"":"none"));return e}b.fn.extend({css:function(e,n){return b.access(this,function(e,n,r){var i,o,a={},s=0;if(b.isArray(n)){for(o=Rt(e),i=n.
 length;i>s;s++)a[n[s]]=b.css(e,n[s],!1,o);return a}return r!==t?b.style(e,n,r):b.css(e,n)},e,n,arguments.length>1)},show:function(){return rn(this,!0)},hide:function(){return rn(this)},toggle:function(e){var t="boolean"==typeof e;return this.each(function(){(t?e:nn(this))?b(this).show():b(this).hide()})}}),b.extend({cssHooks:{opacity:{get:function(e,t){if(t){var n=Wt(e,"opacity");return""===n?"1":n}}}},cssNumber:{columnCount:!0,fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":b.support.cssFloat?"cssFloat":"styleFloat"},style:function(e,n,r,i){if(e&&3!==e.nodeType&&8!==e.nodeType&&e.style){var o,a,s,u=b.camelCase(n),l=e.style;if(n=b.cssProps[u]||(b.cssProps[u]=tn(l,u)),s=b.cssHooks[n]||b.cssHooks[u],r===t)return s&&"get"in s&&(o=s.get(e,!1,i))!==t?o:l[n];if(a=typeof r,"string"===a&&(o=Jt.exec(r))&&(r=(o[1]+1)*o[2]+parseFloat(b.css(e,n)),a="number"),!(null==r||"number"===a&&isNaN(r)||("number"!==a||b.cssNumber[u]||(r+="px"
 ),b.support.clearCloneStyle||""!==r||0!==n.indexOf("background")||(l[n]="inherit"),s&&"set"in s&&(r=s.set(e,r,i))===t)))try{l[n]=r}catch(c){}}},css:function(e,n,r,i){var o,a,s,u=b.camelCase(n);return n=b.cssProps[u]||(b.cssProps[u]=tn(e.style,u)),s=b.cssHooks[n]||b.cssHooks[u],s&&"get"in s&&(a=s.get(e,!0,r)),a===t&&(a=Wt(e,n,i)),"normal"===a&&n in Kt&&(a=Kt[n]),""===r||r?(o=parseFloat(a),r===!0||b.isNumeric(o)?o||0:a):a},swap:function(e,t,n,r){var i,o,a={};for(o in t)a[o]=e.style[o],e.style[o]=t[o];i=n.apply(e,r||[]);for(o in t)e.style[o]=a[o];return i}}),e.getComputedStyle?(Rt=function(t){return e.getComputedStyle(t,null)},Wt=function(e,n,r){var i,o,a,s=r||Rt(e),u=s?s.getPropertyValue(n)||s[n]:t,l=e.style;return s&&(""!==u||b.contains(e.ownerDocument,e)||(u=b.style(e,n)),Yt.test(u)&&Ut.test(n)&&(i=l.width,o=l.minWidth,a=l.maxWidth,l.minWidth=l.maxWidth=l.width=u,u=s.width,l.width=i,l.minWidth=o,l.maxWidth=a)),u}):o.documentElement.currentStyle&&(Rt=function(e){return e.currentStyle
 },Wt=function(e,n,r){var i,o,a,s=r||Rt(e),u=s?s[n]:t,l=e.style;return null==u&&l&&l[n]&&(u=l[n]),Yt.test(u)&&!zt.test(n)&&(i=l.left,o=e.runtimeStyle,a=o&&o.left,a&&(o.left=e.currentStyle.left),l.left="fontSize"===n?"1em":u,u=l.pixelLeft+"px",l.left=i,a&&(o.left=a)),""===u?"auto":u});function on(e,t,n){var r=Vt.exec(t);return r?Math.max(0,r[1]-(n||0))+(r[2]||"px"):t}function an(e,t,n,r,i){var o=n===(r?"border":"content")?4:"width"===t?1:0,a=0;for(;4>o;o+=2)"margin"===n&&(a+=b.css(e,n+Zt[o],!0,i)),r?("content"===n&&(a-=b.css(e,"padding"+Zt[o],!0,i)),"margin"!==n&&(a-=b.css(e,"border"+Zt[o]+"Width",!0,i))):(a+=b.css(e,"padding"+Zt[o],!0,i),"padding"!==n&&(a+=b.css(e,"border"+Zt[o]+"Width",!0,i)));return a}function sn(e,t,n){var r=!0,i="width"===t?e.offsetWidth:e.offsetHeight,o=Rt(e),a=b.support.boxSizing&&"border-box"===b.css(e,"boxSizing",!1,o);if(0>=i||null==i){if(i=Wt(e,t,o),(0>i||null==i)&&(i=e.style[t]),Yt.test(i))return i;r=a&&(b.support.boxSizingReliable||i===e.style[t]),i=parse
 Float(i)||0}return i+an(e,t,n||(a?"border":"content"),r,o)+"px"}function un(e){var t=o,n=Gt[e];return n||(n=ln(e,t),"none"!==n&&n||(Pt=(Pt||b("<iframe frameborder='0' width='0' height='0'/>").css("cssText","display:block !important")).appendTo(t.documentElement),t=(Pt[0].contentWindow||Pt[0].contentDocument).document,t.write("<!doctype html><html><body>"),t.close(),n=ln(e,t),Pt.detach()),Gt[e]=n),n}function ln(e,t){var n=b(t.createElement(e)).appendTo(t.body),r=b.css(n[0],"display");return n.remove(),r}b.each(["height","width"],function(e,n){b.cssHooks[n]={get:function(e,r,i){return r?0===e.offsetWidth&&Xt.test(b.css(e,"display"))?b.swap(e,Qt,function(){return sn(e,n,i)}):sn(e,n,i):t},set:function(e,t,r){var i=r&&Rt(e);return on(e,t,r?an(e,n,r,b.support.boxSizing&&"border-box"===b.css(e,"boxSizing",!1,i),i):0)}}}),b.support.opacity||(b.cssHooks.opacity={get:function(e,t){return It.test((t&&e.currentStyle?e.currentStyle.filter:e.style.filter)||"")?.01*parseFloat(RegExp.$1)+"":t?"1":"
 "},set:function(e,t){var n=e.style,r=e.currentStyle,i=b.isNumeric(t)?"alpha(opacity="+100*t+")":"",o=r&&r.filter||n.filter||"";n.zoom=1,(t>=1||""===t)&&""===b.trim(o.replace($t,""))&&n.removeAttribute&&(n.removeAttribute("filter"),""===t||r&&!r.filter)||(n.filter=$t.test(o)?o.replace($t,i):o+" "+i)}}),b(function(){b.support.reliableMarginRight||(b.cssHooks.marginRight={get:function(e,n){return n?b.swap(e,{display:"inline-block"},Wt,[e,"marginRight"]):t}}),!b.support.pixelPosition&&b.fn.position&&b.each(["top","left"],function(e,n){b.cssHooks[n]={get:function(e,r){return r?(r=Wt(e,n),Yt.test(r)?b(e).position()[n]+"px":r):t}}})}),b.expr&&b.expr.filters&&(b.expr.filters.hidden=function(e){return 0>=e.offsetWidth&&0>=e.offsetHeight||!b.support.reliableHiddenOffsets&&"none"===(e.style&&e.style.display||b.css(e,"display"))},b.expr.filters.visible=function(e){return!b.expr.filters.hidden(e)}),b.each({margin:"",padding:"",border:"Width"},function(e,t){b.cssHooks[e+t]={expand:function(n){var
  r=0,i={},o="string"==typeof n?n.split(" "):[n];for(;4>r;r++)i[e+Zt[r]+t]=o[r]||o[r-2]||o[0];return i}},Ut.test(e)||(b.cssHooks[e+t].set=on)});var cn=/%20/g,pn=/\[\]$/,fn=/\r?\n/g,dn=/^(?:submit|button|image|reset|file)$/i,hn=/^(?:input|select|textarea|keygen)/i;b.fn.extend({serialize:function(){return b.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var e=b.prop(this,"elements");return e?b.makeArray(e):this}).filter(function(){var e=this.type;return this.name&&!b(this).is(":disabled")&&hn.test(this.nodeName)&&!dn.test(e)&&(this.checked||!Nt.test(e))}).map(function(e,t){var n=b(this).val();return null==n?null:b.isArray(n)?b.map(n,function(e){return{name:t.name,value:e.replace(fn,"\r\n")}}):{name:t.name,value:n.replace(fn,"\r\n")}}).get()}}),b.param=function(e,n){var r,i=[],o=function(e,t){t=b.isFunction(t)?t():null==t?"":t,i[i.length]=encodeURIComponent(e)+"="+encodeURIComponent(t)};if(n===t&&(n=b.ajaxSettings&&b.ajaxSettings.traditional),b.isArra
 y(e)||e.jquery&&!b.isPlainObject(e))b.each(e,function(){o(this.name,this.value)});else for(r in e)gn(r,e[r],n,o);return i.join("&").replace(cn,"+")};function gn(e,t,n,r){var i;if(b.isArray(t))b.each(t,function(t,i){n||pn.test(e)?r(e,i):gn(e+"["+("object"==typeof i?t:"")+"]",i,n,r)});else if(n||"object"!==b.type(t))r(e,t);else for(i in t)gn(e+"["+i+"]",t[i],n,r)}b.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error contextmenu".split(" "),function(e,t){b.fn[t]=function(e,n){return arguments.length>0?this.on(t,null,e,n):this.trigger(t)}}),b.fn.hover=function(e,t){return this.mouseenter(e).mouseleave(t||e)};var mn,yn,vn=b.now(),bn=/\?/,xn=/#.*$/,wn=/([?&])_=[^&]*/,Tn=/^(.*?):[ \t]*([^\r\n]*)\r?$/gm,Nn=/^(?:about|app|app-storage|.+-extension|file|res|widget):$/,Cn=/^(?:GET|HEAD)$/,kn=/^\/\//,En=/^([\w.+-]+:)(?:\/\/([^\/?#:]*)(?::(\d+)|)|)/,Sn=b.fn
 .load,An={},jn={},Dn="*/".concat("*");try{yn=a.href}catch(Ln){yn=o.createElement("a"),yn.href="",yn=yn.href}mn=En.exec(yn.toLowerCase())||[];function Hn(e){return function(t,n){"string"!=typeof t&&(n=t,t="*");var r,i=0,o=t.toLowerCase().match(w)||[];if(b.isFunction(n))while(r=o[i++])"+"===r[0]?(r=r.slice(1)||"*",(e[r]=e[r]||[]).unshift(n)):(e[r]=e[r]||[]).push(n)}}function qn(e,n,r,i){var o={},a=e===jn;function s(u){var l;return o[u]=!0,b.each(e[u]||[],function(e,u){var c=u(n,r,i);return"string"!=typeof c||a||o[c]?a?!(l=c):t:(n.dataTypes.unshift(c),s(c),!1)}),l}return s(n.dataTypes[0])||!o["*"]&&s("*")}function Mn(e,n){var r,i,o=b.ajaxSettings.flatOptions||{};for(i in n)n[i]!==t&&((o[i]?e:r||(r={}))[i]=n[i]);return r&&b.extend(!0,e,r),e}b.fn.load=function(e,n,r){if("string"!=typeof e&&Sn)return Sn.apply(this,arguments);var i,o,a,s=this,u=e.indexOf(" ");return u>=0&&(i=e.slice(u,e.length),e=e.slice(0,u)),b.isFunction(n)?(r=n,n=t):n&&"object"==typeof n&&(a="POST"),s.length>0&&b.ajax({
 url:e,type:a,dataType:"html",data:n}).done(function(e){o=arguments,s.html(i?b("<div>").append(b.parseHTML(e)).find(i):e)}).complete(r&&function(e,t){s.each(r,o||[e.responseText,t,e])}),this},b.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(e,t){b.fn[t]=function(e){return this.on(t,e)}}),b.each(["get","post"],function(e,n){b[n]=function(e,r,i,o){return b.isFunction(r)&&(o=o||i,i=r,r=t),b.ajax({url:e,type:n,dataType:o,data:r,success:i})}}),b.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:yn,type:"GET",isLocal:Nn.test(mn[1]),global:!0,processData:!0,async:!0,contentType:"application/x-www-form-urlencoded; charset=UTF-8",accepts:{"*":Dn,text:"text/plain",html:"text/html",xml:"application/xml, text/xml",json:"application/json, text/javascript"},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":e.String,"text html":!0,"text json":b.parseJSON,"text xml":b.parseXML}
 ,flatOptions:{url:!0,context:!0}},ajaxSetup:function(e,t){return t?Mn(Mn(e,b.ajaxSettings),t):Mn(b.ajaxSettings,e)},ajaxPrefilter:Hn(An),ajaxTransport:Hn(jn),ajax:function(e,n){"object"==typeof e&&(n=e,e=t),n=n||{};var r,i,o,a,s,u,l,c,p=b.ajaxSetup({},n),f=p.context||p,d=p.context&&(f.nodeType||f.jquery)?b(f):b.event,h=b.Deferred(),g=b.Callbacks("once memory"),m=p.statusCode||{},y={},v={},x=0,T="canceled",N={readyState:0,getResponseHeader:function(e){var t;if(2===x){if(!c){c={};while(t=Tn.exec(a))c[t[1].toLowerCase()]=t[2]}t=c[e.toLowerCase()]}return null==t?null:t},getAllResponseHeaders:function(){return 2===x?a:null},setRequestHeader:function(e,t){var n=e.toLowerCase();return x||(e=v[n]=v[n]||e,y[e]=t),this},overrideMimeType:function(e){return x||(p.mimeType=e),this},statusCode:function(e){var t;if(e)if(2>x)for(t in e)m[t]=[m[t],e[t]];else N.always(e[N.status]);return this},abort:function(e){var t=e||T;return l&&l.abort(t),k(0,t),this}};if(h.promise(N).complete=g.add,N.success=N.d
 one,N.error=N.fail,p.url=((e||p.url||yn)+"").replace(xn,"").replace(kn,mn[1]+"//"),p.type=n.method||n.type||p.method||p.type,p.dataTypes=b.trim(p.dataType||"*").toLowerCase().match(w)||[""],null==p.crossDomain&&(r=En.exec(p.url.toLowerCase()),p.crossDomain=!(!r||r[1]===mn[1]&&r[2]===mn[2]&&(r[3]||("http:"===r[1]?80:443))==(mn[3]||("http:"===mn[1]?80:443)))),p.data&&p.processData&&"string"!=typeof p.data&&(p.data=b.param(p.data,p.traditional)),qn(An,p,n,N),2===x)return N;u=p.global,u&&0===b.active++&&b.event.trigger("ajaxStart"),p.type=p.type.toUpperCase(),p.hasContent=!Cn.test(p.type),o=p.url,p.hasContent||(p.data&&(o=p.url+=(bn.test(o)?"&":"?")+p.data,delete p.data),p.cache===!1&&(p.url=wn.test(o)?o.replace(wn,"$1_="+vn++):o+(bn.test(o)?"&":"?")+"_="+vn++)),p.ifModified&&(b.lastModified[o]&&N.setRequestHeader("If-Modified-Since",b.lastModified[o]),b.etag[o]&&N.setRequestHeader("If-None-Match",b.etag[o])),(p.data&&p.hasContent&&p.contentType!==!1||n.contentType)&&N.setRequestHeader(
 "Content-Type",p.contentType),N.setRequestHeader("Accept",p.dataTypes[0]&&p.accepts[p.dataTypes[0]]?p.accepts[p.dataTypes[0]]+("*"!==p.dataTypes[0]?", "+Dn+"; q=0.01":""):p.accepts["*"]);for(i in p.headers)N.setRequestHeader(i,p.headers[i]);if(p.beforeSend&&(p.beforeSend.call(f,N,p)===!1||2===x))return N.abort();T="abort";for(i in{success:1,error:1,complete:1})N[i](p[i]);if(l=qn(jn,p,n,N)){N.readyState=1,u&&d.trigger("ajaxSend",[N,p]),p.async&&p.timeout>0&&(s=setTimeout(function(){N.abort("timeout")},p.timeout));try{x=1,l.send(y,k)}catch(C){if(!(2>x))throw C;k(-1,C)}}else k(-1,"No Transport");function k(e,n,r,i){var c,y,v,w,T,C=n;2!==x&&(x=2,s&&clearTimeout(s),l=t,a=i||"",N.readyState=e>0?4:0,r&&(w=_n(p,N,r)),e>=200&&300>e||304===e?(p.ifModified&&(T=N.getResponseHeader("Last-Modified"),T&&(b.lastModified[o]=T),T=N.getResponseHeader("etag"),T&&(b.etag[o]=T)),204===e?(c=!0,C="nocontent"):304===e?(c=!0,C="notmodified"):(c=Fn(p,w),C=c.state,y=c.data,v=c.error,c=!v)):(v=C,(e||!C)&&(C="er
 ror",0>e&&(e=0))),N.status=e,N.statusText=(n||C)+"",c?h.resolveWith(f,[y,C,N]):h.rejectWith(f,[N,C,v]),N.statusCode(m),m=t,u&&d.trigger(c?"ajaxSuccess":"ajaxError",[N,p,c?y:v]),g.fireWith(f,[N,C]),u&&(d.trigger("ajaxComplete",[N,p]),--b.active||b.event.trigger("ajaxStop")))}return N},getScript:function(e,n){return b.get(e,t,n,"script")},getJSON:function(e,t,n){return b.get(e,t,n,"json")}});function _n(e,n,r){var i,o,a,s,u=e.contents,l=e.dataTypes,c=e.responseFields;for(s in c)s in r&&(n[c[s]]=r[s]);while("*"===l[0])l.shift(),o===t&&(o=e.mimeType||n.getResponseHeader("Content-Type"));if(o)for(s in u)if(u[s]&&u[s].test(o)){l.unshift(s);break}if(l[0]in r)a=l[0];else{for(s in r){if(!l[0]||e.converters[s+" "+l[0]]){a=s;break}i||(i=s)}a=a||i}return a?(a!==l[0]&&l.unshift(a),r[a]):t}function Fn(e,t){var n,r,i,o,a={},s=0,u=e.dataTypes.slice(),l=u[0];if(e.dataFilter&&(t=e.dataFilter(t,e.dataType)),u[1])for(i in e.converters)a[i.toLowerCase()]=e.converters[i];for(;r=u[++s];)if("*"!==r){if("*"
 !==l&&l!==r){if(i=a[l+" "+r]||a["* "+r],!i)for(n in a)if(o=n.split(" "),o[1]===r&&(i=a[l+" "+o[0]]||a["* "+o[0]])){i===!0?i=a[n]:a[n]!==!0&&(r=o[0],u.splice(s--,0,r));break}if(i!==!0)if(i&&e["throws"])t=i(t);else try{t=i(t)}catch(c){return{state:"parsererror",error:i?c:"No conversion from "+l+" to "+r}}}l=r}return{state:"success",data:t}}b.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/(?:java|ecma)script/},converters:{"text script":function(e){return b.globalEval(e),e}}}),b.ajaxPrefilter("script",function(e){e.cache===t&&(e.cache=!1),e.crossDomain&&(e.type="GET",e.global=!1)}),b.ajaxTransport("script",function(e){if(e.crossDomain){var n,r=o.head||b("head")[0]||o.documentElement;return{send:function(t,i){n=o.createElement("script"),n.async=!0,e.scriptCharset&&(n.charset=e.scriptCharset),n.src=e.url,n.onload=n.onreadystatechange=function(e,t){(t||!n.readyState||/loaded|complete/.test(n.readySta
 te))&&(n.onload=n.onreadystatechange=null,n.parentNode&&n.parentNode.removeChild(n),n=null,t||i(200,"success"))},r.insertBefore(n,r.firstChild)},abort:function(){n&&n.onload(t,!0)}}}});var On=[],Bn=/(=)\?(?=&|$)|\?\?/;b.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=On.pop()||b.expando+"_"+vn++;return this[e]=!0,e}}),b.ajaxPrefilter("json jsonp",function(n,r,i){var o,a,s,u=n.jsonp!==!1&&(Bn.test(n.url)?"url":"string"==typeof n.data&&!(n.contentType||"").indexOf("application/x-www-form-urlencoded")&&Bn.test(n.data)&&"data");return u||"jsonp"===n.dataTypes[0]?(o=n.jsonpCallback=b.isFunction(n.jsonpCallback)?n.jsonpCallback():n.jsonpCallback,u?n[u]=n[u].replace(Bn,"$1"+o):n.jsonp!==!1&&(n.url+=(bn.test(n.url)?"&":"?")+n.jsonp+"="+o),n.converters["script json"]=function(){return s||b.error(o+" was not called"),s[0]},n.dataTypes[0]="json",a=e[o],e[o]=function(){s=arguments},i.always(function(){e[o]=a,n[o]&&(n.jsonpCallback=r.jsonpCallback,On.push(o)),s&&b.isFunction(a)&&a(s[0
 ]),s=a=t}),"script"):t});var Pn,Rn,Wn=0,$n=e.ActiveXObject&&function(){var e;for(e in Pn)Pn[e](t,!0)};function In(){try{return new e.XMLHttpRequest}catch(t){}}function zn(){try{return new e.ActiveXObject("Microsoft.XMLHTTP")}catch(t){}}b.ajaxSettings.xhr=e.ActiveXObject?function(){return!this.isLocal&&In()||zn()}:In,Rn=b.ajaxSettings.xhr(),b.support.cors=!!Rn&&"withCredentials"in Rn,Rn=b.support.ajax=!!Rn,Rn&&b.ajaxTransport(function(n){if(!n.crossDomain||b.support.cors){var r;return{send:function(i,o){var a,s,u=n.xhr();if(n.username?u.open(n.type,n.url,n.async,n.username,n.password):u.open(n.type,n.url,n.async),n.xhrFields)for(s in n.xhrFields)u[s]=n.xhrFields[s];n.mimeType&&u.overrideMimeType&&u.overrideMimeType(n.mimeType),n.crossDomain||i["X-Requested-With"]||(i["X-Requested-With"]="XMLHttpRequest");try{for(s in i)u.setRequestHeader(s,i[s])}catch(l){}u.send(n.hasContent&&n.data||null),r=function(e,i){var s,l,c,p;try{if(r&&(i||4===u.readyState))if(r=t,a&&(u.onreadystatechange=b.n
 oop,$n&&delete Pn[a]),i)4!==u.readyState&&u.abort();else{p={},s=u.status,l=u.getAllResponseHeaders(),"string"==typeof u.responseText&&(p.text=u.responseText);try{c=u.statusText}catch(f){c=""}s||!n.isLocal||n.crossDomain?1223===s&&(s=204):s=p.text?200:404}}catch(d){i||o(-1,d)}p&&o(s,c,p,l)},n.async?4===u.readyState?setTimeout(r):(a=++Wn,$n&&(Pn||(Pn={},b(e).unload($n)),Pn[a]=r),u.onreadystatechange=r):r()},abort:function(){r&&r(t,!0)}}}});var Xn,Un,Vn=/^(?:toggle|show|hide)$/,Yn=RegExp("^(?:([+-])=|)("+x+")([a-z%]*)$","i"),Jn=/queueHooks$/,Gn=[nr],Qn={"*":[function(e,t){var n,r,i=this.createTween(e,t),o=Yn.exec(t),a=i.cur(),s=+a||0,u=1,l=20;if(o){if(n=+o[2],r=o[3]||(b.cssNumber[e]?"":"px"),"px"!==r&&s){s=b.css(i.elem,e,!0)||n||1;do u=u||".5",s/=u,b.style(i.elem,e,s+r);while(u!==(u=i.cur()/a)&&1!==u&&--l)}i.unit=r,i.start=s,i.end=o[1]?s+(o[1]+1)*n:n}return i}]};function Kn(){return setTimeout(function(){Xn=t}),Xn=b.now()}function Zn(e,t){b.each(t,function(t,n){var r=(Qn[t]||[]).concat
 (Qn["*"]),i=0,o=r.length;for(;o>i;i++)if(r[i].call(e,t,n))return})}function er(e,t,n){var r,i,o=0,a=Gn.length,s=b.Deferred().always(function(){delete u.elem}),u=function(){if(i)return!1;var t=Xn||Kn(),n=Math.max(0,l.startTime+l.duration-t),r=n/l.duration||0,o=1-r,a=0,u=l.tweens.length;for(;u>a;a++)l.tweens[a].run(o);return s.notifyWith(e,[l,o,n]),1>o&&u?n:(s.resolveWith(e,[l]),!1)},l=s.promise({elem:e,props:b.extend({},t),opts:b.extend(!0,{specialEasing:{}},n),originalProperties:t,originalOptions:n,startTime:Xn||Kn(),duration:n.duration,tweens:[],createTween:function(t,n){var r=b.Tween(e,l.opts,t,n,l.opts.specialEasing[t]||l.opts.easing);return l.tweens.push(r),r},stop:function(t){var n=0,r=t?l.tweens.length:0;if(i)return this;for(i=!0;r>n;n++)l.tweens[n].run(1);return t?s.resolveWith(e,[l,t]):s.rejectWith(e,[l,t]),this}}),c=l.props;for(tr(c,l.opts.specialEasing);a>o;o++)if(r=Gn[o].call(l,e,c,l.opts))return r;return Zn(l,c),b.isFunction(l.opts.start)&&l.opts.start.call(e,l),b.fx.tim
 er(b.extend(u,{elem:e,anim:l,queue:l.opts.queue})),l.progress(l.opts.progress).done(l.opts.done,l.opts.complete).fail(l.opts.fail).always(l.opts.always)}function tr(e,t){var n,r,i,o,a;for(i in e)if(r=b.camelCase(i),o=t[r],n=e[i],b.isArray(n)&&(o=n[1],n=e[i]=n[0]),i!==r&&(e[r]=n,delete e[i]),a=b.cssHooks[r],a&&"expand"in a){n=a.expand(n),delete e[r];for(i in n)i in e||(e[i]=n[i],t[i]=o)}else t[r]=o}b.Animation=b.extend(er,{tweener:function(e,t){b.isFunction(e)?(t=e,e=["*"]):e=e.split(" ");var n,r=0,i=e.length;for(;i>r;r++)n=e[r],Qn[n]=Qn[n]||[],Qn[n].unshift(t)},prefilter:function(e,t){t?Gn.unshift(e):Gn.push(e)}});function nr(e,t,n){var r,i,o,a,s,u,l,c,p,f=this,d=e.style,h={},g=[],m=e.nodeType&&nn(e);n.queue||(c=b._queueHooks(e,"fx"),null==c.unqueued&&(c.unqueued=0,p=c.empty.fire,c.empty.fire=function(){c.unqueued||p()}),c.unqueued++,f.always(function(){f.always(function(){c.unqueued--,b.queue(e,"fx").length||c.empty.fire()})})),1===e.nodeType&&("height"in t||"width"in t)&&(n.overfl
 ow=[d.overflow,d.overflowX,d.overflowY],"inline"===b.css(e,"display")&&"none"===b.css(e,"float")&&(b.support.inlineBlockNeedsLayout&&"inline"!==un(e.nodeName)?d.zoom=1:d.display="inline-block")),n.overflow&&(d.overflow="hidden",b.support.shrinkWrapBlocks||f.always(function(){d.overflow=n.overflow[0],d.overflowX=n.overflow[1],d.overflowY=n.overflow[2]}));for(i in t)if(a=t[i],Vn.exec(a)){if(delete t[i],u=u||"toggle"===a,a===(m?"hide":"show"))continue;g.push(i)}if(o=g.length){s=b._data(e,"fxshow")||b._data(e,"fxshow",{}),"hidden"in s&&(m=s.hidden),u&&(s.hidden=!m),m?b(e).show():f.done(function(){b(e).hide()}),f.done(function(){var t;b._removeData(e,"fxshow");for(t in h)b.style(e,t,h[t])});for(i=0;o>i;i++)r=g[i],l=f.createTween(r,m?s[r]:0),h[r]=s[r]||b.style(e,r),r in s||(s[r]=l.start,m&&(l.end=l.start,l.start="width"===r||"height"===r?1:0))}}function rr(e,t,n,r,i){return new rr.prototype.init(e,t,n,r,i)}b.Tween=rr,rr.prototype={constructor:rr,init:function(e,t,n,r,i,o){this.elem=e,this
 .prop=n,this.easing=i||"swing",this.options=t,this.start=this.now=this.cur(),this.end=r,this.unit=o||(b.cssNumber[n]?"":"px")},cur:function(){var e=rr.propHooks[this.prop];return e&&e.get?e.get(this):rr.propHooks._default.get(this)},run:function(e){var t,n=rr.propHooks[this.prop];return this.pos=t=this.options.duration?b.easing[this.easing](e,this.options.duration*e,0,1,this.options.duration):e,this.now=(this.end-this.start)*t+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),n&&n.set?n.set(this):rr.propHooks._default.set(this),this}},rr.prototype.init.prototype=rr.prototype,rr.propHooks={_default:{get:function(e){var t;return null==e.elem[e.prop]||e.elem.style&&null!=e.elem.style[e.prop]?(t=b.css(e.elem,e.prop,""),t&&"auto"!==t?t:0):e.elem[e.prop]},set:function(e){b.fx.step[e.prop]?b.fx.step[e.prop](e):e.elem.style&&(null!=e.elem.style[b.cssProps[e.prop]]||b.cssHooks[e.prop])?b.style(e.elem,e.prop,e.now+e.unit):e.elem[e.prop]=e.now}}},rr.propHooks.scroll
 Top=rr.propHooks.scrollLeft={set:function(e){e.elem.nodeType&&e.elem.parentNode&&(e.elem[e.prop]=e.now)}},b.each(["toggle","show","hide"],function(e,t){var n=b.fn[t];b.fn[t]=function(e,r,i){return null==e||"boolean"==typeof e?n.apply(this,arguments):this.animate(ir(t,!0),e,r,i)}}),b.fn.extend({fadeTo:function(e,t,n,r){return this.filter(nn).css("opacity",0).show().end().animate({opacity:t},e,n,r)},animate:function(e,t,n,r){var i=b.isEmptyObject(e),o=b.speed(t,n,r),a=function(){var t=er(this,b.extend({},e),o);a.finish=function(){t.stop(!0)},(i||b._data(this,"finish"))&&t.stop(!0)};return a.finish=a,i||o.queue===!1?this.each(a):this.queue(o.queue,a)},stop:function(e,n,r){var i=function(e){var t=e.stop;delete e.stop,t(r)};return"string"!=typeof e&&(r=n,n=e,e=t),n&&e!==!1&&this.queue(e||"fx",[]),this.each(function(){var t=!0,n=null!=e&&e+"queueHooks",o=b.timers,a=b._data(this);if(n)a[n]&&a[n].stop&&i(a[n]);else for(n in a)a[n]&&a[n].stop&&Jn.test(n)&&i(a[n]);for(n=o.length;n--;)o[n].ele
 m!==this||null!=e&&o[n].queue!==e||(o[n].anim.stop(r),t=!1,o.splice(n,1));(t||!r)&&b.dequeue(this,e)})},finish:function(e){return e!==!1&&(e=e||"fx"),this.each(function(){var t,n=b._data(this),r=n[e+"queue"],i=n[e+"queueHooks"],o=b.timers,a=r?r.length:0;for(n.finish=!0,b.queue(this,e,[]),i&&i.cur&&i.cur.finish&&i.cur.finish.call(this),t=o.length;t--;)o[t].elem===this&&o[t].queue===e&&(o[t].anim.stop(!0),o.splice(t,1));for(t=0;a>t;t++)r[t]&&r[t].finish&&r[t].finish.call(this);delete n.finish})}});function ir(e,t){var n,r={height:e},i=0;for(t=t?1:0;4>i;i+=2-t)n=Zt[i],r["margin"+n]=r["padding"+n]=e;return t&&(r.opacity=r.width=e),r}b.each({slideDown:ir("show"),slideUp:ir("hide"),slideToggle:ir("toggle"),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(e,t){b.fn[e]=function(e,n,r){return this.animate(t,e,n,r)}}),b.speed=function(e,t,n){var r=e&&"object"==typeof e?b.extend({},e):{complete:n||!n&&t||b.i

<TRUNCATED>

[19/51] [abbrv] [partial] Adding Jinwon's custom RCMET

Posted by jo...@apache.org.
http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/app/lib/angular/.svn/text-base/angular.js.svn-base
----------------------------------------------------------------------
diff --git a/src/main/ui/app/lib/angular/.svn/text-base/angular.js.svn-base b/src/main/ui/app/lib/angular/.svn/text-base/angular.js.svn-base
new file mode 100755
index 0000000..68b33c7
--- /dev/null
+++ b/src/main/ui/app/lib/angular/.svn/text-base/angular.js.svn-base
@@ -0,0 +1,14733 @@
+/**
+ * @license AngularJS v1.0.5
+ * (c) 2010-2012 Google, Inc. http://angularjs.org
+ * License: MIT
+ */
+(function(window, document, undefined) {
+'use strict';
+
+////////////////////////////////////
+
+/**
+ * @ngdoc function
+ * @name angular.lowercase
+ * @function
+ *
+ * @description Converts the specified string to lowercase.
+ * @param {string} string String to be converted to lowercase.
+ * @returns {string} Lowercased string.
+ */
+var lowercase = function(string){return isString(string) ? string.toLowerCase() : string;};
+
+
+/**
+ * @ngdoc function
+ * @name angular.uppercase
+ * @function
+ *
+ * @description Converts the specified string to uppercase.
+ * @param {string} string String to be converted to uppercase.
+ * @returns {string} Uppercased string.
+ */
+var uppercase = function(string){return isString(string) ? string.toUpperCase() : string;};
+
+
+var manualLowercase = function(s) {
+  return isString(s)
+      ? s.replace(/[A-Z]/g, function(ch) {return fromCharCode(ch.charCodeAt(0) | 32);})
+      : s;
+};
+var manualUppercase = function(s) {
+  return isString(s)
+      ? s.replace(/[a-z]/g, function(ch) {return fromCharCode(ch.charCodeAt(0) & ~32);})
+      : s;
+};
+
+
+// String#toLowerCase and String#toUpperCase don't produce correct results in browsers with Turkish
+// locale, for this reason we need to detect this case and redefine lowercase/uppercase methods
+// with correct but slower alternatives.
+if ('i' !== 'I'.toLowerCase()) {
+  lowercase = manualLowercase;
+  uppercase = manualUppercase;
+}
+
+function fromCharCode(code) {return String.fromCharCode(code);}
+
+
+var /** holds major version number for IE or NaN for real browsers */
+    msie              = int((/msie (\d+)/.exec(lowercase(navigator.userAgent)) || [])[1]),
+    jqLite,           // delay binding since jQuery could be loaded after us.
+    jQuery,           // delay binding
+    slice             = [].slice,
+    push              = [].push,
+    toString          = Object.prototype.toString,
+
+    /** @name angular */
+    angular           = window.angular || (window.angular = {}),
+    angularModule,
+    nodeName_,
+    uid               = ['0', '0', '0'];
+
+/**
+ * @ngdoc function
+ * @name angular.forEach
+ * @function
+ *
+ * @description
+ * Invokes the `iterator` function once for each item in `obj` collection, which can be either an
+ * object or an array. The `iterator` function is invoked with `iterator(value, key)`, where `value`
+ * is the value of an object property or an array element and `key` is the object property key or
+ * array element index. Specifying a `context` for the function is optional.
+ *
+ * Note: this function was previously known as `angular.foreach`.
+ *
+   <pre>
+     var values = {name: 'misko', gender: 'male'};
+     var log = [];
+     angular.forEach(values, function(value, key){
+       this.push(key + ': ' + value);
+     }, log);
+     expect(log).toEqual(['name: misko', 'gender:male']);
+   </pre>
+ *
+ * @param {Object|Array} obj Object to iterate over.
+ * @param {Function} iterator Iterator function.
+ * @param {Object=} context Object to become context (`this`) for the iterator function.
+ * @returns {Object|Array} Reference to `obj`.
+ */
+
+
+/**
+ * @private
+ * @param {*} obj
+ * @return {boolean} Returns true if `obj` is an array or array-like object (NodeList, Arguments, ...)
+ */
+function isArrayLike(obj) {
+  if (!obj || (typeof obj.length !== 'number')) return false;
+
+  // We have on object which has length property. Should we treat it as array?
+  if (typeof obj.hasOwnProperty != 'function' &&
+      typeof obj.constructor != 'function') {
+    // This is here for IE8: it is a bogus object treat it as array;
+    return true;
+  } else  {
+    return obj instanceof JQLite ||                      // JQLite
+           (jQuery && obj instanceof jQuery) ||          // jQuery
+           toString.call(obj) !== '[object Object]' ||   // some browser native object
+           typeof obj.callee === 'function';              // arguments (on IE8 looks like regular obj)
+  }
+}
+
+
+function forEach(obj, iterator, context) {
+  var key;
+  if (obj) {
+    if (isFunction(obj)){
+      for (key in obj) {
+        if (key != 'prototype' && key != 'length' && key != 'name' && obj.hasOwnProperty(key)) {
+          iterator.call(context, obj[key], key);
+        }
+      }
+    } else if (obj.forEach && obj.forEach !== forEach) {
+      obj.forEach(iterator, context);
+    } else if (isArrayLike(obj)) {
+      for (key = 0; key < obj.length; key++)
+        iterator.call(context, obj[key], key);
+    } else {
+      for (key in obj) {
+        if (obj.hasOwnProperty(key)) {
+          iterator.call(context, obj[key], key);
+        }
+      }
+    }
+  }
+  return obj;
+}
+
+function sortedKeys(obj) {
+  var keys = [];
+  for (var key in obj) {
+    if (obj.hasOwnProperty(key)) {
+      keys.push(key);
+    }
+  }
+  return keys.sort();
+}
+
+function forEachSorted(obj, iterator, context) {
+  var keys = sortedKeys(obj);
+  for ( var i = 0; i < keys.length; i++) {
+    iterator.call(context, obj[keys[i]], keys[i]);
+  }
+  return keys;
+}
+
+
+/**
+ * when using forEach the params are value, key, but it is often useful to have key, value.
+ * @param {function(string, *)} iteratorFn
+ * @returns {function(*, string)}
+ */
+function reverseParams(iteratorFn) {
+  return function(value, key) { iteratorFn(key, value) };
+}
+
+/**
+ * A consistent way of creating unique IDs in angular. The ID is a sequence of alpha numeric
+ * characters such as '012ABC'. The reason why we are not using simply a number counter is that
+ * the number string gets longer over time, and it can also overflow, where as the nextId
+ * will grow much slower, it is a string, and it will never overflow.
+ *
+ * @returns an unique alpha-numeric string
+ */
+function nextUid() {
+  var index = uid.length;
+  var digit;
+
+  while(index) {
+    index--;
+    digit = uid[index].charCodeAt(0);
+    if (digit == 57 /*'9'*/) {
+      uid[index] = 'A';
+      return uid.join('');
+    }
+    if (digit == 90  /*'Z'*/) {
+      uid[index] = '0';
+    } else {
+      uid[index] = String.fromCharCode(digit + 1);
+      return uid.join('');
+    }
+  }
+  uid.unshift('0');
+  return uid.join('');
+}
+
+/**
+ * @ngdoc function
+ * @name angular.extend
+ * @function
+ *
+ * @description
+ * Extends the destination object `dst` by copying all of the properties from the `src` object(s)
+ * to `dst`. You can specify multiple `src` objects.
+ *
+ * @param {Object} dst Destination object.
+ * @param {...Object} src Source object(s).
+ */
+function extend(dst) {
+  forEach(arguments, function(obj){
+    if (obj !== dst) {
+      forEach(obj, function(value, key){
+        dst[key] = value;
+      });
+    }
+  });
+  return dst;
+}
+
+function int(str) {
+  return parseInt(str, 10);
+}
+
+
+function inherit(parent, extra) {
+  return extend(new (extend(function() {}, {prototype:parent}))(), extra);
+}
+
+
+/**
+ * @ngdoc function
+ * @name angular.noop
+ * @function
+ *
+ * @description
+ * A function that performs no operations. This function can be useful when writing code in the
+ * functional style.
+   <pre>
+     function foo(callback) {
+       var result = calculateResult();
+       (callback || angular.noop)(result);
+     }
+   </pre>
+ */
+function noop() {}
+noop.$inject = [];
+
+
+/**
+ * @ngdoc function
+ * @name angular.identity
+ * @function
+ *
+ * @description
+ * A function that returns its first argument. This function is useful when writing code in the
+ * functional style.
+ *
+   <pre>
+     function transformer(transformationFn, value) {
+       return (transformationFn || identity)(value);
+     };
+   </pre>
+ */
+function identity($) {return $;}
+identity.$inject = [];
+
+
+function valueFn(value) {return function() {return value;};}
+
+/**
+ * @ngdoc function
+ * @name angular.isUndefined
+ * @function
+ *
+ * @description
+ * Determines if a reference is undefined.
+ *
+ * @param {*} value Reference to check.
+ * @returns {boolean} True if `value` is undefined.
+ */
+function isUndefined(value){return typeof value == 'undefined';}
+
+
+/**
+ * @ngdoc function
+ * @name angular.isDefined
+ * @function
+ *
+ * @description
+ * Determines if a reference is defined.
+ *
+ * @param {*} value Reference to check.
+ * @returns {boolean} True if `value` is defined.
+ */
+function isDefined(value){return typeof value != 'undefined';}
+
+
+/**
+ * @ngdoc function
+ * @name angular.isObject
+ * @function
+ *
+ * @description
+ * Determines if a reference is an `Object`. Unlike `typeof` in JavaScript, `null`s are not
+ * considered to be objects.
+ *
+ * @param {*} value Reference to check.
+ * @returns {boolean} True if `value` is an `Object` but not `null`.
+ */
+function isObject(value){return value != null && typeof value == 'object';}
+
+
+/**
+ * @ngdoc function
+ * @name angular.isString
+ * @function
+ *
+ * @description
+ * Determines if a reference is a `String`.
+ *
+ * @param {*} value Reference to check.
+ * @returns {boolean} True if `value` is a `String`.
+ */
+function isString(value){return typeof value == 'string';}
+
+
+/**
+ * @ngdoc function
+ * @name angular.isNumber
+ * @function
+ *
+ * @description
+ * Determines if a reference is a `Number`.
+ *
+ * @param {*} value Reference to check.
+ * @returns {boolean} True if `value` is a `Number`.
+ */
+function isNumber(value){return typeof value == 'number';}
+
+
+/**
+ * @ngdoc function
+ * @name angular.isDate
+ * @function
+ *
+ * @description
+ * Determines if a value is a date.
+ *
+ * @param {*} value Reference to check.
+ * @returns {boolean} True if `value` is a `Date`.
+ */
+function isDate(value){
+  return toString.apply(value) == '[object Date]';
+}
+
+
+/**
+ * @ngdoc function
+ * @name angular.isArray
+ * @function
+ *
+ * @description
+ * Determines if a reference is an `Array`.
+ *
+ * @param {*} value Reference to check.
+ * @returns {boolean} True if `value` is an `Array`.
+ */
+function isArray(value) {
+  return toString.apply(value) == '[object Array]';
+}
+
+
+/**
+ * @ngdoc function
+ * @name angular.isFunction
+ * @function
+ *
+ * @description
+ * Determines if a reference is a `Function`.
+ *
+ * @param {*} value Reference to check.
+ * @returns {boolean} True if `value` is a `Function`.
+ */
+function isFunction(value){return typeof value == 'function';}
+
+
+/**
+ * Checks if `obj` is a window object.
+ *
+ * @private
+ * @param {*} obj Object to check
+ * @returns {boolean} True if `obj` is a window obj.
+ */
+function isWindow(obj) {
+  return obj && obj.document && obj.location && obj.alert && obj.setInterval;
+}
+
+
+function isScope(obj) {
+  return obj && obj.$evalAsync && obj.$watch;
+}
+
+
+function isFile(obj) {
+  return toString.apply(obj) === '[object File]';
+}
+
+
+function isBoolean(value) {
+  return typeof value == 'boolean';
+}
+
+
+function trim(value) {
+  return isString(value) ? value.replace(/^\s*/, '').replace(/\s*$/, '') : value;
+}
+
+/**
+ * @ngdoc function
+ * @name angular.isElement
+ * @function
+ *
+ * @description
+ * Determines if a reference is a DOM element (or wrapped jQuery element).
+ *
+ * @param {*} value Reference to check.
+ * @returns {boolean} True if `value` is a DOM element (or wrapped jQuery element).
+ */
+function isElement(node) {
+  return node &&
+    (node.nodeName  // we are a direct element
+    || (node.bind && node.find));  // we have a bind and find method part of jQuery API
+}
+
+/**
+ * @param str 'key1,key2,...'
+ * @returns {object} in the form of {key1:true, key2:true, ...}
+ */
+function makeMap(str){
+  var obj = {}, items = str.split(","), i;
+  for ( i = 0; i < items.length; i++ )
+    obj[ items[i] ] = true;
+  return obj;
+}
+
+
+if (msie < 9) {
+  nodeName_ = function(element) {
+    element = element.nodeName ? element : element[0];
+    return (element.scopeName && element.scopeName != 'HTML')
+      ? uppercase(element.scopeName + ':' + element.nodeName) : element.nodeName;
+  };
+} else {
+  nodeName_ = function(element) {
+    return element.nodeName ? element.nodeName : element[0].nodeName;
+  };
+}
+
+
+function map(obj, iterator, context) {
+  var results = [];
+  forEach(obj, function(value, index, list) {
+    results.push(iterator.call(context, value, index, list));
+  });
+  return results;
+}
+
+
+/**
+ * @description
+ * Determines the number of elements in an array, the number of properties an object has, or
+ * the length of a string.
+ *
+ * Note: This function is used to augment the Object type in Angular expressions. See
+ * {@link angular.Object} for more information about Angular arrays.
+ *
+ * @param {Object|Array|string} obj Object, array, or string to inspect.
+ * @param {boolean} [ownPropsOnly=false] Count only "own" properties in an object
+ * @returns {number} The size of `obj` or `0` if `obj` is neither an object nor an array.
+ */
+function size(obj, ownPropsOnly) {
+  var size = 0, key;
+
+  if (isArray(obj) || isString(obj)) {
+    return obj.length;
+  } else if (isObject(obj)){
+    for (key in obj)
+      if (!ownPropsOnly || obj.hasOwnProperty(key))
+        size++;
+  }
+
+  return size;
+}
+
+
+function includes(array, obj) {
+  return indexOf(array, obj) != -1;
+}
+
+function indexOf(array, obj) {
+  if (array.indexOf) return array.indexOf(obj);
+
+  for ( var i = 0; i < array.length; i++) {
+    if (obj === array[i]) return i;
+  }
+  return -1;
+}
+
+function arrayRemove(array, value) {
+  var index = indexOf(array, value);
+  if (index >=0)
+    array.splice(index, 1);
+  return value;
+}
+
+function isLeafNode (node) {
+  if (node) {
+    switch (node.nodeName) {
+    case "OPTION":
+    case "PRE":
+    case "TITLE":
+      return true;
+    }
+  }
+  return false;
+}
+
+/**
+ * @ngdoc function
+ * @name angular.copy
+ * @function
+ *
+ * @description
+ * Creates a deep copy of `source`, which should be an object or an array.
+ *
+ * * If no destination is supplied, a copy of the object or array is created.
+ * * If a destination is provided, all of its elements (for array) or properties (for objects)
+ *   are deleted and then all elements/properties from the source are copied to it.
+ * * If  `source` is not an object or array, `source` is returned.
+ *
+ * Note: this function is used to augment the Object type in Angular expressions. See
+ * {@link ng.$filter} for more information about Angular arrays.
+ *
+ * @param {*} source The source that will be used to make a copy.
+ *                   Can be any type, including primitives, `null`, and `undefined`.
+ * @param {(Object|Array)=} destination Destination into which the source is copied. If
+ *     provided, must be of the same type as `source`.
+ * @returns {*} The copy or updated `destination`, if `destination` was specified.
+ */
+function copy(source, destination){
+  if (isWindow(source) || isScope(source)) throw Error("Can't copy Window or Scope");
+  if (!destination) {
+    destination = source;
+    if (source) {
+      if (isArray(source)) {
+        destination = copy(source, []);
+      } else if (isDate(source)) {
+        destination = new Date(source.getTime());
+      } else if (isObject(source)) {
+        destination = copy(source, {});
+      }
+    }
+  } else {
+    if (source === destination) throw Error("Can't copy equivalent objects or arrays");
+    if (isArray(source)) {
+      destination.length = 0;
+      for ( var i = 0; i < source.length; i++) {
+        destination.push(copy(source[i]));
+      }
+    } else {
+      forEach(destination, function(value, key){
+        delete destination[key];
+      });
+      for ( var key in source) {
+        destination[key] = copy(source[key]);
+      }
+    }
+  }
+  return destination;
+}
+
+/**
+ * Create a shallow copy of an object
+ */
+function shallowCopy(src, dst) {
+  dst = dst || {};
+
+  for(var key in src) {
+    if (src.hasOwnProperty(key) && key.substr(0, 2) !== '$$') {
+      dst[key] = src[key];
+    }
+  }
+
+  return dst;
+}
+
+
+/**
+ * @ngdoc function
+ * @name angular.equals
+ * @function
+ *
+ * @description
+ * Determines if two objects or two values are equivalent. Supports value types, arrays and
+ * objects.
+ *
+ * Two objects or values are considered equivalent if at least one of the following is true:
+ *
+ * * Both objects or values pass `===` comparison.
+ * * Both objects or values are of the same type and all of their properties pass `===` comparison.
+ * * Both values are NaN. (In JavasScript, NaN == NaN => false. But we consider two NaN as equal)
+ *
+ * During a property comparision, properties of `function` type and properties with names
+ * that begin with `$` are ignored.
+ *
+ * Scope and DOMWindow objects are being compared only be identify (`===`).
+ *
+ * @param {*} o1 Object or value to compare.
+ * @param {*} o2 Object or value to compare.
+ * @returns {boolean} True if arguments are equal.
+ */
+function equals(o1, o2) {
+  if (o1 === o2) return true;
+  if (o1 === null || o2 === null) return false;
+  if (o1 !== o1 && o2 !== o2) return true; // NaN === NaN
+  var t1 = typeof o1, t2 = typeof o2, length, key, keySet;
+  if (t1 == t2) {
+    if (t1 == 'object') {
+      if (isArray(o1)) {
+        if ((length = o1.length) == o2.length) {
+          for(key=0; key<length; key++) {
+            if (!equals(o1[key], o2[key])) return false;
+          }
+          return true;
+        }
+      } else if (isDate(o1)) {
+        return isDate(o2) && o1.getTime() == o2.getTime();
+      } else {
+        if (isScope(o1) || isScope(o2) || isWindow(o1) || isWindow(o2)) return false;
+        keySet = {};
+        for(key in o1) {
+          if (key.charAt(0) === '$' || isFunction(o1[key])) continue;
+          if (!equals(o1[key], o2[key])) return false;
+          keySet[key] = true;
+        }
+        for(key in o2) {
+          if (!keySet[key] &&
+              key.charAt(0) !== '$' &&
+              o2[key] !== undefined &&
+              !isFunction(o2[key])) return false;
+        }
+        return true;
+      }
+    }
+  }
+  return false;
+}
+
+
+function concat(array1, array2, index) {
+  return array1.concat(slice.call(array2, index));
+}
+
+function sliceArgs(args, startIndex) {
+  return slice.call(args, startIndex || 0);
+}
+
+
+/**
+ * @ngdoc function
+ * @name angular.bind
+ * @function
+ *
+ * @description
+ * Returns a function which calls function `fn` bound to `self` (`self` becomes the `this` for
+ * `fn`). You can supply optional `args` that are are prebound to the function. This feature is also
+ * known as [function currying](http://en.wikipedia.org/wiki/Currying).
+ *
+ * @param {Object} self Context which `fn` should be evaluated in.
+ * @param {function()} fn Function to be bound.
+ * @param {...*} args Optional arguments to be prebound to the `fn` function call.
+ * @returns {function()} Function that wraps the `fn` with all the specified bindings.
+ */
+function bind(self, fn) {
+  var curryArgs = arguments.length > 2 ? sliceArgs(arguments, 2) : [];
+  if (isFunction(fn) && !(fn instanceof RegExp)) {
+    return curryArgs.length
+      ? function() {
+          return arguments.length
+            ? fn.apply(self, curryArgs.concat(slice.call(arguments, 0)))
+            : fn.apply(self, curryArgs);
+        }
+      : function() {
+          return arguments.length
+            ? fn.apply(self, arguments)
+            : fn.call(self);
+        };
+  } else {
+    // in IE, native methods are not functions so they cannot be bound (note: they don't need to be)
+    return fn;
+  }
+}
+
+
+function toJsonReplacer(key, value) {
+  var val = value;
+
+  if (/^\$+/.test(key)) {
+    val = undefined;
+  } else if (isWindow(value)) {
+    val = '$WINDOW';
+  } else if (value &&  document === value) {
+    val = '$DOCUMENT';
+  } else if (isScope(value)) {
+    val = '$SCOPE';
+  }
+
+  return val;
+}
+
+
+/**
+ * @ngdoc function
+ * @name angular.toJson
+ * @function
+ *
+ * @description
+ * Serializes input into a JSON-formatted string.
+ *
+ * @param {Object|Array|Date|string|number} obj Input to be serialized into JSON.
+ * @param {boolean=} pretty If set to true, the JSON output will contain newlines and whitespace.
+ * @returns {string} Jsonified string representing `obj`.
+ */
+function toJson(obj, pretty) {
+  return JSON.stringify(obj, toJsonReplacer, pretty ? '  ' : null);
+}
+
+
+/**
+ * @ngdoc function
+ * @name angular.fromJson
+ * @function
+ *
+ * @description
+ * Deserializes a JSON string.
+ *
+ * @param {string} json JSON string to deserialize.
+ * @returns {Object|Array|Date|string|number} Deserialized thingy.
+ */
+function fromJson(json) {
+  return isString(json)
+      ? JSON.parse(json)
+      : json;
+}
+
+
+function toBoolean(value) {
+  if (value && value.length !== 0) {
+    var v = lowercase("" + value);
+    value = !(v == 'f' || v == '0' || v == 'false' || v == 'no' || v == 'n' || v == '[]');
+  } else {
+    value = false;
+  }
+  return value;
+}
+
+/**
+ * @returns {string} Returns the string representation of the element.
+ */
+function startingTag(element) {
+  element = jqLite(element).clone();
+  try {
+    // turns out IE does not let you set .html() on elements which
+    // are not allowed to have children. So we just ignore it.
+    element.html('');
+  } catch(e) {}
+  // As Per DOM Standards
+  var TEXT_NODE = 3;
+  var elemHtml = jqLite('<div>').append(element).html();
+  try {
+    return element[0].nodeType === TEXT_NODE ? lowercase(elemHtml) :
+        elemHtml.
+          match(/^(<[^>]+>)/)[1].
+          replace(/^<([\w\-]+)/, function(match, nodeName) { return '<' + lowercase(nodeName); });
+  } catch(e) {
+    return lowercase(elemHtml);
+  }
+
+}
+
+
+/////////////////////////////////////////////////
+
+/**
+ * Parses an escaped url query string into key-value pairs.
+ * @returns Object.<(string|boolean)>
+ */
+function parseKeyValue(/**string*/keyValue) {
+  var obj = {}, key_value, key;
+  forEach((keyValue || "").split('&'), function(keyValue){
+    if (keyValue) {
+      key_value = keyValue.split('=');
+      key = decodeURIComponent(key_value[0]);
+      obj[key] = isDefined(key_value[1]) ? decodeURIComponent(key_value[1]) : true;
+    }
+  });
+  return obj;
+}
+
+function toKeyValue(obj) {
+  var parts = [];
+  forEach(obj, function(value, key) {
+    parts.push(encodeUriQuery(key, true) + (value === true ? '' : '=' + encodeUriQuery(value, true)));
+  });
+  return parts.length ? parts.join('&') : '';
+}
+
+
+/**
+ * We need our custom method because encodeURIComponent is too agressive and doesn't follow
+ * http://www.ietf.org/rfc/rfc3986.txt with regards to the character set (pchar) allowed in path
+ * segments:
+ *    segment       = *pchar
+ *    pchar         = unreserved / pct-encoded / sub-delims / ":" / "@"
+ *    pct-encoded   = "%" HEXDIG HEXDIG
+ *    unreserved    = ALPHA / DIGIT / "-" / "." / "_" / "~"
+ *    sub-delims    = "!" / "$" / "&" / "'" / "(" / ")"
+ *                     / "*" / "+" / "," / ";" / "="
+ */
+function encodeUriSegment(val) {
+  return encodeUriQuery(val, true).
+             replace(/%26/gi, '&').
+             replace(/%3D/gi, '=').
+             replace(/%2B/gi, '+');
+}
+
+
+/**
+ * This method is intended for encoding *key* or *value* parts of query component. We need a custom
+ * method becuase encodeURIComponent is too agressive and encodes stuff that doesn't have to be
+ * encoded per http://tools.ietf.org/html/rfc3986:
+ *    query       = *( pchar / "/" / "?" )
+ *    pchar         = unreserved / pct-encoded / sub-delims / ":" / "@"
+ *    unreserved    = ALPHA / DIGIT / "-" / "." / "_" / "~"
+ *    pct-encoded   = "%" HEXDIG HEXDIG
+ *    sub-delims    = "!" / "$" / "&" / "'" / "(" / ")"
+ *                     / "*" / "+" / "," / ";" / "="
+ */
+function encodeUriQuery(val, pctEncodeSpaces) {
+  return encodeURIComponent(val).
+             replace(/%40/gi, '@').
+             replace(/%3A/gi, ':').
+             replace(/%24/g, '$').
+             replace(/%2C/gi, ',').
+             replace((pctEncodeSpaces ? null : /%20/g), '+');
+}
+
+
+/**
+ * @ngdoc directive
+ * @name ng.directive:ngApp
+ *
+ * @element ANY
+ * @param {angular.Module} ngApp an optional application
+ *   {@link angular.module module} name to load.
+ *
+ * @description
+ *
+ * Use this directive to auto-bootstrap on application. Only
+ * one directive can be used per HTML document. The directive
+ * designates the root of the application and is typically placed
+ * at the root of the page.
+ *
+ * In the example below if the `ngApp` directive would not be placed
+ * on the `html` element then the document would not be compiled
+ * and the `{{ 1+2 }}` would not be resolved to `3`.
+ *
+ * `ngApp` is the easiest way to bootstrap an application.
+ *
+ <doc:example>
+   <doc:source>
+    I can add: 1 + 2 =  {{ 1+2 }}
+   </doc:source>
+ </doc:example>
+ *
+ */
+function angularInit(element, bootstrap) {
+  var elements = [element],
+      appElement,
+      module,
+      names = ['ng:app', 'ng-app', 'x-ng-app', 'data-ng-app'],
+      NG_APP_CLASS_REGEXP = /\sng[:\-]app(:\s*([\w\d_]+);?)?\s/;
+
+  function append(element) {
+    element && elements.push(element);
+  }
+
+  forEach(names, function(name) {
+    names[name] = true;
+    append(document.getElementById(name));
+    name = name.replace(':', '\\:');
+    if (element.querySelectorAll) {
+      forEach(element.querySelectorAll('.' + name), append);
+      forEach(element.querySelectorAll('.' + name + '\\:'), append);
+      forEach(element.querySelectorAll('[' + name + ']'), append);
+    }
+  });
+
+  forEach(elements, function(element) {
+    if (!appElement) {
+      var className = ' ' + element.className + ' ';
+      var match = NG_APP_CLASS_REGEXP.exec(className);
+      if (match) {
+        appElement = element;
+        module = (match[2] || '').replace(/\s+/g, ',');
+      } else {
+        forEach(element.attributes, function(attr) {
+          if (!appElement && names[attr.name]) {
+            appElement = element;
+            module = attr.value;
+          }
+        });
+      }
+    }
+  });
+  if (appElement) {
+    bootstrap(appElement, module ? [module] : []);
+  }
+}
+
+/**
+ * @ngdoc function
+ * @name angular.bootstrap
+ * @description
+ * Use this function to manually start up angular application.
+ *
+ * See: {@link guide/bootstrap Bootstrap}
+ *
+ * @param {Element} element DOM element which is the root of angular application.
+ * @param {Array<String|Function>=} modules an array of module declarations. See: {@link angular.module modules}
+ * @returns {AUTO.$injector} Returns the newly created injector for this app.
+ */
+function bootstrap(element, modules) {
+  element = jqLite(element);
+  modules = modules || [];
+  modules.unshift(['$provide', function($provide) {
+    $provide.value('$rootElement', element);
+  }]);
+  modules.unshift('ng');
+  var injector = createInjector(modules);
+  injector.invoke(
+    ['$rootScope', '$rootElement', '$compile', '$injector', function(scope, element, compile, injector){
+      scope.$apply(function() {
+        element.data('$injector', injector);
+        compile(element)(scope);
+      });
+    }]
+  );
+  return injector;
+}
+
+var SNAKE_CASE_REGEXP = /[A-Z]/g;
+function snake_case(name, separator){
+  separator = separator || '_';
+  return name.replace(SNAKE_CASE_REGEXP, function(letter, pos) {
+    return (pos ? separator : '') + letter.toLowerCase();
+  });
+}
+
+function bindJQuery() {
+  // bind to jQuery if present;
+  jQuery = window.jQuery;
+  // reset to jQuery or default to us.
+  if (jQuery) {
+    jqLite = jQuery;
+    extend(jQuery.fn, {
+      scope: JQLitePrototype.scope,
+      controller: JQLitePrototype.controller,
+      injector: JQLitePrototype.injector,
+      inheritedData: JQLitePrototype.inheritedData
+    });
+    JQLitePatchJQueryRemove('remove', true);
+    JQLitePatchJQueryRemove('empty');
+    JQLitePatchJQueryRemove('html');
+  } else {
+    jqLite = JQLite;
+  }
+  angular.element = jqLite;
+}
+
+/**
+ * throw error of the argument is falsy.
+ */
+function assertArg(arg, name, reason) {
+  if (!arg) {
+    throw new Error("Argument '" + (name || '?') + "' is " + (reason || "required"));
+  }
+  return arg;
+}
+
+function assertArgFn(arg, name, acceptArrayAnnotation) {
+  if (acceptArrayAnnotation && isArray(arg)) {
+      arg = arg[arg.length - 1];
+  }
+
+  assertArg(isFunction(arg), name, 'not a function, got ' +
+      (arg && typeof arg == 'object' ? arg.constructor.name || 'Object' : typeof arg));
+  return arg;
+}
+
+/**
+ * @ngdoc interface
+ * @name angular.Module
+ * @description
+ *
+ * Interface for configuring angular {@link angular.module modules}.
+ */
+
+function setupModuleLoader(window) {
+
+  function ensure(obj, name, factory) {
+    return obj[name] || (obj[name] = factory());
+  }
+
+  return ensure(ensure(window, 'angular', Object), 'module', function() {
+    /** @type {Object.<string, angular.Module>} */
+    var modules = {};
+
+    /**
+     * @ngdoc function
+     * @name angular.module
+     * @description
+     *
+     * The `angular.module` is a global place for creating and registering Angular modules. All
+     * modules (angular core or 3rd party) that should be available to an application must be
+     * registered using this mechanism.
+     *
+     *
+     * # Module
+     *
+     * A module is a collocation of services, directives, filters, and configuration information. Module
+     * is used to configure the {@link AUTO.$injector $injector}.
+     *
+     * <pre>
+     * // Create a new module
+     * var myModule = angular.module('myModule', []);
+     *
+     * // register a new service
+     * myModule.value('appName', 'MyCoolApp');
+     *
+     * // configure existing services inside initialization blocks.
+     * myModule.config(function($locationProvider) {
+     *   // Configure existing providers
+     *   $locationProvider.hashPrefix('!');
+     * });
+     * </pre>
+     *
+     * Then you can create an injector and load your modules like this:
+     *
+     * <pre>
+     * var injector = angular.injector(['ng', 'MyModule'])
+     * </pre>
+     *
+     * However it's more likely that you'll just use
+     * {@link ng.directive:ngApp ngApp} or
+     * {@link angular.bootstrap} to simplify this process for you.
+     *
+     * @param {!string} name The name of the module to create or retrieve.
+     * @param {Array.<string>=} requires If specified then new module is being created. If unspecified then the
+     *        the module is being retrieved for further configuration.
+     * @param {Function} configFn Optional configuration function for the module. Same as
+     *        {@link angular.Module#config Module#config()}.
+     * @returns {module} new module with the {@link angular.Module} api.
+     */
+    return function module(name, requires, configFn) {
+      if (requires && modules.hasOwnProperty(name)) {
+        modules[name] = null;
+      }
+      return ensure(modules, name, function() {
+        if (!requires) {
+          throw Error('No module: ' + name);
+        }
+
+        /** @type {!Array.<Array.<*>>} */
+        var invokeQueue = [];
+
+        /** @type {!Array.<Function>} */
+        var runBlocks = [];
+
+        var config = invokeLater('$injector', 'invoke');
+
+        /** @type {angular.Module} */
+        var moduleInstance = {
+          // Private state
+          _invokeQueue: invokeQueue,
+          _runBlocks: runBlocks,
+
+          /**
+           * @ngdoc property
+           * @name angular.Module#requires
+           * @propertyOf angular.Module
+           * @returns {Array.<string>} List of module names which must be loaded before this module.
+           * @description
+           * Holds the list of modules which the injector will load before the current module is loaded.
+           */
+          requires: requires,
+
+          /**
+           * @ngdoc property
+           * @name angular.Module#name
+           * @propertyOf angular.Module
+           * @returns {string} Name of the module.
+           * @description
+           */
+          name: name,
+
+
+          /**
+           * @ngdoc method
+           * @name angular.Module#provider
+           * @methodOf angular.Module
+           * @param {string} name service name
+           * @param {Function} providerType Construction function for creating new instance of the service.
+           * @description
+           * See {@link AUTO.$provide#provider $provide.provider()}.
+           */
+          provider: invokeLater('$provide', 'provider'),
+
+          /**
+           * @ngdoc method
+           * @name angular.Module#factory
+           * @methodOf angular.Module
+           * @param {string} name service name
+           * @param {Function} providerFunction Function for creating new instance of the service.
+           * @description
+           * See {@link AUTO.$provide#factory $provide.factory()}.
+           */
+          factory: invokeLater('$provide', 'factory'),
+
+          /**
+           * @ngdoc method
+           * @name angular.Module#service
+           * @methodOf angular.Module
+           * @param {string} name service name
+           * @param {Function} constructor A constructor function that will be instantiated.
+           * @description
+           * See {@link AUTO.$provide#service $provide.service()}.
+           */
+          service: invokeLater('$provide', 'service'),
+
+          /**
+           * @ngdoc method
+           * @name angular.Module#value
+           * @methodOf angular.Module
+           * @param {string} name service name
+           * @param {*} object Service instance object.
+           * @description
+           * See {@link AUTO.$provide#value $provide.value()}.
+           */
+          value: invokeLater('$provide', 'value'),
+
+          /**
+           * @ngdoc method
+           * @name angular.Module#constant
+           * @methodOf angular.Module
+           * @param {string} name constant name
+           * @param {*} object Constant value.
+           * @description
+           * Because the constant are fixed, they get applied before other provide methods.
+           * See {@link AUTO.$provide#constant $provide.constant()}.
+           */
+          constant: invokeLater('$provide', 'constant', 'unshift'),
+
+          /**
+           * @ngdoc method
+           * @name angular.Module#filter
+           * @methodOf angular.Module
+           * @param {string} name Filter name.
+           * @param {Function} filterFactory Factory function for creating new instance of filter.
+           * @description
+           * See {@link ng.$filterProvider#register $filterProvider.register()}.
+           */
+          filter: invokeLater('$filterProvider', 'register'),
+
+          /**
+           * @ngdoc method
+           * @name angular.Module#controller
+           * @methodOf angular.Module
+           * @param {string} name Controller name.
+           * @param {Function} constructor Controller constructor function.
+           * @description
+           * See {@link ng.$controllerProvider#register $controllerProvider.register()}.
+           */
+          controller: invokeLater('$controllerProvider', 'register'),
+
+          /**
+           * @ngdoc method
+           * @name angular.Module#directive
+           * @methodOf angular.Module
+           * @param {string} name directive name
+           * @param {Function} directiveFactory Factory function for creating new instance of
+           * directives.
+           * @description
+           * See {@link ng.$compileProvider#directive $compileProvider.directive()}.
+           */
+          directive: invokeLater('$compileProvider', 'directive'),
+
+          /**
+           * @ngdoc method
+           * @name angular.Module#config
+           * @methodOf angular.Module
+           * @param {Function} configFn Execute this function on module load. Useful for service
+           *    configuration.
+           * @description
+           * Use this method to register work which needs to be performed on module loading.
+           */
+          config: config,
+
+          /**
+           * @ngdoc method
+           * @name angular.Module#run
+           * @methodOf angular.Module
+           * @param {Function} initializationFn Execute this function after injector creation.
+           *    Useful for application initialization.
+           * @description
+           * Use this method to register work which should be performed when the injector is done
+           * loading all modules.
+           */
+          run: function(block) {
+            runBlocks.push(block);
+            return this;
+          }
+        };
+
+        if (configFn) {
+          config(configFn);
+        }
+
+        return  moduleInstance;
+
+        /**
+         * @param {string} provider
+         * @param {string} method
+         * @param {String=} insertMethod
+         * @returns {angular.Module}
+         */
+        function invokeLater(provider, method, insertMethod) {
+          return function() {
+            invokeQueue[insertMethod || 'push']([provider, method, arguments]);
+            return moduleInstance;
+          }
+        }
+      });
+    };
+  });
+
+}
+
+/**
+ * @ngdoc property
+ * @name angular.version
+ * @description
+ * An object that contains information about the current AngularJS version. This object has the
+ * following properties:
+ *
+ * - `full` – `{string}` – Full version string, such as "0.9.18".
+ * - `major` – `{number}` – Major version number, such as "0".
+ * - `minor` – `{number}` – Minor version number, such as "9".
+ * - `dot` – `{number}` – Dot version number, such as "18".
+ * - `codeName` – `{string}` – Code name of the release, such as "jiggling-armfat".
+ */
+var version = {
+  full: '1.0.5',    // all of these placeholder strings will be replaced by rake's
+  major: 1,    // compile task
+  minor: 0,
+  dot: 5,
+  codeName: 'flatulent-propulsion'
+};
+
+
+function publishExternalAPI(angular){
+  extend(angular, {
+    'bootstrap': bootstrap,
+    'copy': copy,
+    'extend': extend,
+    'equals': equals,
+    'element': jqLite,
+    'forEach': forEach,
+    'injector': createInjector,
+    'noop':noop,
+    'bind':bind,
+    'toJson': toJson,
+    'fromJson': fromJson,
+    'identity':identity,
+    'isUndefined': isUndefined,
+    'isDefined': isDefined,
+    'isString': isString,
+    'isFunction': isFunction,
+    'isObject': isObject,
+    'isNumber': isNumber,
+    'isElement': isElement,
+    'isArray': isArray,
+    'version': version,
+    'isDate': isDate,
+    'lowercase': lowercase,
+    'uppercase': uppercase,
+    'callbacks': {counter: 0}
+  });
+
+  angularModule = setupModuleLoader(window);
+  try {
+    angularModule('ngLocale');
+  } catch (e) {
+    angularModule('ngLocale', []).provider('$locale', $LocaleProvider);
+  }
+
+  angularModule('ng', ['ngLocale'], ['$provide',
+    function ngModule($provide) {
+      $provide.provider('$compile', $CompileProvider).
+        directive({
+            a: htmlAnchorDirective,
+            input: inputDirective,
+            textarea: inputDirective,
+            form: formDirective,
+            script: scriptDirective,
+            select: selectDirective,
+            style: styleDirective,
+            option: optionDirective,
+            ngBind: ngBindDirective,
+            ngBindHtmlUnsafe: ngBindHtmlUnsafeDirective,
+            ngBindTemplate: ngBindTemplateDirective,
+            ngClass: ngClassDirective,
+            ngClassEven: ngClassEvenDirective,
+            ngClassOdd: ngClassOddDirective,
+            ngCsp: ngCspDirective,
+            ngCloak: ngCloakDirective,
+            ngController: ngControllerDirective,
+            ngForm: ngFormDirective,
+            ngHide: ngHideDirective,
+            ngInclude: ngIncludeDirective,
+            ngInit: ngInitDirective,
+            ngNonBindable: ngNonBindableDirective,
+            ngPluralize: ngPluralizeDirective,
+            ngRepeat: ngRepeatDirective,
+            ngShow: ngShowDirective,
+            ngSubmit: ngSubmitDirective,
+            ngStyle: ngStyleDirective,
+            ngSwitch: ngSwitchDirective,
+            ngSwitchWhen: ngSwitchWhenDirective,
+            ngSwitchDefault: ngSwitchDefaultDirective,
+            ngOptions: ngOptionsDirective,
+            ngView: ngViewDirective,
+            ngTransclude: ngTranscludeDirective,
+            ngModel: ngModelDirective,
+            ngList: ngListDirective,
+            ngChange: ngChangeDirective,
+            required: requiredDirective,
+            ngRequired: requiredDirective,
+            ngValue: ngValueDirective
+        }).
+        directive(ngAttributeAliasDirectives).
+        directive(ngEventDirectives);
+      $provide.provider({
+        $anchorScroll: $AnchorScrollProvider,
+        $browser: $BrowserProvider,
+        $cacheFactory: $CacheFactoryProvider,
+        $controller: $ControllerProvider,
+        $document: $DocumentProvider,
+        $exceptionHandler: $ExceptionHandlerProvider,
+        $filter: $FilterProvider,
+        $interpolate: $InterpolateProvider,
+        $http: $HttpProvider,
+        $httpBackend: $HttpBackendProvider,
+        $location: $LocationProvider,
+        $log: $LogProvider,
+        $parse: $ParseProvider,
+        $route: $RouteProvider,
+        $routeParams: $RouteParamsProvider,
+        $rootScope: $RootScopeProvider,
+        $q: $QProvider,
+        $sniffer: $SnifferProvider,
+        $templateCache: $TemplateCacheProvider,
+        $timeout: $TimeoutProvider,
+        $window: $WindowProvider
+      });
+    }
+  ]);
+}
+
+//////////////////////////////////
+//JQLite
+//////////////////////////////////
+
+/**
+ * @ngdoc function
+ * @name angular.element
+ * @function
+ *
+ * @description
+ * Wraps a raw DOM element or HTML string as a [jQuery](http://jquery.com) element.
+ * `angular.element` can be either an alias for [jQuery](http://api.jquery.com/jQuery/) function, if
+ * jQuery is available, or a function that wraps the element or string in Angular's jQuery lite
+ * implementation (commonly referred to as jqLite).
+ *
+ * Real jQuery always takes precedence over jqLite, provided it was loaded before `DOMContentLoaded`
+ * event fired.
+ *
+ * jqLite is a tiny, API-compatible subset of jQuery that allows
+ * Angular to manipulate the DOM. jqLite implements only the most commonly needed functionality
+ * within a very small footprint, so only a subset of the jQuery API - methods, arguments and
+ * invocation styles - are supported.
+ *
+ * Note: All element references in Angular are always wrapped with jQuery or jqLite; they are never
+ * raw DOM references.
+ *
+ * ## Angular's jQuery lite provides the following methods:
+ *
+ * - [addClass()](http://api.jquery.com/addClass/)
+ * - [after()](http://api.jquery.com/after/)
+ * - [append()](http://api.jquery.com/append/)
+ * - [attr()](http://api.jquery.com/attr/)
+ * - [bind()](http://api.jquery.com/bind/)
+ * - [children()](http://api.jquery.com/children/)
+ * - [clone()](http://api.jquery.com/clone/)
+ * - [contents()](http://api.jquery.com/contents/)
+ * - [css()](http://api.jquery.com/css/)
+ * - [data()](http://api.jquery.com/data/)
+ * - [eq()](http://api.jquery.com/eq/)
+ * - [find()](http://api.jquery.com/find/) - Limited to lookups by tag name.
+ * - [hasClass()](http://api.jquery.com/hasClass/)
+ * - [html()](http://api.jquery.com/html/)
+ * - [next()](http://api.jquery.com/next/)
+ * - [parent()](http://api.jquery.com/parent/)
+ * - [prepend()](http://api.jquery.com/prepend/)
+ * - [prop()](http://api.jquery.com/prop/)
+ * - [ready()](http://api.jquery.com/ready/)
+ * - [remove()](http://api.jquery.com/remove/)
+ * - [removeAttr()](http://api.jquery.com/removeAttr/)
+ * - [removeClass()](http://api.jquery.com/removeClass/)
+ * - [removeData()](http://api.jquery.com/removeData/)
+ * - [replaceWith()](http://api.jquery.com/replaceWith/)
+ * - [text()](http://api.jquery.com/text/)
+ * - [toggleClass()](http://api.jquery.com/toggleClass/)
+ * - [triggerHandler()](http://api.jquery.com/triggerHandler/) - Doesn't pass native event objects to handlers.
+ * - [unbind()](http://api.jquery.com/unbind/)
+ * - [val()](http://api.jquery.com/val/)
+ * - [wrap()](http://api.jquery.com/wrap/)
+ *
+ * ## In addtion to the above, Angular provides additional methods to both jQuery and jQuery lite:
+ *
+ * - `controller(name)` - retrieves the controller of the current element or its parent. By default
+ *   retrieves controller associated with the `ngController` directive. If `name` is provided as
+ *   camelCase directive name, then the controller for this directive will be retrieved (e.g.
+ *   `'ngModel'`).
+ * - `injector()` - retrieves the injector of the current element or its parent.
+ * - `scope()` - retrieves the {@link api/ng.$rootScope.Scope scope} of the current
+ *   element or its parent.
+ * - `inheritedData()` - same as `data()`, but walks up the DOM until a value is found or the top
+ *   parent element is reached.
+ *
+ * @param {string|DOMElement} element HTML string or DOMElement to be wrapped into jQuery.
+ * @returns {Object} jQuery object.
+ */
+
+var jqCache = JQLite.cache = {},
+    jqName = JQLite.expando = 'ng-' + new Date().getTime(),
+    jqId = 1,
+    addEventListenerFn = (window.document.addEventListener
+      ? function(element, type, fn) {element.addEventListener(type, fn, false);}
+      : function(element, type, fn) {element.attachEvent('on' + type, fn);}),
+    removeEventListenerFn = (window.document.removeEventListener
+      ? function(element, type, fn) {element.removeEventListener(type, fn, false); }
+      : function(element, type, fn) {element.detachEvent('on' + type, fn); });
+
+function jqNextId() { return ++jqId; }
+
+
+var SPECIAL_CHARS_REGEXP = /([\:\-\_]+(.))/g;
+var MOZ_HACK_REGEXP = /^moz([A-Z])/;
+
+/**
+ * Converts snake_case to camelCase.
+ * Also there is special case for Moz prefix starting with upper case letter.
+ * @param name Name to normalize
+ */
+function camelCase(name) {
+  return name.
+    replace(SPECIAL_CHARS_REGEXP, function(_, separator, letter, offset) {
+      return offset ? letter.toUpperCase() : letter;
+    }).
+    replace(MOZ_HACK_REGEXP, 'Moz$1');
+}
+
+/////////////////////////////////////////////
+// jQuery mutation patch
+//
+//  In conjunction with bindJQuery intercepts all jQuery's DOM destruction apis and fires a
+// $destroy event on all DOM nodes being removed.
+//
+/////////////////////////////////////////////
+
+function JQLitePatchJQueryRemove(name, dispatchThis) {
+  var originalJqFn = jQuery.fn[name];
+  originalJqFn = originalJqFn.$original || originalJqFn;
+  removePatch.$original = originalJqFn;
+  jQuery.fn[name] = removePatch;
+
+  function removePatch() {
+    var list = [this],
+        fireEvent = dispatchThis,
+        set, setIndex, setLength,
+        element, childIndex, childLength, children,
+        fns, events;
+
+    while(list.length) {
+      set = list.shift();
+      for(setIndex = 0, setLength = set.length; setIndex < setLength; setIndex++) {
+        element = jqLite(set[setIndex]);
+        if (fireEvent) {
+          element.triggerHandler('$destroy');
+        } else {
+          fireEvent = !fireEvent;
+        }
+        for(childIndex = 0, childLength = (children = element.children()).length;
+            childIndex < childLength;
+            childIndex++) {
+          list.push(jQuery(children[childIndex]));
+        }
+      }
+    }
+    return originalJqFn.apply(this, arguments);
+  }
+}
+
+/////////////////////////////////////////////
+function JQLite(element) {
+  if (element instanceof JQLite) {
+    return element;
+  }
+  if (!(this instanceof JQLite)) {
+    if (isString(element) && element.charAt(0) != '<') {
+      throw Error('selectors not implemented');
+    }
+    return new JQLite(element);
+  }
+
+  if (isString(element)) {
+    var div = document.createElement('div');
+    // Read about the NoScope elements here:
+    // http://msdn.microsoft.com/en-us/library/ms533897(VS.85).aspx
+    div.innerHTML = '<div>&#160;</div>' + element; // IE insanity to make NoScope elements work!
+    div.removeChild(div.firstChild); // remove the superfluous div
+    JQLiteAddNodes(this, div.childNodes);
+    this.remove(); // detach the elements from the temporary DOM div.
+  } else {
+    JQLiteAddNodes(this, element);
+  }
+}
+
+function JQLiteClone(element) {
+  return element.cloneNode(true);
+}
+
+function JQLiteDealoc(element){
+  JQLiteRemoveData(element);
+  for ( var i = 0, children = element.childNodes || []; i < children.length; i++) {
+    JQLiteDealoc(children[i]);
+  }
+}
+
+function JQLiteUnbind(element, type, fn) {
+  var events = JQLiteExpandoStore(element, 'events'),
+      handle = JQLiteExpandoStore(element, 'handle');
+
+  if (!handle) return; //no listeners registered
+
+  if (isUndefined(type)) {
+    forEach(events, function(eventHandler, type) {
+      removeEventListenerFn(element, type, eventHandler);
+      delete events[type];
+    });
+  } else {
+    if (isUndefined(fn)) {
+      removeEventListenerFn(element, type, events[type]);
+      delete events[type];
+    } else {
+      arrayRemove(events[type], fn);
+    }
+  }
+}
+
+function JQLiteRemoveData(element) {
+  var expandoId = element[jqName],
+      expandoStore = jqCache[expandoId];
+
+  if (expandoStore) {
+    if (expandoStore.handle) {
+      expandoStore.events.$destroy && expandoStore.handle({}, '$destroy');
+      JQLiteUnbind(element);
+    }
+    delete jqCache[expandoId];
+    element[jqName] = undefined; // ie does not allow deletion of attributes on elements.
+  }
+}
+
+function JQLiteExpandoStore(element, key, value) {
+  var expandoId = element[jqName],
+      expandoStore = jqCache[expandoId || -1];
+
+  if (isDefined(value)) {
+    if (!expandoStore) {
+      element[jqName] = expandoId = jqNextId();
+      expandoStore = jqCache[expandoId] = {};
+    }
+    expandoStore[key] = value;
+  } else {
+    return expandoStore && expandoStore[key];
+  }
+}
+
+function JQLiteData(element, key, value) {
+  var data = JQLiteExpandoStore(element, 'data'),
+      isSetter = isDefined(value),
+      keyDefined = !isSetter && isDefined(key),
+      isSimpleGetter = keyDefined && !isObject(key);
+
+  if (!data && !isSimpleGetter) {
+    JQLiteExpandoStore(element, 'data', data = {});
+  }
+
+  if (isSetter) {
+    data[key] = value;
+  } else {
+    if (keyDefined) {
+      if (isSimpleGetter) {
+        // don't create data in this case.
+        return data && data[key];
+      } else {
+        extend(data, key);
+      }
+    } else {
+      return data;
+    }
+  }
+}
+
+function JQLiteHasClass(element, selector) {
+  return ((" " + element.className + " ").replace(/[\n\t]/g, " ").
+      indexOf( " " + selector + " " ) > -1);
+}
+
+function JQLiteRemoveClass(element, cssClasses) {
+  if (cssClasses) {
+    forEach(cssClasses.split(' '), function(cssClass) {
+      element.className = trim(
+          (" " + element.className + " ")
+          .replace(/[\n\t]/g, " ")
+          .replace(" " + trim(cssClass) + " ", " ")
+      );
+    });
+  }
+}
+
+function JQLiteAddClass(element, cssClasses) {
+  if (cssClasses) {
+    forEach(cssClasses.split(' '), function(cssClass) {
+      if (!JQLiteHasClass(element, cssClass)) {
+        element.className = trim(element.className + ' ' + trim(cssClass));
+      }
+    });
+  }
+}
+
+function JQLiteAddNodes(root, elements) {
+  if (elements) {
+    elements = (!elements.nodeName && isDefined(elements.length) && !isWindow(elements))
+      ? elements
+      : [ elements ];
+    for(var i=0; i < elements.length; i++) {
+      root.push(elements[i]);
+    }
+  }
+}
+
+function JQLiteController(element, name) {
+  return JQLiteInheritedData(element, '$' + (name || 'ngController' ) + 'Controller');
+}
+
+function JQLiteInheritedData(element, name, value) {
+  element = jqLite(element);
+
+  // if element is the document object work with the html element instead
+  // this makes $(document).scope() possible
+  if(element[0].nodeType == 9) {
+    element = element.find('html');
+  }
+
+  while (element.length) {
+    if (value = element.data(name)) return value;
+    element = element.parent();
+  }
+}
+
+//////////////////////////////////////////
+// Functions which are declared directly.
+//////////////////////////////////////////
+var JQLitePrototype = JQLite.prototype = {
+  ready: function(fn) {
+    var fired = false;
+
+    function trigger() {
+      if (fired) return;
+      fired = true;
+      fn();
+    }
+
+    this.bind('DOMContentLoaded', trigger); // works for modern browsers and IE9
+    // we can not use jqLite since we are not done loading and jQuery could be loaded later.
+    JQLite(window).bind('load', trigger); // fallback to window.onload for others
+  },
+  toString: function() {
+    var value = [];
+    forEach(this, function(e){ value.push('' + e);});
+    return '[' + value.join(', ') + ']';
+  },
+
+  eq: function(index) {
+      return (index >= 0) ? jqLite(this[index]) : jqLite(this[this.length + index]);
+  },
+
+  length: 0,
+  push: push,
+  sort: [].sort,
+  splice: [].splice
+};
+
+//////////////////////////////////////////
+// Functions iterating getter/setters.
+// these functions return self on setter and
+// value on get.
+//////////////////////////////////////////
+var BOOLEAN_ATTR = {};
+forEach('multiple,selected,checked,disabled,readOnly,required'.split(','), function(value) {
+  BOOLEAN_ATTR[lowercase(value)] = value;
+});
+var BOOLEAN_ELEMENTS = {};
+forEach('input,select,option,textarea,button,form'.split(','), function(value) {
+  BOOLEAN_ELEMENTS[uppercase(value)] = true;
+});
+
+function getBooleanAttrName(element, name) {
+  // check dom last since we will most likely fail on name
+  var booleanAttr = BOOLEAN_ATTR[name.toLowerCase()];
+
+  // booleanAttr is here twice to minimize DOM access
+  return booleanAttr && BOOLEAN_ELEMENTS[element.nodeName] && booleanAttr;
+}
+
+forEach({
+  data: JQLiteData,
+  inheritedData: JQLiteInheritedData,
+
+  scope: function(element) {
+    return JQLiteInheritedData(element, '$scope');
+  },
+
+  controller: JQLiteController ,
+
+  injector: function(element) {
+    return JQLiteInheritedData(element, '$injector');
+  },
+
+  removeAttr: function(element,name) {
+    element.removeAttribute(name);
+  },
+
+  hasClass: JQLiteHasClass,
+
+  css: function(element, name, value) {
+    name = camelCase(name);
+
+    if (isDefined(value)) {
+      element.style[name] = value;
+    } else {
+      var val;
+
+      if (msie <= 8) {
+        // this is some IE specific weirdness that jQuery 1.6.4 does not sure why
+        val = element.currentStyle && element.currentStyle[name];
+        if (val === '') val = 'auto';
+      }
+
+      val = val || element.style[name];
+
+      if (msie <= 8) {
+        // jquery weirdness :-/
+        val = (val === '') ? undefined : val;
+      }
+
+      return  val;
+    }
+  },
+
+  attr: function(element, name, value){
+    var lowercasedName = lowercase(name);
+    if (BOOLEAN_ATTR[lowercasedName]) {
+      if (isDefined(value)) {
+        if (!!value) {
+          element[name] = true;
+          element.setAttribute(name, lowercasedName);
+        } else {
+          element[name] = false;
+          element.removeAttribute(lowercasedName);
+        }
+      } else {
+        return (element[name] ||
+                 (element.attributes.getNamedItem(name)|| noop).specified)
+               ? lowercasedName
+               : undefined;
+      }
+    } else if (isDefined(value)) {
+      element.setAttribute(name, value);
+    } else if (element.getAttribute) {
+      // the extra argument "2" is to get the right thing for a.href in IE, see jQuery code
+      // some elements (e.g. Document) don't have get attribute, so return undefined
+      var ret = element.getAttribute(name, 2);
+      // normalize non-existing attributes to undefined (as jQuery)
+      return ret === null ? undefined : ret;
+    }
+  },
+
+  prop: function(element, name, value) {
+    if (isDefined(value)) {
+      element[name] = value;
+    } else {
+      return element[name];
+    }
+  },
+
+  text: extend((msie < 9)
+      ? function(element, value) {
+        if (element.nodeType == 1 /** Element */) {
+          if (isUndefined(value))
+            return element.innerText;
+          element.innerText = value;
+        } else {
+          if (isUndefined(value))
+            return element.nodeValue;
+          element.nodeValue = value;
+        }
+      }
+      : function(element, value) {
+        if (isUndefined(value)) {
+          return element.textContent;
+        }
+        element.textContent = value;
+      }, {$dv:''}),
+
+  val: function(element, value) {
+    if (isUndefined(value)) {
+      return element.value;
+    }
+    element.value = value;
+  },
+
+  html: function(element, value) {
+    if (isUndefined(value)) {
+      return element.innerHTML;
+    }
+    for (var i = 0, childNodes = element.childNodes; i < childNodes.length; i++) {
+      JQLiteDealoc(childNodes[i]);
+    }
+    element.innerHTML = value;
+  }
+}, function(fn, name){
+  /**
+   * Properties: writes return selection, reads return first value
+   */
+  JQLite.prototype[name] = function(arg1, arg2) {
+    var i, key;
+
+    // JQLiteHasClass has only two arguments, but is a getter-only fn, so we need to special-case it
+    // in a way that survives minification.
+    if (((fn.length == 2 && (fn !== JQLiteHasClass && fn !== JQLiteController)) ? arg1 : arg2) === undefined) {
+      if (isObject(arg1)) {
+
+        // we are a write, but the object properties are the key/values
+        for(i=0; i < this.length; i++) {
+          if (fn === JQLiteData) {
+            // data() takes the whole object in jQuery
+            fn(this[i], arg1);
+          } else {
+            for (key in arg1) {
+              fn(this[i], key, arg1[key]);
+            }
+          }
+        }
+        // return self for chaining
+        return this;
+      } else {
+        // we are a read, so read the first child.
+        if (this.length)
+          return fn(this[0], arg1, arg2);
+      }
+    } else {
+      // we are a write, so apply to all children
+      for(i=0; i < this.length; i++) {
+        fn(this[i], arg1, arg2);
+      }
+      // return self for chaining
+      return this;
+    }
+    return fn.$dv;
+  };
+});
+
+function createEventHandler(element, events) {
+  var eventHandler = function (event, type) {
+    if (!event.preventDefault) {
+      event.preventDefault = function() {
+        event.returnValue = false; //ie
+      };
+    }
+
+    if (!event.stopPropagation) {
+      event.stopPropagation = function() {
+        event.cancelBubble = true; //ie
+      };
+    }
+
+    if (!event.target) {
+      event.target = event.srcElement || document;
+    }
+
+    if (isUndefined(event.defaultPrevented)) {
+      var prevent = event.preventDefault;
+      event.preventDefault = function() {
+        event.defaultPrevented = true;
+        prevent.call(event);
+      };
+      event.defaultPrevented = false;
+    }
+
+    event.isDefaultPrevented = function() {
+      return event.defaultPrevented;
+    };
+
+    forEach(events[type || event.type], function(fn) {
+      fn.call(element, event);
+    });
+
+    // Remove monkey-patched methods (IE),
+    // as they would cause memory leaks in IE8.
+    if (msie <= 8) {
+      // IE7/8 does not allow to delete property on native object
+      event.preventDefault = null;
+      event.stopPropagation = null;
+      event.isDefaultPrevented = null;
+    } else {
+      // It shouldn't affect normal browsers (native methods are defined on prototype).
+      delete event.preventDefault;
+      delete event.stopPropagation;
+      delete event.isDefaultPrevented;
+    }
+  };
+  eventHandler.elem = element;
+  return eventHandler;
+}
+
+//////////////////////////////////////////
+// Functions iterating traversal.
+// These functions chain results into a single
+// selector.
+//////////////////////////////////////////
+forEach({
+  removeData: JQLiteRemoveData,
+
+  dealoc: JQLiteDealoc,
+
+  bind: function bindFn(element, type, fn){
+    var events = JQLiteExpandoStore(element, 'events'),
+        handle = JQLiteExpandoStore(element, 'handle');
+
+    if (!events) JQLiteExpandoStore(element, 'events', events = {});
+    if (!handle) JQLiteExpandoStore(element, 'handle', handle = createEventHandler(element, events));
+
+    forEach(type.split(' '), function(type){
+      var eventFns = events[type];
+
+      if (!eventFns) {
+        if (type == 'mouseenter' || type == 'mouseleave') {
+          var counter = 0;
+
+          events.mouseenter = [];
+          events.mouseleave = [];
+
+          bindFn(element, 'mouseover', function(event) {
+            counter++;
+            if (counter == 1) {
+              handle(event, 'mouseenter');
+            }
+          });
+          bindFn(element, 'mouseout', function(event) {
+            counter --;
+            if (counter == 0) {
+              handle(event, 'mouseleave');
+            }
+          });
+        } else {
+          addEventListenerFn(element, type, handle);
+          events[type] = [];
+        }
+        eventFns = events[type]
+      }
+      eventFns.push(fn);
+    });
+  },
+
+  unbind: JQLiteUnbind,
+
+  replaceWith: function(element, replaceNode) {
+    var index, parent = element.parentNode;
+    JQLiteDealoc(element);
+    forEach(new JQLite(replaceNode), function(node){
+      if (index) {
+        parent.insertBefore(node, index.nextSibling);
+      } else {
+        parent.replaceChild(node, element);
+      }
+      index = node;
+    });
+  },
+
+  children: function(element) {
+    var children = [];
+    forEach(element.childNodes, function(element){
+      if (element.nodeType === 1)
+        children.push(element);
+    });
+    return children;
+  },
+
+  contents: function(element) {
+    return element.childNodes || [];
+  },
+
+  append: function(element, node) {
+    forEach(new JQLite(node), function(child){
+      if (element.nodeType === 1)
+        element.appendChild(child);
+    });
+  },
+
+  prepend: function(element, node) {
+    if (element.nodeType === 1) {
+      var index = element.firstChild;
+      forEach(new JQLite(node), function(child){
+        if (index) {
+          element.insertBefore(child, index);
+        } else {
+          element.appendChild(child);
+          index = child;
+        }
+      });
+    }
+  },
+
+  wrap: function(element, wrapNode) {
+    wrapNode = jqLite(wrapNode)[0];
+    var parent = element.parentNode;
+    if (parent) {
+      parent.replaceChild(wrapNode, element);
+    }
+    wrapNode.appendChild(element);
+  },
+
+  remove: function(element) {
+    JQLiteDealoc(element);
+    var parent = element.parentNode;
+    if (parent) parent.removeChild(element);
+  },
+
+  after: function(element, newElement) {
+    var index = element, parent = element.parentNode;
+    forEach(new JQLite(newElement), function(node){
+      parent.insertBefore(node, index.nextSibling);
+      index = node;
+    });
+  },
+
+  addClass: JQLiteAddClass,
+  removeClass: JQLiteRemoveClass,
+
+  toggleClass: function(element, selector, condition) {
+    if (isUndefined(condition)) {
+      condition = !JQLiteHasClass(element, selector);
+    }
+    (condition ? JQLiteAddClass : JQLiteRemoveClass)(element, selector);
+  },
+
+  parent: function(element) {
+    var parent = element.parentNode;
+    return parent && parent.nodeType !== 11 ? parent : null;
+  },
+
+  next: function(element) {
+    if (element.nextElementSibling) {
+      return element.nextElementSibling;
+    }
+
+    // IE8 doesn't have nextElementSibling
+    var elm = element.nextSibling;
+    while (elm != null && elm.nodeType !== 1) {
+      elm = elm.nextSibling;
+    }
+    return elm;
+  },
+
+  find: function(element, selector) {
+    return element.getElementsByTagName(selector);
+  },
+
+  clone: JQLiteClone,
+
+  triggerHandler: function(element, eventName) {
+    var eventFns = (JQLiteExpandoStore(element, 'events') || {})[eventName];
+
+    forEach(eventFns, function(fn) {
+      fn.call(element, null);
+    });
+  }
+}, function(fn, name){
+  /**
+   * chaining functions
+   */
+  JQLite.prototype[name] = function(arg1, arg2) {
+    var value;
+    for(var i=0; i < this.length; i++) {
+      if (value == undefined) {
+        value = fn(this[i], arg1, arg2);
+        if (value !== undefined) {
+          // any function which returns a value needs to be wrapped
+          value = jqLite(value);
+        }
+      } else {
+        JQLiteAddNodes(value, fn(this[i], arg1, arg2));
+      }
+    }
+    return value == undefined ? this : value;
+  };
+});
+
+/**
+ * Computes a hash of an 'obj'.
+ * Hash of a:
+ *  string is string
+ *  number is number as string
+ *  object is either result of calling $$hashKey function on the object or uniquely generated id,
+ *         that is also assigned to the $$hashKey property of the object.
+ *
+ * @param obj
+ * @returns {string} hash string such that the same input will have the same hash string.
+ *         The resulting string key is in 'type:hashKey' format.
+ */
+function hashKey(obj) {
+  var objType = typeof obj,
+      key;
+
+  if (objType == 'object' && obj !== null) {
+    if (typeof (key = obj.$$hashKey) == 'function') {
+      // must invoke on object to keep the right this
+      key = obj.$$hashKey();
+    } else if (key === undefined) {
+      key = obj.$$hashKey = nextUid();
+    }
+  } else {
+    key = obj;
+  }
+
+  return objType + ':' + key;
+}
+
+/**
+ * HashMap which can use objects as keys
+ */
+function HashMap(array){
+  forEach(array, this.put, this);
+}
+HashMap.prototype = {
+  /**
+   * Store key value pair
+   * @param key key to store can be any type
+   * @param value value to store can be any type
+   */
+  put: function(key, value) {
+    this[hashKey(key)] = value;
+  },
+
+  /**
+   * @param key
+   * @returns the value for the key
+   */
+  get: function(key) {
+    return this[hashKey(key)];
+  },
+
+  /**
+   * Remove the key/value pair
+   * @param key
+   */
+  remove: function(key) {
+    var value = this[key = hashKey(key)];
+    delete this[key];
+    return value;
+  }
+};
+
+/**
+ * A map where multiple values can be added to the same key such that they form a queue.
+ * @returns {HashQueueMap}
+ */
+function HashQueueMap() {}
+HashQueueMap.prototype = {
+  /**
+   * Same as array push, but using an array as the value for the hash
+   */
+  push: function(key, value) {
+    var array = this[key = hashKey(key)];
+    if (!array) {
+      this[key] = [value];
+    } else {
+      array.push(value);
+    }
+  },
+
+  /**
+   * Same as array shift, but using an array as the value for the hash
+   */
+  shift: function(key) {
+    var array = this[key = hashKey(key)];
+    if (array) {
+      if (array.length == 1) {
+        delete this[key];
+        return array[0];
+      } else {
+        return array.shift();
+      }
+    }
+  },
+
+  /**
+   * return the first item without deleting it
+   */
+  peek: function(key) {
+    var array = this[hashKey(key)];
+    if (array) {
+    return array[0];
+    }
+  }
+};
+
+/**
+ * @ngdoc function
+ * @name angular.injector
+ * @function
+ *
+ * @description
+ * Creates an injector function that can be used for retrieving services as well as for
+ * dependency injection (see {@link guide/di dependency injection}).
+ *
+
+ * @param {Array.<string|Function>} modules A list of module functions or their aliases. See
+ *        {@link angular.module}. The `ng` module must be explicitly added.
+ * @returns {function()} Injector function. See {@link AUTO.$injector $injector}.
+ *
+ * @example
+ * Typical usage
+ * <pre>
+ *   // create an injector
+ *   var $injector = angular.injector(['ng']);
+ *
+ *   // use the injector to kick off your application
+ *   // use the type inference to auto inject arguments, or use implicit injection
+ *   $injector.invoke(function($rootScope, $compile, $document){
+ *     $compile($document)($rootScope);
+ *     $rootScope.$digest();
+ *   });
+ * </pre>
+ */
+
+
+/**
+ * @ngdoc overview
+ * @name AUTO
+ * @description
+ *
+ * Implicit module which gets automatically added to each {@link AUTO.$injector $injector}.
+ */
+
+var FN_ARGS = /^function\s*[^\(]*\(\s*([^\)]*)\)/m;
+var FN_ARG_SPLIT = /,/;
+var FN_ARG = /^\s*(_?)(\S+?)\1\s*$/;
+var STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg;
+function annotate(fn) {
+  var $inject,
+      fnText,
+      argDecl,
+      last;
+
+  if (typeof fn == 'function') {
+    if (!($inject = fn.$inject)) {
+      $inject = [];
+      fnText = fn.toString().replace(STRIP_COMMENTS, '');
+      argDecl = fnText.match(FN_ARGS);
+      forEach(argDecl[1].split(FN_ARG_SPLIT), function(arg){
+        arg.replace(FN_ARG, function(all, underscore, name){
+          $inject.push(name);
+        });
+      });
+      fn.$inject = $inject;
+    }
+  } else if (isArray(fn)) {
+    last = fn.length - 1;
+    assertArgFn(fn[last], 'fn')
+    $inject = fn.slice(0, last);
+  } else {
+    assertArgFn(fn, 'fn', true);
+  }
+  return $inject;
+}
+
+///////////////////////////////////////
+
+/**
+ * @ngdoc object
+ * @name AUTO.$injector
+ * @function
+ *
+ * @description
+ *
+ * `$injector` is used to retrieve object instances as defined by
+ * {@link AUTO.$provide provider}, instantiate types, invoke methods,
+ * and load modules.
+ *
+ * The following always holds true:
+ *
+ * <pre>
+ *   var $injector = angular.injector();
+ *   expect($injector.get('$injector')).toBe($injector);
+ *   expect($injector.invoke(function($injector){
+ *     return $injector;
+ *   }).toBe($injector);
+ * </pre>
+ *
+ * # Injection Function Annotation
+ *
+ * JavaScript does not have annotations, and annotations are needed for dependency injection. The
+ * following ways are all valid way of annotating function with injection arguments and are equivalent.
+ *
+ * <pre>
+ *   // inferred (only works if code not minified/obfuscated)
+ *   $inject.invoke(function(serviceA){});
+ *
+ *   // annotated
+ *   function explicit(serviceA) {};
+ *   explicit.$inject = ['serviceA'];
+ *   $inject.invoke(explicit);
+ *
+ *   // inline
+ *   $inject.invoke(['serviceA', function(serviceA){}]);
+ * </pre>
+ *
+ * ## Inference
+ *
+ * In JavaScript calling `toString()` on a function returns the function definition. The definition can then be
+ * parsed and the function arguments can be extracted. *NOTE:* This does not work with minification, and obfuscation
+ * tools since these tools change the argument names.
+ *
+ * ## `$inject` Annotation
+ * By adding a `$inject` property onto a function the injection parameters can be specified.
+ *
+ * ## Inline
+ * As an array of injection names, where the last item in the array is the function to call.
+ */
+
+/**
+ * @ngdoc method
+ * @name AUTO.$injector#get
+ * @methodOf AUTO.$injector
+ *
+ * @description
+ * Return an instance of the service.
+ *
+ * @param {string} name The name of the instance to retrieve.
+ * @return {*} The instance.
+ */
+
+/**
+ * @ngdoc method
+ * @name AUTO.$injector#invoke
+ * @methodOf AUTO.$injector
+ *
+ * @description
+ * Invoke the method and supply the method arguments from the `$injector`.
+ *
+ * @param {!function} fn The function to invoke. The function arguments come form the function annotation.
+ * @param {Object=} self The `this` for the invoked method.
+ * @param {Object=} locals Optional object. If preset then any argument names are read from this object first, before
+ *   the `$injector` is consulted.
+ * @returns {*} the value returned by the invoked `fn` function.
+ */
+
+/**
+ * @ngdoc method
+ * @name AUTO.$injector#instantiate
+ * @methodOf AUTO.$injector
+ * @description
+ * Create a new instance of JS type. The method takes a constructor function invokes the new operator and supplies
+ * all of the arguments to the constructor function as specified by the constructor annotation.
+ *
+ * @param {function} Type Annotated constructor function.
+ * @param {Object=} locals Optional object. If preset then any argument names are read from this object first, before
+ *   the `$injector` is consulted.
+ * @returns {Object} new instance of `Type`.
+ */
+
+/**
+ * @ngdoc method
+ * @name AUTO.$injector#annotate
+ * @methodOf AUTO.$injector
+ *
+ * @description
+ * Returns an array of service names which the function is requesting for injection. This API is used by the injector
+ * to determine which services need to be injected into the function when the function is invoked. There are three
+ * ways in which the function can be annotated with the needed dependencies.
+ *
+ * # Argument names
+ *
+ * The simplest form is to extract the dependencies from the arguments of the function. This is done by converting
+ * the function into a string using `toString()` method and extracting the argument names.
+ * <pre>
+ *   // Given
+ *   function MyController($scope, $route) {
+ *     // ...
+ *   }
+ *
+ *   // Then
+ *   expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);
+ * </pre>
+ *
+ * This method does not work with code minfication / obfuscation. For this reason the following annotation strategies
+ * are supported.
+ *
+ * # The `$inject` property
+ *
+ * If a function has an `$inject` property and its value is an array of strings, then the strings represent names of
+ * services to be injected into the function.
+ * <pre>
+ *   // Given
+ *   var MyController = function(obfuscatedScope, obfuscatedRoute) {
+ *     // ...
+ *   }
+ *   // Define function dependencies
+ *   MyController.$inject = ['$scope', '$route'];
+ *
+ *   // Then
+ *   expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);
+ * </pre>
+ *
+ * # The array notation
+ *
+ * It is often desirable to inline Injected functions and that's when setting the `$inject` property is very
+ * inconvenient. In these situations using the array notation to specify the dependencies in a way that survives
+ * minification is a better choice:
+ *
+ * <pre>
+ *   // We wish to write this (not minification / obfuscation safe)
+ *   injector.invoke(function($compile, $rootScope) {
+ *     // ...
+ *   });
+ *
+ *   // We are forced to write break inlining
+ *   var tmpFn = function(obfuscatedCompile, obfuscatedRootScope) {
+ *     // ...
+ *   };
+ *   tmpFn.$inject = ['$compile', '$rootScope'];
+ *   injector.invoke(tempFn);
+ *
+ *   // To better support inline function the inline annotation is supported
+ *   injector.invoke(['$compile', '$rootScope', function(obfCompile, obfRootScope) {
+ *     // ...
+ *   }]);
+ *
+ *   // Therefore
+ *   expect(injector.annotate(
+ *      ['$compile', '$rootScope', function(obfus_$compile, obfus_$rootScope) {}])
+ *    ).toEqual(['$compile', '$rootScope']);
+ * </pre>
+ *
+ * @param {function|Array.<string|Function>} fn Function for which dependent service names need to be retrieved as described
+ *   above.
+ *
+ * @returns {Array.<string>} The names of the services which the function requires.
+ */
+
+
+
+
+/**
+ * @ngdoc object
+ * @name AUTO.$provide
+ *
+ * @description
+ *
+ * Use `$provide` to register new providers with the `$injector`. The providers are the factories for the instance.
+ * The providers share the same name as the instance they create with the `Provider` suffixed to them.
+ *
+ * A provider is an object with a `$get()` method. The injector calls the `$get` method to create a new instance of
+ * a service. The Provider can have additional methods which would allow for configuration of the provider.
+ *
+ * <pre>
+ *   function GreetProvider() {
+ *     var salutation = 'Hello';
+ *
+ *     this.salutation = function(text) {
+ *       salutation = text;
+ *     };
+ *
+ *     this.$get = function() {
+ *       return function (name) {
+ *         return salutation + ' ' + name + '!';
+ *       };
+ *     };
+ *   }
+ *
+ *   describe('Greeter', function(){
+ *
+ *     beforeEach(module(function($provide) {
+ *       $provide.provider('greet', GreetProvider);
+ *     });
+ *
+ *     it('should greet', inject(function(greet) {
+ *       expect(greet('angular')).toEqual('Hello angular!');
+ *     }));
+ *
+ *     it('should allow configuration of salutation', function() {
+ *       module(function(greetProvider) {
+ *         greetProvider.salutation('Ahoj');
+ *       });
+ *       inject(function(greet) {
+ *         expect(greet('angular')).toEqual('Ahoj angular!');
+ *       });
+ *     )};
+ *
+ *   });
+ * </pre>
+ */
+
+/**
+ * @ngdoc method
+ * @name AUTO.$provide#provider
+ * @methodOf AUTO.$provide
+ * @description
+ *
+ * Register a provider for a service. The providers can be retrieved and can have additional configuration methods.
+ *
+ * @param {string} name The name of the instance. NOTE: the provider will be available under `name + 'Provider'` key.
+ * @param {(Object|function())} provider If the provider is:
+ *
+ *   - `Object`: then it should have a `$get` method. The `$get` method will be invoked using
+ *               {@link AUTO.$injector#invoke $injector.invoke()} when an instance needs to be created.
+ *   - `Constructor`: a new instance of the provider will be created using
+ *               {@link AUTO.$injector#instantiate $injector.instantiate()}, then treated as `object`.
+ *
+ * @returns {Object} registered provider instance
+ */
+
+/**
+ * @ngdoc method
+ * @name AUTO.$provide#factory
+ * @methodOf AUTO.$provide
+ * @description
+ *
+ * A short hand for configuring services if only `$get` method is required.
+ *
+ * @param {string} name The name of the instance.
+ * @param {function()} $getFn The $getFn for the instance creation. Internally this is a short hand for
+ * `$provide.provider(name, {$get: $getFn})`.
+ * @returns {Object} registered provider instance
+ */
+
+
+/**
+ * @ngdoc method
+ * @name AUTO.$provide#service
+ * @methodOf AUTO.$provide
+ * @description
+ *
+ * A short hand for registering service of given class.
+ *
+ * @param {string} name The name of the instance.
+ * @param {Function} constructor A class (constructor function) that will be instantiated.
+ * @returns {Object} registered provider instance
+ */
+
+
+/**
+ * @ngdoc method
+ * @name AUTO.$provide#value
+ * @methodOf AUTO.$provide
+ * @description
+ *
+ * A short hand for configuring services if the `$get` method is a constant.
+ *
+ * @param {string} name The name of the instance.
+ * @param {*} value The value.
+ * @returns {Object} registered provider instance
+ */
+
+
+/**
+ * @ngdoc method
+ * @name AUTO.$provide#constant
+ * @methodOf AUTO.$provide
+ * @description
+ *
+ * A constant value, but unlike {@link AUTO.$provide#value value} it can be injected
+ * into configuration function (other modules) and it is not interceptable by
+ * {@link AUTO.$provide#decorator decorator}.
+ *
+ * @param {string} name The name of the constant.
+ * @param {*} value The constant value.
+ * @returns {Object} registered instance
+ */
+
+
+/**
+ * @ngdoc method
+ * @name AUTO.$provide#decorator
+ * @methodOf AUTO.$provide
+ * @description
+ *
+ * Decoration of service, allows the decorator to intercept the service instance creation. The
+ * returned instance may be the original instance, or a new instance which delegates to the
+ * original instance.
+ *
+ * @param {string} name The name of the service to decorate.
+ * @param {function()} decorator This function will be invoked when the service needs to be
+ *    instanciated. The function is called using the {@link AUTO.$injector#invoke
+ *    injector.invoke} method and is therefore fully injectable. Local injection arguments:
+ *
+ *    * `$delegate` - The original service instance, which can be monkey patched, configured,
+ *      decorated or delegated to.
+ */
+
+
+function createInjector(modulesToLoad) {
+  var INSTANTIATING = {},
+      providerSuffix = 'Provider',
+      path = [],
+      loadedModules = new HashMap(),
+      providerCache = {
+        $provide: {
+            provider: supportObject(provider),
+            factory: supportObject(factory),
+            service: supportObject(service),
+            value: supportObject(value),
+            constant: supportObject(constant),
+            decorator: decorator
+          }
+      },
+      providerInjector = createInternalInjector(providerCache, function() {
+        throw Error("Unknown provider: " + path.join(' <- '));
+      }),
+      instanceCache = {},
+      instanceInjector = (instanceCache.$injector =
+          createInternalInjector(instanceCache, function(servicename) {
+            var provider = providerInjector.get(servicename + providerSuffix);
+            return instanceInjector.invoke(provider.$get, provider);
+          }));
+
+
+  forEach(loadModules(modulesToLoad), function(fn) { instanceInjector.invoke(fn || noop); });
+
+  return instanceInjector;
+
+  ////////////////////////////////////
+  // $provider
+  ////////////////////////////////////
+
+  function supportObject(delegate) {
+    return function(key, value) {
+      if (isObject(key)) {
+        forEach(key, reverseParams(delegate));
+      } else {
+        return delegate(key, value);
+      }
+    }
+  }
+
+  function provider(name, provider_) {
+    if (isFunction(provider_) || isArray(provider_)) {
+      provider_ = providerInjector.instantiate(provider_);
+    }
+    if (!provider_.$get) {
+      throw Error('Provider ' + name + ' must define $get factory method.');
+    }
+    return providerCache[name + providerSuffix] = provider_;
+  }
+
+  function factory(name, factoryFn) { return provider(name, { $get: factoryFn }); }
+
+  function service(name, constructor) {
+    return factory(name, ['$injector', function($injector) {
+      return $injector.instantiate(constructor);
+    }]);
+  }
+
+  function value(name, value) { return factory(name, valueFn(value)); }
+
+  function constant(name, value) {
+    providerCache[name] = value;
+    instanceCache[name] = value;
+  }
+
+  function decorator(serviceName, decorFn) {
+    var origProvider = providerInjector.get(serviceName + providerSuffix),
+        orig$get = origProvider.$get;
+
+    origProvider.$get = function() {
+      var origInstance = instanceInjector.invoke(orig$get, origProvider);
+      return instanceInjector.invoke(decorFn, null, {$delegate: origInstance});
+    };
+  }
+
+  ////////////////////////////////////
+  // Module Loading
+  ////////////////////////////////////
+  function loadModules(modulesToLoad){
+    var runBlocks = [];
+    forEach(modulesToLoad, function(module) {
+      if (loadedModules.get(module)) return;
+      loadedModules.put(module, true);
+      if (isString(module)) {
+        var moduleFn = angularModule(module);
+        runBlocks = runBlocks.concat(loadModules(moduleFn.requires)).concat(moduleFn._runBlocks);
+
+        try {
+          for(var invokeQueue = moduleFn._invokeQueue, i = 0, ii = invokeQueue.length; i < ii; i++) {
+            var invokeArgs = invokeQueue[i],
+                provider = invokeArgs[0] == '$injector'
+                    ? providerInjector
+                    : providerInjector.get(invokeArgs[0]);
+
+            provider[invokeArgs[1]].apply(provider, invokeArgs[2]);
+          }
+        } catch (e) {
+          if (e.message) e.message += ' from ' + module;
+          throw e;
+        }
+      } else if (isFunction(module)) {
+        try {
+          runBlocks.push(providerInjector.invoke(module));
+        } catch (e) {
+          if (e.message) e.message += ' from ' + module;
+          throw e;
+        }
+      } else if (isArray(module)) {
+        try {
+          runBlocks.push(providerInjector.invoke(module));
+        } catch (e) {
+          if (e.message) e.message += ' from ' + String(module[module.length - 1]);
+          throw e;
+        }
+      } else {
+        assertArgFn(module, 'module');
+      }
+    });
+    return runBlocks;
+  }
+
+  ////////////////////////////////////
+  // internal Injector
+  ////////////////////////////////////
+
+  function createInternalInjector(cache, factory) {
+
+    function getService(serviceName) {
+      if (typeof serviceName !== 'string') {
+        throw Error('Service name expected');
+      }
+      if (cache.hasOwnProperty(serviceName)) {
+        if (cache[serviceName] === INSTANTIATING) {
+          throw Error('Circular dependency: ' + path.join(' <- '));
+        }
+        return cache[serviceName];
+      } else {
+        try {
+          path.unshift(serviceName);
+          cache[serviceName] = INSTANTIATING;
+          return cache[serviceName] = factory(serviceName);
+        } finally {
+          path.shift();
+        }
+      }
+    }
+
+    function invoke(fn, self, locals){
+      var args = [],
+          $inject = annotate(fn),
+          length, i,
+          key;
+
+      for(i = 0, length = $inject.length; i < length; i++) {
+        key = $inject[i];
+        args.push(
+          locals && locals.hasOwnProperty(key)
+          ? locals[key]
+          : getService(key)
+        );
+      }
+      if (!fn.$inject) {
+        // this means that we must be an array.
+        fn = fn[length];
+      }
+
+
+      // Performance optimization: http://jsperf.com/apply-vs-call-vs-invoke
+      switch (self ? -1 : args.length) {
+        case  0: return fn();
+        case  1: return fn(args[0]);
+        case  2: return fn(args[0], args[1]);
+        case  3: return fn(args[0], args[1], args[2]);
+        case  4: return fn(args[0], args[1], args[2], args[3]);
+        case  5: return fn(args[0], args[1], args[2], args[3], args[4]);
+        case  6: return fn(args[0], args[1], args[2], args[3], args[4], args[5]);
+        case  7: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6]);
+        case  8: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7]);
+        case  9: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8]);
+        case 10: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9]);
+        default: return fn.apply(self, args);
+      }
+    }
+
+    function instantiate(Type, locals) {
+      var Constructor = function() {},
+          instance, returnedValue;
+
+      Constructor.prototype = (isArray(Type) ? Type[Type.length - 1] : Type).prototype;
+      instance = new Constructor();
+      returnedValue = invoke(Type, instance, locals);
+
+      return isObject(returnedValue) ? returnedValue : instance;
+    }
+
+    return {
+      invoke: invoke,
+      instantiate: instantiate,
+      get: getService,
+      annotate: annotate
+    };
+  }
+}
+/**
+ * @ngdoc function
+ * @name ng.$anchorScroll
+ * @requires $window
+ * @requires $location
+ * @requires $rootScope
+ *
+ * @description
+ * When called, it checks current value of `$location.hash()` and scroll to related element,
+ * according to rules specified in
+ * {@link http://dev.w3.org/html5/spec/Overview.html#the-indicated-part-of-the-document Html5 spec}.
+ *
+ * It also watches the `$location.hash()` and scroll whenever it changes to match any anchor.
+ * This can be disabled by calling `$anchorScrollProvider.disableAutoScrolling()`.
+ */
+function $AnchorScrollProvider() {
+
+  var autoScrollingEnabled = true;
+
+  this.disableAutoScrolling = function() {
+    autoScrollingEnabled = false;
+  };
+
+  this.$get = ['$window', '$location', '$rootScope', function($window, $location, $rootScope) {
+    var document = $window.document;
+
+    // helper function to get first anchor from a NodeList
+    // can't use filter.filter, as it accepts only instances of Array
+    // and IE can't convert NodeList to an array using [].slice
+    // TODO(vojta): use filter if we change it to accept lists as well
+    function getFirstAnchor(list) {
+      var result = null;
+      forEach(list, function(element) {
+        if (!result && lowercase(element.nodeName) === 'a') result = element;
+      });
+      return result;
+    }
+
+    function scroll() {
+      var hash = $location.hash(), elm;
+
+      // empty hash, scroll to the top of the page
+      if (!hash) $window.scrollTo(0, 0);
+
+      // element with given id
+      else if ((elm = document.getElementById(hash))) elm.scrollIntoView();
+
+      // first anchor with given name :-D
+      else 

<TRUNCATED>

[23/51] [abbrv] [partial] Adding Jinwon's custom RCMET

Posted by jo...@apache.org.
http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/app/js/bootstrap.min.js
----------------------------------------------------------------------
diff --git a/src/main/ui/app/js/bootstrap.min.js b/src/main/ui/app/js/bootstrap.min.js
new file mode 100755
index 0000000..95c5ac5
--- /dev/null
+++ b/src/main/ui/app/js/bootstrap.min.js
@@ -0,0 +1,6 @@
+/*!
+* Bootstrap.js by @fat & @mdo
+* Copyright 2012 Twitter, Inc.
+* http://www.apache.org/licenses/LICENSE-2.0.txt
+*/
+!function(e){"use strict";e(function(){e.support.transition=function(){var e=function(){var e=document.createElement("bootstrap"),t={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd otransitionend",transition:"transitionend"},n;for(n in t)if(e.style[n]!==undefined)return t[n]}();return e&&{end:e}}()})}(window.jQuery),!function(e){"use strict";var t='[data-dismiss="alert"]',n=function(n){e(n).on("click",t,this.close)};n.prototype.close=function(t){function s(){i.trigger("closed").remove()}var n=e(this),r=n.attr("data-target"),i;r||(r=n.attr("href"),r=r&&r.replace(/.*(?=#[^\s]*$)/,"")),i=e(r),t&&t.preventDefault(),i.length||(i=n.hasClass("alert")?n:n.parent()),i.trigger(t=e.Event("close"));if(t.isDefaultPrevented())return;i.removeClass("in"),e.support.transition&&i.hasClass("fade")?i.on(e.support.transition.end,s):s()};var r=e.fn.alert;e.fn.alert=function(t){return this.each(function(){var r=e(this),i=r.data("alert");i||r.data("alert",i=
 new n(this)),typeof t=="string"&&i[t].call(r)})},e.fn.alert.Constructor=n,e.fn.alert.noConflict=function(){return e.fn.alert=r,this},e(document).on("click.alert.data-api",t,n.prototype.close)}(window.jQuery),!function(e){"use strict";var t=function(t,n){this.$element=e(t),this.options=e.extend({},e.fn.button.defaults,n)};t.prototype.setState=function(e){var t="disabled",n=this.$element,r=n.data(),i=n.is("input")?"val":"html";e+="Text",r.resetText||n.data("resetText",n[i]()),n[i](r[e]||this.options[e]),setTimeout(function(){e=="loadingText"?n.addClass(t).attr(t,t):n.removeClass(t).removeAttr(t)},0)},t.prototype.toggle=function(){var e=this.$element.closest('[data-toggle="buttons-radio"]');e&&e.find(".active").removeClass("active"),this.$element.toggleClass("active")};var n=e.fn.button;e.fn.button=function(n){return this.each(function(){var r=e(this),i=r.data("button"),s=typeof n=="object"&&n;i||r.data("button",i=new t(this,s)),n=="toggle"?i.toggle():n&&i.setState(n)})},e.fn.button.de
 faults={loadingText:"loading..."},e.fn.button.Constructor=t,e.fn.button.noConflict=function(){return e.fn.button=n,this},e(document).on("click.button.data-api","[data-toggle^=button]",function(t){var n=e(t.target);n.hasClass("btn")||(n=n.closest(".btn")),n.button("toggle")})}(window.jQuery),!function(e){"use strict";var t=function(t,n){this.$element=e(t),this.$indicators=this.$element.find(".carousel-indicators"),this.options=n,this.options.pause=="hover"&&this.$element.on("mouseenter",e.proxy(this.pause,this)).on("mouseleave",e.proxy(this.cycle,this))};t.prototype={cycle:function(t){return t||(this.paused=!1),this.interval&&clearInterval(this.interval),this.options.interval&&!this.paused&&(this.interval=setInterval(e.proxy(this.next,this),this.options.interval)),this},getActiveIndex:function(){return this.$active=this.$element.find(".item.active"),this.$items=this.$active.parent().children(),this.$items.index(this.$active)},to:function(t){var n=this.getActiveIndex(),r=this;if(t>thi
 s.$items.length-1||t<0)return;return this.sliding?this.$element.one("slid",function(){r.to(t)}):n==t?this.pause().cycle():this.slide(t>n?"next":"prev",e(this.$items[t]))},pause:function(t){return t||(this.paused=!0),this.$element.find(".next, .prev").length&&e.support.transition.end&&(this.$element.trigger(e.support.transition.end),this.cycle(!0)),clearInterval(this.interval),this.interval=null,this},next:function(){if(this.sliding)return;return this.slide("next")},prev:function(){if(this.sliding)return;return this.slide("prev")},slide:function(t,n){var r=this.$element.find(".item.active"),i=n||r[t](),s=this.interval,o=t=="next"?"left":"right",u=t=="next"?"first":"last",a=this,f;this.sliding=!0,s&&this.pause(),i=i.length?i:this.$element.find(".item")[u](),f=e.Event("slide",{relatedTarget:i[0],direction:o});if(i.hasClass("active"))return;this.$indicators.length&&(this.$indicators.find(".active").removeClass("active"),this.$element.one("slid",function(){var t=e(a.$indicators.children(
 )[a.getActiveIndex()]);t&&t.addClass("active")}));if(e.support.transition&&this.$element.hasClass("slide")){this.$element.trigger(f);if(f.isDefaultPrevented())return;i.addClass(t),i[0].offsetWidth,r.addClass(o),i.addClass(o),this.$element.one(e.support.transition.end,function(){i.removeClass([t,o].join(" ")).addClass("active"),r.removeClass(["active",o].join(" ")),a.sliding=!1,setTimeout(function(){a.$element.trigger("slid")},0)})}else{this.$element.trigger(f);if(f.isDefaultPrevented())return;r.removeClass("active"),i.addClass("active"),this.sliding=!1,this.$element.trigger("slid")}return s&&this.cycle(),this}};var n=e.fn.carousel;e.fn.carousel=function(n){return this.each(function(){var r=e(this),i=r.data("carousel"),s=e.extend({},e.fn.carousel.defaults,typeof n=="object"&&n),o=typeof n=="string"?n:s.slide;i||r.data("carousel",i=new t(this,s)),typeof n=="number"?i.to(n):o?i[o]():s.interval&&i.pause().cycle()})},e.fn.carousel.defaults={interval:5e3,pause:"hover"},e.fn.carousel.Const
 ructor=t,e.fn.carousel.noConflict=function(){return e.fn.carousel=n,this},e(document).on("click.carousel.data-api","[data-slide], [data-slide-to]",function(t){var n=e(this),r,i=e(n.attr("data-target")||(r=n.attr("href"))&&r.replace(/.*(?=#[^\s]+$)/,"")),s=e.extend({},i.data(),n.data()),o;i.carousel(s),(o=n.attr("data-slide-to"))&&i.data("carousel").pause().to(o).cycle(),t.preventDefault()})}(window.jQuery),!function(e){"use strict";var t=function(t,n){this.$element=e(t),this.options=e.extend({},e.fn.collapse.defaults,n),this.options.parent&&(this.$parent=e(this.options.parent)),this.options.toggle&&this.toggle()};t.prototype={constructor:t,dimension:function(){var e=this.$element.hasClass("width");return e?"width":"height"},show:function(){var t,n,r,i;if(this.transitioning||this.$element.hasClass("in"))return;t=this.dimension(),n=e.camelCase(["scroll",t].join("-")),r=this.$parent&&this.$parent.find("> .accordion-group > .in");if(r&&r.length){i=r.data("collapse");if(i&&i.transitionin
 g)return;r.collapse("hide"),i||r.data("collapse",null)}this.$element[t](0),this.transition("addClass",e.Event("show"),"shown"),e.support.transition&&this.$element[t](this.$element[0][n])},hide:function(){var t;if(this.transitioning||!this.$element.hasClass("in"))return;t=this.dimension(),this.reset(this.$element[t]()),this.transition("removeClass",e.Event("hide"),"hidden"),this.$element[t](0)},reset:function(e){var t=this.dimension();return this.$element.removeClass("collapse")[t](e||"auto")[0].offsetWidth,this.$element[e!==null?"addClass":"removeClass"]("collapse"),this},transition:function(t,n,r){var i=this,s=function(){n.type=="show"&&i.reset(),i.transitioning=0,i.$element.trigger(r)};this.$element.trigger(n);if(n.isDefaultPrevented())return;this.transitioning=1,this.$element[t]("in"),e.support.transition&&this.$element.hasClass("collapse")?this.$element.one(e.support.transition.end,s):s()},toggle:function(){this[this.$element.hasClass("in")?"hide":"show"]()}};var n=e.fn.collapse
 ;e.fn.collapse=function(n){return this.each(function(){var r=e(this),i=r.data("collapse"),s=e.extend({},e.fn.collapse.defaults,r.data(),typeof n=="object"&&n);i||r.data("collapse",i=new t(this,s)),typeof n=="string"&&i[n]()})},e.fn.collapse.defaults={toggle:!0},e.fn.collapse.Constructor=t,e.fn.collapse.noConflict=function(){return e.fn.collapse=n,this},e(document).on("click.collapse.data-api","[data-toggle=collapse]",function(t){var n=e(this),r,i=n.attr("data-target")||t.preventDefault()||(r=n.attr("href"))&&r.replace(/.*(?=#[^\s]+$)/,""),s=e(i).data("collapse")?"toggle":n.data();n[e(i).hasClass("in")?"addClass":"removeClass"]("collapsed"),e(i).collapse(s)})}(window.jQuery),!function(e){"use strict";function r(){e(t).each(function(){i(e(this)).removeClass("open")})}function i(t){var n=t.attr("data-target"),r;n||(n=t.attr("href"),n=n&&/#/.test(n)&&n.replace(/.*(?=#[^\s]*$)/,"")),r=n&&e(n);if(!r||!r.length)r=t.parent();return r}var t="[data-toggle=dropdown]",n=function(t){var n=e(t).o
 n("click.dropdown.data-api",this.toggle);e("html").on("click.dropdown.data-api",function(){n.parent().removeClass("open")})};n.prototype={constructor:n,toggle:function(t){var n=e(this),s,o;if(n.is(".disabled, :disabled"))return;return s=i(n),o=s.hasClass("open"),r(),o||s.toggleClass("open"),n.focus(),!1},keydown:function(n){var r,s,o,u,a,f;if(!/(38|40|27)/.test(n.keyCode))return;r=e(this),n.preventDefault(),n.stopPropagation();if(r.is(".disabled, :disabled"))return;u=i(r),a=u.hasClass("open");if(!a||a&&n.keyCode==27)return n.which==27&&u.find(t).focus(),r.click();s=e("[role=menu] li:not(.divider):visible a",u);if(!s.length)return;f=s.index(s.filter(":focus")),n.keyCode==38&&f>0&&f--,n.keyCode==40&&f<s.length-1&&f++,~f||(f=0),s.eq(f).focus()}};var s=e.fn.dropdown;e.fn.dropdown=function(t){return this.each(function(){var r=e(this),i=r.data("dropdown");i||r.data("dropdown",i=new n(this)),typeof t=="string"&&i[t].call(r)})},e.fn.dropdown.Constructor=n,e.fn.dropdown.noConflict=function()
 {return e.fn.dropdown=s,this},e(document).on("click.dropdown.data-api",r).on("click.dropdown.data-api",".dropdown form",function(e){e.stopPropagation()}).on("click.dropdown-menu",function(e){e.stopPropagation()}).on("click.dropdown.data-api",t,n.prototype.toggle).on("keydown.dropdown.data-api",t+", [role=menu]",n.prototype.keydown)}(window.jQuery),!function(e){"use strict";var t=function(t,n){this.options=n,this.$element=e(t).delegate('[data-dismiss="modal"]',"click.dismiss.modal",e.proxy(this.hide,this)),this.options.remote&&this.$element.find(".modal-body").load(this.options.remote)};t.prototype={constructor:t,toggle:function(){return this[this.isShown?"hide":"show"]()},show:function(){var t=this,n=e.Event("show");this.$element.trigger(n);if(this.isShown||n.isDefaultPrevented())return;this.isShown=!0,this.escape(),this.backdrop(function(){var n=e.support.transition&&t.$element.hasClass("fade");t.$element.parent().length||t.$element.appendTo(document.body),t.$element.show(),n&&t.$e
 lement[0].offsetWidth,t.$element.addClass("in").attr("aria-hidden",!1),t.enforceFocus(),n?t.$element.one(e.support.transition.end,function(){t.$element.focus().trigger("shown")}):t.$element.focus().trigger("shown")})},hide:function(t){t&&t.preventDefault();var n=this;t=e.Event("hide"),this.$element.trigger(t);if(!this.isShown||t.isDefaultPrevented())return;this.isShown=!1,this.escape(),e(document).off("focusin.modal"),this.$element.removeClass("in").attr("aria-hidden",!0),e.support.transition&&this.$element.hasClass("fade")?this.hideWithTransition():this.hideModal()},enforceFocus:function(){var t=this;e(document).on("focusin.modal",function(e){t.$element[0]!==e.target&&!t.$element.has(e.target).length&&t.$element.focus()})},escape:function(){var e=this;this.isShown&&this.options.keyboard?this.$element.on("keyup.dismiss.modal",function(t){t.which==27&&e.hide()}):this.isShown||this.$element.off("keyup.dismiss.modal")},hideWithTransition:function(){var t=this,n=setTimeout(function(){t.
 $element.off(e.support.transition.end),t.hideModal()},500);this.$element.one(e.support.transition.end,function(){clearTimeout(n),t.hideModal()})},hideModal:function(){var e=this;this.$element.hide(),this.backdrop(function(){e.removeBackdrop(),e.$element.trigger("hidden")})},removeBackdrop:function(){this.$backdrop&&this.$backdrop.remove(),this.$backdrop=null},backdrop:function(t){var n=this,r=this.$element.hasClass("fade")?"fade":"";if(this.isShown&&this.options.backdrop){var i=e.support.transition&&r;this.$backdrop=e('<div class="modal-backdrop '+r+'" />').appendTo(document.body),this.$backdrop.click(this.options.backdrop=="static"?e.proxy(this.$element[0].focus,this.$element[0]):e.proxy(this.hide,this)),i&&this.$backdrop[0].offsetWidth,this.$backdrop.addClass("in");if(!t)return;i?this.$backdrop.one(e.support.transition.end,t):t()}else!this.isShown&&this.$backdrop?(this.$backdrop.removeClass("in"),e.support.transition&&this.$element.hasClass("fade")?this.$backdrop.one(e.support.tra
 nsition.end,t):t()):t&&t()}};var n=e.fn.modal;e.fn.modal=function(n){return this.each(function(){var r=e(this),i=r.data("modal"),s=e.extend({},e.fn.modal.defaults,r.data(),typeof n=="object"&&n);i||r.data("modal",i=new t(this,s)),typeof n=="string"?i[n]():s.show&&i.show()})},e.fn.modal.defaults={backdrop:!0,keyboard:!0,show:!0},e.fn.modal.Constructor=t,e.fn.modal.noConflict=function(){return e.fn.modal=n,this},e(document).on("click.modal.data-api",'[data-toggle="modal"]',function(t){var n=e(this),r=n.attr("href"),i=e(n.attr("data-target")||r&&r.replace(/.*(?=#[^\s]+$)/,"")),s=i.data("modal")?"toggle":e.extend({remote:!/#/.test(r)&&r},i.data(),n.data());t.preventDefault(),i.modal(s).one("hide",function(){n.focus()})})}(window.jQuery),!function(e){"use strict";var t=function(e,t){this.init("tooltip",e,t)};t.prototype={constructor:t,init:function(t,n,r){var i,s,o,u,a;this.type=t,this.$element=e(n),this.options=this.getOptions(r),this.enabled=!0,o=this.options.trigger.split(" ");for(a=o
 .length;a--;)u=o[a],u=="click"?this.$element.on("click."+this.type,this.options.selector,e.proxy(this.toggle,this)):u!="manual"&&(i=u=="hover"?"mouseenter":"focus",s=u=="hover"?"mouseleave":"blur",this.$element.on(i+"."+this.type,this.options.selector,e.proxy(this.enter,this)),this.$element.on(s+"."+this.type,this.options.selector,e.proxy(this.leave,this)));this.options.selector?this._options=e.extend({},this.options,{trigger:"manual",selector:""}):this.fixTitle()},getOptions:function(t){return t=e.extend({},e.fn[this.type].defaults,this.$element.data(),t),t.delay&&typeof t.delay=="number"&&(t.delay={show:t.delay,hide:t.delay}),t},enter:function(t){var n=e.fn[this.type].defaults,r={},i;this._options&&e.each(this._options,function(e,t){n[e]!=t&&(r[e]=t)},this),i=e(t.currentTarget)[this.type](r).data(this.type);if(!i.options.delay||!i.options.delay.show)return i.show();clearTimeout(this.timeout),i.hoverState="in",this.timeout=setTimeout(function(){i.hoverState=="in"&&i.show()},i.optio
 ns.delay.show)},leave:function(t){var n=e(t.currentTarget)[this.type](this._options).data(this.type);this.timeout&&clearTimeout(this.timeout);if(!n.options.delay||!n.options.delay.hide)return n.hide();n.hoverState="out",this.timeout=setTimeout(function(){n.hoverState=="out"&&n.hide()},n.options.delay.hide)},show:function(){var t,n,r,i,s,o,u=e.Event("show");if(this.hasContent()&&this.enabled){this.$element.trigger(u);if(u.isDefaultPrevented())return;t=this.tip(),this.setContent(),this.options.animation&&t.addClass("fade"),s=typeof this.options.placement=="function"?this.options.placement.call(this,t[0],this.$element[0]):this.options.placement,t.detach().css({top:0,left:0,display:"block"}),this.options.container?t.appendTo(this.options.container):t.insertAfter(this.$element),n=this.getPosition(),r=t[0].offsetWidth,i=t[0].offsetHeight;switch(s){case"bottom":o={top:n.top+n.height,left:n.left+n.width/2-r/2};break;case"top":o={top:n.top-i,left:n.left+n.width/2-r/2};break;case"left":o={top
 :n.top+n.height/2-i/2,left:n.left-r};break;case"right":o={top:n.top+n.height/2-i/2,left:n.left+n.width}}this.applyPlacement(o,s),this.$element.trigger("shown")}},applyPlacement:function(e,t){var n=this.tip(),r=n[0].offsetWidth,i=n[0].offsetHeight,s,o,u,a;n.offset(e).addClass(t).addClass("in"),s=n[0].offsetWidth,o=n[0].offsetHeight,t=="top"&&o!=i&&(e.top=e.top+i-o,a=!0),t=="bottom"||t=="top"?(u=0,e.left<0&&(u=e.left*-2,e.left=0,n.offset(e),s=n[0].offsetWidth,o=n[0].offsetHeight),this.replaceArrow(u-r+s,s,"left")):this.replaceArrow(o-i,o,"top"),a&&n.offset(e)},replaceArrow:function(e,t,n){this.arrow().css(n,e?50*(1-e/t)+"%":"")},setContent:function(){var e=this.tip(),t=this.getTitle();e.find(".tooltip-inner")[this.options.html?"html":"text"](t),e.removeClass("fade in top bottom left right")},hide:function(){function i(){var t=setTimeout(function(){n.off(e.support.transition.end).detach()},500);n.one(e.support.transition.end,function(){clearTimeout(t),n.detach()})}var t=this,n=this.tip
 (),r=e.Event("hide");this.$element.trigger(r);if(r.isDefaultPrevented())return;return n.removeClass("in"),e.support.transition&&this.$tip.hasClass("fade")?i():n.detach(),this.$element.trigger("hidden"),this},fixTitle:function(){var e=this.$element;(e.attr("title")||typeof e.attr("data-original-title")!="string")&&e.attr("data-original-title",e.attr("title")||"").attr("title","")},hasContent:function(){return this.getTitle()},getPosition:function(){var t=this.$element[0];return e.extend({},typeof t.getBoundingClientRect=="function"?t.getBoundingClientRect():{width:t.offsetWidth,height:t.offsetHeight},this.$element.offset())},getTitle:function(){var e,t=this.$element,n=this.options;return e=t.attr("data-original-title")||(typeof n.title=="function"?n.title.call(t[0]):n.title),e},tip:function(){return this.$tip=this.$tip||e(this.options.template)},arrow:function(){return this.$arrow=this.$arrow||this.tip().find(".tooltip-arrow")},validate:function(){this.$element[0].parentNode||(this.h
 ide(),this.$element=null,this.options=null)},enable:function(){this.enabled=!0},disable:function(){this.enabled=!1},toggleEnabled:function(){this.enabled=!this.enabled},toggle:function(t){var n=t?e(t.currentTarget)[this.type](this._options).data(this.type):this;n.tip().hasClass("in")?n.hide():n.show()},destroy:function(){this.hide().$element.off("."+this.type).removeData(this.type)}};var n=e.fn.tooltip;e.fn.tooltip=function(n){return this.each(function(){var r=e(this),i=r.data("tooltip"),s=typeof n=="object"&&n;i||r.data("tooltip",i=new t(this,s)),typeof n=="string"&&i[n]()})},e.fn.tooltip.Constructor=t,e.fn.tooltip.defaults={animation:!0,placement:"top",selector:!1,template:'<div class="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>',trigger:"hover focus",title:"",delay:0,html:!1,container:!1},e.fn.tooltip.noConflict=function(){return e.fn.tooltip=n,this}}(window.jQuery),!function(e){"use strict";var t=function(e,t){this.init("popover",e,t)};t.pro
 totype=e.extend({},e.fn.tooltip.Constructor.prototype,{constructor:t,setContent:function(){var e=this.tip(),t=this.getTitle(),n=this.getContent();e.find(".popover-title")[this.options.html?"html":"text"](t),e.find(".popover-content")[this.options.html?"html":"text"](n),e.removeClass("fade top bottom left right in")},hasContent:function(){return this.getTitle()||this.getContent()},getContent:function(){var e,t=this.$element,n=this.options;return e=(typeof n.content=="function"?n.content.call(t[0]):n.content)||t.attr("data-content"),e},tip:function(){return this.$tip||(this.$tip=e(this.options.template)),this.$tip},destroy:function(){this.hide().$element.off("."+this.type).removeData(this.type)}});var n=e.fn.popover;e.fn.popover=function(n){return this.each(function(){var r=e(this),i=r.data("popover"),s=typeof n=="object"&&n;i||r.data("popover",i=new t(this,s)),typeof n=="string"&&i[n]()})},e.fn.popover.Constructor=t,e.fn.popover.defaults=e.extend({},e.fn.tooltip.defaults,{placement:"
 right",trigger:"click",content:"",template:'<div class="popover"><div class="arrow"></div><h3 class="popover-title"></h3><div class="popover-content"></div></div>'}),e.fn.popover.noConflict=function(){return e.fn.popover=n,this}}(window.jQuery),!function(e){"use strict";function t(t,n){var r=e.proxy(this.process,this),i=e(t).is("body")?e(window):e(t),s;this.options=e.extend({},e.fn.scrollspy.defaults,n),this.$scrollElement=i.on("scroll.scroll-spy.data-api",r),this.selector=(this.options.target||(s=e(t).attr("href"))&&s.replace(/.*(?=#[^\s]+$)/,"")||"")+" .nav li > a",this.$body=e("body"),this.refresh(),this.process()}t.prototype={constructor:t,refresh:function(){var t=this,n;this.offsets=e([]),this.targets=e([]),n=this.$body.find(this.selector).map(function(){var n=e(this),r=n.data("target")||n.attr("href"),i=/^#\w/.test(r)&&e(r);return i&&i.length&&[[i.position().top+(!e.isWindow(t.$scrollElement.get(0))&&t.$scrollElement.scrollTop()),r]]||null}).sort(function(e,t){return e[0]-t[0]
 }).each(function(){t.offsets.push(this[0]),t.targets.push(this[1])})},process:function(){var e=this.$scrollElement.scrollTop()+this.options.offset,t=this.$scrollElement[0].scrollHeight||this.$body[0].scrollHeight,n=t-this.$scrollElement.height(),r=this.offsets,i=this.targets,s=this.activeTarget,o;if(e>=n)return s!=(o=i.last()[0])&&this.activate(o);for(o=r.length;o--;)s!=i[o]&&e>=r[o]&&(!r[o+1]||e<=r[o+1])&&this.activate(i[o])},activate:function(t){var n,r;this.activeTarget=t,e(this.selector).parent(".active").removeClass("active"),r=this.selector+'[data-target="'+t+'"],'+this.selector+'[href="'+t+'"]',n=e(r).parent("li").addClass("active"),n.parent(".dropdown-menu").length&&(n=n.closest("li.dropdown").addClass("active")),n.trigger("activate")}};var n=e.fn.scrollspy;e.fn.scrollspy=function(n){return this.each(function(){var r=e(this),i=r.data("scrollspy"),s=typeof n=="object"&&n;i||r.data("scrollspy",i=new t(this,s)),typeof n=="string"&&i[n]()})},e.fn.scrollspy.Constructor=t,e.fn.scr
 ollspy.defaults={offset:10},e.fn.scrollspy.noConflict=function(){return e.fn.scrollspy=n,this},e(window).on("load",function(){e('[data-spy="scroll"]').each(function(){var t=e(this);t.scrollspy(t.data())})})}(window.jQuery),!function(e){"use strict";var t=function(t){this.element=e(t)};t.prototype={constructor:t,show:function(){var t=this.element,n=t.closest("ul:not(.dropdown-menu)"),r=t.attr("data-target"),i,s,o;r||(r=t.attr("href"),r=r&&r.replace(/.*(?=#[^\s]*$)/,""));if(t.parent("li").hasClass("active"))return;i=n.find(".active:last a")[0],o=e.Event("show",{relatedTarget:i}),t.trigger(o);if(o.isDefaultPrevented())return;s=e(r),this.activate(t.parent("li"),n),this.activate(s,s.parent(),function(){t.trigger({type:"shown",relatedTarget:i})})},activate:function(t,n,r){function o(){i.removeClass("active").find("> .dropdown-menu > .active").removeClass("active"),t.addClass("active"),s?(t[0].offsetWidth,t.addClass("in")):t.removeClass("fade"),t.parent(".dropdown-menu")&&t.closest("li.dro
 pdown").addClass("active"),r&&r()}var i=n.find("> .active"),s=r&&e.support.transition&&i.hasClass("fade");s?i.one(e.support.transition.end,o):o(),i.removeClass("in")}};var n=e.fn.tab;e.fn.tab=function(n){return this.each(function(){var r=e(this),i=r.data("tab");i||r.data("tab",i=new t(this)),typeof n=="string"&&i[n]()})},e.fn.tab.Constructor=t,e.fn.tab.noConflict=function(){return e.fn.tab=n,this},e(document).on("click.tab.data-api",'[data-toggle="tab"], [data-toggle="pill"]',function(t){t.preventDefault(),e(this).tab("show")})}(window.jQuery),!function(e){"use strict";var t=function(t,n){this.$element=e(t),this.options=e.extend({},e.fn.typeahead.defaults,n),this.matcher=this.options.matcher||this.matcher,this.sorter=this.options.sorter||this.sorter,this.highlighter=this.options.highlighter||this.highlighter,this.updater=this.options.updater||this.updater,this.source=this.options.source,this.$menu=e(this.options.menu),this.shown=!1,this.listen()};t.prototype={constructor:t,select:fu
 nction(){var e=this.$menu.find(".active").attr("data-value");return this.$element.val(this.updater(e)).change(),this.hide()},updater:function(e){return e},show:function(){var t=e.extend({},this.$element.position(),{height:this.$element[0].offsetHeight});return this.$menu.insertAfter(this.$element).css({top:t.top+t.height,left:t.left}).show(),this.shown=!0,this},hide:function(){return this.$menu.hide(),this.shown=!1,this},lookup:function(t){var n;return this.query=this.$element.val(),!this.query||this.query.length<this.options.minLength?this.shown?this.hide():this:(n=e.isFunction(this.source)?this.source(this.query,e.proxy(this.process,this)):this.source,n?this.process(n):this)},process:function(t){var n=this;return t=e.grep(t,function(e){return n.matcher(e)}),t=this.sorter(t),t.length?this.render(t.slice(0,this.options.items)).show():this.shown?this.hide():this},matcher:function(e){return~e.toLowerCase().indexOf(this.query.toLowerCase())},sorter:function(e){var t=[],n=[],r=[],i;whil
 e(i=e.shift())i.toLowerCase().indexOf(this.query.toLowerCase())?~i.indexOf(this.query)?n.push(i):r.push(i):t.push(i);return t.concat(n,r)},highlighter:function(e){var t=this.query.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g,"\\$&");return e.replace(new RegExp("("+t+")","ig"),function(e,t){return"<strong>"+t+"</strong>"})},render:function(t){var n=this;return t=e(t).map(function(t,r){return t=e(n.options.item).attr("data-value",r),t.find("a").html(n.highlighter(r)),t[0]}),t.first().addClass("active"),this.$menu.html(t),this},next:function(t){var n=this.$menu.find(".active").removeClass("active"),r=n.next();r.length||(r=e(this.$menu.find("li")[0])),r.addClass("active")},prev:function(e){var t=this.$menu.find(".active").removeClass("active"),n=t.prev();n.length||(n=this.$menu.find("li").last()),n.addClass("active")},listen:function(){this.$element.on("focus",e.proxy(this.focus,this)).on("blur",e.proxy(this.blur,this)).on("keypress",e.proxy(this.keypress,this)).on("keyup",e.proxy(this.keyup,t
 his)),this.eventSupported("keydown")&&this.$element.on("keydown",e.proxy(this.keydown,this)),this.$menu.on("click",e.proxy(this.click,this)).on("mouseenter","li",e.proxy(this.mouseenter,this)).on("mouseleave","li",e.proxy(this.mouseleave,this))},eventSupported:function(e){var t=e in this.$element;return t||(this.$element.setAttribute(e,"return;"),t=typeof this.$element[e]=="function"),t},move:function(e){if(!this.shown)return;switch(e.keyCode){case 9:case 13:case 27:e.preventDefault();break;case 38:e.preventDefault(),this.prev();break;case 40:e.preventDefault(),this.next()}e.stopPropagation()},keydown:function(t){this.suppressKeyPressRepeat=~e.inArray(t.keyCode,[40,38,9,13,27]),this.move(t)},keypress:function(e){if(this.suppressKeyPressRepeat)return;this.move(e)},keyup:function(e){switch(e.keyCode){case 40:case 38:case 16:case 17:case 18:break;case 9:case 13:if(!this.shown)return;this.select();break;case 27:if(!this.shown)return;this.hide();break;default:this.lookup()}e.stopPropagat
 ion(),e.preventDefault()},focus:function(e){this.focused=!0},blur:function(e){this.focused=!1,!this.mousedover&&this.shown&&this.hide()},click:function(e){e.stopPropagation(),e.preventDefault(),this.select(),this.$element.focus()},mouseenter:function(t){this.mousedover=!0,this.$menu.find(".active").removeClass("active"),e(t.currentTarget).addClass("active")},mouseleave:function(e){this.mousedover=!1,!this.focused&&this.shown&&this.hide()}};var n=e.fn.typeahead;e.fn.typeahead=function(n){return this.each(function(){var r=e(this),i=r.data("typeahead"),s=typeof n=="object"&&n;i||r.data("typeahead",i=new t(this,s)),typeof n=="string"&&i[n]()})},e.fn.typeahead.defaults={source:[],items:8,menu:'<ul class="typeahead dropdown-menu"></ul>',item:'<li><a href="#"></a></li>',minLength:1},e.fn.typeahead.Constructor=t,e.fn.typeahead.noConflict=function(){return e.fn.typeahead=n,this},e(document).on("focus.typeahead.data-api",'[data-provide="typeahead"]',function(t){var n=e(this);if(n.data("typeah
 ead"))return;n.typeahead(n.data())})}(window.jQuery),!function(e){"use strict";var t=function(t,n){this.options=e.extend({},e.fn.affix.defaults,n),this.$window=e(window).on("scroll.affix.data-api",e.proxy(this.checkPosition,this)).on("click.affix.data-api",e.proxy(function(){setTimeout(e.proxy(this.checkPosition,this),1)},this)),this.$element=e(t),this.checkPosition()};t.prototype.checkPosition=function(){if(!this.$element.is(":visible"))return;var t=e(document).height(),n=this.$window.scrollTop(),r=this.$element.offset(),i=this.options.offset,s=i.bottom,o=i.top,u="affix affix-top affix-bottom",a;typeof i!="object"&&(s=o=i),typeof o=="function"&&(o=i.top()),typeof s=="function"&&(s=i.bottom()),a=this.unpin!=null&&n+this.unpin<=r.top?!1:s!=null&&r.top+this.$element.height()>=t-s?"bottom":o!=null&&n<=o?"top":!1;if(this.affixed===a)return;this.affixed=a,this.unpin=a=="bottom"?r.top-n:null,this.$element.removeClass(u).addClass("affix"+(a?"-"+a:""))};var n=e.fn.affix;e.fn.affix=function(
 n){return this.each(function(){var r=e(this),i=r.data("affix"),s=typeof n=="object"&&n;i||r.data("affix",i=new t(this,s)),typeof n=="string"&&i[n]()})},e.fn.affix.Constructor=t,e.fn.affix.defaults={offset:0},e.fn.affix.noConflict=function(){return e.fn.affix=n,this},e(window).on("load",function(){e('[data-spy="affix"]').each(function(){var t=e(this),n=t.data();n.offset=n.offset||{},n.offsetBottom&&(n.offset.bottom=n.offsetBottom),n.offsetTop&&(n.offset.top=n.offsetTop),t.affix(n)})})}(window.jQuery);
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/app/js/controllers.js
----------------------------------------------------------------------
diff --git a/src/main/ui/app/js/controllers.js b/src/main/ui/app/js/controllers.js
new file mode 100755
index 0000000..e68094f
--- /dev/null
+++ b/src/main/ui/app/js/controllers.js
@@ -0,0 +1,572 @@
+'use strict';
+
+// Controller for the world map
+function WorldMapCtrl($rootScope, $scope, selectedDatasetInformation, regionSelectParams) {
+	$scope.datasets = selectedDatasetInformation.getDatasets();
+	$scope.regionParams = regionSelectParams.getParameters();
+
+	$scope.updateMap = function() {
+ 		
+ 		// Clear Group of layers from map if it exists
+ 		if ("rectangleGroup" in $rootScope) {
+ 			$rootScope.rectangleGroup.clearLayers();
+ 		}
+
+		// Don't process if we don't have any datasets added!!
+		if ($scope.datasets.length == 0)
+			return;
+ 		
+ 		if ("map" in $rootScope) {
+ 			// Create Group to add all rectangles to map
+ 			$rootScope.rectangleGroup = L.layerGroup();
+ 			
+ 			// Loop through datasets and add rectangles to Group 
+			var i = 0;
+ 			angular.forEach($scope.datasets, function(dataset) {
+ 				// Get bounds from dataset 
+ 				var maplatlon = dataset.latlonVals;
+ 				var bounds = [[maplatlon.latMax, maplatlon.lonMin], 
+ 				              [maplatlon.latMin, maplatlon.lonMax]];
+ 	
+ 				var polygon = L.rectangle(bounds,{
+					stroke: false,
+					fillColor: $rootScope.fillColors[i],
+ 				    fillOpacity: 0.3
+ 				});
+
+ 				// Add layer to Group
+ 				$rootScope.rectangleGroup.addLayer(polygon);
+				i++;
+ 			});
+
+			// Draw user selected region
+			if ($scope.regionParams.latMin != "" && $scope.regionParams.latMax != "" && 
+				$scope.regionParams.lonMin != "" && $scope.regionParams.lonMax != "") {
+
+				var bounds = [[$scope.regionParams.latMax, $scope.regionParams.lonMin],
+							  [$scope.regionParams.latMin, $scope.regionParams.lonMax]];
+
+				var polygon = L.rectangle(bounds, {
+					color: '#000000',
+					opacity: 1.0,
+					fill: false,
+				});
+
+				$rootScope.rectangleGroup.addLayer(polygon);
+			}
+
+ 			// Add rectangle Group to map
+ 			$rootScope.rectangleGroup.addTo($rootScope.map);
+ 		}
+	};
+
+	$scope.$watch('datasets', function() {
+		$scope.updateMap();
+	}, true);
+
+	$scope.$watch('regionParams', function() {
+		$scope.updateMap();
+	}, true);
+};
+
+// Controller for dataset parameter selection/modification
+function ParameterSelectCtrl($rootScope, $scope, $http, $timeout, selectedDatasetInformation, regionSelectParams) {
+	$scope.datasets = selectedDatasetInformation.getDatasets();
+
+	// The min/max lat/lon values from the selected datasets
+	$scope.latMin = -90;
+	$scope.latMax = 90;
+	$scope.lonMin = -180;
+	$scope.lonMax = 180;
+	$scope.start = "1980-01-01 00:00:00";
+	$scope.end = "2030-01-01 00:00:00";
+
+	// The min/max lat/lon values entered by the user
+	$scope.enteredLatMin = "";
+	$scope.enteredLatMax = "";
+	$scope.enteredLonMin = "";
+	$scope.enteredLonMax = "";
+	$scope.enteredStart = "";
+	$scope.enteredEnd = "";
+
+	// The min/max lat/lon values that are displayed
+	$scope.displayParams = regionSelectParams.getParameters();
+
+	$scope.runningEval = false;
+	
+	var updateDisplayValues = function() {
+		// Update the displayed lat/lon values. We give precedence to users entered values assuming
+		// they're valid given the current set of datasets selected.
+		//
+		// If the user has entered a value for latMin
+		if ($scope.enteredLatMin != "") {
+			// If it's not a valid value...
+			if ($scope.enteredLatMin < $scope.latMin) {
+				// Reset enteredLatMin to the "unmodified" state and display the correct value.
+				$scope.displayParams.latMin = $scope.latMin;
+			} else {
+				$scope.displayParams.latMin = $scope.enteredLatMin;
+			}
+		// Otherwise, just display the value.
+		} else { 
+			$scope.displayParams.latMin = $scope.latMin;
+		}
+		// Update latMax
+		if ($scope.enteredLatMin != "") {
+			if ($scope.enteredLatMax > $scope.latMax) {
+				$scope.displayParams.latMax = $scope.latMax;
+			} else {
+				$scope.displayParams.latMax = $scope.enteredLatMax;
+			}
+		} else { 
+			$scope.displayParams.latMax = $scope.latMax;
+		}
+		// Update lonMin
+		if ($scope.enteredLonMin != "") {
+			if ($scope.enteredLonMin < $scope.lonMin) {
+				$scope.displayParams.lonMin = $scope.lonMin;
+			} else {
+				$scope.displayParams.lonMin = $scope.enteredLonMin;
+			}
+		} else { 
+			$scope.displayParams.lonMin = $scope.lonMin;
+		}
+		// Update lonMax
+		if ($scope.enteredLonMax != "") {
+			if ($scope.enteredLonMax > $scope.lonMax) {
+				$scope.displayParams.lonMax = $scope.lonMax;
+			} else {
+				$scope.displayParams.lonMax = $scope.enteredLonMax;
+			}
+		} else { 
+			$scope.displayParams.lonMax = $scope.lonMax;
+		}
+		// Update Start time
+		if ($scope.enteredStart != "") {
+			if ($scope.enteredStart < $scope.start) {
+				$scope.displayParams.start = $scope.start;
+			} else {
+				$scope.displayParams.start = $scope.enteredStart;
+			}
+		} else {
+			$scope.displayParams.start = $scope.start;
+		}
+		// Update End time
+		if ($scope.enteredEnd != "") {
+			if ($scope.enteredEnd > $scope.end) {
+				$scope.displayParams.end = $scope.end;
+			} else {
+				$scope.displayParams.end = $scope.enteredEnd;
+			}
+		} else {
+			$scope.displayParams.end = $scope.end;
+		}
+	}
+
+	$scope.shouldDisableControls = function() {
+		return (selectedDatasetInformation.getDatasetCount() < 2);
+	}
+
+	$scope.shouldDisableEvaluate = function() {
+		return ($scope.shouldDisableControls() || $scope.runningEval);
+	}
+
+	$scope.shouldDisableClearButton = function() {
+		return (selectedDatasetInformation.getDatasetCount() == 0);
+	}
+
+	$scope.shouldDisableResultsView = function() {
+		var res = false;
+
+		if ($rootScope.evalResults == "")
+			res = true;
+
+		return res;
+	}
+
+	$scope.clearDatasets = function() {
+		selectedDatasetInformation.clearDatasets();
+	}
+
+	$scope.runEvaluation = function() {
+		$scope.runningEval = true;
+
+		// TODO
+		// Currently this has the 1 model, 1 observation format hard coded in. This shouldn't
+		// be the long-term case! This needs to be changed!!!!!!!!
+		var obsIndex = -1,
+			modelIndex = -1;
+
+		for (var i = 0; i < $scope.datasets.length; i++) {
+			if ($scope.datasets[i]['isObs'] == 1)
+				obsIndex = i;
+			else
+				modelIndex = i;
+		}
+
+		// You might wonder why this is using a jQuery ajax call instead of a built
+		// in $http.post call. The reason would be that it wasn't working with the 
+		// $http.post call but it is with this. So...there you go! This should be
+		// changed eventually!!
+		$.ajax({
+			type: 'POST',
+			url: $rootScope.baseURL + '/rcmes/run/', 
+			data: { 
+				'obsDatasetId'     : $scope.datasets[obsIndex]['id'],
+				'obsParameterId'   : $scope.datasets[obsIndex]['param'],
+				'startTime'        : $scope.displayParams.start,
+				'endTime'          : $scope.displayParams.end,
+				'latMin'           : $scope.displayParams.latMin,
+				'latMax'           : $scope.displayParams.latMax,
+				'lonMin'           : $scope.displayParams.lonMin,
+				'lonMax'           : $scope.displayParams.lonMax,
+				'filelist'         : $scope.datasets[modelIndex]['id'],
+				'modelVarName'     : $scope.datasets[modelIndex]['param'],
+				'modelTimeVarName' : $scope.datasets[modelIndex]['time'],
+				'modelLatVarName'  : $scope.datasets[modelIndex]['lat'],
+				'modelLonVarName'  : $scope.datasets[modelIndex]['lon'],
+				'regridOption'     : 'model',
+				'timeRegridOption' : 'monthly',
+				'metricOption'     : 'bias',
+			},
+			success: function(data) {
+				var comp = data['comparisonPath'].split('/');
+				var model = data['modelPath'].split('/');
+				var obs = data['obsPath'].split('/');
+
+				$rootScope.evalResults = {};
+				$rootScope.evalResults.comparisonPath = comp[comp.length - 1];
+				$rootScope.evalResults.modelPath = model[model.length - 1];
+				$rootScope.evalResults.obsPath = obs[obs.length - 1];
+
+				$scope.runningEval = false;
+
+				$timeout(function() {
+					$('#evaluationResults').trigger('modalOpen', true, true);
+				}, 100);
+			},
+			error: function(xhr, status, error) {
+				$scope.runningEval = false;
+			},
+		});
+	}
+
+	$scope.updateParameters = function() {
+		// Save the user input, even if it isn't valid.
+		$scope.enteredLatMin = $scope.displayParams.latMin;
+		$scope.enteredLatMax = $scope.displayParams.latMax;
+		$scope.enteredLonMin = $scope.displayParams.lonMin;
+		$scope.enteredLonMax = $scope.displayParams.lonMax;
+		$scope.enteredStart  = $scope.displayParams.start;
+		$scope.enteredEnd    = $scope.displayParams.end;
+
+		// Check if the user values are valid and update the display values.
+		updateDisplayValues();
+	}
+
+	$scope.$watch('datasets', 
+		function() { 
+			var numDatasets = $scope.datasets.length;
+
+ 			if (numDatasets) {
+				var latMin = -90,
+					latMax = 90,
+					lonMin = -180,
+					lonMax = 180,
+					start  = "1980-01-01 00:00:00",
+					end    = "2030-01-01 00:00:00";
+ 			
+ 				// Get the valid lat/lon range in the selected datasets.
+ 				for (var i = 0; i < numDatasets; i++) {
+ 					var curDataset = $scope.datasets[i];
+ 	
+ 					latMin = (curDataset['latlonVals']['latMin'] > latMin) ? curDataset['latlonVals']['latMin'] : latMin;
+ 					latMax = (curDataset['latlonVals']['latMax'] < latMax) ? curDataset['latlonVals']['latMax'] : latMax;
+ 					lonMin = (curDataset['latlonVals']['lonMin'] > lonMin) ? curDataset['latlonVals']['lonMin'] : lonMin;
+ 					lonMax = (curDataset['latlonVals']['lonMax'] < lonMax) ? curDataset['latlonVals']['lonMax'] : lonMax;
+ 					start = (curDataset['timeVals']['start'] > start) ? curDataset['timeVals']['start'] : start;
+ 					end = (curDataset['timeVals']['end'] < end) ? curDataset['timeVals']['end'] : end;
+				}
+			}
+
+			$scope.latMin = latMin;
+			$scope.latMax = latMax;
+			$scope.lonMin = lonMin;
+			$scope.lonMax = lonMax;
+			$scope.start = start;
+			$scope.end = end;
+
+			updateDisplayValues();
+		}, true);
+}
+
+// Controller for dataset display
+function DatasetDisplayCtrl($rootScope, $scope, selectedDatasetInformation) {
+	$scope.datasets = selectedDatasetInformation.getDatasets();
+
+	$scope.removeDataset = function($index) {
+		selectedDatasetInformation.removeDataset($index);
+	}
+}
+
+// Controller for observation selection in modal
+function ObservationSelectCtrl($rootScope, $scope, $http, $q, $timeout, selectedDatasetInformation) {
+	// Grab a copy of the datasets so we can display a count to the user!
+	$scope.datasetCount = selectedDatasetInformation.getDatasets();
+
+	// Initalize the option arrays and default to the first element
+	$scope.params      = ["Please select a file above"];
+	$scope.paramSelect = $scope.params[0];
+	$scope.lats        = ["Please select a file above"];
+	$scope.latsSelect  = $scope.lats[0];
+	$scope.lons        = ["Please select a file above"];
+	$scope.lonsSelect  = $scope.lons[0];
+	$scope.times       = ["Please select a file above"];
+	$scope.timeSelect  = $scope.times[0];
+
+	// Grab the path leader information that the webserver is using to limit directory access.
+	$scope.pathLeader = 'False';
+	$http.jsonp($rootScope.baseURL + '/getPathLeader/?callback=JSON_CALLBACK').
+		success(function(data) {
+			$scope.pathLeader = data.leader;
+	});
+
+	// Toggle load button view depending on upload state of selected files
+	$scope.loadingFile = false;
+
+	// Toggle display of a confirmation when loading a dataset
+	$scope.fileAdded = false;
+
+	$scope.latLonVals = [];
+	$scope.timeVals = [];
+	$scope.localSelectForm = {};
+
+	$scope.uploadLocalFile = function() {
+		$scope.loadingFile = true;
+
+		// TODO: Need to try to validate the input a bit. At least make sure we're not
+		// pointing at a directory perhaps?
+		
+		// TODO: Two-way binding with ng-model isn't being used here because it fails to update
+		// properly with the auto-complete that we're using on the input box. So we're doing
+		// it the wrong way temporarily...
+		var input = $('#observationFileInput').val();
+
+		// If the backend is limiting directory access we need to add that leader to our path
+		// so it remains valid!
+		if ($scope.pathLeader != 'False') {
+			input = $scope.pathLeader + input
+		}
+
+		// TODO: We're not really handling the case where there is a failure here at all. 
+		// Should check for fails and allow the user to make changes.
+		//
+		// Get model variables
+		var varsPromise = $http.jsonp($rootScope.baseURL + '/list/vars/"' + input + '"?callback=JSON_CALLBACK');
+		// Get Lat and Lon variables
+		var latlonPromise = $http.jsonp($rootScope.baseURL + '/list/latlon/"' + input + '"?callback=JSON_CALLBACK');
+		// Get Time variables
+		var timesPromise = $http.jsonp($rootScope.baseURL + '/list/time/"' + input + '"?callback=JSON_CALLBACK');
+
+		$q.all([varsPromise, latlonPromise, timesPromise]).then(
+			// Handle success fetches!
+			function(arrayOfResults) {
+				$scope.loadingFile = false;
+
+				// Handle lat/lon results
+				var data = arrayOfResults[1].data;
+				$scope.lats = [data.latname];
+				$scope.lons = [data.lonname];
+				$scope.latLonVals = [data.latMin, data.latMax, data.lonMin, data.lonMax];
+
+				// If there is more than one option for the user, tell them they need to pick one!
+				if ($scope.lats.length > 1) $scope.lats.splice(0, 0, "Please select an option");
+				if ($scope.lons.length > 1) $scope.lons.splice(0, 0, "Please select an option");
+				// Default the display to the first available option.
+				$scope.latsSelect = $scope.lats[0];
+				$scope.lonsSelect = $scope.lons[0];
+
+				// Handle time results
+				var data = arrayOfResults[2].data
+				$scope.times = [data.timename];
+
+				if ($scope.times.length > 1) $scope.times.splice(0, 0, "Please select an option");
+				$scope.timeSelect = $scope.times[0];
+
+				// Handle parameter results
+				var data = arrayOfResults[0].data.variables;
+				$scope.params = (data instanceof Array) ? data : [data];
+				$scope.params = $.grep($scope.params, 
+									function(val) {
+										return ($.inArray(val, $scope.lats)  != 0 && 
+												$.inArray(val, $scope.lons)  != 0 && 
+												$.inArray(val, $scope.times) != 0);
+									});
+				
+				if ($scope.params.length > 1) $scope.params.splice(0, 0, "Please select an option");
+				$scope.paramSelect = $scope.params[0];
+			},
+			// Uh oh! AT LEAST on of our fetches failed
+			function(arrayOfFailure) {
+				$scope.loadingFile = false;
+
+				$scope.params      = ["Unable to load variable(s)"];
+				$scope.paramSelect = $scope.params[0];
+				$scope.lats        = ["Unable to load variable(s)"];
+				$scope.latsSelect  = $scope.lats[0];
+				$scope.lons        = ["Unable to load variable(s)"];
+				$scope.lonsSelect  = $scope.lons[0];
+				$scope.times       = ["Unable to load variable(s)"];
+				$scope.timeSelect  = $scope.times[0];
+			}
+		);
+	};
+
+	$scope.addDataSet = function() {
+		// TODO: Need to verify that all the variables selected are correct!!!
+		// TODO: We shouldn't allow different parameters to match the same variables!!
+
+		var newDataset = {};
+		var input = $('#observationFileInput').val();
+
+		// If the backend is limiting directory access we need to add that leader to our path
+		// so it remains valid!
+		if ($scope.pathLeader != 'False') {
+			input = $scope.pathLeader + input
+		}
+
+		newDataset['isObs'] = 0;
+		// Save the model path. Note that the path is effectively the "id" for the model.
+		newDataset['id'] = input;
+		// Grab the file name later for display purposes.
+		var splitFilePath = input.split('/');
+		newDataset['name'] = splitFilePath[splitFilePath.length - 1];
+		// Save the model parameter variable. We save it twice for consistency and display convenience.
+		newDataset['param'] = $scope.paramSelect;
+		newDataset['paramName'] = newDataset['param'];
+		// Save the lat/lon information
+		newDataset['lat'] = $scope.latsSelect;
+		newDataset['lon'] = $scope.lonsSelect;
+
+		newDataset['latlonVals'] = {"latMin": $scope.latLonVals[0], "latMax": $scope.latLonVals[1],
+									"lonMin": $scope.latLonVals[2], "lonMax": $scope.latLonVals[3]};
+		// Get the time information
+		newDataset['time'] = $scope.timeSelect;
+		newDataset['timeVals'] = {"start": $scope.timeVals[0], "end": $scope.timeVals[1]};
+
+		selectedDatasetInformation.addDataset(newDataset);
+
+		// Reset all the fields!!
+		$scope.params = ["Please select a file above"];
+		$scope.paramSelect = $scope.params[0];
+		$scope.lats = ["Please select a file above"];
+		$scope.latsSelect = $scope.lats[0];
+		$scope.lons = ["Please select a file above"];
+		$scope.lonsSelect = $scope.lons[0];
+		$scope.times = ["Please select a file above"];
+		$scope.timeSelect = $scope.times[0];
+		$scope.latLonVals = [];
+		$scope.timeVals = [];
+
+		// Clear the input box
+		$('#observationFileInput').val("");
+
+		// Display a confirmation message for a little bit
+		$scope.fileAdded = true;
+		$timeout(function() {
+			$scope.fileAdded = false;
+		}, 2000);
+	}
+
+	$scope.shouldDisableLoadButton = function() {
+		return $scope.loadingFile;
+	}
+}
+
+function RcmedSelectionCtrl($rootScope, $scope, $http, $timeout, selectedDatasetInformation) {
+	// Grab a copy of the datasets so we can display a count to the user!
+	$scope.datasetCount = selectedDatasetInformation.getDatasets();
+	$scope.fileAdded = false;
+
+	var getObservations = function() {
+		$http.jsonp($rootScope.baseURL + '/getObsDatasets?callback=JSON_CALLBACK').
+			success(function(data) {
+				$scope.availableObs = data;
+				$scope.availableObs.splice(0, 0, {longname: 'Please select an option'});
+				$scope.datasetSelection = $scope.availableObs[0];
+			}).
+			error(function(data) {
+				$scope.availableObs = ["Unable to query RCMED"]
+			});
+	};
+
+	var getObservationTimeRange = function(datasetID) {
+		var times = {
+			'1' : {'start' : '1989-01-01 00:00:00','end' : '2009-12-31 00:00:00'},	// ERA-Interim
+			'2' : {'start' : '2002-08-31 00:00:00','end' : '2010-01-01 00:00:00'},	// AIRS
+			'3' : {'start' : '1998-01-01 00:00:00','end' : '2010-01-01 00:00:00'},	// TRMM
+			'4' : {'start' : '1948-01-01 00:00:00','end' : '2010-01-01 00:00:00'},	// URD
+			'5' : {'start' : '2000-02-24 00:00:00','end' : '2010-05-30 00:00:00'},	// MODIS
+			'6' : {'start' : '1901-01-01 00:00:00','end' : '2006-12-01 00:00:00'}   // CRU
+		};
+
+		return ((datasetID in times) ? times[datasetID] : false);
+	};
+
+	$scope.dataSelectUpdated = function() {
+		var urlString = $rootScope.baseURL + '/getDatasetParam?dataset=' + 
+							$scope.datasetSelection["shortname"] + 
+							"&callback=JSON_CALLBACK";
+		$http.jsonp(urlString).
+			success(function(data) {
+				$scope.retrievedObsParams = data;
+				if ($scope.retrievedObsParams.length > 1) 
+					$scope.retrievedObsParams.splice(0, 0, {shortname: 'Please select a parameter'});
+				$scope.parameterSelection = $scope.retrievedObsParams[0];
+			});
+	};
+
+	$scope.addObservation = function() {
+		// This is a horrible hack for temporarily getting a valid time range
+		// for the selected observation. Eventually we need to handle this more
+		// elegantly than indexing into an array...
+		var timeRange = getObservationTimeRange($scope.datasetSelection["dataset_id"]);
+
+		var newDataset = {};
+
+		newDataset['isObs'] = 1;
+		// Save the dataset id (the important part) and name (for display purposes)
+		newDataset['id'] = $scope.datasetSelection['dataset_id'];
+		newDataset['name'] = $scope.datasetSelection['longname'];
+		// Save the parameter id (the important part) and name (for display purposes)
+		newDataset['param'] = $scope.parameterSelection['parameter_id'];
+		newDataset['paramName'] = $scope.parameterSelection['longname'];
+		// Save the (fake) lat/lon information. Our datasets cover the entire globe (I think...)
+		newDataset['latlonVals'] = {"latMin": -90, "latMax": 90, "lonMin": -180, "lonMax": 180};
+		// Set some defaults for lat/lon variable names. This just helps us display stuff later.
+		newDataset['lat'] = "N/A";
+		newDataset['lon'] = "N/A";
+		// Save time range information. If we don't have saved data for this observation then
+		// we set the values to extreme values so they'll be ignored when calculating overlaps.
+		newDataset['timeVals'] = {"start": (timeRange) ? timeRange['start'] : "1901-01-01 00:00:00",
+								  "end": (timeRange) ? timeRange['end'] : "2050-01-01 00:00:00"};
+		// Set a default for the time variable names for display convenience.
+		newDataset['time'] = "N/A";
+
+		selectedDatasetInformation.addDataset(newDataset);
+
+		// Clear the user selections by requery-ing RCMED. This is really hacky, but it works for now...
+		$scope.availableObs = [];
+		$scope.retrievedObsParams = [];
+		getObservations();
+
+		// Display a confirmation message for a little bit
+		$scope.fileAdded = true;
+		$timeout(function() {
+			$scope.fileAdded = false;
+		}, 2000);
+	};
+
+	// Grab the available observations from RCMED
+	getObservations();
+}

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/app/js/directives.js
----------------------------------------------------------------------
diff --git a/src/main/ui/app/js/directives.js b/src/main/ui/app/js/directives.js
new file mode 100755
index 0000000..46a7627
--- /dev/null
+++ b/src/main/ui/app/js/directives.js
@@ -0,0 +1,374 @@
+'use strict';
+
+// Directive for dealing with the Leaflet map
+angular.module('rcmes').
+directive('sap', function($rootScope) {
+	return {
+		restrict: 'E',
+		replace: true,
+		template: '<div></div>',
+		link: function(scope, element, attrs) {
+			$rootScope.map = L.map(attrs.id, {
+				center: [40, 0],
+				zoom: 2,
+				scrollWheelZoom: false,
+			});
+			//create a CloudMade tile layer and add it to the map
+			L.tileLayer('http://{s}.tile.cloudmade.com/57cbb6ca8cac418dbb1a402586df4528/997/256/{z}/{x}/{y}.png', {
+				maxZoom: 4, minZoom: 2,
+			}).addTo($rootScope.map);
+		}
+	};
+}).
+// Directive for inserting bootstrap modals
+directive('bootstrapModal', function($timeout) {
+	var link = function(scope, elem, attrs) {
+		var escapeEvent;
+		var openModal;
+		var closeModal;
+
+		escapeEvent = function(e) {
+			if (e.which == 27)
+				closeModal();
+		}
+
+		openModal = function(event, toggleBackground, toggleKeyboardEscape) {
+			// Grab the current modal tag based on the modalId attribute in the bootstrapModal tag
+			var modal = $('#' + attrs.modalId);
+
+			// Make all the modal's children of class "close" call the appropriate function for closing!
+			$('.close', modal).bind('click', closeModal);
+
+			modal.modal({
+				show: true,
+				backdrop: toggleBackground,
+				keyboard: toggleKeyboardEscape,
+			});
+		};
+
+		closeModal = function(event) {
+			$('#' + attrs.modalId).modal('hide');
+			
+		};
+
+		// We need to bind the close and open modal events so outside elements can trigger the modal.
+		// This has to wait until the template has been fully inserted, so just wait a bit of time
+		// before we set them. I'm sure there's a better way of handling this...
+		$timeout(function() {
+			$('#' + attrs.modalId).
+				bind('modalOpen', openModal).
+				bind('modalClose', closeModal);
+		}, 100);
+	};
+
+	return {
+		link: link,
+		replace: true,
+		restrict: 'E',
+		scope: {
+			modalId: '@' 
+		},
+		template: '<div id="{{modalId}}" class="modal hide fade" tabindex="-1"><div ng-transclude></div></div>',
+		transclude: true
+	};
+}).
+// This directive process bootstrap-modal-open attributes. This lets the user bind the opening of a specific modal
+// as well as specifying how that modal should open.
+directive('bootstrapModalOpen', function() {
+	return {
+		restrict: 'A',
+		link: function(scope, elem, attrs) {
+			// Default to showing the background if the user didn't specify a value for this.
+			var hasBackground = (attrs.background === undefined ? true : attrs.background);
+			// Enable keyboard closing of modal with escape key.
+			var hasKeyboardEscape = (attrs.keyboard === undefined ? true : attrs.keyboard);
+
+			$(elem).bind('click', function() {
+				$('#' + attrs.bootstrapModalOpen).trigger('modalOpen', [hasBackground, hasKeyboardEscape]);
+			});
+		}
+	};
+}).
+// Setup a text input that the user will use to input a path to a local file.
+directive('predictiveFileBrowserInput', function() {
+	var link = function($scope, $elem, $attrs) {
+		$scope.autocomplete = [];
+		
+		/*
+		 * We need a place to dump our auto-completion options
+		 */
+		$($elem).parent().append('<ul id="autoCompletePath"><ul>');
+
+		// Handle user clicks on auto-complete path options
+		$(document).on('click', '#autoCompletePath li span', function(e) {
+			// Set the input text box's value to that of the user selected path
+			var val = $(e.target).text();
+			$($elem).val(val);
+
+			// If the user selected a directory, find more results..
+			if (val[val.length - 1] == '/') {
+				$scope.fetchFiles($($elem).val());
+			// Otherwise, remove the auto-complete options...
+			} else {
+				$('#autoCompletePath li').remove();
+			}
+		});
+
+		/*
+		 * Handle key-down events on the input box
+		 *
+		 * We need to ignore <TAB> presses here so we can auto-complete with <TAB>.
+		 * If we don't ignore here then <TAB> will move the user to the next field
+		 * in the form and our common-prefix-fill won't work later.
+		 */
+		$($elem).keydown(function(e) {
+			var code = e.keyCode || e.which;
+			var BACKSPACE = 8,
+				TAB = 9;
+
+			if (code == TAB)
+				return false;
+		});
+
+		/*
+		 * Handle key-up events on the input box
+		 */
+		$($elem).keyup(function(e) {
+			var code = e.keyCode || e.which;
+			var BACKSPACE = 8,
+				TAB = 9,
+				FORWARD_SLASH = 191;
+
+			if (code === FORWARD_SLASH) {
+				// Fetch new directory information from the server.
+				$scope.fetchFiles($(this).val());
+			} else if (code === TAB) {
+				// Attempt to auto-fill for the user.
+				$scope.handleTabPress();
+			} else if (code == BACKSPACE) {
+				// Need to properly handle the removal of directory information
+				// and the displaying of auto-complete options
+				$scope.handleBackSpace();
+			} else {
+				// Filter auto-complete options based on user input..
+				$scope.handleMiscKeyPress();
+			}
+
+			// This is being used so we can handle backspacing. The user might hold
+			// down the backspace key or select a section of text and delete. This allows
+			// us to compare the result to its prior state, which makes handling
+			// backspaces easier.
+			$scope.lastInputContents = $elem.val();
+		});
+
+		/*
+		 * Grab additional path information from the web-server
+		 *
+		 * Params:
+		 *		path - The path to get a directory listing of.
+		 */
+		// TODO Make this use $HTTP
+		$scope.fetchFiles = function(path) {
+			$.get($scope.baseURL + '/getDirInfo/' + path, {},
+				 function(data) {
+					 $scope.setNewData(data);
+					 $scope.updateAutoComplete();
+				 }, 'json');
+		};
+
+		/*
+		 * Grab additional path information from the web-server and filter the
+		 * results based on the current input text.
+		 *
+		 * Params:
+		 *		path - The path to get a directory listing of.
+		 *
+		 * This is needed to handle deletion of selected text. It is possible that
+		 * the user will select text and delete only part of a word. The results
+		 * need to be filtered based on this partial input.
+		 */
+		// TODO Why isn't this using $http?!?!?! Because I copy and pasted!!!!
+		$scope.fetchFilesAndFilter = function(path) {
+			$.get($scope.baseURL + '/getDirInfo/' + path, {},
+				 function(data) {
+					 $scope.setNewData(data);
+					 $scope.filterResults();
+					 $scope.updateAutoComplete();
+				 }, 'json');
+		};
+
+		/*
+		 * Handle directory data from the server.
+		 *
+		 * We store the entire directory information along with the remaining
+		 * possible options given the users current input. This lets us avoid
+		 * unnecessary calls to the server for directory information every time
+		 * the user deletes something.
+		 */
+		$scope.setNewData = function(data) {
+			$scope.autocomplete = data.sort();
+			$scope.possibleCompletes = $scope.autocomplete;
+		};
+
+		/* 
+		 * Handle <TAB> presses.
+		 *
+		 * Attempt to auto-complete options when the user presses <TAB>.
+		 */
+		$scope.handleTabPress = function() {
+			// If there's only one option available there's no points in trying to
+			// find a common prefix! Just set the value!
+			if ($scope.possibleCompletes.length === 1) {
+				$elem.val($scope.possibleCompletes[0]);
+
+				// Make sure more options are displayed if a directory was selected.
+				$scope.checkForMoreOptions();
+				$scope.updateAutoComplete();
+				return;
+			}
+
+			// Find the greatest common prefix amongst the remaining choices and set
+			// the input text to it.
+			var prefix = $scope.getLargestCommonPrefix($scope.possibleCompletes);
+			$elem.val(prefix);
+			$scope.updateAutoComplete();
+		};
+
+		/*
+		 * Handle Backspacing and option displaying.
+		 *
+		 * The auto-complete options needs to be displayed correctly when the user
+		 * removes directory information.
+		 */
+		$scope.handleBackSpace = function() {
+			var curInputVal = $elem.val();
+
+			// If the user deletes everything in the input box all we need to do
+			// is make sure that the auto-complete options aren't displayed.
+			if (curInputVal.length === 0) {
+				$('#autoCompletePath li').remove();
+				return;
+			}
+
+			// Figure out how much text the user removed from the input box.
+			var lengthDiff = $scope.lastInputContents.length - curInputVal.length;
+			// Grab the removed text.
+			var removedText = $scope.lastInputContents.substr(-lengthDiff);
+
+			// If the user deleted over a directory we need to fetch information on the
+			// previous directory for auto-completion.
+			if (removedText.indexOf('/') !== -1) {
+				var lastSlashIndex = curInputVal.lastIndexOf('/');
+
+				// If the remaining path still contains a directory...
+				if (lastSlashIndex !== -1) {
+					// Grab the section of the path that points to a valid directory,
+					// fetch the listing, and update the results.
+					var pathToSearch = curInputVal.slice(0, lastSlashIndex + 1);
+					$scope.fetchFilesAndFilter(pathToSearch);
+				} else {
+					// Delete the old auto-complete information in the case where the user
+					// completely removed path information.
+					$('#autoCompletePath li').remove();
+				}
+			} else {
+				// Otherwise, we just need to filter results based on the remaining input.
+				$scope.filterResults();
+				$scope.updateAutoComplete();
+			}
+		};
+
+		/* 
+		 * Handle all other key presses in the input box
+		 *
+		 * Filter the auto-complete options as the user types to ensure that only options
+		 * which are possible given the current input text are still displayed.
+		 */
+		$scope.handleMiscKeyPress = function() {
+			// Safely exit when there are no options available.
+			if ($scope.autocomplete === [])
+				return;
+
+			// Otherwise, filter the results.
+			$scope.filterResults();
+			$scope.updateAutoComplete();
+		};
+
+		/* 
+		 * When a path is auto-completed with <TAB> we need to check to see if it points
+		 * to a directory. If it does, we still need to fetch results!
+		 */
+		$scope.checkForMoreOptions = function() {
+			var path = $elem.val();
+			if (path[path.length - 1] === '/') {
+				$scope.fetchFiles(path);
+			}
+		};
+
+		/* 
+		 * Calculate the greatest common prefix of the passed options.
+		 *
+		 * Params:
+		 *		Options - An array of strings in which the greatest common prefix
+		 *				  should be found
+		 *
+		 * Returns:
+		 *		The greatest common prefix of the strings.
+		 *
+		 *
+		 * Note - For us, there will always be a prefix of at least '/' since this can't
+		 * possible be called without the users entering a starting directory. As a result,
+		 * we don't explicitly handle the case where there is 0 length common prefix.
+		 */
+		$scope.getLargestCommonPrefix = function(options) {
+			var index = 1;
+			var shortestString = options.reduce(function(a, b) { return a.length < b.length ? a : b; });
+			var longestString = options.reduce(function(a, b) { return a.length > b.length ? a : b; });
+			var	substringToCheck = shortestString[0];
+
+			while (longestString.indexOf(substringToCheck) !== -1) {
+				substringToCheck = shortestString.slice(0, ++index);
+			}
+
+			return longestString.slice(0, index - 1);
+		};
+
+		/* 
+		 * Filter the auto-complete options based on the current input.
+		 */
+		$scope.filterResults = function() {
+			$scope.possibleCompletes = $scope.autocomplete.filter(function(item, index, array) {
+				return (~item.indexOf($($elem).val()));
+			});
+
+			$scope.possibleCompletes.sort();
+		};
+
+		/*
+		 * Update the display of auto-complete options.
+		 */
+		$scope.updateAutoComplete = function() {
+			// Remove all the existing options
+			$('#autoCompletePath li').remove();
+
+			// We don't need to show anything if the user has completely selected
+			// the only existing option available.
+			if ($scope.possibleCompletes.length === 1) {
+				if ($scope.possibleCompletes[0] === $elem.val()) {
+					return;
+				}
+			}
+
+			// Display all the possible completes
+			$.each($scope.possibleCompletes, function(i, v) {
+				$('#autoCompletePath').append($('<li>').html($('<span>').text(v)));
+			});
+		};
+	};
+
+	return {
+		link: link,
+		scope: true,
+		restrict: 'A'
+	};
+});

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/app/js/filters.js
----------------------------------------------------------------------
diff --git a/src/main/ui/app/js/filters.js b/src/main/ui/app/js/filters.js
new file mode 100755
index 0000000..259dd4e
--- /dev/null
+++ b/src/main/ui/app/js/filters.js
@@ -0,0 +1,10 @@
+'use strict';
+
+/* Filters */
+
+angular.module('myApp.filters', []).
+  filter('interpolate', ['version', function(version) {
+    return function(text) {
+      return String(text).replace(/\%VERSION\%/mg, version);
+    }
+  }]);

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/app/js/jasny-bootstrap.min.js
----------------------------------------------------------------------
diff --git a/src/main/ui/app/js/jasny-bootstrap.min.js b/src/main/ui/app/js/jasny-bootstrap.min.js
new file mode 100755
index 0000000..320fff4
--- /dev/null
+++ b/src/main/ui/app/js/jasny-bootstrap.min.js
@@ -0,0 +1,6 @@
+/*!
+* Jasny-bootstrap.js by @ArnoldDaniels
+* Copyright 2012 Arnold Daniels
+* http://www.apache.org/licenses/LICENSE-2.0.txt
+*/
+!function(e){"use strict";var t=function(t,n){this.$element=e(t),this.options=e.extend({},e.fn.typeahead.defaults,n),this.options.target&&(this.$target=e(this.options.target)),this.matcher=this.options.matcher||this.matcher,this.sorter=this.options.sorter||this.sorter,this.highlighter=this.options.highlighter||this.highlighter,this.updater=this.options.updater||this.updater,this.source=this.options.source,this.strict=this.options.strict,this.$menu=e(this.options.menu),this.shown=!1,typeof this.source=="string"&&(this.url=this.source,this.source=this.searchAjax),t.nodeName=="SELECT"&&this.replaceSelect(),this.text=this.$element.val(),this.$element.attr("data-text",this.value).attr("autocomplete","off"),typeof this.$target!="undefined"?this.$element.attr("data-value",this.$target.val()):typeof this.$element.attr("data-value")=="undefined"&&this.$element.attr("data-value",this.strict?"":this.value),this.$menu.css("min-width",this.$element.width()+12),this.listen()};t.prototype={constru
 ctor:t,replaceSelect:function(){this.$target=this.$element,this.$element=e('<input type="text" />'),this.source={},this.strict=!0;var t=this.$target.find("option"),n;for(var r=0;r<t.length;r++){n=e(t[r]);if(n.val()===""){this.$element.attr("placeholder",n.html());continue}this.source[n.val()]=n.html(),this.$target.val()==n.val()&&this.$element.val(n.html())}var i=this.$target[0].attributes;for(r=0;r<i.length;r++)i[r].nodeName!="type"&&i[r].nodeName!="name"&&i[r].nodeName!="id"&&i[r].nodeName!="data-provide"&&!i[r].nodeName.match(/^on/)&&this.$element.attr(i[r].nodeName,i[r].nodeValue);this.$element.insertAfter(this.$target),this.$target.attr("autofocus")&&this.$element.trigger("focus").select(),this.$target.attr("autofocus",!1),this.$target.hide()},destroyReplacement:function(){typeof this.$target!="undefined"&&this.$target[0].nodeName=="SELECT"&&this.$element.replaceWith("")},select:function(){var e=this.$menu.find(".active"),t=e.attr("data-value"),n=e.find(".item-text").length>0?e
 .find(".item-text").text():e.text();return t=this.updater(t,"value"),n=this.updater(n,"text"),this.$element.val(n).attr("data-value",t),this.text=n,typeof this.$target!="undefined"&&this.$target.val(t).trigger("change"),this.$element.trigger("change"),this.hide()},updater:function(e,t){return e},show:function(){var t=e.extend({},this.$element.position(),{height:this.$element[0].offsetHeight});return this.$menu.insertAfter(this.$element).css({top:t.top+t.height,left:t.left}).show(),this.shown=!0,this},hide:function(){return this.$menu.hide(),this.shown=!1,this},lookup:function(t){var n;return this.query=this.$element.val(),!this.query||this.query.length<this.options.minLength?this.shown?this.hide():this:(n=e.isFunction(this.source)?this.source(this.query,e.proxy(this.process,this)):this.source,n?this.process(n):this)},process:function(t){return e.isArray(t)?this.processArray(t):this.processObject(t)},processArray:function(t){var n=this;return t=e.grep(t,function(e){return n.matcher(e
 )}),t=this.sorter(t),t.length?this.render(t.slice(0,this.options.items)).show():this.shown?this.hide():this},processObject:function(t){var n=this,r={},i=0;return e.each(t,function(e,t){n.matcher(t)&&(r[e]=t)}),r=this.sorter(r),e.isEmptyObject(r)?this.shown?this.hide():this:(e.each(r,function(e,t){i++>=n.options.items&&delete r[e]}),this.render(r).show())},searchAjax:function(t,n){var r=this;this.ajaxTimeout&&clearTimeout(this.ajaxTimeout),this.ajaxTimeout=setTimeout(function(){r.ajaxTimeout&&clearTimeout(r.ajaxTimeout);if(t===""){r.hide();return}e.get(r.url,{q:t,limit:r.options.items},function(e){typeof e=="string"&&(e=JSON.parse(e)),n(e)})},this.options.ajaxdelay)},matcher:function(e){return~e.toLowerCase().indexOf(this.query.toLowerCase())},sorter:function(t){return e.isArray(t)?this.sortArray(t):this.sortObject(t)},sortArray:function(e){var t=[],n=[],r=[],i;while(i=e.shift())i.toLowerCase().indexOf(this.query.toLowerCase())?~i.indexOf(this.query)?n.push(i):r.push(i):t.push(i);ret
 urn t.concat(n,r)},sortObject:function(e){var t={},n;for(n in e)e[n].toLowerCase().indexOf(this.query.toLowerCase())||(t[n]=e[n],delete e[n]);for(n in e)~e[n].indexOf(this.query)&&(t[n]=e[n],delete e[n]);for(n in e)t[n]=e[n];return t},highlighter:function(e){var t=this.query.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g,"\\$&");return e.replace(new RegExp("("+t+")","ig"),function(e,t){return"<strong>"+t+"</strong>"})},render:function(t){var n=this,r=e([]);return e.map(t,function(i,s){if(r.length>=n.options.items)return;var o,u;e.isArray(t)&&(s=i),o=e(n.options.item),u=o.find("a").length?o.find("a"):o,u.html(n.highlighter(i)),o.attr("data-value",s),o.find("a").length===0&&o.addClass("dropdown-header"),r.push(o[0])}),r.not(".dropdown-header").first().addClass("active"),this.$menu.html(r),this},next:function(t){var n=this.$menu.find(".active").removeClass("active"),r=n.nextAll("li:not(.dropdown-header)").first();r.length||(r=e(this.$menu.find("li:not(.dropdown-header)")[0])),r.addClass("active
 ")},prev:function(e){var t=this.$menu.find(".active").removeClass("active"),n=t.prevAll("li:not(.dropdown-header)").first();n.length||(n=this.$menu.find("li:not(.dropdown-header)").last()),n.addClass("active")},listen:function(){this.$element.on("focus",e.proxy(this.focus,this)).on("blur",e.proxy(this.blur,this)).on("change",e.proxy(this.change,this)).on("keypress",e.proxy(this.keypress,this)).on("keyup",e.proxy(this.keyup,this)),this.eventSupported("keydown")&&this.$element.on("keydown",e.proxy(this.keydown,this)),this.$menu.on("click",e.proxy(this.click,this)).on("mouseenter","li",e.proxy(this.mouseenter,this)).on("mouseleave","li",e.proxy(this.mouseleave,this)),e(window).on("unload",e.proxy(this.destroyReplacement,this))},eventSupported:function(e){var t=e in this.$element;return t||(this.$element.setAttribute(e,"return;"),t=typeof this.$element[e]=="function"),t},move:function(e){if(!this.shown)return;switch(e.keyCode){case 9:case 13:case 27:e.preventDefault();break;case 38:e.pr
 eventDefault(),this.prev();break;case 40:e.preventDefault(),this.next()}e.stopPropagation()},keydown:function(t){this.suppressKeyPressRepeat=~e.inArray(t.keyCode,[40,38,9,13,27]),this.move(t)},keypress:function(e){if(this.suppressKeyPressRepeat)return;this.move(e)},keyup:function(e){switch(e.keyCode){case 40:case 38:case 16:case 17:case 18:break;case 9:case 13:if(!this.shown)return;this.select();break;case 27:if(!this.shown)return;this.hide();break;default:this.lookup()}e.stopPropagation(),e.preventDefault()},change:function(e){var t;this.$element.val()!=this.text&&(t=this.$element.val()===""||this.strict?"":this.$element.val(),this.$element.val(t),this.$element.attr("data-value",t),this.text=t,typeof this.$target!="undefined"&&this.$target.val(t))},focus:function(e){this.focused=!0},blur:function(e){this.focused=!1,!this.mousedover&&this.shown&&this.hide()},click:function(e){e.stopPropagation(),e.preventDefault(),this.select(),this.$element.focus()},mouseenter:function(t){this.mous
 edover=!0,this.$menu.find(".active").removeClass("active"),e(t.currentTarget).addClass("active")},mouseleave:function(e){this.mousedover=!1,!this.focused&&this.shown&&this.hide()}};var n=e.fn.typeahead;e.fn.typeahead=function(n){return this.each(function(){var r=e(this),i=r.data("typeahead"),s=typeof n=="object"&&n;i||r.data("typeahead",i=new t(this,s)),typeof n=="string"&&i[n]()})},e.fn.typeahead.defaults={source:[],items:8,menu:'<ul class="typeahead dropdown-menu"></ul>',item:'<li><a href="#"></a></li>',ajaxdelay:400,minLength:1},e.fn.typeahead.Constructor=t,e.fn.typeahead.noConflict=function(){return e.fn.typeahead=n,this},e(document).off("focus.typeahead.data-api").on("focus.typeahead.data-api",'[data-provide="typeahead"]',function(t){var n=e(this);if(n.data("typeahead"))return;n.is("select")&&n.attr("autofocus",!0),t.preventDefault(),n.typeahead(n.data())})}(window.jQuery),!function(e){"use strict";var t=window.orientation!==undefined,n=navigator.userAgent.toLowerCase().indexOf
 ("android")>-1,r=function(t,r){if(n)return;this.$element=e(t),this.options=e.extend({},e.fn.inputmask.defaults,r),this.mask=String(r.mask),this.init(),this.listen(),this.checkVal()};r.prototype={init:function(){var t=this.options.definitions,n=this.mask.length;this.tests=[],this.partialPosition=this.mask.length,this.firstNonMaskPos=null,e.each(this.mask.split(""),e.proxy(function(e,r){r=="?"?(n--,this.partialPosition=e):t[r]?(this.tests.push(new RegExp(t[r])),this.firstNonMaskPos===null&&(this.firstNonMaskPos=this.tests.length-1)):this.tests.push(null)},this)),this.buffer=e.map(this.mask.split(""),e.proxy(function(e,n){if(e!="?")return t[e]?this.options.placeholder:e},this)),this.focusText=this.$element.val(),this.$element.data("rawMaskFn",e.proxy(function(){return e.map(this.buffer,function(e,t){return this.tests[t]&&e!=this.options.placeholder?e:null}).join("")},this))},listen:function(){if(this.$element.attr("readonly"))return;var t=(navigator.userAgent.match(/msie/i)?"paste":"in
 put")+".mask";this.$element.on("unmask",e.proxy(this.unmask,this)).on("focus.mask",e.proxy(this.focusEvent,this)).on("blur.mask",e.proxy(this.blurEvent,this)).on("keydown.mask",e.proxy(this.keydownEvent,this)).on("keypress.mask",e.proxy(this.keypressEvent,this)).on(t,e.proxy(this.pasteEvent,this))},caret:function(e,t){if(this.$element.length===0)return;if(typeof e=="number")return t=typeof t=="number"?t:e,this.$element.each(function(){if(this.setSelectionRange)this.setSelectionRange(e,t);else if(this.createTextRange){var n=this.createTextRange();n.collapse(!0),n.moveEnd("character",t),n.moveStart("character",e),n.select()}});if(this.$element[0].setSelectionRange)e=this.$element[0].selectionStart,t=this.$element[0].selectionEnd;else if(document.selection&&document.selection.createRange){var n=document.selection.createRange();e=0-n.duplicate().moveStart("character",-1e5),t=e+n.text.length}return{begin:e,end:t}},seekNext:function(e){var t=this.mask.length;while(++e<=t&&!this.tests[e]);
 return e},seekPrev:function(e){while(--e>=0&&!this.tests[e]);return e},shiftL:function(e,t){var n=this.mask.length;if(e<0)return;for(var r=e,i=this.seekNext(t);r<n;r++)if(this.tests[r]){if(!(i<n&&this.tests[r].test(this.buffer[i])))break;this.buffer[r]=this.buffer[i],this.buffer[i]=this.options.placeholder,i=this.seekNext(i)}this.writeBuffer(),this.caret(Math.max(this.firstNonMaskPos,e))},shiftR:function(e){var t=this.mask.length;for(var n=e,r=this.options.placeholder;n<t;n++)if(this.tests[n]){var i=this.seekNext(n),s=this.buffer[n];this.buffer[n]=r;if(!(i<t&&this.tests[i].test(s)))break;r=s}},unmask:function(){this.$element.unbind(".mask").removeData("inputmask")},focusEvent:function(){this.focusText=this.$element.val();var t=this.mask.length,n=this.checkVal();this.writeBuffer();var r=this,i=function(){n==t?r.caret(0,n):r.caret(n)};e.browser.msie?i():setTimeout(i,0)},blurEvent:function(){this.checkVal(),this.$element.val()!=this.focusText&&this.$element.trigger("change")},keydownEv
 ent:function(e){var n=e.which;if(n==8||n==46||t&&n==127){var r=this.caret(),i=r.begin,s=r.end;return s-i===0&&(i=n!=46?this.seekPrev(i):s=this.seekNext(i-1),s=n==46?this.seekNext(s):s),this.clearBuffer(i,s),this.shiftL(i,s-1),!1}if(n==27)return this.$element.val(this.focusText),this.caret(0,this.checkVal()),!1},keypressEvent:function(e){var t=this.mask.length,n=e.which,r=this.caret();if(e.ctrlKey||e.altKey||e.metaKey||n<32)return!0;if(n){r.end-r.begin!==0&&(this.clearBuffer(r.begin,r.end),this.shiftL(r.begin,r.end-1));var i=this.seekNext(r.begin-1);if(i<t){var s=String.fromCharCode(n);if(this.tests[i].test(s)){this.shiftR(i),this.buffer[i]=s,this.writeBuffer();var o=this.seekNext(i);this.caret(o)}}return!1}},pasteEvent:function(){var e=this;setTimeout(function(){e.caret(e.checkVal(!0))},0)},clearBuffer:function(e,t){var n=this.mask.length;for(var r=e;r<t&&r<n;r++)this.tests[r]&&(this.buffer[r]=this.options.placeholder)},writeBuffer:function(){return this.$element.val(this.buffer.joi
 n("")).val()},checkVal:function(e){var t=this.mask.length,n=this.$element.val(),r=-1;for(var i=0,s=0;i<t;i++)if(this.tests[i]){this.buffer[i]=this.options.placeholder;while(s++<n.length){var o=n.charAt(s-1);if(this.tests[i].test(o)){this.buffer[i]=o,r=i;break}}if(s>n.length)break}else this.buffer[i]==n.charAt(s)&&i!=this.partialPosition&&(s++,r=i);if(!e&&r+1<this.partialPosition)this.$element.val(""),this.clearBuffer(0,t);else if(e||r+1>=this.partialPosition)this.writeBuffer(),e||this.$element.val(this.$element.val().substring(0,r+1));return this.partialPosition?i:this.firstNonMaskPos}},e.fn.inputmask=function(t){return this.each(function(){var n=e(this),i=n.data("inputmask");i||n.data("inputmask",i=new r(this,t))})},e.fn.inputmask.defaults={mask:"",placeholder:"_",definitions:{9:"[0-9]",a:"[A-Za-z]","?":"[A-Za-z0-9]","*":"."}},e.fn.inputmask.Constructor=r,e(document).on("focus.inputmask.data-api","[data-mask]",function(t){var n=e(this);if(n.data("inputmask"))return;t.preventDefault
 (),n.inputmask(n.data())})}(window.jQuery),!function(e){"use strict";var t=function(t,n){n=e.extend({},e.fn.rowlink.defaults,n);var r=t.nodeName.toLowerCase()=="tr"?e(t):e(t).find("tr:has(td)");r.each(function(){var t=e(this).find(n.target).first();if(!t.length)return;var r=t.attr("href");e(this).find("td").not(".nolink").click(function(){window.location=r}),e(this).addClass("rowlink"),t.replaceWith(t.html())})};e.fn.rowlink=function(n){return this.each(function(){var r=e(this),i=r.data("rowlink");i||r.data("rowlink",i=new t(this,n))})},e.fn.rowlink.defaults={target:"a"},e.fn.rowlink.Constructor=t,e(function(){e('[data-provide="rowlink"],[data-provides="rowlink"]').each(function(){e(this).rowlink(e(this).data())})})}(window.jQuery),!function(e){"use strict";var t=function(t,n){this.$element=e(t),this.type=this.$element.data("uploadtype")||(this.$element.find(".thumbnail").length>0?"image":"file"),this.$input=this.$element.find(":file");if(this.$input.length===0)return;this.name=this
 .$input.attr("name")||n.name,this.$hidden=this.$element.find('input[type=hidden][name="'+this.name+'"]'),this.$hidden.length===0&&(this.$hidden=e('<input type="hidden" />'),this.$element.prepend(this.$hidden)),this.$preview=this.$element.find(".fileupload-preview");var r=this.$preview.css("height");this.$preview.css("display")!="inline"&&r!="0px"&&r!="none"&&this.$preview.css("line-height",r),this.original={exists:this.$element.hasClass("fileupload-exists"),preview:this.$preview.html(),hiddenVal:this.$hidden.val()},this.$remove=this.$element.find('[data-dismiss="fileupload"]'),this.$element.find('[data-trigger="fileupload"]').on("click.fileupload",e.proxy(this.trigger,this)),this.listen()};t.prototype={listen:function(){this.$input.on("change.fileupload",e.proxy(this.change,this)),e(this.$input[0].form).on("reset.fileupload",e.proxy(this.reset,this)),this.$remove&&this.$remove.on("click.fileupload",e.proxy(this.clear,this))},change:function(e,t){if(t==="clear")return;var n=e.target.
 files!==undefined?e.target.files[0]:e.target.value?{name:e.target.value.replace(/^.+\\/,"")}:null;if(!n){this.clear();return}this.$hidden.val(""),this.$hidden.attr("name",""),this.$input.attr("name",this.name);if(this.type==="image"&&this.$preview.length>0&&(typeof n.type!="undefined"?n.type.match("image.*"):n.name.match(/\.(gif|png|jpe?g)$/i))&&typeof FileReader!="undefined"){var r=new FileReader,i=this.$preview,s=this.$element;r.onload=function(e){i.html('<img src="'+e.target.result+'" '+(i.css("max-height")!="none"?'style="max-height: '+i.css("max-height")+';"':"")+" />"),s.addClass("fileupload-exists").removeClass("fileupload-new")},r.readAsDataURL(n)}else this.$preview.text(n.name),this.$element.addClass("fileupload-exists").removeClass("fileupload-new")},clear:function(e){this.$hidden.val(""),this.$hidden.attr("name",this.name),this.$input.attr("name","");if(navigator.userAgent.match(/msie/i)){var t=this.$input.clone(!0);this.$input.after(t),this.$input.remove(),this.$input=t}
 else this.$input.val("");this.$preview.html(""),this.$element.addClass("fileupload-new").removeClass("fileupload-exists"),e&&(this.$input.trigger("change",["clear"]),e.preventDefault())},reset:function(e){this.clear(),this.$hidden.val(this.original.hiddenVal),this.$preview.html(this.original.preview),this.original.exists?this.$element.addClass("fileupload-exists").removeClass("fileupload-new"):this.$element.addClass("fileupload-new").removeClass("fileupload-exists")},trigger:function(e){this.$input.trigger("click"),e.preventDefault()}},e.fn.fileupload=function(n){return this.each(function(){var r=e(this),i=r.data("fileupload");i||r.data("fileupload",i=new t(this,n)),typeof n=="string"&&i[n]()})},e.fn.fileupload.Constructor=t,e(document).on("click.fileupload.data-api",'[data-provides="fileupload"]',function(t){var n=e(this);if(n.data("fileupload"))return;n.fileupload(n.data());var r=e(t.target).closest('[data-dismiss="fileupload"],[data-trigger="fileupload"]');r.length>0&&(r.trigger(
 "click.fileupload"),t.preventDefault())})}(window.jQuery);
\ No newline at end of file


[30/51] [abbrv] [partial] Adding Jinwon's custom RCMET

Posted by jo...@apache.org.
http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/app/font/.svn/text-base/fontawesome-webfont.ttf.svn-base
----------------------------------------------------------------------
diff --git a/src/main/ui/app/font/.svn/text-base/fontawesome-webfont.ttf.svn-base b/src/main/ui/app/font/.svn/text-base/fontawesome-webfont.ttf.svn-base
new file mode 100755
index 0000000..d461724
Binary files /dev/null and b/src/main/ui/app/font/.svn/text-base/fontawesome-webfont.ttf.svn-base differ

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/app/font/.svn/text-base/fontawesome-webfont.woff.svn-base
----------------------------------------------------------------------
diff --git a/src/main/ui/app/font/.svn/text-base/fontawesome-webfont.woff.svn-base b/src/main/ui/app/font/.svn/text-base/fontawesome-webfont.woff.svn-base
new file mode 100755
index 0000000..3c89ae0
Binary files /dev/null and b/src/main/ui/app/font/.svn/text-base/fontawesome-webfont.woff.svn-base differ

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/app/font/FontAwesome.otf
----------------------------------------------------------------------
diff --git a/src/main/ui/app/font/FontAwesome.otf b/src/main/ui/app/font/FontAwesome.otf
new file mode 100755
index 0000000..64049bf
Binary files /dev/null and b/src/main/ui/app/font/FontAwesome.otf differ

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/app/font/fontawesome-webfont.eot
----------------------------------------------------------------------
diff --git a/src/main/ui/app/font/fontawesome-webfont.eot b/src/main/ui/app/font/fontawesome-webfont.eot
new file mode 100755
index 0000000..7d81019
Binary files /dev/null and b/src/main/ui/app/font/fontawesome-webfont.eot differ


[48/51] [abbrv] [partial] Adding Jinwon's custom RCMET

Posted by jo...@apache.org.
http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/rcmes/cli/.svn/text-base/rcmet20_cordexAF.py.svn-base
----------------------------------------------------------------------
diff --git a/src/main/python/rcmes/cli/.svn/text-base/rcmet20_cordexAF.py.svn-base b/src/main/python/rcmes/cli/.svn/text-base/rcmet20_cordexAF.py.svn-base
new file mode 100755
index 0000000..76ea5e5
--- /dev/null
+++ b/src/main/python/rcmes/cli/.svn/text-base/rcmet20_cordexAF.py.svn-base
@@ -0,0 +1,980 @@
+#!/usr/local/bin/python
+
+# 0. Keep both Peter's original and modified libraries
+
+# Python Standard Lib Imports
+import argparse
+import ConfigParser
+import datetime
+import glob
+import os
+import sys
+import json
+
+# 3rd Party Modules
+import numpy as np
+import numpy.ma as ma
+
+# RCMES Imports
+# Appending rcmes via relative path
+#sys.path.append(os.path.abspath('../.'))
+import storage.files_v12
+import storage.rcmed as db
+import toolkit.do_data_prep
+import toolkit.do_metrics_20
+import toolkit.process as process
+from classes import Settings, Model, BoundingBox, SubRegion, GridBox
+
+parser = argparse.ArgumentParser(description='Regional Climate Model Evaluation Toolkit.  Use -h for help and options')
+parser.add_argument('-c', '--config', dest='CONFIG', help='Path to an evaluation configuration file')
+args = parser.parse_args()
+
+
+def getSettings(settings):
+    """
+    This function will collect 2 parameters from the user about the RCMET run they have started.
+    
+    Input::
+        settings - Empty Python Dictionary they will be used to store the user supplied inputs
+        
+    Output::
+        None - The user inputs will be added to the supplied dictionary.
+    """
+    settings['workDir'] = os.path.abspath(raw_input('Please enter workDir:\n> '))
+    if os.path.isdir(settings['workDir']):
+        pass
+    else:
+        makeDirectory(settings['workDir'])
+    
+    settings['cacheDir'] = os.path.abspath(raw_input('Please enter cacheDir:\n> '))
+    if os.path.isdir(settings['cacheDir']):
+        pass
+    else:
+        makeDirectory(settings['cacheDir'])    
+
+def setSettings(settings, config):
+    """
+    This function is used to set the values within the 'SETTINGS' dictionary when a user provides an external
+    configuration file.
+    
+    Input::
+        settings - Python Dictionary object that will collect the key : value pairs
+        config - A configparse object that contains the external config values
+    
+    Output::
+        None - The settings dictionary will be updated in place.
+    """
+    pass
+
+def makeDirectory(directory):
+    print "%s doesn't exist.  Trying to create it now." % directory
+    try:
+        os.mkdir(directory)
+    except OSError:
+        print "This program cannot create dir: %s due to permission issues." % directory
+        sys.exit()
+
+def rcmet_cordexAF():
+    """
+     Command Line User interface for RCMET.
+     Collects user options then runs RCMET to perform processing.
+     Duplicates job of GUI.
+     Peter Lean   March 2011
+     
+     Jul 2, 2011
+     Modified to process multiple models
+     Follow the logical variable "GUI" for interactive operations
+     
+     July 6, 2012: Jinwon Kim
+     * This version works with do_rcmes_processing_sub_v12cmip5multi.py *
+     Re-gridded data output options include both binary and netCDF.
+      Interpolation of both model and obs data onto a user-define grid system has been completed.
+      Allow generic treatment of both multiple model and observation data
+       * longitudes/latitudes are defined for individual datasets
+       * the metadata for observations will utilized Cameron's updates
+      Still works for the global observation coverage scheme (may involve missing/bad values)
+     * this version requires that all obs data are to be defined at the same temporal grid (monthly, daily)
+     * this version requires that all mdl data are to be defined at the same temporal grid (monthly, daily)
+    """
+    print 'Start RCMET'
+
+
+    """  COMMENTED OUT UN-USED CODE
+    # Specify GUI or nonGUI version [True/False]
+    GUI = False
+    user_input = int(raw_input('Enter interactive/specified run: [0/1]: \n> '))
+    if user_input == 0:
+        GUI = True
+
+    # 1.   Prescribe the directories and variable names for processing
+    #dir_rcmet = '/nas/share3-wf/jinwonki/rcmet'   # The path to the python script to process the cordex-AF data
+    if GUI: 
+        workdir = os.path.abspath(raw_input('Please enter workdir:\n> '))
+        cachedir = os.path.abspath(raw_input('Please enter cachedir:\n> '))
+        mdlDataDir = os.path.abspath(raw_input('Enter the model data directory (e.g., ~/data/cordex-af):\n> '))
+        modelVarName = raw_input('Enter the model variable name from above:\n> ')     # Input model variable name
+        modelLatVarName = raw_input('Enter the Latitude variable name:\n> ')     # Input model variable name
+        modelLonVarName = raw_input('Enter the Longitude variable name:\n> ')     # Input model variable name
+        modelTimeVarName = raw_input('Enter the Time variable name:\n> ')     # Input model variable name
+        mdlTimeStep = raw_input('Enter the model Time step (e.g., daily, monthly):\n> ')     # Input model variable name
+    else:
+        modelVarName = 'pr'
+        #modelVarName='tas'
+        #modelVarName='tasmax'
+        #modelVarName='tasmin'
+        #modelVarName='clt'
+        mdlTimeStep = 'monthly'
+        modelLatVarName = 'lat'
+        modelLonVarName = 'lon'
+        modelTimeVarName = 'time' # mdl var names for lat, long, & time coords
+        workdir = '../cases/cordex-af/wrk2'
+        cachedir = '../cases/cordex-af/cache'
+        mdlDataDir = '/nas/share4-cf/jinwonki/data/cordex-af'
+    if modelVarName == 'pr':
+        precipFlag = True
+    else:
+        precipFlag = False
+    """
+    # 2.   Metadata for the RCMED database
+    
+    # TODO:  WORK OUT THE RCMED PARAMETERS API USAGE - Prolly need to move this into a PARAMETERS Object
+    """  COMMENTED OUT HARDCODED VALUES
+    try:
+        parameters = db.getParams()
+    except Exception:
+        sys.exit()
+    
+    datasets = [parameter['longname'] for parameter in parameters]
+    
+    #   NOTE: the list must be updated whenever a new dataset is added to RCMED (current as of 11/22/2011)
+    db_datasets = ['TRMM', 'ERA-Interim', 'AIRS', 'MODIS', 'URD', 'CRU3.0', 'CRU3.1']
+    db_dataset_ids = [3, 1, 2, 5, 4, 6, 10]
+    db_dataset_startTimes = [datetime.datetime(1998, 1, 1, 0, 0, 0, 0), datetime.datetime(1989, 01, 01, 0, 0, 0, 0), datetime.datetime(2002, 8, 31, 0, 0, 0, 0), \
+                             datetime.datetime(2000, 2, 24, 0, 0, 0, 0), datetime.datetime(1948, 1, 1, 0, 0, 0, 0), datetime.datetime(1901, 1, 1, 0, 0, 0, 0), \
+                             datetime.datetime(1901, 1, 1, 0, 0, 0, 0)]
+    db_dataset_endTimes = [datetime.datetime(2010, 1, 1, 0, 0, 0, 0), datetime.datetime(2009, 12, 31, 0, 0, 0, 0), datetime.datetime(2010, 1, 1, 0, 0, 0, 0), \
+                           datetime.datetime(2010, 5, 30, 0, 0, 0, 0), datetime.datetime(2010, 1, 1, 0, 0, 0, 0), datetime.datetime(2006, 12, 1, 0, 0, 0, 0), \
+                           datetime.datetime(2009, 12, 31, 0, 0, 0, 0)] #adjusted the last end_time to 31-DEC-2009 instead of 01-DEC-2009
+    db_parameters = [['pr_day', 'pr_mon'], ['T2m', 'Tdew2m'], ['T2m'], ['cldFrac'], ['pr_day'], ['T2m', 'T2max', 'T2min', 'pr'], ['pr', 'T2m', 'T2max', 'T2min', 'cldFrac']]
+    db_parameter_ids = [[14, 36], [12, 13], [15], [31], [30], [33, 34, 35, 32], [37, 38, 39, 41, 42]]
+    
+     # Assign the obs dataset & and its attributes from the RCNMED dataset/parameter list above
+    idObsDat = []
+    idObsDatPara = []
+    obsTimeStep = []
+    
+    if GUI:
+        for n in np.arange(len(db_datasets)):
+            print n, db_datasets[n]
+
+        numOBSs = int(raw_input('Enter the number of observed datasets to be utilized:\n> '))
+        # assign the obs dataset id and the parameter id defined within the dataset into the lists "idObsDat" & "idObsDatPara".
+        for m in np.arange(numOBSs):
+            idObsDat.append(input=int(raw_input('Enter the observed dataset number from above:\n> ')))
+            for l in np.arange(len(db_parameters[input])):
+                print l, db_parameters[idObsDat][l]
+        
+            idObsDatPara.append(int(raw_input('Enter the observed data parameter from above:\n> ')))
+    else:
+        numOBSs = 2
+        idObsDat = [0, 6]
+        idObsDatPara = [1, 0]
+        obsTimeStep = ['monthly', 'monthly']
+        #numOBSs=1; idObsDat=[6]; idObsDatPara=[0]; obsTimeStep=['monthly']
+        #numOBSs=1; idObsDat=[5]; idObsDatPara=[3]; obsTimeStep=['monthly']
+        #numOBSs=1; idObsDat=[0]; idObsDatPara=[1]; obsTimeStep=['monthly']
+        ##### Data table to be replace with the use of metadata #################################
+        #idObsDat=0; idObsDatPara=0; obsTimeStep='monthly'                 # TRMM daily
+        #idObsDat=0; idObsDatPara=1; obsTimeStep='monthly'                 # TRMM monthly
+        #idObsDat=3; idObsDatPara=0; obsTimeStep='monthly'                 # MODIS cloud fraction
+        #idObsDat=5; idObsDatPara=0; obsTimeStep='monthly'                 # CRU3.0 - t2bar
+        #idObsDat=5; idObsDatPara=1; obsTimeStep='monthly'                 # CRU3.0 - t2max
+        #idObsDat=5; idObsDatPara=2; obsTimeStep='monthly'                 # CRU3.0 - t2min
+        #idObsDat=5; idObsDatPara=3; obsTimeStep='monthly'                 # CRU3.0 - pr
+        #idObsDat=6; idObsDatPara=0; obsTimeStep='monthly'                 # CRU3.1 - pr
+        #idObsDat=6; idObsDatPara=1; obsTimeStep='monthly'                 # CRU3.1 - t2bar
+        #idObsDat=6; idObsDatPara=2; obsTimeStep='monthly'                 # CRU3.1 - t2max
+        #idObsDat=6; idObsDatPara=3; obsTimeStep='monthly'                 # CRU3.1 - t2min
+        #idObsDat=6; idObsDatPara=4; obsTimeStep='monthly'                 # CRU3.1 - cloud fraction
+        ##### Data table to be replace with the use of metadata #################################
+    # assign observed data info: all variables are 'list'
+    obsDataset = []
+    data_type = []
+    obsDatasetId = []
+    obsParameterId = []
+    obsStartTime = []
+    obsEndTime = []
+    obsList = []
+
+    for m in np.arange(numOBSs):
+        obsDataset.append(db_datasets[idObsDat[m]])# obsDataset=db_datasets[idObsDat[m]]
+        data_type.append(db_parameters[idObsDat[m]][idObsDatPara[m]])# data_type = db_parameters[idObsDat[m]][idObsDatPara[m]]
+        obsDatasetId.append(db_dataset_ids[idObsDat[m]])# obsDatasetId = db_dataset_ids[idObsDat[m]]
+        obsParameterId.append(db_parameter_ids[idObsDat[m]][idObsDatPara[m]])# obsParameterId = db_parameter_ids[idObsDat[m]][idObsDatPara[m]]
+        obsStartTime.append(db_dataset_startTimes[idObsDat[m]])# obsStartTime = db_dataset_startTimes[idObsDat[m]]
+        obsEndTime.append(db_dataset_endTimes[idObsDat[m]])# obsEndTime = db_dataset_endTimes[idObsDat[m]]
+        obsList.append(db_datasets[idObsDat[m]] + '_' + db_parameters[idObsDat[m]][idObsDatPara[m]])
+                        TRMM_pr_mon
+                        CRU3.1_pr
+        
+    print'obsDatasetId,obsParameterId,obsList,obsStartTime,obsEndTime= ', obsDatasetId, obsParameterId, obsStartTime, obsEndTime# return -1
+    obsStartTmax = max(obsStartTime)
+    obsEndTmin = min(obsEndTime)
+    
+    ###################################################################
+    # 3.   Load model data and assign model-related processing info
+    ###################################################################
+    # 3a:  construct the list of model data files
+    if GUI:
+        FileList_instructions = raw_input('Enter model file (specify multiple files using wildcard: e.g., *pr.nc):\n> ')
+    else:
+        FileList_instructions = '*' + modelVarName + '.nc'
+        #FileList_instructions = '*' + 'ARPEGE51' + '*' + modelVarName + '.nc'
+    FileList_instructions = mdlDataDir + '/' + FileList_instructions
+    FileList = glob.glob(FileList_instructions)
+    n_infiles = len(FileList)
+    #print FileList_instructions,n_infiles,FileList
+
+    # 3b: (1) Attempt to auto-detect latitude and longitude variable names (removed in rcmes.files_v12.find_latlon_var_from_file)
+    #     (2) Find lat,lon limits from first file in FileList              (active)
+    file_type = 'nc'
+    laName = modelLatVarName
+    loName = modelLonVarName
+    latMin = ma.zeros(n_infiles)
+    latMax = ma.zeros(n_infiles)
+    lonMin = ma.zeros(n_infiles)
+    lonMax = ma.zeros(n_infiles)
+    
+    for n in np.arange(n_infiles):
+        ifile = FileList[n]
+        status, latMin[n], latMax[n], lonMin[n], lonMax[n] = storage.files_v12.find_latlon_var_from_file(ifile, file_type, laName, loName)
+        print 'Min/Max Lon & Lat: ', n, lonMin[n], lonMax[n], latMin[n], latMax[n]
+    if GUI:
+        instruction = raw_input('Do the long/lat ranges all model files match? (y/n)\n> ')
+
+    else:
+        instruction = 'y'
+    print instruction
+    if instruction != 'y':
+        print 'Long & lat ranges of model data files do not match: EXIT'; return -1
+    latMin = latMin[0]
+    latMax = latMax[0]
+    lonMin = lonMin[0]
+    lonMax = lonMax[0]
+    print 'Min/Max Lon & Lat:', lonMin, lonMax, latMin, latMax
+    print ''
+
+
+
+    # TODO:  Work out how to handle when model files have different ranges for Latitude, Longitude or Time
+
+    # 3c: Decode model times into a python datetime object (removed in rcmes.process_v12.decode_model_times; var name is hardwired in 1.)
+    #     Check the length of model data period. Retain only the files that contain the entire 20yr records
+    #     Also specify the model data time step. Not used for now, but will be used to control the selection of the obs data (4) & temporal regridding (7).
+    # Note July 25, 2011: model selection for analysis is moved and is combined with the determination of the evaluation period
+    timeName = modelTimeVarName
+    mdldataTimeStep = 'monthly'
+    file_type = 'nc'
+    n_mos = ma.zeros(n_infiles)
+    newFileList = []
+    mdlStartT = []
+    mdlEndT = []
+    mdlName = []
+    k = 0
+
+    for n in np.arange(n_infiles):
+        # extract model names for identification
+        # Provided that model results are named as 
+        # mdlDataDir/projectName_mdlName_(some other information)_variableName.nc
+        ifile = FileList[n]
+        name = ifile[len(mdlDataDir)+1:len(mdlDataDir)+20]  # +1 excludes '/'
+        name_wo_project = name[name.find('_')+1:]   # file name without its project name
+        
+        mdlName.append(name_wo_project[0:name_wo_project.find('_')]) # print'model name= ',name[0:name.find('_')]
+        # extract the temporal coverage of each model data file and the related time parameters
+        
+        modelTimes = process.getModelTimes(ifile, timeName)
+        
+        # NOW WE HAVE MODEL TIMES...WHAT ARE THEY USED FOR???
+        
+        # THIS APPEARS TO BE A MONTHLY SPECIFIC IMPLEMENTATAION DETAIL
+        n_mos[n] = len(modelTimes)
+        
+        # PARSE OUT THE Min(YEAR and MONTH) and Max(YEAR and MONTH)
+        # Could this merely be a MinTime and MaxTime so essentially a TimeRange?
+        
+        
+        y0 = min(modelTimes).strftime("%Y")
+        m0 = min(modelTimes).strftime("%m")
+        y1 = max(modelTimes).strftime("%Y")
+        m1 = max(modelTimes).strftime("%m")
+        
+        
+        
+        if mdlTimeStep == 'monthly':
+            d0 = 1
+            d1 = 1
+        else:
+            d0 = min(modelTimes).strftime("%d")
+            d1 = max(modelTimes).strftime("%d")
+            
+        minMdlT = datetime.datetime(int(y0), int(m0), int(d0), 0, 0, 0, 0)
+        maxMdlT = datetime.datetime(int(y1), int(m1), int(d1), 0, 0, 0, 0)
+        
+        # AFTER all the Datetime to string to int and back to datetime, we are left with the ModelTimeStart and ModelTimeEnd
+        mdlStartT.append(minMdlT)
+        mdlEndT.append(maxMdlT)
+
+    print 'Mdl Times decoded: n= ', n, ' Name: ', mdlName[n], ' length= ', len(modelTimes), \
+          ' 1st mdl time: ', mdlStartT[n].strftime("%Y/%m"), ' Lst mdl time: ', mdlEndT[n].strftime("%Y/%m")
+
+    #print 'mdlStartT'; print mdlStartT; print 'mdlEndT'; print mdlEndT
+    #print max(mdlStartT),min(mdlEndT)
+    
+    # get the list of models to be evaluated and the period of evaluation
+    # July 25, 2011: the selection of model and evaluation period are modified:
+    #   1. Default: If otherwise specified, select the longest overlapping period and exclude the model outputs that do not cover the default period
+    #   2. MaxMdl : Select the max number of models for evaluation. The evaluation period may be reduced
+    #   3. PrdSpc : The evaluation period is specified and the only data files that cover the specified period are included for evaluation.
+    #   4. Note that the analysis period is limited to the full annual cycle, i.e., starts in Jan and ends in Dec.
+    # 5:   Select the period for evaluation/analysis (defaults to overlapping times between model and obs)
+    # 5a: First calculate the overlapping period
+    startTime = []
+    endTime = []
+    
+    for n in np.arange(n_infiles):
+        startTime.append(max(mdlStartT[n], obsStartTmax))
+        endTime.append(min(mdlEndT[n], obsEndTmin))
+        
+        #print n,mdlStartT[n],mdlEndT[n],startTime[n],endTime[n]
+        yy = int(startTime[n].strftime("%Y"))
+        mm = int(startTime[n].strftime("%m"))
+        
+        if mm != 1:
+            yy = yy + 1
+            mm = 1
+
+        startTime[n] = datetime.datetime(int(yy), int(mm), 1, 0, 0, 0, 0)
+        yy = int(endTime[n].strftime("%Y"))
+        mm = int(endTime[n].strftime("%m"))
+        
+        if mm != 12:
+            yy = yy - 1
+            mm = 12
+        
+        endTime[n] = datetime.datetime(int(yy), int(mm), 1, 0, 0, 0, 0)
+        print mdlName[n], ' common start/end time: ', startTime[n], endTime[n]
+
+    maxAnlT0 = min(startTime)
+    maxAnlT1 = max(endTime)
+    minAnlT0 = max(startTime)
+    minAnlT1 = min(endTime)
+    #print startTime; print endTime
+    print 'max common period: ', maxAnlT0, '-', maxAnlT1; print 'min common period: ', minAnlT0, '-', minAnlT1
+    
+    # 5b: Determine the evaluation period and the models to be evaluated
+    if GUI:
+        print 'Select evaluation period. Depending on the selected period, the number of models may vary. See above common start/end times'
+        print 'Enter: 1 for max common period, 2 for min common period, 3 for your own choice: Note that all period starts from Jan and end at Dec'
+        choice = int(raw_input('Enter your choice from above [1,2,3] \n> '))
+    else:
+        choice = 3
+    if choice == 1:
+        startTime = maxAnlT0
+        endTime = maxAnlT1
+        print 'Maximum(model,obs) period is selected. Some models will be dropped from evaluation'
+        
+    if choice == 2:
+        startTime = minAnlT0
+        endTime = minAnlT1
+        print 'Minimum(model,obs) period is selected. All models will be evaluated except there are problems'
+      
+    if choice == 3:
+        startYear = int(raw_input('Enter start year YYYY \n'))
+        endYear = int(raw_input('Enter end year YYYY \n'))
+        
+        if startYear < int(maxAnlT0.strftime("%Y")):
+            print 'Your start year is earlier than the available data period: EXIT; return -1'
+            
+        if endYear > int(maxAnlT1.strftime("%Y")):
+            print 'Your end year is later than the available data period: EXIT; return -1'
+            
+        # CGOODALE - Updating the Static endTime to be 31-DEC
+        startTime = datetime.datetime(startYear, 1, 1, 0, 0)
+        endTime = datetime.datetime(endYear, 12, 31, 0, 0)
+        print 'Evaluation will be performed for a user-selected period'
+        
+    print 'Final: startTime/endTime: ', startTime, '/', endTime
+
+
+    # select model data for analysis and analysis period
+    k = 0
+    newFileList = []
+    name = []
+    print 'n_infiles= ', n_infiles
+    for n in np.arange(n_infiles): 
+        ifile = FileList[n]
+        nMos = n_mos[n]
+        print mdlName[n], n_mos[n], mdlStartT[n], startTime, mdlEndT[n], endTime
+        
+        # LOOP OVER THE MODEL START TIMES AND DETERMINE WHICH TO KEEP based on user entered Start/End Years
+        
+        if mdlStartT[n] <= startTime and mdlEndT[n] >= endTime:
+            newFileList.append(ifile)
+            name.append(mdlName[n])
+            k += 1
+    FileList = newFileList
+    newFileList = 0
+    FileList.sort()
+    print 'the number of select files = ', len(FileList)
+    mdlName = name
+    numMDLs = len(FileList)
+    
+    for n in np.arange(numMDLs):
+        print n, mdlName[n], FileList[n]
+    
+    # 6:   Select spatial regridding options
+    # PULLED DOWN INTO THE MAIN Loop
+    regridOption = 2      # for multi-model cases, this option can be selected only when all model data are on the same grid system.
+    naLons = 1
+    naLats = 1
+    dLon = 0.5
+    dLat = 0.5  # these are dummies for regridOption = 1 & 2
+    
+    if GUI:
+        print 'Spatial regridding options: '
+        print '[0] Use Observational grid'
+        print '[1] Use Model grid'
+        print '[2] Define new regular lat/lon grid to use'
+        regridOption = int(raw_input('Please make a selection from above:\n> '))
+        
+    if np.logical_or(regridOption > 2, regridOption < 0):
+        print 'Error: Non-existing spatial regridding option. EXIT'; return -1, -1, -1, -1
+    # specify the regridding option
+    if regridOption == 0: 
+        regridOption = 'obs'
+    if regridOption == 1:
+        regridOption = 'model'
+    # If requested, get new grid parameters: min/max long & lat values and their uniform increments; the # of longs and lats
+    
+    if regridOption == 2:
+        regridOption = 'regular'
+        dLon = 0.44
+        dLat = 0.44
+        lonMin = -24.64
+        lonMax = 60.28
+        latMin = -45.76
+        latMax = 42.24
+        naLons = int((lonMax - lonMin + 1.e-5 * dLon) / dLon) + 1
+        naLats = int((latMax - latMin + 1.e-5 * dLat) / dLat) + 1
+
+    if GUI:
+        if regridOption == 2:
+            regridOption = 'regular'
+            lonMin = float(raw_input('Please enter the longitude at the left edge of the domain:\n> '))
+            lonMax = float(raw_input('Please enter the longitude at the right edge of the domain:\n> '))
+            latMin = float(raw_input('Please enter the latitude at the lower edge of the domain:\n> '))
+            latMax = float(raw_input('Please enter the latitude at the upper edge of the domain:\n> '))
+            dLon = float(raw_input('Please enter the longitude spacing (in degrees) e.g. 0.5:\n> '))
+            dLat = float(raw_input('Please enter the latitude spacing (in degrees) e.g. 0.5:\n> '))
+            nLons = int((lonMax - lonMin + 1.e-5 * dLon) / dLon) + 1
+            nLats = int((latMax - latMin + 1.e-5 * dLat) / dLat) + 1
+            
+    print 'Spatial re-grid data on the ', regridOption, ' grid'
+
+
+    # 7:   Temporal regridding: Bring the model and obs data to the same temporal grid for comparison
+    #      (e.g., daily vs. daily; monthly vs. monthly)
+    timeRegridOption = 2
+    if GUI == True:
+        print 'Temporal regridding options: i.e. averaging from daily data -> monthly data'
+        print 'The time averaging will be performed on both model and observational data.'
+        print '[0] Calculate time mean for full period.'
+        print '[1] Calculate annual means'
+        print '[2] Calculate monthly means'
+        print '[3] Calculate daily means (from sub-daily data)'
+        timeRegridOption = int(raw_input('Please make a selection from above:\n> '))
+    # non-existing option is selected
+    if np.logical_or(timeRegridOption > 3, timeRegridOption < 0):
+        print 'Error: ', timeRegridOption, ' is a non-existing temporal regridding option. EXIT'; return -1, -1, -1, -1
+    # specify the temporal regridding option
+    if timeRegridOption == 0: 
+        timeRegridOption = 'mean over all times: i.e., annual-mean climatology'
+        
+    if timeRegridOption == 1: 
+        timeRegridOption = 'annual'
+        
+    if timeRegridOption == 2: 
+        timeRegridOption = 'monthly'
+        
+    if timeRegridOption == 3: 
+        timeRegridOption = 'daily'
+        
+    print 'timeRegridOption= ', timeRegridOption
+    
+
+    #******************************************************************************************************************
+    # 8:   Select whether to perform Area-Averaging over masked region
+    #      If choice != 'y', the analysis/evaluation will be performed at every grid points within the analysis domain
+    #******************************************************************************************************************
+    numSubRgn = 21
+    subRgnLon0 = ma.zeros(numSubRgn)
+    subRgnLon1 = ma.zeros(numSubRgn)
+    subRgnLat0 = ma.zeros(numSubRgn)
+    subRgnLat1 = ma.zeros(numSubRgn)
+    # 21 rgns: SMHI11 + W+C+E. Mediterrenean (JK) + 3 in UCT (Western Sahara, Somalia, Madagascar) + 4 in Mideast
+    subRgnLon0 = [-10.0, 0.0, 10.0, 20.0, -19.3, 15.0, -10.0, -10.0, 33.9, 44.2, 10.0, 10.0, 30.0, 13.6, 13.6, 20.0, 43.2, 33.0, 45.0, 43.0, 50.0]   # HYB 21 rgns
+    subRgnLon1 = [  0.0, 10.0, 20.0, 33.0, -10.2, 30.0, 10.0, 10.0, 40.0, 51.8, 25.0, 25.0, 40.0, 20.0, 20.0, 35.7, 50.3, 40.0, 50.0, 50.0, 58.0]   # HYB 21 rgns
+    subRgnLat0 = [ 29.0, 29.0, 25.0, 25.0, 12.0, 15.0, 7.3, 5.0, 6.9, 2.2, 0.0, -10.0, -15.0, -27.9, -35.0, -35.0, -25.8, 25.0, 28.0, 13.0, 20.0]   # HYB 21 rgns
+    subRgnLat1 = [ 36.5, 37.5, 32.5, 32.5, 20.0, 25.0, 15.0, 7.3, 15.0, 11.8, 10.0, 0.0, 0.0, -21.4, -27.9, -21.4, -11.7, 35.0, 35.0, 20.0, 27.5]   # HYB 21 rgns
+    subRgnName = ['R01', 'R02', 'R03', 'R04', 'R05', 'R06', 'R07', 'R08', 'R09', 'R10', 'R11', 'R12', 'R13', 'R14', 'R15', 'R16', 'R17', 'R18', 'R19', 'R20', 'R21']   # HYB 21 rgns
+    print subRgnName
+
+    maskOption = 0
+    maskLonMin = 0
+    maskLonMax = 0
+    maskLatMin = 0
+    maskLatMax = 0
+    rgnSelect = 0
+    
+    choice = 'y'
+
+    if GUI:
+        choice = raw_input('Do you want to calculate area averages over a masked region of interest? [y/n]\n> ').lower()
+        if choice == 'y':
+            maskOption = 1
+            #print '[0] Load spatial mask from file.'
+            #print '[1] Enter regular lat/lon box to use as mask.'
+            #print '[2] Use pre-determined mask ranges'
+            #try:
+            #  maskInputChoice = int(raw_input('Please make a selection from above:\n> '))
+            #if maskInputChoice==0:    # Read mask from file
+            #  maskFile = raw_input('Please enter the file containing the mask data (including full path):\n> ') 
+            #  maskFileVar = raw_input('Please enter variable name of the mask data in the file:\n> ')
+            #if maskInputChoice==1:
+            #  maskLonMin = float(raw_input('Please enter the longitude at the left edge of the mask region:\n> '))
+            #  maskLonMax = float(raw_input('Please enter the longitude at the right edge of the mask region:\n> '))
+            #  maskLatMin = float(raw_input('Please enter the latitude at the lower edge of the mask region:\n> '))
+            #  maskLatMax = float(raw_input('Please enter the latitude at the upper edge of the mask region:\n> '))
+    ## maskInputChoice = 0/1: Load spatial mask from file/specifify with long,lat range'
+
+    
+    if choice == 'y':
+        maskOption = 1
+        maskInputChoice = 1
+        if maskInputChoice == 1:
+            for n in np.arange(numSubRgn):
+                print 'Subregion [', n, '] ', subRgnName[n], subRgnLon0[n], 'E - ', subRgnLon1[n], ' E: ', subRgnLat0[n], 'N - ', subRgnLat1[n], 'N'
+            rgnSelect = 3
+            if GUI:
+                rgnSelect = raw_input('Select the region for which regional-mean timeseries are to be analyzed\n')
+
+        #if maskInputChoice==0:    # Read mask from file
+        #   maskFile = 'maskFileNameTBD'
+        #   maskFileVar = 'maskFileVarTBD'
+    
+    # 9.   Select properties to evaluate/analyze
+    # old Section 8: Select: calculate seasonal cycle composites
+    
+    seasonalCycleOption = 'y'
+    if GUI:
+        seasonalCycleOption = raw_input('Composite the data to show seasonal cycles? [y/n]\n> ').lower()
+    if seasonalCycleOption == 'y':
+        seasonalCycleOption = 1
+    else:
+        seasonalCycleOption = 0
+
+      
+    # Section 9: Select Peformance Metric
+    choice = 0
+    if GUI:
+        print 'Metric options'
+        print '[0] Bias: mean bias across full time range'
+        print '[1] Mean Absolute Error: across full time range'
+        print '[2] Difference: calculated at each time unit'
+        print '[3] Anomaly Correlation> '
+        print '[4] Pattern Correlation> '
+        print '[5] TODO: Probability Distribution Function similarity score'
+        print '[6] RMS error'
+        choice = int(raw_input('Please make a selection from the options above\n> '))
+    # assign the metrics to be calculated
+    if choice == 0: 
+        metricOption = 'bias'
+        
+    if choice == 1: 
+        metricOption = 'mae'
+        
+    if choice == 2:
+        metricOption = 'difference'
+    
+    if choice == 3:
+        metricOption = 'acc'
+    
+    if choice == 4:
+        metricOption = 'patcor'
+    
+    if choice == 5:
+        metricOption = 'pdf'
+    
+    if choice == 6:
+        metricOption = 'rms'
+
+
+    #  Select output option
+    FoutOption = 0
+    if GUI:
+        choice = raw_input('Option for output files of obs/model data: Enter no/bn/nc\n> ').lower()
+        if choice == 'no':
+            FoutOption = 0
+        if choice == 'bn':
+            FoutOption = 1
+        if choice == 'nc':
+            FoutOption = 2
+
+    ###################################################################################################
+    # Section 11: Select Plot Options
+    ###################################################################################################
+
+
+    modifyPlotOptions = 'no'
+    plotTitle = modelVarName + '_'
+    plotFilenameStub = modelVarName + '_'
+    
+    if GUI:
+        modifyPlotOptions = raw_input('Do you want to modify the default plot options? [y/n]\n> ').lower()
+        
+    if modifyPlotOptions == 'y':
+        plotTitle = raw_input('Enter the plot title:\n> ')
+        plotFilenameStub = raw_input('Enter the filename stub to use, without suffix e.g. files will be named <YOUR CHOICE>.png\n> ')
+
+
+
+    print'------------------------------'
+    print'End of preprocessor: Run RCMET'
+    print'------------------------------'
+
+    """
+
+
+    # Section 13: Run RCMET, passing in all of the user options
+
+    # TODO: **Cameron** Add an option to write a file that includes all options selected before this step to help repeating the same analysis.
+    # read-in and regrid both obs and model data onto a common grid system (temporally & spatially).
+    # the data are passed to compute metrics and plotting
+    # numOBSs & numMDLs will be increased by +1 for multiple obs & mdls, respectively, to accomodate obs and model ensembles
+    # nT: the number of time steps in the data
+    
+    
+#    numOBS, numMDL, nT, ngrdY, ngrdX, Times, obsData, mdlData, obsRgn, mdlRgn, obsList, mdlList = toolkit.do_data_prep.prep_data(\
+#         cachedir, workdir, \
+#         obsList, obsDatasetId, obsParameterId, \
+#         startTime, endTime, \
+#         latMin, latMax, lonMin, lonMax, dLat, dLon, naLats, naLons, \
+#         FileList, \
+#         numSubRgn, subRgnLon0, subRgnLon1, subRgnLat0, subRgnLat1, subRgnName, \
+#         modelVarName, precipFlag, modelTimeVarName, modelLatVarName, modelLonVarName, \
+#         regridOption, timeRegridOption, maskOption, FoutOption)
+
+    """
+    Parameter to Object Mapping
+    cachedir = settings.cacheDir
+    workdir = settings.cacheDir
+    obsList = obsDatasetList.each['longname']
+    """
+
+    numOBS, numMDL, nT, ngrdY, ngrdX, Times, obsData, mdlData, obsRgn, mdlRgn, obsList, mdlList = toolkit.do_data_prep(\
+          settings, obsDatasetList, gridBox, models, subRegionTuple)
+    
+    """
+    print 'Input and regridding of both obs and model data are completed. now move to metrics calculations'
+    # Input and regridding of both obs and model data are completed. now move to metrics calculations
+
+    print '-----------------------------------------------'
+    print 'mdlID  numMOs  mdlStartTime mdlEndTime fileName'
+    print '-----------------------------------------------'
+    
+    """
+    mdlSelect = numMDL - 1                      # numMDL-1 corresponds to the model ensemble
+
+    """
+    if GUI:
+        n = 0
+        while n < len(mdlList):
+            print n, n_mos[n], mdlStartT[n], mdlEndT[n], FileList[n][35:]
+            n += 1
+        ask = 'Enter the model ID to be evaluated from above:  ', len(FileList), ' for the model-ensemble: \n'
+        mdlSelect = int(raw_input(ask))
+
+    print '----------------------------------------------------------------------------------------------------------'
+
+    
+    if maskOption == 1:
+        seasonalCycleOption = 1
+    
+    # TODO:  This seems like we can just use numOBS to compute obsSelect (obsSelect = numbOBS -1)
+    if numOBS == 1:
+        obsSelect = 1
+    else:
+        #obsSelect = 1          #  1st obs (TRMM)
+        #obsSelect = 2          # 2nd obs (CRU3.1)
+        obsSelect = numOBS      # obs ensemble
+
+    obsSelect = obsSelect - 1   # convert to fit the indexing that starts from 0
+
+    toolkit.do_metrics_20.metrics_plots(numOBS, numMDL, nT, ngrdY, ngrdX, Times, obsData, mdlData, obsRgn, mdlRgn, obsList, mdlList, \
+                              workdir, \
+                              mdlSelect, obsSelect, \
+                              numSubRgn, subRgnName, rgnSelect, \
+                              obsParameterId, precipFlag, timeRegridOption, maskOption, seasonalCycleOption, metricOption, \
+                                                                                           plotTitle, plotFilenameStub)
+    """
+
+def generateModels(modelConfig):
+    """
+    This function will return a list of Model objects that can easily be used for 
+    metric computation and other processing tasks.
+    
+    Input::  
+        modelConfig - list of ('key', 'value') tuples.  Below is a list of valid keys
+            filenamepattern - string i.e. '/nas/run/model/output/MOD*precip*.nc'
+            latvariable - string i.e. 'latitude'
+            lonvariable - string i.e. 'longitude'
+            timevariable - string i.e. 't'
+            timestep - string 'monthly' | 'daily' | 'annual'
+            varname - string i.e. 'pr'
+
+    Output::
+        modelList - List of Model objects
+    """
+    # Setup the config Data Dictionary to make parsing easier later
+    configData = {}
+    for entry in modelConfig:
+        configData[entry[0]] = entry[1]
+
+    modelFileList = None
+    for keyValTuple in modelConfig:
+        if keyValTuple[0] == 'filenamePattern':
+            modelFileList = glob.glob(keyValTuple[1])
+    
+    # Remove the filenamePattern from the dict since it is no longer used
+    configData.pop('filenamePattern')
+    
+    models = []
+    for modelFile in modelFileList:
+        configData['filename'] = modelFile
+        model = Model(**configData)
+        models.append(model)
+    
+    return models
+
+def generateSettings(settingsConfig):
+    """
+    Helper function to decouple the argument parsing from the Settings object creation
+    
+    Input::  
+        settingsConfig - list of ('key', 'value') tuples.
+            workdir - string i.e. '/nas/run/rcmet/work/'
+            cachedir - string i.e. '/tmp/rcmet/cache/'
+    Output::
+        settings - Settings Object
+    """
+    # Setup the config Data Dictionary to make parsing easier later
+    configData = {}
+    for entry in settingsConfig:
+        configData[entry[0]] = entry[1]
+        
+    return Settings(**configData)
+
+def generateDatasets(rcmedConfig):
+    """
+    Helper function to decouple the argument parsing from the RCMEDDataset object creation
+
+    Input::  
+        rcmedConfig - list of ('key', 'value') tuples.
+            obsDatasetId=3,10
+            obsParamId=36,32
+            obsTimeStep=monthly,monthly
+
+    Output::
+        datasets - list of RCMEDDataset Objects
+    # Setup the config Data Dictionary to make parsing easier later
+    """
+    delimiter = ','
+    configData = {}
+    for entry in rcmedConfig:
+        if delimiter in entry[1]:
+            # print 'delim found - %s' % entry[1]
+            valueList = entry[1].split(delimiter)
+            configData[entry[0]] = valueList
+        else:
+            configData[entry[0]] = entry[1]
+
+    return configData
+
+def tempGetYears():
+    startYear = int(raw_input('Enter start year YYYY \n'))
+    endYear = int(raw_input('Enter end year YYYY \n'))
+    # CGOODALE - Updating the Static endTime to be 31-DEC
+    startTime = datetime.datetime(startYear, 1, 1, 0, 0)
+    endTime = datetime.datetime(endYear, 12, 31, 0, 0)
+    return (startTime, endTime)
+
+if __name__ == "__main__":
+    
+    if args.CONFIG:
+        print 'Running using config file: %s' % args.CONFIG
+        # Parse the Config file
+        userConfig = ConfigParser.SafeConfigParser()
+        userConfig.optionxform = str # This is so the case is preserved on the items in the config file
+        userConfig.read(args.CONFIG)
+        settings = generateSettings(userConfig.items('SETTINGS'))
+        models = generateModels(userConfig.items('MODEL'))
+        datasets = generateDatasets(userConfig.items('RCMED'))
+        
+        # Go get the parameter listing from the database
+        try:
+            params = db.getParams()
+        except Exception:
+            sys.exit()
+        
+        obsDatasetList = []
+        for param_id in datasets['obsParamId']:
+            for param in params:
+                if param['parameter_id'] == int(param_id):
+                    obsDatasetList.append(param)
+                else:
+                    pass
+
+        # TODO:  Find a home for the regrid parameters in the CONFIG file
+        # Setup the Regridding Options
+        regridOption = 'regular'
+        # dLon = 0.44 - Provided in the SETTINGS config section
+        # dLat = 0.44
+        lonMin = -24.64
+        lonMax = 60.28
+        latMin = -45.76
+        latMax = 42.24
+        # Create a Grid Box Object that extends the bounding box Object
+        gridBox = GridBox(latMin, lonMin, latMax, lonMax, settings.gridLonStep, settings.gridLatStep)
+       
+        """ These can now be accessed from the gridBox object using gridBox.latCount and gridBox.lonCount attributes
+        naLons = int((gridBox.lonMax - gridBox.lonMin + 1.e-5 * settings.gridLonStep) / settings.gridLonStep) + 1
+        print naLons
+        print int((gridBox.lonMax - gridBox.lonMin) / gridBox.lonStep) + 1 
+        naLats = int((gridBox.latMax - gridBox.latMin + 1.e-5 * settings.gridLatStep) / settings.gridLatStep) + 1
+        """
+        timeRegridOption = settings.temporalGrid
+        
+        # TODO:  How do we support n subregions as Jinwon has below?
+        
+        numSubRgn = 21
+#        subRgnLon0 = ma.zeros(numSubRgn)
+#        subRgnLon1 = ma.zeros(numSubRgn)
+#        subRgnLat0 = ma.zeros(numSubRgn)
+#        subRgnLat1 = ma.zeros(numSubRgn)
+        # 21 rgns: SMHI11 + W+C+E. Mediterrenean (JK) + 3 in UCT (Western Sahara, Somalia, Madagascar) + 4 in Mideast
+        subRgnLon0 = [-10.0, 0.0, 10.0, 20.0, -19.3, 15.0, -10.0, -10.0, 33.9, 44.2, 10.0, 10.0, 30.0, 13.6, 13.6, 20.0, 43.2, 33.0, 45.0, 43.0, 50.0]   # HYB 21 rgns
+        subRgnLon1 = [  0.0, 10.0, 20.0, 33.0, -10.2, 30.0, 10.0, 10.0, 40.0, 51.8, 25.0, 25.0, 40.0, 20.0, 20.0, 35.7, 50.3, 40.0, 50.0, 50.0, 58.0]   # HYB 21 rgns
+        subRgnLat0 = [ 29.0, 29.0, 25.0, 25.0, 12.0, 15.0, 7.3, 5.0, 6.9, 2.2, 0.0, -10.0, -15.0, -27.9, -35.0, -35.0, -25.8, 25.0, 28.0, 13.0, 20.0]   # HYB 21 rgns
+        subRgnLat1 = [ 36.5, 37.5, 32.5, 32.5, 20.0, 25.0, 15.0, 7.3, 15.0, 11.8, 10.0, 0.0, 0.0, -21.4, -27.9, -21.4, -11.7, 35.0, 35.0, 20.0, 27.5]   # HYB 21 rgns
+        subRgnName = ['R01', 'R02', 'R03', 'R04', 'R05', 'R06', 'R07', 'R08', 'R09', 'R10', 'R11', 'R12', 'R13', 'R14', 'R15', 'R16', 'R17', 'R18', 'R19', 'R20', 'R21']   # HYB 21 rgns
+        print subRgnName
+        
+        subRegionTuple = (numSubRgn, subRgnLon0, subRgnLon1, subRgnLat0, subRgnLat1, subRgnName)
+        
+        
+        rgnSelect = 3
+        maskOption = settings.maskOption
+        
+        bbox = BoundingBox(subRgnLat0[rgnSelect], 
+                           subRgnLon0[rgnSelect], 
+                           subRgnLat1[rgnSelect], 
+                           subRgnLon1[rgnSelect])
+        
+        regionMask = SubRegion(subRgnName[rgnSelect], bbox)
+        
+        # Using a 'mask' instance of the BoundingBox object
+#        maskLonMin = 0
+#        maskLonMax = 0
+#        maskLatMin = 0
+#        maskLatMax = 0
+        
+        choice = 'y'
+        
+        #  THIS JUST MEANS A USER DEFINED MASK IS BEING USED (basically from the hardcoded values listed above (line 819 ish)
+        maskInputChoice = 1
+
+        if maskInputChoice == 1:
+            for n in np.arange(numSubRgn):
+                print 'Subregion [', n, '] ', subRgnName[n], subRgnLon0[n], 'E - ', subRgnLon1[n], ' E: ', subRgnLat0[n], 'N - ', subRgnLat1[n], 'N'
+            rgnSelect = 3
+        
+        # Section 9: Select Peformance Metric
+        metricOption = 'bias'
+        FoutOption = 0
+        
+        # Section 11: Select Plot Options
+        # TODO: Using first model in models since Var name is the same across all
+        modifyPlotOptions = 'no'
+        plotTitle = models[0].varName + '_'
+        plotFilenameStub = models[0].varName + '_'
+        
+        print'------------------------------'
+        print'End of preprocessor: Run RCMET'
+        print'------------------------------'
+        
+        numOBS, numMDL, nT, ngrdY, ngrdX, Times, obsData, mdlData, obsRgn, mdlRgn, obsList, mdlList = toolkit.do_data_prep.prep_data(settings, obsDatasetList, gridBox, models, subRegionTuple)
+        
+        
+        print 'Input and regridding of both obs and model data are completed. now move to metrics calculations'
+        
+        """FROM THE UPPER SECTION OF CODE"""
+
+        mdlSelect = numMDL - 1                      # numMDL-1 corresponds to the model ensemble
+    
+        """ Disregard GUI block for now
+        if GUI:
+            n = 0
+            while n < len(mdlList):
+                print n, n_mos[n], mdlStartT[n], mdlEndT[n], FileList[n][35:]
+                n += 1
+            ask = 'Enter the model ID to be evaluated from above:  ', len(FileList), ' for the model-ensemble: \n'
+            mdlSelect = int(raw_input(ask))
+    
+        print '----------------------------------------------------------------------------------------------------------'
+        """
+        
+        if maskOption:
+            seasonalCycleOption = True
+        
+        # TODO:  This seems like we can just use numOBS to compute obsSelect (obsSelect = numbOBS -1)
+        if numOBS == 1:
+            obsSelect = 1
+        else:
+            #obsSelect = 1          #  1st obs (TRMM)
+            #obsSelect = 2          # 2nd obs (CRU3.1)
+            obsSelect = numOBS      # obs ensemble
+    
+        obsSelect = obsSelect - 1   # convert to fit the indexing that starts from 0
+    
+    
+    
+        # TODO:  Undo the following code when refactoring later
+        obsParameterId = [str(x['parameter_id']) for x in obsDatasetList]
+        precipFlag = models[0].precipFlag
+    
+        toolkit.do_metrics_20.metrics_plots(numOBS, numMDL, nT, ngrdY, ngrdX, Times, obsData, mdlData, obsRgn, mdlRgn, obsList, mdlList, \
+                                  settings.workDir, \
+                                  mdlSelect, obsSelect, \
+                                  numSubRgn, subRgnName, rgnSelect, \
+                                  obsParameterId, precipFlag, timeRegridOption, maskOption, seasonalCycleOption, metricOption, \
+                                                                                               plotTitle, plotFilenameStub)
+        
+
+        
+    else:
+        print 'Interactive mode has been enabled'
+        #getSettings(SETTINGS)
+        print "But isn't implemented.  Try using the -c option instead"
+
+    #rcmet_cordexAF()

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/rcmes/cli/.svn/text-base/rcmet_ui.py.svn-base
----------------------------------------------------------------------
diff --git a/src/main/python/rcmes/cli/.svn/text-base/rcmet_ui.py.svn-base b/src/main/python/rcmes/cli/.svn/text-base/rcmet_ui.py.svn-base
new file mode 100755
index 0000000..ddc11f6
--- /dev/null
+++ b/src/main/python/rcmes/cli/.svn/text-base/rcmet_ui.py.svn-base
@@ -0,0 +1,91 @@
+#!/usr/local/bin/python
+""" 
+    Step by Step Wizard that demonstrates how the underlying RCMES code can
+    be used to generate climate dataset intercomparisons
+"""
+# Imports
+# Native Python Module Imports
+import sys
+
+# RCMES Imports
+from classes import Model, JobProperties, GridBox
+import storage.rcmed as rcmed
+import toolkit.metrics
+import toolkit.do_data_prep
+from utils import misc
+
+def rcmetUI():
+    """"
+    Command Line User interface for RCMET.
+    Collects user OPTIONS then runs RCMET to perform processing.
+    
+    Duplicates job of GUI.
+    """
+    print 'Regional Climate Model Evaluation System BETA'
+    print "Querying RCMED for available parameters..."
+
+    try:
+        parameters = rcmed.getParams()
+    except Exception:
+        raise
+        sys.exit()
+
+    # Section 0: Collect directories to store RCMET working files.
+    workDir, cacheDir = misc.getDirSettings()
+    temporalGrid = misc.getTemporalGrid()
+    spatialGrid = misc.getSpatialGrid()
+    jobProperties = JobProperties(workDir, cacheDir, spatialGrid, temporalGrid)
+    
+    # Section 1a: Enter model file/s
+    modelFiles = misc.getModelFiles()
+    # Create a list of model objects for use later
+    models = [Model(modelFile) for modelFile in modelFiles]
+
+    # Section 3b: Select 1 Parameter from list
+    for parameter in parameters:
+        """( 38 ) - CRU3.1 Daily-Mean Temperature : monthly"""
+        print "({:^2}) - {:<54} :: {:<10}".format(parameter['parameter_id'], parameter['longname'], parameter['timestep'])
+
+    obsDatasetList = []
+    validParamIds = [int(p['parameter_id']) for p in parameters]
+    while obsDatasetList == []:
+        print("Please select the available observation you would like to use from the list above:")
+        userChoice = int(raw_input(">>>"))
+        if userChoice in validParamIds:
+            for param in parameters:
+                if param['parameter_id'] == userChoice:
+                    obsDatasetList.append(param)
+                else:
+                    pass
+        else:
+            print("Your selection '%s' is invalid.  Please make another selection." % userChoice)
+    
+
+    # User must provide startTime and endTime if not defined
+    if jobProperties.startDate == None or jobProperties.endDate == None:
+        jobProperties.startDate, jobProperties.endDate = misc.userDefinedStartEndTimes(obsDatasetList, models)
+
+    try:
+        gridBox = GridBox(jobProperties.latMin, jobProperties.lonMin, jobProperties.latMax,
+                          jobProperties.lonMax, jobProperties.gridLonStep, jobProperties.gridLatStep)
+    except:
+        gridBox = None
+
+    numOBS, numMDL, nT, ngrdY, ngrdX, Times, lons, lats, obsData, mdlData, obsList, mdlName = toolkit.do_data_prep.prep_data(jobProperties, obsDatasetList, gridBox, models)
+  
+    counts = {'observations': numOBS,
+              'models'      : numMDL,
+              'times'       : nT}
+    subRegions = misc.getSubRegionsInteractively(counts, jobProperties.workDir)
+
+    # TODO: New function Call
+    fileOutputOption = jobProperties.writeOutFile
+    modelVarName = models[0].varName
+    toolkit.metrics.metrics_plots(modelVarName, numOBS, numMDL, nT, ngrdY, ngrdX, Times, lons, lats, obsData, mdlData, obsList, mdlName, workDir, subRegions, fileOutputOption)
+
+
+
+# Actually call the UI function.
+if __name__ == "__main__":
+    rcmetUI()
+

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/rcmes/cli/__init__.py
----------------------------------------------------------------------
diff --git a/src/main/python/rcmes/cli/__init__.py b/src/main/python/rcmes/cli/__init__.py
new file mode 100755
index 0000000..b2171fb
--- /dev/null
+++ b/src/main/python/rcmes/cli/__init__.py
@@ -0,0 +1,11 @@
+"""This is the Command Line Interface Package
+
+Here we have a collection of modules that can be used to interact with the RCMES
+from the command line.
+
+Example:
+------------
+
+>>> ./rcmet_ui.py
+
+"""
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/rcmes/cli/__init__.pyc
----------------------------------------------------------------------
diff --git a/src/main/python/rcmes/cli/__init__.pyc b/src/main/python/rcmes/cli/__init__.pyc
new file mode 100644
index 0000000..bb00913
Binary files /dev/null and b/src/main/python/rcmes/cli/__init__.pyc differ


[35/51] [abbrv] [partial] Adding Jinwon's custom RCMET

Posted by jo...@apache.org.
http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/app/css/.svn/text-base/bootstrap.min.css.svn-base
----------------------------------------------------------------------
diff --git a/src/main/ui/app/css/.svn/text-base/bootstrap.min.css.svn-base b/src/main/ui/app/css/.svn/text-base/bootstrap.min.css.svn-base
new file mode 100755
index 0000000..c10c7f4
--- /dev/null
+++ b/src/main/ui/app/css/.svn/text-base/bootstrap.min.css.svn-base
@@ -0,0 +1,9 @@
+/*!
+ * Bootstrap v2.3.1
+ *
+ * Copyright 2012 Twitter, Inc
+ * Licensed under the Apache License v2.0
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Designed and built with all the love in the world @twitter by @mdo and @fat.
+ */.clearfix{*zoom:1}.clearfix:before,.clearfix:after{display:table;line-height:0;content:""}.clearfix:after{clear:both}.hide-text{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.input-block-level{display:block;width:100%;min-height:30px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}article,aside,details,figcaption,figure,footer,header,hgroup,nav,section{display:block}audio,canvas,video{display:inline-block;*display:inline;*zoom:1}audio:not([controls]){display:none}html{font-size:100%;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%}a:focus{outline:thin dotted #333;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}a:hover,a:active{outline:0}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sup{top:-0.5em}sub{bottom:-0.25em}img{width:auto\9;height:auto;max-width:100%;vertical-align:middle;border:0;-ms-interpolation-mode:bicubic}#map_canvas img,.google-maps img{max-widt
 h:none}button,input,select,textarea{margin:0;font-size:100%;vertical-align:middle}button,input{*overflow:visible;line-height:normal}button::-moz-focus-inner,input::-moz-focus-inner{padding:0;border:0}button,html input[type="button"],input[type="reset"],input[type="submit"]{cursor:pointer;-webkit-appearance:button}label,select,button,input[type="button"],input[type="reset"],input[type="submit"],input[type="radio"],input[type="checkbox"]{cursor:pointer}input[type="search"]{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;-webkit-appearance:textfield}input[type="search"]::-webkit-search-decoration,input[type="search"]::-webkit-search-cancel-button{-webkit-appearance:none}textarea{overflow:auto;vertical-align:top}@media print{*{color:#000!important;text-shadow:none!important;background:transparent!important;box-shadow:none!important}a,a:visited{text-decoration:underline}a[href]:after{content:" (" attr(href) ")"}abbr[title]:after{content:" (" attr(title) 
 ")"}.ir a:after,a[href^="javascript:"]:after,a[href^="#"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100%!important}@page{margin:.5cm}p,h2,h3{orphans:3;widows:3}h2,h3{page-break-after:avoid}}body{margin:0;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;line-height:20px;color:#333;background-color:#fff}a{color:#08c;text-decoration:none}a:hover,a:focus{color:#005580;text-decoration:underline}.img-rounded{-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px}.img-polaroid{padding:4px;background-color:#fff;border:1px solid #ccc;border:1px solid rgba(0,0,0,0.2);-webkit-box-shadow:0 1px 3px rgba(0,0,0,0.1);-moz-box-shadow:0 1px 3px rgba(0,0,0,0.1);box-shadow:0 1px 3px rgba(0,0,0,0.1)}.img-circle{-webkit-border-radius:500px;-moz-border-radius:500px;border-radius:500px}.row{margin-left:-20px;*zoom:1}.row:before,.row:after{display:table;line-hei
 ght:0;content:""}.row:after{clear:both}[class*="span"]{float:left;min-height:1px;margin-left:20px}.container,.navbar-static-top .container,.navbar-fixed-top .container,.navbar-fixed-bottom .container{width:940px}.span12{width:940px}.span11{width:860px}.span10{width:780px}.span9{width:700px}.span8{width:620px}.span7{width:540px}.span6{width:460px}.span5{width:380px}.span4{width:300px}.span3{width:220px}.span2{width:140px}.span1{width:60px}.offset12{margin-left:980px}.offset11{margin-left:900px}.offset10{margin-left:820px}.offset9{margin-left:740px}.offset8{margin-left:660px}.offset7{margin-left:580px}.offset6{margin-left:500px}.offset5{margin-left:420px}.offset4{margin-left:340px}.offset3{margin-left:260px}.offset2{margin-left:180px}.offset1{margin-left:100px}.row-fluid{width:100%;*zoom:1}.row-fluid:before,.row-fluid:after{display:table;line-height:0;content:""}.row-fluid:after{clear:both}.row-fluid [class*="span"]{display:block;float:left;width:100%;min-height:30px;margin-left:2.127
 659574468085%;*margin-left:2.074468085106383%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.row-fluid [class*="span"]:first-child{margin-left:0}.row-fluid .controls-row [class*="span"]+[class*="span"]{margin-left:2.127659574468085%}.row-fluid .span12{width:100%;*width:99.94680851063829%}.row-fluid .span11{width:91.48936170212765%;*width:91.43617021276594%}.row-fluid .span10{width:82.97872340425532%;*width:82.92553191489361%}.row-fluid .span9{width:74.46808510638297%;*width:74.41489361702126%}.row-fluid .span8{width:65.95744680851064%;*width:65.90425531914893%}.row-fluid .span7{width:57.44680851063829%;*width:57.39361702127659%}.row-fluid .span6{width:48.93617021276595%;*width:48.88297872340425%}.row-fluid .span5{width:40.42553191489362%;*width:40.37234042553192%}.row-fluid .span4{width:31.914893617021278%;*width:31.861702127659576%}.row-fluid .span3{width:23.404255319148934%;*width:23.351063829787233%}.row-fluid .span2{width:14.893617021276595%;*wid
 th:14.840425531914894%}.row-fluid .span1{width:6.382978723404255%;*width:6.329787234042553%}.row-fluid .offset12{margin-left:104.25531914893617%;*margin-left:104.14893617021275%}.row-fluid .offset12:first-child{margin-left:102.12765957446808%;*margin-left:102.02127659574467%}.row-fluid .offset11{margin-left:95.74468085106382%;*margin-left:95.6382978723404%}.row-fluid .offset11:first-child{margin-left:93.61702127659574%;*margin-left:93.51063829787232%}.row-fluid .offset10{margin-left:87.23404255319149%;*margin-left:87.12765957446807%}.row-fluid .offset10:first-child{margin-left:85.1063829787234%;*margin-left:84.99999999999999%}.row-fluid .offset9{margin-left:78.72340425531914%;*margin-left:78.61702127659572%}.row-fluid .offset9:first-child{margin-left:76.59574468085106%;*margin-left:76.48936170212764%}.row-fluid .offset8{margin-left:70.2127659574468%;*margin-left:70.10638297872339%}.row-fluid .offset8:first-child{margin-left:68.08510638297872%;*margin-left:67.9787234042553%}.row-flui
 d .offset7{margin-left:61.70212765957446%;*margin-left:61.59574468085106%}.row-fluid .offset7:first-child{margin-left:59.574468085106375%;*margin-left:59.46808510638297%}.row-fluid .offset6{margin-left:53.191489361702125%;*margin-left:53.085106382978715%}.row-fluid .offset6:first-child{margin-left:51.063829787234035%;*margin-left:50.95744680851063%}.row-fluid .offset5{margin-left:44.68085106382979%;*margin-left:44.57446808510638%}.row-fluid .offset5:first-child{margin-left:42.5531914893617%;*margin-left:42.4468085106383%}.row-fluid .offset4{margin-left:36.170212765957444%;*margin-left:36.06382978723405%}.row-fluid .offset4:first-child{margin-left:34.04255319148936%;*margin-left:33.93617021276596%}.row-fluid .offset3{margin-left:27.659574468085104%;*margin-left:27.5531914893617%}.row-fluid .offset3:first-child{margin-left:25.53191489361702%;*margin-left:25.425531914893618%}.row-fluid .offset2{margin-left:19.148936170212764%;*margin-left:19.04255319148936%}.row-fluid .offset2:first-ch
 ild{margin-left:17.02127659574468%;*margin-left:16.914893617021278%}.row-fluid .offset1{margin-left:10.638297872340425%;*margin-left:10.53191489361702%}.row-fluid .offset1:first-child{margin-left:8.51063829787234%;*margin-left:8.404255319148938%}[class*="span"].hide,.row-fluid [class*="span"].hide{display:none}[class*="span"].pull-right,.row-fluid [class*="span"].pull-right{float:right}.container{margin-right:auto;margin-left:auto;*zoom:1}.container:before,.container:after{display:table;line-height:0;content:""}.container:after{clear:both}.container-fluid{padding-right:20px;padding-left:20px;*zoom:1}.container-fluid:before,.container-fluid:after{display:table;line-height:0;content:""}.container-fluid:after{clear:both}p{margin:0 0 10px}.lead{margin-bottom:20px;font-size:21px;font-weight:200;line-height:30px}small{font-size:85%}strong{font-weight:bold}em{font-style:italic}cite{font-style:normal}.muted{color:#999}a.muted:hover,a.muted:focus{color:#808080}.text-warning{color:#c09853}a.t
 ext-warning:hover,a.text-warning:focus{color:#a47e3c}.text-error{color:#b94a48}a.text-error:hover,a.text-error:focus{color:#953b39}.text-info{color:#3a87ad}a.text-info:hover,a.text-info:focus{color:#2d6987}.text-success{color:#468847}a.text-success:hover,a.text-success:focus{color:#356635}.text-left{text-align:left}.text-right{text-align:right}.text-center{text-align:center}h1,h2,h3,h4,h5,h6{margin:10px 0;font-family:inherit;font-weight:bold;line-height:20px;color:inherit;text-rendering:optimizelegibility}h1 small,h2 small,h3 small,h4 small,h5 small,h6 small{font-weight:normal;line-height:1;color:#999}h1,h2,h3{line-height:40px}h1{font-size:38.5px}h2{font-size:31.5px}h3{font-size:24.5px}h4{font-size:17.5px}h5{font-size:14px}h6{font-size:11.9px}h1 small{font-size:24.5px}h2 small{font-size:17.5px}h3 small{font-size:14px}h4 small{font-size:14px}.page-header{padding-bottom:9px;margin:20px 0 30px;border-bottom:1px solid #eee}ul,ol{padding:0;margin:0 0 10px 25px}ul ul,ul ol,ol ol,ol ul{mar
 gin-bottom:0}li{line-height:20px}ul.unstyled,ol.unstyled{margin-left:0;list-style:none}ul.inline,ol.inline{margin-left:0;list-style:none}ul.inline>li,ol.inline>li{display:inline-block;*display:inline;padding-right:5px;padding-left:5px;*zoom:1}dl{margin-bottom:20px}dt,dd{line-height:20px}dt{font-weight:bold}dd{margin-left:10px}.dl-horizontal{*zoom:1}.dl-horizontal:before,.dl-horizontal:after{display:table;line-height:0;content:""}.dl-horizontal:after{clear:both}.dl-horizontal dt{float:left;width:160px;overflow:hidden;clear:left;text-align:right;text-overflow:ellipsis;white-space:nowrap}.dl-horizontal dd{margin-left:180px}hr{margin:20px 0;border:0;border-top:1px solid #eee;border-bottom:1px solid #fff}abbr[title],abbr[data-original-title]{cursor:help;border-bottom:1px dotted #999}abbr.initialism{font-size:90%;text-transform:uppercase}blockquote{padding:0 0 0 15px;margin:0 0 20px;border-left:5px solid #eee}blockquote p{margin-bottom:0;font-size:17.5px;font-weight:300;line-height:1.25}b
 lockquote small{display:block;line-height:20px;color:#999}blockquote small:before{content:'\2014 \00A0'}blockquote.pull-right{float:right;padding-right:15px;padding-left:0;border-right:5px solid #eee;border-left:0}blockquote.pull-right p,blockquote.pull-right small{text-align:right}blockquote.pull-right small:before{content:''}blockquote.pull-right small:after{content:'\00A0 \2014'}q:before,q:after,blockquote:before,blockquote:after{content:""}address{display:block;margin-bottom:20px;font-style:normal;line-height:20px}code,pre{padding:0 3px 2px;font-family:Monaco,Menlo,Consolas,"Courier New",monospace;font-size:12px;color:#333;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}code{padding:2px 4px;color:#d14;white-space:nowrap;background-color:#f7f7f9;border:1px solid #e1e1e8}pre{display:block;padding:9.5px;margin:0 0 10px;font-size:13px;line-height:20px;word-break:break-all;word-wrap:break-word;white-space:pre;white-space:pre-wrap;background-color:#f5f5f5;border:1px
  solid #ccc;border:1px solid rgba(0,0,0,0.15);-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}pre.prettyprint{margin-bottom:20px}pre code{padding:0;color:inherit;white-space:pre;white-space:pre-wrap;background-color:transparent;border:0}.pre-scrollable{max-height:340px;overflow-y:scroll}form{margin:0 0 20px}fieldset{padding:0;margin:0;border:0}legend{display:block;width:100%;padding:0;margin-bottom:20px;font-size:21px;line-height:40px;color:#333;border:0;border-bottom:1px solid #e5e5e5}legend small{font-size:15px;color:#999}label,input,button,select,textarea{font-size:14px;font-weight:normal;line-height:20px}input,button,select,textarea{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif}label{display:block;margin-bottom:5px}select,textarea,input[type="text"],input[type="password"],input[type="datetime"],input[type="datetime-local"],input[type="date"],input[type="month"],input[type="time"],input[type="week"],input[type="number"],input[type="email"],input[type=
 "url"],input[type="search"],input[type="tel"],input[type="color"],.uneditable-input{display:inline-block;height:20px;padding:4px 6px;margin-bottom:10px;font-size:14px;line-height:20px;color:#555;vertical-align:middle;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}input,textarea,.uneditable-input{width:206px}textarea{height:auto}textarea,input[type="text"],input[type="password"],input[type="datetime"],input[type="datetime-local"],input[type="date"],input[type="month"],input[type="time"],input[type="week"],input[type="number"],input[type="email"],input[type="url"],input[type="search"],input[type="tel"],input[type="color"],.uneditable-input{background-color:#fff;border:1px solid #ccc;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-webkit-transition:border linear .2s,box-shadow linear .2s;-moz-transition:border linear .2s,box-shadow linear .2s;-o-transition:border lin
 ear .2s,box-shadow linear .2s;transition:border linear .2s,box-shadow linear .2s}textarea:focus,input[type="text"]:focus,input[type="password"]:focus,input[type="datetime"]:focus,input[type="datetime-local"]:focus,input[type="date"]:focus,input[type="month"]:focus,input[type="time"]:focus,input[type="week"]:focus,input[type="number"]:focus,input[type="email"]:focus,input[type="url"]:focus,input[type="search"]:focus,input[type="tel"]:focus,input[type="color"]:focus,.uneditable-input:focus{border-color:rgba(82,168,236,0.8);outline:0;outline:thin dotted \9;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 8px rgba(82,168,236,0.6);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 8px rgba(82,168,236,0.6);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 8px rgba(82,168,236,0.6)}input[type="radio"],input[type="checkbox"]{margin:4px 0 0;margin-top:1px \9;*margin-top:0;line-height:normal}input[type="file"],input[type="image"],input[type="submit"],input[type="reset"],input[type="b
 utton"],input[type="radio"],input[type="checkbox"]{width:auto}select,input[type="file"]{height:30px;*margin-top:4px;line-height:30px}select{width:220px;background-color:#fff;border:1px solid #ccc}select[multiple],select[size]{height:auto}select:focus,input[type="file"]:focus,input[type="radio"]:focus,input[type="checkbox"]:focus{outline:thin dotted #333;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.uneditable-input,.uneditable-textarea{color:#999;cursor:not-allowed;background-color:#fcfcfc;border-color:#ccc;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,0.025);-moz-box-shadow:inset 0 1px 2px rgba(0,0,0,0.025);box-shadow:inset 0 1px 2px rgba(0,0,0,0.025)}.uneditable-input{overflow:hidden;white-space:nowrap}.uneditable-textarea{width:auto;height:auto}input:-moz-placeholder,textarea:-moz-placeholder{color:#999}input:-ms-input-placeholder,textarea:-ms-input-placeholder{color:#999}input::-webkit-input-placeholder,textarea::-webkit-input-placeholder{color:#999}.radio,.chec
 kbox{min-height:20px;padding-left:20px}.radio input[type="radio"],.checkbox input[type="checkbox"]{float:left;margin-left:-20px}.controls>.radio:first-child,.controls>.checkbox:first-child{padding-top:5px}.radio.inline,.checkbox.inline{display:inline-block;padding-top:5px;margin-bottom:0;vertical-align:middle}.radio.inline+.radio.inline,.checkbox.inline+.checkbox.inline{margin-left:10px}.input-mini{width:60px}.input-small{width:90px}.input-medium{width:150px}.input-large{width:210px}.input-xlarge{width:270px}.input-xxlarge{width:530px}input[class*="span"],select[class*="span"],textarea[class*="span"],.uneditable-input[class*="span"],.row-fluid input[class*="span"],.row-fluid select[class*="span"],.row-fluid textarea[class*="span"],.row-fluid .uneditable-input[class*="span"]{float:none;margin-left:0}.input-append input[class*="span"],.input-append .uneditable-input[class*="span"],.input-prepend input[class*="span"],.input-prepend .uneditable-input[class*="span"],.row-fluid input[clas
 s*="span"],.row-fluid select[class*="span"],.row-fluid textarea[class*="span"],.row-fluid .uneditable-input[class*="span"],.row-fluid .input-prepend [class*="span"],.row-fluid .input-append [class*="span"]{display:inline-block}input,textarea,.uneditable-input{margin-left:0}.controls-row [class*="span"]+[class*="span"]{margin-left:20px}input.span12,textarea.span12,.uneditable-input.span12{width:926px}input.span11,textarea.span11,.uneditable-input.span11{width:846px}input.span10,textarea.span10,.uneditable-input.span10{width:766px}input.span9,textarea.span9,.uneditable-input.span9{width:686px}input.span8,textarea.span8,.uneditable-input.span8{width:606px}input.span7,textarea.span7,.uneditable-input.span7{width:526px}input.span6,textarea.span6,.uneditable-input.span6{width:446px}input.span5,textarea.span5,.uneditable-input.span5{width:366px}input.span4,textarea.span4,.uneditable-input.span4{width:286px}input.span3,textarea.span3,.uneditable-input.span3{width:206px}input.span2,textarea.
 span2,.uneditable-input.span2{width:126px}input.span1,textarea.span1,.uneditable-input.span1{width:46px}.controls-row{*zoom:1}.controls-row:before,.controls-row:after{display:table;line-height:0;content:""}.controls-row:after{clear:both}.controls-row [class*="span"],.row-fluid .controls-row [class*="span"]{float:left}.controls-row .checkbox[class*="span"],.controls-row .radio[class*="span"]{padding-top:5px}input[disabled],select[disabled],textarea[disabled],input[readonly],select[readonly],textarea[readonly]{cursor:not-allowed;background-color:#eee}input[type="radio"][disabled],input[type="checkbox"][disabled],input[type="radio"][readonly],input[type="checkbox"][readonly]{background-color:transparent}.control-group.warning .control-label,.control-group.warning .help-block,.control-group.warning .help-inline{color:#c09853}.control-group.warning .checkbox,.control-group.warning .radio,.control-group.warning input,.control-group.warning select,.control-group.warning textarea{color:#c09
 853}.control-group.warning input,.control-group.warning select,.control-group.warning textarea{border-color:#c09853;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.control-group.warning input:focus,.control-group.warning select:focus,.control-group.warning textarea:focus{border-color:#a47e3c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #dbc59e;-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #dbc59e;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #dbc59e}.control-group.warning .input-prepend .add-on,.control-group.warning .input-append .add-on{color:#c09853;background-color:#fcf8e3;border-color:#c09853}.control-group.error .control-label,.control-group.error .help-block,.control-group.error .help-inline{color:#b94a48}.control-group.error .checkbox,.control-group.error .radio,.control-group.error input,.control-group.error select,.control-group.error text
 area{color:#b94a48}.control-group.error input,.control-group.error select,.control-group.error textarea{border-color:#b94a48;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.control-group.error input:focus,.control-group.error select:focus,.control-group.error textarea:focus{border-color:#953b39;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #d59392;-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #d59392;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #d59392}.control-group.error .input-prepend .add-on,.control-group.error .input-append .add-on{color:#b94a48;background-color:#f2dede;border-color:#b94a48}.control-group.success .control-label,.control-group.success .help-block,.control-group.success .help-inline{color:#468847}.control-group.success .checkbox,.control-group.success .radio,.control-group.success input,.control-group.success select,.control-gro
 up.success textarea{color:#468847}.control-group.success input,.control-group.success select,.control-group.success textarea{border-color:#468847;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.control-group.success input:focus,.control-group.success select:focus,.control-group.success textarea:focus{border-color:#356635;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #7aba7b;-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #7aba7b;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #7aba7b}.control-group.success .input-prepend .add-on,.control-group.success .input-append .add-on{color:#468847;background-color:#dff0d8;border-color:#468847}.control-group.info .control-label,.control-group.info .help-block,.control-group.info .help-inline{color:#3a87ad}.control-group.info .checkbox,.control-group.info .radio,.control-group.info input,.control-group.info select,.c
 ontrol-group.info textarea{color:#3a87ad}.control-group.info input,.control-group.info select,.control-group.info textarea{border-color:#3a87ad;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.control-group.info input:focus,.control-group.info select:focus,.control-group.info textarea:focus{border-color:#2d6987;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #7ab5d3;-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #7ab5d3;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #7ab5d3}.control-group.info .input-prepend .add-on,.control-group.info .input-append .add-on{color:#3a87ad;background-color:#d9edf7;border-color:#3a87ad}input:focus:invalid,textarea:focus:invalid,select:focus:invalid{color:#b94a48;border-color:#ee5f5b}input:focus:invalid:focus,textarea:focus:invalid:focus,select:focus:invalid:focus{border-color:#e9322d;-webkit-box-shadow:0 0 6px #f8b9b7;-moz-b
 ox-shadow:0 0 6px #f8b9b7;box-shadow:0 0 6px #f8b9b7}.form-actions{padding:19px 20px 20px;margin-top:20px;margin-bottom:20px;background-color:#f5f5f5;border-top:1px solid #e5e5e5;*zoom:1}.form-actions:before,.form-actions:after{display:table;line-height:0;content:""}.form-actions:after{clear:both}.help-block,.help-inline{color:#595959}.help-block{display:block;margin-bottom:10px}.help-inline{display:inline-block;*display:inline;padding-left:5px;vertical-align:middle;*zoom:1}.input-append,.input-prepend{display:inline-block;margin-bottom:10px;font-size:0;white-space:nowrap;vertical-align:middle}.input-append input,.input-prepend input,.input-append select,.input-prepend select,.input-append .uneditable-input,.input-prepend .uneditable-input,.input-append .dropdown-menu,.input-prepend .dropdown-menu,.input-append .popover,.input-prepend .popover{font-size:14px}.input-append input,.input-prepend input,.input-append select,.input-prepend select,.input-append .uneditable-input,.input-pre
 pend .uneditable-input{position:relative;margin-bottom:0;*margin-left:0;vertical-align:top;-webkit-border-radius:0 4px 4px 0;-moz-border-radius:0 4px 4px 0;border-radius:0 4px 4px 0}.input-append input:focus,.input-prepend input:focus,.input-append select:focus,.input-prepend select:focus,.input-append .uneditable-input:focus,.input-prepend .uneditable-input:focus{z-index:2}.input-append .add-on,.input-prepend .add-on{display:inline-block;width:auto;height:20px;min-width:16px;padding:4px 5px;font-size:14px;font-weight:normal;line-height:20px;text-align:center;text-shadow:0 1px 0 #fff;background-color:#eee;border:1px solid #ccc}.input-append .add-on,.input-prepend .add-on,.input-append .btn,.input-prepend .btn,.input-append .btn-group>.dropdown-toggle,.input-prepend .btn-group>.dropdown-toggle{vertical-align:top;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.input-append .active,.input-prepend .active{background-color:#a9dba9;border-color:#46a546}.input-prepend .add-on
 ,.input-prepend .btn{margin-right:-1px}.input-prepend .add-on:first-child,.input-prepend .btn:first-child{-webkit-border-radius:4px 0 0 4px;-moz-border-radius:4px 0 0 4px;border-radius:4px 0 0 4px}.input-append input,.input-append select,.input-append .uneditable-input{-webkit-border-radius:4px 0 0 4px;-moz-border-radius:4px 0 0 4px;border-radius:4px 0 0 4px}.input-append input+.btn-group .btn:last-child,.input-append select+.btn-group .btn:last-child,.input-append .uneditable-input+.btn-group .btn:last-child{-webkit-border-radius:0 4px 4px 0;-moz-border-radius:0 4px 4px 0;border-radius:0 4px 4px 0}.input-append .add-on,.input-append .btn,.input-append .btn-group{margin-left:-1px}.input-append .add-on:last-child,.input-append .btn:last-child,.input-append .btn-group:last-child>.dropdown-toggle{-webkit-border-radius:0 4px 4px 0;-moz-border-radius:0 4px 4px 0;border-radius:0 4px 4px 0}.input-prepend.input-append input,.input-prepend.input-append select,.input-prepend.input-append .une
 ditable-input{-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.input-prepend.input-append input+.btn-group .btn,.input-prepend.input-append select+.btn-group .btn,.input-prepend.input-append .uneditable-input+.btn-group .btn{-webkit-border-radius:0 4px 4px 0;-moz-border-radius:0 4px 4px 0;border-radius:0 4px 4px 0}.input-prepend.input-append .add-on:first-child,.input-prepend.input-append .btn:first-child{margin-right:-1px;-webkit-border-radius:4px 0 0 4px;-moz-border-radius:4px 0 0 4px;border-radius:4px 0 0 4px}.input-prepend.input-append .add-on:last-child,.input-prepend.input-append .btn:last-child{margin-left:-1px;-webkit-border-radius:0 4px 4px 0;-moz-border-radius:0 4px 4px 0;border-radius:0 4px 4px 0}.input-prepend.input-append .btn-group:first-child{margin-left:0}input.search-query{padding-right:14px;padding-right:4px \9;padding-left:14px;padding-left:4px \9;margin-bottom:0;-webkit-border-radius:15px;-moz-border-radius:15px;border-radius:15px}.form-search .input
 -append .search-query,.form-search .input-prepend .search-query{-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.form-search .input-append .search-query{-webkit-border-radius:14px 0 0 14px;-moz-border-radius:14px 0 0 14px;border-radius:14px 0 0 14px}.form-search .input-append .btn{-webkit-border-radius:0 14px 14px 0;-moz-border-radius:0 14px 14px 0;border-radius:0 14px 14px 0}.form-search .input-prepend .search-query{-webkit-border-radius:0 14px 14px 0;-moz-border-radius:0 14px 14px 0;border-radius:0 14px 14px 0}.form-search .input-prepend .btn{-webkit-border-radius:14px 0 0 14px;-moz-border-radius:14px 0 0 14px;border-radius:14px 0 0 14px}.form-search input,.form-inline input,.form-horizontal input,.form-search textarea,.form-inline textarea,.form-horizontal textarea,.form-search select,.form-inline select,.form-horizontal select,.form-search .help-inline,.form-inline .help-inline,.form-horizontal .help-inline,.form-search .uneditable-input,.form-inline .uneditable-inp
 ut,.form-horizontal .uneditable-input,.form-search .input-prepend,.form-inline .input-prepend,.form-horizontal .input-prepend,.form-search .input-append,.form-inline .input-append,.form-horizontal .input-append{display:inline-block;*display:inline;margin-bottom:0;vertical-align:middle;*zoom:1}.form-search .hide,.form-inline .hide,.form-horizontal .hide{display:none}.form-search label,.form-inline label,.form-search .btn-group,.form-inline .btn-group{display:inline-block}.form-search .input-append,.form-inline .input-append,.form-search .input-prepend,.form-inline .input-prepend{margin-bottom:0}.form-search .radio,.form-search .checkbox,.form-inline .radio,.form-inline .checkbox{padding-left:0;margin-bottom:0;vertical-align:middle}.form-search .radio input[type="radio"],.form-search .checkbox input[type="checkbox"],.form-inline .radio input[type="radio"],.form-inline .checkbox input[type="checkbox"]{float:left;margin-right:3px;margin-left:0}.control-group{margin-bottom:10px}legend+.c
 ontrol-group{margin-top:20px;-webkit-margin-top-collapse:separate}.form-horizontal .control-group{margin-bottom:20px;*zoom:1}.form-horizontal .control-group:before,.form-horizontal .control-group:after{display:table;line-height:0;content:""}.form-horizontal .control-group:after{clear:both}.form-horizontal .control-label{float:left;width:160px;padding-top:5px;text-align:right}.form-horizontal .controls{*display:inline-block;*padding-left:20px;margin-left:180px;*margin-left:0}.form-horizontal .controls:first-child{*padding-left:180px}.form-horizontal .help-block{margin-bottom:0}.form-horizontal input+.help-block,.form-horizontal select+.help-block,.form-horizontal textarea+.help-block,.form-horizontal .uneditable-input+.help-block,.form-horizontal .input-prepend+.help-block,.form-horizontal .input-append+.help-block{margin-top:10px}.form-horizontal .form-actions{padding-left:180px}table{max-width:100%;background-color:transparent;border-collapse:collapse;border-spacing:0}.table{width:
 100%;margin-bottom:20px}.table th,.table td{padding:8px;line-height:20px;text-align:left;vertical-align:top;border-top:1px solid #ddd}.table th{font-weight:bold}.table thead th{vertical-align:bottom}.table caption+thead tr:first-child th,.table caption+thead tr:first-child td,.table colgroup+thead tr:first-child th,.table colgroup+thead tr:first-child td,.table thead:first-child tr:first-child th,.table thead:first-child tr:first-child td{border-top:0}.table tbody+tbody{border-top:2px solid #ddd}.table .table{background-color:#fff}.table-condensed th,.table-condensed td{padding:4px 5px}.table-bordered{border:1px solid #ddd;border-collapse:separate;*border-collapse:collapse;border-left:0;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.table-bordered th,.table-bordered td{border-left:1px solid #ddd}.table-bordered caption+thead tr:first-child th,.table-bordered caption+tbody tr:first-child th,.table-bordered caption+tbody tr:first-child td,.table-bordered colgroup+
 thead tr:first-child th,.table-bordered colgroup+tbody tr:first-child th,.table-bordered colgroup+tbody tr:first-child td,.table-bordered thead:first-child tr:first-child th,.table-bordered tbody:first-child tr:first-child th,.table-bordered tbody:first-child tr:first-child td{border-top:0}.table-bordered thead:first-child tr:first-child>th:first-child,.table-bordered tbody:first-child tr:first-child>td:first-child,.table-bordered tbody:first-child tr:first-child>th:first-child{-webkit-border-top-left-radius:4px;border-top-left-radius:4px;-moz-border-radius-topleft:4px}.table-bordered thead:first-child tr:first-child>th:last-child,.table-bordered tbody:first-child tr:first-child>td:last-child,.table-bordered tbody:first-child tr:first-child>th:last-child{-webkit-border-top-right-radius:4px;border-top-right-radius:4px;-moz-border-radius-topright:4px}.table-bordered thead:last-child tr:last-child>th:first-child,.table-bordered tbody:last-child tr:last-child>td:first-child,.table-borde
 red tbody:last-child tr:last-child>th:first-child,.table-bordered tfoot:last-child tr:last-child>td:first-child,.table-bordered tfoot:last-child tr:last-child>th:first-child{-webkit-border-bottom-left-radius:4px;border-bottom-left-radius:4px;-moz-border-radius-bottomleft:4px}.table-bordered thead:last-child tr:last-child>th:last-child,.table-bordered tbody:last-child tr:last-child>td:last-child,.table-bordered tbody:last-child tr:last-child>th:last-child,.table-bordered tfoot:last-child tr:last-child>td:last-child,.table-bordered tfoot:last-child tr:last-child>th:last-child{-webkit-border-bottom-right-radius:4px;border-bottom-right-radius:4px;-moz-border-radius-bottomright:4px}.table-bordered tfoot+tbody:last-child tr:last-child td:first-child{-webkit-border-bottom-left-radius:0;border-bottom-left-radius:0;-moz-border-radius-bottomleft:0}.table-bordered tfoot+tbody:last-child tr:last-child td:last-child{-webkit-border-bottom-right-radius:0;border-bottom-right-radius:0;-moz-border-ra
 dius-bottomright:0}.table-bordered caption+thead tr:first-child th:first-child,.table-bordered caption+tbody tr:first-child td:first-child,.table-bordered colgroup+thead tr:first-child th:first-child,.table-bordered colgroup+tbody tr:first-child td:first-child{-webkit-border-top-left-radius:4px;border-top-left-radius:4px;-moz-border-radius-topleft:4px}.table-bordered caption+thead tr:first-child th:last-child,.table-bordered caption+tbody tr:first-child td:last-child,.table-bordered colgroup+thead tr:first-child th:last-child,.table-bordered colgroup+tbody tr:first-child td:last-child{-webkit-border-top-right-radius:4px;border-top-right-radius:4px;-moz-border-radius-topright:4px}.table-striped tbody>tr:nth-child(odd)>td,.table-striped tbody>tr:nth-child(odd)>th{background-color:#f9f9f9}.table-hover tbody tr:hover>td,.table-hover tbody tr:hover>th{background-color:#f5f5f5}table td[class*="span"],table th[class*="span"],.row-fluid table td[class*="span"],.row-fluid table th[class*="sp
 an"]{display:table-cell;float:none;margin-left:0}.table td.span1,.table th.span1{float:none;width:44px;margin-left:0}.table td.span2,.table th.span2{float:none;width:124px;margin-left:0}.table td.span3,.table th.span3{float:none;width:204px;margin-left:0}.table td.span4,.table th.span4{float:none;width:284px;margin-left:0}.table td.span5,.table th.span5{float:none;width:364px;margin-left:0}.table td.span6,.table th.span6{float:none;width:444px;margin-left:0}.table td.span7,.table th.span7{float:none;width:524px;margin-left:0}.table td.span8,.table th.span8{float:none;width:604px;margin-left:0}.table td.span9,.table th.span9{float:none;width:684px;margin-left:0}.table td.span10,.table th.span10{float:none;width:764px;margin-left:0}.table td.span11,.table th.span11{float:none;width:844px;margin-left:0}.table td.span12,.table th.span12{float:none;width:924px;margin-left:0}.table tbody tr.success>td{background-color:#dff0d8}.table tbody tr.error>td{background-color:#f2dede}.table tbody 
 tr.warning>td{background-color:#fcf8e3}.table tbody tr.info>td{background-color:#d9edf7}.table-hover tbody tr.success:hover>td{background-color:#d0e9c6}.table-hover tbody tr.error:hover>td{background-color:#ebcccc}.table-hover tbody tr.warning:hover>td{background-color:#faf2cc}.table-hover tbody tr.info:hover>td{background-color:#c4e3f3}[class^="icon-"],[class*=" icon-"]{display:inline-block;width:14px;height:14px;margin-top:1px;*margin-right:.3em;line-height:14px;vertical-align:text-top;background-image:url("../img/glyphicons-halflings.png");background-position:14px 14px;background-repeat:no-repeat}.icon-white,.nav-pills>.active>a>[class^="icon-"],.nav-pills>.active>a>[class*=" icon-"],.nav-list>.active>a>[class^="icon-"],.nav-list>.active>a>[class*=" icon-"],.navbar-inverse .nav>.active>a>[class^="icon-"],.navbar-inverse .nav>.active>a>[class*=" icon-"],.dropdown-menu>li>a:hover>[class^="icon-"],.dropdown-menu>li>a:focus>[class^="icon-"],.dropdown-menu>li>a:hover>[class*=" icon-"]
 ,.dropdown-menu>li>a:focus>[class*=" icon-"],.dropdown-menu>.active>a>[class^="icon-"],.dropdown-menu>.active>a>[class*=" icon-"],.dropdown-submenu:hover>a>[class^="icon-"],.dropdown-submenu:focus>a>[class^="icon-"],.dropdown-submenu:hover>a>[class*=" icon-"],.dropdown-submenu:focus>a>[class*=" icon-"]{background-image:url("../img/glyphicons-halflings-white.png")}.icon-glass{background-position:0 0}.icon-music{background-position:-24px 0}.icon-search{background-position:-48px 0}.icon-envelope{background-position:-72px 0}.icon-heart{background-position:-96px 0}.icon-star{background-position:-120px 0}.icon-star-empty{background-position:-144px 0}.icon-user{background-position:-168px 0}.icon-film{background-position:-192px 0}.icon-th-large{background-position:-216px 0}.icon-th{background-position:-240px 0}.icon-th-list{background-position:-264px 0}.icon-ok{background-position:-288px 0}.icon-remove{background-position:-312px 0}.icon-zoom-in{background-position:-336px 0}.icon-zoom-out{ba
 ckground-position:-360px 0}.icon-off{background-position:-384px 0}.icon-signal{background-position:-408px 0}.icon-cog{background-position:-432px 0}.icon-trash{background-position:-456px 0}.icon-home{background-position:0 -24px}.icon-file{background-position:-24px -24px}.icon-time{background-position:-48px -24px}.icon-road{background-position:-72px -24px}.icon-download-alt{background-position:-96px -24px}.icon-download{background-position:-120px -24px}.icon-upload{background-position:-144px -24px}.icon-inbox{background-position:-168px -24px}.icon-play-circle{background-position:-192px -24px}.icon-repeat{background-position:-216px -24px}.icon-refresh{background-position:-240px -24px}.icon-list-alt{background-position:-264px -24px}.icon-lock{background-position:-287px -24px}.icon-flag{background-position:-312px -24px}.icon-headphones{background-position:-336px -24px}.icon-volume-off{background-position:-360px -24px}.icon-volume-down{background-position:-384px -24px}.icon-volume-up{back
 ground-position:-408px -24px}.icon-qrcode{background-position:-432px -24px}.icon-barcode{background-position:-456px -24px}.icon-tag{background-position:0 -48px}.icon-tags{background-position:-25px -48px}.icon-book{background-position:-48px -48px}.icon-bookmark{background-position:-72px -48px}.icon-print{background-position:-96px -48px}.icon-camera{background-position:-120px -48px}.icon-font{background-position:-144px -48px}.icon-bold{background-position:-167px -48px}.icon-italic{background-position:-192px -48px}.icon-text-height{background-position:-216px -48px}.icon-text-width{background-position:-240px -48px}.icon-align-left{background-position:-264px -48px}.icon-align-center{background-position:-288px -48px}.icon-align-right{background-position:-312px -48px}.icon-align-justify{background-position:-336px -48px}.icon-list{background-position:-360px -48px}.icon-indent-left{background-position:-384px -48px}.icon-indent-right{background-position:-408px -48px}.icon-facetime-video{backg
 round-position:-432px -48px}.icon-picture{background-position:-456px -48px}.icon-pencil{background-position:0 -72px}.icon-map-marker{background-position:-24px -72px}.icon-adjust{background-position:-48px -72px}.icon-tint{background-position:-72px -72px}.icon-edit{background-position:-96px -72px}.icon-share{background-position:-120px -72px}.icon-check{background-position:-144px -72px}.icon-move{background-position:-168px -72px}.icon-step-backward{background-position:-192px -72px}.icon-fast-backward{background-position:-216px -72px}.icon-backward{background-position:-240px -72px}.icon-play{background-position:-264px -72px}.icon-pause{background-position:-288px -72px}.icon-stop{background-position:-312px -72px}.icon-forward{background-position:-336px -72px}.icon-fast-forward{background-position:-360px -72px}.icon-step-forward{background-position:-384px -72px}.icon-eject{background-position:-408px -72px}.icon-chevron-left{background-position:-432px -72px}.icon-chevron-right{background-p
 osition:-456px -72px}.icon-plus-sign{background-position:0 -96px}.icon-minus-sign{background-position:-24px -96px}.icon-remove-sign{background-position:-48px -96px}.icon-ok-sign{background-position:-72px -96px}.icon-question-sign{background-position:-96px -96px}.icon-info-sign{background-position:-120px -96px}.icon-screenshot{background-position:-144px -96px}.icon-remove-circle{background-position:-168px -96px}.icon-ok-circle{background-position:-192px -96px}.icon-ban-circle{background-position:-216px -96px}.icon-arrow-left{background-position:-240px -96px}.icon-arrow-right{background-position:-264px -96px}.icon-arrow-up{background-position:-289px -96px}.icon-arrow-down{background-position:-312px -96px}.icon-share-alt{background-position:-336px -96px}.icon-resize-full{background-position:-360px -96px}.icon-resize-small{background-position:-384px -96px}.icon-plus{background-position:-408px -96px}.icon-minus{background-position:-433px -96px}.icon-asterisk{background-position:-456px -9
 6px}.icon-exclamation-sign{background-position:0 -120px}.icon-gift{background-position:-24px -120px}.icon-leaf{background-position:-48px -120px}.icon-fire{background-position:-72px -120px}.icon-eye-open{background-position:-96px -120px}.icon-eye-close{background-position:-120px -120px}.icon-warning-sign{background-position:-144px -120px}.icon-plane{background-position:-168px -120px}.icon-calendar{background-position:-192px -120px}.icon-random{width:16px;background-position:-216px -120px}.icon-comment{background-position:-240px -120px}.icon-magnet{background-position:-264px -120px}.icon-chevron-up{background-position:-288px -120px}.icon-chevron-down{background-position:-313px -119px}.icon-retweet{background-position:-336px -120px}.icon-shopping-cart{background-position:-360px -120px}.icon-folder-close{width:16px;background-position:-384px -120px}.icon-folder-open{width:16px;background-position:-408px -120px}.icon-resize-vertical{background-position:-432px -119px}.icon-resize-horizont
 al{background-position:-456px -118px}.icon-hdd{background-position:0 -144px}.icon-bullhorn{background-position:-24px -144px}.icon-bell{background-position:-48px -144px}.icon-certificate{background-position:-72px -144px}.icon-thumbs-up{background-position:-96px -144px}.icon-thumbs-down{background-position:-120px -144px}.icon-hand-right{background-position:-144px -144px}.icon-hand-left{background-position:-168px -144px}.icon-hand-up{background-position:-192px -144px}.icon-hand-down{background-position:-216px -144px}.icon-circle-arrow-right{background-position:-240px -144px}.icon-circle-arrow-left{background-position:-264px -144px}.icon-circle-arrow-up{background-position:-288px -144px}.icon-circle-arrow-down{background-position:-312px -144px}.icon-globe{background-position:-336px -144px}.icon-wrench{background-position:-360px -144px}.icon-tasks{background-position:-384px -144px}.icon-filter{background-position:-408px -144px}.icon-briefcase{background-position:-432px -144px}.icon-fulls
 creen{background-position:-456px -144px}.dropup,.dropdown{position:relative}.dropdown-toggle{*margin-bottom:-3px}.dropdown-toggle:active,.open .dropdown-toggle{outline:0}.caret{display:inline-block;width:0;height:0;vertical-align:top;border-top:4px solid #000;border-right:4px solid transparent;border-left:4px solid transparent;content:""}.dropdown .caret{margin-top:8px;margin-left:2px}.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;float:left;min-width:160px;padding:5px 0;margin:2px 0 0;list-style:none;background-color:#fff;border:1px solid #ccc;border:1px solid rgba(0,0,0,0.2);*border-right-width:2px;*border-bottom-width:2px;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;-webkit-box-shadow:0 5px 10px rgba(0,0,0,0.2);-moz-box-shadow:0 5px 10px rgba(0,0,0,0.2);box-shadow:0 5px 10px rgba(0,0,0,0.2);-webkit-background-clip:padding-box;-moz-background-clip:padding;background-clip:padding-box}.dropdown-menu.pull-right{right:0;left:auto}.drop
 down-menu .divider{*width:100%;height:1px;margin:9px 1px;*margin:-5px 0 5px;overflow:hidden;background-color:#e5e5e5;border-bottom:1px solid #fff}.dropdown-menu>li>a{display:block;padding:3px 20px;clear:both;font-weight:normal;line-height:20px;color:#333;white-space:nowrap}.dropdown-menu>li>a:hover,.dropdown-menu>li>a:focus,.dropdown-submenu:hover>a,.dropdown-submenu:focus>a{color:#fff;text-decoration:none;background-color:#0081c2;background-image:-moz-linear-gradient(top,#08c,#0077b3);background-image:-webkit-gradient(linear,0 0,0 100%,from(#08c),to(#0077b3));background-image:-webkit-linear-gradient(top,#08c,#0077b3);background-image:-o-linear-gradient(top,#08c,#0077b3);background-image:linear-gradient(to bottom,#08c,#0077b3);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc',endColorstr='#ff0077b3',GradientType=0)}.dropdown-menu>.active>a,.dropdown-menu>.active>a:hover,.dropdown-menu>.active>a:focus{color:#fff;text-decoration:non
 e;background-color:#0081c2;background-image:-moz-linear-gradient(top,#08c,#0077b3);background-image:-webkit-gradient(linear,0 0,0 100%,from(#08c),to(#0077b3));background-image:-webkit-linear-gradient(top,#08c,#0077b3);background-image:-o-linear-gradient(top,#08c,#0077b3);background-image:linear-gradient(to bottom,#08c,#0077b3);background-repeat:repeat-x;outline:0;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc',endColorstr='#ff0077b3',GradientType=0)}.dropdown-menu>.disabled>a,.dropdown-menu>.disabled>a:hover,.dropdown-menu>.disabled>a:focus{color:#999}.dropdown-menu>.disabled>a:hover,.dropdown-menu>.disabled>a:focus{text-decoration:none;cursor:default;background-color:transparent;background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.open{*z-index:1000}.open>.dropdown-menu{display:block}.pull-right>.dropdown-menu{right:0;left:auto}.dropup .caret,.navbar-fixed-bottom .dropdown .caret{border-top:0;border-bottom:4px solid #00
 0;content:""}.dropup .dropdown-menu,.navbar-fixed-bottom .dropdown .dropdown-menu{top:auto;bottom:100%;margin-bottom:1px}.dropdown-submenu{position:relative}.dropdown-submenu>.dropdown-menu{top:0;left:100%;margin-top:-6px;margin-left:-1px;-webkit-border-radius:0 6px 6px 6px;-moz-border-radius:0 6px 6px 6px;border-radius:0 6px 6px 6px}.dropdown-submenu:hover>.dropdown-menu{display:block}.dropup .dropdown-submenu>.dropdown-menu{top:auto;bottom:0;margin-top:0;margin-bottom:-2px;-webkit-border-radius:5px 5px 5px 0;-moz-border-radius:5px 5px 5px 0;border-radius:5px 5px 5px 0}.dropdown-submenu>a:after{display:block;float:right;width:0;height:0;margin-top:5px;margin-right:-10px;border-color:transparent;border-left-color:#ccc;border-style:solid;border-width:5px 0 5px 5px;content:" "}.dropdown-submenu:hover>a:after{border-left-color:#fff}.dropdown-submenu.pull-left{float:none}.dropdown-submenu.pull-left>.dropdown-menu{left:-100%;margin-left:10px;-webkit-border-radius:6px 0 6px 6px;-moz-borde
 r-radius:6px 0 6px 6px;border-radius:6px 0 6px 6px}.dropdown .dropdown-menu .nav-header{padding-right:20px;padding-left:20px}.typeahead{z-index:1051;margin-top:2px;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.well{min-height:20px;padding:19px;margin-bottom:20px;background-color:#f5f5f5;border:1px solid #e3e3e3;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.05);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.05);box-shadow:inset 0 1px 1px rgba(0,0,0,0.05)}.well blockquote{border-color:#ddd;border-color:rgba(0,0,0,0.15)}.well-large{padding:24px;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px}.well-small{padding:9px;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}.fade{opacity:0;-webkit-transition:opacity .15s linear;-moz-transition:opacity .15s linear;-o-transition:opacity .15s linear;transition:opacity .15s linear}.fade.in{opacity:1}.collapse{position:relative
 ;height:0;overflow:hidden;-webkit-transition:height .35s ease;-moz-transition:height .35s ease;-o-transition:height .35s ease;transition:height .35s ease}.collapse.in{height:auto}.close{float:right;font-size:20px;font-weight:bold;line-height:20px;color:#000;text-shadow:0 1px 0 #fff;opacity:.2;filter:alpha(opacity=20)}.close:hover,.close:focus{color:#000;text-decoration:none;cursor:pointer;opacity:.4;filter:alpha(opacity=40)}button.close{padding:0;cursor:pointer;background:transparent;border:0;-webkit-appearance:none}.btn{display:inline-block;*display:inline;padding:4px 12px;margin-bottom:0;*margin-left:.3em;font-size:14px;line-height:20px;color:#333;text-align:center;text-shadow:0 1px 1px rgba(255,255,255,0.75);vertical-align:middle;cursor:pointer;background-color:#f5f5f5;*background-color:#e6e6e6;background-image:-moz-linear-gradient(top,#fff,#e6e6e6);background-image:-webkit-gradient(linear,0 0,0 100%,from(#fff),to(#e6e6e6));background-image:-webkit-linear-gradient(top,#fff,#e6e6e
 6);background-image:-o-linear-gradient(top,#fff,#e6e6e6);background-image:linear-gradient(to bottom,#fff,#e6e6e6);background-repeat:repeat-x;border:1px solid #ccc;*border:0;border-color:#e6e6e6 #e6e6e6 #bfbfbf;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);border-bottom-color:#b3b3b3;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff',endColorstr='#ffe6e6e6',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);*zoom:1;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05);-moz-box-shadow:inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05);box-shadow:inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05)}.btn:hover,.btn:focus,.btn:active,.btn.active,.btn.disabled,.btn[disabled]{color:#333;background-color:#e6e6e6;*background-color:#d9d9d9}.btn:active,.btn.active{background-color:#ccc \9}.btn:first-child{*ma
 rgin-left:0}.btn:hover,.btn:focus{color:#333;text-decoration:none;background-position:0 -15px;-webkit-transition:background-position .1s linear;-moz-transition:background-position .1s linear;-o-transition:background-position .1s linear;transition:background-position .1s linear}.btn:focus{outline:thin dotted #333;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.btn.active,.btn:active{background-image:none;outline:0;-webkit-box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05);-moz-box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05);box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05)}.btn.disabled,.btn[disabled]{cursor:default;background-image:none;opacity:.65;filter:alpha(opacity=65);-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none}.btn-large{padding:11px 19px;font-size:17.5px;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px}.btn-large [class^="icon-"],.btn-large [class*=" icon-"]{margi
 n-top:4px}.btn-small{padding:2px 10px;font-size:11.9px;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}.btn-small [class^="icon-"],.btn-small [class*=" icon-"]{margin-top:0}.btn-mini [class^="icon-"],.btn-mini [class*=" icon-"]{margin-top:-1px}.btn-mini{padding:0 6px;font-size:10.5px;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}.btn-block{display:block;width:100%;padding-right:0;padding-left:0;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.btn-block+.btn-block{margin-top:5px}input[type="submit"].btn-block,input[type="reset"].btn-block,input[type="button"].btn-block{width:100%}.btn-primary.active,.btn-warning.active,.btn-danger.active,.btn-success.active,.btn-info.active,.btn-inverse.active{color:rgba(255,255,255,0.75)}.btn-primary{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#006dcc;*background-color:#04c;background-image:-moz-linear-gradient(top,#08c,#04c);background-image:-webkit-gradien
 t(linear,0 0,0 100%,from(#08c),to(#04c));background-image:-webkit-linear-gradient(top,#08c,#04c);background-image:-o-linear-gradient(top,#08c,#04c);background-image:linear-gradient(to bottom,#08c,#04c);background-repeat:repeat-x;border-color:#04c #04c #002a80;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc',endColorstr='#ff0044cc',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.btn-primary:hover,.btn-primary:focus,.btn-primary:active,.btn-primary.active,.btn-primary.disabled,.btn-primary[disabled]{color:#fff;background-color:#04c;*background-color:#003bb3}.btn-primary:active,.btn-primary.active{background-color:#039 \9}.btn-warning{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#faa732;*background-color:#f89406;background-image:-moz-linear-gradient(top,#fbb450,#f89406);background-image:-webkit-gradient(linear,0 0,0 100%,from(#fbb450),to(#f8940
 6));background-image:-webkit-linear-gradient(top,#fbb450,#f89406);background-image:-o-linear-gradient(top,#fbb450,#f89406);background-image:linear-gradient(to bottom,#fbb450,#f89406);background-repeat:repeat-x;border-color:#f89406 #f89406 #ad6704;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450',endColorstr='#fff89406',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.btn-warning:hover,.btn-warning:focus,.btn-warning:active,.btn-warning.active,.btn-warning.disabled,.btn-warning[disabled]{color:#fff;background-color:#f89406;*background-color:#df8505}.btn-warning:active,.btn-warning.active{background-color:#c67605 \9}.btn-danger{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#da4f49;*background-color:#bd362f;background-image:-moz-linear-gradient(top,#ee5f5b,#bd362f);background-image:-webkit-gradient(linear,0 0,0 100%,from(#ee5f5b),to(#bd362f));back
 ground-image:-webkit-linear-gradient(top,#ee5f5b,#bd362f);background-image:-o-linear-gradient(top,#ee5f5b,#bd362f);background-image:linear-gradient(to bottom,#ee5f5b,#bd362f);background-repeat:repeat-x;border-color:#bd362f #bd362f #802420;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b',endColorstr='#ffbd362f',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.btn-danger:hover,.btn-danger:focus,.btn-danger:active,.btn-danger.active,.btn-danger.disabled,.btn-danger[disabled]{color:#fff;background-color:#bd362f;*background-color:#a9302a}.btn-danger:active,.btn-danger.active{background-color:#942a25 \9}.btn-success{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#5bb75b;*background-color:#51a351;background-image:-moz-linear-gradient(top,#62c462,#51a351);background-image:-webkit-gradient(linear,0 0,0 100%,from(#62c462),to(#51a351));background-image:-w
 ebkit-linear-gradient(top,#62c462,#51a351);background-image:-o-linear-gradient(top,#62c462,#51a351);background-image:linear-gradient(to bottom,#62c462,#51a351);background-repeat:repeat-x;border-color:#51a351 #51a351 #387038;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462',endColorstr='#ff51a351',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.btn-success:hover,.btn-success:focus,.btn-success:active,.btn-success.active,.btn-success.disabled,.btn-success[disabled]{color:#fff;background-color:#51a351;*background-color:#499249}.btn-success:active,.btn-success.active{background-color:#408140 \9}.btn-info{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#49afcd;*background-color:#2f96b4;background-image:-moz-linear-gradient(top,#5bc0de,#2f96b4);background-image:-webkit-gradient(linear,0 0,0 100%,from(#5bc0de),to(#2f96b4));background-image:-webkit-line
 ar-gradient(top,#5bc0de,#2f96b4);background-image:-o-linear-gradient(top,#5bc0de,#2f96b4);background-image:linear-gradient(to bottom,#5bc0de,#2f96b4);background-repeat:repeat-x;border-color:#2f96b4 #2f96b4 #1f6377;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de',endColorstr='#ff2f96b4',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.btn-info:hover,.btn-info:focus,.btn-info:active,.btn-info.active,.btn-info.disabled,.btn-info[disabled]{color:#fff;background-color:#2f96b4;*background-color:#2a85a0}.btn-info:active,.btn-info.active{background-color:#24748c \9}.btn-inverse{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#363636;*background-color:#222;background-image:-moz-linear-gradient(top,#444,#222);background-image:-webkit-gradient(linear,0 0,0 100%,from(#444),to(#222));background-image:-webkit-linear-gradient(top,#444,#222);background-image:-o
 -linear-gradient(top,#444,#222);background-image:linear-gradient(to bottom,#444,#222);background-repeat:repeat-x;border-color:#222 #222 #000;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff444444',endColorstr='#ff222222',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.btn-inverse:hover,.btn-inverse:focus,.btn-inverse:active,.btn-inverse.active,.btn-inverse.disabled,.btn-inverse[disabled]{color:#fff;background-color:#222;*background-color:#151515}.btn-inverse:active,.btn-inverse.active{background-color:#080808 \9}button.btn,input[type="submit"].btn{*padding-top:3px;*padding-bottom:3px}button.btn::-moz-focus-inner,input[type="submit"].btn::-moz-focus-inner{padding:0;border:0}button.btn.btn-large,input[type="submit"].btn.btn-large{*padding-top:7px;*padding-bottom:7px}button.btn.btn-small,input[type="submit"].btn.btn-small{*padding-top:3px;*padding-bottom:3px}button.btn.bt
 n-mini,input[type="submit"].btn.btn-mini{*padding-top:1px;*padding-bottom:1px}.btn-link,.btn-link:active,.btn-link[disabled]{background-color:transparent;background-image:none;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none}.btn-link{color:#08c;cursor:pointer;border-color:transparent;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.btn-link:hover,.btn-link:focus{color:#005580;text-decoration:underline;background-color:transparent}.btn-link[disabled]:hover,.btn-link[disabled]:focus{color:#333;text-decoration:none}.btn-group{position:relative;display:inline-block;*display:inline;*margin-left:.3em;font-size:0;white-space:nowrap;vertical-align:middle;*zoom:1}.btn-group:first-child{*margin-left:0}.btn-group+.btn-group{margin-left:5px}.btn-toolbar{margin-top:10px;margin-bottom:10px;font-size:0}.btn-toolbar>.btn+.btn,.btn-toolbar>.btn-group+.btn,.btn-toolbar>.btn+.btn-group{margin-left:5px}.btn-group>.btn{position:relative;-webkit-border-radius:0;-moz-border-radiu
 s:0;border-radius:0}.btn-group>.btn+.btn{margin-left:-1px}.btn-group>.btn,.btn-group>.dropdown-menu,.btn-group>.popover{font-size:14px}.btn-group>.btn-mini{font-size:10.5px}.btn-group>.btn-small{font-size:11.9px}.btn-group>.btn-large{font-size:17.5px}.btn-group>.btn:first-child{margin-left:0;-webkit-border-bottom-left-radius:4px;border-bottom-left-radius:4px;-webkit-border-top-left-radius:4px;border-top-left-radius:4px;-moz-border-radius-bottomleft:4px;-moz-border-radius-topleft:4px}.btn-group>.btn:last-child,.btn-group>.dropdown-toggle{-webkit-border-top-right-radius:4px;border-top-right-radius:4px;-webkit-border-bottom-right-radius:4px;border-bottom-right-radius:4px;-moz-border-radius-topright:4px;-moz-border-radius-bottomright:4px}.btn-group>.btn.large:first-child{margin-left:0;-webkit-border-bottom-left-radius:6px;border-bottom-left-radius:6px;-webkit-border-top-left-radius:6px;border-top-left-radius:6px;-moz-border-radius-bottomleft:6px;-moz-border-radius-topleft:6px}.btn-group
 >.btn.large:last-child,.btn-group>.large.dropdown-toggle{-webkit-border-top-right-radius:6px;border-top-right-radius:6px;-webkit-border-bottom-right-radius:6px;border-bottom-right-radius:6px;-moz-border-radius-topright:6px;-moz-border-radius-bottomright:6px}.btn-group>.btn:hover,.btn-group>.btn:focus,.btn-group>.btn:active,.btn-group>.btn.active{z-index:2}.btn-group .dropdown-toggle:active,.btn-group.open .dropdown-toggle{outline:0}.btn-group>.btn+.dropdown-toggle{*padding-top:5px;padding-right:8px;*padding-bottom:5px;padding-left:8px;-webkit-box-shadow:inset 1px 0 0 rgba(255,255,255,0.125),inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05);-moz-box-shadow:inset 1px 0 0 rgba(255,255,255,0.125),inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05);box-shadow:inset 1px 0 0 rgba(255,255,255,0.125),inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05)}.btn-group>.btn-mini+.dropdown-toggle{*padding-top:2px;padding-right:5px;*padding-bottom:2px;padding-left:5
 px}.btn-group>.btn-small+.dropdown-toggle{*padding-top:5px;*padding-bottom:4px}.btn-group>.btn-large+.dropdown-toggle{*padding-top:7px;padding-right:12px;*padding-bottom:7px;padding-left:12px}.btn-group.open .dropdown-toggle{background-image:none;-webkit-box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05);-moz-box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05);box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05)}.btn-group.open .btn.dropdown-toggle{background-color:#e6e6e6}.btn-group.open .btn-primary.dropdown-toggle{background-color:#04c}.btn-group.open .btn-warning.dropdown-toggle{background-color:#f89406}.btn-group.open .btn-danger.dropdown-toggle{background-color:#bd362f}.btn-group.open .btn-success.dropdown-toggle{background-color:#51a351}.btn-group.open .btn-info.dropdown-toggle{background-color:#2f96b4}.btn-group.open .btn-inverse.dropdown-toggle{background-color:#222}.btn .caret{margin-top:8px;margin-left:0}.btn-large 
 .caret{margin-top:6px}.btn-large .caret{border-top-width:5px;border-right-width:5px;border-left-width:5px}.btn-mini .caret,.btn-small .caret{margin-top:8px}.dropup .btn-large .caret{border-bottom-width:5px}.btn-primary .caret,.btn-warning .caret,.btn-danger .caret,.btn-info .caret,.btn-success .caret,.btn-inverse .caret{border-top-color:#fff;border-bottom-color:#fff}.btn-group-vertical{display:inline-block;*display:inline;*zoom:1}.btn-group-vertical>.btn{display:block;float:none;max-width:100%;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.btn-group-vertical>.btn+.btn{margin-top:-1px;margin-left:0}.btn-group-vertical>.btn:first-child{-webkit-border-radius:4px 4px 0 0;-moz-border-radius:4px 4px 0 0;border-radius:4px 4px 0 0}.btn-group-vertical>.btn:last-child{-webkit-border-radius:0 0 4px 4px;-moz-border-radius:0 0 4px 4px;border-radius:0 0 4px 4px}.btn-group-vertical>.btn-large:first-child{-webkit-border-radius:6px 6px 0 0;-moz-border-radius:6px 6px 0 0;border-radius:
 6px 6px 0 0}.btn-group-vertical>.btn-large:last-child{-webkit-border-radius:0 0 6px 6px;-moz-border-radius:0 0 6px 6px;border-radius:0 0 6px 6px}.alert{padding:8px 35px 8px 14px;margin-bottom:20px;text-shadow:0 1px 0 rgba(255,255,255,0.5);background-color:#fcf8e3;border:1px solid #fbeed5;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.alert,.alert h4{color:#c09853}.alert h4{margin:0}.alert .close{position:relative;top:-2px;right:-21px;line-height:20px}.alert-success{color:#468847;background-color:#dff0d8;border-color:#d6e9c6}.alert-success h4{color:#468847}.alert-danger,.alert-error{color:#b94a48;background-color:#f2dede;border-color:#eed3d7}.alert-danger h4,.alert-error h4{color:#b94a48}.alert-info{color:#3a87ad;background-color:#d9edf7;border-color:#bce8f1}.alert-info h4{color:#3a87ad}.alert-block{padding-top:14px;padding-bottom:14px}.alert-block>p,.alert-block>ul{margin-bottom:0}.alert-block p+p{margin-top:5px}.nav{margin-bottom:20px;margin-left:0;list-style:n
 one}.nav>li>a{display:block}.nav>li>a:hover,.nav>li>a:focus{text-decoration:none;background-color:#eee}.nav>li>a>img{max-width:none}.nav>.pull-right{float:right}.nav-header{display:block;padding:3px 15px;font-size:11px;font-weight:bold;line-height:20px;color:#999;text-shadow:0 1px 0 rgba(255,255,255,0.5);text-transform:uppercase}.nav li+.nav-header{margin-top:9px}.nav-list{padding-right:15px;padding-left:15px;margin-bottom:0}.nav-list>li>a,.nav-list .nav-header{margin-right:-15px;margin-left:-15px;text-shadow:0 1px 0 rgba(255,255,255,0.5)}.nav-list>li>a{padding:3px 15px}.nav-list>.active>a,.nav-list>.active>a:hover,.nav-list>.active>a:focus{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.2);background-color:#08c}.nav-list [class^="icon-"],.nav-list [class*=" icon-"]{margin-right:2px}.nav-list .divider{*width:100%;height:1px;margin:9px 1px;*margin:-5px 0 5px;overflow:hidden;background-color:#e5e5e5;border-bottom:1px solid #fff}.nav-tabs,.nav-pills{*zoom:1}.nav-tabs:before,.nav-pills:bef
 ore,.nav-tabs:after,.nav-pills:after{display:table;line-height:0;content:""}.nav-tabs:after,.nav-pills:after{clear:both}.nav-tabs>li,.nav-pills>li{float:left}.nav-tabs>li>a,.nav-pills>li>a{padding-right:12px;padding-left:12px;margin-right:2px;line-height:14px}.nav-tabs{border-bottom:1px solid #ddd}.nav-tabs>li{margin-bottom:-1px}.nav-tabs>li>a{padding-top:8px;padding-bottom:8px;line-height:20px;border:1px solid transparent;-webkit-border-radius:4px 4px 0 0;-moz-border-radius:4px 4px 0 0;border-radius:4px 4px 0 0}.nav-tabs>li>a:hover,.nav-tabs>li>a:focus{border-color:#eee #eee #ddd}.nav-tabs>.active>a,.nav-tabs>.active>a:hover,.nav-tabs>.active>a:focus{color:#555;cursor:default;background-color:#fff;border:1px solid #ddd;border-bottom-color:transparent}.nav-pills>li>a{padding-top:8px;padding-bottom:8px;margin-top:2px;margin-bottom:2px;-webkit-border-radius:5px;-moz-border-radius:5px;border-radius:5px}.nav-pills>.active>a,.nav-pills>.active>a:hover,.nav-pills>.active>a:focus{color:#ff
 f;background-color:#08c}.nav-stacked>li{float:none}.nav-stacked>li>a{margin-right:0}.nav-tabs.nav-stacked{border-bottom:0}.nav-tabs.nav-stacked>li>a{border:1px solid #ddd;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.nav-tabs.nav-stacked>li:first-child>a{-webkit-border-top-right-radius:4px;border-top-right-radius:4px;-webkit-border-top-left-radius:4px;border-top-left-radius:4px;-moz-border-radius-topright:4px;-moz-border-radius-topleft:4px}.nav-tabs.nav-stacked>li:last-child>a{-webkit-border-bottom-right-radius:4px;border-bottom-right-radius:4px;-webkit-border-bottom-left-radius:4px;border-bottom-left-radius:4px;-moz-border-radius-bottomright:4px;-moz-border-radius-bottomleft:4px}.nav-tabs.nav-stacked>li>a:hover,.nav-tabs.nav-stacked>li>a:focus{z-index:2;border-color:#ddd}.nav-pills.nav-stacked>li>a{margin-bottom:3px}.nav-pills.nav-stacked>li:last-child>a{margin-bottom:1px}.nav-tabs .dropdown-menu{-webkit-border-radius:0 0 6px 6px;-moz-border-radius:0 0 6px 6px;borde
 r-radius:0 0 6px 6px}.nav-pills .dropdown-menu{-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px}.nav .dropdown-toggle .caret{margin-top:6px;border-top-color:#08c;border-bottom-color:#08c}.nav .dropdown-toggle:hover .caret,.nav .dropdown-toggle:focus .caret{border-top-color:#005580;border-bottom-color:#005580}.nav-tabs .dropdown-toggle .caret{margin-top:8px}.nav .active .dropdown-toggle .caret{border-top-color:#fff;border-bottom-color:#fff}.nav-tabs .active .dropdown-toggle .caret{border-top-color:#555;border-bottom-color:#555}.nav>.dropdown.active>a:hover,.nav>.dropdown.active>a:focus{cursor:pointer}.nav-tabs .open .dropdown-toggle,.nav-pills .open .dropdown-toggle,.nav>li.dropdown.open.active>a:hover,.nav>li.dropdown.open.active>a:focus{color:#fff;background-color:#999;border-color:#999}.nav li.dropdown.open .caret,.nav li.dropdown.open.active .caret,.nav li.dropdown.open a:hover .caret,.nav li.dropdown.open a:focus .caret{border-top-color:#fff;border-bottom-color
 :#fff;opacity:1;filter:alpha(opacity=100)}.tabs-stacked .open>a:hover,.tabs-stacked .open>a:focus{border-color:#999}.tabbable{*zoom:1}.tabbable:before,.tabbable:after{display:table;line-height:0;content:""}.tabbable:after{clear:both}.tab-content{overflow:auto}.tabs-below>.nav-tabs,.tabs-right>.nav-tabs,.tabs-left>.nav-tabs{border-bottom:0}.tab-content>.tab-pane,.pill-content>.pill-pane{display:none}.tab-content>.active,.pill-content>.active{display:block}.tabs-below>.nav-tabs{border-top:1px solid #ddd}.tabs-below>.nav-tabs>li{margin-top:-1px;margin-bottom:0}.tabs-below>.nav-tabs>li>a{-webkit-border-radius:0 0 4px 4px;-moz-border-radius:0 0 4px 4px;border-radius:0 0 4px 4px}.tabs-below>.nav-tabs>li>a:hover,.tabs-below>.nav-tabs>li>a:focus{border-top-color:#ddd;border-bottom-color:transparent}.tabs-below>.nav-tabs>.active>a,.tabs-below>.nav-tabs>.active>a:hover,.tabs-below>.nav-tabs>.active>a:focus{border-color:transparent #ddd #ddd #ddd}.tabs-left>.nav-tabs>li,.tabs-right>.nav-tabs>l
 i{float:none}.tabs-left>.nav-tabs>li>a,.tabs-right>.nav-tabs>li>a{min-width:74px;margin-right:0;margin-bottom:3px}.tabs-left>.nav-tabs{float:left;margin-right:19px;border-right:1px solid #ddd}.tabs-left>.nav-tabs>li>a{margin-right:-1px;-webkit-border-radius:4px 0 0 4px;-moz-border-radius:4px 0 0 4px;border-radius:4px 0 0 4px}.tabs-left>.nav-tabs>li>a:hover,.tabs-left>.nav-tabs>li>a:focus{border-color:#eee #ddd #eee #eee}.tabs-left>.nav-tabs .active>a,.tabs-left>.nav-tabs .active>a:hover,.tabs-left>.nav-tabs .active>a:focus{border-color:#ddd transparent #ddd #ddd;*border-right-color:#fff}.tabs-right>.nav-tabs{float:right;margin-left:19px;border-left:1px solid #ddd}.tabs-right>.nav-tabs>li>a{margin-left:-1px;-webkit-border-radius:0 4px 4px 0;-moz-border-radius:0 4px 4px 0;border-radius:0 4px 4px 0}.tabs-right>.nav-tabs>li>a:hover,.tabs-right>.nav-tabs>li>a:focus{border-color:#eee #eee #eee #ddd}.tabs-right>.nav-tabs .active>a,.tabs-right>.nav-tabs .active>a:hover,.tabs-right>.nav-tabs
  .active>a:focus{border-color:#ddd #ddd #ddd transparent;*border-left-color:#fff}.nav>.disabled>a{color:#999}.nav>.disabled>a:hover,.nav>.disabled>a:focus{text-decoration:none;cursor:default;background-color:transparent}.navbar{*position:relative;*z-index:2;margin-bottom:20px;overflow:visible}.navbar-inner{min-height:40px;padding-right:20px;padding-left:20px;background-color:#fafafa;background-image:-moz-linear-gradient(top,#fff,#f2f2f2);background-image:-webkit-gradient(linear,0 0,0 100%,from(#fff),to(#f2f2f2));background-image:-webkit-linear-gradient(top,#fff,#f2f2f2);background-image:-o-linear-gradient(top,#fff,#f2f2f2);background-image:linear-gradient(to bottom,#fff,#f2f2f2);background-repeat:repeat-x;border:1px solid #d4d4d4;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff',endColorstr='#fff2f2f2',GradientType=0);*zoom:1;-webkit-box-shadow:0 1px 4px rgba(0,0,0,0.065);-moz-box-shadow:0 1
 px 4px rgba(0,0,0,0.065);box-shadow:0 1px 4px rgba(0,0,0,0.065)}.navbar-inner:before,.navbar-inner:after{display:table;line-height:0;content:""}.navbar-inner:after{clear:both}.navbar .container{width:auto}.nav-collapse.collapse{height:auto;overflow:visible}.navbar .brand{display:block;float:left;padding:10px 20px 10px;margin-left:-20px;font-size:20px;font-weight:200;color:#777;text-shadow:0 1px 0 #fff}.navbar .brand:hover,.navbar .brand:focus{text-decoration:none}.navbar-text{margin-bottom:0;line-height:40px;color:#777}.navbar-link{color:#777}.navbar-link:hover,.navbar-link:focus{color:#333}.navbar .divider-vertical{height:40px;margin:0 9px;border-right:1px solid #fff;border-left:1px solid #f2f2f2}.navbar .btn,.navbar .btn-group{margin-top:5px}.navbar .btn-group .btn,.navbar .input-prepend .btn,.navbar .input-append .btn,.navbar .input-prepend .btn-group,.navbar .input-append .btn-group{margin-top:0}.navbar-form{margin-bottom:0;*zoom:1}.navbar-form:before,.navbar-form:after{display:
 table;line-height:0;content:""}.navbar-form:after{clear:both}.navbar-form input,.navbar-form select,.navbar-form .radio,.navbar-form .checkbox{margin-top:5px}.navbar-form input,.navbar-form select,.navbar-form .btn{display:inline-block;margin-bottom:0}.navbar-form input[type="image"],.navbar-form input[type="checkbox"],.navbar-form input[type="radio"]{margin-top:3px}.navbar-form .input-append,.navbar-form .input-prepend{margin-top:5px;white-space:nowrap}.navbar-form .input-append input,.navbar-form .input-prepend input{margin-top:0}.navbar-search{position:relative;float:left;margin-top:5px;margin-bottom:0}.navbar-search .search-query{padding:4px 14px;margin-bottom:0;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:13px;font-weight:normal;line-height:1;-webkit-border-radius:15px;-moz-border-radius:15px;border-radius:15px}.navbar-static-top{position:static;margin-bottom:0}.navbar-static-top .navbar-inner{-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.na
 vbar-fixed-top,.navbar-fixed-bottom{position:fixed;right:0;left:0;z-index:1030;margin-bottom:0}.navbar-fixed-top .navbar-inner,.navbar-static-top .navbar-inner{border-width:0 0 1px}.navbar-fixed-bottom .navbar-inner{border-width:1px 0 0}.navbar-fixed-top .navbar-inner,.navbar-fixed-bottom .navbar-inner{padding-right:0;padding-left:0;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.navbar-static-top .container,.navbar-fixed-top .container,.navbar-fixed-bottom .container{width:940px}.navbar-fixed-top{top:0}.navbar-fixed-top .navbar-inner,.navbar-static-top .navbar-inner{-webkit-box-shadow:0 1px 10px rgba(0,0,0,0.1);-moz-box-shadow:0 1px 10px rgba(0,0,0,0.1);box-shadow:0 1px 10px rgba(0,0,0,0.1)}.navbar-fixed-bottom{bottom:0}.navbar-fixed-bottom .navbar-inner{-webkit-box-shadow:0 -1px 10px rgba(0,0,0,0.1);-moz-box-shadow:0 -1px 10px rgba(0,0,0,0.1);box-shadow:0 -1px 10px rgba(0,0,0,0.1)}.navbar .nav{position:relative;left:0;display:block;float:left;margin:0 10px 0 0}.navba
 r .nav.pull-right{float:right;margin-right:0}.navbar .nav>li{float:left}.navbar .nav>li>a{float:none;padding:10px 15px 10px;color:#777;text-decoration:none;text-shadow:0 1px 0 #fff}.navbar .nav .dropdown-toggle .caret{margin-top:8px}.navbar .nav>li>a:focus,.navbar .nav>li>a:hover{color:#333;text-decoration:none;background-color:transparent}.navbar .nav>.active>a,.navbar .nav>.active>a:hover,.navbar .nav>.active>a:focus{color:#555;text-decoration:none;background-color:#e5e5e5;-webkit-box-shadow:inset 0 3px 8px rgba(0,0,0,0.125);-moz-box-shadow:inset 0 3px 8px rgba(0,0,0,0.125);box-shadow:inset 0 3px 8px rgba(0,0,0,0.125)}.navbar .btn-navbar{display:none;float:right;padding:7px 10px;margin-right:5px;margin-left:5px;color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#ededed;*background-color:#e5e5e5;background-image:-moz-linear-gradient(top,#f2f2f2,#e5e5e5);background-image:-webkit-gradient(linear,0 0,0 100%,from(#f2f2f2),to(#e5e5e5));background-image:-webkit-linear-grad
 ient(top,#f2f2f2,#e5e5e5);background-image:-o-linear-gradient(top,#f2f2f2,#e5e5e5);background-image:linear-gradient(to bottom,#f2f2f2,#e5e5e5);background-repeat:repeat-x;border-color:#e5e5e5 #e5e5e5 #bfbfbf;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2f2f2',endColorstr='#ffe5e5e5',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.075);-moz-box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.075);box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.075)}.navbar .btn-navbar:hover,.navbar .btn-navbar:focus,.navbar .btn-navbar:active,.navbar .btn-navbar.active,.navbar .btn-navbar.disabled,.navbar .btn-navbar[disabled]{color:#fff;background-color:#e5e5e5;*background-color:#d9d9d9}.navbar .btn-navbar:active,.navbar .btn-navbar.active{background-color
 :#ccc \9}.navbar .btn-navbar .icon-bar{display:block;width:18px;height:2px;background-color:#f5f5f5;-webkit-border-radius:1px;-moz-border-radius:1px;border-radius:1px;-webkit-box-shadow:0 1px 0 rgba(0,0,0,0.25);-moz-box-shadow:0 1px 0 rgba(0,0,0,0.25);box-shadow:0 1px 0 rgba(0,0,0,0.25)}.btn-navbar .icon-bar+.icon-bar{margin-top:3px}.navbar .nav>li>.dropdown-menu:before{position:absolute;top:-7px;left:9px;display:inline-block;border-right:7px solid transparent;border-bottom:7px solid #ccc;border-left:7px solid transparent;border-bottom-color:rgba(0,0,0,0.2);content:''}.navbar .nav>li>.dropdown-menu:after{position:absolute;top:-6px;left:10px;display:inline-block;border-right:6px solid transparent;border-bottom:6px solid #fff;border-left:6px solid transparent;content:''}.navbar-fixed-bottom .nav>li>.dropdown-menu:before{top:auto;bottom:-7px;border-top:7px solid #ccc;border-bottom:0;border-top-color:rgba(0,0,0,0.2)}.navbar-fixed-bottom .nav>li>.dropdown-menu:after{top:auto;bottom:-6px;
 border-top:6px solid #fff;border-bottom:0}.navbar .nav li.dropdown>a:hover .caret,.navbar .nav li.dropdown>a:focus .caret{border-top-color:#333;border-bottom-color:#333}.navbar .nav li.dropdown.open>.dropdown-toggle,.navbar .nav li.dropdown.active>.dropdown-toggle,.navbar .nav li.dropdown.open.active>.dropdown-toggle{color:#555;background-color:#e5e5e5}.navbar .nav li.dropdown>.dropdown-toggle .caret{border-top-color:#777;border-bottom-color:#777}.navbar .nav li.dropdown.open>.dropdown-toggle .caret,.navbar .nav li.dropdown.active>.dropdown-toggle .caret,.navbar .nav li.dropdown.open.active>.dropdown-toggle .caret{border-top-color:#555;border-bottom-color:#555}.navbar .pull-right>li>.dropdown-menu,.navbar .nav>li>.dropdown-menu.pull-right{right:0;left:auto}.navbar .pull-right>li>.dropdown-menu:before,.navbar .nav>li>.dropdown-menu.pull-right:before{right:12px;left:auto}.navbar .pull-right>li>.dropdown-menu:after,.navbar .nav>li>.dropdown-menu.pull-right:after{right:13px;left:auto}.n
 avbar .pull-right>li>.dropdown-menu .dropdown-menu,.navbar .nav>li>.dropdown-menu.pull-right .dropdown-menu{right:100%;left:auto;margin-right:-1px;margin-left:0;-webkit-border-radius:6px 0 6px 6px;-moz-border-radius:6px 0 6px 6px;border-radius:6px 0 6px 6px}.navbar-inverse .navbar-inner{background-color:#1b1b1b;background-image:-moz-linear-gradient(top,#222,#111);background-image:-webkit-gradient(linear,0 0,0 100%,from(#222),to(#111));background-image:-webkit-linear-gradient(top,#222,#111);background-image:-o-linear-gradient(top,#222,#111);background-image:linear-gradient(to bottom,#222,#111);background-repeat:repeat-x;border-color:#252525;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff222222',endColorstr='#ff111111',GradientType=0)}.navbar-inverse .brand,.navbar-inverse .nav>li>a{color:#999;text-shadow:0 -1px 0 rgba(0,0,0,0.25)}.navbar-inverse .brand:hover,.navbar-inverse .nav>li>a:hover,.navbar-inverse .brand:focus,.navbar-inverse .nav>li>a:focus{color:#fff}.n
 avbar-inverse .brand{color:#999}.navbar-inverse .navbar-text{color:#999}.navbar-inverse .nav>li>a:focus,.navbar-inverse .nav>li>a:hover{color:#fff;background-color:transparent}.navbar-inverse .nav .active>a,.navbar-inverse .nav .active>a:hover,.navbar-inverse .nav .active>a:focus{color:#fff;background-color:#111}.navbar-inverse .navbar-link{color:#999}.navbar-inverse .navbar-link:hover,.navbar-inverse .navbar-link:focus{color:#fff}.navbar-inverse .divider-vertical{border-right-color:#222;border-left-color:#111}.navbar-inverse .nav li.dropdown.open>.dropdown-toggle,.navbar-inverse .nav li.dropdown.active>.dropdown-toggle,.navbar-inverse .nav li.dropdown.open.active>.dropdown-toggle{color:#fff;background-color:#111}.navbar-inverse .nav li.dropdown>a:hover .caret,.navbar-inverse .nav li.dropdown>a:focus .caret{border-top-color:#fff;border-bottom-color:#fff}.navbar-inverse .nav li.dropdown>.dropdown-toggle .caret{border-top-color:#999;border-bottom-color:#999}.navbar-inverse .nav li.dro
 pdown.open>.dropdown-toggle .caret,.navbar-inverse .nav li.dropdown.active>.dropdown-toggle .caret,.navbar-inverse .nav li.dropdown.open.active>.dropdown-toggle .caret{border-top-color:#fff;border-bottom-color:#fff}.navbar-inverse .navbar-search .search-query{color:#fff;background-color:#515151;border-color:#111;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,0.1),0 1px 0 rgba(255,255,255,0.15);-moz-box-shadow:inset 0 1px 2px rgba(0,0,0,0.1),0 1px 0 rgba(255,255,255,0.15);box-shadow:inset 0 1px 2px rgba(0,0,0,0.1),0 1px 0 rgba(255,255,255,0.15);-webkit-transition:none;-moz-transition:none;-o-transition:none;transition:none}.navbar-inverse .navbar-search .search-query:-moz-placeholder{color:#ccc}.navbar-inverse .navbar-search .search-query:-ms-input-placeholder{color:#ccc}.navbar-inverse .navbar-search .search-query::-webkit-input-placeholder{color:#ccc}.navbar-inverse .navbar-search .search-query:focus,.navbar-inverse .navbar-search .search-query.focused{padding:5px 15px;color:#333;te
 xt-shadow:0 1px 0 #fff;background-color:#fff;border:0;outline:0;-webkit-box-shadow:0 0 3px rgba(0,0,0,0.15);-moz-box-shadow:0 0 3px rgba(0,0,0,0.15);box-shadow:0 0 3px rgba(0,0,0,0.15)}.navbar-inverse .btn-navbar{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#0e0e0e;*background-color:#040404;background-image:-moz-linear-gradient(top,#151515,#040404);background-image:-webkit-gradient(linear,0 0,0 100%,from(#151515),to(#040404));background-image:-webkit-linear-gradient(top,#151515,#040404);background-image:-o-linear-gradient(top,#151515,#040404);background-image:linear-gradient(to bottom,#151515,#040404);background-repeat:repeat-x;border-color:#040404 #040404 #000;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff151515',endColorstr='#ff040404',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.navbar-inverse .btn-navbar:hover,.navbar-inverse .btn-navbar:f
 ocus,.navbar-inverse .btn-navbar:active,.navbar-inverse .btn-navbar.active,.navbar-inverse .btn-navbar.disabled,.navbar-inverse .btn-navbar[disabled]{color:#fff;background-color:#040404;*background-color:#000}.navbar-inverse .btn-navbar:active,.navbar-inverse .btn-navbar.active{background-color:#000 \9}.breadcrumb{padding:8px 15px;margin:0 0 20px;list-style:none;background-color:#f5f5f5;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.breadcrumb>li{display:inline-block;*display:inline;text-shadow:0 1px 0 #fff;*zoom:1}.breadcrumb>li>.divider{padding:0 5px;color:#ccc}.breadcrumb>.active{color:#999}.pagination{margin:20px 0}.pagination ul{display:inline-block;*display:inline;margin-bottom:0;margin-left:0;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;*zoom:1;-webkit-box-shadow:0 1px 2px rgba(0,0,0,0.05);-moz-box-shadow:0 1px 2px rgba(0,0,0,0.05);box-shadow:0 1px 2px rgba(0,0,0,0.05)}.pagination ul>li{display:inline}.pagination ul>li>a,.pagination 
 ul>li>span{float:left;padding:4px 12px;line-height:20px;text-decoration:none;background-color:#fff;border:1px solid #ddd;border-left-width:0}.pagination ul>li>a:hover,.pagination ul>li>a:focus,.pagination ul>.active>a,.pagination ul>.active>span{background-color:#f5f5f5}.pagination ul>.active>a,.pagination ul>.active>span{color:#999;cursor:default}.pagination ul>.disabled>span,.pagination ul>.disabled>a,.pagination ul>.disabled>a:hover,.pagination ul>.disabled>a:focus{color:#999;cursor:default;background-color:transparent}.pagination ul>li:first-child>a,.pagination ul>li:first-child>span{border-left-width:1px;-webkit-border-bottom-left-radius:4px;border-bottom-left-radius:4px;-webkit-border-top-left-radius:4px;border-top-left-radius:4px;-moz-border-radius-bottomleft:4px;-moz-border-radius-topleft:4px}.pagination ul>li:last-child>a,.pagination ul>li:last-child>span{-webkit-border-top-right-radius:4px;border-top-right-radius:4px;-webkit-border-bottom-right-radius:4px;border-bottom-rig
 ht-radius:4px;-moz-border-radius-topright:4px;-moz-border-radius-bottomright:4px}.pagination-centered{text-align:center}.pagination-right{text-align:right}.pagination-large ul>li>a,.pagination-large ul>li>span{padding:11px 19px;font-size:17.5px}.pagination-large ul>li:first-child>a,.pagination-large ul>li:first-child>span{-webkit-border-bottom-left-radius:6px;border-bottom-left-radius:6px;-webkit-border-top-left-radius:6px;border-top-left-radius:6px;-moz-border-radius-bottomleft:6px;-moz-border-radius-topleft:6px}.pagination-large ul>li:last-child>a,.pagination-large ul>li:last-child>span{-webkit-border-top-right-radius:6px;border-top-right-radius:6px;-webkit-border-bottom-right-radius:6px;border-bottom-right-radius:6px;-moz-border-radius-topright:6px;-moz-border-radius-bottomright:6px}.pagination-mini ul>li:first-child>a,.pagination-small ul>li:first-child>a,.pagination-mini ul>li:first-child>span,.pagination-small ul>li:first-child>span{-webkit-border-bottom-left-radius:3px;border
 -bottom-left-radius:3px;-webkit-border-top-left-radius:3px;border-top-left-radius:3px;-moz-border-radius-bottomleft:3px;-moz-border-radius-topleft:3px}.pagination-mini ul>li:last-child>a,.pagination-small ul>li:last-child>a,.pagination-mini ul>li:last-child>span,.pagination-small ul>li:last-child>span{-webkit-border-top-right-radius:3px;border-top-right-radius:3px;-webkit-border-bottom-right-radius:3px;border-bottom-right-radius:3px;-moz-border-radius-topright:3px;-moz-border-radius-bottomright:3px}.pagination-small ul>li>a,.pagination-small ul>li>span{padding:2px 10px;font-size:11.9px}.pagination-mini ul>li>a,.pagination-mini ul>li>span{padding:0 6px;font-size:10.5px}.pager{margin:20px 0;text-align:center;list-style:none;*zoom:1}.pager:before,.pager:after{display:table;line-height:0;content:""}.pager:after{clear:both}.pager li{display:inline}.pager li>a,.pager li>span{display:inline-block;padding:5px 14px;background-color:#fff;border:1px solid #ddd;-webkit-border-radius:15px;-moz-b
 order-radius:15px;border-radius:15px}.pager li>a:hover,.pager li>a:focus{text-decoration:none;background-color:#f5f5f5}.pager .next>a,.pager .next>span{float:right}.pager .previous>a,.pager .previous>span{float:left}.pager .disabled>a,.pager .disabled>a:hover,.pager .disabled>a:focus,.pager .disabled>span{color:#999;cursor:default;background-color:#fff}.modal-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040;background-color:#000}.modal-backdrop.fade{opacity:0}.modal-backdrop,.modal-backdrop.fade.in{opacity:.8;filter:alpha(opacity=80)}.modal{position:fixed;top:10%;left:50%;z-index:1050;width:560px;margin-left:-280px;background-color:#fff;border:1px solid #999;border:1px solid rgba(0,0,0,0.3);*border:1px solid #999;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;outline:0;-webkit-box-shadow:0 3px 7px rgba(0,0,0,0.3);-moz-box-shadow:0 3px 7px rgba(0,0,0,0.3);box-shadow:0 3px 7px rgba(0,0,0,0.3);-webkit-background-clip:padding-box;-moz-background-cli
 p:padding-box;background-clip:padding-box}.modal.fade{top:-25%;-webkit-transition:opacity .3s linear,top .3s ease-out;-moz-transition:opacity .3s linear,top .3s ease-out;-o-transition:opacity .3s linear,top .3s ease-out;transition:opacity .3s linear,top .3s ease-out}.modal.fade.in{top:10%}.modal-header{padding:9px 15px;border-bottom:1px solid #eee}.modal-header .close{margin-top:2px}.modal-header h3{margin:0;line-height:30px}.modal-body{position:relative;max-height:400px;padding:15px;overflow-y:auto}.modal-form{margin-bottom:0}.modal-footer{padding:14px 15px 15px;margin-bottom:0;text-align:right;background-color:#f5f5f5;border-top:1px solid #ddd;-webkit-border-radius:0 0 6px 6px;-moz-border-radius:0 0 6px 6px;border-radius:0 0 6px 6px;*zoom:1;-webkit-box-shadow:inset 0 1px 0 #fff;-moz-box-shadow:inset 0 1px 0 #fff;box-shadow:inset 0 1px 0 #fff}.modal-footer:before,.modal-footer:after{display:table;line-height:0;content:""}.modal-footer:after{clear:both}.modal-footer .btn+.btn{margin
 -bottom:0;margin-left:5px}.modal-footer .btn-group .btn+.btn{margin-left:-1px}.modal-footer .btn-block+.btn-block{margin-left:0}.tooltip{position:absolute;z-index:1030;display:block;font-size:11px;line-height:1.4;opacity:0;filter:alpha(opacity=0);visibility:visible}.tooltip.in{opacity:.8;filter:alpha(opacity=80)}.tooltip.top{padding:5px 0;margin-top:-3px}.tooltip.right{padding:0 5px;margin-left:3px}.tooltip.bottom{padding:5px 0;margin-top:3px}.tooltip.left{padding:0 5px;margin-left:-3px}.tooltip-inner{max-width:200px;padding:8px;color:#fff;text-align:center;text-decoration:none;background-color:#000;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.tooltip-arrow{position:absolute;width:0;height:0;border-color:transparent;border-style:solid}.tooltip.top .tooltip-arrow{bottom:0;left:50%;margin-left:-5px;border-top-color:#000;border-width:5px 5px 0}.tooltip.right .tooltip-arrow{top:50%;left:0;margin-top:-5px;border-right-color:#000;border-width:5px 5px 5px 0}.tooltip.
 left .tooltip-arrow{top:50%;right:0;margin-top:-5px;border-left-color:#000;border-width:5px 0 5px 5px}.tooltip.bottom .tooltip-arrow{top:0;left:50%;margin-left:-5px;border-bottom-color:#000;border-width:0 5px 5px}.popover{position:absolute;top:0;left:0;z-index:1010;display:none;max-width:276px;padding:1px;text-align:left;white-space:normal;background-color:#fff;border:1px solid #ccc;border:1px solid rgba(0,0,0,0.2);-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;-webkit-box-shadow:0 5px 10px rgba(0,0,0,0.2);-moz-box-shadow:0 5px 10px rgba(0,0,0,0.2);box-shadow:0 5px 10px rgba(0,0,0,0.2);-webkit-background-clip:padding-box;-moz-background-clip:padding;background-clip:padding-box}.popover.top{margin-top:-10px}.popover.right{margin-left:10px}.popover.bottom{margin-top:10px}.popover.left{margin-left:-10px}.popover-title{padding:8px 14px;margin:0;font-size:14px;font-weight:normal;line-height:18px;background-color:#f7f7f7;border-bottom:1px solid #ebebeb;-webkit-border-r
 adius:5px 5px 0 0;-moz-border-radius:5px 5

<TRUNCATED>

[44/51] [abbrv] [partial] Adding Jinwon's custom RCMET

Posted by jo...@apache.org.
http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/rcmes/storage/.svn/text-base/files.py.svn-base
----------------------------------------------------------------------
diff --git a/src/main/python/rcmes/storage/.svn/text-base/files.py.svn-base b/src/main/python/rcmes/storage/.svn/text-base/files.py.svn-base
new file mode 100755
index 0000000..17fd5e9
--- /dev/null
+++ b/src/main/python/rcmes/storage/.svn/text-base/files.py.svn-base
@@ -0,0 +1,692 @@
+"""
+Module for handling data input files.  Requires PyNIO and Numpy be 
+installed.
+
+This module can easily open NetCDF, HDF and Grib files.  Search the PyNIO
+documentation for a complete list of supported formats.
+"""
+
+from os import path
+
+try:
+    import Nio
+except ImportError:
+    import nio as Nio
+
+import numpy as np
+import numpy.ma as ma
+import sys
+
+from toolkit import process
+from utils import fortranfile
+from utils import misc
+
+
+VARIABLE_NAMES = {'time': ['time', 'times', 'date', 'dates', 'julian'],
+                  'latitude': ['latitude', 'lat', 'lats', 'latitudes'],
+                  'longitude': ['longitude', 'lon', 'lons', 'longitudes']
+                  }
+
+
+def findunique(seq):
+    keys = {}
+    for e in seq:
+        keys[e] = 1
+    return keys.keys()
+
+def getVariableByType(filename, variableType):
+    """
+    Function that will try to return the variable from a file based on a provided
+    parameter type.
+    
+    Input::
+        filename - the file to inspect
+        variableType - time | latitude | longitude
+    
+    Output::
+        variable name OR list of all variables in the file if a single variable
+        name match cannot be found.
+    """
+    try:
+        f = Nio.open_file(filename)
+    except:
+        #print 'PyNio had an issue opening the filename (%s) you provided' % filename
+        print "NIOError:", sys.exc_info()[0]
+        raise
+    
+    variableKeys = f.variables.keys()
+    f.close()
+    variableKeys = [variable.lower() for variable in variableKeys]
+    variableMatch = VARIABLE_NAMES[variableType]
+
+    commonVariables = list(set(variableKeys).intersection(variableMatch)) 
+
+    if len(commonVariables) == 1:
+        return str(commonVariables[0])
+    
+    else:
+        return variableKeys
+
+def getVariableRange(filename, variableName):
+    """
+    Function to return the min and max values of the given variable in
+    the supplied filename.
+   
+    Input::
+        filename - absolute path to a file
+        variableName - variable whose min and max values should be returned
+
+    Output::
+        variableRange - tuple of order (variableMin, variableMax)
+    """
+    try:
+        f = Nio.open_file(filename)
+    except:
+        #print 'PyNio had an issue opening the filename (%s) you provided' % filename
+        print "NIOError:", sys.exc_info()[0]
+        raise
+    
+    varArray = f.variables[variableName][:]
+    return (varArray.min(), varArray.max())
+
+
+def read_data_from_file_list(filelist, myvar, timeVarName, latVarName, lonVarName):
+    '''
+    Read in data from a list of model files into a single data structure
+   
+    Input:
+       filelist - list of filenames (including path)
+       myvar    - string containing name of variable to load in (as it appears in file)
+    Output:
+       lat, lon - 2D array of latitude and longitude values
+       timestore    - list of times
+       t2store  - numpy array containing data from all files    
+   
+     NB. originally written specific for WRF netCDF output files
+         modified to make more general (Feb 2011)
+   
+      Peter Lean July 2010 
+    '''
+
+    filelist.sort()
+    filename = filelist[0]
+    # Crash nicely if 'filelist' is zero length
+    """TODO:  Throw Error instead via try Except"""
+    if len(filelist) == 0:
+        print 'Error: no files have been passed to read_data_from_file_list()'
+        sys.exit()
+
+    # Open the first file in the list to:
+    #    i) read in lats, lons
+    #    ii) find out how many timesteps in the file 
+    #        (assume same ntimes in each file in list)
+    #     -allows you to create an empty array to store variable data for all times
+    tmp = Nio.open_file(filename)
+    latsraw = tmp.variables[latVarName][:]
+    lonsraw = tmp.variables[lonVarName][:]
+    lonsraw[lonsraw > 180] = lonsraw[lonsraw > 180] - 360.  # convert to -180,180 if necessary
+
+    """TODO:  Guard against case where latsraw and lonsraw are not the same dim?"""
+   
+    if(latsraw.ndim == 1):
+        lon, lat = np.meshgrid(lonsraw, latsraw)
+    if(latsraw.ndim == 2):
+        lon = lonsraw
+        lat = latsraw
+
+    timesraw = tmp.variables[timeVarName]
+    ntimes = len(timesraw)
+    
+    print 'Lats and lons read in for first file in filelist'
+
+    # Create a single empty masked array to store model data from all files
+    t2store = ma.zeros((ntimes * len(filelist), len(lat[:, 0]), len(lon[0, :])))
+    timestore = ma.zeros((ntimes * len(filelist))) 
+    
+    # Now load in the data for real
+    #  NB. no need to reload in the latitudes and longitudes -assume invariant
+    i = 0
+    timesaccu = 0 # a counter for number of times stored so far in t2store 
+    #  NB. this method allows for missing times in data files 
+    #      as no assumption made that same number of times in each file...
+
+
+    for ifile in filelist:
+
+        #print 'Loading data from file: ',filelist[i]
+        f = Nio.open_file(ifile)
+        t2raw = f.variables[myvar][:]
+        timesraw = f.variables[timeVarName]
+        time = timesraw[:]
+        ntimes = len(time)
+        print 'file= ', i, 'ntimes= ', ntimes, filelist[i]
+        print 't2raw shape: ', t2raw.shape
+        
+        # Flatten dimensions which needn't exist, i.e. level 
+        #   e.g. if for single level then often data have 4 dimensions, when 3 dimensions will do.
+        #  Code requires data to have dimensions, (time,lat,lon)
+        #    i.e. remove level dimensions
+        # Remove 1d axis from the t2raw array
+        # Example: t2raw.shape == (365, 180, 360 1) <maps to (time, lat, lon, height)>
+        # After the squeeze you will be left with (365, 180, 360) instead
+        t2tmp = t2raw.squeeze()
+        # Nb. if this happens to be data for a single time only, then we just flattened it by accident
+        #     lets put it back... 
+        if t2tmp.ndim == 2:
+            t2tmp = np.expand_dims(t2tmp, 0)
+
+        t2store[timesaccu + np.arange(ntimes), :, :] = t2tmp[:, :, :]
+        timestore[timesaccu + np.arange(ntimes)] = time
+        timesaccu = timesaccu + ntimes
+        f.close()
+        i += 1 
+      
+    print 'Data read in successfully with dimensions: ', t2store.shape
+    
+    # TODO: search for duplicated entries (same time) and remove duplicates.
+    # Check to see if number of unique times == number of times, if so then no problem
+
+    if(len(np.unique(timestore)) != len(np.where(timestore != 0)[0].view())):
+        print 'WARNING: Possible duplicated times'
+
+    # Decode model times into python datetime objects. Note: timestore becomes a list (no more an array) here
+    timestore, _ = process.getModelTimes(filename, timeVarName)
+    
+    data_dict = {}
+    data_dict['lats'] = lat
+    data_dict['lons'] = lon
+    data_dict['times'] = timestore
+    data_dict['data'] = t2store
+    #return lat, lon, timestore, t2store
+    return data_dict
+
+def select_var_from_file(myfile, fmt='not set'):
+    '''
+     Routine to act as user interface to allow users to select variable of interest from a file.
+     
+      Input:
+         myfile - filename
+         fmt - (optional) specify fileformat for PyNIO if filename suffix is non-standard
+    
+      Output:
+         myvar - variable name in file
+    
+        Peter Lean  September 2010
+    '''
+
+    print fmt
+    
+    if fmt == 'not set':
+        f = Nio.open_file(myfile)
+    
+    if fmt != 'not set':
+        f = Nio.open_file(myfile, format=fmt)
+    
+    keylist = f.variables.keys()
+    
+    i = 0
+    for v in keylist:
+        print '[', i, '] ', f.variables[v].long_name, ' (', v, ')'
+        i += 1
+
+    user_selection = raw_input('Please select variable : [0 -' + str(i - 1) + ']  ')
+    
+    myvar = keylist[int(user_selection)]
+    
+    return myvar
+
+def select_var_from_wrf_file(myfile):
+    '''
+     Routine to act as user interface to allow users to select variable of interest from a wrf netCDF file.
+     
+      Input:
+         myfile - filename
+    
+      Output:
+         mywrfvar - variable name in wrf file
+    
+        Peter Lean  September 2010
+    '''
+
+    f = Nio.open_file(myfile, format='nc')
+    
+    keylist = f.variables.keys()
+
+    i = 0
+    for v in keylist:
+        try:
+            print '[', i, '] ', f.variables[v].description, ' (', v, ')'
+        except:
+            print ''
+
+        i += 1
+    
+    user_selection = raw_input('Please select WRF variable : [0 -' + str(i - 1) + ']  ')
+    
+    mywrfvar = keylist[int(user_selection)]
+    
+    return mywrfvar
+
+def read_lolaT_from_file(filename, latVarName, lonVarName, timeVarName, file_type):
+    """
+    Function that will return lat, lon, and time arrays
+    
+    Input::
+        filename - the file to inspect
+        latVarName - name of the Latitude Variable
+        lonVarName - name of the Longitude Variable
+        timeVarName - name of the Time Variable
+        fileType = type of file we are trying to parse
+    
+    Output::
+        lat - MESH GRID of Latitude values with shape (nx, ny)
+        lon - MESH GRID of Longitude values with shape (nx, ny)
+        timestore - Python list of Datetime objects
+        
+        MESHGRID docs: http://docs.scipy.org/doc/numpy/reference/generated/numpy.meshgrid.html
+        
+    """
+
+    tmp = Nio.open_file(filename, format=file_type)
+    lonsraw = tmp.variables[lonVarName][:]
+    latsraw = tmp.variables[latVarName][:]
+    lonsraw[lonsraw > 180] = lonsraw[lonsraw > 180] - 360.  # convert to -180,180 if necessary
+    if(latsraw.ndim == 1):
+        lon, lat = np.meshgrid(lonsraw, latsraw)
+    if(latsraw.ndim == 2):
+        lon = lonsraw
+        lat = latsraw
+    timestore, _ = process.getModelTimes(filename, timeVarName)
+    print '  read_lolaT_from_file: Lats, lons and times read in for the model domain'
+    return lat, lon, timestore
+
+def read_data_from_one_file(ifile, myvar, timeVarName, lat, file_type):
+    ##################################################################################
+    # Read in data from one file at a time
+    # Input:   filelist - list of filenames (including path)
+    #          myvar    - string containing name of variable to load in (as it appears in file)
+    # Output:  lat, lon - 2D array of latitude and longitude values
+    #          times    - list of times
+    #          t2store  - numpy array containing data from all files    
+    # Modified from read_data_from_file_list to read data from multiple models into a 4-D array
+    # 1. The code now processes model data that completely covers the 20-yr period. Thus,
+    #    all model data must have the same time levels (ntimes). Unlike in the oroginal, ntimes
+    #    is fixed here.
+    # 2. Because one of the model data exceeds 240 mos (243 mos), the model data must be
+    #    truncated to the 240 mons using the ntimes determined from the first file.
+    ##################################################################################
+    f = Nio.open_file(ifile)
+    try:
+        varUnit = f.variables[myvar].units.upper()
+    except:
+        varUnit = raw_input('Enter the model variable unit: \n> ').upper()
+    t2raw = f.variables[myvar][:]
+    t2tmp = t2raw.squeeze()
+    if t2tmp.ndim == 2:
+        t2tmp = np.expand_dims(t2tmp, 0)
+    t2tmp = t2tmp
+    f.close()
+    print '  success read_data_from_one_file: VarName=', myvar, ' Shape(Full)= ', t2tmp.shape, ' Unit= ', varUnit
+    timestore = process.decode_model_timesK(ifile, timeVarName, file_type)
+    return timestore, t2tmp, varUnit
+
+def findTimeVariable(filename):
+    """
+     Function to find what the time variable is called in a model file.
+        Input::
+            filename - file to crack open and check for a time variable
+        Output::
+            timeName - name of the input file's time variable
+            variableNameList - list of variable names from the input filename
+    """
+    try:
+        f = Nio.open_file(filename, mode='r')
+    except:
+        print("Unable to open '%s' to try and read the Time variable" % filename)
+        raise
+
+    variableNameList = f.variables.keys()
+    # convert all variable names into lower case
+    varNameListLowerCase = [x.lower() for x in variableNameList]
+
+    # Use "set" types for finding common variable name from in the file and from the list of possibilities
+    possibleTimeNames = set(['time', 'times', 'date', 'dates', 'julian'])
+    
+    # Use the sets to find the intersection where variable names are in possibleNames
+    timeNameSet = possibleTimeNames.intersection(varNameListLowerCase)
+    
+    if len(timeNameSet) == 0:
+        print("Unable to autodetect the Time Variable Name in the '%s'" % filename)
+        timeName = misc.askUserForVariableName(variableNameList, targetName ="Time")
+    
+    else:
+        timeName = timeNameSet.pop()
+    
+    return timeName, variableNameList
+
+
+def findLatLonVarFromFile(filename):
+    """
+    Function to find what the latitude and longitude variables are called in a model file.
+    
+    Input:: 
+        -filename 
+    Output::
+        -latVarName
+        -lonVarName
+        -latMin 
+        -latMax
+        -lonMin
+        -lonMax
+    """
+    try:
+        f = Nio.open_file(filename, mode='r')
+    except:
+        print("Unable to open '%s' to try and read the Latitude and Longitude variables" % filename)
+        raise
+
+    variableNameList = f.variables.keys()
+    # convert all variable names into lower case
+    varNameListLowerCase = [x.lower() for x in variableNameList]
+
+    # Use "set" types for finding common variable name from in the file and from the list of possibilities
+    possibleLatNames = set(['latitude', 'lat', 'lats', 'latitudes'])
+    possibleLonNames = set(['longitude', 'lon', 'lons', 'longitudes'])
+    
+    # Use the sets to find the intersection where variable names are in possibleNames
+    latNameSet = possibleLatNames.intersection(varNameListLowerCase)
+    lonNameSet = possibleLonNames.intersection(varNameListLowerCase)
+    
+    if len(latNameSet) == 0 or len(lonNameSet) == 0:
+        print("Unable to autodetect Latitude and/or Longitude values in the file")
+        latName = misc.askUserForVariableName(variableNameList, targetName ="Latitude")
+        lonName = misc.askUserForVariableName(variableNameList, targetName ="Longitude")
+    
+    else:
+        latName = latNameSet.pop()
+        lonName = lonNameSet.pop()
+    
+    lats = np.array(f.variables[latName][:])
+    lons = np.array(f.variables[lonName][:])
+    
+    latMin = lats.min()
+    latMax = lats.max()
+    
+    # Convert the lons from 0:360 into -180:180
+    lons[lons > 180] = lons[lons > 180] - 360.
+    lonMin = lons.min()
+    lonMax = lons.max()
+
+    return latName, lonName, latMin, latMax, lonMin, lonMax
+
+
+def read_data_from_file_list_K(filelist, myvar, timeVarName, latVarName, lonVarName, file_type):
+    ##################################################################################
+    # Read in data from a list of model files into a single data structure
+    # Input:   filelist - list of filenames (including path)
+    #          myvar    - string containing name of variable to load in (as it appears in file)
+    # Output:  lat, lon - 2D array of latitude and longitude values
+    #          times    - list of times
+    #          t2store  - numpy array containing data from all files    
+    # Modified from read_data_from_file_list to read data from multiple models into a 4-D array
+    # 1. The code now processes model data that completely covers the 20-yr period. Thus,
+    #    all model data must have the same time levels (ntimes). Unlike in the oroginal, ntimes
+    #    is fixed here.
+    # 2. Because one of the model data exceeds 240 mos (243 mos), the model data must be
+    #    truncated to the 240 mons using the ntimes determined from the first file.
+    ##################################################################################
+    filelist.sort()
+    nfiles = len(filelist)
+    # Crash nicely if 'filelist' is zero length
+    if nfiles == 0:
+        print 'Error: no files have been passed to read_data_from_file_list(): Exit'
+        sys.exit()
+
+    # Open the first file in the list to:
+    #    i)  read in lats, lons
+    #    ii) find out how many timesteps in the file (assume same ntimes in each file in list)
+    #     -allows you to create an empty array to store variable data for all times
+    tmp = Nio.open_file(filelist[0], format=file_type)
+    latsraw = tmp.variables[latVarName][:]
+    lonsraw = tmp.variables[lonVarName][:]
+    lonsraw[lonsraw > 180] = lonsraw[lonsraw > 180] - 360.  # convert to -180,180 if necessary
+    if(latsraw.ndim == 1):
+        lon, lat = np.meshgrid(lonsraw, latsraw)
+    if(latsraw.ndim == 2):
+        lon = lonsraw; lat = latsraw
+    
+    timesraw = tmp.variables[timeVarName]
+    ntimes = len(timesraw); nygrd = len(lat[:, 0]); nxgrd = len(lon[0, :])
+    
+    print 'Lats and lons read in for first file in filelist'
+
+    # Create a single empty masked array to store model data from all files
+    #t2store = ma.zeros((ntimes*nfiles,nygrd,nxgrd))
+    t2store = ma.zeros((nfiles, ntimes, nygrd, nxgrd))
+    #timestore=ma.zeros((ntimes*nfiles)) 
+    
+    ## Now load in the data for real
+    ##  NB. no need to reload in the latitudes and longitudes -assume invariant
+    #timesaccu=0 # a counter for number of times stored so far in t2store 
+    #  NB. this method allows for missing times in data files 
+    #      as no assumption made that same number of times in each file...
+
+    i = 0
+    for ifile in filelist:
+        #print 'Loading data from file: ',filelist[i]
+        f = Nio.open_file(ifile)
+        t2raw = f.variables[myvar][:]
+        timesraw = f.variables[timeVarName]
+        time = timesraw[0:ntimes]
+        #ntimes=len(time)
+        #print 'file= ',i,'ntimes= ',ntimes,filelist[i]
+        ## Flatten dimensions which needn't exist, i.e. level 
+        ##   e.g. if for single level then often data have 4 dimensions, when 3 dimensions will do.
+        ##  Code requires data to have dimensions, (time,lat,lon)
+        ##    i.e. remove level dimensions
+        t2tmp = t2raw.squeeze()
+        ## Nb. if data happen to be for a single time, we flattened it by accident; lets put it back... 
+        if t2tmp.ndim == 2:
+            t2tmp = np.expand_dims(t2tmp, 0)
+        #t2store[timesaccu+np.arange(ntimes),:,:]=t2tmp[0:ntimes,:,:]
+        t2store[i, 0:ntimes, :, :] = t2tmp[0:ntimes, :, :]
+        #timestore[timesaccu+np.arange(ntimes)]=time
+        #timesaccu=timesaccu+ntimes
+        f.close()
+        i += 1 
+
+    print 'Data read in successfully with dimensions: ', t2store.shape
+    
+    # Decode model times into python datetime objects. Note: timestore becomes a list (no more an array) here
+    ifile = filelist[0]
+    timestore, _ = process.getModelTimes(ifile, timeVarName)
+    
+    return lat, lon, timestore, t2store
+
+def find_latlon_ranges(filelist, lat_var_name, lon_var_name):
+    # Function to return the latitude and longitude ranges of the data in a file,
+    # given the identifying variable names.
+    #
+    #    Input:
+    #            filelist - list of filenames (data is read in from first file only)
+    #            lat_var_name - variable name of the 'latitude' variable
+    #            lon_var_name - variable name of the 'longitude' variable
+    #
+    #    Output:
+    #            latMin, latMax, lonMin, lonMax - self explanatory
+    #
+    #                    Peter Lean      March 2011
+    
+    filename = filelist[0]
+    
+    try:
+        f = Nio.open_file(filename)
+        
+        lats = f.variables[lat_var_name][:]
+        latMin = lats.min()
+        latMax = lats.max()
+        
+        lons = f.variables[lon_var_name][:]
+        lons[lons > 180] = lons[lons > 180] - 360.
+        lonMin = lons.min()
+        lonMax = lons.max()
+        
+        return latMin, latMax, lonMin, lonMax
+
+    except:
+        print 'Error: there was a problem with finding the latitude and longitude ranges in the file'
+        print '       Please check that you specified the filename, and variable names correctly.'
+        
+        sys.exit()
+
+def writeBN_lola(fileName, lons, lats):
+    # write a binary data file that include longitude (1-d) and latitude (1-d) values
+    
+    F = fortranfile.FortranFile(fileName, mode='w')
+    ngrdY = lons.shape[0]; ngrdX = lons.shape[1]
+    tmpDat = ma.zeros(ngrdX); tmpDat[:] = lons[0, :]; F.writeReals(tmpDat)
+    tmpDat = ma.zeros(ngrdY); tmpDat[:] = lats[:, 0]; F.writeReals(tmpDat)
+    # release temporary arrays
+    tmpDat = 0
+    F.close()
+
+def writeBNdata(fileName, numOBSs, numMDLs, nT, ngrdX, ngrdY, numSubRgn, obsData, mdlData, obsRgnAvg, mdlRgnAvg):
+    #(fileName,maskOption,numOBSs,numMDLs,nT,ngrdX,ngrdY,numSubRgn,obsData,mdlData,obsRgnAvg,mdlRgnAvg):
+    # write spatially- and regionally regridded data into a binary data file
+    missing = -1.e26
+    F = fortranfile.FortranFile(fileName, mode='w')
+    # construct a data array to replace mask flag with a missing value (missing=-1.e12) for printing
+    data = ma.zeros((nT, ngrdY, ngrdX))
+    for m in np.arange(numOBSs):
+        data[:, :, :] = obsData[m, :, :, :]; msk = data.mask
+        for n in np.arange(nT):
+            for j in np.arange(ngrdY):
+                for i in np.arange(ngrdX):
+                    if msk[n, j, i]: data[n, j, i] = missing
+
+        # write observed data. allowed to write only one row at a time
+        tmpDat = ma.zeros(ngrdX)
+        for n in np.arange(nT):
+            for j in np.arange(ngrdY):
+                tmpDat[:] = data[n, j, :]
+                F.writeReals(tmpDat)
+
+    # write model data (dep. on the number of models).
+    for m in np.arange(numMDLs):
+        data[:, :, :] = mdlData[m, :, :, :]
+        msk = data.mask
+        for n in np.arange(nT):
+            for j in np.arange(ngrdY):
+                for i in np.arange(ngrdX):
+                    if msk[n, j, i]:
+                        data[n, j, i] = missing
+
+        for n in np.arange(nT):
+            for j in np.arange(ngrdY):
+                tmpDat[:] = data[n, j, :]
+                F.writeReals(tmpDat)
+
+    data = 0     # release the array allocated for data
+    # write data in subregions
+    if numSubRgn > 0:
+        print 'Also included are the time series of the means over ', numSubRgn, ' areas from obs and model data'
+        tmpDat = ma.zeros(nT); print numSubRgn
+        for m in np.arange(numOBSs):
+            for n in np.arange(numSubRgn):
+                tmpDat[:] = obsRgnAvg[m, n, :]
+                F.writeReals(tmpDat)
+        for m in np.arange(numMDLs):
+            for n in np.arange(numSubRgn):
+                tmpDat[:] = mdlRgnAvg[m, n, :]
+                F.writeReals(tmpDat)
+    tmpDat = 0     # release the array allocated for tmpDat
+    F.close()
+
+def writeNCfile(fileName, numSubRgn, lons, lats, obsData, mdlData, obsRgnAvg, mdlRgnAvg, obsList, mdlList, subRegions):
+    # write an output file of variables up to 3 dimensions
+    # fileName: the name of the output data file
+    # numSubRgn  : the number of subregions
+    # lons[ngrdX]: longitude
+    # lats[ngrdY]: latitudes
+    # obsData[nT,ngrdY,ngrdX]: the obs time series of the entire model domain
+    # mdlData[numMDLs,nT,ngrdY,ngrdX]: the mdltime series of the entire model domain
+    # obsRgnAvg[numSubRgn,nT]: the obs time series for the all subregions
+    # mdlRgnAvg[numMDLs,numSubRgn,nT]: the mdl time series for the all subregions
+    dimO = obsData.shape[0]      # the number of obs data
+    dimM = mdlData.shape[0]      # the number of mdl data
+    dimT = mdlData.shape[1]      # the number of time levels
+    dimY = mdlData.shape[2]      # y-dimension
+    dimX = mdlData.shape[3]      # x-dimension
+    dimR = obsRgnAvg.shape[1]    # the number of subregions
+    f = Nio.open_file(fileName, mode='w', format='nc')
+    print mdlRgnAvg.shape, dimM, dimR, dimT
+    #create global attributes
+    f.globalAttName = ''
+    # create dimensions
+    print 'Creating Dimensions within the NetCDF Object...'
+    f.create_dimension('unity', 1)
+    f.create_dimension('time', dimT)
+    f.create_dimension('west_east', dimX)
+    f.create_dimension('south_north', dimY)
+    f.create_dimension('obs', dimO)
+    f.create_dimension('models', dimM)
+        
+    # create the variable (real*4) to be written in the file
+    print 'Creating Variables...'
+    f.create_variable('lon', 'd', ('south_north', 'west_east'))
+    f.create_variable('lat', 'd', ('south_north', 'west_east'))
+    f.create_variable('oDat', 'd', ('obs', 'time', 'south_north', 'west_east'))
+    f.create_variable('mDat', 'd', ('models', 'time', 'south_north', 'west_east'))
+    
+    if subRegions:
+        f.create_dimension('regions', dimR)
+        f.create_variable('oRgn', 'd', ('obs', 'regions', 'time'))
+        f.create_variable('mRgn', 'd', ('models', 'regions', 'time'))
+        f.variables['oRgn'].varAttName = 'Observation time series: Subregions'
+        f.variables['mRgn'].varAttName = 'Model time series: Subregions'
+
+    loadDataIntoNetCDF(f, obsList, obsData, 'Observation')
+    print 'Loaded the Observations into the NetCDF'
+
+    loadDataIntoNetCDF(f, mdlList, mdlData, 'Model')
+
+    # create attributes and units for the variable
+    print 'Creating Attributes and Units...'
+    f.variables['lon'].varAttName = 'Longitudes'
+    f.variables['lon'].varUnit = 'degrees East'
+    f.variables['lat'].varAttName = 'Latitudes'
+    f.variables['lat'].varUnit = 'degrees North'
+    f.variables['oDat'].varAttName = 'Observation time series: entire domain'
+    f.variables['mDat'].varAttName = 'Model time series: entire domain'
+
+    # assign the values to the variable and write it
+    f.variables['lon'][:, :] = lons
+    f.variables['lat'][:, :] = lats
+    if subRegions:
+        f.variables['oRgn'][:, :, :] = obsRgnAvg
+        f.variables['mRgn'][:, :, :] = mdlRgnAvg
+
+    f.close()
+
+def loadDataIntoNetCDF(fileObject, datasets, dataArray, dataType):
+    """
+    Input::
+        fileObject - PyNIO file object data will be loaded into
+        datasets - List of dataset names
+        dataArray - Multi-dimensional array of data to be loaded into the NetCDF file
+        dataType - String with value of either 'Model' or 'Observation'
+    Output::
+        No return value.  PyNIO file object is updated in place
+    """
+    datasetCount = 0
+    for dataset in datasets:
+        if dataType.lower() == 'observation':
+            datasetName = dataset.replace(' ','')
+        elif dataType.lower() == 'model':
+            datasetName = path.splitext(path.basename(dataset))[0]
+        print "Creating variable %s" % datasetName
+        fileObject.create_variable(datasetName, 'd', ('time', 'south_north', 'west_east'))
+        fileObject.variables[datasetName].varAttName = 'Obseration time series: entire domain'
+        print 'Loading values into %s' % datasetName
+        fileObject.variables[datasetName].assign_value(dataArray[datasetCount,:,:,:])
+        datasetCount += 1

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/rcmes/storage/.svn/text-base/rcmed.py.svn-base
----------------------------------------------------------------------
diff --git a/src/main/python/rcmes/storage/.svn/text-base/rcmed.py.svn-base b/src/main/python/rcmes/storage/.svn/text-base/rcmed.py.svn-base
new file mode 100755
index 0000000..f538bc1
--- /dev/null
+++ b/src/main/python/rcmes/storage/.svn/text-base/rcmed.py.svn-base
@@ -0,0 +1,113 @@
+'''This is a collection of functions that provide the single interface to the
+rcmed.  Initial design will includes several functions to interact with the 
+available parameters within rcmed and their metadata.
+
+Future work includes rolling the rcmed querying code into this module as well.
+'''
+
+import requests, json
+
+paramUri = 'http://rcmes.jpl.nasa.gov/bottle/rcmed/param.json'
+
+def getParams(uri=paramUri):
+    '''This will return all of the parameters from the database as
+    a list of dictionaries.
+    
+    If the database is not available, then the method will return None'''
+    # Use a get request to call the Web Service
+    try:
+        httpRequest = requests.get(uri)
+    except:
+        print "HTTPRequest failed.  Bottle WebServer is offline"
+        raise
+    # TODO Check the request status code if it is 400 or 500 range then 
+    #      return None
+    # if the status code is 200 then return the request.text's param list
+    # http_request.status_code is an int we can inspect
+    paramDict = json.loads(httpRequest.text)
+    paramList = paramDict['param']
+    
+    filteredParams = []
+    # Filter list to remove missing data values
+    for param in paramList:
+        paramGood = True
+        for key, value in param.iteritems():
+            if value == None:
+                paramGood = False
+        
+        if paramGood:
+            filteredParams.append(param)
+        else:
+            filteredParams.append(param)
+    
+    
+    return filteredParams
+
+
+
+#class Parameter(object):
+#    
+#    def __init__(self):
+#        self.param_query_uri = 'http://some.url'
+#        self.param_list = self.param_metadata()
+#        
+#    def param_metadata(self):
+#        '''This method will return a list of python dict's.  Each dict will 
+#        contain a complete record for each parameter from rcmed'''
+#        # 1.  Query the Parameters Metadata Endpoint using param_query_uri
+#        # 2.  Parse the returned data and re-format into a dict
+#        # 3.  define self.para_met_dict
+#        test_list = [{"id":12,
+#                      "description":"ERA Dataset 2 Metre Temperature",
+#                      "type":'temp'
+#                      },
+#                      {"id":13,
+#                       "description":"ERA Dataset 2 Metre Dewpoint Temperature",
+#                       'type':'temp'
+#                       },
+#                      {"id":14,
+#                       "description":"TRMM Dataset HRF parameter",
+#                       'type':'hrf'
+#                        }
+#                     ]
+#        print "self.param_met_dict has been created"
+#        return test_list
+#    
+#    def get_param_by_id(self, id):
+#        '''This will take in a parameter id and return a single dict.  Can we 
+#        safely assume we will always hold a unique parameter id?  - Currently
+#        this is True'''
+#        for p in self.param_list:
+#            if p['id'] == id: 
+#                return p
+#            else: 
+#                pass
+#    
+#    def get_params_by_type(self, type):
+#        '''This will take in a parameter type like precip, temp, pressure, etc.
+#        and will return a list of all the params that are of the given type.'''
+#        param_list = [] #empty list to collect the param dicts
+#        for p in self.param_list:
+#            if p['type'] == type:
+#                param_list.append(p)
+#            else:
+#                pass
+#        return param_list
+#
+#
+#class ObsData(object):
+#    
+#    def __init__(self):
+#        self.query_url = 'http://rcmes/rcmed....'  #can we merely insert the query criteria into the url attribute?
+#        self.param_id = 6
+#        self.dataset_id = 1
+#        self.lat_range = [25.4,55.0]
+#        self.lon_range = [0.0,10.7]
+#        self.time_range = [start,end]
+#        
+#    def set_param(self, param_dict):
+#        self.param_id = param_dict['id']
+#        self.dataset_id = null
+#        # look up the dataset id using the parameter id and set it
+#        p = Parameter.get_param_by_id(id)
+        
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/rcmes/storage/__init__.py
----------------------------------------------------------------------
diff --git a/src/main/python/rcmes/storage/__init__.py b/src/main/python/rcmes/storage/__init__.py
new file mode 100755
index 0000000..a1d4f62
--- /dev/null
+++ b/src/main/python/rcmes/storage/__init__.py
@@ -0,0 +1,2 @@
+"""This Package is used to handle various forms of data storage from opening
+files to accessing the RCMED and returning data in the form of numpy arrays"""
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/rcmes/storage/__init__.pyc
----------------------------------------------------------------------
diff --git a/src/main/python/rcmes/storage/__init__.pyc b/src/main/python/rcmes/storage/__init__.pyc
new file mode 100644
index 0000000..1facbc9
Binary files /dev/null and b/src/main/python/rcmes/storage/__init__.pyc differ

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/rcmes/storage/db.py
----------------------------------------------------------------------
diff --git a/src/main/python/rcmes/storage/db.py b/src/main/python/rcmes/storage/db.py
new file mode 100755
index 0000000..22a1dfd
--- /dev/null
+++ b/src/main/python/rcmes/storage/db.py
@@ -0,0 +1,359 @@
+#
+#  Licensed to the Apache Software Foundation (ASF) under one or more
+#  contributor license agreements.  See the NOTICE file distributed with
+#  this work for additional information regarding copyright ownership.
+#  The ASF licenses this file to You under the Apache License, Version 2.0
+#  (the "License"); you may not use this file except in compliance with
+#  the License.  You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+#  Unless required by applicable law or agreed to in writing, software
+#  distributed under the License is distributed on an "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#  See the License for the specific language governing permissions and
+#  limitations under the License.
+#
+"""Collection of functions used to interface with the database and to create netCDF file
+"""
+import os
+import urllib2
+import re
+import numpy as np
+import numpy.ma as ma
+import json
+import netCDF4
+
+from classes import RCMED
+from toolkit import process
+from datetime import timedelta ,datetime
+from calendar import monthrange
+
+def reorderXYT(lons, lats, times, values):
+    # Re-order values in values array such that when reshaped everywhere is where it should be
+    #  (as DB doesn't necessarily return everything in order)
+    order = np.lexsort((lons, lats, times))
+    counter = 0
+    sortedValues = np.zeros_like(values)
+    sortedLats = np.zeros_like(lats)
+    sortedLons = np.zeros_like(lons)
+    for i in order:
+        sortedValues[counter] = values[i]
+        sortedLats[counter] = lats[i]
+        sortedLons[counter] = lons[i]
+        counter += 1
+    
+    return sortedValues, sortedLats, sortedLons
+
+def findUnique(seq, idfun=None):
+    """
+     Function to find unique values (used in construction of unique datetime list)
+     NB. order preserving
+     Input: seq  - a list of randomly ordered values
+     Output: result - list of ordered values
+    """
+    if idfun is None:
+        def idfun(x): 
+            return x
+
+    seen = {};
+    result = []
+    
+    for item in seq:
+        marker = idfun(item)
+        # in old Python versions:
+        # if seen.has_key(marker)
+        # but in new ones:
+        if marker in seen: continue
+        seen[marker] = 1
+        result.append(item)
+    return result
+
+def get_param_info(url):
+
+    '''
+    This function will get the general information by given URL from the parameter table.
+    '''
+    url = url + "&info=yes"
+    result = urllib2.urlopen(url)
+    datastring = result.read()
+    datastring=json.loads(datastring)
+    database=datastring["database"]
+    timestep=datastring["timestep"]
+    realm=datastring["realm"]
+    instrument=datastring["instrument"]
+    start_date=datastring["start_date"]
+    end_date=datastring["end_date"]
+    unit=datastring["units"]
+    
+    return database, timestep, realm, instrument, start_date, end_date, unit
+
+def get_data(url):
+    
+    '''
+    This function will get the url, query from database and will return datapoints' latitude, longitude, level, time and value.
+    '''
+
+    result = urllib2.urlopen(url)
+    datastring = result.read()    
+    d = re.search('data: \r\n', datastring)
+    data = datastring[d.end():len(datastring)]
+    
+    # To create a list of all datapoints
+    data=data.split('\r\n')    
+            
+    latitudes = []
+    longitudes = []
+    levels = []
+    values = []
+    timestamps = []
+    
+    # To make a series of lists from datapoints
+    for i in range(len(data)-1):  # Because the last row is empty, "len(data)-1" is used.
+        row=data[i].split(',')
+        latitudes.append(np.float32(row[0]))
+        longitudes.append(np.float32(row[1]))
+        levels.append(np.float32(row[2]))
+        # timestamps are strings so we will leave them alone for now
+        timestamps.append(row[3])
+        values.append(np.float32(row[4]))
+        
+    return latitudes, longitudes, levels, values, timestamps
+    
+
+def create_netCDF(latitudes, longitudes, levels, values, timestamps, database, latMin, latMax, lonMin, lonMax, startTime, endTime, unit, netCD_fileName):
+    
+    '''
+    This function will generate netCDF files.
+    '''
+        
+    # To generate netCDF file from database
+    netcdf =  netCDF4.Dataset(netCD_fileName,mode='w')
+    string="The netCDF file for parameter: " + database + ", latMin: " + str(latMin) + ", latMax: " + str(latMax) + ", lonMin: " + str(lonMin) + ", lonMax: " + str(lonMax) + " startTime: " + str(startTime) + " and endTime: " + str(endTime) + "."
+    netcdf.globalAttName = str(string)
+    netcdf.createDimension('dim', len(latitudes))
+    latitude = netcdf.createVariable('lat', 'd', ('dim',))
+    longitude = netcdf.createVariable('lon', 'd', ('dim',))
+    level = netcdf.createVariable('lev', 'd', ('dim',))
+    time = netcdf.createVariable('time', 'd', ('dim',))
+    value = netcdf.createVariable('value', 'd', ('dim',))
+    
+    netcdf.variables['lat'].varAttName = 'latitude'
+    netcdf.variables['lat'].units = 'degrees_north'
+    netcdf.variables['lon'].varAttName = 'longitude'
+    netcdf.variables['lon'].units = 'degrees_east'
+    netcdf.variables['time'].varAttName = 'time'
+    netcdf.variables['time'].units = 'hours since ' + str(startTime)
+    netcdf.variables['value'].varAttName = 'value'
+    netcdf.variables['value'].units = str(unit)
+    netcdf.variables['lev'].varAttName = 'level'
+    netcdf.variables['lev'].units = 'hPa'
+
+    hours=[]
+    timeFormat = "%Y-%m-%d %H:%M:%S"
+    base_date=startTime
+    # To convert the date to hours 
+    for t in timestamps:
+        date=datetime.strptime(t, timeFormat)
+        diff=date-base_date
+        hours.append(diff.days*24)
+        
+    latitude[:]=latitudes[:]
+    longitude[:]=longitudes[:]
+    level[:]=levels[:]
+    time[:]=hours[:]
+    value[:]=values[:]
+    netcdf.close()
+        
+def read_netcdf(netCD_fileName):
+    
+    '''
+    This function will read the existed netCDF file, convert the hours from netCDF time variable
+    and return latitudes, longitudes, levels, times and values.
+    '''
+    # To use the created netCDF file
+    netcdf = netCDF4.Dataset(netCD_fileName , mode='r')
+    # To get all data from netCDF file
+    latitudes = netcdf.variables['lat'][:]
+    longitudes = netcdf.variables['lon'][:]
+    levels = netcdf.variables['lev'][:]
+    hours = netcdf.variables['time'][:]
+    values = ma.array(netcdf.variables['value'][:])
+    
+    # To get the base date
+    time_unit=netcdf.variables['time'].units.encode()
+    time_unit=time_unit.split(' ')
+    base_date=time_unit[2] + " " + time_unit[3]
+    
+    netcdf.close()
+    
+    timeFormat = "%Y-%m-%d %H:%M:%S"
+    
+    # Because time in netCDF file is based on hours since a specific date, it needs to be converted to date format
+    times=[]
+    # To convert the base date to the python datetime format
+    base_date = datetime.strptime(base_date, timeFormat)
+    for each in range(len(hours)): 
+        hour=timedelta(hours[each]/24)    
+        eachTime=base_date + hour
+        times.append(str(eachTime.year) + '-' + str("%02d" % (eachTime.month)) + '-' + str("%02d" % (eachTime.day)) + ' ' + str("%02d" % (eachTime.hour)) + ':' + str("%02d" % (eachTime.minute)) + ':' + str("%02d" % (eachTime.second)))
+
+    return latitudes, longitudes, levels, times, values
+
+
+def improve_data(latitudes, longitudes, levels, times, values, timestep):
+    
+    # Make arrays of unique latitudes, longitudes, levels and times
+    uniqueLatitudes = np.unique(latitudes)
+    uniqueLongitudes = np.unique(longitudes)
+    uniqueLevels = np.unique(levels)
+    uniqueTimestamps = np.unique(times)
+    
+    # Calculate nx and ny
+    uniqueLongitudeCount = len(uniqueLongitudes)
+    uniqueLatitudeCount = len(uniqueLatitudes)
+    uniqueLevelCount = len(uniqueLevels)
+    uniqueTimeCount = len(uniqueTimestamps)
+
+    values, latitudes, longitudes = reorderXYT(longitudes, latitudes, times, values)
+
+    # Convert each unique time from strings into list of Python datetime objects
+    # TODO - LIST COMPS!
+    timeFormat = "%Y-%m-%d %H:%M:%S"
+    timesUnique = [datetime.strptime(t, timeFormat) for t in uniqueTimestamps]
+    timesUnique.sort()
+    timesUnique = process.normalizeDatetimes(timesUnique, timestep)
+
+    # Reshape arrays
+    latitudes = latitudes.reshape(uniqueTimeCount, uniqueLatitudeCount, uniqueLongitudeCount, uniqueLevelCount)
+    longitudes = longitudes.reshape(uniqueTimeCount, uniqueLatitudeCount, uniqueLongitudeCount, uniqueLevelCount)
+    levels = np.array(levels).reshape(uniqueTimeCount, uniqueLatitudeCount, uniqueLongitudeCount, uniqueLevelCount)
+    values = values.reshape(uniqueTimeCount, uniqueLatitudeCount, uniqueLongitudeCount, uniqueLevelCount)
+
+    # Flatten dimension if only single level
+    if uniqueLevelCount == 1:
+        values = values[:, :, :, 0]
+        latitudes = latitudes[0, :, :, 0]
+        longitudes = longitudes[0, :, :, 0]
+
+    # Created masked array to deal with missing values
+    #  -these make functions like values.mean(), values.max() etc ignore missing values
+    mdi = -9999  # TODO: extract this value from the DB retrieval metadata
+    mdata = ma.masked_array(values, mask=(values == mdi))
+
+
+    return latitudes, longitudes, uniqueLevels, timesUnique, mdata
+    
+    
+def extractData ( datasetID, paramID, latMin, latMax, lonMin, lonMax, userStartTime, userEndTime, cachedir, timestep ):
+    
+    """
+    Main function to extract data from DB into numpy masked arrays, and also to create monthly netCDF file as cache
+    
+    Input::
+        datasetID, paramID: required identifiers of data in database
+        latMin, latMax, lonMin, lonMax: location range to extract data for
+        startTime, endTime: python datetime objects describing required time range to extract
+        cachedir: directory path used to store temporary cache files
+        timestep: "daily" | "monthly" so we can be sure to query the RCMED properly
+    Output:
+        uniqueLatitudes,uniqueLongitudes: 1d-numpy array of latitude and longitude grid values
+        uniqueLevels:	1d-numpy array of vertical level values
+        timesUnique: list of python datetime objects describing times of returned data
+        mdata: masked numpy arrays of data values
+    """
+
+    url = RCMED.jplUrl(datasetID, paramID, latMin, latMax, lonMin, lonMax, userStartTime, userEndTime, cachedir, timestep) 
+    
+    # To get the parameter's information from parameter table
+    database, timestep, realm, instrument, dbStartDate, dbEndDate, unit = get_param_info(url)
+        
+    # Create a directory inside the cache directory
+    name = []
+    # activity is a fix value
+    activity = "obs4cmip5"
+    name.append(activity)
+    # product is a fix value
+    product = "observations"
+    name.append(product)
+    # realm, variable,frequency and instrument will be get from parameter table
+    realm = realm
+    name.append(realm)
+    variable = database
+    name.append(variable)
+    frequency = timestep
+    name.append(frequency)
+    data_structure = "grid"
+    name.append(data_structure)
+    institution = "NASA"
+    name.append(institution)
+    project = "RCMES"
+    name.append(project)
+    instrument = instrument
+    name.append(instrument)
+    version = "v1"
+    name.append(version)
+    
+    # Check to see whether the folder is already created for netCDF or not, then it will be created
+    temp_path = cachedir
+    for n in name:
+        path = os.path.join(temp_path, n)
+        if os.path.exists(path):
+            temp_path = path
+            pass
+        else:
+            os.mkdir(path)
+            temp_path = path
+
+    processing_level = 'L3'
+    processing_version = "processing_version"  # the processing version is still unknown and can be added later
+    
+    timeFormat = "%Y-%m-%d %H:%M:%S"
+   
+    date_list, lats, longs, uniqueLevls, uniqueTimes, vals = [], [], [], [], [], []
+
+    # To make a list (date_list) of all months available based on user time request
+    while userStartTime <= userEndTime:
+        #To get the beginning of month
+        beginningOfMonth = str("%04d" % userStartTime.year) + "-" + str("%02d" % userStartTime.month) + "-" + "01 00:00:00"
+        #To get the end of month
+        endOfMonth = str("%04d" % userStartTime.year) + "-" + str("%02d" % userStartTime.month) + "-" + str(monthrange(userStartTime.year,userStartTime.month)[1]) + " 00:00:00"
+        #To convert both beginning and end of month from string to Python datetime format
+        beginningOfMonth = datetime.strptime(beginningOfMonth, timeFormat)
+        endOfMonth = datetime.strptime(endOfMonth, timeFormat)
+        #To add beginning and end of month as a list to the date_list list
+        date_list.append([beginningOfMonth, endOfMonth])
+        #To get the beginning of next month
+        userStartTime= endOfMonth + timedelta(days=1)
+
+    
+    # To loop over all months and return data
+    for i, date in enumerate(date_list):
+        netCDF_name = variable + '_' + project + '_' + processing_level + '_' + processing_version + '_' + str(latMin) + '_' + str(latMax) + '_' + str(lonMin) + '_' + str(lonMax) + '_' + str("%04d" % date[0].year) + str("%02d" % date[0].month) + '.nc'
+        
+        # To check if netCDF file  exists, then use it
+        if os.path.exists(path+"/"+ netCDF_name):
+            latitudes, longitudes, levels, times, values = read_netcdf(path + "/" + netCDF_name)  
+        
+        # If the netCDF file does not exist, then create one and read it.
+        else:            
+            # To just query for one year of data
+            print "%s of %s Database Download(s) Complete" % (i, len(date_list))  
+            url = RCMED.jplUrl(datasetID, paramID, latMin, latMax, lonMin, lonMax, date[0], date[1], cachedir, timestep)
+            
+            # To get data from DB
+            latitudes, longitudes, levels, values, timestamps = get_data(url)
+            create_netCDF(latitudes, longitudes, levels, values, timestamps, database, latMin, latMax, lonMin, lonMax, date[0], date[1], unit, path + "/" + netCDF_name)
+
+            # To read from netCDF files
+            latitudes, longitudes, levels, times, values = read_netcdf(path + "/" + netCDF_name)            
+
+        lats=np.append(lats,latitudes)
+        longs=np.append(longs,longitudes)
+        uniqueLevls=np.append(uniqueLevls,levels)
+        uniqueTimes=np.append(uniqueTimes,times)
+        vals=np.append(vals,values)
+        
+    latitudes, longitudes, uniqueLevels, timesUnique, mdata = improve_data(lats, longs, uniqueLevls, uniqueTimes, vals, timestep)
+        
+    return latitudes, longitudes, uniqueLevels, timesUnique, mdata

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/rcmes/storage/db.pyc
----------------------------------------------------------------------
diff --git a/src/main/python/rcmes/storage/db.pyc b/src/main/python/rcmes/storage/db.pyc
new file mode 100644
index 0000000..e684278
Binary files /dev/null and b/src/main/python/rcmes/storage/db.pyc differ

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/rcmes/storage/files.py
----------------------------------------------------------------------
diff --git a/src/main/python/rcmes/storage/files.py b/src/main/python/rcmes/storage/files.py
new file mode 100755
index 0000000..7bbcc1e
--- /dev/null
+++ b/src/main/python/rcmes/storage/files.py
@@ -0,0 +1,861 @@
+#
+#  Licensed to the Apache Software Foundation (ASF) under one or more
+#  contributor license agreements.  See the NOTICE file distributed with
+#  this work for additional information regarding copyright ownership.
+#  The ASF licenses this file to You under the Apache License, Version 2.0
+#  (the "License"); you may not use this file except in compliance with
+#  the License.  You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+#  Unless required by applicable law or agreed to in writing, software
+#  distributed under the License is distributed on an "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#  See the License for the specific language governing permissions and
+#  limitations under the License.
+#
+"""
+Module for handling data input files.  Requires netCDF and Numpy be 
+installed.
+
+This module can easily open NetCDF, HDF and Grib files.  Search the netCDF4
+documentation for a complete list of supported formats.
+"""
+
+from os import path
+import netCDF4
+import numpy as np
+import numpy.ma as ma
+import sys
+
+from toolkit import process
+from utils import fortranfile
+from utils import misc
+
+
+VARIABLE_NAMES = {'time': ['time', 'times', 'date', 'dates', 'julian'],
+                  'latitude': ['latitude', 'lat', 'lats', 'latitudes'],
+                  'longitude': ['longitude', 'lon', 'lons', 'longitudes']
+                  }
+
+
+def findunique(seq):
+    keys = {}
+    for e in seq:
+        keys[e] = 1
+    return keys.keys()
+
+def getVariableByType(filename, variableType):
+    """
+    Function that will try to return the variable from a file based on a provided
+    parameter type.
+    
+    Input::
+        filename - the file to inspect
+        variableType - time | latitude | longitude
+    
+    Output::
+        variable name OR list of all variables in the file if a single variable
+        name match cannot be found.
+    """
+    try:
+        f = netCDF4.Dataset(filename, mode='r')
+    except:
+        print "netCDF4Error:", sys.exc_info()[0]
+        raise
+    
+    variableKeys = f.variables.keys()
+    f.close()
+    variableKeys = [variable.encode().lower() for variable in variableKeys]
+    variableMatch = VARIABLE_NAMES[variableType]
+
+    commonVariables = list(set(variableKeys).intersection(variableMatch)) 
+
+    if len(commonVariables) == 1:
+        return str(commonVariables[0])
+    
+    else:
+        return variableKeys
+
+def getVariableRange(filename, variableName):
+    """
+    Function to return the min and max values of the given variable in
+    the supplied filename.
+   
+    Input::
+        filename - absolute path to a file
+        variableName - variable whose min and max values should be returned
+
+    Output::
+        variableRange - tuple of order (variableMin, variableMax)
+    """
+    try:
+        f = netCDF4.Dataset(filename, mode='r')
+    except:
+        print "netCDF4Error:", sys.exc_info()[0]
+        raise
+    
+    varArray = f.variables[variableName][:]
+    return (varArray.min(), varArray.max())
+
+
+def read_data_from_file_list(filelist, myvar, timeVarName, latVarName, lonVarName):
+    '''
+    Read in data from a list of model files into a single data structure
+   
+    Input:
+       filelist - list of filenames (including path)
+       myvar    - string containing name of variable to load in (as it appears in file)
+    Output:
+       lat, lon - 2D array of latitude and longitude values
+       timestore    - list of times
+       t2store  - numpy array containing data from all files    
+   
+     NB. originally written specific for WRF netCDF output files
+         modified to make more general (Feb 2011)
+   
+      Peter Lean July 2010 
+    '''
+
+    filelist.sort()
+    filename = filelist[0]
+    # Crash nicely if 'filelist' is zero length
+    """TODO:  Throw Error instead via try Except"""
+    if len(filelist) == 0:
+        print 'Error: no files have been passed to read_data_from_file_list()'
+        sys.exit()
+
+    # Open the first file in the list to:
+    #    i) read in lats, lons
+    #    ii) find out how many timesteps in the file 
+    #        (assume same ntimes in each file in list)
+    #     -allows you to create an empty array to store variable data for all times
+    tmp = netCDF4.Dataset(filename, mode='r')
+    latsraw = tmp.variables[latVarName][:]
+    lonsraw = tmp.variables[lonVarName][:]
+    if(latsraw.ndim == 1):
+        lon, lat = np.meshgrid(lonsraw, latsraw)
+    if(latsraw.ndim == 2):
+        lon = lonsraw
+        lat = latsraw
+
+    timesraw = tmp.variables[timeVarName]
+    ntimes = len(timesraw)
+    
+    print 'Lats and lons read in for first file in filelist'
+
+    # Create a single empty masked array to store model data from all files
+    t2store = ma.zeros((ntimes * len(filelist), len(lat[:, 0]), len(lon[0, :])))
+    timestore = ma.zeros((ntimes * len(filelist))) 
+    
+    # Now load in the data for real
+    #  NB. no need to reload in the latitudes and longitudes -assume invariant
+    i = 0
+    timesaccu = 0 # a counter for number of times stored so far in t2store 
+    #  NB. this method allows for missing times in data files 
+    #      as no assumption made that same number of times in each file...
+
+
+    for i, ifile in enumerate(filelist):
+
+        #print 'Loading data from file: ',filelist[i]
+        f = netCDF4.Dataset(ifile, mode='r')
+        t2raw = ma.array(f.variables[myvar][:])
+        timesraw = f.variables[timeVarName]
+        time = timesraw[:]
+        ntimes = len(time)
+        print 'file= ', i, 'ntimes= ', ntimes, filelist[i]
+        print 't2raw shape: ', t2raw.shape
+        
+        # Flatten dimensions which needn't exist, i.e. level 
+        #   e.g. if for single level then often data have 4 dimensions, when 3 dimensions will do.
+        #  Code requires data to have dimensions, (time,lat,lon)
+        #    i.e. remove level dimensions
+        # Remove 1d axis from the t2raw array
+        # Example: t2raw.shape == (365, 180, 360 1) <maps to (time, lat, lon, height)>
+        # After the squeeze you will be left with (365, 180, 360) instead
+        t2tmp = t2raw.squeeze()
+        # Nb. if this happens to be data for a single time only, then we just flattened it by accident
+        #     lets put it back... 
+        if t2tmp.ndim == 2:
+            t2tmp = np.expand_dims(t2tmp, 0)
+
+        t2store[timesaccu + np.arange(ntimes), :, :] = t2tmp[:, :, :]
+        timestore[timesaccu + np.arange(ntimes)] = time
+        timesaccu += ntimes
+        f.close()
+        
+    print 'Data read in successfully with dimensions: ', t2store.shape
+    
+    # TODO: search for duplicated entries (same time) and remove duplicates.
+    # Check to see if number of unique times == number of times, if so then no problem
+
+    if(len(np.unique(timestore)) != len(np.where(timestore != 0)[0].view())):
+        print 'WARNING: Possible duplicated times'
+
+    # Decode model times into python datetime objects. Note: timestore becomes a list (no more an array) here
+    timestore, _ = process.getModelTimes(filename, timeVarName)
+    
+    # Make sure latlon grid is monotonically increasing and that the domains
+    # are correct
+    lat, lon, t2store = checkLatLon(lat, lon, t2store)
+    data_dict = {'lats': lat, 'lons': lon, 'times': timestore, 'data': t2store}
+    return data_dict
+
+def select_var_from_file(myfile, fmt='not set'):
+    '''
+     Routine to act as user interface to allow users to select variable of interest from a file.
+     
+      Input:
+         myfile - filename
+         fmt - (optional) specify fileformat for netCDF4 if filename suffix is non-standard
+    
+      Output:
+         myvar - variable name in file
+    
+        Peter Lean  September 2010
+    '''
+
+    print fmt
+    
+    if fmt == 'not set':
+        f = netCDF4.Dataset(myfile, mode='r')
+    
+    if fmt != 'not set':
+        f = netCDF4.Dataset(myfile, mode='r', format=fmt)
+    
+    keylist = [key.encode().lower() for key in f.variables.keys()]
+    
+    i = 0
+    for v in keylist:
+        print '[', i, '] ', f.variables[v].long_name, ' (', v, ')'
+        i += 1
+
+    user_selection = raw_input('Please select variable : [0 -' + str(i - 1) + ']  ')
+    
+    myvar = keylist[int(user_selection)]
+    
+    return myvar
+
+def select_var_from_wrf_file(myfile):
+    '''
+     Routine to act as user interface to allow users to select variable of interest from a wrf netCDF file.
+     
+      Input:
+         myfile - filename
+    
+      Output:
+         mywrfvar - variable name in wrf file
+    
+        Peter Lean  September 2010
+    '''
+
+    f = netCDF4.Dataset(myfile, mode='r', format='NETCDF4')
+    keylist = [key.encode().lower() for key in f.variables.keys()]
+
+    i = 0
+    for v in keylist:
+        try:
+            print '[', i, '] ', f.variables[v].description, ' (', v, ')'
+        except:
+            print ''
+
+        i += 1
+    
+    user_selection = raw_input('Please select WRF variable : [0 -' + str(i - 1) + ']  ')
+    
+    mywrfvar = keylist[int(user_selection)]
+    
+    return mywrfvar
+
+def read_data_from_one_file(ifile, myvar, latVarName, lonVarName, timeVarName, file_type):
+    """
+    Purpose::
+        Read in data from one file at a time
+    
+    Input::   
+        filelist - list of filenames (including path)
+        myvar - string containing name of variable to load in (as it appears in file)s
+        lonVarName - name of the Longitude Variable
+        timeVarName - name of the Time Variable
+        fileType - type of file we are trying to parse
+        
+     Output::  
+        lat, lon - 2D arrays of latitude and longitude values
+        times - list of times
+        t2store - numpy array containing data from the file for the requested variable
+        varUnit - units for the variable given by t2store  
+    """           
+    f = netCDF4.Dataset(ifile, mode='r')
+    try:
+        varUnit = f.variables[myvar].units.encode().upper()
+    except:
+        varUnit = raw_input('Enter the model variable unit: \n> ').upper()
+    t2raw = ma.array(f.variables[myvar][:])
+    t2tmp = t2raw.squeeze()
+    if t2tmp.ndim == 2:
+        t2tmp = np.expand_dims(t2tmp, 0)
+        
+    lonsraw = f.variables[lonVarName][:]
+    latsraw = f.variables[latVarName][:]
+    if(latsraw.ndim == 1):
+        lon, lat = np.meshgrid(lonsraw, latsraw)
+    if(latsraw.ndim == 2):
+        lon = lonsraw
+        lat = latsraw
+    
+    f.close()
+    print '  success read_data_from_one_file: VarName=', myvar, ' Shape(Full)= ', t2tmp.shape, ' Unit= ', varUnit
+    timestore = process.decode_model_timesK(ifile, timeVarName, file_type)
+    
+    # Make sure latlon grid is monotonically increasing and that the domains
+    # are correct
+    lat, lon, t2store = checkLatLon(lat, lon, t2tmp)
+    return lat, lon, timestore, t2store, varUnit
+
+def findTimeVariable(filename):
+    """
+     Function to find what the time variable is called in a model file.
+        Input::
+            filename - file to crack open and check for a time variable
+        Output::
+            timeName - name of the input file's time variable
+            variableNameList - list of variable names from the input filename
+    """
+    try:
+        f = netCDF4.Dataset(filename, mode='r')
+    except:
+        print("Unable to open '%s' to try and read the Time variable" % filename)
+        raise
+
+    variableNameList = [variable.encode() for variable in f.variables.keys()]
+    # convert all variable names into lower case
+    varNameListLowerCase = [x.lower() for x in variableNameList]
+
+    # Use "set" types for finding common variable name from in the file and from the list of possibilities
+    possibleTimeNames = set(['time', 'times', 'date', 'dates', 'julian'])
+    
+    # Use the sets to find the intersection where variable names are in possibleNames
+    timeNameSet = possibleTimeNames.intersection(varNameListLowerCase)
+    
+    if len(timeNameSet) == 0:
+        print("Unable to autodetect the Time Variable Name in the '%s'" % filename)
+        timeName = misc.askUserForVariableName(variableNameList, targetName ="Time")
+    
+    else:
+        timeName = timeNameSet.pop()
+    
+    return timeName, variableNameList
+
+
+def findLatLonVarFromFile(filename):
+    """
+    Function to find what the latitude and longitude variables are called in a model file.
+    
+    Input:: 
+        -filename 
+    Output::
+        -latVarName
+        -lonVarName
+        -latMin 
+        -latMax
+        -lonMin
+        -lonMax
+    """
+    try:
+        f = netCDF4.Dataset(filename, mode='r')
+    except:
+        print("Unable to open '%s' to try and read the Latitude and Longitude variables" % filename)
+        raise
+
+    variableNameList = [variable.encode() for variable in f.variables.keys()]
+    # convert all variable names into lower case
+    varNameListLowerCase = [x.lower() for x in variableNameList]
+
+    # Use "set" types for finding common variable name from in the file and from the list of possibilities
+    possibleLatNames = set(['latitude', 'lat', 'lats', 'latitudes'])
+    possibleLonNames = set(['longitude', 'lon', 'lons', 'longitudes'])
+    
+    # Use the sets to find the intersection where variable names are in possibleNames
+    latNameSet = possibleLatNames.intersection(varNameListLowerCase)
+    lonNameSet = possibleLonNames.intersection(varNameListLowerCase)
+    
+    if len(latNameSet) == 0 or len(lonNameSet) == 0:
+        print("Unable to autodetect Latitude and/or Longitude values in the file")
+        latName = misc.askUserForVariableName(variableNameList, targetName ="Latitude")
+        lonName = misc.askUserForVariableName(variableNameList, targetName ="Longitude")
+    
+    else:
+        latName = latNameSet.pop()
+        lonName = lonNameSet.pop()
+    
+    lats = np.array(f.variables[latName][:])
+    lons = np.array(f.variables[lonName][:])
+    
+    latMin = lats.min()
+    latMax = lats.max()
+    
+    # Convert the lons from 0:360 into -180:180
+    lons[lons > 180] = lons[lons > 180] - 360.
+    lonMin = lons.min()
+    lonMax = lons.max()
+
+    return latName, lonName, latMin, latMax, lonMin, lonMax
+
+
+def read_data_from_file_list_K(filelist, myvar, timeVarName, latVarName, lonVarName, file_type):
+    ##################################################################################
+    # Read in data from a list of model files into a single data structure
+    # Input:   filelist - list of filenames (including path)
+    #          myvar    - string containing name of variable to load in (as it appears in file)
+    # Output:  lat, lon - 2D array of latitude and longitude values
+    #          times    - list of times
+    #          t2store  - numpy array containing data from all files    
+    # Modified from read_data_from_file_list to read data from multiple models into a 4-D array
+    # 1. The code now processes model data that completely covers the 20-yr period. Thus,
+    #    all model data must have the same time levels (ntimes). Unlike in the oroginal, ntimes
+    #    is fixed here.
+    # 2. Because one of the model data exceeds 240 mos (243 mos), the model data must be
+    #    truncated to the 240 mons using the ntimes determined from the first file.
+    ##################################################################################
+    filelist.sort()
+    nfiles = len(filelist)
+    # Crash nicely if 'filelist' is zero length
+    if nfiles == 0:
+        print 'Error: no files have been passed to read_data_from_file_list(): Exit'
+        sys.exit()
+
+    # Open the first file in the list to:
+    #    i)  read in lats, lons
+    #    ii) find out how many timesteps in the file (assume same ntimes in each file in list)
+    #     -allows you to create an empty array to store variable data for all times
+    tmp = netCDF4.Dataset(filelist[0], mode='r', format=file_type)
+    latsraw = tmp.variables[latVarName][:]
+    lonsraw = tmp.variables[lonVarName][:]
+    timesraw = tmp.variables[timeVarName]
+    
+    if(latsraw.ndim == 1):
+        lon, lat = np.meshgrid(lonsraw, latsraw)
+        
+    elif(latsraw.ndim == 2):
+        lon = lonsraw
+        lat = latsraw
+    ntimes = len(timesraw); nygrd = len(lat[:, 0]); nxgrd = len(lon[0, :])
+    
+    print 'Lats and lons read in for first file in filelist'
+
+    # Create a single empty masked array to store model data from all files
+    #t2store = ma.zeros((ntimes*nfiles,nygrd,nxgrd))
+    t2store = ma.zeros((nfiles, ntimes, nygrd, nxgrd))
+    #timestore=ma.zeros((ntimes*nfiles)) 
+    
+    ## Now load in the data for real
+    ##  NB. no need to reload in the latitudes and longitudes -assume invariant
+    #timesaccu=0 # a counter for number of times stored so far in t2store 
+    #  NB. this method allows for missing times in data files 
+    #      as no assumption made that same number of times in each file...
+
+    for i, ifile in enumerate(filelist):
+        #print 'Loading data from file: ',filelist[i]
+        f = netCDF4.Dataset(ifile, mode='r')
+        t2raw = ma.array(f.variables[myvar][:])
+        timesraw = f.variables[timeVarName]
+        #ntimes=len(time)
+        #print 'file= ',i,'ntimes= ',ntimes,filelist[i]
+        ## Flatten dimensions which needn't exist, i.e. level 
+        ##   e.g. if for single level then often data have 4 dimensions, when 3 dimensions will do.
+        ##  Code requires data to have dimensions, (time,lat,lon)
+        ##    i.e. remove level dimensions
+        t2tmp = t2raw.squeeze()
+        ## Nb. if data happen to be for a single time, we flattened it by accident; lets put it back... 
+        if t2tmp.ndim == 2:
+            t2tmp = np.expand_dims(t2tmp, 0)
+        #t2store[timesaccu+np.arange(ntimes),:,:]=t2tmp[0:ntimes,:,:]
+        t2store[i, 0:ntimes, :, :] = t2tmp[0:ntimes, :, :]
+        #timestore[timesaccu+np.arange(ntimes)]=time
+        #timesaccu=timesaccu+ntimes
+        f.close()
+
+    print 'Data read in successfully with dimensions: ', t2store.shape
+    
+    # Decode model times into python datetime objects. Note: timestore becomes a list (no more an array) here
+    ifile = filelist[0]
+    timestore, _ = process.getModelTimes(ifile, timeVarName)
+
+    # Make sure latlon grid is monotonically increasing and that the domains
+    # are correct
+    lat, lon, t2store = checkLatLon(lat, lon, t2store)
+    return lat, lon, timestore, t2store
+
+def find_latlon_ranges(filelist, lat_var_name, lon_var_name):
+    # Function to return the latitude and longitude ranges of the data in a file,
+    # given the identifying variable names.
+    #
+    #    Input:
+    #            filelist - list of filenames (data is read in from first file only)
+    #            lat_var_name - variable name of the 'latitude' variable
+    #            lon_var_name - variable name of the 'longitude' variable
+    #
+    #    Output:
+    #            latMin, latMax, lonMin, lonMax - self explanatory
+    #
+    #                    Peter Lean      March 2011
+    
+    filename = filelist[0]
+    
+    try:
+        f = netCDF4.Dataset(filename, mode='r')
+        
+        lats = f.variables[lat_var_name][:]
+        latMin = lats.min()
+        latMax = lats.max()
+        
+        lons = f.variables[lon_var_name][:]
+        lons[lons > 180] = lons[lons > 180] - 360.
+        lonMin = lons.min()
+        lonMax = lons.max()
+        
+        return latMin, latMax, lonMin, lonMax
+
+    except:
+        print 'Error: there was a problem with finding the latitude and longitude ranges in the file'
+        print '       Please check that you specified the filename, and variable names correctly.'
+        
+        sys.exit()
+
+def writeBN_lola(fileName, lons, lats):
+    # write a binary data file that include longitude (1-d) and latitude (1-d) values
+    
+    F = fortranfile.FortranFile(fileName, mode='w')
+    ngrdY = lons.shape[0]; ngrdX = lons.shape[1]
+    tmpDat = ma.zeros(ngrdX); tmpDat[:] = lons[0, :]; F.writeReals(tmpDat)
+    tmpDat = ma.zeros(ngrdY); tmpDat[:] = lats[:, 0]; F.writeReals(tmpDat)
+    # release temporary arrays
+    tmpDat = 0
+    F.close()
+
+def writeBNdata(fileName, numOBSs, numMDLs, nT, ngrdX, ngrdY, numSubRgn, obsData, mdlData, obsRgnAvg, mdlRgnAvg):
+    #(fileName,maskOption,numOBSs,numMDLs,nT,ngrdX,ngrdY,numSubRgn,obsData,mdlData,obsRgnAvg,mdlRgnAvg):
+    # write spatially- and regionally regridded data into a binary data file
+    missing = -1.e26
+    F = fortranfile.FortranFile(fileName, mode='w')
+    # construct a data array to replace mask flag with a missing value (missing=-1.e12) for printing
+    data = ma.zeros((nT, ngrdY, ngrdX))
+    for m in np.arange(numOBSs):
+        data[:, :, :] = obsData[m, :, :, :]; msk = data.mask
+        for n in np.arange(nT):
+            for j in np.arange(ngrdY):
+                for i in np.arange(ngrdX):
+                    if msk[n, j, i]: data[n, j, i] = missing
+
+        # write observed data. allowed to write only one row at a time
+        tmpDat = ma.zeros(ngrdX)
+        for n in np.arange(nT):
+            for j in np.arange(ngrdY):
+                tmpDat[:] = data[n, j, :]
+                F.writeReals(tmpDat)
+
+    # write model data (dep. on the number of models).
+    for m in np.arange(numMDLs):
+        data[:, :, :] = mdlData[m, :, :, :]
+        msk = data.mask
+        for n in np.arange(nT):
+            for j in np.arange(ngrdY):
+                for i in np.arange(ngrdX):
+                    if msk[n, j, i]:
+                        data[n, j, i] = missing
+
+        for n in np.arange(nT):
+            for j in np.arange(ngrdY):
+                tmpDat[:] = data[n, j, :]
+                F.writeReals(tmpDat)
+
+    data = 0     # release the array allocated for data
+    # write data in subregions
+    if numSubRgn > 0:
+        print 'Also included are the time series of the means over ', numSubRgn, ' areas from obs and model data'
+        tmpDat = ma.zeros(nT); print numSubRgn
+        for m in np.arange(numOBSs):
+            for n in np.arange(numSubRgn):
+                tmpDat[:] = obsRgnAvg[m, n, :]
+                F.writeReals(tmpDat)
+        for m in np.arange(numMDLs):
+            for n in np.arange(numSubRgn):
+                tmpDat[:] = mdlRgnAvg[m, n, :]
+                F.writeReals(tmpDat)
+    tmpDat = 0     # release the array allocated for tmpDat
+    F.close()
+
+def writeNCfile(fileName, numSubRgn, lons, lats, obsData, mdlData, obsRgnAvg, mdlRgnAvg, obsList, mdlList, subRegions):
+    # write an output file of variables up to 3 dimensions
+    # fileName: the name of the output data file
+    # numSubRgn  : the number of subregions
+    # lons[ngrdX]: longitude
+    # lats[ngrdY]: latitudes
+    # obsData[nT,ngrdY,ngrdX]: the obs time series of the entire model domain
+    # mdlData[numMDLs,nT,ngrdY,ngrdX]: the mdltime series of the entire model domain
+    # obsRgnAvg[numSubRgn,nT]: the obs time series for the all subregions
+    # mdlRgnAvg[numMDLs,numSubRgn,nT]: the mdl time series for the all subregions
+    dimO = obsData.shape[0]      # the number of obs data
+    dimM = mdlData.shape[0]      # the number of mdl data
+    dimT = mdlData.shape[1]      # the number of time levels
+    dimY = mdlData.shape[2]      # y-dimension
+    dimX = mdlData.shape[3]      # x-dimension
+    dimR = obsRgnAvg.shape[1]    # the number of subregions
+    f = netCDF4.Dataset(fileName, mode='w', format='NETCDF4')
+    print mdlRgnAvg.shape, dimM, dimR, dimT
+    #create global attributes
+    f.description = ''
+    # create dimensions
+    print 'Creating Dimensions within the NetCDF Object...'
+    f.createDimension('unity', 1)
+    f.createDimension('time', dimT)
+    f.createDimension('west_east', dimX)
+    f.createDimension('south_north', dimY)
+    f.createDimension('obs', dimO)
+    f.createDimension('models', dimM)
+        
+    # create the variable (real*4) to be written in the file
+    print 'Creating Variables...'
+    f.createVariable('lon', 'd', ('south_north', 'west_east'))
+    f.createVariable('lat', 'd', ('south_north', 'west_east'))
+    f.createVariable('oDat', 'd', ('obs', 'time', 'south_north', 'west_east'))
+    f.createVariable('mDat', 'd', ('models', 'time', 'south_north', 'west_east'))
+    
+    if subRegions:
+        f.createDimension('regions', dimR)
+        f.createVariable('oRgn', 'd', ('obs', 'regions', 'time'))
+        f.createVariable('mRgn', 'd', ('models', 'regions', 'time'))
+        f.variables['oRgn'].varAttName = 'Observation time series: Subregions'
+        f.variables['mRgn'].varAttName = 'Model time series: Subregions'
+
+    loadDataIntoNetCDF(f, obsList, obsData, 'Observation')
+    print 'Loaded the Observations into the NetCDF'
+
+    loadDataIntoNetCDF(f, mdlList, mdlData, 'Model')
+
+    # create attributes and units for the variable
+    print 'Creating Attributes and Units...'
+    f.variables['lon'].varAttName = 'Longitudes'
+    f.variables['lon'].varUnit = 'degrees East'
+    f.variables['lat'].varAttName = 'Latitudes'
+    f.variables['lat'].varUnit = 'degrees North'
+    f.variables['oDat'].varAttName = 'Observation time series: entire domain'
+    f.variables['mDat'].varAttName = 'Model time series: entire domain'
+
+    # assign the values to the variable and write it
+    f.variables['lon'][:] = lons[:]
+    f.variables['lat'][:] = lats[:]
+    if subRegions:
+        f.variables['oRgn'][:] = obsRgnAvg[:]
+        f.variables['mRgn'][:] = mdlRgnAvg[:]
+
+    f.close()
+
+def writeNCfile1(fileName, numDatasets, numObs, numMdl, numSubRgn, lons, lats, allData, dataRgn, dataList, subRegions):
+    # write an output file of variables up to 3 dimensions
+    # fileName: the name of the output data file
+    # numDatasets: the total number of datasets (numObs + numMdl)
+    # numObs     : the number of obs datasets (including the obs ensemble, if exists)
+    # numMdl     : the number of mdl datasets (including the mdl ensemble, if exists)
+    # numSubRgn  : the number of subregions
+    # lons[ngrdX]: longitude
+    # lats[ngrdY]: latitudes
+    # allData[numDatasets,nT,ngrdY,ngrdX]: the combined obs and model time series for the entire model domain (t,y,x)
+    # dataRgn[numDatasets,numSubRgn,nT]: the obs time series for the all subregions
+    # dataList   : the names of datasets
+    # subRegions : sub-region info
+    dimN = allData.shape[0]      # the number of all (obs + model) datasets
+    dimT = allData.shape[1]      # the number of time levels
+    dimY = allData.shape[2]      # y-dimension
+    dimX = allData.shape[3]      # x-dimension
+    dimR = dataRgn.shape[1]      # the number of subregions
+    f = netCDF4.Dataset(fileName, mode='w', format='NETCDF4')
+    print dataRgn.shape, dimN, dimR, dimT
+    #create global attributes
+    f.description = ''
+    # create dimensions
+    print 'Creating Dimensions within the NetCDF Object...'
+    f.createDimension('unity', 1)
+    f.createDimension('time', dimT)
+    f.createDimension('west_east', dimX)
+    f.createDimension('south_north', dimY)
+    f.createDimension('data', dimN)
+    # create the variable (real*4) to be written in the file
+    print 'Creating Variables...'
+    f.createVariable('lon', 'd', ('south_north', 'west_east'))
+    f.createVariable('lat', 'd', ('south_north', 'west_east'))
+    f.createVariable('dGrd', 'd', ('data', 'time', 'south_north', 'west_east'))
+
+    if subRegions:
+        f.createDimension('regions', dimR)
+        f.createVariable('dRgn', 'd', ('data', 'regions', 'time'))
+        f.variables['dRgn'].varAttName = 'Sub-region mean time series'
+
+    # load the gridded data into the output file
+    loadDataIntoNetCDF1(f, dataList, allData)
+    print 'Loaded the gridded into the NetCDF'
+
+    # create attributes and units for the variable
+    print 'Creating Attributes and Units...'
+    f.variables['lon'].varAttName = 'Longitudes'
+    f.variables['lon'].varUnit = 'degrees East'
+    f.variables['lat'].varAttName = 'Latitudes'
+    f.variables['lat'].varUnit = 'degrees North'
+    f.variables['dGrd'].varAttName = 'Gridded time series'
+
+    # assign the values to the variable and write it
+    f.variables['lon'][:] = lons[:]
+    f.variables['lat'][:] = lats[:]
+    if subRegions:
+        f.variables['dRgn'][:] = dataRgn[:]
+
+    f.close()
+
+def loadDataIntoNetCDF(fileObject, datasets, dataArray, dataType):
+    """
+    Input::
+        fileObject - netCDF4 file object data will be loaded into
+        datasets - List of dataset names
+        dataArray - Multi-dimensional array of data to be loaded into the NetCDF file
+        dataType - String with value of either 'Model' or 'Observation'
+    Output::
+        No return value.  netCDF4 file object is updated in place
+    """
+    datasetCount = 0
+    for datasetCount, dataset in enumerate(datasets):
+        if dataType.lower() == 'observation':
+            datasetName = dataset.replace(' ','')
+        elif dataType.lower() == 'model':
+            datasetName = path.splitext(path.basename(dataset))[0]
+        print "Creating variable %s" % datasetName
+        fileObject.createVariable(datasetName, 'd', ('time', 'south_north', 'west_east'))
+        fileObject.variables[datasetName].varAttName = 'Obseration time series: entire domain'
+        print 'Loading values into %s' % datasetName
+        fileObject.variables[datasetName][:] = dataArray[datasetCount,:,:,:]
+
+def loadDataIntoNetCDF1(fileObject, datasets, dataArray):
+    """
+    Input::
+        fileObject - netCDF4 file object data will be loaded into
+        datasets - List of dataset names
+        dataArray - Multi-dimensional array of data to be loaded into the NetCDF file
+    Output::
+        No return value.  netCDF4 file object is updated in place
+    """
+    datasetCount = 0
+    for datasetCount, dataset in enumerate(datasets):
+        datasetName = path.splitext(path.basename(dataset))[0]
+        print "Creating variable %s" % datasetName
+        fileObject.createVariable(datasetName, 'd', ('time', 'south_north', 'west_east'))
+        fileObject.variables[datasetName].varAttName = 'Gridded time series: entire domain'
+        print 'Loading values into %s' % datasetName
+        fileObject.variables[datasetName][:] = dataArray[datasetCount,:,:,:]
+
+def checkLatLon(latsin, lonsin, datain):
+    """
+    Purpose::
+        Checks whether latitudes and longitudes are monotonically increasing
+        within the domains [-90, 90) and [-180, 180) respectively, and rearranges the input data
+        accordingly if they are not.
+    
+    Input::
+        latsin - Array of latitudes read from a raw netcdf file
+        lonsin - Array of longitudes read from a raw netcdf file
+        datain  - Array of data values read from a raw netcdf file.
+                   The shape is assumed to be (..., nLat, nLon).
+        
+    Output::
+        latsout - 2D array of (rearranged) latitudes
+        lonsout - 2D array of (rearranged) longitudes
+        dataout - Array of (rearranged) data
+    """
+    # Avoid unnecessary shifting if all lons are higher than 180
+    if lonsin.min() > 180:
+        lonsin -= 360
+        
+    # Make sure lats and lons are monotonically increasing
+    latsDecreasing = np.diff(latsin[:, 0]) < 0
+    lonsDecreasing = np.diff(lonsin[0]) < 0
+    
+    # If all values are decreasing then they just need to be reversed
+    latsReversed, lonsReversed = latsDecreasing.all(), lonsDecreasing.all()
+    
+    # If the lat values are unsorted then raise an exception
+    if not latsReversed and latsDecreasing.any():
+        raise ValueError('Latitudes must be monotonically increasing.')
+    
+    # Perform same checks now for lons
+    if not lonsReversed and lonsDecreasing.any():
+        raise ValueError('Longitudes must be monotonically increasing.')
+    
+    # Also check if lons go from [0, 360), and convert to [-180, 180)
+    # if necessary
+    lonsShifted = lonsin.max() > 180
+    latsout, lonsout, dataout = latsin[:], lonsin[:], datain[:]
+    # Now correct data if latlon grid needs to be shifted    
+    if latsReversed:
+        latsout = latsout[::-1]
+        dataout = dataout[..., ::-1, :]
+        
+    if lonsReversed:
+        lonsout = lonsout[..., ::-1]
+        dataout = dataout[..., ::-1]
+        
+    if lonsShifted:
+        lat1d = latsout[:, 0]
+        dataout, lon1d = shiftgrid(180, dataout, lonsout[0], start=False)
+        lonsout, latsout = np.meshgrid(lon1d, lat1d) 
+        
+    return latsout, lonsout, dataout
+    
+def shiftgrid(lon0, datain, lonsin, start= True, cyclic=360.0):
+    """
+    Purpose::
+        Shift global lat/lon grid east or west. This function is taken directly
+        from the (unreleased) basemap 1.0.7 source code as version 1.0.6 does not
+        currently support arrays with more than two dimensions.
+        https://github.com/matplotlib/basemap
+        
+    Input::
+        lon0 - starting longitude for shifted grid (ending longitude if start=False). 
+               lon0 must be on input grid (within the range of lonsin).
+        datain - original data with longitude the right-most dimension.
+        lonsin - original longitudes.
+        start  - if True, lon0 represents the starting longitude of the new grid. 
+                 if False, lon0 is the ending longitude. Default True.
+        cyclic - width of periodic domain (default 360)
+
+    Output:: 
+        dataout - data on shifted grid
+        lonsout - lons on shifted grid
+    """
+    if np.fabs(lonsin[-1]-lonsin[0]-cyclic) > 1.e-4:
+        # Use all data instead of raise ValueError, 'cyclic point not included'
+        start_idx = 0
+    else:
+        # If cyclic, remove the duplicate point
+        start_idx = 1
+    if lon0 < lonsin[0] or lon0 > lonsin[-1]:
+        raise ValueError('lon0 outside of range of lonsin')
+    i0 = np.argmin(np.fabs(lonsin-lon0))
+    i0_shift = len(lonsin)-i0
+    if ma.isMA(datain):
+        dataout  = ma.zeros(datain.shape,datain.dtype)
+    else:
+        dataout  = np.zeros(datain.shape,datain.dtype)
+    if ma.isMA(lonsin):
+        lonsout = ma.zeros(lonsin.shape,lonsin.dtype)
+    else:
+        lonsout = np.zeros(lonsin.shape,lonsin.dtype)
+    if start:
+        lonsout[0:i0_shift] = lonsin[i0:]
+    else:
+        lonsout[0:i0_shift] = lonsin[i0:]-cyclic
+    dataout[...,0:i0_shift] = datain[...,i0:]
+    if start:
+        lonsout[i0_shift:] = lonsin[start_idx:i0+start_idx]+cyclic
+    else:
+        lonsout[i0_shift:] = lonsin[start_idx:i0+start_idx]
+    dataout[...,i0_shift:] = datain[...,start_idx:i0+start_idx]
+    return dataout,lonsout

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/rcmes/storage/files.pyc
----------------------------------------------------------------------
diff --git a/src/main/python/rcmes/storage/files.pyc b/src/main/python/rcmes/storage/files.pyc
new file mode 100644
index 0000000..ddd7366
Binary files /dev/null and b/src/main/python/rcmes/storage/files.pyc differ


[06/51] [abbrv] [partial] Adding Jinwon's custom RCMET

Posted by jo...@apache.org.
http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/templates/default/.svn/text-base/apache2.conf.erb.svn-base
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/templates/default/.svn/text-base/apache2.conf.erb.svn-base b/src/main/vm/src/cookbooks/apache2/templates/default/.svn/text-base/apache2.conf.erb.svn-base
new file mode 100755
index 0000000..c94b92a
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/templates/default/.svn/text-base/apache2.conf.erb.svn-base
@@ -0,0 +1,230 @@
+#
+# Generated by Chef
+#
+# Based on the Ubuntu apache2.conf
+
+ServerRoot "<%= node[:apache][:dir] %>"
+
+#
+# The accept serialization lock file MUST BE STORED ON A LOCAL DISK.
+#
+<% if node[:platform] == "debian" || node[:platform] == "ubuntu" -%>
+LockFile /var/lock/apache2/accept.lock
+<% else %>
+LockFile logs/accept.lock
+<% end -%>
+
+#
+# PidFile: The file in which the server should record its process
+# identification number when it starts.
+#
+<% if node[:platform] == "debian" || node[:platform] == "ubuntu" -%>
+PidFile /var/run/apache2.pid
+<% elsif node[:platform] == "centos" || node[:platform] == "redhat" || node[:platform] == "fedora" -%>
+PidFile /var/run/httpd.pid
+<% else -%>
+PidFile logs/httpd.pid
+<% end -%>
+
+#
+# Timeout: The number of seconds before receives and sends time out.
+#
+Timeout <%= node[:apache][:timeout] %>
+
+#
+# KeepAlive: Whether or not to allow persistent connections (more than
+# one request per connection). Set to "Off" to deactivate.
+#
+KeepAlive <%= node[:apache][:keepalive] %>
+
+#
+# MaxKeepAliveRequests: The maximum number of requests to allow
+# during a persistent connection. Set to 0 to allow an unlimited amount.
+# We recommend you leave this number high, for maximum performance.
+#
+MaxKeepAliveRequests <%= node[:apache][:keepaliverequests] %>
+
+#
+# KeepAliveTimeout: Number of seconds to wait for the next request from the
+# same client on the same connection.
+#
+KeepAliveTimeout <%= node[:apache][:keepalivetimeout] %>
+
+##
+## Server-Pool Size Regulation (MPM specific)
+## 
+
+# prefork MPM
+# StartServers: number of server processes to start
+# MinSpareServers: minimum number of server processes which are kept spare
+# MaxSpareServers: maximum number of server processes which are kept spare
+# MaxClients: maximum number of server processes allowed to start
+# MaxRequestsPerChild: maximum number of requests a server process serves
+<IfModule mpm_prefork_module>
+    StartServers          <%= node[:apache][:prefork][:startservers] %>
+    MinSpareServers       <%= node[:apache][:prefork][:minspareservers] %>
+    MaxSpareServers       <%= node[:apache][:prefork][:maxspareservers] %>
+    ServerLimit           <%= node[:apache][:prefork][:serverlimit] %>
+    MaxClients            <%= node[:apache][:prefork][:maxclients] %>
+    MaxRequestsPerChild   <%= node[:apache][:prefork][:maxrequestsperchild] %>
+</IfModule>
+
+# worker MPM
+# StartServers: initial number of server processes to start
+# MaxClients: maximum number of simultaneous client connections
+# MinSpareThreads: minimum number of worker threads which are kept spare
+# MaxSpareThreads: maximum number of worker threads which are kept spare
+# ThreadsPerChild: constant number of worker threads in each server process
+# MaxRequestsPerChild: maximum number of requests a server process serves
+<IfModule mpm_worker_module>
+    StartServers          <%= node[:apache][:worker][:startservers] %>
+    MaxClients            <%= node[:apache][:worker][:maxclients] %>
+    MinSpareThreads       <%= node[:apache][:worker][:minsparethreads] %>
+    MaxSpareThreads       <%= node[:apache][:worker][:maxsparethreads] %>
+    ThreadsPerChild       <%= node[:apache][:worker][:threadsperchild] %>
+    MaxRequestsPerChild   <%= node[:apache][:worker][:maxrequestsperchild] %>
+</IfModule>
+
+User <%= node[:apache][:user] %>
+Group <%= node[:apache][:user] %>
+
+#
+# AccessFileName: The name of the file to look for in each directory
+# for additional configuration directives.  See also the AllowOverride
+# directive.
+#
+
+AccessFileName .htaccess
+
+#
+# The following lines prevent .htaccess and .htpasswd files from being 
+# viewed by Web clients. 
+#
+<Files ~ "^\.ht">
+    Order allow,deny
+    Deny from all
+</Files>
+
+#
+# DefaultType is the default MIME type the server will use for a document
+# if it cannot otherwise determine one, such as from filename extensions.
+# If your server contains mostly text or HTML documents, "text/plain" is
+# a good value.  If most of your content is binary, such as applications
+# or images, you may want to use "application/octet-stream" instead to
+# keep browsers from trying to display binary files as though they are
+# text.
+#
+DefaultType text/plain
+
+
+#
+# HostnameLookups: Log the names of clients or just their IP addresses
+# e.g., www.apache.org (on) or 204.62.129.132 (off).
+# The default is off because it'd be overall better for the net if people
+# had to knowingly turn this feature on, since enabling it means that
+# each client request will result in AT LEAST one lookup request to the
+# nameserver.
+#
+HostnameLookups Off
+
+# ErrorLog: The location of the error log file.
+# If you do not specify an ErrorLog directive within a <VirtualHost>
+# container, error messages relating to that virtual host will be
+# logged here.  If you *do* define an error logfile for a <VirtualHost>
+# container, that host's errors will be logged there and not here.
+#
+ErrorLog <%= node[:apache][:log_dir] %>/error.log 
+
+#
+# LogLevel: Control the number of messages logged to the error_log.
+# Possible values include: debug, info, notice, warn, error, crit,
+# alert, emerg.
+#
+LogLevel warn
+
+# Include module configuration:
+Include <%= node[:apache][:dir] %>/mods-enabled/*.load
+Include <%= node[:apache][:dir] %>/mods-enabled/*.conf
+
+# Include ports listing
+Include <%= node[:apache][:dir] %>/ports.conf
+
+#
+# The following directives define some format nicknames for use with
+# a CustomLog directive (see below).
+#
+LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
+LogFormat "%h %l %u %t \"%r\" %>s %b" common
+LogFormat "%{Referer}i -> %U" referer
+LogFormat "%{User-agent}i" agent
+#
+
+# Customizable error responses come in three flavors:
+# 1) plain text 2) local redirects 3) external redirects
+#
+# Some examples:
+#ErrorDocument 500 "The server made a boo boo."
+#ErrorDocument 404 /missing.html
+#ErrorDocument 404 "/cgi-bin/missing_handler.pl"
+#ErrorDocument 402 http://www.example.com/subscription_info.html
+#
+
+#
+# Putting this all together, we can internationalize error responses.
+#
+# We use Alias to redirect any /error/HTTP_<error>.html.var response to
+# our collection of by-error message multi-language collections.  We use 
+# includes to substitute the appropriate text.
+#
+# You can modify the messages' appearance without changing any of the
+# default HTTP_<error>.html.var files by adding the line:
+#
+#   Alias /error/include/ "/your/include/path/"
+#
+# which allows you to create your own set of files by starting with the
+# /usr/share/apache2/error/include/ files and copying them to /your/include/path/, 
+# even on a per-VirtualHost basis.  The default include files will display
+# your Apache version number and your ServerAdmin email address regardless
+# of the setting of ServerSignature.
+#
+# The internationalized error documents require mod_alias, mod_include
+# and mod_negotiation.  To activate them, uncomment the following 30 lines.
+
+#    Alias /error/ "/usr/share/apache2/error/"
+#
+#    <Directory "/usr/share/apache2/error">
+#        AllowOverride None
+#        Options IncludesNoExec
+#        AddOutputFilter Includes html
+#        AddHandler type-map var
+#        Order allow,deny
+#        Allow from all
+#        LanguagePriority en cs de es fr it nl sv pt-br ro
+#        ForceLanguagePriority Prefer Fallback
+#    </Directory>
+#
+#    ErrorDocument 400 /error/HTTP_BAD_REQUEST.html.var
+#    ErrorDocument 401 /error/HTTP_UNAUTHORIZED.html.var
+#    ErrorDocument 403 /error/HTTP_FORBIDDEN.html.var
+#    ErrorDocument 404 /error/HTTP_NOT_FOUND.html.var
+#    ErrorDocument 405 /error/HTTP_METHOD_NOT_ALLOWED.html.var
+#    ErrorDocument 408 /error/HTTP_REQUEST_TIME_OUT.html.var
+#    ErrorDocument 410 /error/HTTP_GONE.html.var
+#    ErrorDocument 411 /error/HTTP_LENGTH_REQUIRED.html.var
+#    ErrorDocument 412 /error/HTTP_PRECONDITION_FAILED.html.var
+#    ErrorDocument 413 /error/HTTP_REQUEST_ENTITY_TOO_LARGE.html.var
+#    ErrorDocument 414 /error/HTTP_REQUEST_URI_TOO_LARGE.html.var
+#    ErrorDocument 415 /error/HTTP_UNSUPPORTED_MEDIA_TYPE.html.var
+#    ErrorDocument 500 /error/HTTP_INTERNAL_SERVER_ERROR.html.var
+#    ErrorDocument 501 /error/HTTP_NOT_IMPLEMENTED.html.var
+#    ErrorDocument 502 /error/HTTP_BAD_GATEWAY.html.var
+#    ErrorDocument 503 /error/HTTP_SERVICE_UNAVAILABLE.html.var
+#    ErrorDocument 506 /error/HTTP_VARIANT_ALSO_VARIES.html.var
+
+
+
+# Include generic snippets of statements
+Include <%= node[:apache][:dir] %>/conf.d/
+
+# Include the virtual host configurations:
+Include <%= node[:apache][:dir] %>/sites-enabled/

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/templates/default/.svn/text-base/apache2.god.erb.svn-base
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/templates/default/.svn/text-base/apache2.god.erb.svn-base b/src/main/vm/src/cookbooks/apache2/templates/default/.svn/text-base/apache2.god.erb.svn-base
new file mode 100755
index 0000000..b7315e4
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/templates/default/.svn/text-base/apache2.god.erb.svn-base
@@ -0,0 +1,19 @@
+God.watch do |w|
+  w.name = "apache2"
+  w.interval = 30.seconds # default
+  w.start = "<%= @params[:start] %>"
+  w.stop = "/etc/init.d/httpd stop"
+  w.restart = "<%= @params[:restart] %>"
+  w.start_grace = 10.seconds
+  w.restart_grace = 10.seconds
+  w.pid_file = "/var/run/httpd.pid"
+  w.behavior(:clean_pid_file)
+
+  w.start_if do |start|
+    start.condition(:process_running) do |c|
+        c.interval = 5.seconds
+        c.running = false
+        c.notify = 'admin'
+    end
+  end
+end

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/templates/default/.svn/text-base/charset.erb.svn-base
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/templates/default/.svn/text-base/charset.erb.svn-base b/src/main/vm/src/cookbooks/apache2/templates/default/.svn/text-base/charset.erb.svn-base
new file mode 100755
index 0000000..40d7198
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/templates/default/.svn/text-base/charset.erb.svn-base
@@ -0,0 +1,6 @@
+# Read the documentation before enabling AddDefaultCharset.
+# In general, it is only a good idea if you know that all your files
+# have this encoding. It will override any encoding given in the files
+# in meta http-equiv or xml encoding tags.
+
+#AddDefaultCharset UTF-8

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/templates/default/.svn/text-base/default-site.erb.svn-base
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/templates/default/.svn/text-base/default-site.erb.svn-base b/src/main/vm/src/cookbooks/apache2/templates/default/.svn/text-base/default-site.erb.svn-base
new file mode 100755
index 0000000..14b2563
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/templates/default/.svn/text-base/default-site.erb.svn-base
@@ -0,0 +1,57 @@
+<VirtualHost *:80>
+        ServerAdmin <%= node[:apache][:contact] %>
+
+        DocumentRoot /var/www/
+        <Directory />
+                Options FollowSymLinks
+                AllowOverride None
+        </Directory>
+        <Directory /var/www/>
+                Options Indexes FollowSymLinks MultiViews
+                AllowOverride None
+                Order allow,deny
+                allow from all
+                # This directive allows us to have apache2's default start page
+                # in /apache2-default/, but still have / go to the right place
+                #RedirectMatch ^/$ /apache2-default/
+        </Directory>
+
+        ScriptAlias /cgi-bin/ /usr/lib/cgi-bin/
+        <Directory "/usr/lib/cgi-bin">
+                AllowOverride None
+                Options ExecCGI -MultiViews +SymLinksIfOwnerMatch
+                Order allow,deny
+                Allow from all
+        </Directory>
+
+        ErrorLog <%= node[:apache][:log_dir] %>/error.log 
+
+        # Possible values include: debug, info, notice, warn, error, crit,
+        # alert, emerg.
+        LogLevel warn
+
+        CustomLog <%= node[:apache][:log_dir] %>/access.log combined
+        ServerSignature On
+
+        Alias /doc/ "/usr/share/doc/"
+        <Directory "/usr/share/doc/">
+            Options Indexes MultiViews FollowSymLinks
+            AllowOverride None
+            Order deny,allow
+            Deny from all
+            Allow from 127.0.0.0/255.0.0.0 ::1/128
+        </Directory>
+
+        <% if node[:platform] == "centos" || node[:platform] == "redhat" || node[:platform] == "fedora" -%>
+        #
+        # This configuration file enables the default "Welcome"
+        # page if there is no default index page present for
+        # the root URL.  To disable the Welcome page, comment
+        # out all the lines below.
+        #
+        <LocationMatch "^/+$">
+            Options -Indexes
+            ErrorDocument 403 /error/noindex.html
+        </LocationMatch>
+        <% end -%>
+</VirtualHost>

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/templates/default/.svn/text-base/mod_auth_openid.rb.erb.svn-base
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/templates/default/.svn/text-base/mod_auth_openid.rb.erb.svn-base b/src/main/vm/src/cookbooks/apache2/templates/default/.svn/text-base/mod_auth_openid.rb.erb.svn-base
new file mode 100755
index 0000000..51fc1d7
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/templates/default/.svn/text-base/mod_auth_openid.rb.erb.svn-base
@@ -0,0 +1,12 @@
+#!/usr/bin/env ruby
+
+allowed_openids = Array.new
+<% node[:apache][:allowed_openids].each do |id| -%>
+allowed_openids << "<%= id %>"
+<% end -%>
+
+if allowed_openids.grep(ARGV[0]).length > 0
+  exit 0
+else
+  exit 1
+end

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/templates/default/.svn/text-base/port_apache.erb.svn-base
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/templates/default/.svn/text-base/port_apache.erb.svn-base b/src/main/vm/src/cookbooks/apache2/templates/default/.svn/text-base/port_apache.erb.svn-base
new file mode 100755
index 0000000..f6078dd
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/templates/default/.svn/text-base/port_apache.erb.svn-base
@@ -0,0 +1,2 @@
+# Port <%= @port %> 
+-A FWR -p tcp -m tcp --dport <%= @port %> -j ACCEPT
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/templates/default/.svn/text-base/ports.conf.erb.svn-base
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/templates/default/.svn/text-base/ports.conf.erb.svn-base b/src/main/vm/src/cookbooks/apache2/templates/default/.svn/text-base/ports.conf.erb.svn-base
new file mode 100755
index 0000000..cc3631e
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/templates/default/.svn/text-base/ports.conf.erb.svn-base
@@ -0,0 +1,6 @@
+#This file generated via template by Chef.
+<% @apache_listen_ports.each do |port| -%>
+Listen <%= port %>
+NameVirtualHost *:<%= port %>
+
+<% end -%>

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/templates/default/.svn/text-base/security.erb.svn-base
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/templates/default/.svn/text-base/security.erb.svn-base b/src/main/vm/src/cookbooks/apache2/templates/default/.svn/text-base/security.erb.svn-base
new file mode 100755
index 0000000..70c97ad
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/templates/default/.svn/text-base/security.erb.svn-base
@@ -0,0 +1,50 @@
+#
+# Disable access to the entire file system except for the directories that
+# are explicitly allowed later.
+#
+# This currently breaks the configurations that come with some web application
+# Debian packages. It will be made the default for the release after lenny.
+#
+#<Directory />
+#	AllowOverride None
+#	Order Deny,Allow
+#	Deny from all
+#</Directory>
+
+
+# Changing the following options will not really affect the security of the
+# server, but might make attacks slightly more difficult in some cases.
+
+#
+# ServerTokens
+# This directive configures what you return as the Server HTTP response
+# Header. The default is 'Full' which sends information about the OS-Type
+# and compiled in modules.
+# Set to one of:  Full | OS | Minimal | Minor | Major | Prod
+# where Full conveys the most information, and Prod the least.
+#
+#ServerTokens Minimal
+ServerTokens <%= node[:apache][:servertokens] %> 
+
+#
+# Optionally add a line containing the server version and virtual host
+# name to server-generated pages (internal error documents, FTP directory
+# listings, mod_status and mod_info output etc., but not CGI generated
+# documents or custom error documents).
+# Set to "EMail" to also include a mailto: link to the ServerAdmin.
+# Set to one of:  On | Off | EMail
+#
+#ServerSignature Off
+ServerSignature <%= node[:apache][:serversignature] %> 
+
+#
+# Allow TRACE method
+#
+# Set to "extended" to also reflect the request body (only for testing and
+# diagnostic purposes).
+#
+# Set to one of:  On | Off | extended
+#
+#TraceEnable Off
+TraceEnable <%= node[:apache][:traceenable] %> 
+

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/templates/default/.svn/text-base/web_app.conf.erb.svn-base
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/templates/default/.svn/text-base/web_app.conf.erb.svn-base b/src/main/vm/src/cookbooks/apache2/templates/default/.svn/text-base/web_app.conf.erb.svn-base
new file mode 100755
index 0000000..6be3fc9
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/templates/default/.svn/text-base/web_app.conf.erb.svn-base
@@ -0,0 +1,43 @@
+<VirtualHost *:80>
+  ServerName <%= @params[:server_name] %>
+  ServerAlias <% @params[:server_aliases].each do |a| %><%= "#{a}" %> <% end %>
+  DocumentRoot <%= @params[:docroot] %>
+  RewriteEngine On
+  
+  <Directory <%= @params[:docroot] %>>
+    Options FollowSymLinks
+    AllowOverride None
+    Order allow,deny
+    Allow from all
+  </Directory>
+  
+  <Directory />
+    Options FollowSymLinks
+    AllowOverride None
+  </Directory>
+
+  <Location /server-status>
+    SetHandler server-status
+
+    Order Deny,Allow
+    Deny from all
+    Allow from 127.0.0.1
+  </Location>
+
+  LogLevel info
+  ErrorLog <%= node[:apache][:log_dir] %>/<%= @params[:name] %>-error.log
+  CustomLog <%= node[:apache][:log_dir] %>/<%= @params[:name] %>-access.log combined
+
+  RewriteEngine On
+  RewriteLog <%= node[:apache][:log_dir] %>/<%= @application_name %>-rewrite.log
+  RewriteLogLevel 0
+
+  # Canonical host, <%= @params[:server_name] %>
+  RewriteCond %{HTTP_HOST}   !^<%= @params[:server_name] %> [NC]
+  RewriteCond %{HTTP_HOST}   !^$
+  RewriteRule ^/(.*)$        http://<%= @params[:server_name] %>/$1 [L,R=301]
+
+  RewriteCond %{DOCUMENT_ROOT}/system/maintenance.html -f
+  RewriteCond %{SCRIPT_FILENAME} !maintenance.html
+  RewriteRule ^.*$ /system/maintenance.html [L]
+</VirtualHost>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/templates/default/a2dismod.erb
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/templates/default/a2dismod.erb b/src/main/vm/src/cookbooks/apache2/templates/default/a2dismod.erb
new file mode 100755
index 0000000..06fb6b3
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/templates/default/a2dismod.erb
@@ -0,0 +1,22 @@
+#!/bin/sh -e
+
+SYSCONFDIR='<%= node[:apache][:dir] %>'
+
+if [ -z $1 ]; then
+        echo "Which module would you like to disable?"
+        echo -n "Your choices are: "
+        ls $SYSCONFDIR/mods-enabled/*.load | \
+        sed -e "s,$SYSCONFDIR/mods-enabled/,,g" | sed -e 's/\.load$//g;' | xargs echo
+        echo -n "Module name? "
+        read MODNAME
+else
+        MODNAME=$1
+fi
+
+if ! [ -e $SYSCONFDIR/mods-enabled/$MODNAME.load ]; then
+        echo "This module is already disabled, or does not exist!"
+        exit 1
+fi
+
+rm -f $SYSCONFDIR/mods-enabled/$MODNAME.*
+echo "Module $MODNAME disabled; reload apache to fully disable."
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/templates/default/a2dissite.erb
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/templates/default/a2dissite.erb b/src/main/vm/src/cookbooks/apache2/templates/default/a2dissite.erb
new file mode 100755
index 0000000..41feda5
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/templates/default/a2dissite.erb
@@ -0,0 +1,29 @@
+#!/bin/sh -e
+
+SYSCONFDIR='<%= node[:apache][:dir] %>'
+
+if [ -z $1 ]; then
+        echo "Which site would you like to disable?"
+        echo -n "Your choices are: "
+        ls $node[:apache][:dir]/sites-enabled/* | \
+        sed -e "s,$SYSCONFDIR/sites-enabled/,,g" | xargs echo
+        echo -n "Site name? "
+        read SITENAME
+else
+        SITENAME=$1
+fi
+
+if [ $SITENAME = "default" ]; then
+        PRIORITY="000"
+fi
+
+if ! [ -e $SYSCONFDIR/sites-enabled/$SITENAME -o \
+       -e $SYSCONFDIR/sites-enabled/"$PRIORITY"-"$SITENAME" ]; then
+        echo "This site is already disabled, or does not exist!"
+        exit 1
+fi
+
+if ! rm $SYSCONFDIR/sites-enabled/$SITENAME 2>/dev/null; then
+        rm -f $SYSCONFDIR/sites-enabled/"$PRIORITY"-"$SITENAME"
+fi
+echo "Site $SITENAME disabled; reload apache to disable."
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/templates/default/a2enmod.erb
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/templates/default/a2enmod.erb b/src/main/vm/src/cookbooks/apache2/templates/default/a2enmod.erb
new file mode 100755
index 0000000..a59c72f
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/templates/default/a2enmod.erb
@@ -0,0 +1,37 @@
+#!/bin/sh -e
+
+SYSCONFDIR='<%= node[:apache][:dir] %>'
+
+if [ -z $1 ]; then
+        echo "Which module would you like to enable?"
+        echo -n "Your choices are: "
+        ls $SYSCONFDIR/mods-available/*.load | \
+        sed -e "s,$SYSCONFDIR/mods-available/,,g" | sed -e 's/\.load$//g;' | xargs echo
+        echo -n "Module name? "
+        read MODNAME
+else
+        MODNAME=$1
+fi
+
+#figure out if we're on a prefork or threaded mpm
+if [ -x /usr/sbin/apache2 ]; then
+        PREFORK=`/usr/sbin/apache2 -l | grep prefork || true`
+fi
+
+if [ -e $SYSCONFDIR/mods-enabled/$MODNAME.load && -e $SYSCONFDIR/mods-enabled/$MODNAME.conf ]; then
+        echo "This module is already enabled!"
+        exit 0 
+fi
+
+if ! [ -e $SYSCONFDIR/mods-available/$MODNAME.load ]; then
+        echo "This module does not exist!"
+        exit 1
+fi
+
+for i in conf load; do 
+        if [ -e $SYSCONFDIR/mods-available/$MODNAME.$i -a ! -e $SYSCONFDIR/mods-enabled/$MODNAME.$i ]; then
+        ln -sf $SYSCONFDIR/mods-available/$MODNAME.$i $SYSCONFDIR/mods-enabled/$MODNAME.$i;
+        fi
+done
+
+echo "Module $MODNAME installed; reload apache to enable."
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/templates/default/a2ensite.erb
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/templates/default/a2ensite.erb b/src/main/vm/src/cookbooks/apache2/templates/default/a2ensite.erb
new file mode 100755
index 0000000..4288869
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/templates/default/a2ensite.erb
@@ -0,0 +1,38 @@
+#!/bin/sh -e
+
+SYSCONFDIR='<%= node[:apache][:dir] %>'
+
+if [ -z $1 ]; then
+        echo "Which site would you like to enable?"
+        echo -n "Your choices are: "
+        ls $SYSCONFDIR/sites-available/* | \
+        sed -e "s,$SYSCONFDIR/sites-available/,,g" | xargs echo
+        echo -n "Site name? "
+        read SITENAME
+else
+        SITENAME=$1
+fi
+
+if [ $SITENAME = "default" ]; then
+        PRIORITY="000"
+fi
+
+if [ -e $SYSCONFDIR/sites-enabled/$SITENAME -o \
+     -e $SYSCONFDIR/sites-enabled/"$PRIORITY"-"$SITENAME" ]; then
+        echo "This site is already enabled!"
+        exit 0
+fi
+
+if ! [ -e $SYSCONFDIR/sites-available/$SITENAME ]; then
+        echo "This site does not exist!"
+        exit 1
+fi
+
+if [ $SITENAME = "default" ]; then
+        ln -sf $SYSCONFDIR/sites-available/$SITENAME \
+               $SYSCONFDIR/sites-enabled/"$PRIORITY"-"$SITENAME"
+else
+        ln -sf $SYSCONFDIR/sites-available/$SITENAME $SYSCONFDIR/sites-enabled/$SITENAME
+fi
+
+echo "Site $SITENAME installed; reload apache to enable."
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/templates/default/apache2.conf.erb
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/templates/default/apache2.conf.erb b/src/main/vm/src/cookbooks/apache2/templates/default/apache2.conf.erb
new file mode 100755
index 0000000..c94b92a
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/templates/default/apache2.conf.erb
@@ -0,0 +1,230 @@
+#
+# Generated by Chef
+#
+# Based on the Ubuntu apache2.conf
+
+ServerRoot "<%= node[:apache][:dir] %>"
+
+#
+# The accept serialization lock file MUST BE STORED ON A LOCAL DISK.
+#
+<% if node[:platform] == "debian" || node[:platform] == "ubuntu" -%>
+LockFile /var/lock/apache2/accept.lock
+<% else %>
+LockFile logs/accept.lock
+<% end -%>
+
+#
+# PidFile: The file in which the server should record its process
+# identification number when it starts.
+#
+<% if node[:platform] == "debian" || node[:platform] == "ubuntu" -%>
+PidFile /var/run/apache2.pid
+<% elsif node[:platform] == "centos" || node[:platform] == "redhat" || node[:platform] == "fedora" -%>
+PidFile /var/run/httpd.pid
+<% else -%>
+PidFile logs/httpd.pid
+<% end -%>
+
+#
+# Timeout: The number of seconds before receives and sends time out.
+#
+Timeout <%= node[:apache][:timeout] %>
+
+#
+# KeepAlive: Whether or not to allow persistent connections (more than
+# one request per connection). Set to "Off" to deactivate.
+#
+KeepAlive <%= node[:apache][:keepalive] %>
+
+#
+# MaxKeepAliveRequests: The maximum number of requests to allow
+# during a persistent connection. Set to 0 to allow an unlimited amount.
+# We recommend you leave this number high, for maximum performance.
+#
+MaxKeepAliveRequests <%= node[:apache][:keepaliverequests] %>
+
+#
+# KeepAliveTimeout: Number of seconds to wait for the next request from the
+# same client on the same connection.
+#
+KeepAliveTimeout <%= node[:apache][:keepalivetimeout] %>
+
+##
+## Server-Pool Size Regulation (MPM specific)
+## 
+
+# prefork MPM
+# StartServers: number of server processes to start
+# MinSpareServers: minimum number of server processes which are kept spare
+# MaxSpareServers: maximum number of server processes which are kept spare
+# MaxClients: maximum number of server processes allowed to start
+# MaxRequestsPerChild: maximum number of requests a server process serves
+<IfModule mpm_prefork_module>
+    StartServers          <%= node[:apache][:prefork][:startservers] %>
+    MinSpareServers       <%= node[:apache][:prefork][:minspareservers] %>
+    MaxSpareServers       <%= node[:apache][:prefork][:maxspareservers] %>
+    ServerLimit           <%= node[:apache][:prefork][:serverlimit] %>
+    MaxClients            <%= node[:apache][:prefork][:maxclients] %>
+    MaxRequestsPerChild   <%= node[:apache][:prefork][:maxrequestsperchild] %>
+</IfModule>
+
+# worker MPM
+# StartServers: initial number of server processes to start
+# MaxClients: maximum number of simultaneous client connections
+# MinSpareThreads: minimum number of worker threads which are kept spare
+# MaxSpareThreads: maximum number of worker threads which are kept spare
+# ThreadsPerChild: constant number of worker threads in each server process
+# MaxRequestsPerChild: maximum number of requests a server process serves
+<IfModule mpm_worker_module>
+    StartServers          <%= node[:apache][:worker][:startservers] %>
+    MaxClients            <%= node[:apache][:worker][:maxclients] %>
+    MinSpareThreads       <%= node[:apache][:worker][:minsparethreads] %>
+    MaxSpareThreads       <%= node[:apache][:worker][:maxsparethreads] %>
+    ThreadsPerChild       <%= node[:apache][:worker][:threadsperchild] %>
+    MaxRequestsPerChild   <%= node[:apache][:worker][:maxrequestsperchild] %>
+</IfModule>
+
+User <%= node[:apache][:user] %>
+Group <%= node[:apache][:user] %>
+
+#
+# AccessFileName: The name of the file to look for in each directory
+# for additional configuration directives.  See also the AllowOverride
+# directive.
+#
+
+AccessFileName .htaccess
+
+#
+# The following lines prevent .htaccess and .htpasswd files from being 
+# viewed by Web clients. 
+#
+<Files ~ "^\.ht">
+    Order allow,deny
+    Deny from all
+</Files>
+
+#
+# DefaultType is the default MIME type the server will use for a document
+# if it cannot otherwise determine one, such as from filename extensions.
+# If your server contains mostly text or HTML documents, "text/plain" is
+# a good value.  If most of your content is binary, such as applications
+# or images, you may want to use "application/octet-stream" instead to
+# keep browsers from trying to display binary files as though they are
+# text.
+#
+DefaultType text/plain
+
+
+#
+# HostnameLookups: Log the names of clients or just their IP addresses
+# e.g., www.apache.org (on) or 204.62.129.132 (off).
+# The default is off because it'd be overall better for the net if people
+# had to knowingly turn this feature on, since enabling it means that
+# each client request will result in AT LEAST one lookup request to the
+# nameserver.
+#
+HostnameLookups Off
+
+# ErrorLog: The location of the error log file.
+# If you do not specify an ErrorLog directive within a <VirtualHost>
+# container, error messages relating to that virtual host will be
+# logged here.  If you *do* define an error logfile for a <VirtualHost>
+# container, that host's errors will be logged there and not here.
+#
+ErrorLog <%= node[:apache][:log_dir] %>/error.log 
+
+#
+# LogLevel: Control the number of messages logged to the error_log.
+# Possible values include: debug, info, notice, warn, error, crit,
+# alert, emerg.
+#
+LogLevel warn
+
+# Include module configuration:
+Include <%= node[:apache][:dir] %>/mods-enabled/*.load
+Include <%= node[:apache][:dir] %>/mods-enabled/*.conf
+
+# Include ports listing
+Include <%= node[:apache][:dir] %>/ports.conf
+
+#
+# The following directives define some format nicknames for use with
+# a CustomLog directive (see below).
+#
+LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
+LogFormat "%h %l %u %t \"%r\" %>s %b" common
+LogFormat "%{Referer}i -> %U" referer
+LogFormat "%{User-agent}i" agent
+#
+
+# Customizable error responses come in three flavors:
+# 1) plain text 2) local redirects 3) external redirects
+#
+# Some examples:
+#ErrorDocument 500 "The server made a boo boo."
+#ErrorDocument 404 /missing.html
+#ErrorDocument 404 "/cgi-bin/missing_handler.pl"
+#ErrorDocument 402 http://www.example.com/subscription_info.html
+#
+
+#
+# Putting this all together, we can internationalize error responses.
+#
+# We use Alias to redirect any /error/HTTP_<error>.html.var response to
+# our collection of by-error message multi-language collections.  We use 
+# includes to substitute the appropriate text.
+#
+# You can modify the messages' appearance without changing any of the
+# default HTTP_<error>.html.var files by adding the line:
+#
+#   Alias /error/include/ "/your/include/path/"
+#
+# which allows you to create your own set of files by starting with the
+# /usr/share/apache2/error/include/ files and copying them to /your/include/path/, 
+# even on a per-VirtualHost basis.  The default include files will display
+# your Apache version number and your ServerAdmin email address regardless
+# of the setting of ServerSignature.
+#
+# The internationalized error documents require mod_alias, mod_include
+# and mod_negotiation.  To activate them, uncomment the following 30 lines.
+
+#    Alias /error/ "/usr/share/apache2/error/"
+#
+#    <Directory "/usr/share/apache2/error">
+#        AllowOverride None
+#        Options IncludesNoExec
+#        AddOutputFilter Includes html
+#        AddHandler type-map var
+#        Order allow,deny
+#        Allow from all
+#        LanguagePriority en cs de es fr it nl sv pt-br ro
+#        ForceLanguagePriority Prefer Fallback
+#    </Directory>
+#
+#    ErrorDocument 400 /error/HTTP_BAD_REQUEST.html.var
+#    ErrorDocument 401 /error/HTTP_UNAUTHORIZED.html.var
+#    ErrorDocument 403 /error/HTTP_FORBIDDEN.html.var
+#    ErrorDocument 404 /error/HTTP_NOT_FOUND.html.var
+#    ErrorDocument 405 /error/HTTP_METHOD_NOT_ALLOWED.html.var
+#    ErrorDocument 408 /error/HTTP_REQUEST_TIME_OUT.html.var
+#    ErrorDocument 410 /error/HTTP_GONE.html.var
+#    ErrorDocument 411 /error/HTTP_LENGTH_REQUIRED.html.var
+#    ErrorDocument 412 /error/HTTP_PRECONDITION_FAILED.html.var
+#    ErrorDocument 413 /error/HTTP_REQUEST_ENTITY_TOO_LARGE.html.var
+#    ErrorDocument 414 /error/HTTP_REQUEST_URI_TOO_LARGE.html.var
+#    ErrorDocument 415 /error/HTTP_UNSUPPORTED_MEDIA_TYPE.html.var
+#    ErrorDocument 500 /error/HTTP_INTERNAL_SERVER_ERROR.html.var
+#    ErrorDocument 501 /error/HTTP_NOT_IMPLEMENTED.html.var
+#    ErrorDocument 502 /error/HTTP_BAD_GATEWAY.html.var
+#    ErrorDocument 503 /error/HTTP_SERVICE_UNAVAILABLE.html.var
+#    ErrorDocument 506 /error/HTTP_VARIANT_ALSO_VARIES.html.var
+
+
+
+# Include generic snippets of statements
+Include <%= node[:apache][:dir] %>/conf.d/
+
+# Include the virtual host configurations:
+Include <%= node[:apache][:dir] %>/sites-enabled/

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/templates/default/apache2.god.erb
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/templates/default/apache2.god.erb b/src/main/vm/src/cookbooks/apache2/templates/default/apache2.god.erb
new file mode 100755
index 0000000..b7315e4
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/templates/default/apache2.god.erb
@@ -0,0 +1,19 @@
+God.watch do |w|
+  w.name = "apache2"
+  w.interval = 30.seconds # default
+  w.start = "<%= @params[:start] %>"
+  w.stop = "/etc/init.d/httpd stop"
+  w.restart = "<%= @params[:restart] %>"
+  w.start_grace = 10.seconds
+  w.restart_grace = 10.seconds
+  w.pid_file = "/var/run/httpd.pid"
+  w.behavior(:clean_pid_file)
+
+  w.start_if do |start|
+    start.condition(:process_running) do |c|
+        c.interval = 5.seconds
+        c.running = false
+        c.notify = 'admin'
+    end
+  end
+end

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/templates/default/charset.erb
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/templates/default/charset.erb b/src/main/vm/src/cookbooks/apache2/templates/default/charset.erb
new file mode 100755
index 0000000..40d7198
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/templates/default/charset.erb
@@ -0,0 +1,6 @@
+# Read the documentation before enabling AddDefaultCharset.
+# In general, it is only a good idea if you know that all your files
+# have this encoding. It will override any encoding given in the files
+# in meta http-equiv or xml encoding tags.
+
+#AddDefaultCharset UTF-8

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/templates/default/default-site.erb
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/templates/default/default-site.erb b/src/main/vm/src/cookbooks/apache2/templates/default/default-site.erb
new file mode 100755
index 0000000..14b2563
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/templates/default/default-site.erb
@@ -0,0 +1,57 @@
+<VirtualHost *:80>
+        ServerAdmin <%= node[:apache][:contact] %>
+
+        DocumentRoot /var/www/
+        <Directory />
+                Options FollowSymLinks
+                AllowOverride None
+        </Directory>
+        <Directory /var/www/>
+                Options Indexes FollowSymLinks MultiViews
+                AllowOverride None
+                Order allow,deny
+                allow from all
+                # This directive allows us to have apache2's default start page
+                # in /apache2-default/, but still have / go to the right place
+                #RedirectMatch ^/$ /apache2-default/
+        </Directory>
+
+        ScriptAlias /cgi-bin/ /usr/lib/cgi-bin/
+        <Directory "/usr/lib/cgi-bin">
+                AllowOverride None
+                Options ExecCGI -MultiViews +SymLinksIfOwnerMatch
+                Order allow,deny
+                Allow from all
+        </Directory>
+
+        ErrorLog <%= node[:apache][:log_dir] %>/error.log 
+
+        # Possible values include: debug, info, notice, warn, error, crit,
+        # alert, emerg.
+        LogLevel warn
+
+        CustomLog <%= node[:apache][:log_dir] %>/access.log combined
+        ServerSignature On
+
+        Alias /doc/ "/usr/share/doc/"
+        <Directory "/usr/share/doc/">
+            Options Indexes MultiViews FollowSymLinks
+            AllowOverride None
+            Order deny,allow
+            Deny from all
+            Allow from 127.0.0.0/255.0.0.0 ::1/128
+        </Directory>
+
+        <% if node[:platform] == "centos" || node[:platform] == "redhat" || node[:platform] == "fedora" -%>
+        #
+        # This configuration file enables the default "Welcome"
+        # page if there is no default index page present for
+        # the root URL.  To disable the Welcome page, comment
+        # out all the lines below.
+        #
+        <LocationMatch "^/+$">
+            Options -Indexes
+            ErrorDocument 403 /error/noindex.html
+        </LocationMatch>
+        <% end -%>
+</VirtualHost>

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/templates/default/mod_auth_openid.rb.erb
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/templates/default/mod_auth_openid.rb.erb b/src/main/vm/src/cookbooks/apache2/templates/default/mod_auth_openid.rb.erb
new file mode 100755
index 0000000..51fc1d7
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/templates/default/mod_auth_openid.rb.erb
@@ -0,0 +1,12 @@
+#!/usr/bin/env ruby
+
+allowed_openids = Array.new
+<% node[:apache][:allowed_openids].each do |id| -%>
+allowed_openids << "<%= id %>"
+<% end -%>
+
+if allowed_openids.grep(ARGV[0]).length > 0
+  exit 0
+else
+  exit 1
+end

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/templates/default/mods/.svn/all-wcprops
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/templates/default/mods/.svn/all-wcprops b/src/main/vm/src/cookbooks/apache2/templates/default/mods/.svn/all-wcprops
new file mode 100755
index 0000000..cc0f912
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/templates/default/mods/.svn/all-wcprops
@@ -0,0 +1,83 @@
+K 25
+svn:wc:ra_dav:version-url
+V 114
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks/apache2/templates/default/mods
+END
+deflate.conf.erb
+K 25
+svn:wc:ra_dav:version-url
+V 131
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks/apache2/templates/default/mods/deflate.conf.erb
+END
+mime.conf.erb
+K 25
+svn:wc:ra_dav:version-url
+V 128
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks/apache2/templates/default/mods/mime.conf.erb
+END
+alias.conf.erb
+K 25
+svn:wc:ra_dav:version-url
+V 129
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks/apache2/templates/default/mods/alias.conf.erb
+END
+authopenid.load.erb
+K 25
+svn:wc:ra_dav:version-url
+V 134
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks/apache2/templates/default/mods/authopenid.load.erb
+END
+fcgid.conf.erb
+K 25
+svn:wc:ra_dav:version-url
+V 129
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks/apache2/templates/default/mods/fcgid.conf.erb
+END
+dir.conf.erb
+K 25
+svn:wc:ra_dav:version-url
+V 127
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks/apache2/templates/default/mods/dir.conf.erb
+END
+autoindex.conf.erb
+K 25
+svn:wc:ra_dav:version-url
+V 133
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks/apache2/templates/default/mods/autoindex.conf.erb
+END
+negotiation.conf.erb
+K 25
+svn:wc:ra_dav:version-url
+V 135
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks/apache2/templates/default/mods/negotiation.conf.erb
+END
+proxy.conf.erb
+K 25
+svn:wc:ra_dav:version-url
+V 129
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks/apache2/templates/default/mods/proxy.conf.erb
+END
+ssl.conf.erb
+K 25
+svn:wc:ra_dav:version-url
+V 127
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks/apache2/templates/default/mods/ssl.conf.erb
+END
+README
+K 25
+svn:wc:ra_dav:version-url
+V 121
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks/apache2/templates/default/mods/README
+END
+setenvif.conf.erb
+K 25
+svn:wc:ra_dav:version-url
+V 132
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks/apache2/templates/default/mods/setenvif.conf.erb
+END
+status.conf.erb
+K 25
+svn:wc:ra_dav:version-url
+V 130
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks/apache2/templates/default/mods/status.conf.erb
+END

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/templates/default/mods/.svn/entries
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/templates/default/mods/.svn/entries b/src/main/vm/src/cookbooks/apache2/templates/default/mods/.svn/entries
new file mode 100755
index 0000000..ebe15ab
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/templates/default/mods/.svn/entries
@@ -0,0 +1,470 @@
+10
+
+dir
+1485921
+https://svn.apache.org/repos/asf/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks/apache2/templates/default/mods
+https://svn.apache.org/repos/asf
+
+
+
+2012-10-10T00:49:17.045897Z
+1474264
+ahart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+13f79535-47bb-0310-9956-ffa450edef68
+
+deflate.conf.erb
+file
+
+
+
+
+2013-05-24T10:13:53.000000Z
+be181978c5856a761c0091b9c37ebb03
+2012-10-10T00:49:17.045897Z
+1474264
+ahart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+855
+
+mime.conf.erb
+file
+
+
+
+
+2013-05-24T10:13:53.000000Z
+07381b9d3f95d2df0d6a1fa3632493e2
+2012-10-10T00:49:17.045897Z
+1474264
+ahart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+6362
+
+alias.conf.erb
+file
+
+
+
+
+2013-05-24T10:13:53.000000Z
+b193116af9bdc1e5427fc10b8f99087b
+2012-10-10T00:49:17.045897Z
+1474264
+ahart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+826
+
+authopenid.load.erb
+file
+
+
+
+
+2013-05-24T10:13:53.000000Z
+480f2cf6ad926cf5b2b4a1d0c9e46c3d
+2012-10-10T00:49:17.045897Z
+1474264
+ahart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+73
+
+fcgid.conf.erb
+file
+
+
+
+
+2013-05-24T10:13:53.000000Z
+7cf690346eed89a806f451ef2be94ffe
+2012-10-10T00:49:17.045897Z
+1474264
+ahart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+318
+
+dir.conf.erb
+file
+
+
+
+
+2013-05-24T10:13:53.000000Z
+b6882491a6d2b823da960f19a50b132f
+2012-10-10T00:49:17.045897Z
+1474264
+ahart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+122
+
+autoindex.conf.erb
+file
+
+
+
+
+2013-05-24T10:13:53.000000Z
+77ea294b47d8d2e4dc68107907da8311
+2012-10-10T00:49:17.045897Z
+1474264
+ahart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+3265
+
+negotiation.conf.erb
+file
+
+
+
+
+2013-05-24T10:13:53.000000Z
+25480201827ba22eef212617006c1491
+2012-10-10T00:49:17.045897Z
+1474264
+ahart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+666
+
+proxy.conf.erb
+file
+
+
+
+
+2013-05-24T10:13:53.000000Z
+91c1f50d8c18df72c50dbe82e78156fa
+2012-10-10T00:49:17.045897Z
+1474264
+ahart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+589
+
+ssl.conf.erb
+file
+
+
+
+
+2013-05-24T10:13:53.000000Z
+15fd18938f51e36739dd784b10b9c215
+2012-10-10T00:49:17.045897Z
+1474264
+ahart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+2732
+
+README
+file
+
+
+
+
+2013-05-24T10:13:53.000000Z
+18d5765cc152b19b351790cfcf00f3b8
+2012-10-10T00:49:17.045897Z
+1474264
+ahart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+132
+
+setenvif.conf.erb
+file
+
+
+
+
+2013-05-24T10:13:53.000000Z
+e79d13751e71f24206025ffcd25a20cb
+2012-10-10T00:49:17.045897Z
+1474264
+ahart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+1122
+
+status.conf.erb
+file
+
+
+
+
+2013-05-24T10:13:53.000000Z
+2db2247ae37ae1e2bf9bf35413c14ab7
+2012-10-10T00:49:17.045897Z
+1474264
+ahart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+398
+

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/templates/default/mods/.svn/text-base/README.svn-base
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/templates/default/mods/.svn/text-base/README.svn-base b/src/main/vm/src/cookbooks/apache2/templates/default/mods/.svn/text-base/README.svn-base
new file mode 100755
index 0000000..df9f0bc
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/templates/default/mods/.svn/text-base/README.svn-base
@@ -0,0 +1,2 @@
+These configs are taken from a Debian apache2.2-common 2.2.11-3 install. They 
+work on CentOS 5.3 with a few conditions using erb. 

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/templates/default/mods/.svn/text-base/alias.conf.erb.svn-base
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/templates/default/mods/.svn/text-base/alias.conf.erb.svn-base b/src/main/vm/src/cookbooks/apache2/templates/default/mods/.svn/text-base/alias.conf.erb.svn-base
new file mode 100755
index 0000000..45568a5
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/templates/default/mods/.svn/text-base/alias.conf.erb.svn-base
@@ -0,0 +1,24 @@
+<IfModule alias_module>
+#
+# Aliases: Add here as many aliases as you need (with no limit). The format is 
+# Alias fakename realname
+#
+# Note that if you include a trailing / on fakename then the server will
+# require it to be present in the URL.  So "/icons" isn't aliased in this
+# example, only "/icons/".  If the fakename is slash-terminated, then the 
+# realname must also be slash terminated, and if the fakename omits the 
+# trailing slash, the realname must also omit it.
+#
+# We include the /icons/ alias for FancyIndexed directory listings.  If
+# you do not use FancyIndexing, you may comment this out.
+#
+Alias /icons/ "<%= node[:apache][:icondir] %>"
+
+<Directory "<%= node[:apache][:icondir] %>">
+    Options Indexes MultiViews
+    AllowOverride None
+    Order allow,deny
+    Allow from all
+</Directory>
+
+</IfModule>

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/templates/default/mods/.svn/text-base/authopenid.load.erb.svn-base
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/templates/default/mods/.svn/text-base/authopenid.load.erb.svn-base b/src/main/vm/src/cookbooks/apache2/templates/default/mods/.svn/text-base/authopenid.load.erb.svn-base
new file mode 100755
index 0000000..f21882b
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/templates/default/mods/.svn/text-base/authopenid.load.erb.svn-base
@@ -0,0 +1 @@
+LoadModule authopenid_module /usr/lib/apache2/modules/mod_auth_openid.so

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/templates/default/mods/.svn/text-base/autoindex.conf.erb.svn-base
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/templates/default/mods/.svn/text-base/autoindex.conf.erb.svn-base b/src/main/vm/src/cookbooks/apache2/templates/default/mods/.svn/text-base/autoindex.conf.erb.svn-base
new file mode 100755
index 0000000..3839093
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/templates/default/mods/.svn/text-base/autoindex.conf.erb.svn-base
@@ -0,0 +1,101 @@
+<IfModule mod_autoindex.c>
+#
+# Directives controlling the display of server-generated directory listings.
+#
+
+#
+# IndexOptions: Controls the appearance of server-generated directory
+# listings.
+# Remove/replace the "Charset=UTF-8" if you don't use UTF-8 for your filenames.
+#
+IndexOptions FancyIndexing VersionSort HTMLTable NameWidth=* DescriptionWidth=* Charset=UTF-8
+
+#
+# AddIcon* directives tell the server which icon to show for different
+# files or filename extensions.  These are only displayed for
+# FancyIndexed directories.
+#
+AddIconByEncoding (CMP,/icons/compressed.gif) x-compress x-gzip x-bzip2
+
+AddIconByType (TXT,/icons/text.gif) text/*
+AddIconByType (IMG,/icons/image2.gif) image/*
+AddIconByType (SND,/icons/sound2.gif) audio/*
+AddIconByType (VID,/icons/movie.gif) video/*
+
+AddIcon /icons/binary.gif .bin .exe
+AddIcon /icons/binhex.gif .hqx
+AddIcon /icons/tar.gif .tar
+AddIcon /icons/world2.gif .wrl .wrl.gz .vrml .vrm .iv
+AddIcon /icons/compressed.gif .Z .z .tgz .gz .zip
+AddIcon /icons/a.gif .ps .ai .eps
+AddIcon /icons/layout.gif .html .shtml .htm .pdf
+AddIcon /icons/text.gif .txt
+AddIcon /icons/c.gif .c
+AddIcon /icons/p.gif .pl .py
+AddIcon /icons/f.gif .for
+AddIcon /icons/dvi.gif .dvi
+AddIcon /icons/uuencoded.gif .uu
+AddIcon /icons/script.gif .conf .sh .shar .csh .ksh .tcl
+AddIcon /icons/tex.gif .tex
+# It's a suffix rule, so simply matching "core" matches "score" as well !
+AddIcon /icons/bomb.gif /core
+AddIcon (SND,/icons/sound2.gif) .ogg
+AddIcon (VID,/icons/movie.gif) .ogm
+
+AddIcon /icons/back.gif ..
+AddIcon /icons/hand.right.gif README
+AddIcon /icons/folder.gif ^^DIRECTORY^^
+AddIcon /icons/blank.gif ^^BLANKICON^^
+
+# Default icons for OpenDocument format
+AddIcon /icons/odf6odt-20x22.png .odt
+AddIcon /icons/odf6ods-20x22.png .ods
+AddIcon /icons/odf6odp-20x22.png .odp
+AddIcon /icons/odf6odg-20x22.png .odg
+AddIcon /icons/odf6odc-20x22.png .odc
+AddIcon /icons/odf6odf-20x22.png .odf
+AddIcon /icons/odf6odb-20x22.png .odb
+AddIcon /icons/odf6odi-20x22.png .odi
+AddIcon /icons/odf6odm-20x22.png .odm
+
+AddIcon /icons/odf6ott-20x22.png .ott
+AddIcon /icons/odf6ots-20x22.png .ots
+AddIcon /icons/odf6otp-20x22.png .otp
+AddIcon /icons/odf6otg-20x22.png .otg
+AddIcon /icons/odf6otc-20x22.png .otc
+AddIcon /icons/odf6otf-20x22.png .otf
+AddIcon /icons/odf6oti-20x22.png .oti
+AddIcon /icons/odf6oth-20x22.png .oth
+
+#
+# DefaultIcon is which icon to show for files which do not have an icon
+# explicitly set.
+#
+DefaultIcon /icons/unknown.gif
+
+#
+# AddDescription allows you to place a short description after a file in
+# server-generated indexes.  These are only displayed for FancyIndexed
+# directories.
+# Format: AddDescription "description" filename
+#
+#AddDescription "GZIP compressed document" .gz
+#AddDescription "tar archive" .tar
+#AddDescription "GZIP compressed tar archive" .tgz
+
+#
+# ReadmeName is the name of the README file the server will look for by
+# default, and append to directory listings.
+#
+# HeaderName is the name of a file which should be prepended to
+# directory indexes. 
+ReadmeName README.html
+HeaderName HEADER.html
+
+#
+# IndexIgnore is a set of filenames which directory indexing should ignore
+# and not include in the listing.  Shell-style wildcarding is permitted.
+#
+IndexIgnore .??* *~ *# RCS CVS *,v *,t 
+
+</IfModule>

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/templates/default/mods/.svn/text-base/deflate.conf.erb.svn-base
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/templates/default/mods/.svn/text-base/deflate.conf.erb.svn-base b/src/main/vm/src/cookbooks/apache2/templates/default/mods/.svn/text-base/deflate.conf.erb.svn-base
new file mode 100755
index 0000000..2e41975
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/templates/default/mods/.svn/text-base/deflate.conf.erb.svn-base
@@ -0,0 +1,16 @@
+<IfModule mod_deflate.c>
+          AddOutputFilterByType DEFLATE text/html
+          AddOutputFilterByType DEFLATE text/css
+          AddOutputFilterByType DEFLATE text/plain
+          AddOutputFilterByType DEFLATE text/xml
+          AddOutputFilterByType DEFLATE application/xhtml+xml
+          AddOutputFilterByType DEFLATE application/xml
+          AddOutputFilterByType DEFLATE image/svg+xml
+          AddOutputFilterByType DEFLATE application/rss+xml
+          AddOutputFilterByType DEFLATE application/atom_xml
+          AddOutputFilterByType DEFLATE application/javascript
+          AddOutputFilterByType DEFLATE application/x-javascript
+          AddOutputFilterByType DEFLATE application/x-httpd-php
+          AddOutputFilterByType DEFLATE application/x-httpd-fastphp
+          AddOutputFilterByType DEFLATE application/x-httpd-eruby
+</IfModule>

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/templates/default/mods/.svn/text-base/dir.conf.erb.svn-base
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/templates/default/mods/.svn/text-base/dir.conf.erb.svn-base b/src/main/vm/src/cookbooks/apache2/templates/default/mods/.svn/text-base/dir.conf.erb.svn-base
new file mode 100755
index 0000000..e16fcb3
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/templates/default/mods/.svn/text-base/dir.conf.erb.svn-base
@@ -0,0 +1,5 @@
+<IfModule mod_dir.c>
+
+          DirectoryIndex index.html index.cgi index.pl index.php index.xhtml index.htm
+
+</IfModule>

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/templates/default/mods/.svn/text-base/fcgid.conf.erb.svn-base
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/templates/default/mods/.svn/text-base/fcgid.conf.erb.svn-base b/src/main/vm/src/cookbooks/apache2/templates/default/mods/.svn/text-base/fcgid.conf.erb.svn-base
new file mode 100755
index 0000000..0e6fc9a
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/templates/default/mods/.svn/text-base/fcgid.conf.erb.svn-base
@@ -0,0 +1,10 @@
+<IfModule mod_fcgid.c>
+  AddHandler    fcgid-script .fcgi
+  IPCConnectTimeout 20
+</IfModule>
+
+<% if node[:platform] == "centos" || node[:platform] == "redhat" || node[:platform] == "fedora" -%>
+# Sane place to put sockets and shared memory file
+SocketPath run/mod_fcgid
+SharememPath run/mod_fcgid/fcgid_shm
+<% end -%>

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/templates/default/mods/.svn/text-base/mime.conf.erb.svn-base
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/templates/default/mods/.svn/text-base/mime.conf.erb.svn-base b/src/main/vm/src/cookbooks/apache2/templates/default/mods/.svn/text-base/mime.conf.erb.svn-base
new file mode 100755
index 0000000..b6954a3
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/templates/default/mods/.svn/text-base/mime.conf.erb.svn-base
@@ -0,0 +1,191 @@
+<IfModule mod_mime.c>
+
+#
+# TypesConfig points to the file containing the list of mappings from
+# filename extension to MIME-type.
+#
+TypesConfig /etc/mime.types
+
+#
+# AddType allows you to add to or override the MIME configuration
+# file mime.types for specific file types.
+#
+#AddType application/x-gzip .tgz
+#
+# AddEncoding allows you to have certain browsers uncompress
+# information on the fly. Note: Not all browsers support this.
+# Despite the name similarity, the following Add* directives have
+# nothing to do with the FancyIndexing customization directives above.
+#
+#AddEncoding x-compress .Z
+#AddEncoding x-gzip .gz .tgz
+#AddEncoding x-bzip2 .bz2
+#
+# If the AddEncoding directives above are commented-out, then you
+# probably should define those extensions to indicate media types:
+#
+AddType application/x-compress .Z
+AddType application/x-gzip .gz .tgz
+AddType application/x-bzip2 .bz2
+
+#
+# DefaultLanguage and AddLanguage allows you to specify the language of 
+# a document. You can then use content negotiation to give a browser a 
+# file in a language the user can understand.
+#
+# Specify a default language. This means that all data
+# going out without a specific language tag (see below) will 
+# be marked with this one. You probably do NOT want to set
+# this unless you are sure it is correct for all cases.
+#
+# * It is generally better to not mark a page as 
+# * being a certain language than marking it with the wrong
+# * language!
+#
+# DefaultLanguage nl
+#
+# Note 1: The suffix does not have to be the same as the language
+# keyword --- those with documents in Polish (whose net-standard
+# language code is pl) may wish to use "AddLanguage pl .po" to
+# avoid the ambiguity with the common suffix for perl scripts.
+#
+# Note 2: The example entries below illustrate that in some cases 
+# the two character 'Language' abbreviation is not identical to 
+# the two character 'Country' code for its country,
+# E.g. 'Danmark/dk' versus 'Danish/da'.
+#
+# Note 3: In the case of 'ltz' we violate the RFC by using a three char
+# specifier. There is 'work in progress' to fix this and get
+# the reference data for rfc1766 cleaned up.
+#
+# Catalan (ca) - Croatian (hr) - Czech (cs) - Danish (da) - Dutch (nl)
+# English (en) - Esperanto (eo) - Estonian (et) - French (fr) - German (de)
+# Greek-Modern (el) - Hebrew (he) - Italian (it) - Japanese (ja)
+# Korean (ko) - Luxembourgeois* (ltz) - Norwegian Nynorsk (nn)
+# Norwegian (no) - Polish (pl) - Portugese (pt)
+# Brazilian Portuguese (pt-BR) - Russian (ru) - Swedish (sv)
+# Simplified Chinese (zh-CN) - Spanish (es) - Traditional Chinese (zh-TW)
+#
+AddLanguage ca .ca
+AddLanguage cs .cz .cs
+AddLanguage da .dk
+AddLanguage de .de
+AddLanguage el .el
+AddLanguage en .en
+AddLanguage eo .eo
+# See README.Debian for Spanish
+AddLanguage es .es
+AddLanguage et .et
+AddLanguage fr .fr
+AddLanguage he .he
+AddLanguage hr .hr
+AddLanguage it .it
+AddLanguage ja .ja
+AddLanguage ko .ko
+AddLanguage ltz .ltz
+AddLanguage nl .nl
+AddLanguage nn .nn
+AddLanguage no .no
+AddLanguage pl .po
+AddLanguage pt .pt
+AddLanguage pt-BR .pt-br
+AddLanguage ru .ru
+AddLanguage sv .sv
+# See README.Debian for Turkish
+AddLanguage tr .tr
+AddLanguage zh-CN .zh-cn
+AddLanguage zh-TW .zh-tw
+
+#
+# Commonly used filename extensions to character sets. You probably
+# want to avoid clashes with the language extensions, unless you
+# are good at carefully testing your setup after each change.
+# See http://www.iana.org/assignments/character-sets for the
+# official list of charset names and their respective RFCs.
+#
+AddCharset us-ascii    .ascii .us-ascii
+AddCharset ISO-8859-1  .iso8859-1  .latin1
+AddCharset ISO-8859-2  .iso8859-2  .latin2 .cen
+AddCharset ISO-8859-3  .iso8859-3  .latin3
+AddCharset ISO-8859-4  .iso8859-4  .latin4
+AddCharset ISO-8859-5  .iso8859-5  .cyr .iso-ru
+AddCharset ISO-8859-6  .iso8859-6  .arb .arabic
+AddCharset ISO-8859-7  .iso8859-7  .grk .greek
+AddCharset ISO-8859-8  .iso8859-8  .heb .hebrew
+AddCharset ISO-8859-9  .iso8859-9  .latin5 .trk
+AddCharset ISO-8859-10  .iso8859-10  .latin6
+AddCharset ISO-8859-13  .iso8859-13
+AddCharset ISO-8859-14  .iso8859-14  .latin8
+AddCharset ISO-8859-15  .iso8859-15  .latin9
+AddCharset ISO-8859-16  .iso8859-16  .latin10
+AddCharset ISO-2022-JP .iso2022-jp .jis
+AddCharset ISO-2022-KR .iso2022-kr .kis
+AddCharset ISO-2022-CN .iso2022-cn .cis
+AddCharset Big5        .Big5       .big5 .b5
+AddCharset cn-Big5     .cn-big5
+# For russian, more than one charset is used (depends on client, mostly):
+AddCharset WINDOWS-1251 .cp-1251   .win-1251
+AddCharset CP866       .cp866
+AddCharset KOI8      .koi8
+AddCharset KOI8-E      .koi8-e
+AddCharset KOI8-r      .koi8-r .koi8-ru
+AddCharset KOI8-U      .koi8-u
+AddCharset KOI8-ru     .koi8-uk .ua
+AddCharset ISO-10646-UCS-2 .ucs2
+AddCharset ISO-10646-UCS-4 .ucs4
+AddCharset UTF-7       .utf7
+AddCharset UTF-8       .utf8
+AddCharset UTF-16      .utf16
+AddCharset UTF-16BE    .utf16be
+AddCharset UTF-16LE    .utf16le
+AddCharset UTF-32      .utf32
+AddCharset UTF-32BE    .utf32be
+AddCharset UTF-32LE    .utf32le
+AddCharset euc-cn      .euc-cn
+AddCharset euc-gb      .euc-gb
+AddCharset euc-jp      .euc-jp
+AddCharset euc-kr      .euc-kr
+#Not sure how euc-tw got in - IANA doesn't list it???
+AddCharset EUC-TW      .euc-tw
+AddCharset gb2312      .gb2312 .gb
+AddCharset iso-10646-ucs-2 .ucs-2 .iso-10646-ucs-2
+AddCharset iso-10646-ucs-4 .ucs-4 .iso-10646-ucs-4
+AddCharset shift_jis   .shift_jis .sjis
+
+#
+# AddHandler allows you to map certain file extensions to "handlers":
+# actions unrelated to filetype. These can be either built into the server
+# or added with the Action directive (see below)
+#
+# To use CGI scripts outside of ScriptAliased directories:
+# (You will also need to add "ExecCGI" to the "Options" directive.)
+#
+#AddHandler cgi-script .cgi
+
+#
+# For files that include their own HTTP headers:
+#
+#AddHandler send-as-is asis
+
+#
+# For server-parsed imagemap files:
+#
+#AddHandler imap-file map
+
+#
+# For type maps (negotiated resources):
+# (This is enabled by default to allow the Apache "It Worked" page
+#  to be distributed in multiple languages.)
+#
+AddHandler type-map var
+
+#
+# Filters allow you to process content before it is sent to the client.
+#
+# To parse .shtml files for server-side includes (SSI):
+# (You will also need to add "Includes" to the "Options" directive.)
+#
+AddType text/html .shtml
+AddOutputFilter INCLUDES .shtml
+
+</IfModule>

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/templates/default/mods/.svn/text-base/negotiation.conf.erb.svn-base
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/templates/default/mods/.svn/text-base/negotiation.conf.erb.svn-base b/src/main/vm/src/cookbooks/apache2/templates/default/mods/.svn/text-base/negotiation.conf.erb.svn-base
new file mode 100755
index 0000000..0e3455b
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/templates/default/mods/.svn/text-base/negotiation.conf.erb.svn-base
@@ -0,0 +1,18 @@
+<IfModule mod_negotiation.c>
+#
+# LanguagePriority allows you to give precedence to some languages
+# in case of a tie during content negotiation.
+#
+# Just list the languages in decreasing order of preference. We have
+# more or less alphabetized them here. You probably want to change this.
+#
+LanguagePriority en ca cs da de el eo es et fr he hr it ja ko ltz nl nn no pl pt pt-BR ru sv tr zh-CN zh-TW
+
+#
+# ForceLanguagePriority allows you to serve a result page rather than
+# MULTIPLE CHOICES (Prefer) [in case of a tie] or NOT ACCEPTABLE (Fallback)
+# [in case no accepted languages matched the available variants]
+#
+ForceLanguagePriority Prefer Fallback
+
+</IfModule>

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/templates/default/mods/.svn/text-base/proxy.conf.erb.svn-base
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/templates/default/mods/.svn/text-base/proxy.conf.erb.svn-base b/src/main/vm/src/cookbooks/apache2/templates/default/mods/.svn/text-base/proxy.conf.erb.svn-base
new file mode 100755
index 0000000..46407a1
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/templates/default/mods/.svn/text-base/proxy.conf.erb.svn-base
@@ -0,0 +1,19 @@
+<IfModule mod_proxy.c>
+        #turning ProxyRequests on and allowing proxying from all may allow
+        #spammers to use your proxy to send email.
+
+        ProxyRequests Off
+
+        <Proxy *>
+                AddDefaultCharset off
+                Order deny,allow
+                Deny from all
+                #Allow from .example.com
+        </Proxy>
+
+        # Enable/disable the handling of HTTP/1.1 "Via:" headers.
+        # ("Full" adds the server version; "Block" removes all outgoing Via: headers)
+        # Set to one of: Off | On | Full | Block
+
+        ProxyVia On
+</IfModule>

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/templates/default/mods/.svn/text-base/setenvif.conf.erb.svn-base
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/templates/default/mods/.svn/text-base/setenvif.conf.erb.svn-base b/src/main/vm/src/cookbooks/apache2/templates/default/mods/.svn/text-base/setenvif.conf.erb.svn-base
new file mode 100755
index 0000000..6b7d6e2
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/templates/default/mods/.svn/text-base/setenvif.conf.erb.svn-base
@@ -0,0 +1,28 @@
+<IfModule mod_setenvif.c>
+
+#
+# The following directives modify normal HTTP response behavior to
+# handle known problems with browser implementations.
+#
+BrowserMatch "Mozilla/2" nokeepalive
+BrowserMatch "MSIE 4\.0b2;" nokeepalive downgrade-1.0 force-response-1.0
+BrowserMatch "RealPlayer 4\.0" force-response-1.0
+BrowserMatch "Java/1\.0" force-response-1.0
+BrowserMatch "JDK/1\.0" force-response-1.0
+
+#
+# The following directive disables redirects on non-GET requests for
+# a directory that does not include the trailing slash.  This fixes a 
+# problem with Microsoft WebFolders which does not appropriately handle 
+# redirects for folders with DAV methods.
+# Same deal with Apple's DAV filesystem and Gnome VFS support for DAV.
+#
+BrowserMatch "Microsoft Data Access Internet Publishing Provider" redirect-carefully
+BrowserMatch "MS FrontPage" redirect-carefully
+BrowserMatch "^WebDrive" redirect-carefully
+BrowserMatch "^WebDAVFS/1.[012]" redirect-carefully
+BrowserMatch "^gnome-vfs/1.0" redirect-carefully
+BrowserMatch "^XML Spy" redirect-carefully
+BrowserMatch "^Dreamweaver-WebDAV-SCM1" redirect-carefully
+
+</IfModule>

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/templates/default/mods/.svn/text-base/ssl.conf.erb.svn-base
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/templates/default/mods/.svn/text-base/ssl.conf.erb.svn-base b/src/main/vm/src/cookbooks/apache2/templates/default/mods/.svn/text-base/ssl.conf.erb.svn-base
new file mode 100755
index 0000000..3b7735f
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/templates/default/mods/.svn/text-base/ssl.conf.erb.svn-base
@@ -0,0 +1,72 @@
+<IfModule mod_ssl.c>
+#
+# Pseudo Random Number Generator (PRNG):
+# Configure one or more sources to seed the PRNG of the SSL library.
+# The seed data should be of good random quality.
+# WARNING! On some platforms /dev/random blocks if not enough entropy
+# is available. This means you then cannot use the /dev/random device
+# because it would lead to very long connection times (as long as
+# it requires to make more entropy available). But usually those
+# platforms additionally provide a /dev/urandom device which doesn't
+# block. So, if available, use this one instead. Read the mod_ssl User
+# Manual for more details.
+#
+SSLRandomSeed startup builtin
+SSLRandomSeed startup file:/dev/urandom 512
+SSLRandomSeed connect builtin
+SSLRandomSeed connect file:/dev/urandom 512
+
+##
+##  SSL Global Context
+##
+##  All SSL configuration in this context applies both to
+##  the main server and all SSL-enabled virtual hosts.
+##
+
+#
+#   Some MIME-types for downloading Certificates and CRLs
+#
+AddType application/x-x509-ca-cert .crt
+AddType application/x-pkcs7-crl    .crl
+
+#   Pass Phrase Dialog:
+#   Configure the pass phrase gathering process.
+#   The filtering dialog program (`builtin' is a internal
+#   terminal dialog) has to provide the pass phrase on stdout.
+SSLPassPhraseDialog  builtin
+
+#   Inter-Process Session Cache:
+#   Configure the SSL Session Cache: First the mechanism 
+#   to use and second the expiring timeout (in seconds).
+#SSLSessionCache         dbm:/var/run/apache2/ssl_scache
+<% if node[:platform] == "centos" || node[:platform] == "redhat" || node[:platform] == "fedora" -%>
+SSLSessionCache        shmcb:/var/cache/mod_ssl/scache(512000)
+<% else -%>
+SSLSessionCache        shmcb:/var/run/apache2/ssl_scache
+<% end -%> 
+SSLSessionCacheTimeout  300
+
+#   Semaphore:
+#   Configure the path to the mutual exclusion semaphore the
+#   SSL engine uses internally for inter-process synchronization. 
+<% if node[:platform] == "centos" || node[:platform] == "redhat" || node[:platform] == "fedora" -%>
+SSLMutex  default
+<% else -%>
+SSLMutex  file:/var/run/apache2/ssl_mutex
+<% end -%>
+
+#   SSL Cipher Suite:
+#   List the ciphers that the client is permitted to negotiate.
+#   See the mod_ssl documentation for a complete list.
+#   enable only secure ciphers:
+SSLCipherSuite HIGH:MEDIUM:!ADH
+#   Use this instead if you want to allow cipher upgrades via SGC facility.
+#   In this case you also have to use something like 
+#        SSLRequire %{SSL_CIPHER_USEKEYSIZE} >= 128
+#   see http://httpd.apache.org/docs/2.2/ssl/ssl_howto.html.en#upgradeenc
+#SSLCipherSuite ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP:+eNULL
+
+# enable only secure protocols: SSLv3 and TLSv1, but not SSLv2
+SSLProtocol all -SSLv2
+
+</IfModule>

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/templates/default/mods/.svn/text-base/status.conf.erb.svn-base
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/templates/default/mods/.svn/text-base/status.conf.erb.svn-base b/src/main/vm/src/cookbooks/apache2/templates/default/mods/.svn/text-base/status.conf.erb.svn-base
new file mode 100755
index 0000000..679d111
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/templates/default/mods/.svn/text-base/status.conf.erb.svn-base
@@ -0,0 +1,16 @@
+<IfModule mod_status.c>
+#
+# Allow server status reports generated by mod_status,
+# with the URL of http://servername/server-status
+# Uncomment and change the ".example.com" to allow
+# access from other hosts.
+#
+<Location /server-status>
+    SetHandler server-status
+    Order deny,allow
+    Deny from all
+    Allow from localhost ip6-localhost
+#    Allow from .example.com
+</Location>
+
+</IfModule>

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/templates/default/mods/README
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/templates/default/mods/README b/src/main/vm/src/cookbooks/apache2/templates/default/mods/README
new file mode 100755
index 0000000..df9f0bc
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/templates/default/mods/README
@@ -0,0 +1,2 @@
+These configs are taken from a Debian apache2.2-common 2.2.11-3 install. They 
+work on CentOS 5.3 with a few conditions using erb. 

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/templates/default/mods/alias.conf.erb
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/templates/default/mods/alias.conf.erb b/src/main/vm/src/cookbooks/apache2/templates/default/mods/alias.conf.erb
new file mode 100755
index 0000000..45568a5
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/templates/default/mods/alias.conf.erb
@@ -0,0 +1,24 @@
+<IfModule alias_module>
+#
+# Aliases: Add here as many aliases as you need (with no limit). The format is 
+# Alias fakename realname
+#
+# Note that if you include a trailing / on fakename then the server will
+# require it to be present in the URL.  So "/icons" isn't aliased in this
+# example, only "/icons/".  If the fakename is slash-terminated, then the 
+# realname must also be slash terminated, and if the fakename omits the 
+# trailing slash, the realname must also omit it.
+#
+# We include the /icons/ alias for FancyIndexed directory listings.  If
+# you do not use FancyIndexing, you may comment this out.
+#
+Alias /icons/ "<%= node[:apache][:icondir] %>"
+
+<Directory "<%= node[:apache][:icondir] %>">
+    Options Indexes MultiViews
+    AllowOverride None
+    Order allow,deny
+    Allow from all
+</Directory>
+
+</IfModule>

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/templates/default/mods/authopenid.load.erb
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/templates/default/mods/authopenid.load.erb b/src/main/vm/src/cookbooks/apache2/templates/default/mods/authopenid.load.erb
new file mode 100755
index 0000000..f21882b
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/templates/default/mods/authopenid.load.erb
@@ -0,0 +1 @@
+LoadModule authopenid_module /usr/lib/apache2/modules/mod_auth_openid.so

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/templates/default/mods/autoindex.conf.erb
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/templates/default/mods/autoindex.conf.erb b/src/main/vm/src/cookbooks/apache2/templates/default/mods/autoindex.conf.erb
new file mode 100755
index 0000000..3839093
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/templates/default/mods/autoindex.conf.erb
@@ -0,0 +1,101 @@
+<IfModule mod_autoindex.c>
+#
+# Directives controlling the display of server-generated directory listings.
+#
+
+#
+# IndexOptions: Controls the appearance of server-generated directory
+# listings.
+# Remove/replace the "Charset=UTF-8" if you don't use UTF-8 for your filenames.
+#
+IndexOptions FancyIndexing VersionSort HTMLTable NameWidth=* DescriptionWidth=* Charset=UTF-8
+
+#
+# AddIcon* directives tell the server which icon to show for different
+# files or filename extensions.  These are only displayed for
+# FancyIndexed directories.
+#
+AddIconByEncoding (CMP,/icons/compressed.gif) x-compress x-gzip x-bzip2
+
+AddIconByType (TXT,/icons/text.gif) text/*
+AddIconByType (IMG,/icons/image2.gif) image/*
+AddIconByType (SND,/icons/sound2.gif) audio/*
+AddIconByType (VID,/icons/movie.gif) video/*
+
+AddIcon /icons/binary.gif .bin .exe
+AddIcon /icons/binhex.gif .hqx
+AddIcon /icons/tar.gif .tar
+AddIcon /icons/world2.gif .wrl .wrl.gz .vrml .vrm .iv
+AddIcon /icons/compressed.gif .Z .z .tgz .gz .zip
+AddIcon /icons/a.gif .ps .ai .eps
+AddIcon /icons/layout.gif .html .shtml .htm .pdf
+AddIcon /icons/text.gif .txt
+AddIcon /icons/c.gif .c
+AddIcon /icons/p.gif .pl .py
+AddIcon /icons/f.gif .for
+AddIcon /icons/dvi.gif .dvi
+AddIcon /icons/uuencoded.gif .uu
+AddIcon /icons/script.gif .conf .sh .shar .csh .ksh .tcl
+AddIcon /icons/tex.gif .tex
+# It's a suffix rule, so simply matching "core" matches "score" as well !
+AddIcon /icons/bomb.gif /core
+AddIcon (SND,/icons/sound2.gif) .ogg
+AddIcon (VID,/icons/movie.gif) .ogm
+
+AddIcon /icons/back.gif ..
+AddIcon /icons/hand.right.gif README
+AddIcon /icons/folder.gif ^^DIRECTORY^^
+AddIcon /icons/blank.gif ^^BLANKICON^^
+
+# Default icons for OpenDocument format
+AddIcon /icons/odf6odt-20x22.png .odt
+AddIcon /icons/odf6ods-20x22.png .ods
+AddIcon /icons/odf6odp-20x22.png .odp
+AddIcon /icons/odf6odg-20x22.png .odg
+AddIcon /icons/odf6odc-20x22.png .odc
+AddIcon /icons/odf6odf-20x22.png .odf
+AddIcon /icons/odf6odb-20x22.png .odb
+AddIcon /icons/odf6odi-20x22.png .odi
+AddIcon /icons/odf6odm-20x22.png .odm
+
+AddIcon /icons/odf6ott-20x22.png .ott
+AddIcon /icons/odf6ots-20x22.png .ots
+AddIcon /icons/odf6otp-20x22.png .otp
+AddIcon /icons/odf6otg-20x22.png .otg
+AddIcon /icons/odf6otc-20x22.png .otc
+AddIcon /icons/odf6otf-20x22.png .otf
+AddIcon /icons/odf6oti-20x22.png .oti
+AddIcon /icons/odf6oth-20x22.png .oth
+
+#
+# DefaultIcon is which icon to show for files which do not have an icon
+# explicitly set.
+#
+DefaultIcon /icons/unknown.gif
+
+#
+# AddDescription allows you to place a short description after a file in
+# server-generated indexes.  These are only displayed for FancyIndexed
+# directories.
+# Format: AddDescription "description" filename
+#
+#AddDescription "GZIP compressed document" .gz
+#AddDescription "tar archive" .tar
+#AddDescription "GZIP compressed tar archive" .tgz
+
+#
+# ReadmeName is the name of the README file the server will look for by
+# default, and append to directory listings.
+#
+# HeaderName is the name of a file which should be prepended to
+# directory indexes. 
+ReadmeName README.html
+HeaderName HEADER.html
+
+#
+# IndexIgnore is a set of filenames which directory indexing should ignore
+# and not include in the listing.  Shell-style wildcarding is permitted.
+#
+IndexIgnore .??* *~ *# RCS CVS *,v *,t 
+
+</IfModule>

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/templates/default/mods/deflate.conf.erb
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/templates/default/mods/deflate.conf.erb b/src/main/vm/src/cookbooks/apache2/templates/default/mods/deflate.conf.erb
new file mode 100755
index 0000000..2e41975
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/templates/default/mods/deflate.conf.erb
@@ -0,0 +1,16 @@
+<IfModule mod_deflate.c>
+          AddOutputFilterByType DEFLATE text/html
+          AddOutputFilterByType DEFLATE text/css
+          AddOutputFilterByType DEFLATE text/plain
+          AddOutputFilterByType DEFLATE text/xml
+          AddOutputFilterByType DEFLATE application/xhtml+xml
+          AddOutputFilterByType DEFLATE application/xml
+          AddOutputFilterByType DEFLATE image/svg+xml
+          AddOutputFilterByType DEFLATE application/rss+xml
+          AddOutputFilterByType DEFLATE application/atom_xml
+          AddOutputFilterByType DEFLATE application/javascript
+          AddOutputFilterByType DEFLATE application/x-javascript
+          AddOutputFilterByType DEFLATE application/x-httpd-php
+          AddOutputFilterByType DEFLATE application/x-httpd-fastphp
+          AddOutputFilterByType DEFLATE application/x-httpd-eruby
+</IfModule>

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/templates/default/mods/dir.conf.erb
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/templates/default/mods/dir.conf.erb b/src/main/vm/src/cookbooks/apache2/templates/default/mods/dir.conf.erb
new file mode 100755
index 0000000..e16fcb3
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/templates/default/mods/dir.conf.erb
@@ -0,0 +1,5 @@
+<IfModule mod_dir.c>
+
+          DirectoryIndex index.html index.cgi index.pl index.php index.xhtml index.htm
+
+</IfModule>

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/templates/default/mods/fcgid.conf.erb
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/templates/default/mods/fcgid.conf.erb b/src/main/vm/src/cookbooks/apache2/templates/default/mods/fcgid.conf.erb
new file mode 100755
index 0000000..0e6fc9a
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/templates/default/mods/fcgid.conf.erb
@@ -0,0 +1,10 @@
+<IfModule mod_fcgid.c>
+  AddHandler    fcgid-script .fcgi
+  IPCConnectTimeout 20
+</IfModule>
+
+<% if node[:platform] == "centos" || node[:platform] == "redhat" || node[:platform] == "fedora" -%>
+# Sane place to put sockets and shared memory file
+SocketPath run/mod_fcgid
+SharememPath run/mod_fcgid/fcgid_shm
+<% end -%>

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/templates/default/mods/mime.conf.erb
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/templates/default/mods/mime.conf.erb b/src/main/vm/src/cookbooks/apache2/templates/default/mods/mime.conf.erb
new file mode 100755
index 0000000..b6954a3
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/templates/default/mods/mime.conf.erb
@@ -0,0 +1,191 @@
+<IfModule mod_mime.c>
+
+#
+# TypesConfig points to the file containing the list of mappings from
+# filename extension to MIME-type.
+#
+TypesConfig /etc/mime.types
+
+#
+# AddType allows you to add to or override the MIME configuration
+# file mime.types for specific file types.
+#
+#AddType application/x-gzip .tgz
+#
+# AddEncoding allows you to have certain browsers uncompress
+# information on the fly. Note: Not all browsers support this.
+# Despite the name similarity, the following Add* directives have
+# nothing to do with the FancyIndexing customization directives above.
+#
+#AddEncoding x-compress .Z
+#AddEncoding x-gzip .gz .tgz
+#AddEncoding x-bzip2 .bz2
+#
+# If the AddEncoding directives above are commented-out, then you
+# probably should define those extensions to indicate media types:
+#
+AddType application/x-compress .Z
+AddType application/x-gzip .gz .tgz
+AddType application/x-bzip2 .bz2
+
+#
+# DefaultLanguage and AddLanguage allows you to specify the language of 
+# a document. You can then use content negotiation to give a browser a 
+# file in a language the user can understand.
+#
+# Specify a default language. This means that all data
+# going out without a specific language tag (see below) will 
+# be marked with this one. You probably do NOT want to set
+# this unless you are sure it is correct for all cases.
+#
+# * It is generally better to not mark a page as 
+# * being a certain language than marking it with the wrong
+# * language!
+#
+# DefaultLanguage nl
+#
+# Note 1: The suffix does not have to be the same as the language
+# keyword --- those with documents in Polish (whose net-standard
+# language code is pl) may wish to use "AddLanguage pl .po" to
+# avoid the ambiguity with the common suffix for perl scripts.
+#
+# Note 2: The example entries below illustrate that in some cases 
+# the two character 'Language' abbreviation is not identical to 
+# the two character 'Country' code for its country,
+# E.g. 'Danmark/dk' versus 'Danish/da'.
+#
+# Note 3: In the case of 'ltz' we violate the RFC by using a three char
+# specifier. There is 'work in progress' to fix this and get
+# the reference data for rfc1766 cleaned up.
+#
+# Catalan (ca) - Croatian (hr) - Czech (cs) - Danish (da) - Dutch (nl)
+# English (en) - Esperanto (eo) - Estonian (et) - French (fr) - German (de)
+# Greek-Modern (el) - Hebrew (he) - Italian (it) - Japanese (ja)
+# Korean (ko) - Luxembourgeois* (ltz) - Norwegian Nynorsk (nn)
+# Norwegian (no) - Polish (pl) - Portugese (pt)
+# Brazilian Portuguese (pt-BR) - Russian (ru) - Swedish (sv)
+# Simplified Chinese (zh-CN) - Spanish (es) - Traditional Chinese (zh-TW)
+#
+AddLanguage ca .ca
+AddLanguage cs .cz .cs
+AddLanguage da .dk
+AddLanguage de .de
+AddLanguage el .el
+AddLanguage en .en
+AddLanguage eo .eo
+# See README.Debian for Spanish
+AddLanguage es .es
+AddLanguage et .et
+AddLanguage fr .fr
+AddLanguage he .he
+AddLanguage hr .hr
+AddLanguage it .it
+AddLanguage ja .ja
+AddLanguage ko .ko
+AddLanguage ltz .ltz
+AddLanguage nl .nl
+AddLanguage nn .nn
+AddLanguage no .no
+AddLanguage pl .po
+AddLanguage pt .pt
+AddLanguage pt-BR .pt-br
+AddLanguage ru .ru
+AddLanguage sv .sv
+# See README.Debian for Turkish
+AddLanguage tr .tr
+AddLanguage zh-CN .zh-cn
+AddLanguage zh-TW .zh-tw
+
+#
+# Commonly used filename extensions to character sets. You probably
+# want to avoid clashes with the language extensions, unless you
+# are good at carefully testing your setup after each change.
+# See http://www.iana.org/assignments/character-sets for the
+# official list of charset names and their respective RFCs.
+#
+AddCharset us-ascii    .ascii .us-ascii
+AddCharset ISO-8859-1  .iso8859-1  .latin1
+AddCharset ISO-8859-2  .iso8859-2  .latin2 .cen
+AddCharset ISO-8859-3  .iso8859-3  .latin3
+AddCharset ISO-8859-4  .iso8859-4  .latin4
+AddCharset ISO-8859-5  .iso8859-5  .cyr .iso-ru
+AddCharset ISO-8859-6  .iso8859-6  .arb .arabic
+AddCharset ISO-8859-7  .iso8859-7  .grk .greek
+AddCharset ISO-8859-8  .iso8859-8  .heb .hebrew
+AddCharset ISO-8859-9  .iso8859-9  .latin5 .trk
+AddCharset ISO-8859-10  .iso8859-10  .latin6
+AddCharset ISO-8859-13  .iso8859-13
+AddCharset ISO-8859-14  .iso8859-14  .latin8
+AddCharset ISO-8859-15  .iso8859-15  .latin9
+AddCharset ISO-8859-16  .iso8859-16  .latin10
+AddCharset ISO-2022-JP .iso2022-jp .jis
+AddCharset ISO-2022-KR .iso2022-kr .kis
+AddCharset ISO-2022-CN .iso2022-cn .cis
+AddCharset Big5        .Big5       .big5 .b5
+AddCharset cn-Big5     .cn-big5
+# For russian, more than one charset is used (depends on client, mostly):
+AddCharset WINDOWS-1251 .cp-1251   .win-1251
+AddCharset CP866       .cp866
+AddCharset KOI8      .koi8
+AddCharset KOI8-E      .koi8-e
+AddCharset KOI8-r      .koi8-r .koi8-ru
+AddCharset KOI8-U      .koi8-u
+AddCharset KOI8-ru     .koi8-uk .ua
+AddCharset ISO-10646-UCS-2 .ucs2
+AddCharset ISO-10646-UCS-4 .ucs4
+AddCharset UTF-7       .utf7
+AddCharset UTF-8       .utf8
+AddCharset UTF-16      .utf16
+AddCharset UTF-16BE    .utf16be
+AddCharset UTF-16LE    .utf16le
+AddCharset UTF-32      .utf32
+AddCharset UTF-32BE    .utf32be
+AddCharset UTF-32LE    .utf32le
+AddCharset euc-cn      .euc-cn
+AddCharset euc-gb      .euc-gb
+AddCharset euc-jp      .euc-jp
+AddCharset euc-kr      .euc-kr
+#Not sure how euc-tw got in - IANA doesn't list it???
+AddCharset EUC-TW      .euc-tw
+AddCharset gb2312      .gb2312 .gb
+AddCharset iso-10646-ucs-2 .ucs-2 .iso-10646-ucs-2
+AddCharset iso-10646-ucs-4 .ucs-4 .iso-10646-ucs-4
+AddCharset shift_jis   .shift_jis .sjis
+
+#
+# AddHandler allows you to map certain file extensions to "handlers":
+# actions unrelated to filetype. These can be either built into the server
+# or added with the Action directive (see below)
+#
+# To use CGI scripts outside of ScriptAliased directories:
+# (You will also need to add "ExecCGI" to the "Options" directive.)
+#
+#AddHandler cgi-script .cgi
+
+#
+# For files that include their own HTTP headers:
+#
+#AddHandler send-as-is asis
+
+#
+# For server-parsed imagemap files:
+#
+#AddHandler imap-file map
+
+#
+# For type maps (negotiated resources):
+# (This is enabled by default to allow the Apache "It Worked" page
+#  to be distributed in multiple languages.)
+#
+AddHandler type-map var
+
+#
+# Filters allow you to process content before it is sent to the client.
+#
+# To parse .shtml files for server-side includes (SSI):
+# (You will also need to add "Includes" to the "Options" directive.)
+#
+AddType text/html .shtml
+AddOutputFilter INCLUDES .shtml
+
+</IfModule>


[34/51] [abbrv] [partial] Adding Jinwon's custom RCMET

Posted by jo...@apache.org.
http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/app/css/.svn/text-base/font-awesome.min.css.svn-base
----------------------------------------------------------------------
diff --git a/src/main/ui/app/css/.svn/text-base/font-awesome.min.css.svn-base b/src/main/ui/app/css/.svn/text-base/font-awesome.min.css.svn-base
new file mode 100755
index 0000000..d4e45b3
--- /dev/null
+++ b/src/main/ui/app/css/.svn/text-base/font-awesome.min.css.svn-base
@@ -0,0 +1,33 @@
+/*!
+ *  Font Awesome 3.0.2
+ *  the iconic font designed for use with Twitter Bootstrap
+ *  -------------------------------------------------------
+ *  The full suite of pictographic icons, examples, and documentation
+ *  can be found at: http://fortawesome.github.com/Font-Awesome/
+ *
+ *  License
+ *  -------------------------------------------------------
+ *  - The Font Awesome font is licensed under the SIL Open Font License - http://scripts.sil.org/OFL
+ *  - Font Awesome CSS, LESS, and SASS files are licensed under the MIT License -
+ *    http://opensource.org/licenses/mit-license.html
+ *  - The Font Awesome pictograms are licensed under the CC BY 3.0 License - http://creativecommons.org/licenses/by/3.0/
+ *  - Attribution is no longer required in Font Awesome 3.0, but much appreciated:
+ *    "Font Awesome by Dave Gandy - http://fortawesome.github.com/Font-Awesome"
+
+ *  Contact
+ *  -------------------------------------------------------
+ *  Email: dave@davegandy.com
+ *  Twitter: http://twitter.com/fortaweso_me
+ *  Work: Lead Product Designer @ http://kyruus.com
+ */
+
+@font-face{
+  font-family:'FontAwesome';
+  src:url('../font/fontawesome-webfont.eot?v=3.0.1');
+  src:url('../font/fontawesome-webfont.eot?#iefix&v=3.0.1') format('embedded-opentype'),
+  url('../font/fontawesome-webfont.woff?v=3.0.1') format('woff'),
+  url('../font/fontawesome-webfont.ttf?v=3.0.1') format('truetype');
+  font-weight:normal;
+  font-style:normal }
+
+[class^="icon-"],[class*=" icon-"]{font-family:FontAwesome;font-weight:normal;font-style:normal;text-decoration:inherit;-webkit-font-smoothing:antialiased;display:inline;width:auto;height:auto;line-height:normal;vertical-align:baseline;background-image:none;background-position:0 0;background-repeat:repeat;margin-top:0}.icon-white,.nav-pills>.active>a>[class^="icon-"],.nav-pills>.active>a>[class*=" icon-"],.nav-list>.active>a>[class^="icon-"],.nav-list>.active>a>[class*=" icon-"],.navbar-inverse .nav>.active>a>[class^="icon-"],.navbar-inverse .nav>.active>a>[class*=" icon-"],.dropdown-menu>li>a:hover>[class^="icon-"],.dropdown-menu>li>a:hover>[class*=" icon-"],.dropdown-menu>.active>a>[class^="icon-"],.dropdown-menu>.active>a>[class*=" icon-"],.dropdown-submenu:hover>a>[class^="icon-"],.dropdown-submenu:hover>a>[class*=" icon-"]{background-image:none}[class^="icon-"]:before,[class*=" icon-"]:before{text-decoration:inherit;display:inline-block;speak:none}a [class^="icon-"],a [class*="
  icon-"]{display:inline-block}.icon-large:before{vertical-align:-10%;font-size:1.3333333333333333em}.btn [class^="icon-"],.nav [class^="icon-"],.btn [class*=" icon-"],.nav [class*=" icon-"]{display:inline}.btn [class^="icon-"].icon-large,.nav [class^="icon-"].icon-large,.btn [class*=" icon-"].icon-large,.nav [class*=" icon-"].icon-large{line-height:.9em}.btn [class^="icon-"].icon-spin,.nav [class^="icon-"].icon-spin,.btn [class*=" icon-"].icon-spin,.nav [class*=" icon-"].icon-spin{display:inline-block}.nav-tabs [class^="icon-"],.nav-pills [class^="icon-"],.nav-tabs [class*=" icon-"],.nav-pills [class*=" icon-"],.nav-tabs [class^="icon-"].icon-large,.nav-pills [class^="icon-"].icon-large,.nav-tabs [class*=" icon-"].icon-large,.nav-pills [class*=" icon-"].icon-large{line-height:.9em}li [class^="icon-"],.nav li [class^="icon-"],li [class*=" icon-"],.nav li [class*=" icon-"]{display:inline-block;width:1.25em;text-align:center}li [class^="icon-"].icon-large,.nav li [class^="icon-"].icon-
 large,li [class*=" icon-"].icon-large,.nav li [class*=" icon-"].icon-large{width:1.5625em}ul.icons{list-style-type:none;text-indent:-0.75em}ul.icons li [class^="icon-"],ul.icons li [class*=" icon-"]{width:.75em}.icon-muted{color:#eee}.icon-border{border:solid 1px #eee;padding:.2em .25em .15em;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}.icon-2x{font-size:2em}.icon-2x.icon-border{border-width:2px;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.icon-3x{font-size:3em}.icon-3x.icon-border{border-width:3px;-webkit-border-radius:5px;-moz-border-radius:5px;border-radius:5px}.icon-4x{font-size:4em}.icon-4x.icon-border{border-width:4px;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px}.pull-right{float:right}.pull-left{float:left}[class^="icon-"].pull-left,[class*=" icon-"].pull-left{margin-right:.3em}[class^="icon-"].pull-right,[class*=" icon-"].pull-right{margin-left:.3em}.btn [class^="icon-"].pull-left.icon-2x,.btn [class*=" icon
 -"].pull-left.icon-2x,.btn [class^="icon-"].pull-right.icon-2x,.btn [class*=" icon-"].pull-right.icon-2x{margin-top:.18em}.btn [class^="icon-"].icon-spin.icon-large,.btn [class*=" icon-"].icon-spin.icon-large{line-height:.8em}.btn.btn-small [class^="icon-"].pull-left.icon-2x,.btn.btn-small [class*=" icon-"].pull-left.icon-2x,.btn.btn-small [class^="icon-"].pull-right.icon-2x,.btn.btn-small [class*=" icon-"].pull-right.icon-2x{margin-top:.25em}.btn.btn-large [class^="icon-"],.btn.btn-large [class*=" icon-"]{margin-top:0}.btn.btn-large [class^="icon-"].pull-left.icon-2x,.btn.btn-large [class*=" icon-"].pull-left.icon-2x,.btn.btn-large [class^="icon-"].pull-right.icon-2x,.btn.btn-large [class*=" icon-"].pull-right.icon-2x{margin-top:.05em}.btn.btn-large [class^="icon-"].pull-left.icon-2x,.btn.btn-large [class*=" icon-"].pull-left.icon-2x{margin-right:.2em}.btn.btn-large [class^="icon-"].pull-right.icon-2x,.btn.btn-large [class*=" icon-"].pull-right.icon-2x{margin-left:.2em}.icon-spin{d
 isplay:inline-block;-moz-animation:spin 2s infinite linear;-o-animation:spin 2s infinite linear;-webkit-animation:spin 2s infinite linear;animation:spin 2s infinite linear}@-moz-keyframes spin{0%{-moz-transform:rotate(0deg)}100%{-moz-transform:rotate(359deg)}}@-webkit-keyframes spin{0%{-webkit-transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg)}}@-o-keyframes spin{0%{-o-transform:rotate(0deg)}100%{-o-transform:rotate(359deg)}}@-ms-keyframes spin{0%{-ms-transform:rotate(0deg)}100%{-ms-transform:rotate(359deg)}}@keyframes spin{0%{transform:rotate(0deg)}100%{transform:rotate(359deg)}}@-moz-document url-prefix(){.icon-spin{height:.9em}.btn .icon-spin{height:auto}.icon-spin.icon-large{height:1.25em}.btn .icon-spin.icon-large{height:.75em}}.icon-glass:before{content:"\f000"}.icon-music:before{content:"\f001"}.icon-search:before{content:"\f002"}.icon-envelope:before{content:"\f003"}.icon-heart:before{content:"\f004"}.icon-star:before{content:"\f005"}.icon-star-empty:before{content
 :"\f006"}.icon-user:before{content:"\f007"}.icon-film:before{content:"\f008"}.icon-th-large:before{content:"\f009"}.icon-th:before{content:"\f00a"}.icon-th-list:before{content:"\f00b"}.icon-ok:before{content:"\f00c"}.icon-remove:before{content:"\f00d"}.icon-zoom-in:before{content:"\f00e"}.icon-zoom-out:before{content:"\f010"}.icon-off:before{content:"\f011"}.icon-signal:before{content:"\f012"}.icon-cog:before{content:"\f013"}.icon-trash:before{content:"\f014"}.icon-home:before{content:"\f015"}.icon-file:before{content:"\f016"}.icon-time:before{content:"\f017"}.icon-road:before{content:"\f018"}.icon-download-alt:before{content:"\f019"}.icon-download:before{content:"\f01a"}.icon-upload:before{content:"\f01b"}.icon-inbox:before{content:"\f01c"}.icon-play-circle:before{content:"\f01d"}.icon-repeat:before{content:"\f01e"}.icon-refresh:before{content:"\f021"}.icon-list-alt:before{content:"\f022"}.icon-lock:before{content:"\f023"}.icon-flag:before{content:"\f024"}.icon-headphones:before{co
 ntent:"\f025"}.icon-volume-off:before{content:"\f026"}.icon-volume-down:before{content:"\f027"}.icon-volume-up:before{content:"\f028"}.icon-qrcode:before{content:"\f029"}.icon-barcode:before{content:"\f02a"}.icon-tag:before{content:"\f02b"}.icon-tags:before{content:"\f02c"}.icon-book:before{content:"\f02d"}.icon-bookmark:before{content:"\f02e"}.icon-print:before{content:"\f02f"}.icon-camera:before{content:"\f030"}.icon-font:before{content:"\f031"}.icon-bold:before{content:"\f032"}.icon-italic:before{content:"\f033"}.icon-text-height:before{content:"\f034"}.icon-text-width:before{content:"\f035"}.icon-align-left:before{content:"\f036"}.icon-align-center:before{content:"\f037"}.icon-align-right:before{content:"\f038"}.icon-align-justify:before{content:"\f039"}.icon-list:before{content:"\f03a"}.icon-indent-left:before{content:"\f03b"}.icon-indent-right:before{content:"\f03c"}.icon-facetime-video:before{content:"\f03d"}.icon-picture:before{content:"\f03e"}.icon-pencil:before{content:"\f
 040"}.icon-map-marker:before{content:"\f041"}.icon-adjust:before{content:"\f042"}.icon-tint:before{content:"\f043"}.icon-edit:before{content:"\f044"}.icon-share:before{content:"\f045"}.icon-check:before{content:"\f046"}.icon-move:before{content:"\f047"}.icon-step-backward:before{content:"\f048"}.icon-fast-backward:before{content:"\f049"}.icon-backward:before{content:"\f04a"}.icon-play:before{content:"\f04b"}.icon-pause:before{content:"\f04c"}.icon-stop:before{content:"\f04d"}.icon-forward:before{content:"\f04e"}.icon-fast-forward:before{content:"\f050"}.icon-step-forward:before{content:"\f051"}.icon-eject:before{content:"\f052"}.icon-chevron-left:before{content:"\f053"}.icon-chevron-right:before{content:"\f054"}.icon-plus-sign:before{content:"\f055"}.icon-minus-sign:before{content:"\f056"}.icon-remove-sign:before{content:"\f057"}.icon-ok-sign:before{content:"\f058"}.icon-question-sign:before{content:"\f059"}.icon-info-sign:before{content:"\f05a"}.icon-screenshot:before{content:"\f05
 b"}.icon-remove-circle:before{content:"\f05c"}.icon-ok-circle:before{content:"\f05d"}.icon-ban-circle:before{content:"\f05e"}.icon-arrow-left:before{content:"\f060"}.icon-arrow-right:before{content:"\f061"}.icon-arrow-up:before{content:"\f062"}.icon-arrow-down:before{content:"\f063"}.icon-share-alt:before{content:"\f064"}.icon-resize-full:before{content:"\f065"}.icon-resize-small:before{content:"\f066"}.icon-plus:before{content:"\f067"}.icon-minus:before{content:"\f068"}.icon-asterisk:before{content:"\f069"}.icon-exclamation-sign:before{content:"\f06a"}.icon-gift:before{content:"\f06b"}.icon-leaf:before{content:"\f06c"}.icon-fire:before{content:"\f06d"}.icon-eye-open:before{content:"\f06e"}.icon-eye-close:before{content:"\f070"}.icon-warning-sign:before{content:"\f071"}.icon-plane:before{content:"\f072"}.icon-calendar:before{content:"\f073"}.icon-random:before{content:"\f074"}.icon-comment:before{content:"\f075"}.icon-magnet:before{content:"\f076"}.icon-chevron-up:before{content:"\f
 077"}.icon-chevron-down:before{content:"\f078"}.icon-retweet:before{content:"\f079"}.icon-shopping-cart:before{content:"\f07a"}.icon-folder-close:before{content:"\f07b"}.icon-folder-open:before{content:"\f07c"}.icon-resize-vertical:before{content:"\f07d"}.icon-resize-horizontal:before{content:"\f07e"}.icon-bar-chart:before{content:"\f080"}.icon-twitter-sign:before{content:"\f081"}.icon-facebook-sign:before{content:"\f082"}.icon-camera-retro:before{content:"\f083"}.icon-key:before{content:"\f084"}.icon-cogs:before{content:"\f085"}.icon-comments:before{content:"\f086"}.icon-thumbs-up:before{content:"\f087"}.icon-thumbs-down:before{content:"\f088"}.icon-star-half:before{content:"\f089"}.icon-heart-empty:before{content:"\f08a"}.icon-signout:before{content:"\f08b"}.icon-linkedin-sign:before{content:"\f08c"}.icon-pushpin:before{content:"\f08d"}.icon-external-link:before{content:"\f08e"}.icon-signin:before{content:"\f090"}.icon-trophy:before{content:"\f091"}.icon-github-sign:before{content
 :"\f092"}.icon-upload-alt:before{content:"\f093"}.icon-lemon:before{content:"\f094"}.icon-phone:before{content:"\f095"}.icon-check-empty:before{content:"\f096"}.icon-bookmark-empty:before{content:"\f097"}.icon-phone-sign:before{content:"\f098"}.icon-twitter:before{content:"\f099"}.icon-facebook:before{content:"\f09a"}.icon-github:before{content:"\f09b"}.icon-unlock:before{content:"\f09c"}.icon-credit-card:before{content:"\f09d"}.icon-rss:before{content:"\f09e"}.icon-hdd:before{content:"\f0a0"}.icon-bullhorn:before{content:"\f0a1"}.icon-bell:before{content:"\f0a2"}.icon-certificate:before{content:"\f0a3"}.icon-hand-right:before{content:"\f0a4"}.icon-hand-left:before{content:"\f0a5"}.icon-hand-up:before{content:"\f0a6"}.icon-hand-down:before{content:"\f0a7"}.icon-circle-arrow-left:before{content:"\f0a8"}.icon-circle-arrow-right:before{content:"\f0a9"}.icon-circle-arrow-up:before{content:"\f0aa"}.icon-circle-arrow-down:before{content:"\f0ab"}.icon-globe:before{content:"\f0ac"}.icon-wre
 nch:before{content:"\f0ad"}.icon-tasks:before{content:"\f0ae"}.icon-filter:before{content:"\f0b0"}.icon-briefcase:before{content:"\f0b1"}.icon-fullscreen:before{content:"\f0b2"}.icon-group:before{content:"\f0c0"}.icon-link:before{content:"\f0c1"}.icon-cloud:before{content:"\f0c2"}.icon-beaker:before{content:"\f0c3"}.icon-cut:before{content:"\f0c4"}.icon-copy:before{content:"\f0c5"}.icon-paper-clip:before{content:"\f0c6"}.icon-save:before{content:"\f0c7"}.icon-sign-blank:before{content:"\f0c8"}.icon-reorder:before{content:"\f0c9"}.icon-list-ul:before{content:"\f0ca"}.icon-list-ol:before{content:"\f0cb"}.icon-strikethrough:before{content:"\f0cc"}.icon-underline:before{content:"\f0cd"}.icon-table:before{content:"\f0ce"}.icon-magic:before{content:"\f0d0"}.icon-truck:before{content:"\f0d1"}.icon-pinterest:before{content:"\f0d2"}.icon-pinterest-sign:before{content:"\f0d3"}.icon-google-plus-sign:before{content:"\f0d4"}.icon-google-plus:before{content:"\f0d5"}.icon-money:before{content:"\f0
 d6"}.icon-caret-down:before{content:"\f0d7"}.icon-caret-up:before{content:"\f0d8"}.icon-caret-left:before{content:"\f0d9"}.icon-caret-right:before{content:"\f0da"}.icon-columns:before{content:"\f0db"}.icon-sort:before{content:"\f0dc"}.icon-sort-down:before{content:"\f0dd"}.icon-sort-up:before{content:"\f0de"}.icon-envelope-alt:before{content:"\f0e0"}.icon-linkedin:before{content:"\f0e1"}.icon-undo:before{content:"\f0e2"}.icon-legal:before{content:"\f0e3"}.icon-dashboard:before{content:"\f0e4"}.icon-comment-alt:before{content:"\f0e5"}.icon-comments-alt:before{content:"\f0e6"}.icon-bolt:before{content:"\f0e7"}.icon-sitemap:before{content:"\f0e8"}.icon-umbrella:before{content:"\f0e9"}.icon-paste:before{content:"\f0ea"}.icon-lightbulb:before{content:"\f0eb"}.icon-exchange:before{content:"\f0ec"}.icon-cloud-download:before{content:"\f0ed"}.icon-cloud-upload:before{content:"\f0ee"}.icon-user-md:before{content:"\f0f0"}.icon-stethoscope:before{content:"\f0f1"}.icon-suitcase:before{content:"
 \f0f2"}.icon-bell-alt:before{content:"\f0f3"}.icon-coffee:before{content:"\f0f4"}.icon-food:before{content:"\f0f5"}.icon-file-alt:before{content:"\f0f6"}.icon-building:before{content:"\f0f7"}.icon-hospital:before{content:"\f0f8"}.icon-ambulance:before{content:"\f0f9"}.icon-medkit:before{content:"\f0fa"}.icon-fighter-jet:before{content:"\f0fb"}.icon-beer:before{content:"\f0fc"}.icon-h-sign:before{content:"\f0fd"}.icon-plus-sign-alt:before{content:"\f0fe"}.icon-double-angle-left:before{content:"\f100"}.icon-double-angle-right:before{content:"\f101"}.icon-double-angle-up:before{content:"\f102"}.icon-double-angle-down:before{content:"\f103"}.icon-angle-left:before{content:"\f104"}.icon-angle-right:before{content:"\f105"}.icon-angle-up:before{content:"\f106"}.icon-angle-down:before{content:"\f107"}.icon-desktop:before{content:"\f108"}.icon-laptop:before{content:"\f109"}.icon-tablet:before{content:"\f10a"}.icon-mobile-phone:before{content:"\f10b"}.icon-circle-blank:before{content:"\f10c"}
 .icon-quote-left:before{content:"\f10d"}.icon-quote-right:before{content:"\f10e"}.icon-spinner:before{content:"\f110"}.icon-circle:before{content:"\f111"}.icon-reply:before{content:"\f112"}.icon-github-alt:before{content:"\f113"}.icon-folder-close-alt:before{content:"\f114"}.icon-folder-open-alt:before{content:"\f115"}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/app/css/.svn/text-base/jasny-bootstrap-responsive.min.css.svn-base
----------------------------------------------------------------------
diff --git a/src/main/ui/app/css/.svn/text-base/jasny-bootstrap-responsive.min.css.svn-base b/src/main/ui/app/css/.svn/text-base/jasny-bootstrap-responsive.min.css.svn-base
new file mode 100755
index 0000000..0d43d71
--- /dev/null
+++ b/src/main/ui/app/css/.svn/text-base/jasny-bootstrap-responsive.min.css.svn-base
@@ -0,0 +1,9 @@
+/*!
+ * Jasny Bootstrap Responsive Extensions j3
+ *
+ * Copyright 2012 Jasny BV
+ * Licensed under the Apache License v2.0
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Extended with pride by @ArnoldDaniels of jasny.net
+ */.clearfix{*zoom:1}.clearfix:before,.clearfix:after{display:table;line-height:0;content:""}.clearfix:after{clear:both}.hide-text{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.input-block-level{display:block;width:100%;min-height:30px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.container-semifluid{max-width:1170px}@media(min-width:768px) and (max-width:979px){.row-desktop.row-fluid{width:100%}.row-desktop.row{margin-left:0}.row-desktop>[class*="span"],.row-desktop>[class*="span"]{display:block;float:none;width:auto;margin:0}}@media(max-width:767px){.table-responsive tr{display:block;padding:8px}.table-bordered.table-responsive tr{border:1px solid #DDD;border-top:0;border-right:0}.table-responsive td,.table-responsive th{display:block;padding:0;font-weight:normal;border:0}.table-responsive th{font-style:italic}.responsive-strong{font-weight:bold}.responsive-em{font-style:italic}.responsive-soft{color:#999}}@m
 edia(max-width:480px){.form-horizontal .controls,.form-horizontal .well .controls,.small-labels .controls{margin-left:0}}@media(max-width:768px){.form-horizontal .form-actions{padding-left:18px}}@media(min-width:768px) and (max-width:979px){.form-horizontal .control-label{width:100px}.form-horizontal .controls{margin-left:110px}.form-horizontal .form-actions{padding-left:110px}.form-horizontal .well .control-label{width:80px}.form-horizontal .well .controls{margin-left:90px}.small-labels .control-group>label{width:50px}.small-labels .controls{margin-left:60px}.small-labels .form-actions{padding-left:60px}}@media(min-width:1200px){.small-labels .control-group>label{width:80px}.small-labels .controls{margin-left:100px}.small-labels .form-actions{padding-left:100px}}@media(max-width:480px){.page-alert{position:static;width:auto}.page-alert .alert{width:auto;margin-left:0;border-top-width:1px;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}body>.page-alert{position:st
 atic}}@media(min-width:1200px){.page-alert .alert{width:700px;margin-left:-375px}}

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/app/css/.svn/text-base/jasny-bootstrap.min.css.svn-base
----------------------------------------------------------------------
diff --git a/src/main/ui/app/css/.svn/text-base/jasny-bootstrap.min.css.svn-base b/src/main/ui/app/css/.svn/text-base/jasny-bootstrap.min.css.svn-base
new file mode 100755
index 0000000..1862711
--- /dev/null
+++ b/src/main/ui/app/css/.svn/text-base/jasny-bootstrap.min.css.svn-base
@@ -0,0 +1,9 @@
+/*!
+ * Jasny Bootstrap Extensions j3
+ *
+ * Copyright 2012 Jasny BV
+ * Licensed under the Apache License v2.0
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Extended with pride by @ArnoldDaniels of jasny.net
+ */.clearfix{*zoom:1}.clearfix:before,.clearfix:after{display:table;line-height:0;content:""}.clearfix:after{clear:both}.hide-text{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.input-block-level{display:block;width:100%;min-height:30px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.container-semifluid{max-width:940px;padding-right:20px;padding-left:20px;margin-right:auto;margin-left:auto;*zoom:1}.container-semifluid:before,.container-semifluid:after{display:table;line-height:0;content:""}.container-semifluid:after{clear:both}form>*:last-child{margin-bottom:0}label input[type="image"],label input[type="checkbox"],label input[type="radio"]{vertical-align:middle}select{padding-left:2px}.small-labels .control-group>label{width:70px}.small-labels .controls{margin-left:80px}.small-labels .form-actions{padding-left:80px}.form-vertical .form-horizontal .control-group>label{text-align:left}.form-horizontal .form-vertical
  .control-group>label{float:none;padding-top:0;text-align:left}.form-horizontal .form-vertical .controls{margin-left:0}.form-horizontal .form-vertical.form-actions,.form-horizontal .form-vertical .form-actions{padding-left:20px}.control-group .control-group{margin-bottom:0}.form-horizontal .well .control-label{width:120px}.form-horizontal .well .controls{margin-left:140px}form .well>*:last-child{margin-bottom:0}.editor{width:100%;height:100px;padding:5px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.uneditable-textarea.editor-html{padding:5px 3px 5px 5px;white-space:normal}textarea.editor-html{visibility:hidden}.uneditable-input,.uneditable-textarea{display:inline-block;padding:4px 3px 4px 5px;font-size:14px;line-height:20px;color:#555;cursor:not-allowed;background-color:#fff;border:1px solid #eee;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,0.025);-webkit-box-shadow:inset 0 1px 1px
  rgba(0,0,0,0.075);-moz-box-shadow:inset 0 1px 2px rgba(0,0,0,0.025);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 2px rgba(0,0,0,0.025);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.uneditable-input{height:20px;overflow:hidden;white-space:pre}.uneditable-textarea{overflow-x:hidden;overflow-y:auto;white-space:pre-wrap}select[disabled],textarea[disabled],input[type="text"][disabled],input[type="password"][disabled],input[type="datetime"][disabled],input[type="datetime-local"][disabled],input[type="date"][disabled],input[type="month"][disabled],input[type="time"][disabled],input[type="week"][disabled],input[type="number"][disabled],input[type="email"][disabled],input[type="url"][disabled],input[type="search"][disabled]{color:#999}.uneditable-input.disabled,.uneditable-textarea.disabled{color:#999;cursor:not-allowed;background-color:#f5f5f5;border-color:#ddd}textarea,.uneditable-textarea{height:60px}textarea[rows="1"],.uneditable-textarea[rows="1"]{height:40p
 x}textarea[rows="2"],.uneditable-textarea[rows="2"]{height:60px}textarea[rows="3"],.uneditable-textarea[rows="3"]{height:80px}textarea[rows="4"],.uneditable-textarea[rows="4"]{height:100px}textarea[rows="5"],.uneditable-textarea[rows="5"]{height:120px}textarea[rows="6"],.uneditable-textarea[rows="6"]{height:140px}textarea[rows="7"],.uneditable-textarea[rows="7"]{height:160px}textarea[rows="8"],.uneditable-textarea[rows="8"]{height:180px}textarea[rows="9"],.uneditable-textarea[rows="9"]{height:200px}textarea[rows="10"],.uneditable-textarea[rows="10"]{height:220px}textarea[rows="11"],.uneditable-textarea[rows="11"]{height:240px}textarea[rows="12"],.uneditable-textarea[rows="12"]{height:260px}textarea[rows="13"],.uneditable-textarea[rows="13"]{height:280px}textarea[rows="14"],.uneditable-textarea[rows="14"]{height:300px}textarea[rows="15"],.uneditable-textarea[rows="15"]{height:320px}textarea[rows="16"],.uneditable-textarea[rows="16"]{height:340px}textarea[rows="17"],.uneditable-textar
 ea[rows="17"]{height:360px}textarea[rows="18"],.uneditable-textarea[rows="18"]{height:380px}textarea[rows="19"],.uneditable-textarea[rows="19"]{height:400px}textarea[rows="20"],.uneditable-textarea[rows="20"]{height:420px}textarea[rows="21"],.uneditable-textarea[rows="21"]{height:440px}textarea[rows="22"],.uneditable-textarea[rows="22"]{height:460px}textarea[rows="23"],.uneditable-textarea[rows="23"]{height:480px}textarea[rows="24"],.uneditable-textarea[rows="24"]{height:500px}textarea[rows="25"],.uneditable-textarea[rows="25"]{height:520px}textarea[rows="26"],.uneditable-textarea[rows="26"]{height:540px}textarea[rows="27"],.uneditable-textarea[rows="27"]{height:560px}textarea[rows="28"],.uneditable-textarea[rows="28"]{height:580px}textarea[rows="29"],.uneditable-textarea[rows="29"]{height:600px}textarea[rows="30"],.uneditable-textarea[rows="30"]{height:620px}textarea[rows="35"],.uneditable-textarea[rows="35"]{height:720px}textarea[rows="40"],.uneditable-textarea[rows="40"]{height:8
 20px}textarea[rows="45"],.uneditable-textarea[rows="45"]{height:920px}textarea[rows="50"],.uneditable-textarea[rows="50"]{height:1020px}textarea[rows="55"],.uneditable-textarea[rows="55"]{height:1120px}textarea[rows="60"],.uneditable-textarea[rows="60"]{height:1220px}textarea[rows="65"],.uneditable-textarea[rows="65"]{height:1320px}textarea[rows="70"],.uneditable-textarea[rows="70"]{height:1420px}textarea[rows="75"],.uneditable-textarea[rows="75"]{height:1520px}textarea[rows="80"],.uneditable-textarea[rows="80"]{height:1620px}textarea[rows="85"],.uneditable-textarea[rows="85"]{height:1720px}textarea[rows="90"],.uneditable-textarea[rows="90"]{height:1820px}textarea[rows="95"],.uneditable-textarea[rows="95"]{height:1920px}textarea[rows="100"],.uneditable-textarea[rows="100"]{height:2020px}.uneditable-textarea{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.uneditable-input[class*="span"],.uneditable-textarea[class*="span"],.row-fluid .uneditable-input[c
 lass*="span"],.row-fluid .uneditable-textarea[class*="span"]{float:none;margin-left:0}.input-append .uneditable-input,.input-prepend .uneditable-input{vertical-align:top}.input-append .uneditable-input[class*="span"],.input-prepend .uneditable-input[class*="span"]{display:inline-block}.uneditable-form input[disabled],.uneditable-form textarea[disabled],.uneditable-form select[disabled]{cursor:auto}.uneditable-form .uneditable-input,.uneditable-form .uneditable-textarea{cursor:text}.uneditable-form .form-actions{background-color:transparent}.header-actions{padding:0 20px;line-height:36px}.table-actions{padding-bottom:20px;*zoom:1}.table-actions:before,.table-actions:after{display:table;line-height:0;content:""}.table-actions:after{clear:both}tr.rowlink td{cursor:pointer}tr.rowlink td.nolink{cursor:auto}.table tbody tr.rowlink:hover td{background-color:#cfcfcf}a.rowlink{font:inherit;color:inherit;text-decoration:inherit}.act{display:inline;padding:0;font-weight:bold;color:#555;backgro
 und:inherit;border:0;-webkit-transition:text-shadow .1s linear;-moz-transition:text-shadow .1s linear;-o-transition:text-shadow .1s linear;transition:text-shadow .1s linear}.act:hover{color:#333;text-decoration:none;text-shadow:1px 1px 3px rgba(85,85,85,0.5)}.act-primary{color:#006dcc}.act-primary:hover{color:#04c;text-shadow:1px 1px 3px rgba(0,109,204,0.5)}.act-info{color:#49afcd}.act-info:hover{color:#2f96b4;text-shadow:1px 1px 3px rgba(75,175,206,0.5)}.act-success{color:#51a351}.act-success:hover{color:#468847;text-shadow:1px 1px 3px rgba(81,164,81,0.5)}.act-warning{color:#c09853}.act-warning:hover{color:#f89406;text-shadow:1px 1px 3px rgba(192,152,84,0.5)}.act-danger{color:#b94a48}.act-danger:hover{color:#bd362f;text-shadow:1px 1px 3px rgba(185,72,70,0.5)}.act.disabled,.act[disabled]{color:#aaa;cursor:not-allowed}.act.disabled:hover,.act[disabled]:hover{color:#aaa;text-shadow:none}.form-actions .act{line-height:30px}@font-face{font-family:IconicStroke;font-weight:normal;src:url(
 ../font/iconic_stroke.eot);src:local('IconicStroke'),url(../font/iconic_stroke.eot?#iefix) format('embedded-opentype'),url(../font/iconic_stroke.woff) format('woff'),url(../font/iconic_stroke.ttf) format('truetype'),url(../font/iconic_stroke.svg#iconic) format('svg'),url(../font/iconic_stroke.otf) format('opentype')}@font-face{font-family:IconicFill;font-weight:normal;src:url(../font/iconic_fill.eot);src:local('IconicFill'),url(../font/iconic_fill.eot?#iefix) format('embedded-opentype'),url(../font/iconic_fill.woff) format('woff'),url(../font/iconic_fill.ttf) format('truetype'),url(../font/iconic_fill.svg#iconic) format('svg'),url(../font/iconic_fill.otf) format('opentype')}@media screen,print{[class*="iconic-"]{font-style:inherit;font-weight:normal;vertical-align:bottom}[class*="iconic-"]:before{display:inline-block;width:1em;font-family:IconicFill;font-size:.9em;text-align:center;vertical-align:middle;content:""}.iconic-stroke:before{font-family:IconicStroke}.iconic-hash:before{co
 ntent:'\23'}.iconic-question-mark:before{content:'\3f'}.iconic-at:before{content:'\40'}.iconic-pilcrow:before{content:'\b6'}.iconic-info:before{content:'\2139'}.iconic-arrow-left:before{content:'\2190'}.iconic-arrow-up:before{content:'\2191'}.iconic-arrow-right:before{content:'\2192'}.iconic-arrow-down:before{content:'\2193'}.iconic-home:before{content:'\2302'}.iconic-sun:before{content:'\2600'}.iconic-cloud:before{content:'\2601'}.iconic-umbrella:before{content:'\2602'}.iconic-star:before{content:'\2605'}.iconic-moon:before{content:'\263e'}.iconic-heart:before{content:'\2764'}.iconic-cog:before{content:'\2699'}.iconic-bolt:before{content:'\26a1'}.iconic-key:before{content:'\26bf'}.iconic-rain:before{content:'\26c6'}.iconic-denied:before{content:'\26d4'}.iconic-mail:before{content:'\2709'}.iconic-pen:before{content:'\270e'}.iconic-x:before{content:'\2717'}.iconic-o-x:before{content:'\2718'}.iconic-check:before{content:'\2713'}.iconic-o-check:before{content:'\2714'}.iconic-left-quote
 :before{content:'\275d'}.iconic-right-quote:before{content:'\275e'}.iconic-plus:before{content:'\2795'}.iconic-minus:before{content:'\2796'}.iconic-curved-arrow:before{content:'\2935'}.iconic-document-alt:before{content:'\e000'}.iconic-calendar:before{content:'\e001'}.iconic-map-pin-alt:before{content:'\e002'}.iconic-comment-alt1:before{content:'\e003'}.iconic-comment-alt2:before{content:'\e004'}.iconic-pen-alt:before{content:'\e005'}.iconic-pen-alt2:before{content:'\e006'}.iconic-chat-alt:before{content:'\e007'}.iconic-o-plus:before{content:'\e008'}.iconic-o-minus:before{content:'\e009'}.iconic-bars-alt:before{content:'\e00a'}.iconic-book-alt:before{content:'\e00b'}.iconic-aperture-alt:before{content:'\e00c'}.iconic-beaker-alt:before{content:'\e010'}.iconic-left-quote-alt:before{content:'\e011'}.iconic-right-quote-alt:before{content:'\e012'}.iconic-o-arrow-left:before{content:'\e013'}.iconic-o-arrow-up:before{content:'\e014'}.iconic-o-arrow-right:before{content:'\e015'}.iconic-o-ar
 row-down:before{content:'\e016'}.iconic-o-arrow-left-alt:before{content:'\e017'}.iconic-o-arrow-up-alt:before{content:'\e018'}.iconic-o-arrow-right-alt:before{content:'\e019'}.iconic-o-arrow-down-alt:before{content:'\e01a'}.iconic-brush:before{content:'\e01b'}.iconic-brush-alt:before{content:'\e01c'}.iconic-eyedropper:before{content:'\e01e'}.iconic-layers:before{content:'\e01f'}.iconic-layers-alt:before{content:'\e020'}.iconic-compass:before{content:'\e021'}.iconic-award:before{content:'\e022'}.iconic-beaker:before{content:'\e023'}.iconic-steering-wheel:before{content:'\e024'}.iconic-eye:before{content:'\e025'}.iconic-aperture:before{content:'\e026'}.iconic-image:before{content:'\e027'}.iconic-chart:before{content:'\e028'}.iconic-chart-alt:before{content:'\e029'}.iconic-target:before{content:'\e02a'}.iconic-tag:before{content:'\e02b'}.iconic-rss:before{content:'\e02c'}.iconic-rss-alt:before{content:'\e02d'}.iconic-share:before{content:'\e02e'}.iconic-undo:before{content:'\e02f'}.ico
 nic-reload:before{content:'\e030'}.iconic-reload-alt:before{content:'\e031'}.iconic-loop:before{content:'\e032'}.iconic-loop-alt:before{content:'\e033'}.iconic-back-forth:before{content:'\e034'}.iconic-back-forth-alt:before{content:'\e035'}.iconic-spin:before{content:'\e036'}.iconic-spin-alt:before{content:'\e037'}.iconic-move-horizontal:before{content:'\e038'}.iconic-move-horizontal-alt:before{content:'\e039'}.iconic-o-move-horizontal:before{content:'\e03a'}.iconic-move-vertical:before{content:'\e03b'}.iconic-move-vertical-alt:before{content:'\e03c'}.iconic-o-move-vertical:before{content:'\e03d'}.iconic-move:before{content:'\e03e'}.iconic-move-alt:before{content:'\e03f'}.iconic-o-move:before{content:'\e040'}.iconic-transfer:before{content:'\e041'}.iconic-download:before{content:'\e042'}.iconic-upload:before{content:'\e043'}.iconic-cloud-download:before{content:'\e044'}.iconic-cloud-upload:before{content:'\e045'}.iconic-fork:before{content:'\e046'}.iconic-play:before{content:'\e047'
 }.iconic-o-play:before{content:'\e048'}.iconic-pause:before{content:'\e049'}.iconic-stop:before{content:'\e04a'}.iconic-eject:before{content:'\e04b'}.iconic-first:before{content:'\e04c'}.iconic-last:before{content:'\e04d'}.iconic-fullscreen:before{content:'\e04e'}.iconic-fullscreen-alt:before{content:'\e04f'}.iconic-fullscreen-exit:before{content:'\e050'}.iconic-fullscreen-exit-alt:before{content:'\e051'}.iconic-equalizer:before{content:'\e052'}.iconic-article:before{content:'\e053'}.iconic-read-more:before{content:'\e054'}.iconic-list:before{content:'\e055'}.iconic-list-nested:before{content:'\e056'}.iconic-cursor:before{content:'\e057'}.iconic-dial:before{content:'\e058'}.iconic-new-window:before{content:'\e059'}.iconic-trash:before{content:'\e05a'}.iconic-battery-half:before{content:'\e05b'}.iconic-battery-empty:before{content:'\e05c'}.iconic-battery-charging:before{content:'\e05d'}.iconic-chat:before{content:'\e05e'}.iconic-mic:before{content:'\e05f'}.iconic-movie:before{content
 :'\e060'}.iconic-headphones:before{content:'\e061'}.iconic-user:before{content:'\e062'}.iconic-lightbulb:before{content:'\e063'}.iconic-cd:before{content:'\e064'}.iconic-folder:before{content:'\e065'}.iconic-document:before{content:'\e066'}.iconic-pin:before{content:'\e067'}.iconic-map-pin:before{content:'\e068'}.iconic-book:before{content:'\e069'}.iconic-book-alt2:before{content:'\e06a'}.iconic-box:before{content:'\e06b'}.iconic-calendar-alt:before{content:'\e06c'}.iconic-comment:before{content:'\e06d'}.iconic-iphone:before{content:'\e06e'}.iconic-bars:before{content:'\e06f'}.iconic-camera:before{content:'\e070'}.iconic-volume-mute:before{content:'\e071'}.iconic-volume:before{content:'\e072'}.iconic-battery-full:before{content:'\e073'}.iconic-magnifying-glass:before{content:'\e074'}.iconic-lock:before{content:'\e075'}.iconic-unlock:before{content:'\e076'}.iconic-link:before{content:'\e077'}.iconic-wrench:before{content:'\e078'}.iconic-clock:before{content:'\e079'}.iconic-sun-stroke
 :before{font-family:IconicStroke;content:'\2600'}.iconic-moon-stroke:before{font-family:IconicStroke;content:'\263e'}.iconic-star-stroke:before{font-family:IconicStroke;content:'\2605'}.iconic-heart-stroke:before{font-family:IconicStroke;content:'\2764'}.iconic-key-stroke:before{font-family:IconicStroke;content:'\26bf'}.iconic-document-alt-stroke:before{font-family:IconicStroke;content:'\e000'}.iconic-comment-alt1-stroke:before{font-family:IconicStroke;content:'\e003'}.iconic-comment-alt2-stroke:before{font-family:IconicStroke;content:'\e004'}.iconic-pen-alt-stroke:before{font-family:IconicStroke;content:'\e005'}.iconic-chat-alt-stroke:before{font-family:IconicStroke;content:'\e007'}.iconic-award-stroke:before{font-family:IconicStroke;content:'\e022'}.iconic-tag-stroke:before{font-family:IconicStroke;content:'\e02b'}.iconic-trash-stroke:before{font-family:IconicStroke;content:'\e05a'}.iconic-folder-stroke:before{font-family:IconicStroke;content:'\e065'}.iconic-document-stroke:before
 {font-family:IconicStroke;content:'\e066'}.iconic-map-pin-stroke:before{font-family:IconicStroke;content:'\e068'}.iconic-calendar-alt-stroke:before{font-family:IconicStroke;content:'\e06c'}.iconic-comment-stroke:before{font-family:IconicStroke;content:'\e06d'}.iconic-lock-stroke:before{font-family:IconicStroke;content:'\e075'}.iconic-unlock-stroke:before{font-family:IconicStroke;content:'\e076'}}.page-alert{position:absolute;top:0;left:50%;z-index:1020;width:0}.page-alert .alert{width:550px;margin-left:-300px;border-top-width:0;-webkit-border-radius:0 0 4px 4px;-moz-border-radius:0 0 4px 4px;border-radius:0 0 4px 4px}.navbar-fixed-top+.page-alert{top:40px}body>.page-alert{position:fixed}.btn-file{position:relative;overflow:hidden;vertical-align:middle}.btn-file>input{position:absolute;top:0;right:0;margin:0;font-size:23px;cursor:pointer;opacity:0;filter:alpha(opacity=0);transform:translate(-300px,0) scale(4);direction:ltr}.fileupload{margin-bottom:9px}.fileupload .uneditable-input{d
 isplay:inline-block;margin-bottom:0;vertical-align:middle;cursor:text}.fileupload .thumbnail{display:inline-block;margin-bottom:5px;overflow:hidden;text-align:center;vertical-align:middle}.fileupload .thumbnail>img{display:inline-block;max-height:100%;vertical-align:middle}.fileupload .btn{vertical-align:middle}.fileupload-exists .fileupload-new,.fileupload-new .fileupload-exists{display:none}.fileupload-inline .fileupload-controls{display:inline}.fileupload-new .input-append .btn-file{-webkit-border-radius:0 3px 3px 0;-moz-border-radius:0 3px 3px 0;border-radius:0 3px 3px 0}.thumbnail-borderless .thumbnail{padding:0;border:0;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none}.fileupload-new.thumbnail-borderless .thumbnail{border:1px solid #ddd}.control-group.warning .fileupload .uneditable-input{color:#a47e3c;border-color:#a47e3c}.control-group.warning .fileupload .fileupload-preview{color:#a47e3c}.control-group
 .warning .fileupload .thumbnail{border-color:#a47e3c}.control-group.error .fileupload .uneditable-input{color:#b94a48;border-color:#b94a48}.control-group.error .fileupload .fileupload-preview{color:#b94a48}.control-group.error .fileupload .thumbnail{border-color:#b94a48}.control-group.success .fileupload .uneditable-input{color:#468847;border-color:#468847}.control-group.success .fileupload .fileupload-preview{color:#468847}.control-group.success .fileupload .thumbnail{border-color:#468847}.nav-tabs>li>a,.nav-pills>li>a{outline:0}.nav-tabs>li.disabled>a{color:#ccc;cursor:not-allowed}.tabbable{border-color:#ddd;border-style:solid;border-width:0;*zoom:1}.tabbable:before,.tabbable:after{display:table;line-height:0;content:""}.tabbable:after{clear:both}.tabbable>.nav-tabs{margin:0}.tab-content{padding:18px 0 0 0;overflow:auto;border-color:#ddd;border-style:solid;border-width:0}.tabbable-bordered{-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.tabbable-bordered>.tab-c
 ontent{padding:20px 20px 10px 20px;border-width:0 1px 1px 1px;-webkit-border-radius:0 0 4px 4px;-moz-border-radius:0 0 4px 4px;border-radius:0 0 4px 4px}body>.container.tabbable>.nav-tabs{padding-top:15px}.tabs-below>.tab-content{padding:0 0 10px 0}.tabs-below.tabbable-bordered>.tab-content{padding:20px 20px 10px 20px;border-width:1px 1px 0 1px;-webkit-border-radius:4px 4px 0 0;-moz-border-radius:4px 4px 0 0;border-radius:4px 4px 0 0}body>.container.tabs-below.tabbable-bodered>.tab-content{border-top-width:0;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.tabs-left,.tabs-right{margin-bottom:20px}.tabs-left>.nav-tabs,.tabs-right>.nav-tabs{position:relative;z-index:1;margin-bottom:0}.tabs-left>.tab-content,.tabs-right>.tab-content{overflow:hidden}.tabs-left>.nav-tabs{left:1px}.tabs-left>.nav-tabs>.active>a,.tabs-left>.nav-tabs>.active>a:hover{border-color:#ddd transparent #ddd #ddd;*border-right-color:#fff}.tabs-left>.tab-content{padding:0 0 0 19px;border-left-width:1px}
 .tabs-left.tabbable-bordered{border-width:0 1px 0 0}.tabs-left.tabbable-bordered>.tab-content{padding:20px 20px 10px 20px;border-width:1px 0 1px 1px;-webkit-border-radius:0 4px 4px 0;-moz-border-radius:0 4px 4px 0;border-radius:0 4px 4px 0}body>.container.tabs-left.tabbable-bodered>.tab-content{border-top-width:0;-webkit-border-radius:0 0 4px 0;-moz-border-radius:0 0 4px 0;border-radius:0 0 4px 0}.tabs-right>.nav-tabs{right:1px}.tabs-right>.nav-tabs>.active>a,.tabs-right>.nav-tabs>.active>a:hover{border-color:#ddd #ddd #ddd transparent;*border-left-color:#fff}.tabs-right>.tab-content{padding:0 19px 0 0;border-right-width:1px}.tabs-right.tabbable-bordered{border-width:0 0 0 1px}.tabs-right.tabbable-bordered>.tab-content{padding:20px 20px 10px 20px;border-width:1px 1px 1px 0;-webkit-border-radius:4px 0 0 4px;-moz-border-radius:4px 0 0 4px;border-radius:4px 0 0 4px}body>.container.tabs-right.tabbable-bodered>.tab-content{border-top-width:0;-webkit-border-radius:0 0 0 4px;-moz-border-ra
 dius:0 0 0 4px;border-radius:0 0 0 4px}

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/app/css/app.css
----------------------------------------------------------------------
diff --git a/src/main/ui/app/css/app.css b/src/main/ui/app/css/app.css
new file mode 100755
index 0000000..66ff15d
--- /dev/null
+++ b/src/main/ui/app/css/app.css
@@ -0,0 +1,27 @@
+/* app css stylesheet */
+
+#map 
+{
+    height: 670px;
+    width: 80%;
+    margin-left: 10%;
+	margin-bottom: 20px;
+}
+
+#rcmetHeader
+{
+	margin-left: 10%;
+}
+
+.small-alert 
+{
+	font-size: 12px;
+	color: green;
+	margin-top: 4px;
+	margin-left: 10px;
+}
+
+ul 
+{
+	list-style-type: none;
+}

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/app/css/bootstrap-responsive.min.css
----------------------------------------------------------------------
diff --git a/src/main/ui/app/css/bootstrap-responsive.min.css b/src/main/ui/app/css/bootstrap-responsive.min.css
new file mode 100755
index 0000000..d1b7f4b
--- /dev/null
+++ b/src/main/ui/app/css/bootstrap-responsive.min.css
@@ -0,0 +1,9 @@
+/*!
+ * Bootstrap Responsive v2.3.1
+ *
+ * Copyright 2012 Twitter, Inc
+ * Licensed under the Apache License v2.0
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Designed and built with all the love in the world @twitter by @mdo and @fat.
+ */.clearfix{*zoom:1}.clearfix:before,.clearfix:after{display:table;line-height:0;content:""}.clearfix:after{clear:both}.hide-text{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.input-block-level{display:block;width:100%;min-height:30px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}@-ms-viewport{width:device-width}.hidden{display:none;visibility:hidden}.visible-phone{display:none!important}.visible-tablet{display:none!important}.hidden-desktop{display:none!important}.visible-desktop{display:inherit!important}@media(min-width:768px) and (max-width:979px){.hidden-desktop{display:inherit!important}.visible-desktop{display:none!important}.visible-tablet{display:inherit!important}.hidden-tablet{display:none!important}}@media(max-width:767px){.hidden-desktop{display:inherit!important}.visible-desktop{display:none!important}.visible-phone{display:inherit!important}.hidden-phone{display:none!important}}.visible-print{dis
 play:none!important}@media print{.visible-print{display:inherit!important}.hidden-print{display:none!important}}@media(min-width:1200px){.row{margin-left:-30px;*zoom:1}.row:before,.row:after{display:table;line-height:0;content:""}.row:after{clear:both}[class*="span"]{float:left;min-height:1px;margin-left:30px}.container,.navbar-static-top .container,.navbar-fixed-top .container,.navbar-fixed-bottom .container{width:1170px}.span12{width:1170px}.span11{width:1070px}.span10{width:970px}.span9{width:870px}.span8{width:770px}.span7{width:670px}.span6{width:570px}.span5{width:470px}.span4{width:370px}.span3{width:270px}.span2{width:170px}.span1{width:70px}.offset12{margin-left:1230px}.offset11{margin-left:1130px}.offset10{margin-left:1030px}.offset9{margin-left:930px}.offset8{margin-left:830px}.offset7{margin-left:730px}.offset6{margin-left:630px}.offset5{margin-left:530px}.offset4{margin-left:430px}.offset3{margin-left:330px}.offset2{margin-left:230px}.offset1{margin-left:130px}.row-flui
 d{width:100%;*zoom:1}.row-fluid:before,.row-fluid:after{display:table;line-height:0;content:""}.row-fluid:after{clear:both}.row-fluid [class*="span"]{display:block;float:left;width:100%;min-height:30px;margin-left:2.564102564102564%;*margin-left:2.5109110747408616%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.row-fluid [class*="span"]:first-child{margin-left:0}.row-fluid .controls-row [class*="span"]+[class*="span"]{margin-left:2.564102564102564%}.row-fluid .span12{width:100%;*width:99.94680851063829%}.row-fluid .span11{width:91.45299145299145%;*width:91.39979996362975%}.row-fluid .span10{width:82.90598290598291%;*width:82.8527914166212%}.row-fluid .span9{width:74.35897435897436%;*width:74.30578286961266%}.row-fluid .span8{width:65.81196581196582%;*width:65.75877432260411%}.row-fluid .span7{width:57.26495726495726%;*width:57.21176577559556%}.row-fluid .span6{width:48.717948717948715%;*width:48.664757228587014%}.row-fluid .span5{width:40.17094017094
 017%;*width:40.11774868157847%}.row-fluid .span4{width:31.623931623931625%;*width:31.570740134569924%}.row-fluid .span3{width:23.076923076923077%;*width:23.023731587561375%}.row-fluid .span2{width:14.52991452991453%;*width:14.476723040552828%}.row-fluid .span1{width:5.982905982905983%;*width:5.929714493544281%}.row-fluid .offset12{margin-left:105.12820512820512%;*margin-left:105.02182214948171%}.row-fluid .offset12:first-child{margin-left:102.56410256410257%;*margin-left:102.45771958537915%}.row-fluid .offset11{margin-left:96.58119658119658%;*margin-left:96.47481360247316%}.row-fluid .offset11:first-child{margin-left:94.01709401709402%;*margin-left:93.91071103837061%}.row-fluid .offset10{margin-left:88.03418803418803%;*margin-left:87.92780505546462%}.row-fluid .offset10:first-child{margin-left:85.47008547008548%;*margin-left:85.36370249136206%}.row-fluid .offset9{margin-left:79.48717948717949%;*margin-left:79.38079650845607%}.row-fluid .offset9:first-child{margin-left:76.92307692307
 693%;*margin-left:76.81669394435352%}.row-fluid .offset8{margin-left:70.94017094017094%;*margin-left:70.83378796144753%}.row-fluid .offset8:first-child{margin-left:68.37606837606839%;*margin-left:68.26968539734497%}.row-fluid .offset7{margin-left:62.393162393162385%;*margin-left:62.28677941443899%}.row-fluid .offset7:first-child{margin-left:59.82905982905982%;*margin-left:59.72267685033642%}.row-fluid .offset6{margin-left:53.84615384615384%;*margin-left:53.739770867430444%}.row-fluid .offset6:first-child{margin-left:51.28205128205128%;*margin-left:51.175668303327875%}.row-fluid .offset5{margin-left:45.299145299145295%;*margin-left:45.1927623204219%}.row-fluid .offset5:first-child{margin-left:42.73504273504273%;*margin-left:42.62865975631933%}.row-fluid .offset4{margin-left:36.75213675213675%;*margin-left:36.645753773413354%}.row-fluid .offset4:first-child{margin-left:34.18803418803419%;*margin-left:34.081651209310785%}.row-fluid .offset3{margin-left:28.205128205128204%;*margin-left:
 28.0987452264048%}.row-fluid .offset3:first-child{margin-left:25.641025641025642%;*margin-left:25.53464266230224%}.row-fluid .offset2{margin-left:19.65811965811966%;*margin-left:19.551736679396257%}.row-fluid .offset2:first-child{margin-left:17.094017094017094%;*margin-left:16.98763411529369%}.row-fluid .offset1{margin-left:11.11111111111111%;*margin-left:11.004728132387708%}.row-fluid .offset1:first-child{margin-left:8.547008547008547%;*margin-left:8.440625568285142%}input,textarea,.uneditable-input{margin-left:0}.controls-row [class*="span"]+[class*="span"]{margin-left:30px}input.span12,textarea.span12,.uneditable-input.span12{width:1156px}input.span11,textarea.span11,.uneditable-input.span11{width:1056px}input.span10,textarea.span10,.uneditable-input.span10{width:956px}input.span9,textarea.span9,.uneditable-input.span9{width:856px}input.span8,textarea.span8,.uneditable-input.span8{width:756px}input.span7,textarea.span7,.uneditable-input.span7{width:656px}input.span6,textarea.span
 6,.uneditable-input.span6{width:556px}input.span5,textarea.span5,.uneditable-input.span5{width:456px}input.span4,textarea.span4,.uneditable-input.span4{width:356px}input.span3,textarea.span3,.uneditable-input.span3{width:256px}input.span2,textarea.span2,.uneditable-input.span2{width:156px}input.span1,textarea.span1,.uneditable-input.span1{width:56px}.thumbnails{margin-left:-30px}.thumbnails>li{margin-left:30px}.row-fluid .thumbnails{margin-left:0}}@media(min-width:768px) and (max-width:979px){.row{margin-left:-20px;*zoom:1}.row:before,.row:after{display:table;line-height:0;content:""}.row:after{clear:both}[class*="span"]{float:left;min-height:1px;margin-left:20px}.container,.navbar-static-top .container,.navbar-fixed-top .container,.navbar-fixed-bottom .container{width:724px}.span12{width:724px}.span11{width:662px}.span10{width:600px}.span9{width:538px}.span8{width:476px}.span7{width:414px}.span6{width:352px}.span5{width:290px}.span4{width:228px}.span3{width:166px}.span2{width:104px
 }.span1{width:42px}.offset12{margin-left:764px}.offset11{margin-left:702px}.offset10{margin-left:640px}.offset9{margin-left:578px}.offset8{margin-left:516px}.offset7{margin-left:454px}.offset6{margin-left:392px}.offset5{margin-left:330px}.offset4{margin-left:268px}.offset3{margin-left:206px}.offset2{margin-left:144px}.offset1{margin-left:82px}.row-fluid{width:100%;*zoom:1}.row-fluid:before,.row-fluid:after{display:table;line-height:0;content:""}.row-fluid:after{clear:both}.row-fluid [class*="span"]{display:block;float:left;width:100%;min-height:30px;margin-left:2.7624309392265194%;*margin-left:2.709239449864817%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.row-fluid [class*="span"]:first-child{margin-left:0}.row-fluid .controls-row [class*="span"]+[class*="span"]{margin-left:2.7624309392265194%}.row-fluid .span12{width:100%;*width:99.94680851063829%}.row-fluid .span11{width:91.43646408839778%;*width:91.38327259903608%}.row-fluid .span10{width:82.87
 292817679558%;*width:82.81973668743387%}.row-fluid .span9{width:74.30939226519337%;*width:74.25620077583166%}.row-fluid .span8{width:65.74585635359117%;*width:65.69266486422946%}.row-fluid .span7{width:57.18232044198895%;*width:57.12912895262725%}.row-fluid .span6{width:48.61878453038674%;*width:48.56559304102504%}.row-fluid .span5{width:40.05524861878453%;*width:40.00205712942283%}.row-fluid .span4{width:31.491712707182323%;*width:31.43852121782062%}.row-fluid .span3{width:22.92817679558011%;*width:22.87498530621841%}.row-fluid .span2{width:14.3646408839779%;*width:14.311449394616199%}.row-fluid .span1{width:5.801104972375691%;*width:5.747913483013988%}.row-fluid .offset12{margin-left:105.52486187845304%;*margin-left:105.41847889972962%}.row-fluid .offset12:first-child{margin-left:102.76243093922652%;*margin-left:102.6560479605031%}.row-fluid .offset11{margin-left:96.96132596685082%;*margin-left:96.8549429881274%}.row-fluid .offset11:first-child{margin-left:94.1988950276243%;*margi
 n-left:94.09251204890089%}.row-fluid .offset10{margin-left:88.39779005524862%;*margin-left:88.2914070765252%}.row-fluid .offset10:first-child{margin-left:85.6353591160221%;*margin-left:85.52897613729868%}.row-fluid .offset9{margin-left:79.8342541436464%;*margin-left:79.72787116492299%}.row-fluid .offset9:first-child{margin-left:77.07182320441989%;*margin-left:76.96544022569647%}.row-fluid .offset8{margin-left:71.2707182320442%;*margin-left:71.16433525332079%}.row-fluid .offset8:first-child{margin-left:68.50828729281768%;*margin-left:68.40190431409427%}.row-fluid .offset7{margin-left:62.70718232044199%;*margin-left:62.600799341718584%}.row-fluid .offset7:first-child{margin-left:59.94475138121547%;*margin-left:59.838368402492065%}.row-fluid .offset6{margin-left:54.14364640883978%;*margin-left:54.037263430116376%}.row-fluid .offset6:first-child{margin-left:51.38121546961326%;*margin-left:51.27483249088986%}.row-fluid .offset5{margin-left:45.58011049723757%;*margin-left:45.4737275185141
 7%}.row-fluid .offset5:first-child{margin-left:42.81767955801105%;*margin-left:42.71129657928765%}.row-fluid .offset4{margin-left:37.01657458563536%;*margin-left:36.91019160691196%}.row-fluid .offset4:first-child{margin-left:34.25414364640884%;*margin-left:34.14776066768544%}.row-fluid .offset3{margin-left:28.45303867403315%;*margin-left:28.346655695309746%}.row-fluid .offset3:first-child{margin-left:25.69060773480663%;*margin-left:25.584224756083227%}.row-fluid .offset2{margin-left:19.88950276243094%;*margin-left:19.783119783707537%}.row-fluid .offset2:first-child{margin-left:17.12707182320442%;*margin-left:17.02068884448102%}.row-fluid .offset1{margin-left:11.32596685082873%;*margin-left:11.219583872105325%}.row-fluid .offset1:first-child{margin-left:8.56353591160221%;*margin-left:8.457152932878806%}input,textarea,.uneditable-input{margin-left:0}.controls-row [class*="span"]+[class*="span"]{margin-left:20px}input.span12,textarea.span12,.uneditable-input.span12{width:710px}input.sp
 an11,textarea.span11,.uneditable-input.span11{width:648px}input.span10,textarea.span10,.uneditable-input.span10{width:586px}input.span9,textarea.span9,.uneditable-input.span9{width:524px}input.span8,textarea.span8,.uneditable-input.span8{width:462px}input.span7,textarea.span7,.uneditable-input.span7{width:400px}input.span6,textarea.span6,.uneditable-input.span6{width:338px}input.span5,textarea.span5,.uneditable-input.span5{width:276px}input.span4,textarea.span4,.uneditable-input.span4{width:214px}input.span3,textarea.span3,.uneditable-input.span3{width:152px}input.span2,textarea.span2,.uneditable-input.span2{width:90px}input.span1,textarea.span1,.uneditable-input.span1{width:28px}}@media(max-width:767px){body{padding-right:20px;padding-left:20px}.navbar-fixed-top,.navbar-fixed-bottom,.navbar-static-top{margin-right:-20px;margin-left:-20px}.container-fluid{padding:0}.dl-horizontal dt{float:none;width:auto;clear:none;text-align:left}.dl-horizontal dd{margin-left:0}.container{width:aut
 o}.row-fluid{width:100%}.row,.thumbnails{margin-left:0}.thumbnails>li{float:none;margin-left:0}[class*="span"],.uneditable-input[class*="span"],.row-fluid [class*="span"]{display:block;float:none;width:100%;margin-left:0;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.span12,.row-fluid .span12{width:100%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.row-fluid [class*="offset"]:first-child{margin-left:0}.input-large,.input-xlarge,.input-xxlarge,input[class*="span"],select[class*="span"],textarea[class*="span"],.uneditable-input{display:block;width:100%;min-height:30px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.input-prepend input,.input-append input,.input-prepend input[class*="span"],.input-append input[class*="span"]{display:inline-block;width:auto}.controls-row [class*="span"]+[class*="span"]{margin-left:0}.modal{position:fixed;top:20px;right:20px;left:20px;width:auto;margin:0}.m
 odal.fade{top:-100px}.modal.fade.in{top:20px}}@media(max-width:480px){.nav-collapse{-webkit-transform:translate3d(0,0,0)}.page-header h1 small{display:block;line-height:20px}input[type="checkbox"],input[type="radio"]{border:1px solid #ccc}.form-horizontal .control-label{float:none;width:auto;padding-top:0;text-align:left}.form-horizontal .controls{margin-left:0}.form-horizontal .control-list{padding-top:0}.form-horizontal .form-actions{padding-right:10px;padding-left:10px}.media .pull-left,.media .pull-right{display:block;float:none;margin-bottom:10px}.media-object{margin-right:0;margin-left:0}.modal{top:10px;right:10px;left:10px}.modal-header .close{padding:10px;margin:-10px}.carousel-caption{position:static}}@media(max-width:979px){body{padding-top:0}.navbar-fixed-top,.navbar-fixed-bottom{position:static}.navbar-fixed-top{margin-bottom:20px}.navbar-fixed-bottom{margin-top:20px}.navbar-fixed-top .navbar-inner,.navbar-fixed-bottom .navbar-inner{padding:5px}.navbar .container{width:a
 uto;padding:0}.navbar .brand{padding-right:10px;padding-left:10px;margin:0 0 0 -5px}.nav-collapse{clear:both}.nav-collapse .nav{float:none;margin:0 0 10px}.nav-collapse .nav>li{float:none}.nav-collapse .nav>li>a{margin-bottom:2px}.nav-collapse .nav>.divider-vertical{display:none}.nav-collapse .nav .nav-header{color:#777;text-shadow:none}.nav-collapse .nav>li>a,.nav-collapse .dropdown-menu a{padding:9px 15px;font-weight:bold;color:#777;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}.nav-collapse .btn{padding:4px 10px 4px;font-weight:normal;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.nav-collapse .dropdown-menu li+li a{margin-bottom:2px}.nav-collapse .nav>li>a:hover,.nav-collapse .nav>li>a:focus,.nav-collapse .dropdown-menu a:hover,.nav-collapse .dropdown-menu a:focus{background-color:#f2f2f2}.navbar-inverse .nav-collapse .nav>li>a,.navbar-inverse .nav-collapse .dropdown-menu a{color:#999}.navbar-inverse .nav-collapse .nav>li>a:hover,.navbar
 -inverse .nav-collapse .nav>li>a:focus,.navbar-inverse .nav-collapse .dropdown-menu a:hover,.navbar-inverse .nav-collapse .dropdown-menu a:focus{background-color:#111}.nav-collapse.in .btn-group{padding:0;margin-top:5px}.nav-collapse .dropdown-menu{position:static;top:auto;left:auto;display:none;float:none;max-width:none;padding:0;margin:0 15px;background-color:transparent;border:0;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none}.nav-collapse .open>.dropdown-menu{display:block}.nav-collapse .dropdown-menu:before,.nav-collapse .dropdown-menu:after{display:none}.nav-collapse .dropdown-menu .divider{display:none}.nav-collapse .nav>li>.dropdown-menu:before,.nav-collapse .nav>li>.dropdown-menu:after{display:none}.nav-collapse .navbar-form,.nav-collapse .navbar-search{float:none;padding:10px 15px;margin:10px 0;border-top:1px solid #f2f2f2;border-bottom:1px solid #f2f2f2;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,
 255,0.1),0 1px 0 rgba(255,255,255,0.1);-moz-box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.1);box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.1)}.navbar-inverse .nav-collapse .navbar-form,.navbar-inverse .nav-collapse .navbar-search{border-top-color:#111;border-bottom-color:#111}.navbar .nav-collapse .nav.pull-right{float:none;margin-left:0}.nav-collapse,.nav-collapse.collapse{height:0;overflow:hidden}.navbar .btn-navbar{display:block}.navbar-static .navbar-inner{padding-right:10px;padding-left:10px}}@media(min-width:980px){.nav-collapse.collapse{height:auto!important;overflow:visible!important}}


[14/51] [abbrv] [partial] Adding Jinwon's custom RCMET

Posted by jo...@apache.org.
http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/app/partials/.svn/text-base/selectObservation.html.svn-base
----------------------------------------------------------------------
diff --git a/src/main/ui/app/partials/.svn/text-base/selectObservation.html.svn-base b/src/main/ui/app/partials/.svn/text-base/selectObservation.html.svn-base
new file mode 100755
index 0000000..6f72cb5
--- /dev/null
+++ b/src/main/ui/app/partials/.svn/text-base/selectObservation.html.svn-base
@@ -0,0 +1,44 @@
+<ul class="nav nav-pills">
+	<li class="active"><a href="#/obs">Local File</a></li>
+	<li><a href="#/rcmed">RCMED</a></li>
+	<li class="disabled"><a href="#/esg">ESG</a></li>
+  <li class="pull-right">Queued Datasets: {{datasetCount.length}}</li>
+</ul>
+
+<form class="form-inline" autocomplete="off">
+	<input id="observationFileInput" predictive-file-browser-input ng-model="filePathInput" type="text" class="input-xlarge" autocomplete="off" />
+	<button class="btn" ng-click="uploadLocalFile()" ng-disabled="shouldDisableLoadButton()">
+    <div ng-hide="loadingFile">Parse File</div>
+    <div ng-show="loadingFile"><i class="icon-spinner icon-spin"></i></div>
+  </button>
+</form>
+
+<div class="row">
+	<div class="span2 text-center">
+    Evaluation Variable
+	</div>
+	<div class="span3">
+    <select ng-model="paramSelect" ng-options="param for param in params"></select>
+	</div>
+	<div class="span2 text-center">
+		Latitude Variable
+	</div>
+	<div class="span3">
+    <select ng-model="latsSelect" ng-options="lat for lat in lats"></select>
+	</div>
+	<div class="span2 text-center">
+		Longitude Variable
+	</div>
+	<div class="span3">
+    <select ng-model="lonsSelect" ng-options="lon for lon in lons"></select>
+	</div>
+	<div class="span2 text-center">
+		Date/Time Variable
+	</div>
+	<div class="span3">
+    <select ng-model="timeSelect" ng-options="time for time in times"></select>
+	</div>
+</div>
+
+<button class="btn pull-left" ng-click="addDataSet()">Add Dataset</button>
+<div class="pull-left small-alert" ng-show="fileAdded">Successfully added dataset...</div>

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/app/partials/.svn/text-base/selectRcmed.html.svn-base
----------------------------------------------------------------------
diff --git a/src/main/ui/app/partials/.svn/text-base/selectRcmed.html.svn-base b/src/main/ui/app/partials/.svn/text-base/selectRcmed.html.svn-base
new file mode 100755
index 0000000..dcac499
--- /dev/null
+++ b/src/main/ui/app/partials/.svn/text-base/selectRcmed.html.svn-base
@@ -0,0 +1,30 @@
+<ul class="nav nav-pills">
+	<li><a href="#/obs">Local File</a></li>
+	<li class="active"><a href="#/rcmed">RCMED</a></li>
+	<li class="disabled"><a href="#/esg">ESG</a></li>
+  <li class="pull-right">Queued Datasets: {{datasetCount.length}}</li>
+</ul>
+
+<div class="row">
+	<div class="span5">
+		Select the RCMED dataset that you would like use.
+	</div>
+</div>
+<div class="row">
+	<div class="span4">
+		<select ng-change="dataSelectUpdated()" class="span5" ng-model="datasetSelection" ng-options="obs as obs.longname for obs in availableObs"></select>
+	</div>
+</div>
+<div class="row">
+	<div class="span5">
+		Select the dataset parameter that you would like to test.
+	</div>
+</div>
+<div class="row">
+	<div class="span4">
+		<select class="span3" ng-model="parameterSelection" ng-options="param as param.shortname for param in retrievedObsParams"></select>
+	</div>
+</div>
+
+<button class="btn pull-left" ng-click="addObservation()">Add Observation</button>
+<div class="pull-left small-alert" ng-show="fileAdded">Successfully added dataset...</div>

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/app/partials/modelSelect.html
----------------------------------------------------------------------
diff --git a/src/main/ui/app/partials/modelSelect.html b/src/main/ui/app/partials/modelSelect.html
new file mode 100755
index 0000000..49a7dec
--- /dev/null
+++ b/src/main/ui/app/partials/modelSelect.html
@@ -0,0 +1,67 @@
+<div class="container">
+  <div class="row">
+    <div class="span10 offset1 columns">
+      <div class="row">
+        <div class="span10">
+          <center>
+            <form id="modelSelectorForm">
+              <input type="file" name="modelSelector">
+            </form>
+          </center>
+        </div>
+      </div>
+      <div class="row">
+        <div class="span10 offset2">
+          <form class="form-horizontal" id="parameterSelectorForm">
+            <div class="control-group">
+              <label class="control-label" for="paramSelect">Parameter Value</label>
+              <div class="controls">
+                <select id="paramSelect">
+                  <option ng-repeat="param in modelParameters">
+                    {{param.text}}
+                  </option>
+                </select>
+              </div>
+            </div>
+            <div class="control-group">
+              <label class="control-label" for="latSelect">Latitude Variable</label>
+              <div class="controls">
+                <select id="latSelect">
+                  <option ng-repeat="lat in latVariables">
+                    {{lat.text}}
+                  </option>
+                </select>
+              </div>
+            </div>
+            <div class="control-group">
+              <label class="control-label" for="lonSelect">Longitude Variable</label>
+              <div class"controls">
+                <select id="lonSelect">
+                  <option ng-repeat="lon in lonVariables">
+                    {{lon.text}}
+                  </option>
+                </select>
+              </div>
+            </div>
+            <div class="control-group">
+              <label class="control-label" for="dateTimeSelect">Date/Time Variable</label>
+              <div class="controls">
+                <select id="dateTimeSelect">
+                  <option ng-repeat="dateTime in dateTimeVariables">
+                    {{dateTime.text}}
+                  </option>
+                </select>
+              </div>
+            </div>
+            <div class="control-group">
+              <div class="controls">
+                <button type="submit" class="btn btn-warn">Cancel</button>
+                <button type="submit" class="btn">Add Model</button>
+              </div>
+            </div>
+          </form>
+        </div>
+      </div>
+    </div>
+  </div>
+</div>

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/app/partials/partial1.html
----------------------------------------------------------------------
diff --git a/src/main/ui/app/partials/partial1.html b/src/main/ui/app/partials/partial1.html
new file mode 100755
index 0000000..89459a6
--- /dev/null
+++ b/src/main/ui/app/partials/partial1.html
@@ -0,0 +1 @@
+<p>This is the partial for view 1.</p>

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/app/partials/partial2.html
----------------------------------------------------------------------
diff --git a/src/main/ui/app/partials/partial2.html b/src/main/ui/app/partials/partial2.html
new file mode 100755
index 0000000..b6503ee
--- /dev/null
+++ b/src/main/ui/app/partials/partial2.html
@@ -0,0 +1,5 @@
+<p>This is the partial for view 2.</p>
+<p>
+  Showing of 'interpolate' filter:
+  {{ 'Current version is v%VERSION%.' | interpolate }}
+</p>

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/app/partials/selectObservation.html
----------------------------------------------------------------------
diff --git a/src/main/ui/app/partials/selectObservation.html b/src/main/ui/app/partials/selectObservation.html
new file mode 100755
index 0000000..6f72cb5
--- /dev/null
+++ b/src/main/ui/app/partials/selectObservation.html
@@ -0,0 +1,44 @@
+<ul class="nav nav-pills">
+	<li class="active"><a href="#/obs">Local File</a></li>
+	<li><a href="#/rcmed">RCMED</a></li>
+	<li class="disabled"><a href="#/esg">ESG</a></li>
+  <li class="pull-right">Queued Datasets: {{datasetCount.length}}</li>
+</ul>
+
+<form class="form-inline" autocomplete="off">
+	<input id="observationFileInput" predictive-file-browser-input ng-model="filePathInput" type="text" class="input-xlarge" autocomplete="off" />
+	<button class="btn" ng-click="uploadLocalFile()" ng-disabled="shouldDisableLoadButton()">
+    <div ng-hide="loadingFile">Parse File</div>
+    <div ng-show="loadingFile"><i class="icon-spinner icon-spin"></i></div>
+  </button>
+</form>
+
+<div class="row">
+	<div class="span2 text-center">
+    Evaluation Variable
+	</div>
+	<div class="span3">
+    <select ng-model="paramSelect" ng-options="param for param in params"></select>
+	</div>
+	<div class="span2 text-center">
+		Latitude Variable
+	</div>
+	<div class="span3">
+    <select ng-model="latsSelect" ng-options="lat for lat in lats"></select>
+	</div>
+	<div class="span2 text-center">
+		Longitude Variable
+	</div>
+	<div class="span3">
+    <select ng-model="lonsSelect" ng-options="lon for lon in lons"></select>
+	</div>
+	<div class="span2 text-center">
+		Date/Time Variable
+	</div>
+	<div class="span3">
+    <select ng-model="timeSelect" ng-options="time for time in times"></select>
+	</div>
+</div>
+
+<button class="btn pull-left" ng-click="addDataSet()">Add Dataset</button>
+<div class="pull-left small-alert" ng-show="fileAdded">Successfully added dataset...</div>

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/app/partials/selectRcmed.html
----------------------------------------------------------------------
diff --git a/src/main/ui/app/partials/selectRcmed.html b/src/main/ui/app/partials/selectRcmed.html
new file mode 100755
index 0000000..dcac499
--- /dev/null
+++ b/src/main/ui/app/partials/selectRcmed.html
@@ -0,0 +1,30 @@
+<ul class="nav nav-pills">
+	<li><a href="#/obs">Local File</a></li>
+	<li class="active"><a href="#/rcmed">RCMED</a></li>
+	<li class="disabled"><a href="#/esg">ESG</a></li>
+  <li class="pull-right">Queued Datasets: {{datasetCount.length}}</li>
+</ul>
+
+<div class="row">
+	<div class="span5">
+		Select the RCMED dataset that you would like use.
+	</div>
+</div>
+<div class="row">
+	<div class="span4">
+		<select ng-change="dataSelectUpdated()" class="span5" ng-model="datasetSelection" ng-options="obs as obs.longname for obs in availableObs"></select>
+	</div>
+</div>
+<div class="row">
+	<div class="span5">
+		Select the dataset parameter that you would like to test.
+	</div>
+</div>
+<div class="row">
+	<div class="span4">
+		<select class="span3" ng-model="parameterSelection" ng-options="param as param.shortname for param in retrievedObsParams"></select>
+	</div>
+</div>
+
+<button class="btn pull-left" ng-click="addObservation()">Add Observation</button>
+<div class="pull-left small-alert" ng-show="fileAdded">Successfully added dataset...</div>

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/config/.svn/all-wcprops
----------------------------------------------------------------------
diff --git a/src/main/ui/config/.svn/all-wcprops b/src/main/ui/config/.svn/all-wcprops
new file mode 100755
index 0000000..e78ad30
--- /dev/null
+++ b/src/main/ui/config/.svn/all-wcprops
@@ -0,0 +1,17 @@
+K 25
+svn:wc:ra_dav:version-url
+V 76
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/ui/config
+END
+testacular-e2e.conf.js
+K 25
+svn:wc:ra_dav:version-url
+V 99
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/ui/config/testacular-e2e.conf.js
+END
+testacular.conf.js
+K 25
+svn:wc:ra_dav:version-url
+V 95
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/ui/config/testacular.conf.js
+END

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/config/.svn/entries
----------------------------------------------------------------------
diff --git a/src/main/ui/config/.svn/entries b/src/main/ui/config/.svn/entries
new file mode 100755
index 0000000..ff777da
--- /dev/null
+++ b/src/main/ui/config/.svn/entries
@@ -0,0 +1,96 @@
+10
+
+dir
+1485921
+https://svn.apache.org/repos/asf/incubator/climate/trunk/rcmet/src/main/ui/config
+https://svn.apache.org/repos/asf
+
+
+
+2013-03-13T02:34:49.535183Z
+1475148
+mjjoyce
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+13f79535-47bb-0310-9956-ffa450edef68
+
+testacular-e2e.conf.js
+file
+
+
+
+
+2013-05-24T10:13:57.000000Z
+bac9ba3117ed4a65ba637b1736661052
+2013-03-13T02:34:30.834306Z
+1475137
+mjjoyce
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+283
+
+testacular.conf.js
+file
+
+
+
+
+2013-05-24T10:13:57.000000Z
+61f1d3a123c766a2a66554387197c2d5
+2013-03-13T02:34:49.535183Z
+1475148
+mjjoyce
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+405
+

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/config/.svn/prop-base/testacular-e2e.conf.js.svn-base
----------------------------------------------------------------------
diff --git a/src/main/ui/config/.svn/prop-base/testacular-e2e.conf.js.svn-base b/src/main/ui/config/.svn/prop-base/testacular-e2e.conf.js.svn-base
new file mode 100755
index 0000000..869ac71
--- /dev/null
+++ b/src/main/ui/config/.svn/prop-base/testacular-e2e.conf.js.svn-base
@@ -0,0 +1,5 @@
+K 14
+svn:executable
+V 1
+*
+END

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/config/.svn/prop-base/testacular.conf.js.svn-base
----------------------------------------------------------------------
diff --git a/src/main/ui/config/.svn/prop-base/testacular.conf.js.svn-base b/src/main/ui/config/.svn/prop-base/testacular.conf.js.svn-base
new file mode 100755
index 0000000..869ac71
--- /dev/null
+++ b/src/main/ui/config/.svn/prop-base/testacular.conf.js.svn-base
@@ -0,0 +1,5 @@
+K 14
+svn:executable
+V 1
+*
+END

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/config/.svn/text-base/testacular-e2e.conf.js.svn-base
----------------------------------------------------------------------
diff --git a/src/main/ui/config/.svn/text-base/testacular-e2e.conf.js.svn-base b/src/main/ui/config/.svn/text-base/testacular-e2e.conf.js.svn-base
new file mode 100755
index 0000000..51f51d2
--- /dev/null
+++ b/src/main/ui/config/.svn/text-base/testacular-e2e.conf.js.svn-base
@@ -0,0 +1,22 @@
+basePath = '../';
+
+files = [
+  ANGULAR_SCENARIO,
+  ANGULAR_SCENARIO_ADAPTER,
+  'test/e2e/**/*.js'
+];
+
+autoWatch = false;
+
+browsers = ['Chrome'];
+
+singleRun = true;
+
+proxies = {
+  '/': 'http://localhost:8000/'
+};
+
+junitReporter = {
+  outputFile: 'test_out/e2e.xml',
+  suite: 'e2e'
+};

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/config/.svn/text-base/testacular.conf.js.svn-base
----------------------------------------------------------------------
diff --git a/src/main/ui/config/.svn/text-base/testacular.conf.js.svn-base b/src/main/ui/config/.svn/text-base/testacular.conf.js.svn-base
new file mode 100755
index 0000000..5dc0dae
--- /dev/null
+++ b/src/main/ui/config/.svn/text-base/testacular.conf.js.svn-base
@@ -0,0 +1,23 @@
+basePath = '../';
+
+files = [
+  JASMINE,
+  JASMINE_ADAPTER,
+  'app/js/jquery-1.9.1.min.js',
+  'app/js/bootstrap.js',
+  'app/lib/angular/angular.js',
+  'app/lib/angular/angular-*.js',
+  'test/lib/angular/angular-mocks.js',
+  'app/js/leaflet.js',
+  'app/js/**/*.js',
+  'test/unit/**/*.js'
+];
+
+autoWatch = true;
+
+browsers = ['Chrome'];
+
+junitReporter = {
+  outputFile: 'test_out/unit.xml',
+  suite: 'unit'
+};

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/config/testacular-e2e.conf.js
----------------------------------------------------------------------
diff --git a/src/main/ui/config/testacular-e2e.conf.js b/src/main/ui/config/testacular-e2e.conf.js
new file mode 100755
index 0000000..51f51d2
--- /dev/null
+++ b/src/main/ui/config/testacular-e2e.conf.js
@@ -0,0 +1,22 @@
+basePath = '../';
+
+files = [
+  ANGULAR_SCENARIO,
+  ANGULAR_SCENARIO_ADAPTER,
+  'test/e2e/**/*.js'
+];
+
+autoWatch = false;
+
+browsers = ['Chrome'];
+
+singleRun = true;
+
+proxies = {
+  '/': 'http://localhost:8000/'
+};
+
+junitReporter = {
+  outputFile: 'test_out/e2e.xml',
+  suite: 'e2e'
+};

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/config/testacular.conf.js
----------------------------------------------------------------------
diff --git a/src/main/ui/config/testacular.conf.js b/src/main/ui/config/testacular.conf.js
new file mode 100755
index 0000000..5dc0dae
--- /dev/null
+++ b/src/main/ui/config/testacular.conf.js
@@ -0,0 +1,23 @@
+basePath = '../';
+
+files = [
+  JASMINE,
+  JASMINE_ADAPTER,
+  'app/js/jquery-1.9.1.min.js',
+  'app/js/bootstrap.js',
+  'app/lib/angular/angular.js',
+  'app/lib/angular/angular-*.js',
+  'test/lib/angular/angular-mocks.js',
+  'app/js/leaflet.js',
+  'app/js/**/*.js',
+  'test/unit/**/*.js'
+];
+
+autoWatch = true;
+
+browsers = ['Chrome'];
+
+junitReporter = {
+  outputFile: 'test_out/unit.xml',
+  suite: 'unit'
+};

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/logs/.svn/all-wcprops
----------------------------------------------------------------------
diff --git a/src/main/ui/logs/.svn/all-wcprops b/src/main/ui/logs/.svn/all-wcprops
new file mode 100755
index 0000000..db808ee
--- /dev/null
+++ b/src/main/ui/logs/.svn/all-wcprops
@@ -0,0 +1,5 @@
+K 25
+svn:wc:ra_dav:version-url
+V 74
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/ui/logs
+END

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/logs/.svn/entries
----------------------------------------------------------------------
diff --git a/src/main/ui/logs/.svn/entries b/src/main/ui/logs/.svn/entries
new file mode 100755
index 0000000..b179a80
--- /dev/null
+++ b/src/main/ui/logs/.svn/entries
@@ -0,0 +1,28 @@
+10
+
+dir
+1485921
+https://svn.apache.org/repos/asf/incubator/climate/trunk/rcmet/src/main/ui/logs
+https://svn.apache.org/repos/asf
+
+
+
+2013-03-13T02:34:38.209785Z
+1475139
+mjjoyce
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+13f79535-47bb-0310-9956-ffa450edef68
+

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/scripts/.svn/all-wcprops
----------------------------------------------------------------------
diff --git a/src/main/ui/scripts/.svn/all-wcprops b/src/main/ui/scripts/.svn/all-wcprops
new file mode 100755
index 0000000..360f92f
--- /dev/null
+++ b/src/main/ui/scripts/.svn/all-wcprops
@@ -0,0 +1,53 @@
+K 25
+svn:wc:ra_dav:version-url
+V 77
+/repos/asf/!svn/ver/1480068/incubator/climate/trunk/rcmet/src/main/ui/scripts
+END
+testacular-e2e.conf.js
+K 25
+svn:wc:ra_dav:version-url
+V 100
+/repos/asf/!svn/ver/1480068/incubator/climate/trunk/rcmet/src/main/ui/scripts/testacular-e2e.conf.js
+END
+e2e-test.sh
+K 25
+svn:wc:ra_dav:version-url
+V 89
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/ui/scripts/e2e-test.sh
+END
+test.bat
+K 25
+svn:wc:ra_dav:version-url
+V 86
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/ui/scripts/test.bat
+END
+testacular.conf.js
+K 25
+svn:wc:ra_dav:version-url
+V 96
+/repos/asf/!svn/ver/1480068/incubator/climate/trunk/rcmet/src/main/ui/scripts/testacular.conf.js
+END
+test.sh
+K 25
+svn:wc:ra_dav:version-url
+V 85
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/ui/scripts/test.sh
+END
+watchr.rb
+K 25
+svn:wc:ra_dav:version-url
+V 87
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/ui/scripts/watchr.rb
+END
+web-server.js
+K 25
+svn:wc:ra_dav:version-url
+V 91
+/repos/asf/!svn/ver/1480068/incubator/climate/trunk/rcmet/src/main/ui/scripts/web-server.js
+END
+e2e-test.bat
+K 25
+svn:wc:ra_dav:version-url
+V 90
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/ui/scripts/e2e-test.bat
+END

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/scripts/.svn/entries
----------------------------------------------------------------------
diff --git a/src/main/ui/scripts/.svn/entries b/src/main/ui/scripts/.svn/entries
new file mode 100755
index 0000000..e10c6d1
--- /dev/null
+++ b/src/main/ui/scripts/.svn/entries
@@ -0,0 +1,300 @@
+10
+
+dir
+1485921
+https://svn.apache.org/repos/asf/incubator/climate/trunk/rcmet/src/main/ui/scripts
+https://svn.apache.org/repos/asf
+
+
+
+2013-05-07T20:50:17.582309Z
+1480068
+joyce
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+13f79535-47bb-0310-9956-ffa450edef68
+
+testacular-e2e.conf.js
+file
+
+
+
+
+2013-05-24T10:13:58.000000Z
+bac9ba3117ed4a65ba637b1736661052
+2013-05-07T20:50:17.582309Z
+1480068
+joyce
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+283
+
+e2e-test.sh
+file
+
+
+
+
+2013-05-24T10:13:58.000000Z
+6b4333e8172e4059584e7751d06aef39
+2013-03-13T02:34:30.834306Z
+1475137
+mjjoyce
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+258
+
+test.bat
+file
+
+
+
+
+2013-05-24T10:13:58.000000Z
+b6ddbd00e9e919b7dd40b8a6413854cb
+2013-03-13T02:34:30.834306Z
+1475137
+mjjoyce
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+305
+
+testacular.conf.js
+file
+
+
+
+
+2013-05-24T10:13:58.000000Z
+61f1d3a123c766a2a66554387197c2d5
+2013-05-07T20:50:17.582309Z
+1480068
+joyce
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+405
+
+test.sh
+file
+
+
+
+
+2013-05-24T10:13:58.000000Z
+a8859b0de82e7db1fb0b302295423631
+2013-03-13T02:34:30.834306Z
+1475137
+mjjoyce
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+254
+
+watchr.rb
+file
+
+
+
+
+2013-05-24T10:13:58.000000Z
+bc2871a5662031fbb61e312426004abb
+2013-03-13T02:34:30.834306Z
+1475137
+mjjoyce
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+503
+
+web-server.js
+file
+
+
+
+
+2013-05-24T10:13:58.000000Z
+88fdfdf89e31b40797b50745ebf9928c
+2013-05-07T20:50:17.582309Z
+1480068
+joyce
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+8080
+
+e2e-test.bat
+file
+
+
+
+
+2013-05-24T10:13:58.000000Z
+10131a94d448fc4a49347db3db54505e
+2013-03-13T02:34:30.834306Z
+1475137
+mjjoyce
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+297
+

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/scripts/.svn/prop-base/e2e-test.bat.svn-base
----------------------------------------------------------------------
diff --git a/src/main/ui/scripts/.svn/prop-base/e2e-test.bat.svn-base b/src/main/ui/scripts/.svn/prop-base/e2e-test.bat.svn-base
new file mode 100755
index 0000000..869ac71
--- /dev/null
+++ b/src/main/ui/scripts/.svn/prop-base/e2e-test.bat.svn-base
@@ -0,0 +1,5 @@
+K 14
+svn:executable
+V 1
+*
+END

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/scripts/.svn/prop-base/e2e-test.sh.svn-base
----------------------------------------------------------------------
diff --git a/src/main/ui/scripts/.svn/prop-base/e2e-test.sh.svn-base b/src/main/ui/scripts/.svn/prop-base/e2e-test.sh.svn-base
new file mode 100755
index 0000000..869ac71
--- /dev/null
+++ b/src/main/ui/scripts/.svn/prop-base/e2e-test.sh.svn-base
@@ -0,0 +1,5 @@
+K 14
+svn:executable
+V 1
+*
+END

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/scripts/.svn/prop-base/test.bat.svn-base
----------------------------------------------------------------------
diff --git a/src/main/ui/scripts/.svn/prop-base/test.bat.svn-base b/src/main/ui/scripts/.svn/prop-base/test.bat.svn-base
new file mode 100755
index 0000000..869ac71
--- /dev/null
+++ b/src/main/ui/scripts/.svn/prop-base/test.bat.svn-base
@@ -0,0 +1,5 @@
+K 14
+svn:executable
+V 1
+*
+END

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/scripts/.svn/prop-base/test.sh.svn-base
----------------------------------------------------------------------
diff --git a/src/main/ui/scripts/.svn/prop-base/test.sh.svn-base b/src/main/ui/scripts/.svn/prop-base/test.sh.svn-base
new file mode 100755
index 0000000..869ac71
--- /dev/null
+++ b/src/main/ui/scripts/.svn/prop-base/test.sh.svn-base
@@ -0,0 +1,5 @@
+K 14
+svn:executable
+V 1
+*
+END

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/scripts/.svn/prop-base/testacular-e2e.conf.js.svn-base
----------------------------------------------------------------------
diff --git a/src/main/ui/scripts/.svn/prop-base/testacular-e2e.conf.js.svn-base b/src/main/ui/scripts/.svn/prop-base/testacular-e2e.conf.js.svn-base
new file mode 100755
index 0000000..869ac71
--- /dev/null
+++ b/src/main/ui/scripts/.svn/prop-base/testacular-e2e.conf.js.svn-base
@@ -0,0 +1,5 @@
+K 14
+svn:executable
+V 1
+*
+END

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/scripts/.svn/prop-base/testacular.conf.js.svn-base
----------------------------------------------------------------------
diff --git a/src/main/ui/scripts/.svn/prop-base/testacular.conf.js.svn-base b/src/main/ui/scripts/.svn/prop-base/testacular.conf.js.svn-base
new file mode 100755
index 0000000..869ac71
--- /dev/null
+++ b/src/main/ui/scripts/.svn/prop-base/testacular.conf.js.svn-base
@@ -0,0 +1,5 @@
+K 14
+svn:executable
+V 1
+*
+END

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/scripts/.svn/prop-base/watchr.rb.svn-base
----------------------------------------------------------------------
diff --git a/src/main/ui/scripts/.svn/prop-base/watchr.rb.svn-base b/src/main/ui/scripts/.svn/prop-base/watchr.rb.svn-base
new file mode 100755
index 0000000..869ac71
--- /dev/null
+++ b/src/main/ui/scripts/.svn/prop-base/watchr.rb.svn-base
@@ -0,0 +1,5 @@
+K 14
+svn:executable
+V 1
+*
+END

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/scripts/.svn/prop-base/web-server.js.svn-base
----------------------------------------------------------------------
diff --git a/src/main/ui/scripts/.svn/prop-base/web-server.js.svn-base b/src/main/ui/scripts/.svn/prop-base/web-server.js.svn-base
new file mode 100755
index 0000000..869ac71
--- /dev/null
+++ b/src/main/ui/scripts/.svn/prop-base/web-server.js.svn-base
@@ -0,0 +1,5 @@
+K 14
+svn:executable
+V 1
+*
+END

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/scripts/.svn/text-base/e2e-test.bat.svn-base
----------------------------------------------------------------------
diff --git a/src/main/ui/scripts/.svn/text-base/e2e-test.bat.svn-base b/src/main/ui/scripts/.svn/text-base/e2e-test.bat.svn-base
new file mode 100755
index 0000000..c89a708
--- /dev/null
+++ b/src/main/ui/scripts/.svn/text-base/e2e-test.bat.svn-base
@@ -0,0 +1,11 @@
+@echo off
+
+REM Windows script for running e2e tests
+REM You have to run server and capture some browser first
+REM
+REM Requirements:
+REM - NodeJS (http://nodejs.org/)
+REM - Testacular (npm install -g testacular)
+
+set BASE_DIR=%~dp0
+testacular start "%BASE_DIR%\..\config\testacular-e2e.conf.js" %*

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/scripts/.svn/text-base/e2e-test.sh.svn-base
----------------------------------------------------------------------
diff --git a/src/main/ui/scripts/.svn/text-base/e2e-test.sh.svn-base b/src/main/ui/scripts/.svn/text-base/e2e-test.sh.svn-base
new file mode 100755
index 0000000..e887c34
--- /dev/null
+++ b/src/main/ui/scripts/.svn/text-base/e2e-test.sh.svn-base
@@ -0,0 +1,9 @@
+#!/bin/bash
+
+BASE_DIR=`dirname $0`
+
+echo ""
+echo "Starting Testacular Server (http://vojtajina.github.com/testacular)"
+echo "-------------------------------------------------------------------"
+
+testacular start $BASE_DIR/../config/testacular-e2e.conf.js $*

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/scripts/.svn/text-base/test.bat.svn-base
----------------------------------------------------------------------
diff --git a/src/main/ui/scripts/.svn/text-base/test.bat.svn-base b/src/main/ui/scripts/.svn/text-base/test.bat.svn-base
new file mode 100755
index 0000000..000242f
--- /dev/null
+++ b/src/main/ui/scripts/.svn/text-base/test.bat.svn-base
@@ -0,0 +1,11 @@
+@echo off
+
+REM Windows script for running unit tests
+REM You have to run server and capture some browser first
+REM
+REM Requirements:
+REM - NodeJS (http://nodejs.org/)
+REM - Testacular (npm install -g testacular)
+
+set BASE_DIR=%~dp0
+testacular start "%BASE_DIR%\..\config\testacular.conf.js" %*

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/scripts/.svn/text-base/test.sh.svn-base
----------------------------------------------------------------------
diff --git a/src/main/ui/scripts/.svn/text-base/test.sh.svn-base b/src/main/ui/scripts/.svn/text-base/test.sh.svn-base
new file mode 100755
index 0000000..4c37cde
--- /dev/null
+++ b/src/main/ui/scripts/.svn/text-base/test.sh.svn-base
@@ -0,0 +1,9 @@
+#!/bin/bash
+
+BASE_DIR=`dirname $0`
+
+echo ""
+echo "Starting Testacular Server (http://vojtajina.github.com/testacular)"
+echo "-------------------------------------------------------------------"
+
+testacular start $BASE_DIR/../config/testacular.conf.js $*

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/scripts/.svn/text-base/testacular-e2e.conf.js.svn-base
----------------------------------------------------------------------
diff --git a/src/main/ui/scripts/.svn/text-base/testacular-e2e.conf.js.svn-base b/src/main/ui/scripts/.svn/text-base/testacular-e2e.conf.js.svn-base
new file mode 100755
index 0000000..51f51d2
--- /dev/null
+++ b/src/main/ui/scripts/.svn/text-base/testacular-e2e.conf.js.svn-base
@@ -0,0 +1,22 @@
+basePath = '../';
+
+files = [
+  ANGULAR_SCENARIO,
+  ANGULAR_SCENARIO_ADAPTER,
+  'test/e2e/**/*.js'
+];
+
+autoWatch = false;
+
+browsers = ['Chrome'];
+
+singleRun = true;
+
+proxies = {
+  '/': 'http://localhost:8000/'
+};
+
+junitReporter = {
+  outputFile: 'test_out/e2e.xml',
+  suite: 'e2e'
+};

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/scripts/.svn/text-base/testacular.conf.js.svn-base
----------------------------------------------------------------------
diff --git a/src/main/ui/scripts/.svn/text-base/testacular.conf.js.svn-base b/src/main/ui/scripts/.svn/text-base/testacular.conf.js.svn-base
new file mode 100755
index 0000000..5dc0dae
--- /dev/null
+++ b/src/main/ui/scripts/.svn/text-base/testacular.conf.js.svn-base
@@ -0,0 +1,23 @@
+basePath = '../';
+
+files = [
+  JASMINE,
+  JASMINE_ADAPTER,
+  'app/js/jquery-1.9.1.min.js',
+  'app/js/bootstrap.js',
+  'app/lib/angular/angular.js',
+  'app/lib/angular/angular-*.js',
+  'test/lib/angular/angular-mocks.js',
+  'app/js/leaflet.js',
+  'app/js/**/*.js',
+  'test/unit/**/*.js'
+];
+
+autoWatch = true;
+
+browsers = ['Chrome'];
+
+junitReporter = {
+  outputFile: 'test_out/unit.xml',
+  suite: 'unit'
+};

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/scripts/.svn/text-base/watchr.rb.svn-base
----------------------------------------------------------------------
diff --git a/src/main/ui/scripts/.svn/text-base/watchr.rb.svn-base b/src/main/ui/scripts/.svn/text-base/watchr.rb.svn-base
new file mode 100755
index 0000000..89ef656
--- /dev/null
+++ b/src/main/ui/scripts/.svn/text-base/watchr.rb.svn-base
@@ -0,0 +1,19 @@
+#!/usr/bin/env watchr
+
+# config file for watchr http://github.com/mynyml/watchr
+# install: gem install watchr
+# run: watch watchr.rb
+# note: make sure that you have jstd server running (server.sh) and a browser captured
+
+log_file = File.expand_path(File.dirname(__FILE__) + '/../logs/jstd.log')
+
+`cd ..`
+`touch #{log_file}`
+
+puts "String watchr... log file: #{log_file}"
+
+watch( '(app/js|test/unit)' )  do
+  `echo "\n\ntest run started @ \`date\`" > #{log_file}`
+  `scripts/test.sh &> #{log_file}`
+end
+

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/scripts/.svn/text-base/web-server.js.svn-base
----------------------------------------------------------------------
diff --git a/src/main/ui/scripts/.svn/text-base/web-server.js.svn-base b/src/main/ui/scripts/.svn/text-base/web-server.js.svn-base
new file mode 100755
index 0000000..0d1a248
--- /dev/null
+++ b/src/main/ui/scripts/.svn/text-base/web-server.js.svn-base
@@ -0,0 +1,295 @@
+#!/usr/bin/env node
+
+var util = require('util'),
+    http = require('http'),
+    fs = require('fs'),
+    url = require('url'),
+    events = require('events');
+
+var DEFAULT_PORT = 8000;
+
+function main(argv) {
+  new HttpServer({
+    'GET': createServlet(StaticServlet),
+    'HEAD': createServlet(StaticServlet)
+  }).start(Number(argv[2]) || DEFAULT_PORT);
+}
+
+function escapeHtml(value) {
+  return value.toString().
+    replace('<', '&lt;').
+    replace('>', '&gt;').
+    replace('"', '&quot;');
+}
+
+function createServlet(Class) {
+  var servlet = new Class();
+  return servlet.handleRequest.bind(servlet);
+}
+
+/**
+ * An Http server implementation that uses a map of methods to decide
+ * action routing.
+ *
+ * @param {Object} Map of method => Handler function
+ */
+function HttpServer(handlers) {
+  this.handlers = handlers;
+  this.server = http.createServer(this.handleRequest_.bind(this));
+}
+
+HttpServer.prototype.start = function(port) {
+  this.port = port;
+  this.server.listen(port);
+  util.puts('Http Server running at http://localhost:' + port + '/');
+};
+
+HttpServer.prototype.parseUrl_ = function(urlString) {
+  var parsed = url.parse(urlString);
+  parsed.pathname = url.resolve('/', parsed.pathname);
+  return url.parse(url.format(parsed), true);
+};
+
+HttpServer.prototype.handleRequest_ = function(req, res) {
+  var logEntry = req.method + ' ' + req.url;
+  if (req.headers['user-agent']) {
+    logEntry += ' ' + req.headers['user-agent'];
+  }
+  util.puts(logEntry);
+  req.url = this.parseUrl_(req.url);
+  var handler = this.handlers[req.method];
+  if (!handler) {
+    res.writeHead(501);
+    res.end();
+  } else {
+    handler.call(this, req, res);
+  }
+};
+
+/**
+ * Handles static content.
+ */
+function StaticServlet() {}
+
+StaticServlet.MimeMap = {
+  'txt': 'text/plain',
+  'html': 'text/html',
+  'css': 'text/css',
+  'xml': 'application/xml',
+  'json': 'application/json',
+  'js': 'application/javascript',
+  'jpg': 'image/jpeg',
+  'jpeg': 'image/jpeg',
+  'gif': 'image/gif',
+  'png': 'image/png',
+  'svg': 'image/svg+xml'
+};
+
+StaticServlet.prototype.handleRequest = function(req, res) {
+  var self = this;
+  var path = ('./' + req.url.pathname).replace('//','/').replace(/%(..)/g, function(match, hex){
+    return String.fromCharCode(parseInt(hex, 16));
+  });
+  var parts = path.split('/');
+  if (parts[parts.length-1].charAt(0) === '.')
+    return self.sendForbidden_(req, res, path);
+  if (~path.indexOf("dirlist"))
+    return self.getDirList_(req, res, path);
+  fs.stat(path, function(err, stat) {
+    if (err)
+      return self.sendMissing_(req, res, path);
+    if (stat.isDirectory())
+      return self.sendDirectory_(req, res, path);
+    return self.sendFile_(req, res, path);
+  });
+}
+
+StaticServlet.prototype.sendError_ = function(req, res, error) {
+  res.writeHead(500, {
+      'Content-Type': 'text/html'
+  });
+  res.write('<!doctype html>\n');
+  res.write('<title>Internal Server Error</title>\n');
+  res.write('<h1>Internal Server Error</h1>');
+  res.write('<pre>' + escapeHtml(util.inspect(error)) + '</pre>');
+  util.puts('500 Internal Server Error');
+  util.puts(util.inspect(error));
+};
+
+StaticServlet.prototype.sendMissing_ = function(req, res, path) {
+  path = path.substring(1);
+  res.writeHead(404, {
+      'Content-Type': 'text/html'
+  });
+  res.write('<!doctype html>\n');
+  res.write('<title>404 Not Found</title>\n');
+  res.write('<h1>Not Found</h1>');
+  res.write(
+    '<p>The requested URL ' +
+    escapeHtml(path) +
+    ' was not found on this server.</p>'
+  );
+  res.end();
+  util.puts('404 Not Found: ' + path);
+};
+
+StaticServlet.prototype.sendForbidden_ = function(req, res, path) {
+  path = path.substring(1);
+  res.writeHead(403, {
+      'Content-Type': 'text/html'
+  });
+  res.write('<!doctype html>\n');
+  res.write('<title>403 Forbidden</title>\n');
+  res.write('<h1>Forbidden</h1>');
+  res.write(
+    '<p>You do not have permission to access ' +
+    escapeHtml(path) + ' on this server.</p>'
+  );
+  res.end();
+  util.puts('403 Forbidden: ' + path);
+};
+
+StaticServlet.prototype.sendRedirect_ = function(req, res, redirectUrl) {
+  res.writeHead(301, {
+      'Content-Type': 'text/html',
+      'Location': redirectUrl
+  });
+  res.write('<!doctype html>\n');
+  res.write('<title>301 Moved Permanently</title>\n');
+  res.write('<h1>Moved Permanently</h1>');
+  res.write(
+    '<p>The document has moved <a href="' +
+    redirectUrl +
+    '">here</a>.</p>'
+  );
+  res.end();
+  util.puts('301 Moved Permanently: ' + redirectUrl);
+};
+
+StaticServlet.prototype.getDirList_ = function(req, res, path) {
+  res.writeHead(200, {
+	'Content-Type': 'json'
+  });
+
+  // Grab the passed path value
+  var pathQuery = url.parse(req.url, true).query.path
+  // Using the supplied path, grab directory information
+  var dirList = fs.readdirSync(pathQuery);
+
+  // Filter out any hidden files or current/previous directory references
+  dirList = dirList.filter(function(item, index, array) {
+	return (item[0] !== ".");
+  });
+  
+  // Generate the full path names for all the items found when 'ls'-ing 
+  // the passed directory.
+  dirList = dirList.map(function(item, index, array) {
+    var temp = item; 
+
+	// Make sure the path is joined properly. Sometimes there will be a trailing
+	// '/' in the path and sometimes there won't. Don't want to end up with '//'.
+    if (pathQuery[pathQuery.length - 1] === "/") {
+      temp = pathQuery + item;
+    } else {
+  	  temp = pathQuery + "/" + item;
+    }
+  
+	// We want the directories that are found to have a trailing '/'. Let's make sure
+	// that we do that!
+    var ret = temp;
+    if (fs.existsSync(temp + "/")) {
+     ret = temp + "/";
+    }  
+
+    return ret;
+  });
+  
+  // Sort all the results alphabetically ignoring case.
+  dirList = dirList.sort(function(a, b) {
+    if (a.toLowerCase() < b.toLowerCase()) return -1;
+    if (a.toLowerCase() > b.toLowerCase()) return 1;
+    return 0;
+  });
+
+  res.write(JSON.stringify(dirList));
+  res.end();
+}
+
+StaticServlet.prototype.sendFile_ = function(req, res, path) {
+  var self = this;
+  var file = fs.createReadStream(path);
+  res.writeHead(200, {
+    'Content-Type': StaticServlet.
+      MimeMap[path.split('.').pop()] || 'text/plain'
+  });
+  if (req.method === 'HEAD') {
+    res.end();
+  } else {
+    file.on('data', res.write.bind(res));
+    file.on('close', function() {
+      res.end();
+    });
+    file.on('error', function(error) {
+      self.sendError_(req, res, error);
+    });
+  }
+};
+
+StaticServlet.prototype.sendDirectory_ = function(req, res, path) {
+  var self = this;
+  if (path.match(/[^\/]$/)) {
+    req.url.pathname += '/';
+    var redirectUrl = url.format(url.parse(url.format(req.url)));
+    return self.sendRedirect_(req, res, redirectUrl);
+  }
+  fs.readdir(path, function(err, files) {
+    if (err)
+      return self.sendError_(req, res, error);
+
+    if (!files.length)
+      return self.writeDirectoryIndex_(req, res, path, []);
+
+    var remaining = files.length;
+    files.forEach(function(fileName, index) {
+      fs.stat(path + '/' + fileName, function(err, stat) {
+        if (err)
+          return self.sendError_(req, res, err);
+        if (stat.isDirectory()) {
+          files[index] = fileName + '/';
+        }
+        if (!(--remaining))
+          return self.writeDirectoryIndex_(req, res, path, files);
+      });
+    });
+  });
+};
+
+StaticServlet.prototype.writeDirectoryIndex_ = function(req, res, path, files) {
+  path = path.substring(1);
+  res.writeHead(200, {
+    'Content-Type': 'text/html'
+  });
+  if (req.method === 'HEAD') {
+    res.end();
+    return;
+  }
+  res.write('<!doctype html>\n');
+  res.write('<title>' + escapeHtml(path) + '</title>\n');
+  res.write('<style>\n');
+  res.write('  ol { list-style-type: none; font-size: 1.2em; }\n');
+  res.write('</style>\n');
+  res.write('<h1>Directory: ' + escapeHtml(path) + '</h1>');
+  res.write('<ol>');
+  files.forEach(function(fileName) {
+    if (fileName.charAt(0) !== '.') {
+      res.write('<li><a href="' +
+        escapeHtml(fileName) + '">' +
+        escapeHtml(fileName) + '</a></li>');
+    }
+  });
+  res.write('</ol>');
+  res.end();
+};
+
+// Must be last,
+main(process.argv);

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/scripts/e2e-test.bat
----------------------------------------------------------------------
diff --git a/src/main/ui/scripts/e2e-test.bat b/src/main/ui/scripts/e2e-test.bat
new file mode 100755
index 0000000..c89a708
--- /dev/null
+++ b/src/main/ui/scripts/e2e-test.bat
@@ -0,0 +1,11 @@
+@echo off
+
+REM Windows script for running e2e tests
+REM You have to run server and capture some browser first
+REM
+REM Requirements:
+REM - NodeJS (http://nodejs.org/)
+REM - Testacular (npm install -g testacular)
+
+set BASE_DIR=%~dp0
+testacular start "%BASE_DIR%\..\config\testacular-e2e.conf.js" %*

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/scripts/e2e-test.sh
----------------------------------------------------------------------
diff --git a/src/main/ui/scripts/e2e-test.sh b/src/main/ui/scripts/e2e-test.sh
new file mode 100755
index 0000000..e887c34
--- /dev/null
+++ b/src/main/ui/scripts/e2e-test.sh
@@ -0,0 +1,9 @@
+#!/bin/bash
+
+BASE_DIR=`dirname $0`
+
+echo ""
+echo "Starting Testacular Server (http://vojtajina.github.com/testacular)"
+echo "-------------------------------------------------------------------"
+
+testacular start $BASE_DIR/../config/testacular-e2e.conf.js $*

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/scripts/test.bat
----------------------------------------------------------------------
diff --git a/src/main/ui/scripts/test.bat b/src/main/ui/scripts/test.bat
new file mode 100755
index 0000000..000242f
--- /dev/null
+++ b/src/main/ui/scripts/test.bat
@@ -0,0 +1,11 @@
+@echo off
+
+REM Windows script for running unit tests
+REM You have to run server and capture some browser first
+REM
+REM Requirements:
+REM - NodeJS (http://nodejs.org/)
+REM - Testacular (npm install -g testacular)
+
+set BASE_DIR=%~dp0
+testacular start "%BASE_DIR%\..\config\testacular.conf.js" %*

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/scripts/test.sh
----------------------------------------------------------------------
diff --git a/src/main/ui/scripts/test.sh b/src/main/ui/scripts/test.sh
new file mode 100755
index 0000000..4c37cde
--- /dev/null
+++ b/src/main/ui/scripts/test.sh
@@ -0,0 +1,9 @@
+#!/bin/bash
+
+BASE_DIR=`dirname $0`
+
+echo ""
+echo "Starting Testacular Server (http://vojtajina.github.com/testacular)"
+echo "-------------------------------------------------------------------"
+
+testacular start $BASE_DIR/../config/testacular.conf.js $*

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/scripts/testacular-e2e.conf.js
----------------------------------------------------------------------
diff --git a/src/main/ui/scripts/testacular-e2e.conf.js b/src/main/ui/scripts/testacular-e2e.conf.js
new file mode 100755
index 0000000..51f51d2
--- /dev/null
+++ b/src/main/ui/scripts/testacular-e2e.conf.js
@@ -0,0 +1,22 @@
+basePath = '../';
+
+files = [
+  ANGULAR_SCENARIO,
+  ANGULAR_SCENARIO_ADAPTER,
+  'test/e2e/**/*.js'
+];
+
+autoWatch = false;
+
+browsers = ['Chrome'];
+
+singleRun = true;
+
+proxies = {
+  '/': 'http://localhost:8000/'
+};
+
+junitReporter = {
+  outputFile: 'test_out/e2e.xml',
+  suite: 'e2e'
+};

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/scripts/testacular.conf.js
----------------------------------------------------------------------
diff --git a/src/main/ui/scripts/testacular.conf.js b/src/main/ui/scripts/testacular.conf.js
new file mode 100755
index 0000000..5dc0dae
--- /dev/null
+++ b/src/main/ui/scripts/testacular.conf.js
@@ -0,0 +1,23 @@
+basePath = '../';
+
+files = [
+  JASMINE,
+  JASMINE_ADAPTER,
+  'app/js/jquery-1.9.1.min.js',
+  'app/js/bootstrap.js',
+  'app/lib/angular/angular.js',
+  'app/lib/angular/angular-*.js',
+  'test/lib/angular/angular-mocks.js',
+  'app/js/leaflet.js',
+  'app/js/**/*.js',
+  'test/unit/**/*.js'
+];
+
+autoWatch = true;
+
+browsers = ['Chrome'];
+
+junitReporter = {
+  outputFile: 'test_out/unit.xml',
+  suite: 'unit'
+};

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/scripts/watchr.rb
----------------------------------------------------------------------
diff --git a/src/main/ui/scripts/watchr.rb b/src/main/ui/scripts/watchr.rb
new file mode 100755
index 0000000..89ef656
--- /dev/null
+++ b/src/main/ui/scripts/watchr.rb
@@ -0,0 +1,19 @@
+#!/usr/bin/env watchr
+
+# config file for watchr http://github.com/mynyml/watchr
+# install: gem install watchr
+# run: watch watchr.rb
+# note: make sure that you have jstd server running (server.sh) and a browser captured
+
+log_file = File.expand_path(File.dirname(__FILE__) + '/../logs/jstd.log')
+
+`cd ..`
+`touch #{log_file}`
+
+puts "String watchr... log file: #{log_file}"
+
+watch( '(app/js|test/unit)' )  do
+  `echo "\n\ntest run started @ \`date\`" > #{log_file}`
+  `scripts/test.sh &> #{log_file}`
+end
+

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/scripts/web-server.js
----------------------------------------------------------------------
diff --git a/src/main/ui/scripts/web-server.js b/src/main/ui/scripts/web-server.js
new file mode 100755
index 0000000..0d1a248
--- /dev/null
+++ b/src/main/ui/scripts/web-server.js
@@ -0,0 +1,295 @@
+#!/usr/bin/env node
+
+var util = require('util'),
+    http = require('http'),
+    fs = require('fs'),
+    url = require('url'),
+    events = require('events');
+
+var DEFAULT_PORT = 8000;
+
+function main(argv) {
+  new HttpServer({
+    'GET': createServlet(StaticServlet),
+    'HEAD': createServlet(StaticServlet)
+  }).start(Number(argv[2]) || DEFAULT_PORT);
+}
+
+function escapeHtml(value) {
+  return value.toString().
+    replace('<', '&lt;').
+    replace('>', '&gt;').
+    replace('"', '&quot;');
+}
+
+function createServlet(Class) {
+  var servlet = new Class();
+  return servlet.handleRequest.bind(servlet);
+}
+
+/**
+ * An Http server implementation that uses a map of methods to decide
+ * action routing.
+ *
+ * @param {Object} Map of method => Handler function
+ */
+function HttpServer(handlers) {
+  this.handlers = handlers;
+  this.server = http.createServer(this.handleRequest_.bind(this));
+}
+
+HttpServer.prototype.start = function(port) {
+  this.port = port;
+  this.server.listen(port);
+  util.puts('Http Server running at http://localhost:' + port + '/');
+};
+
+HttpServer.prototype.parseUrl_ = function(urlString) {
+  var parsed = url.parse(urlString);
+  parsed.pathname = url.resolve('/', parsed.pathname);
+  return url.parse(url.format(parsed), true);
+};
+
+HttpServer.prototype.handleRequest_ = function(req, res) {
+  var logEntry = req.method + ' ' + req.url;
+  if (req.headers['user-agent']) {
+    logEntry += ' ' + req.headers['user-agent'];
+  }
+  util.puts(logEntry);
+  req.url = this.parseUrl_(req.url);
+  var handler = this.handlers[req.method];
+  if (!handler) {
+    res.writeHead(501);
+    res.end();
+  } else {
+    handler.call(this, req, res);
+  }
+};
+
+/**
+ * Handles static content.
+ */
+function StaticServlet() {}
+
+StaticServlet.MimeMap = {
+  'txt': 'text/plain',
+  'html': 'text/html',
+  'css': 'text/css',
+  'xml': 'application/xml',
+  'json': 'application/json',
+  'js': 'application/javascript',
+  'jpg': 'image/jpeg',
+  'jpeg': 'image/jpeg',
+  'gif': 'image/gif',
+  'png': 'image/png',
+  'svg': 'image/svg+xml'
+};
+
+StaticServlet.prototype.handleRequest = function(req, res) {
+  var self = this;
+  var path = ('./' + req.url.pathname).replace('//','/').replace(/%(..)/g, function(match, hex){
+    return String.fromCharCode(parseInt(hex, 16));
+  });
+  var parts = path.split('/');
+  if (parts[parts.length-1].charAt(0) === '.')
+    return self.sendForbidden_(req, res, path);
+  if (~path.indexOf("dirlist"))
+    return self.getDirList_(req, res, path);
+  fs.stat(path, function(err, stat) {
+    if (err)
+      return self.sendMissing_(req, res, path);
+    if (stat.isDirectory())
+      return self.sendDirectory_(req, res, path);
+    return self.sendFile_(req, res, path);
+  });
+}
+
+StaticServlet.prototype.sendError_ = function(req, res, error) {
+  res.writeHead(500, {
+      'Content-Type': 'text/html'
+  });
+  res.write('<!doctype html>\n');
+  res.write('<title>Internal Server Error</title>\n');
+  res.write('<h1>Internal Server Error</h1>');
+  res.write('<pre>' + escapeHtml(util.inspect(error)) + '</pre>');
+  util.puts('500 Internal Server Error');
+  util.puts(util.inspect(error));
+};
+
+StaticServlet.prototype.sendMissing_ = function(req, res, path) {
+  path = path.substring(1);
+  res.writeHead(404, {
+      'Content-Type': 'text/html'
+  });
+  res.write('<!doctype html>\n');
+  res.write('<title>404 Not Found</title>\n');
+  res.write('<h1>Not Found</h1>');
+  res.write(
+    '<p>The requested URL ' +
+    escapeHtml(path) +
+    ' was not found on this server.</p>'
+  );
+  res.end();
+  util.puts('404 Not Found: ' + path);
+};
+
+StaticServlet.prototype.sendForbidden_ = function(req, res, path) {
+  path = path.substring(1);
+  res.writeHead(403, {
+      'Content-Type': 'text/html'
+  });
+  res.write('<!doctype html>\n');
+  res.write('<title>403 Forbidden</title>\n');
+  res.write('<h1>Forbidden</h1>');
+  res.write(
+    '<p>You do not have permission to access ' +
+    escapeHtml(path) + ' on this server.</p>'
+  );
+  res.end();
+  util.puts('403 Forbidden: ' + path);
+};
+
+StaticServlet.prototype.sendRedirect_ = function(req, res, redirectUrl) {
+  res.writeHead(301, {
+      'Content-Type': 'text/html',
+      'Location': redirectUrl
+  });
+  res.write('<!doctype html>\n');
+  res.write('<title>301 Moved Permanently</title>\n');
+  res.write('<h1>Moved Permanently</h1>');
+  res.write(
+    '<p>The document has moved <a href="' +
+    redirectUrl +
+    '">here</a>.</p>'
+  );
+  res.end();
+  util.puts('301 Moved Permanently: ' + redirectUrl);
+};
+
+StaticServlet.prototype.getDirList_ = function(req, res, path) {
+  res.writeHead(200, {
+	'Content-Type': 'json'
+  });
+
+  // Grab the passed path value
+  var pathQuery = url.parse(req.url, true).query.path
+  // Using the supplied path, grab directory information
+  var dirList = fs.readdirSync(pathQuery);
+
+  // Filter out any hidden files or current/previous directory references
+  dirList = dirList.filter(function(item, index, array) {
+	return (item[0] !== ".");
+  });
+  
+  // Generate the full path names for all the items found when 'ls'-ing 
+  // the passed directory.
+  dirList = dirList.map(function(item, index, array) {
+    var temp = item; 
+
+	// Make sure the path is joined properly. Sometimes there will be a trailing
+	// '/' in the path and sometimes there won't. Don't want to end up with '//'.
+    if (pathQuery[pathQuery.length - 1] === "/") {
+      temp = pathQuery + item;
+    } else {
+  	  temp = pathQuery + "/" + item;
+    }
+  
+	// We want the directories that are found to have a trailing '/'. Let's make sure
+	// that we do that!
+    var ret = temp;
+    if (fs.existsSync(temp + "/")) {
+     ret = temp + "/";
+    }  
+
+    return ret;
+  });
+  
+  // Sort all the results alphabetically ignoring case.
+  dirList = dirList.sort(function(a, b) {
+    if (a.toLowerCase() < b.toLowerCase()) return -1;
+    if (a.toLowerCase() > b.toLowerCase()) return 1;
+    return 0;
+  });
+
+  res.write(JSON.stringify(dirList));
+  res.end();
+}
+
+StaticServlet.prototype.sendFile_ = function(req, res, path) {
+  var self = this;
+  var file = fs.createReadStream(path);
+  res.writeHead(200, {
+    'Content-Type': StaticServlet.
+      MimeMap[path.split('.').pop()] || 'text/plain'
+  });
+  if (req.method === 'HEAD') {
+    res.end();
+  } else {
+    file.on('data', res.write.bind(res));
+    file.on('close', function() {
+      res.end();
+    });
+    file.on('error', function(error) {
+      self.sendError_(req, res, error);
+    });
+  }
+};
+
+StaticServlet.prototype.sendDirectory_ = function(req, res, path) {
+  var self = this;
+  if (path.match(/[^\/]$/)) {
+    req.url.pathname += '/';
+    var redirectUrl = url.format(url.parse(url.format(req.url)));
+    return self.sendRedirect_(req, res, redirectUrl);
+  }
+  fs.readdir(path, function(err, files) {
+    if (err)
+      return self.sendError_(req, res, error);
+
+    if (!files.length)
+      return self.writeDirectoryIndex_(req, res, path, []);
+
+    var remaining = files.length;
+    files.forEach(function(fileName, index) {
+      fs.stat(path + '/' + fileName, function(err, stat) {
+        if (err)
+          return self.sendError_(req, res, err);
+        if (stat.isDirectory()) {
+          files[index] = fileName + '/';
+        }
+        if (!(--remaining))
+          return self.writeDirectoryIndex_(req, res, path, files);
+      });
+    });
+  });
+};
+
+StaticServlet.prototype.writeDirectoryIndex_ = function(req, res, path, files) {
+  path = path.substring(1);
+  res.writeHead(200, {
+    'Content-Type': 'text/html'
+  });
+  if (req.method === 'HEAD') {
+    res.end();
+    return;
+  }
+  res.write('<!doctype html>\n');
+  res.write('<title>' + escapeHtml(path) + '</title>\n');
+  res.write('<style>\n');
+  res.write('  ol { list-style-type: none; font-size: 1.2em; }\n');
+  res.write('</style>\n');
+  res.write('<h1>Directory: ' + escapeHtml(path) + '</h1>');
+  res.write('<ol>');
+  files.forEach(function(fileName) {
+    if (fileName.charAt(0) !== '.') {
+      res.write('<li><a href="' +
+        escapeHtml(fileName) + '">' +
+        escapeHtml(fileName) + '</a></li>');
+    }
+  });
+  res.write('</ol>');
+  res.end();
+};
+
+// Must be last,
+main(process.argv);

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/test/.svn/all-wcprops
----------------------------------------------------------------------
diff --git a/src/main/ui/test/.svn/all-wcprops b/src/main/ui/test/.svn/all-wcprops
new file mode 100755
index 0000000..985f754
--- /dev/null
+++ b/src/main/ui/test/.svn/all-wcprops
@@ -0,0 +1,5 @@
+K 25
+svn:wc:ra_dav:version-url
+V 74
+/repos/asf/!svn/ver/1480068/incubator/climate/trunk/rcmet/src/main/ui/test
+END

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/test/.svn/entries
----------------------------------------------------------------------
diff --git a/src/main/ui/test/.svn/entries b/src/main/ui/test/.svn/entries
new file mode 100755
index 0000000..23f284c
--- /dev/null
+++ b/src/main/ui/test/.svn/entries
@@ -0,0 +1,37 @@
+10
+
+dir
+1485921
+https://svn.apache.org/repos/asf/incubator/climate/trunk/rcmet/src/main/ui/test
+https://svn.apache.org/repos/asf
+
+
+
+2013-05-07T20:50:17.582309Z
+1480068
+joyce
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+13f79535-47bb-0310-9956-ffa450edef68
+
+unit
+dir
+
+lib
+dir
+
+e2e
+dir
+

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/test/e2e/.svn/all-wcprops
----------------------------------------------------------------------
diff --git a/src/main/ui/test/e2e/.svn/all-wcprops b/src/main/ui/test/e2e/.svn/all-wcprops
new file mode 100755
index 0000000..9630d5c
--- /dev/null
+++ b/src/main/ui/test/e2e/.svn/all-wcprops
@@ -0,0 +1,17 @@
+K 25
+svn:wc:ra_dav:version-url
+V 78
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/ui/test/e2e
+END
+scenarios.js
+K 25
+svn:wc:ra_dav:version-url
+V 91
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/ui/test/e2e/scenarios.js
+END
+runner.html
+K 25
+svn:wc:ra_dav:version-url
+V 90
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/ui/test/e2e/runner.html
+END

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/test/e2e/.svn/entries
----------------------------------------------------------------------
diff --git a/src/main/ui/test/e2e/.svn/entries b/src/main/ui/test/e2e/.svn/entries
new file mode 100755
index 0000000..689e080
--- /dev/null
+++ b/src/main/ui/test/e2e/.svn/entries
@@ -0,0 +1,96 @@
+10
+
+dir
+1485921
+https://svn.apache.org/repos/asf/incubator/climate/trunk/rcmet/src/main/ui/test/e2e
+https://svn.apache.org/repos/asf
+
+
+
+2013-03-13T02:34:30.834306Z
+1475137
+mjjoyce
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+13f79535-47bb-0310-9956-ffa450edef68
+
+scenarios.js
+file
+
+
+
+
+2013-05-24T10:13:56.000000Z
+c7986c2afc527fad2b30a95162c86f52
+2013-03-13T02:34:30.834306Z
+1475137
+mjjoyce
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+938
+
+runner.html
+file
+
+
+
+
+2013-05-24T10:13:56.000000Z
+1c808bdae719fb220a52654dcd304633
+2013-03-13T02:34:30.834306Z
+1475137
+mjjoyce
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+234
+

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/test/e2e/.svn/prop-base/runner.html.svn-base
----------------------------------------------------------------------
diff --git a/src/main/ui/test/e2e/.svn/prop-base/runner.html.svn-base b/src/main/ui/test/e2e/.svn/prop-base/runner.html.svn-base
new file mode 100755
index 0000000..869ac71
--- /dev/null
+++ b/src/main/ui/test/e2e/.svn/prop-base/runner.html.svn-base
@@ -0,0 +1,5 @@
+K 14
+svn:executable
+V 1
+*
+END

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/test/e2e/.svn/prop-base/scenarios.js.svn-base
----------------------------------------------------------------------
diff --git a/src/main/ui/test/e2e/.svn/prop-base/scenarios.js.svn-base b/src/main/ui/test/e2e/.svn/prop-base/scenarios.js.svn-base
new file mode 100755
index 0000000..869ac71
--- /dev/null
+++ b/src/main/ui/test/e2e/.svn/prop-base/scenarios.js.svn-base
@@ -0,0 +1,5 @@
+K 14
+svn:executable
+V 1
+*
+END

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/test/e2e/.svn/text-base/runner.html.svn-base
----------------------------------------------------------------------
diff --git a/src/main/ui/test/e2e/.svn/text-base/runner.html.svn-base b/src/main/ui/test/e2e/.svn/text-base/runner.html.svn-base
new file mode 100755
index 0000000..a40fa08
--- /dev/null
+++ b/src/main/ui/test/e2e/.svn/text-base/runner.html.svn-base
@@ -0,0 +1,10 @@
+<!doctype html>
+<html lang="en">
+  <head>
+    <title>End2end Test Runner</title>
+    <script src="../lib/angular/angular-scenario.js" ng-autotest></script>
+    <script src="scenarios.js"></script>
+  </head>
+  <body>
+  </body>
+</html>

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/test/e2e/.svn/text-base/scenarios.js.svn-base
----------------------------------------------------------------------
diff --git a/src/main/ui/test/e2e/.svn/text-base/scenarios.js.svn-base b/src/main/ui/test/e2e/.svn/text-base/scenarios.js.svn-base
new file mode 100755
index 0000000..26e174a
--- /dev/null
+++ b/src/main/ui/test/e2e/.svn/text-base/scenarios.js.svn-base
@@ -0,0 +1,45 @@
+'use strict';
+
+/* http://docs.angularjs.org/guide/dev_guide.e2e-testing */
+
+describe('my app', function() {
+
+  beforeEach(function() {
+    browser().navigateTo('../../app/index.html');
+  });
+
+
+  it('should automatically redirect to /view1 when location hash/fragment is empty', function() {
+    expect(browser().location().url()).toBe("/view1");
+  });
+
+
+  describe('view1', function() {
+
+    beforeEach(function() {
+      browser().navigateTo('#/view1');
+    });
+
+
+    it('should render view1 when user navigates to /view1', function() {
+      expect(element('[ng-view] p:first').text()).
+        toMatch(/partial for view 1/);
+    });
+
+  });
+
+
+  describe('view2', function() {
+
+    beforeEach(function() {
+      browser().navigateTo('#/view2');
+    });
+
+
+    it('should render view2 when user navigates to /view2', function() {
+      expect(element('[ng-view] p:first').text()).
+        toMatch(/partial for view 2/);
+    });
+
+  });
+});

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/test/e2e/runner.html
----------------------------------------------------------------------
diff --git a/src/main/ui/test/e2e/runner.html b/src/main/ui/test/e2e/runner.html
new file mode 100755
index 0000000..a40fa08
--- /dev/null
+++ b/src/main/ui/test/e2e/runner.html
@@ -0,0 +1,10 @@
+<!doctype html>
+<html lang="en">
+  <head>
+    <title>End2end Test Runner</title>
+    <script src="../lib/angular/angular-scenario.js" ng-autotest></script>
+    <script src="scenarios.js"></script>
+  </head>
+  <body>
+  </body>
+</html>

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/test/e2e/scenarios.js
----------------------------------------------------------------------
diff --git a/src/main/ui/test/e2e/scenarios.js b/src/main/ui/test/e2e/scenarios.js
new file mode 100755
index 0000000..26e174a
--- /dev/null
+++ b/src/main/ui/test/e2e/scenarios.js
@@ -0,0 +1,45 @@
+'use strict';
+
+/* http://docs.angularjs.org/guide/dev_guide.e2e-testing */
+
+describe('my app', function() {
+
+  beforeEach(function() {
+    browser().navigateTo('../../app/index.html');
+  });
+
+
+  it('should automatically redirect to /view1 when location hash/fragment is empty', function() {
+    expect(browser().location().url()).toBe("/view1");
+  });
+
+
+  describe('view1', function() {
+
+    beforeEach(function() {
+      browser().navigateTo('#/view1');
+    });
+
+
+    it('should render view1 when user navigates to /view1', function() {
+      expect(element('[ng-view] p:first').text()).
+        toMatch(/partial for view 1/);
+    });
+
+  });
+
+
+  describe('view2', function() {
+
+    beforeEach(function() {
+      browser().navigateTo('#/view2');
+    });
+
+
+    it('should render view2 when user navigates to /view2', function() {
+      expect(element('[ng-view] p:first').text()).
+        toMatch(/partial for view 2/);
+    });
+
+  });
+});

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/test/lib/.svn/all-wcprops
----------------------------------------------------------------------
diff --git a/src/main/ui/test/lib/.svn/all-wcprops b/src/main/ui/test/lib/.svn/all-wcprops
new file mode 100755
index 0000000..e697ac9
--- /dev/null
+++ b/src/main/ui/test/lib/.svn/all-wcprops
@@ -0,0 +1,5 @@
+K 25
+svn:wc:ra_dav:version-url
+V 78
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/ui/test/lib
+END

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/test/lib/.svn/entries
----------------------------------------------------------------------
diff --git a/src/main/ui/test/lib/.svn/entries b/src/main/ui/test/lib/.svn/entries
new file mode 100755
index 0000000..8b12b3a
--- /dev/null
+++ b/src/main/ui/test/lib/.svn/entries
@@ -0,0 +1,31 @@
+10
+
+dir
+1485921
+https://svn.apache.org/repos/asf/incubator/climate/trunk/rcmet/src/main/ui/test/lib
+https://svn.apache.org/repos/asf
+
+
+
+2013-03-13T02:34:30.834306Z
+1475137
+mjjoyce
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+13f79535-47bb-0310-9956-ffa450edef68
+
+angular
+dir
+

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/test/lib/angular/.svn/all-wcprops
----------------------------------------------------------------------
diff --git a/src/main/ui/test/lib/angular/.svn/all-wcprops b/src/main/ui/test/lib/angular/.svn/all-wcprops
new file mode 100755
index 0000000..7bbdef5
--- /dev/null
+++ b/src/main/ui/test/lib/angular/.svn/all-wcprops
@@ -0,0 +1,23 @@
+K 25
+svn:wc:ra_dav:version-url
+V 86
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/ui/test/lib/angular
+END
+version.txt
+K 25
+svn:wc:ra_dav:version-url
+V 98
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/ui/test/lib/angular/version.txt
+END
+angular-scenario.js
+K 25
+svn:wc:ra_dav:version-url
+V 106
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/ui/test/lib/angular/angular-scenario.js
+END
+angular-mocks.js
+K 25
+svn:wc:ra_dav:version-url
+V 103
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/ui/test/lib/angular/angular-mocks.js
+END

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/test/lib/angular/.svn/entries
----------------------------------------------------------------------
diff --git a/src/main/ui/test/lib/angular/.svn/entries b/src/main/ui/test/lib/angular/.svn/entries
new file mode 100755
index 0000000..9782df5
--- /dev/null
+++ b/src/main/ui/test/lib/angular/.svn/entries
@@ -0,0 +1,130 @@
+10
+
+dir
+1485921
+https://svn.apache.org/repos/asf/incubator/climate/trunk/rcmet/src/main/ui/test/lib/angular
+https://svn.apache.org/repos/asf
+
+
+
+2013-03-13T02:34:30.834306Z
+1475137
+mjjoyce
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+13f79535-47bb-0310-9956-ffa450edef68
+
+version.txt
+file
+
+
+
+
+2013-05-24T10:13:55.000000Z
+34cd1f67e8156bf27ba489aacd9acb1f
+2013-03-13T02:34:30.834306Z
+1475137
+mjjoyce
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+6
+
+angular-scenario.js
+file
+
+
+
+
+2013-05-24T10:13:55.000000Z
+01b3e787da465d718535aa127e82f2af
+2013-03-13T02:34:30.834306Z
+1475137
+mjjoyce
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+805828
+
+angular-mocks.js
+file
+
+
+
+
+2013-05-24T10:13:55.000000Z
+1924c97ae0d78b43f093e529c6143d86
+2013-03-13T02:34:30.834306Z
+1475137
+mjjoyce
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+56116
+

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/test/lib/angular/.svn/prop-base/angular-mocks.js.svn-base
----------------------------------------------------------------------
diff --git a/src/main/ui/test/lib/angular/.svn/prop-base/angular-mocks.js.svn-base b/src/main/ui/test/lib/angular/.svn/prop-base/angular-mocks.js.svn-base
new file mode 100755
index 0000000..869ac71
--- /dev/null
+++ b/src/main/ui/test/lib/angular/.svn/prop-base/angular-mocks.js.svn-base
@@ -0,0 +1,5 @@
+K 14
+svn:executable
+V 1
+*
+END

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/test/lib/angular/.svn/prop-base/angular-scenario.js.svn-base
----------------------------------------------------------------------
diff --git a/src/main/ui/test/lib/angular/.svn/prop-base/angular-scenario.js.svn-base b/src/main/ui/test/lib/angular/.svn/prop-base/angular-scenario.js.svn-base
new file mode 100755
index 0000000..869ac71
--- /dev/null
+++ b/src/main/ui/test/lib/angular/.svn/prop-base/angular-scenario.js.svn-base
@@ -0,0 +1,5 @@
+K 14
+svn:executable
+V 1
+*
+END

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/test/lib/angular/.svn/prop-base/version.txt.svn-base
----------------------------------------------------------------------
diff --git a/src/main/ui/test/lib/angular/.svn/prop-base/version.txt.svn-base b/src/main/ui/test/lib/angular/.svn/prop-base/version.txt.svn-base
new file mode 100755
index 0000000..869ac71
--- /dev/null
+++ b/src/main/ui/test/lib/angular/.svn/prop-base/version.txt.svn-base
@@ -0,0 +1,5 @@
+K 14
+svn:executable
+V 1
+*
+END


[31/51] [abbrv] [partial] Adding Jinwon's custom RCMET

Posted by jo...@apache.org.
http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/app/font/.svn/text-base/fontawesome-webfont.svg.svn-base
----------------------------------------------------------------------
diff --git a/src/main/ui/app/font/.svn/text-base/fontawesome-webfont.svg.svn-base b/src/main/ui/app/font/.svn/text-base/fontawesome-webfont.svg.svn-base
new file mode 100755
index 0000000..ba0afe5
--- /dev/null
+++ b/src/main/ui/app/font/.svn/text-base/fontawesome-webfont.svg.svn-base
@@ -0,0 +1,284 @@
+<?xml version="1.0" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
+<svg xmlns="http://www.w3.org/2000/svg">
+<metadata></metadata>
+<defs>
+<font id="fontawesomeregular" horiz-adv-x="1536" >
+<font-face units-per-em="1792" ascent="1536" descent="-256" />
+<missing-glyph horiz-adv-x="448" />
+<glyph unicode=" "  horiz-adv-x="448" />
+<glyph unicode="&#x09;" horiz-adv-x="448" />
+<glyph unicode="&#xa0;" horiz-adv-x="448" />
+<glyph unicode="&#xa8;" horiz-adv-x="1792" />
+<glyph unicode="&#xa9;" horiz-adv-x="1792" />
+<glyph unicode="&#xae;" horiz-adv-x="1792" />
+<glyph unicode="&#xb4;" horiz-adv-x="1792" />
+<glyph unicode="&#xc6;" horiz-adv-x="1792" />
+<glyph unicode="&#x2000;" horiz-adv-x="768" />
+<glyph unicode="&#x2001;" />
+<glyph unicode="&#x2002;" horiz-adv-x="768" />
+<glyph unicode="&#x2003;" />
+<glyph unicode="&#x2004;" horiz-adv-x="512" />
+<glyph unicode="&#x2005;" horiz-adv-x="384" />
+<glyph unicode="&#x2006;" horiz-adv-x="256" />
+<glyph unicode="&#x2007;" horiz-adv-x="256" />
+<glyph unicode="&#x2008;" horiz-adv-x="192" />
+<glyph unicode="&#x2009;" horiz-adv-x="307" />
+<glyph unicode="&#x200a;" horiz-adv-x="85" />
+<glyph unicode="&#x202f;" horiz-adv-x="307" />
+<glyph unicode="&#x205f;" horiz-adv-x="384" />
+<glyph unicode="&#x2122;" horiz-adv-x="1792" />
+<glyph unicode="&#x221e;" horiz-adv-x="1792" />
+<glyph unicode="&#x2260;" horiz-adv-x="1792" />
+<glyph unicode="&#xe000;" horiz-adv-x="500" d="M0 0z" />
+<glyph unicode="&#xf000;" horiz-adv-x="1792" d="M1699 1350q0 -35 -43 -78l-632 -632v-768h320q26 0 45 -19t19 -45t-19 -45t-45 -19h-896q-26 0 -45 19t-19 45t19 45t45 19h320v768l-632 632q-43 43 -43 78q0 23 18 36.5t38 17.5t43 4h1408q23 0 43 -4t38 -17.5t18 -36.5z" />
+<glyph unicode="&#xf001;" d="M1536 1312v-1120q0 -50 -34 -89t-86 -60.5t-103.5 -32t-96.5 -10.5t-96.5 10.5t-103.5 32t-86 60.5t-34 89t34 89t86 60.5t103.5 32t96.5 10.5q105 0 192 -39v537l-768 -237v-709q0 -50 -34 -89t-86 -60.5t-103.5 -32t-96.5 -10.5t-96.5 10.5t-103.5 32t-86 60.5t-34 89 t34 89t86 60.5t103.5 32t96.5 10.5q105 0 192 -39v967q0 31 19 56.5t49 35.5l832 256q12 4 28 4q40 0 68 -28t28 -68z" />
+<glyph unicode="&#xf002;" horiz-adv-x="1664" d="M1152 704q0 185 -131.5 316.5t-316.5 131.5t-316.5 -131.5t-131.5 -316.5t131.5 -316.5t316.5 -131.5t316.5 131.5t131.5 316.5zM1664 -128q0 -52 -38 -90t-90 -38q-54 0 -90 38l-343 342q-179 -124 -399 -124q-143 0 -273.5 55.5t-225 150t-150 225t-55.5 273.5 t55.5 273.5t150 225t225 150t273.5 55.5t273.5 -55.5t225 -150t150 -225t55.5 -273.5q0 -220 -124 -399l343 -343q37 -37 37 -90z" />
+<glyph unicode="&#xf003;" horiz-adv-x="1792" d="M1664 32v768q-32 -36 -69 -66q-268 -206 -426 -338q-51 -43 -83 -67t-86.5 -48.5t-102.5 -24.5h-1h-1q-48 0 -102.5 24.5t-86.5 48.5t-83 67q-158 132 -426 338q-37 30 -69 66v-768q0 -13 9.5 -22.5t22.5 -9.5h1472q13 0 22.5 9.5t9.5 22.5zM1664 1083v11v13.5t-0.5 13 t-3 12.5t-5.5 9t-9 7.5t-14 2.5h-1472q-13 0 -22.5 -9.5t-9.5 -22.5q0 -168 147 -284q193 -152 401 -317q6 -5 35 -29.5t46 -37.5t44.5 -31.5t50.5 -27.5t43 -9h1h1q20 0 43 9t50.5 27.5t44.5 31.5t46 37.5t35 29.5q208 165 401 317q54 43 100.5 115.5t46.5 131.5z M1792 1120v-1088q0 -66 -47 -113t-113 -47h-1472q-66 0 -113 47t-47 113v1088q0 66 47 113t113 47h1472q66 0 113 -47t47 -113z" />
+<glyph unicode="&#xf004;" horiz-adv-x="1792" d="M896 -128q-26 0 -44 18l-624 602q-10 8 -27.5 26t-55.5 65.5t-68 97.5t-53.5 121t-23.5 138q0 220 127 344t351 124q62 0 126.5 -21.5t120 -58t95.5 -68.5t76 -68q36 36 76 68t95.5 68.5t120 58t126.5 21.5q224 0 351 -124t127 -344q0 -221 -229 -450l-623 -600 q-18 -18 -44 -18z" />
+<glyph unicode="&#xf005;" horiz-adv-x="1664" d="M1664 889q0 -22 -26 -48l-363 -354l86 -500q1 -7 1 -20q0 -21 -10.5 -35.5t-30.5 -14.5q-19 0 -40 12l-449 236l-449 -236q-22 -12 -40 -12q-21 0 -31.5 14.5t-10.5 35.5q0 6 2 20l86 500l-364 354q-25 27 -25 48q0 37 56 46l502 73l225 455q19 41 49 41t49 -41l225 -455 l502 -73q56 -9 56 -46z" />
+<glyph unicode="&#xf006;" horiz-adv-x="1664" d="M1137 532l306 297l-422 62l-189 382l-189 -382l-422 -62l306 -297l-73 -421l378 199l377 -199zM1664 889q0 -22 -26 -48l-363 -354l86 -500q1 -7 1 -20q0 -50 -41 -50q-19 0 -40 12l-449 236l-449 -236q-22 -12 -40 -12q-21 0 -31.5 14.5t-10.5 35.5q0 6 2 20l86 500 l-364 354q-25 27 -25 48q0 37 56 46l502 73l225 455q19 41 49 41t49 -41l225 -455l502 -73q56 -9 56 -46z" />
+<glyph unicode="&#xf007;" horiz-adv-x="1408" d="M1408 131q0 -120 -73 -189.5t-194 -69.5h-874q-121 0 -194 69.5t-73 189.5q0 53 3.5 103.5t14 109t26.5 108.5t43 97.5t62 81t85.5 53.5t111.5 20q9 0 42 -21.5t74.5 -48t108 -48t133.5 -21.5t133.5 21.5t108 48t74.5 48t42 21.5q61 0 111.5 -20t85.5 -53.5t62 -81 t43 -97.5t26.5 -108.5t14 -109t3.5 -103.5zM1088 1024q0 -159 -112.5 -271.5t-271.5 -112.5t-271.5 112.5t-112.5 271.5t112.5 271.5t271.5 112.5t271.5 -112.5t112.5 -271.5z" />
+<glyph unicode="&#xf008;" horiz-adv-x="1920" d="M384 -64v128q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h128q26 0 45 19t19 45zM384 320v128q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h128q26 0 45 19t19 45zM384 704v128q0 26 -19 45t-45 19h-128 q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h128q26 0 45 19t19 45zM1408 -64v512q0 26 -19 45t-45 19h-768q-26 0 -45 -19t-19 -45v-512q0 -26 19 -45t45 -19h768q26 0 45 19t19 45zM384 1088v128q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45 t45 -19h128q26 0 45 19t19 45zM1792 -64v128q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h128q26 0 45 19t19 45zM1408 704v512q0 26 -19 45t-45 19h-768q-26 0 -45 -19t-19 -45v-512q0 -26 19 -45t45 -19h768q26 0 45 19t19 45zM1792 320v128 q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h128q26 0 45 19t19 45zM1792 704v128q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h128q26 0 45 19t1
 9 45zM1792 1088v128q0 26 -19 45t-45 19h-128q-26 0 -45 -19 t-19 -45v-128q0 -26 19 -45t45 -19h128q26 0 45 19t19 45zM1920 1248v-1344q0 -66 -47 -113t-113 -47h-1600q-66 0 -113 47t-47 113v1344q0 66 47 113t113 47h1600q66 0 113 -47t47 -113z" />
+<glyph unicode="&#xf009;" horiz-adv-x="1664" d="M768 512v-384q0 -52 -38 -90t-90 -38h-512q-52 0 -90 38t-38 90v384q0 52 38 90t90 38h512q52 0 90 -38t38 -90zM768 1280v-384q0 -52 -38 -90t-90 -38h-512q-52 0 -90 38t-38 90v384q0 52 38 90t90 38h512q52 0 90 -38t38 -90zM1664 512v-384q0 -52 -38 -90t-90 -38 h-512q-52 0 -90 38t-38 90v384q0 52 38 90t90 38h512q52 0 90 -38t38 -90zM1664 1280v-384q0 -52 -38 -90t-90 -38h-512q-52 0 -90 38t-38 90v384q0 52 38 90t90 38h512q52 0 90 -38t38 -90z" />
+<glyph unicode="&#xf00a;" horiz-adv-x="1792" d="M512 288v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM512 800v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM1152 288v-192q0 -40 -28 -68t-68 -28h-320 q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM512 1312v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM1152 800v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28 h320q40 0 68 -28t28 -68zM1792 288v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM1152 1312v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM1792 800v-192 q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM1792 1312v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28
 t28 -68z" />
+<glyph unicode="&#xf00b;" horiz-adv-x="1792" d="M512 288v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM512 800v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM1792 288v-192q0 -40 -28 -68t-68 -28h-960 q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h960q40 0 68 -28t28 -68zM512 1312v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM1792 800v-192q0 -40 -28 -68t-68 -28h-960q-40 0 -68 28t-28 68v192q0 40 28 68t68 28 h960q40 0 68 -28t28 -68zM1792 1312v-192q0 -40 -28 -68t-68 -28h-960q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h960q40 0 68 -28t28 -68z" />
+<glyph unicode="&#xf00c;" horiz-adv-x="1792" d="M1671 970q0 -40 -28 -68l-724 -724l-136 -136q-28 -28 -68 -28t-68 28l-136 136l-362 362q-28 28 -28 68t28 68l136 136q28 28 68 28t68 -28l294 -295l656 657q28 28 68 28t68 -28l136 -136q28 -28 28 -68z" />
+<glyph unicode="&#xf00d;" horiz-adv-x="1408" d="M1298 214q0 -40 -28 -68l-136 -136q-28 -28 -68 -28t-68 28l-294 294l-294 -294q-28 -28 -68 -28t-68 28l-136 136q-28 28 -28 68t28 68l294 294l-294 294q-28 28 -28 68t28 68l136 136q28 28 68 28t68 -28l294 -294l294 294q28 28 68 28t68 -28l136 -136q28 -28 28 -68 t-28 -68l-294 -294l294 -294q28 -28 28 -68z" />
+<glyph unicode="&#xf00e;" horiz-adv-x="1664" d="M1024 736v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-224v-224q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v224h-224q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h224v224q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5v-224h224 q13 0 22.5 -9.5t9.5 -22.5zM1152 704q0 185 -131.5 316.5t-316.5 131.5t-316.5 -131.5t-131.5 -316.5t131.5 -316.5t316.5 -131.5t316.5 131.5t131.5 316.5zM1664 -128q0 -53 -37.5 -90.5t-90.5 -37.5q-54 0 -90 38l-343 342q-179 -124 -399 -124q-143 0 -273.5 55.5 t-225 150t-150 225t-55.5 273.5t55.5 273.5t150 225t225 150t273.5 55.5t273.5 -55.5t225 -150t150 -225t55.5 -273.5q0 -220 -124 -399l343 -343q37 -37 37 -90z" />
+<glyph unicode="&#xf010;" horiz-adv-x="1664" d="M1024 736v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-576q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h576q13 0 22.5 -9.5t9.5 -22.5zM1152 704q0 185 -131.5 316.5t-316.5 131.5t-316.5 -131.5t-131.5 -316.5t131.5 -316.5t316.5 -131.5t316.5 131.5t131.5 316.5z M1664 -128q0 -53 -37.5 -90.5t-90.5 -37.5q-54 0 -90 38l-343 342q-179 -124 -399 -124q-143 0 -273.5 55.5t-225 150t-150 225t-55.5 273.5t55.5 273.5t150 225t225 150t273.5 55.5t273.5 -55.5t225 -150t150 -225t55.5 -273.5q0 -220 -124 -399l343 -343q37 -37 37 -90z " />
+<glyph unicode="&#xf011;" d="M1536 640q0 -156 -61 -298t-164 -245t-245 -164t-298 -61t-298 61t-245 164t-164 245t-61 298q0 182 80.5 343t226.5 270q43 32 95.5 25t83.5 -50q32 -42 24.5 -94.5t-49.5 -84.5q-98 -74 -151.5 -181t-53.5 -228q0 -104 40.5 -198.5t109.5 -163.5t163.5 -109.5 t198.5 -40.5t198.5 40.5t163.5 109.5t109.5 163.5t40.5 198.5q0 121 -53.5 228t-151.5 181q-42 32 -49.5 84.5t24.5 94.5q31 43 84 50t95 -25q146 -109 226.5 -270t80.5 -343zM896 1408v-640q0 -52 -38 -90t-90 -38t-90 38t-38 90v640q0 52 38 90t90 38t90 -38t38 -90z" />
+<glyph unicode="&#xf012;" horiz-adv-x="1792" d="M256 96v-192q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h192q14 0 23 -9t9 -23zM640 224v-320q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v320q0 14 9 23t23 9h192q14 0 23 -9t9 -23zM1024 480v-576q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23 v576q0 14 9 23t23 9h192q14 0 23 -9t9 -23zM1408 864v-960q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v960q0 14 9 23t23 9h192q14 0 23 -9t9 -23zM1792 1376v-1472q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v1472q0 14 9 23t23 9h192q14 0 23 -9t9 -23z" />
+<glyph unicode="&#xf013;" d="M1024 640q0 106 -75 181t-181 75t-181 -75t-75 -181t75 -181t181 -75t181 75t75 181zM1536 749v-222q0 -12 -8 -23t-20 -13l-185 -28q-19 -54 -39 -91q35 -50 107 -138q10 -12 10 -25t-9 -23q-27 -37 -99 -108t-94 -71q-12 0 -26 9l-138 108q-44 -23 -91 -38 q-16 -136 -29 -186q-7 -28 -36 -28h-222q-14 0 -24.5 8.5t-11.5 21.5l-28 184q-49 16 -90 37l-141 -107q-10 -9 -25 -9q-14 0 -25 11q-126 114 -165 168q-7 10 -7 23q0 12 8 23q15 21 51 66.5t54 70.5q-27 50 -41 99l-183 27q-13 2 -21 12.5t-8 23.5v222q0 12 8 23t19 13 l186 28q14 46 39 92q-40 57 -107 138q-10 12 -10 24q0 10 9 23q26 36 98.5 107.5t94.5 71.5q13 0 26 -10l138 -107q44 23 91 38q16 136 29 186q7 28 36 28h222q14 0 24.5 -8.5t11.5 -21.5l28 -184q49 -16 90 -37l142 107q9 9 24 9q13 0 25 -10q129 -119 165 -170q7 -8 7 -22 q0 -12 -8 -23q-15 -21 -51 -66.5t-54 -70.5q26 -50 41 -98l183 -28q13 -2 21 -12.5t8 -23.5z" />
+<glyph unicode="&#xf014;" horiz-adv-x="1408" d="M512 800v-576q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v576q0 14 9 23t23 9h64q14 0 23 -9t9 -23zM768 800v-576q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v576q0 14 9 23t23 9h64q14 0 23 -9t9 -23zM1024 800v-576q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v576 q0 14 9 23t23 9h64q14 0 23 -9t9 -23zM1152 76v948h-896v-948q0 -22 7 -40.5t14.5 -27t10.5 -8.5h832q3 0 10.5 8.5t14.5 27t7 40.5zM480 1152h448l-48 117q-7 9 -17 11h-317q-10 -2 -17 -11zM1408 1120v-64q0 -14 -9 -23t-23 -9h-96v-948q0 -83 -47 -143.5t-113 -60.5h-832 q-66 0 -113 58.5t-47 141.5v952h-96q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h309l70 167q15 37 54 63t79 26h320q40 0 79 -26t54 -63l70 -167h309q14 0 23 -9t9 -23z" />
+<glyph unicode="&#xf015;" horiz-adv-x="1664" d="M1408 544v-480q0 -26 -19 -45t-45 -19h-384v384h-256v-384h-384q-26 0 -45 19t-19 45v480q0 1 0.5 3t0.5 3l575 474l575 -474q1 -2 1 -6zM1631 613l-62 -74q-8 -9 -21 -11h-3q-13 0 -21 7l-692 577l-692 -577q-12 -8 -24 -7q-13 2 -21 11l-62 74q-8 10 -7 23.5t11 21.5 l719 599q32 26 76 26t76 -26l244 -204v195q0 14 9 23t23 9h192q14 0 23 -9t9 -23v-408l219 -182q10 -8 11 -21.5t-7 -23.5z" />
+<glyph unicode="&#xf016;" horiz-adv-x="1280" d="M128 0h1024v768h-416q-40 0 -68 28t-28 68v416h-512v-1280zM768 896h299l-299 299v-299zM1280 768v-800q0 -40 -28 -68t-68 -28h-1088q-40 0 -68 28t-28 68v1344q0 40 28 68t68 28h544q40 0 88 -20t76 -48l408 -408q28 -28 48 -76t20 -88z" />
+<glyph unicode="&#xf017;" d="M1088 608v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-384q-13 0 -22.5 9.5t-9.5 22.5v448q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5v-352h288q13 0 22.5 -9.5t9.5 -22.5zM1280 640q0 104 -40.5 198.5t-109.5 163.5t-163.5 109.5t-198.5 40.5t-198.5 -40.5 t-163.5 -109.5t-109.5 -163.5t-40.5 -198.5t40.5 -198.5t109.5 -163.5t163.5 -109.5t198.5 -40.5t198.5 40.5t163.5 109.5t109.5 163.5t40.5 198.5zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5 t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+<glyph unicode="&#xf018;" horiz-adv-x="1920" d="M1111 540v4l-24 320q-1 13 -11 22.5t-23 9.5h-186q-13 0 -23 -9.5t-11 -22.5l-24 -320v-4q-1 -12 8 -20t21 -8h244q12 0 21 8t8 20zM1870 73q0 -73 -46 -73h-704q13 0 22 9.5t8 22.5l-20 256q-1 13 -11 22.5t-23 9.5h-272q-13 0 -23 -9.5t-11 -22.5l-20 -256 q-1 -13 8 -22.5t22 -9.5h-704q-46 0 -46 73q0 54 26 116l417 1044q8 19 26 33t38 14h339q-13 0 -23 -9.5t-11 -22.5l-15 -192q-1 -14 8 -23t22 -9h166q13 0 22 9t8 23l-15 192q-1 13 -11 22.5t-23 9.5h339q20 0 38 -14t26 -33l417 -1044q26 -62 26 -116z" />
+<glyph unicode="&#xf019;" horiz-adv-x="1664" d="M1339 729q17 -41 -14 -70l-448 -448q-18 -19 -45 -19t-45 19l-448 448q-31 29 -14 70q17 39 59 39h256v448q0 26 19 45t45 19h256q26 0 45 -19t19 -45v-448h256q42 0 59 -39zM1632 512q14 0 23 -9t9 -23v-576q0 -14 -9 -23t-23 -9h-1600q-14 0 -23 9t-9 23v576q0 14 9 23 t23 9h192q14 0 23 -9t9 -23v-352h1152v352q0 14 9 23t23 9h192z" />
+<glyph unicode="&#xf01a;" d="M1120 608q0 -12 -10 -24l-319 -319q-9 -9 -23 -9t-23 9l-320 320q-9 9 -9 23q0 13 9.5 22.5t22.5 9.5h192v352q0 13 9.5 22.5t22.5 9.5h192q13 0 22.5 -9.5t9.5 -22.5v-352h192q14 0 23 -9t9 -23zM1280 640q0 104 -40.5 198.5t-109.5 163.5t-163.5 109.5t-198.5 40.5 t-198.5 -40.5t-163.5 -109.5t-109.5 -163.5t-40.5 -198.5t40.5 -198.5t109.5 -163.5t163.5 -109.5t198.5 -40.5t198.5 40.5t163.5 109.5t109.5 163.5t40.5 198.5zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5 t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+<glyph unicode="&#xf01b;" d="M1120 672q0 -13 -9.5 -22.5t-22.5 -9.5h-192v-352q0 -13 -9.5 -22.5t-22.5 -9.5h-192q-13 0 -22.5 9.5t-9.5 22.5v352h-192q-14 0 -23 9t-9 23q0 12 10 24l319 319q9 9 23 9t23 -9l320 -320q9 -9 9 -23zM1280 640q0 104 -40.5 198.5t-109.5 163.5t-163.5 109.5 t-198.5 40.5t-198.5 -40.5t-163.5 -109.5t-109.5 -163.5t-40.5 -198.5t40.5 -198.5t109.5 -163.5t163.5 -109.5t198.5 -40.5t198.5 40.5t163.5 109.5t109.5 163.5t40.5 198.5zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5 t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+<glyph unicode="&#xf01c;" d="M1023 576h316q-1 3 -2.5 8t-2.5 8l-212 496h-708l-212 -496q-1 -2 -2.5 -8t-2.5 -8h316l95 -192h320zM1536 546v-482q0 -26 -19 -45t-45 -19h-1408q-26 0 -45 19t-19 45v482q0 62 25 123l238 552q10 25 36.5 42t52.5 17h832q26 0 52.5 -17t36.5 -42l238 -552 q25 -61 25 -123z" />
+<glyph unicode="&#xf01d;" d="M1152 640q0 -37 -33 -56l-512 -288q-14 -8 -31 -8t-32 9q-32 18 -32 55v576q0 37 32 55q31 20 63 1l512 -288q33 -19 33 -56zM1280 640q0 104 -40.5 198.5t-109.5 163.5t-163.5 109.5t-198.5 40.5t-198.5 -40.5t-163.5 -109.5t-109.5 -163.5t-40.5 -198.5t40.5 -198.5 t109.5 -163.5t163.5 -109.5t198.5 -40.5t198.5 40.5t163.5 109.5t109.5 163.5t40.5 198.5zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+<glyph unicode="&#xf01e;" d="M1536 1280v-448q0 -26 -19 -45t-45 -19h-448q-42 0 -59 40q-17 39 14 69l138 138q-148 137 -349 137q-104 0 -198.5 -40.5t-163.5 -109.5t-109.5 -163.5t-40.5 -198.5t40.5 -198.5t109.5 -163.5t163.5 -109.5t198.5 -40.5q169 0 304 99.5t185 261.5q7 23 30 23h199 q16 0 25 -12q10 -13 7 -27q-39 -175 -147.5 -312t-266 -213t-336.5 -76q-156 0 -298 61t-245 164t-164 245t-61 298t61 298t164 245t245 164t298 61q147 0 284.5 -55.5t244.5 -156.5l130 129q29 31 70 14q39 -17 39 -59z" />
+<glyph unicode="&#xf021;" d="M1511 480q0 -5 -1 -7q-64 -268 -268 -434.5t-478 -166.5q-146 0 -282.5 55t-243.5 157l-129 -129q-19 -19 -45 -19t-45 19t-19 45v448q0 26 19 45t45 19h448q26 0 45 -19t19 -45t-19 -45l-137 -137q71 -66 161 -102t187 -36q134 0 250 65t186 179q11 17 53 117 q8 23 30 23h192q13 0 22.5 -9.5t9.5 -22.5zM1536 1280v-448q0 -26 -19 -45t-45 -19h-448q-26 0 -45 19t-19 45t19 45l138 138q-148 137 -349 137q-134 0 -250 -65t-186 -179q-11 -17 -53 -117q-8 -23 -30 -23h-199q-13 0 -22.5 9.5t-9.5 22.5v7q65 268 270 434.5t480 166.5 q146 0 284 -55.5t245 -156.5l130 129q19 19 45 19t45 -19t19 -45z" />
+<glyph unicode="&#xf022;" horiz-adv-x="1792" d="M384 352v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM384 608v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M384 864v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM1536 352v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-960q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h960q13 0 22.5 -9.5t9.5 -22.5z M1536 608v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-960q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h960q13 0 22.5 -9.5t9.5 -22.5zM1536 864v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-960q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h960q13 0 22.5 -9.5 t9.5 -22.5zM1664 160v832q0 13 -9.5 22.5t-22.5 9.5h-1472q-13 0 -22.5 -9.5t-9.5 -22.5v-832q0 -13 9.5 -22.5t22.5 -9.5h1472q13 0 22.5 9.5t9.5 22.5zM1792 1248v-1088q0 -66 -47 -113t-113 -47h-1472q-66 0 -1
 13 47t-47 113v1088q0 66 47 113t113 47h1472q66 0 113 -47 t47 -113z" />
+<glyph unicode="&#xf023;" horiz-adv-x="1152" d="M704 512q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5q0 -37 19 -67t51 -47l-69 -229q-5 -15 5 -28t26 -13h192q16 0 26 13t5 28l-69 229q32 17 51 47t19 67zM320 768h512v192q0 106 -75 181t-181 75t-181 -75t-75 -181v-192zM1152 672v-576q0 -40 -28 -68 t-68 -28h-960q-40 0 -68 28t-28 68v576q0 40 28 68t68 28h32v192q0 184 132 316t316 132t316 -132t132 -316v-192h32q40 0 68 -28t28 -68z" />
+<glyph unicode="&#xf024;" horiz-adv-x="1792" d="M320 1280q0 -72 -64 -110v-1266q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v1266q-64 38 -64 110q0 53 37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1792 1216v-763q0 -25 -12.5 -38.5t-39.5 -27.5q-215 -116 -369 -116q-61 0 -123.5 22t-108.5 48 t-115.5 48t-142.5 22q-192 0 -464 -146q-17 -9 -33 -9q-26 0 -45 19t-19 45v742q0 32 31 55q21 14 79 43q236 120 421 120q107 0 200 -29t219 -88q38 -19 88 -19q54 0 117.5 21t110 47t88 47t54.5 21q26 0 45 -19t19 -45z" />
+<glyph unicode="&#xf025;" horiz-adv-x="1664" d="M1664 650q0 -166 -60 -314l-20 -49l-185 -33q-22 -83 -90.5 -136.5t-156.5 -53.5v-32q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v576q0 14 9 23t23 9h64q14 0 23 -9t9 -23v-32q71 0 130 -35.5t93 -95.5l68 12q29 95 29 193q0 148 -88 279t-236.5 209t-315.5 78 t-315.5 -78t-236.5 -209t-88 -279q0 -98 29 -193l68 -12q34 60 93 95.5t130 35.5v32q0 14 9 23t23 9h64q14 0 23 -9t9 -23v-576q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v32q-88 0 -156.5 53.5t-90.5 136.5l-185 33l-20 49q-60 148 -60 314q0 151 67 291t179 242.5 t266 163.5t320 61t320 -61t266 -163.5t179 -242.5t67 -291z" />
+<glyph unicode="&#xf026;" horiz-adv-x="768" d="M768 1184v-1088q0 -26 -19 -45t-45 -19t-45 19l-333 333h-262q-26 0 -45 19t-19 45v384q0 26 19 45t45 19h262l333 333q19 19 45 19t45 -19t19 -45z" />
+<glyph unicode="&#xf027;" horiz-adv-x="1152" d="M768 1184v-1088q0 -26 -19 -45t-45 -19t-45 19l-333 333h-262q-26 0 -45 19t-19 45v384q0 26 19 45t45 19h262l333 333q19 19 45 19t45 -19t19 -45zM1152 640q0 -76 -42.5 -141.5t-112.5 -93.5q-10 -5 -25 -5q-26 0 -45 18.5t-19 45.5q0 21 12 35.5t29 25t34 23t29 35.5 t12 57t-12 57t-29 35.5t-34 23t-29 25t-12 35.5q0 27 19 45.5t45 18.5q15 0 25 -5q70 -27 112.5 -93t42.5 -142z" />
+<glyph unicode="&#xf028;" horiz-adv-x="1664" d="M768 1184v-1088q0 -26 -19 -45t-45 -19t-45 19l-333 333h-262q-26 0 -45 19t-19 45v384q0 26 19 45t45 19h262l333 333q19 19 45 19t45 -19t19 -45zM1152 640q0 -76 -42.5 -141.5t-112.5 -93.5q-10 -5 -25 -5q-26 0 -45 18.5t-19 45.5q0 21 12 35.5t29 25t34 23t29 35.5 t12 57t-12 57t-29 35.5t-34 23t-29 25t-12 35.5q0 27 19 45.5t45 18.5q15 0 25 -5q70 -27 112.5 -93t42.5 -142zM1408 640q0 -153 -85 -282.5t-225 -188.5q-13 -5 -25 -5q-27 0 -46 19t-19 45q0 39 39 59q56 29 76 44q74 54 115.5 135.5t41.5 173.5t-41.5 173.5 t-115.5 135.5q-20 15 -76 44q-39 20 -39 59q0 26 19 45t45 19q13 0 26 -5q140 -59 225 -188.5t85 -282.5zM1664 640q0 -230 -127 -422.5t-338 -283.5q-13 -5 -26 -5q-26 0 -45 19t-19 45q0 36 39 59q7 4 22.5 10.5t22.5 10.5q46 25 82 51q123 91 192 227t69 289t-69 289 t-192 227q-36 26 -82 51q-7 4 -22.5 10.5t-22.5 10.5q-39 23 -39 59q0 26 19 45t45 19q13 0 26 -5q211 -91 338 -283.5t127 -422.5z" />
+<glyph unicode="&#xf029;" horiz-adv-x="1408" d="M384 384v-128h-128v128h128zM384 1152v-128h-128v128h128zM1152 1152v-128h-128v128h128zM128 129h384v383h-384v-383zM128 896h384v384h-384v-384zM896 896h384v384h-384v-384zM640 640v-640h-640v640h640zM1152 128v-128h-128v128h128zM1408 128v-128h-128v128h128z M1408 640v-384h-384v128h-128v-384h-128v640h384v-128h128v128h128zM640 1408v-640h-640v640h640zM1408 1408v-640h-640v640h640z" />
+<glyph unicode="&#xf02a;" horiz-adv-x="1792" d="M672 1408v-1536h-64v1536h64zM1408 1408v-1536h-64v1536h64zM1568 1408v-1536h-64v1536h64zM576 1408v-1536h-64v1536h64zM1280 1408v-1536h-256v1536h256zM896 1408v-1536h-128v1536h128zM448 1408v-1536h-128v1536h128zM1792 1408v-1536h-128v1536h128zM256 1408v-1536 h-256v1536h256z" />
+<glyph unicode="&#xf02b;" d="M448 1088q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1515 512q0 -53 -37 -90l-491 -492q-39 -37 -91 -37q-53 0 -90 37l-715 716q-38 37 -64.5 101t-26.5 117v416q0 52 38 90t90 38h416q53 0 117 -26.5t102 -64.5 l715 -714q37 -39 37 -91z" />
+<glyph unicode="&#xf02c;" horiz-adv-x="1920" d="M448 1088q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1515 512q0 -53 -37 -90l-491 -492q-39 -37 -91 -37q-53 0 -90 37l-715 716q-38 37 -64.5 101t-26.5 117v416q0 52 38 90t90 38h416q53 0 117 -26.5t102 -64.5 l715 -714q37 -39 37 -91zM1899 512q0 -53 -37 -90l-491 -492q-39 -37 -91 -37q-36 0 -59 14t-53 45l470 470q37 37 37 90q0 52 -37 91l-715 714q-38 38 -102 64.5t-117 26.5h224q53 0 117 -26.5t102 -64.5l715 -714q37 -39 37 -91z" />
+<glyph unicode="&#xf02d;" horiz-adv-x="1664" d="M1639 1058q40 -57 18 -129l-275 -906q-19 -64 -76.5 -107.5t-122.5 -43.5h-923q-77 0 -148.5 53.5t-99.5 131.5q-24 67 -2 127q0 4 3 27t4 37q1 8 -3 21.5t-3 19.5q2 11 8 21t16.5 23.5t16.5 23.5q23 38 45 91.5t30 91.5q3 10 0.5 30t-0.5 28q3 11 17 28t17 23 q21 36 42 92t25 90q1 9 -2.5 32t0.5 28q4 13 22 30.5t22 22.5q19 26 42.5 84.5t27.5 96.5q1 8 -3 25.5t-2 26.5q2 8 9 18t18 23t17 21q8 12 16.5 30.5t15 35t16 36t19.5 32t26.5 23.5t36 11.5t47.5 -5.5l-1 -3q38 9 51 9h761q74 0 114 -56t18 -130l-274 -906 q-36 -119 -71.5 -153.5t-128.5 -34.5h-869q-27 0 -38 -15q-11 -16 -1 -43q24 -70 144 -70h923q29 0 56 15.5t35 41.5l300 987q7 22 5 57q38 -15 59 -43zM575 1056q-4 -13 2 -22.5t20 -9.5h608q13 0 25.5 9.5t16.5 22.5l21 64q4 13 -2 22.5t-20 9.5h-608q-13 0 -25.5 -9.5 t-16.5 -22.5zM492 800q-4 -13 2 -22.5t20 -9.5h608q13 0 25.5 9.5t16.5 22.5l21 64q4 13 -2 22.5t-20 9.5h-608q-13 0 -25.5 -9.5t-16.5 -22.5z" />
+<glyph unicode="&#xf02e;" horiz-adv-x="1280" d="M1164 1408q23 0 44 -9q33 -13 52.5 -41t19.5 -62v-1289q0 -34 -19.5 -62t-52.5 -41q-19 -8 -44 -8q-48 0 -83 32l-441 424l-441 -424q-36 -33 -83 -33q-23 0 -44 9q-33 13 -52.5 41t-19.5 62v1289q0 34 19.5 62t52.5 41q21 9 44 9h1048z" />
+<glyph unicode="&#xf02f;" horiz-adv-x="1664" d="M384 0h896v256h-896v-256zM384 640h896v384h-160q-40 0 -68 28t-28 68v160h-640v-640zM1536 576q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1664 576v-416q0 -13 -9.5 -22.5t-22.5 -9.5h-224v-160q0 -40 -28 -68t-68 -28h-960q-40 0 -68 28t-28 68 v160h-224q-13 0 -22.5 9.5t-9.5 22.5v416q0 79 56.5 135.5t135.5 56.5h64v544q0 40 28 68t68 28h672q40 0 88 -20t76 -48l152 -152q28 -28 48 -76t20 -88v-256h64q79 0 135.5 -56.5t56.5 -135.5z" />
+<glyph unicode="&#xf030;" horiz-adv-x="1920" d="M960 864q119 0 203.5 -84.5t84.5 -203.5t-84.5 -203.5t-203.5 -84.5t-203.5 84.5t-84.5 203.5t84.5 203.5t203.5 84.5zM1664 1280q106 0 181 -75t75 -181v-896q0 -106 -75 -181t-181 -75h-1408q-106 0 -181 75t-75 181v896q0 106 75 181t181 75h224l51 136 q19 49 69.5 84.5t103.5 35.5h512q53 0 103.5 -35.5t69.5 -84.5l51 -136h224zM960 128q185 0 316.5 131.5t131.5 316.5t-131.5 316.5t-316.5 131.5t-316.5 -131.5t-131.5 -316.5t131.5 -316.5t316.5 -131.5z" />
+<glyph unicode="&#xf031;" horiz-adv-x="1664" d="M725 977l-170 -450q73 -1 153.5 -2t119 -1.5t52.5 -0.5l29 2q-32 95 -92 241q-53 132 -92 211zM21 -128h-21l2 79q22 7 80 18q89 16 110 31q20 16 48 68l237 616l280 724h75h53l11 -21l205 -480q103 -242 124 -297q39 -102 96 -235q26 -58 65 -164q24 -67 65 -149 q22 -49 35 -57q22 -19 69 -23q47 -6 103 -27q6 -39 6 -57q0 -14 -1 -26q-80 0 -192 8q-93 8 -189 8q-79 0 -135 -2l-200 -11l-58 -2q0 45 4 78l131 28q56 13 68 23q12 12 12 27t-6 32l-47 114l-92 228l-450 2q-29 -65 -104 -274q-23 -64 -23 -84q0 -31 17 -43 q26 -21 103 -32q3 0 13.5 -2t30 -5t40.5 -6q1 -28 1 -58q0 -17 -2 -27q-66 0 -349 20l-48 -8q-81 -14 -167 -14z" />
+<glyph unicode="&#xf032;" horiz-adv-x="1408" d="M555 15q76 -32 140 -32q131 0 216 41t122 113q38 70 38 181q0 114 -41 180q-58 94 -141 126q-80 32 -247 32q-74 0 -101 -10v-144l-1 -173l3 -270q0 -15 12 -44zM541 761q43 -7 109 -7q175 0 264 65t89 224q0 112 -85 187q-84 75 -255 75q-52 0 -130 -13q0 -44 2 -77 q7 -122 6 -279l-1 -98q0 -43 1 -77zM0 -128l2 94q45 9 68 12q77 12 123 31q17 27 21 51q9 66 9 194l-2 497q-5 256 -9 404q-1 87 -11 109q-1 4 -12 12q-18 12 -69 15q-30 2 -114 13l-4 83l260 6l380 13l45 1q5 0 14 0.5t14 0.5q1 0 21.5 -0.5t40.5 -0.5h74q88 0 191 -27 q43 -13 96 -39q57 -29 102 -76q44 -47 65 -104t21 -122q0 -70 -32 -128t-95 -105q-26 -20 -150 -77q177 -41 267 -146q92 -106 92 -236q0 -76 -29 -161q-21 -62 -71 -117q-66 -72 -140 -108q-73 -36 -203 -60q-82 -15 -198 -11l-197 4q-84 2 -298 -11q-33 -3 -272 -11z" />
+<glyph unicode="&#xf033;" horiz-adv-x="1024" d="M0 -126l17 85q4 1 77 20q76 19 116 39q29 37 41 101l27 139l56 268l12 64q8 44 17 84.5t16 67t12.5 46.5t9 30.5t3.5 11.5l29 157l16 63l22 135l8 50v38q-41 22 -144 28q-28 2 -38 4l19 103l317 -14q39 -2 73 -2q66 0 214 9q33 2 68 4.5t36 2.5q-2 -19 -6 -38 q-7 -29 -13 -51q-55 -19 -109 -31q-64 -16 -101 -31q-12 -31 -24 -88q-9 -44 -13 -82q-44 -199 -66 -306l-61 -311l-38 -158l-43 -235l-12 -45q-2 -7 1 -27q64 -15 119 -21q36 -5 66 -10q-1 -29 -7 -58q-7 -31 -9 -41q-18 0 -23 -1q-24 -2 -42 -2q-9 0 -28 3q-19 4 -145 17 l-198 2q-41 1 -174 -11q-74 -7 -98 -9z" />
+<glyph unicode="&#xf034;" horiz-adv-x="1792" d="M81 1407l54 -27q20 -5 211 -5h130l19 3l115 1l215 -1h293l34 -2q14 -1 28 7t21 16l7 8l42 1q15 0 28 -1v-104.5t1 -131.5l1 -100l-1 -58q0 -32 -4 -51q-39 -15 -68 -18q-25 43 -54 128q-8 24 -15.5 62.5t-11.5 65.5t-6 29q-13 15 -27 19q-7 2 -42.5 2t-103.5 -1t-111 -1 q-34 0 -67 -5q-10 -97 -8 -136l1 -152v-332l3 -359l-1 -147q-1 -46 11 -85q49 -25 89 -32q2 0 18 -5t44 -13t43 -12q30 -8 50 -18q5 -45 5 -50q0 -10 -3 -29q-14 -1 -34 -1q-110 0 -187 10q-72 8 -238 8q-88 0 -233 -14q-48 -4 -70 -4q-2 22 -2 26l-1 26v9q21 33 79 49 q139 38 159 50q9 21 12 56q8 192 6 433l-5 428q-1 62 -0.5 118.5t0.5 102.5t-2 57t-6 15q-6 5 -14 6q-38 6 -148 6q-43 0 -100 -13.5t-73 -24.5q-13 -9 -22 -33t-22 -75t-24 -84q-6 -19 -19.5 -32t-20.5 -13q-44 27 -56 44v297v86zM1744 128q33 0 42 -18.5t-11 -44.5 l-126 -162q-20 -26 -49 -26t-49 26l-126 162q-20 26 -11 44.5t42 18.5h80v1024h-80q-33 0 -42 18.5t11 44.5l126 162q20 26 49 26t49 -26l126 -162q20 -26 11 -44.5t-42 -18.5h-80v-1024h80z" />
+<glyph unicode="&#xf035;" d="M81 1407l54 -27q20 -5 211 -5h130l19 3l115 1l446 -1h318l34 -2q14 -1 28 7t21 16l7 8l42 1q15 0 28 -1v-104.5t1 -131.5l1 -100l-1 -58q0 -32 -4 -51q-39 -15 -68 -18q-25 43 -54 128q-8 24 -15.5 62.5t-11.5 65.5t-6 29q-13 15 -27 19q-7 2 -58.5 2t-138.5 -1t-128 -1 q-94 0 -127 -5q-10 -97 -8 -136l1 -152v52l3 -359l-1 -147q-1 -46 11 -85q49 -25 89 -32q2 0 18 -5t44 -13t43 -12q30 -8 50 -18q5 -45 5 -50q0 -10 -3 -29q-14 -1 -34 -1q-110 0 -187 10q-72 8 -238 8q-82 0 -233 -13q-45 -5 -70 -5q-2 22 -2 26l-1 26v9q21 33 79 49 q139 38 159 50q9 21 12 56q6 137 6 433l-5 44q0 265 -2 278q-2 11 -6 15q-6 5 -14 6q-38 6 -148 6q-50 0 -168.5 -14t-132.5 -24q-13 -9 -22 -33t-22 -75t-24 -84q-6 -19 -19.5 -32t-20.5 -13q-44 27 -56 44v297v86zM1505 113q26 -20 26 -49t-26 -49l-162 -126 q-26 -20 -44.5 -11t-18.5 42v80h-1024v-80q0 -33 -18.5 -42t-44.5 11l-162 126q-26 20 -26 49t26 49l162 126q26 20 44.5 11t18.5 -42v-80h1024v80q0 33 18.5 42t44.5 -11z" />
+<glyph unicode="&#xf036;" horiz-adv-x="1792" d="M1792 192v-128q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1664q26 0 45 -19t19 -45zM1408 576v-128q0 -26 -19 -45t-45 -19h-1280q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1280q26 0 45 -19t19 -45zM1664 960v-128q0 -26 -19 -45 t-45 -19h-1536q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1536q26 0 45 -19t19 -45zM1280 1344v-128q0 -26 -19 -45t-45 -19h-1152q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1152q26 0 45 -19t19 -45z" />
+<glyph unicode="&#xf037;" horiz-adv-x="1792" d="M1792 192v-128q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1664q26 0 45 -19t19 -45zM1408 576v-128q0 -26 -19 -45t-45 -19h-896q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h896q26 0 45 -19t19 -45zM1664 960v-128q0 -26 -19 -45t-45 -19 h-1408q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1408q26 0 45 -19t19 -45zM1280 1344v-128q0 -26 -19 -45t-45 -19h-640q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h640q26 0 45 -19t19 -45z" />
+<glyph unicode="&#xf038;" horiz-adv-x="1792" d="M1792 192v-128q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1664q26 0 45 -19t19 -45zM1792 576v-128q0 -26 -19 -45t-45 -19h-1280q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1280q26 0 45 -19t19 -45zM1792 960v-128q0 -26 -19 -45 t-45 -19h-1536q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1536q26 0 45 -19t19 -45zM1792 1344v-128q0 -26 -19 -45t-45 -19h-1152q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1152q26 0 45 -19t19 -45z" />
+<glyph unicode="&#xf039;" horiz-adv-x="1792" d="M1792 192v-128q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1664q26 0 45 -19t19 -45zM1792 576v-128q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1664q26 0 45 -19t19 -45zM1792 960v-128q0 -26 -19 -45 t-45 -19h-1664q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1664q26 0 45 -19t19 -45zM1792 1344v-128q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1664q26 0 45 -19t19 -45z" />
+<glyph unicode="&#xf03a;" horiz-adv-x="1792" d="M256 224v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-192q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h192q13 0 22.5 -9.5t9.5 -22.5zM256 608v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-192q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h192q13 0 22.5 -9.5 t9.5 -22.5zM256 992v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-192q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h192q13 0 22.5 -9.5t9.5 -22.5zM1792 224v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1344q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1344 q13 0 22.5 -9.5t9.5 -22.5zM256 1376v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-192q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h192q13 0 22.5 -9.5t9.5 -22.5zM1792 608v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1344q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5 t22.5 9.5h1344q13 0 22.5 -9.5t9.5 -22.5zM1792 992v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1344q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1344q13 0 22.5 -9.5t9.5 -22.5zM1792 1376v-192q0 -13 -9.5 -22.5t
 -22.5 -9.5h-1344q-13 0 -22.5 9.5t-9.5 22.5v192 q0 13 9.5 22.5t22.5 9.5h1344q13 0 22.5 -9.5t9.5 -22.5z" />
+<glyph unicode="&#xf03b;" horiz-adv-x="1792" d="M384 992v-576q0 -13 -9.5 -22.5t-22.5 -9.5q-14 0 -23 9l-288 288q-9 9 -9 23t9 23l288 288q9 9 23 9q13 0 22.5 -9.5t9.5 -22.5zM1792 224v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1728q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1728q13 0 22.5 -9.5 t9.5 -22.5zM1792 608v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1088q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1088q13 0 22.5 -9.5t9.5 -22.5zM1792 992v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1088q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1088 q13 0 22.5 -9.5t9.5 -22.5zM1792 1376v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1728q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1728q13 0 22.5 -9.5t9.5 -22.5z" />
+<glyph unicode="&#xf03c;" horiz-adv-x="1792" d="M352 704q0 -14 -9 -23l-288 -288q-9 -9 -23 -9q-13 0 -22.5 9.5t-9.5 22.5v576q0 13 9.5 22.5t22.5 9.5q14 0 23 -9l288 -288q9 -9 9 -23zM1792 224v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1728q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1728q13 0 22.5 -9.5 t9.5 -22.5zM1792 608v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1088q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1088q13 0 22.5 -9.5t9.5 -22.5zM1792 992v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1088q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1088 q13 0 22.5 -9.5t9.5 -22.5zM1792 1376v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1728q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1728q13 0 22.5 -9.5t9.5 -22.5z" />
+<glyph unicode="&#xf03d;" horiz-adv-x="1920" d="M1900 1278q20 -8 20 -30v-1216q0 -22 -20 -30q-8 -2 -12 -2q-12 0 -23 9l-585 586v-307q0 -119 -84.5 -203.5t-203.5 -84.5h-704q-119 0 -203.5 84.5t-84.5 203.5v704q0 119 84.5 203.5t203.5 84.5h704q119 0 203.5 -84.5t84.5 -203.5v-307l585 586q16 15 35 7z" />
+<glyph unicode="&#xf03e;" horiz-adv-x="1920" d="M640 960q0 -80 -56 -136t-136 -56t-136 56t-56 136t56 136t136 56t136 -56t56 -136zM1664 576v-448h-1408v192l320 320l160 -160l512 512zM1760 1280h-1600q-13 0 -22.5 -9.5t-9.5 -22.5v-1216q0 -13 9.5 -22.5t22.5 -9.5h1600q13 0 22.5 9.5t9.5 22.5v1216 q0 13 -9.5 22.5t-22.5 9.5zM1920 1248v-1216q0 -66 -47 -113t-113 -47h-1600q-66 0 -113 47t-47 113v1216q0 66 47 113t113 47h1600q66 0 113 -47t47 -113z" />
+<glyph unicode="&#xf040;" d="M363 0l91 91l-235 235l-91 -91v-107h128v-128h107zM886 928q0 22 -22 22q-10 0 -17 -7l-542 -542q-7 -7 -7 -17q0 -22 22 -22q10 0 17 7l542 542q7 7 7 17zM832 1120l416 -416l-832 -832h-416v416zM1515 1024q0 -53 -37 -90l-166 -166l-416 416l166 165q36 38 90 38 q53 0 91 -38l235 -234q37 -39 37 -91z" />
+<glyph unicode="&#xf041;" horiz-adv-x="1024" d="M768 896q0 106 -75 181t-181 75t-181 -75t-75 -181t75 -181t181 -75t181 75t75 181zM1024 896q0 -109 -33 -179l-364 -774q-16 -33 -47.5 -52t-67.5 -19t-67.5 19t-46.5 52l-365 774q-33 70 -33 179q0 212 150 362t362 150t362 -150t150 -362z" />
+<glyph unicode="&#xf042;" d="M768 1408q209 0 385.5 -103t279.5 -279.5t103 -385.5t-103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103zM256 640q0 -104 40.5 -198.5t109.5 -163.5t163.5 -109.5t198.5 -40.5v1024q-104 0 -198.5 -40.5 t-163.5 -109.5t-109.5 -163.5t-40.5 -198.5z" />
+<glyph unicode="&#xf043;" horiz-adv-x="1024" d="M512 384q0 36 -20 69q-1 1 -15.5 22.5t-25.5 38t-25 44t-21 50.5q-4 16 -21 16t-21 -16q-7 -23 -21 -50.5t-25 -44t-25.5 -38t-15.5 -22.5q-20 -33 -20 -69q0 -53 37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1024 512q0 -212 -150 -362t-362 -150t-362 150t-150 362 q0 145 81 275q6 9 62.5 90.5t101 151t99.5 178t83 201.5q9 30 34 47t51 17t51.5 -17t33.5 -47q28 -93 83 -201.5t99.5 -178t101 -151t62.5 -90.5q81 -127 81 -275z" />
+<glyph unicode="&#xf044;" horiz-adv-x="1792" d="M888 352l116 116l-152 152l-116 -116v-56h96v-96h56zM1328 1072q-16 16 -33 -1l-350 -350q-17 -17 -1 -33t33 1l350 350q17 17 1 33zM1408 478v-190q0 -119 -84.5 -203.5t-203.5 -84.5h-832q-119 0 -203.5 84.5t-84.5 203.5v832q0 119 84.5 203.5t203.5 84.5h832 q63 0 117 -25q15 -7 18 -23q3 -17 -9 -29l-49 -49q-14 -14 -32 -8q-23 6 -45 6h-832q-66 0 -113 -47t-47 -113v-832q0 -66 47 -113t113 -47h832q66 0 113 47t47 113v126q0 13 9 22l64 64q15 15 35 7t20 -29zM1312 1216l288 -288l-672 -672h-288v288zM1756 1084l-92 -92 l-288 288l92 92q28 28 68 28t68 -28l152 -152q28 -28 28 -68t-28 -68z" />
+<glyph unicode="&#xf045;" horiz-adv-x="1664" d="M1408 547v-259q0 -119 -84.5 -203.5t-203.5 -84.5h-832q-119 0 -203.5 84.5t-84.5 203.5v832q0 119 84.5 203.5t203.5 84.5h255v0q13 0 22.5 -9.5t9.5 -22.5q0 -27 -26 -32q-77 -26 -133 -60q-10 -4 -16 -4h-112q-66 0 -113 -47t-47 -113v-832q0 -66 47 -113t113 -47h832 q66 0 113 47t47 113v214q0 19 18 29q28 13 54 37q16 16 35 8q21 -9 21 -29zM1645 1043l-384 -384q-18 -19 -45 -19q-12 0 -25 5q-39 17 -39 59v192h-160q-323 0 -438 -131q-119 -137 -74 -473q3 -23 -20 -34q-8 -2 -12 -2q-16 0 -26 13q-10 14 -21 31t-39.5 68.5t-49.5 99.5 t-38.5 114t-17.5 122q0 49 3.5 91t14 90t28 88t47 81.5t68.5 74t94.5 61.5t124.5 48.5t159.5 30.5t196.5 11h160v192q0 42 39 59q13 5 25 5q26 0 45 -19l384 -384q19 -19 19 -45t-19 -45z" />
+<glyph unicode="&#xf046;" horiz-adv-x="1664" d="M1408 606v-318q0 -119 -84.5 -203.5t-203.5 -84.5h-832q-119 0 -203.5 84.5t-84.5 203.5v832q0 119 84.5 203.5t203.5 84.5h832q63 0 117 -25q15 -7 18 -23q3 -17 -9 -29l-49 -49q-10 -10 -23 -10q-3 0 -9 2q-23 6 -45 6h-832q-66 0 -113 -47t-47 -113v-832 q0 -66 47 -113t113 -47h832q66 0 113 47t47 113v254q0 13 9 22l64 64q10 10 23 10q6 0 12 -3q20 -8 20 -29zM1639 1095l-814 -814q-24 -24 -57 -24t-57 24l-430 430q-24 24 -24 57t24 57l110 110q24 24 57 24t57 -24l263 -263l647 647q24 24 57 24t57 -24l110 -110 q24 -24 24 -57t-24 -57z" />
+<glyph unicode="&#xf047;" horiz-adv-x="1792" d="M1792 640q0 -26 -19 -45l-256 -256q-19 -19 -45 -19t-45 19t-19 45v128h-384v-384h128q26 0 45 -19t19 -45t-19 -45l-256 -256q-19 -19 -45 -19t-45 19l-256 256q-19 19 -19 45t19 45t45 19h128v384h-384v-128q0 -26 -19 -45t-45 -19t-45 19l-256 256q-19 19 -19 45 t19 45l256 256q19 19 45 19t45 -19t19 -45v-128h384v384h-128q-26 0 -45 19t-19 45t19 45l256 256q19 19 45 19t45 -19l256 -256q19 -19 19 -45t-19 -45t-45 -19h-128v-384h384v128q0 26 19 45t45 19t45 -19l256 -256q19 -19 19 -45z" />
+<glyph unicode="&#xf048;" horiz-adv-x="1024" d="M979 1395q19 19 32 13t13 -32v-1472q0 -26 -13 -32t-32 13l-710 710q-9 9 -13 19v-678q0 -26 -19 -45t-45 -19h-128q-26 0 -45 19t-19 45v1408q0 26 19 45t45 19h128q26 0 45 -19t19 -45v-678q4 11 13 19z" />
+<glyph unicode="&#xf049;" horiz-adv-x="1792" d="M1747 1395q19 19 32 13t13 -32v-1472q0 -26 -13 -32t-32 13l-710 710q-9 9 -13 19v-710q0 -26 -13 -32t-32 13l-710 710q-9 9 -13 19v-678q0 -26 -19 -45t-45 -19h-128q-26 0 -45 19t-19 45v1408q0 26 19 45t45 19h128q26 0 45 -19t19 -45v-678q4 11 13 19l710 710 q19 19 32 13t13 -32v-710q4 11 13 19z" />
+<glyph unicode="&#xf04a;" horiz-adv-x="1664" d="M1619 1395q19 19 32 13t13 -32v-1472q0 -26 -13 -32t-32 13l-710 710q-8 9 -13 19v-710q0 -26 -13 -32t-32 13l-710 710q-19 19 -19 45t19 45l710 710q19 19 32 13t13 -32v-710q5 11 13 19z" />
+<glyph unicode="&#xf04b;" horiz-adv-x="1408" d="M1384 609l-1328 -738q-23 -13 -39.5 -3t-16.5 36v1472q0 26 16.5 36t39.5 -3l1328 -738q23 -13 23 -31t-23 -31z" />
+<glyph unicode="&#xf04c;" d="M1536 1344v-1408q0 -26 -19 -45t-45 -19h-512q-26 0 -45 19t-19 45v1408q0 26 19 45t45 19h512q26 0 45 -19t19 -45zM640 1344v-1408q0 -26 -19 -45t-45 -19h-512q-26 0 -45 19t-19 45v1408q0 26 19 45t45 19h512q26 0 45 -19t19 -45z" />
+<glyph unicode="&#xf04d;" d="M1536 1344v-1408q0 -26 -19 -45t-45 -19h-1408q-26 0 -45 19t-19 45v1408q0 26 19 45t45 19h1408q26 0 45 -19t19 -45z" />
+<glyph unicode="&#xf04e;" horiz-adv-x="1664" d="M45 -115q-19 -19 -32 -13t-13 32v1472q0 26 13 32t32 -13l710 -710q8 -8 13 -19v710q0 26 13 32t32 -13l710 -710q19 -19 19 -45t-19 -45l-710 -710q-19 -19 -32 -13t-13 32v710q-5 -10 -13 -19z" />
+<glyph unicode="&#xf050;" horiz-adv-x="1792" d="M45 -115q-19 -19 -32 -13t-13 32v1472q0 26 13 32t32 -13l710 -710q8 -8 13 -19v710q0 26 13 32t32 -13l710 -710q8 -8 13 -19v678q0 26 19 45t45 19h128q26 0 45 -19t19 -45v-1408q0 -26 -19 -45t-45 -19h-128q-26 0 -45 19t-19 45v678q-5 -10 -13 -19l-710 -710 q-19 -19 -32 -13t-13 32v710q-5 -10 -13 -19z" />
+<glyph unicode="&#xf051;" horiz-adv-x="1024" d="M45 -115q-19 -19 -32 -13t-13 32v1472q0 26 13 32t32 -13l710 -710q8 -8 13 -19v678q0 26 19 45t45 19h128q26 0 45 -19t19 -45v-1408q0 -26 -19 -45t-45 -19h-128q-26 0 -45 19t-19 45v678q-5 -10 -13 -19z" />
+<glyph unicode="&#xf052;" horiz-adv-x="1538" d="M14 557l710 710q19 19 45 19t45 -19l710 -710q19 -19 13 -32t-32 -13h-1472q-26 0 -32 13t13 32zM1473 0h-1408q-26 0 -45 19t-19 45v256q0 26 19 45t45 19h1408q26 0 45 -19t19 -45v-256q0 -26 -19 -45t-45 -19z" />
+<glyph unicode="&#xf053;" horiz-adv-x="1152" d="M742 -37l-652 651q-37 37 -37 90.5t37 90.5l652 651q37 37 90.5 37t90.5 -37l75 -75q37 -37 37 -90.5t-37 -90.5l-486 -486l486 -485q37 -38 37 -91t-37 -90l-75 -75q-37 -37 -90.5 -37t-90.5 37z" />
+<glyph unicode="&#xf054;" horiz-adv-x="1152" d="M1099 704q0 -52 -37 -91l-652 -651q-37 -37 -90 -37t-90 37l-76 75q-37 39 -37 91q0 53 37 90l486 486l-486 485q-37 39 -37 91q0 53 37 90l76 75q36 38 90 38t90 -38l652 -651q37 -37 37 -90z" />
+<glyph unicode="&#xf055;" d="M1216 576v128q0 26 -19 45t-45 19h-256v256q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-256h-256q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h256v-256q0 -26 19 -45t45 -19h128q26 0 45 19t19 45v256h256q26 0 45 19t19 45zM1536 640q0 -209 -103 -385.5 t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+<glyph unicode="&#xf056;" d="M1216 576v128q0 26 -19 45t-45 19h-768q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h768q26 0 45 19t19 45zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5 t103 -385.5z" />
+<glyph unicode="&#xf057;" d="M1149 414q0 26 -19 45l-181 181l181 181q19 19 19 45q0 27 -19 46l-90 90q-19 19 -46 19q-26 0 -45 -19l-181 -181l-181 181q-19 19 -45 19q-27 0 -46 -19l-90 -90q-19 -19 -19 -46q0 -26 19 -45l181 -181l-181 -181q-19 -19 -19 -45q0 -27 19 -46l90 -90q19 -19 46 -19 q26 0 45 19l181 181l181 -181q19 -19 45 -19q27 0 46 19l90 90q19 19 19 46zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+<glyph unicode="&#xf058;" d="M1284 802q0 28 -18 46l-91 90q-19 19 -45 19t-45 -19l-408 -407l-226 226q-19 19 -45 19t-45 -19l-91 -90q-18 -18 -18 -46q0 -27 18 -45l362 -362q19 -19 45 -19q27 0 46 19l543 543q18 18 18 45zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103 t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+<glyph unicode="&#xf059;" d="M896 160v192q0 13 -9.5 22.5t-22.5 9.5h-192q-13 0 -22.5 -9.5t-9.5 -22.5v-192q0 -13 9.5 -22.5t22.5 -9.5h192q13 0 22.5 9.5t9.5 22.5zM1152 832q0 97 -58.5 172t-144.5 111.5t-181 36.5t-181 -36.5t-144.5 -111.5t-58.5 -172v-11v-13t1 -11.5t3 -11.5t5.5 -8t9 -7 t13.5 -2h192q14 0 23 9t9 23q0 12 11 27q19 31 50.5 50t66.5 19q39 0 83 -21.5t44 -57.5q0 -33 -26.5 -58t-63.5 -44t-74.5 -41.5t-64 -63.5t-26.5 -98v-11v-13t1 -11.5t3 -11.5t5.5 -8t9 -7t13.5 -2h192q17 0 24 10.5t8 24.5t13.5 33t37.5 32q60 33 70 39q62 44 98.5 108 t36.5 137zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+<glyph unicode="&#xf05a;" d="M1024 160v64q0 14 -9 23t-23 9h-96v480q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h96v-384h-96q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h448q14 0 23 9t9 23zM896 928v192q0 14 -9 23t-23 9h-192q-14 0 -23 -9t-9 -23v-192q0 -14 9 -23 t23 -9h192q14 0 23 9t9 23zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+<glyph unicode="&#xf05b;" d="M1197 512h-109q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h109q-32 108 -112.5 188.5t-188.5 112.5v-109q0 -26 -19 -45t-45 -19h-128q-26 0 -45 19t-19 45v109q-108 -32 -188.5 -112.5t-112.5 -188.5h109q26 0 45 -19t19 -45v-128q0 -26 -19 -45t-45 -19h-109 q32 -108 112.5 -188.5t188.5 -112.5v109q0 26 19 45t45 19h128q26 0 45 -19t19 -45v-109q108 32 188.5 112.5t112.5 188.5zM1536 704v-128q0 -26 -19 -45t-45 -19h-143q-37 -161 -154.5 -278.5t-278.5 -154.5v-143q0 -26 -19 -45t-45 -19h-128q-26 0 -45 19t-19 45v143 q-161 37 -278.5 154.5t-154.5 278.5h-143q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h143q37 161 154.5 278.5t278.5 154.5v143q0 26 19 45t45 19h128q26 0 45 -19t19 -45v-143q161 -37 278.5 -154.5t154.5 -278.5h143q26 0 45 -19t19 -45z" />
+<glyph unicode="&#xf05c;" d="M1125 448q0 -27 -18 -45l-102 -102q-18 -18 -45 -18t-45 18l-147 147l-147 -147q-18 -18 -45 -18t-45 18l-102 102q-18 18 -18 45t18 45l147 147l-147 147q-18 18 -18 45t18 45l102 102q18 18 45 18t45 -18l147 -147l147 147q18 18 45 18t45 -18l102 -102q18 -18 18 -45 t-18 -45l-147 -147l147 -147q18 -18 18 -45zM1280 640q0 104 -40.5 198.5t-109.5 163.5t-163.5 109.5t-198.5 40.5t-198.5 -40.5t-163.5 -109.5t-109.5 -163.5t-40.5 -198.5t40.5 -198.5t109.5 -163.5t163.5 -109.5t198.5 -40.5t198.5 40.5t163.5 109.5t109.5 163.5 t40.5 198.5zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+<glyph unicode="&#xf05d;" d="M1189 768q0 -27 -18 -45l-320 -320l-102 -102q-18 -18 -45 -18t-45 18l-102 102l-192 192q-18 18 -18 45t18 45l102 102q18 18 45 18t45 -18l147 -147l275 275q18 18 45 18t45 -18l102 -102q18 -18 18 -45zM1280 640q0 104 -40.5 198.5t-109.5 163.5t-163.5 109.5 t-198.5 40.5t-198.5 -40.5t-163.5 -109.5t-109.5 -163.5t-40.5 -198.5t40.5 -198.5t109.5 -163.5t163.5 -109.5t198.5 -40.5t198.5 40.5t163.5 109.5t109.5 163.5t40.5 198.5zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5 t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+<glyph unicode="&#xf05e;" d="M1280 640q0 139 -71 260l-701 -701q121 -71 260 -71q104 0 198.5 40.5t163.5 109.5t109.5 163.5t40.5 198.5zM327 380l701 701q-121 71 -260 71q-104 0 -198.5 -40.5t-163.5 -109.5t-109.5 -163.5t-40.5 -198.5q0 -139 71 -260zM1536 640q0 -209 -103 -385.5 t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+<glyph unicode="&#xf060;" d="M1536 640v-128q0 -53 -32.5 -90.5t-84.5 -37.5h-704l293 -294q38 -36 38 -90t-38 -90l-75 -76q-37 -37 -90 -37q-52 0 -91 37l-651 652q-37 37 -37 90q0 52 37 91l651 650q38 38 91 38q52 0 90 -38l75 -74q38 -38 38 -91t-38 -91l-293 -293h704q52 0 84.5 -37.5 t32.5 -90.5z" />
+<glyph unicode="&#xf061;" d="M1472 576q0 -54 -37 -91l-651 -651q-39 -37 -91 -37q-51 0 -90 37l-75 75q-38 38 -38 91t38 91l293 293h-704q-52 0 -84.5 37.5t-32.5 90.5v128q0 53 32.5 90.5t84.5 37.5h704l-293 294q-38 36 -38 90t38 90l75 75q38 38 90 38q53 0 91 -38l651 -651q37 -35 37 -90z" />
+<glyph unicode="&#xf062;" horiz-adv-x="1664" d="M1611 565q0 -51 -37 -90l-75 -75q-38 -38 -91 -38q-54 0 -90 38l-294 293v-704q0 -52 -37.5 -84.5t-90.5 -32.5h-128q-53 0 -90.5 32.5t-37.5 84.5v704l-294 -293q-36 -38 -90 -38t-90 38l-75 75q-38 38 -38 90q0 53 38 91l651 651q35 37 90 37q54 0 91 -37l651 -651 q37 -39 37 -91z" />
+<glyph unicode="&#xf063;" horiz-adv-x="1664" d="M1611 704q0 -53 -37 -90l-651 -652q-39 -37 -91 -37q-53 0 -90 37l-651 652q-38 36 -38 90q0 53 38 91l74 75q39 37 91 37q53 0 90 -37l294 -294v704q0 52 38 90t90 38h128q52 0 90 -38t38 -90v-704l294 294q37 37 90 37q52 0 91 -37l75 -75q37 -39 37 -91z" />
+<glyph unicode="&#xf064;" horiz-adv-x="1792" d="M1792 896q0 -26 -19 -45l-512 -512q-19 -19 -45 -19t-45 19t-19 45v256h-224q-98 0 -175.5 -6t-154 -21.5t-133 -42.5t-105.5 -69.5t-80 -101t-48.5 -138.5t-17.5 -181q0 -55 5 -123q0 -6 2.5 -23.5t2.5 -26.5q0 -15 -8.5 -25t-23.5 -10q-16 0 -28 17q-7 9 -13 22 t-13.5 30t-10.5 24q-127 285 -127 451q0 199 53 333q162 403 875 403h224v256q0 26 19 45t45 19t45 -19l512 -512q19 -19 19 -45z" />
+<glyph unicode="&#xf065;" d="M755 480q0 -13 -10 -23l-332 -332l144 -144q19 -19 19 -45t-19 -45t-45 -19h-448q-26 0 -45 19t-19 45v448q0 26 19 45t45 19t45 -19l144 -144l332 332q10 10 23 10t23 -10l114 -114q10 -10 10 -23zM1536 1344v-448q0 -26 -19 -45t-45 -19t-45 19l-144 144l-332 -332 q-10 -10 -23 -10t-23 10l-114 114q-10 10 -10 23t10 23l332 332l-144 144q-19 19 -19 45t19 45t45 19h448q26 0 45 -19t19 -45z" />
+<glyph unicode="&#xf066;" d="M768 576v-448q0 -26 -19 -45t-45 -19t-45 19l-144 144l-332 -332q-10 -10 -23 -10t-23 10l-114 114q-10 10 -10 23t10 23l332 332l-144 144q-19 19 -19 45t19 45t45 19h448q26 0 45 -19t19 -45zM1523 1248q0 -13 -10 -23l-332 -332l144 -144q19 -19 19 -45t-19 -45 t-45 -19h-448q-26 0 -45 19t-19 45v448q0 26 19 45t45 19t45 -19l144 -144l332 332q10 10 23 10t23 -10l114 -114q10 -10 10 -23z" />
+<glyph unicode="&#xf067;" horiz-adv-x="1408" d="M1408 800v-192q0 -40 -28 -68t-68 -28h-416v-416q0 -40 -28 -68t-68 -28h-192q-40 0 -68 28t-28 68v416h-416q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h416v416q0 40 28 68t68 28h192q40 0 68 -28t28 -68v-416h416q40 0 68 -28t28 -68z" />
+<glyph unicode="&#xf068;" horiz-adv-x="1408" d="M1408 800v-192q0 -40 -28 -68t-68 -28h-1216q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h1216q40 0 68 -28t28 -68z" />
+<glyph unicode="&#xf069;" horiz-adv-x="1664" d="M1482 486q46 -26 59.5 -77.5t-12.5 -97.5l-64 -110q-26 -46 -77.5 -59.5t-97.5 12.5l-266 153v-307q0 -52 -38 -90t-90 -38h-128q-52 0 -90 38t-38 90v307l-266 -153q-46 -26 -97.5 -12.5t-77.5 59.5l-64 110q-26 46 -12.5 97.5t59.5 77.5l266 154l-266 154 q-46 26 -59.5 77.5t12.5 97.5l64 110q26 46 77.5 59.5t97.5 -12.5l266 -153v307q0 52 38 90t90 38h128q52 0 90 -38t38 -90v-307l266 153q46 26 97.5 12.5t77.5 -59.5l64 -110q26 -46 12.5 -97.5t-59.5 -77.5l-266 -154z" />
+<glyph unicode="&#xf06a;" d="M768 1408q209 0 385.5 -103t279.5 -279.5t103 -385.5t-103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103zM896 161v190q0 14 -9 23.5t-22 9.5h-192q-13 0 -23 -10t-10 -23v-190q0 -13 10 -23t23 -10h192 q13 0 22 9.5t9 23.5zM894 505l18 621q0 12 -10 18q-10 8 -24 8h-220q-14 0 -24 -8q-10 -6 -10 -18l17 -621q0 -10 10 -17.5t24 -7.5h185q14 0 23.5 7.5t10.5 17.5z" />
+<glyph unicode="&#xf06b;" d="M928 180v716h-320v-716q0 -25 18.5 -38.5t45.5 -13.5h192q27 0 45.5 13.5t18.5 38.5zM472 1024h195l-126 161q-24 31 -69 31q-40 0 -68 -28t-28 -68t28 -68t68 -28zM1160 1120q0 40 -28 68t-68 28q-45 0 -69 -31l-125 -161h194q40 0 68 28t28 68zM1536 864v-320 q0 -14 -10 -22t-27 -10.5t-32 -2.5t-34.5 1.5t-24.5 1.5v-416q0 -40 -28 -68t-68 -28h-1088q-40 0 -68 28t-28 68v416q-5 0 -24.5 -1.5t-34.5 -1.5t-32 2.5t-27 10.5t-10 22v320q0 13 9.5 22.5t22.5 9.5h440q-93 0 -158.5 65.5t-65.5 158.5t65.5 158.5t158.5 65.5 q108 0 168 -77l128 -165l128 165q60 77 168 77q93 0 158.5 -65.5t65.5 -158.5t-65.5 -158.5t-158.5 -65.5h440q13 0 22.5 -9.5t9.5 -22.5z" />
+<glyph unicode="&#xf06c;" horiz-adv-x="1792" d="M1280 832q0 26 -19 45t-45 19q-172 0 -318 -49.5t-259.5 -134t-235.5 -219.5q-19 -21 -19 -45q0 -26 19 -45t45 -19q24 0 45 19q27 24 74 71t67 66q137 124 268.5 176t313.5 52q26 0 45 19t19 45zM1792 1030q0 -95 -20 -193q-46 -224 -184.5 -383t-357.5 -268 q-214 -108 -438 -108q-148 0 -286 47q-15 5 -88 42t-96 37q-16 0 -39.5 -32t-45 -70t-52.5 -70t-60 -32q-30 0 -51 11t-31 24t-27 42q-2 4 -6 11t-5.5 10t-3 9.5t-1.5 13.5q0 35 31 73.5t68 65.5t68 56t31 48q0 4 -14 38t-16 44q-9 51 -9 104q0 115 43.5 220t119 184.5 t170.5 139t204 95.5q55 18 145 25.5t179.5 9t178.5 6t163.5 24t113.5 56.5l29.5 29.5t29.5 28t27 20t36.5 16t43.5 4.5q39 0 70.5 -46t47.5 -112t24 -124t8 -96z" />
+<glyph unicode="&#xf06d;" horiz-adv-x="1408" d="M1408 -160v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-1344q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h1344q13 0 22.5 -9.5t9.5 -22.5zM1152 896q0 -78 -24.5 -144t-64 -112.5t-87.5 -88t-96 -77.5t-87.5 -72t-64 -81.5t-24.5 -96.5q0 -96 67 -224l-4 1l1 -1 q-90 41 -160 83t-138.5 100t-113.5 122.5t-72.5 150.5t-27.5 184q0 78 24.5 144t64 112.5t87.5 88t96 77.5t87.5 72t64 81.5t24.5 96.5q0 94 -66 224l3 -1l-1 1q90 -41 160 -83t138.5 -100t113.5 -122.5t72.5 -150.5t27.5 -184z" />
+<glyph unicode="&#xf06e;" horiz-adv-x="1792" d="M1664 576q-152 236 -381 353q61 -104 61 -225q0 -185 -131.5 -316.5t-316.5 -131.5t-316.5 131.5t-131.5 316.5q0 121 61 225q-229 -117 -381 -353q133 -205 333.5 -326.5t434.5 -121.5t434.5 121.5t333.5 326.5zM944 960q0 20 -14 34t-34 14q-125 0 -214.5 -89.5 t-89.5 -214.5q0 -20 14 -34t34 -14t34 14t14 34q0 86 61 147t147 61q20 0 34 14t14 34zM1792 576q0 -34 -20 -69q-140 -230 -376.5 -368.5t-499.5 -138.5t-499.5 139t-376.5 368q-20 35 -20 69t20 69q140 229 376.5 368t499.5 139t499.5 -139t376.5 -368q20 -35 20 -69z" />
+<glyph unicode="&#xf070;" horiz-adv-x="1792" d="M555 201l78 141q-87 63 -136 159t-49 203q0 121 61 225q-229 -117 -381 -353q167 -258 427 -375zM944 960q0 20 -14 34t-34 14q-125 0 -214.5 -89.5t-89.5 -214.5q0 -20 14 -34t34 -14t34 14t14 34q0 86 61 147t147 61q20 0 34 14t14 34zM1307 1151q0 -7 -1 -9 q-105 -188 -315 -566t-316 -567l-49 -89q-10 -16 -28 -16q-12 0 -134 70q-16 10 -16 28q0 12 44 87q-143 65 -263.5 173t-208.5 245q-20 31 -20 69t20 69q153 235 380 371t496 136q89 0 180 -17l54 97q10 16 28 16q5 0 18 -6t31 -15.5t33 -18.5t31.5 -18.5t19.5 -11.5 q16 -10 16 -27zM1344 704q0 -139 -79 -253.5t-209 -164.5l280 502q8 -45 8 -84zM1792 576q0 -35 -20 -69q-39 -64 -109 -145q-150 -172 -347.5 -267t-419.5 -95l74 132q212 18 392.5 137t301.5 307q-115 179 -282 294l63 112q95 -64 182.5 -153t144.5 -184q20 -34 20 -69z " />
+<glyph unicode="&#xf071;" horiz-adv-x="1792" d="M1024 161v190q0 14 -9.5 23.5t-22.5 9.5h-192q-13 0 -22.5 -9.5t-9.5 -23.5v-190q0 -14 9.5 -23.5t22.5 -9.5h192q13 0 22.5 9.5t9.5 23.5zM1022 535l18 459q0 12 -10 19q-13 11 -24 11h-220q-11 0 -24 -11q-10 -7 -10 -21l17 -457q0 -10 10 -16.5t24 -6.5h185 q14 0 23.5 6.5t10.5 16.5zM1008 1469l768 -1408q35 -63 -2 -126q-17 -29 -46.5 -46t-63.5 -17h-1536q-34 0 -63.5 17t-46.5 46q-37 63 -2 126l768 1408q17 31 47 49t65 18t65 -18t47 -49z" />
+<glyph unicode="&#xf072;" horiz-adv-x="1408" d="M1397 1324q0 -87 -149 -236l-240 -240l143 -746l1 -6q0 -14 -9 -23l-64 -64q-9 -9 -23 -9q-21 0 -29 18l-274 575l-245 -245q68 -238 68 -252t-9 -23l-64 -64q-9 -9 -23 -9q-18 0 -28 16l-155 280l-280 155q-17 9 -17 28q0 14 9 23l64 65q9 9 23 9t252 -68l245 245 l-575 274q-18 8 -18 29q0 14 9 23l64 64q9 9 23 9q4 0 6 -1l746 -143l240 240q149 149 236 149q32 0 52.5 -20.5t20.5 -52.5z" />
+<glyph unicode="&#xf073;" horiz-adv-x="1664" d="M128 -128h288v288h-288v-288zM480 -128h320v288h-320v-288zM128 224h288v320h-288v-320zM480 224h320v320h-320v-320zM128 608h288v288h-288v-288zM864 -128h320v288h-320v-288zM480 608h320v288h-320v-288zM1248 -128h288v288h-288v-288zM864 224h320v320h-320v-320z M512 1088v288q0 13 -9.5 22.5t-22.5 9.5h-64q-13 0 -22.5 -9.5t-9.5 -22.5v-288q0 -13 9.5 -22.5t22.5 -9.5h64q13 0 22.5 9.5t9.5 22.5zM1248 224h288v320h-288v-320zM864 608h320v288h-320v-288zM1248 608h288v288h-288v-288zM1280 1088v288q0 13 -9.5 22.5t-22.5 9.5h-64 q-13 0 -22.5 -9.5t-9.5 -22.5v-288q0 -13 9.5 -22.5t22.5 -9.5h64q13 0 22.5 9.5t9.5 22.5zM1664 1152v-1280q0 -52 -38 -90t-90 -38h-1408q-52 0 -90 38t-38 90v1280q0 52 38 90t90 38h128v96q0 66 47 113t113 47h64q66 0 113 -47t47 -113v-96h384v96q0 66 47 113t113 47 h64q66 0 113 -47t47 -113v-96h128q52 0 90 -38t38 -90z" />
+<glyph unicode="&#xf074;" horiz-adv-x="1792" d="M666 1055q-60 -92 -137 -273q-22 45 -37 72.5t-40.5 63.5t-51 56.5t-63 35t-81.5 14.5h-224q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h224q250 0 410 -225zM1792 256q0 -14 -9 -23l-320 -320q-9 -9 -23 -9q-13 0 -22.5 9.5t-9.5 22.5v192q-32 0 -85 -0.5t-81 -1t-73 1 t-71 5t-64 10.5t-63 18.5t-58 28.5t-59 40t-55 53.5t-56 69.5q59 93 136 273q22 -45 37 -72.5t40.5 -63.5t51 -56.5t63 -35t81.5 -14.5h256v192q0 14 9 23t23 9q12 0 24 -10l319 -319q9 -9 9 -23zM1792 1152q0 -14 -9 -23l-320 -320q-9 -9 -23 -9q-13 0 -22.5 9.5t-9.5 22.5 v192h-256q-48 0 -87 -15t-69 -45t-51 -61.5t-45 -77.5q-32 -62 -78 -171q-29 -66 -49.5 -111t-54 -105t-64 -100t-74 -83t-90 -68.5t-106.5 -42t-128 -16.5h-224q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h224q48 0 87 15t69 45t51 61.5t45 77.5q32 62 78 171q29 66 49.5 111 t54 105t64 100t74 83t90 68.5t106.5 42t128 16.5h256v192q0 14 9 23t23 9q12 0 24 -10l319 -319q9 -9 9 -23z" />
+<glyph unicode="&#xf075;" horiz-adv-x="1792" d="M1792 640q0 -174 -120 -321.5t-326 -233t-450 -85.5q-70 0 -145 8q-198 -175 -460 -242q-49 -14 -114 -22q-17 -2 -30.5 9t-17.5 29v1q-3 4 -0.5 12t2 10t4.5 9.5l6 9t7 8.5t8 9q7 8 31 34.5t34.5 38t31 39.5t32.5 51t27 59t26 76q-157 89 -247.5 220t-90.5 281 q0 130 71 248.5t191 204.5t286 136.5t348 50.5q244 0 450 -85.5t326 -233t120 -321.5z" />
+<glyph unicode="&#xf076;" d="M1536 704v-128q0 -201 -98.5 -362t-274 -251.5t-395.5 -90.5t-395.5 90.5t-274 251.5t-98.5 362v128q0 26 19 45t45 19h384q26 0 45 -19t19 -45v-128q0 -52 23.5 -90t53.5 -57t71 -30t64 -13t44 -2t44 2t64 13t71 30t53.5 57t23.5 90v128q0 26 19 45t45 19h384 q26 0 45 -19t19 -45zM512 1344v-384q0 -26 -19 -45t-45 -19h-384q-26 0 -45 19t-19 45v384q0 26 19 45t45 19h384q26 0 45 -19t19 -45zM1536 1344v-384q0 -26 -19 -45t-45 -19h-384q-26 0 -45 19t-19 45v384q0 26 19 45t45 19h384q26 0 45 -19t19 -45z" />
+<glyph unicode="&#xf077;" horiz-adv-x="1664" d="M1611 320q0 -53 -37 -90l-75 -75q-38 -38 -91 -38q-54 0 -90 38l-486 485l-486 -485q-36 -38 -90 -38t-90 38l-75 75q-38 36 -38 90q0 53 38 91l651 651q37 37 90 37q52 0 91 -37l650 -651q38 -38 38 -91z" />
+<glyph unicode="&#xf078;" horiz-adv-x="1664" d="M1611 832q0 -53 -37 -90l-651 -651q-38 -38 -91 -38q-54 0 -90 38l-651 651q-38 36 -38 90q0 53 38 91l74 75q39 37 91 37q53 0 90 -37l486 -486l486 486q37 37 90 37q52 0 91 -37l75 -75q37 -39 37 -91z" />
+<glyph unicode="&#xf079;" horiz-adv-x="1920" d="M1280 32q0 -13 -9.5 -22.5t-22.5 -9.5h-960q-8 0 -13.5 2t-9 7t-5.5 8t-3 11.5t-1 11.5v13v11v160v416h-192q-26 0 -45 19t-19 45q0 24 15 41l320 384q19 22 49 22t49 -22l320 -384q15 -17 15 -41q0 -26 -19 -45t-45 -19h-192v-384h576q16 0 25 -11l160 -192q7 -11 7 -21 zM1920 448q0 -24 -15 -41l-320 -384q-20 -23 -49 -23t-49 23l-320 384q-15 17 -15 41q0 26 19 45t45 19h192v384h-576q-16 0 -25 12l-160 192q-7 9 -7 20q0 13 9.5 22.5t22.5 9.5h960q8 0 13.5 -2t9 -7t5.5 -8t3 -11.5t1 -11.5v-13v-11v-160v-416h192q26 0 45 -19t19 -45z " />
+<glyph unicode="&#xf07a;" horiz-adv-x="1664" d="M640 0q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1536 0q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1664 1088v-512q0 -24 -16 -42.5t-41 -21.5 l-1044 -122q1 -7 4.5 -21.5t6 -26.5t2.5 -22q0 -16 -24 -64h920q26 0 45 -19t19 -45t-19 -45t-45 -19h-1024q-26 0 -45 19t-19 45q0 14 11 39.5t29.5 59.5t20.5 38l-177 823h-204q-26 0 -45 19t-19 45t19 45t45 19h256q16 0 28.5 -6.5t20 -15.5t13 -24.5t7.5 -26.5 t5.5 -29.5t4.5 -25.5h1201q26 0 45 -19t19 -45z" />
+<glyph unicode="&#xf07b;" horiz-adv-x="1664" d="M1664 928v-704q0 -92 -66 -158t-158 -66h-1216q-92 0 -158 66t-66 158v960q0 92 66 158t158 66h320q92 0 158 -66t66 -158v-32h672q92 0 158 -66t66 -158z" />
+<glyph unicode="&#xf07c;" horiz-adv-x="1920" d="M1879 584q0 -31 -31 -66l-336 -396q-43 -51 -120.5 -86.5t-143.5 -35.5h-1088q-34 0 -60.5 13t-26.5 43q0 31 31 66l336 396q43 51 120.5 86.5t143.5 35.5h1088q34 0 60.5 -13t26.5 -43zM1536 928v-160h-832q-94 0 -197 -47.5t-164 -119.5l-337 -396l-5 -6q0 4 -0.5 12.5 t-0.5 12.5v960q0 92 66 158t158 66h320q92 0 158 -66t66 -158v-32h544q92 0 158 -66t66 -158z" />
+<glyph unicode="&#xf07d;" horiz-adv-x="768" d="M704 1216q0 -26 -19 -45t-45 -19h-128v-1024h128q26 0 45 -19t19 -45t-19 -45l-256 -256q-19 -19 -45 -19t-45 19l-256 256q-19 19 -19 45t19 45t45 19h128v1024h-128q-26 0 -45 19t-19 45t19 45l256 256q19 19 45 19t45 -19l256 -256q19 -19 19 -45z" />
+<glyph unicode="&#xf07e;" horiz-adv-x="1792" d="M1792 640q0 -26 -19 -45l-256 -256q-19 -19 -45 -19t-45 19t-19 45v128h-1024v-128q0 -26 -19 -45t-45 -19t-45 19l-256 256q-19 19 -19 45t19 45l256 256q19 19 45 19t45 -19t19 -45v-128h1024v128q0 26 19 45t45 19t45 -19l256 -256q19 -19 19 -45z" />
+<glyph unicode="&#xf080;" horiz-adv-x="1920" d="M512 512v-384h-256v384h256zM896 1024v-896h-256v896h256zM1280 768v-640h-256v640h256zM1664 1152v-1024h-256v1024h256zM1792 32v1216q0 13 -9.5 22.5t-22.5 9.5h-1600q-13 0 -22.5 -9.5t-9.5 -22.5v-1216q0 -13 9.5 -22.5t22.5 -9.5h1600q13 0 22.5 9.5t9.5 22.5z M1920 1248v-1216q0 -66 -47 -113t-113 -47h-1600q-66 0 -113 47t-47 113v1216q0 66 47 113t113 47h1600q66 0 113 -47t47 -113z" />
+<glyph unicode="&#xf081;" d="M1280 958q0 13 -9.5 22.5t-22.5 9.5q-5 0 -15 -4q20 34 20 55q0 13 -9.5 22.5t-22.5 9.5q-7 0 -17 -5q-60 -34 -97 -43q-65 63 -154 63q-98 0 -164.5 -72.5t-64.5 -169.5v-12q-107 14 -187.5 64t-156.5 139q-10 12 -28 12q-26 0 -41 -50.5t-15 -86.5q0 -62 29 -117 q-13 -2 -21.5 -11.5t-8.5 -22.5q0 -112 81 -185q-12 -8 -12 -25q0 -6 1 -9q15 -51 50.5 -91.5t84.5 -60.5q-77 -43 -165 -43q-8 0 -24 1.5t-23 1.5q-13 0 -22.5 -9.5t-9.5 -22.5q0 -17 14 -26q63 -47 150 -73.5t170 -26.5q130 0 248 58q166 79 256 232.5t88 339.5v12 q27 22 62.5 63t35.5 61zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
+<glyph unicode="&#xf082;" d="M1248 1408q119 0 203.5 -84.5t84.5 -203.5v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-350q-2 0 -2 1v671h177q31 0 32 23l12 164q2 15 -8 25q-10 12 -24 12h-189v72q0 44 11.5 57t54.5 13q57 0 117 -13q13 -3 26 5q11 8 13 22l23 166q2 12 -5.5 22.5t-19.5 13.5 q-93 26 -197 26q-311 0 -311 -299v-85h-95q-13 0 -23 -10.5t-10 -24.5v-172q0 -8 5.5 -12t10 -4.5t17.5 -0.5h95v-671l10 -1h-330q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960z" />
+<glyph unicode="&#xf083;" horiz-adv-x="1792" d="M928 704q0 14 -9 23t-23 9q-66 0 -113 -47t-47 -113q0 -14 9 -23t23 -9t23 9t9 23q0 40 28 68t68 28q14 0 23 9t9 23zM1152 574q0 -106 -75 -181t-181 -75t-181 75t-75 181t75 181t181 75t181 -75t75 -181zM128 0h1536v128h-1536v-128zM1280 574q0 159 -112.5 271.5 t-271.5 112.5t-271.5 -112.5t-112.5 -271.5t112.5 -271.5t271.5 -112.5t271.5 112.5t112.5 271.5zM256 1216h384v128h-384v-128zM128 1024h1536v118v138h-828l-64 -128h-644v-128zM1792 1280v-1280q0 -53 -37.5 -90.5t-90.5 -37.5h-1536q-53 0 -90.5 37.5t-37.5 90.5v1280 q0 53 37.5 90.5t90.5 37.5h1536q53 0 90.5 -37.5t37.5 -90.5z" />
+<glyph unicode="&#xf084;" horiz-adv-x="1792" d="M832 1024q0 80 -56 136t-136 56t-136 -56t-56 -136q0 -42 19 -83q-41 19 -83 19q-80 0 -136 -56t-56 -136t56 -136t136 -56t136 56t56 136q0 42 -19 83q41 -19 83 -19q80 0 136 56t56 136zM1683 320q0 -17 -49 -66t-66 -49q-9 0 -28.5 16t-36.5 33t-38.5 40t-24.5 26 l-96 -96l220 -220q28 -28 28 -68q0 -42 -39 -81t-81 -39q-40 0 -68 28l-671 671q-176 -131 -365 -131q-163 0 -265.5 102.5t-102.5 265.5q0 160 95 313t248 248t313 95q163 0 265.5 -102.5t102.5 -265.5q0 -189 -131 -365l355 -355l96 96q-3 3 -26 24.5t-40 38.5t-33 36.5 t-16 28.5q0 17 49 66t66 49q13 0 23 -10q6 -6 46 -44.5t82 -79.5t86.5 -86t73 -78t28.5 -41z" />
+<glyph unicode="&#xf085;" horiz-adv-x="1920" d="M896 640q0 106 -75 181t-181 75t-181 -75t-75 -181t75 -181t181 -75t181 75t75 181zM1664 128q0 52 -38 90t-90 38t-90 -38t-38 -90q0 -53 37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1664 1152q0 52 -38 90t-90 38t-90 -38t-38 -90q0 -53 37.5 -90.5t90.5 -37.5 t90.5 37.5t37.5 90.5zM1280 731v-185q0 -10 -7 -19.5t-16 -10.5l-155 -24q-11 -35 -32 -76q34 -48 90 -115q7 -10 7 -20q0 -12 -7 -19q-23 -30 -82.5 -89.5t-78.5 -59.5q-11 0 -21 7l-115 90q-37 -19 -77 -31q-11 -108 -23 -155q-7 -24 -30 -24h-186q-11 0 -20 7.5t-10 17.5 l-23 153q-34 10 -75 31l-118 -89q-7 -7 -20 -7q-11 0 -21 8q-144 133 -144 160q0 9 7 19q10 14 41 53t47 61q-23 44 -35 82l-152 24q-10 1 -17 9.5t-7 19.5v185q0 10 7 19.5t16 10.5l155 24q11 35 32 76q-34 48 -90 115q-7 11 -7 20q0 12 7 20q22 30 82 89t79 59q11 0 21 -7 l115 -90q34 18 77 32q11 108 23 154q7 24 30 24h186q11 0 20 -7.5t10 -17.5l23 -153q34 -10 75 -31l118 89q8 7 20 7q11 0 21 -8q144 -133 144 -160q0 -9 -7 -19q-12 -16 -42 -54t-45 -60q23 -48 34 -82l152 
 -23q10 -2 17 -10.5t7 -19.5zM1920 198v-140q0 -16 -149 -31 q-12 -27 -30 -52q51 -113 51 -138q0 -4 -4 -7q-122 -71 -124 -71q-8 0 -46 47t-52 68q-20 -2 -30 -2t-30 2q-14 -21 -52 -68t-46 -47q-2 0 -124 71q-4 3 -4 7q0 25 51 138q-18 25 -30 52q-149 15 -149 31v140q0 16 149 31q13 29 30 52q-51 113 -51 138q0 4 4 7q4 2 35 20 t59 34t30 16q8 0 46 -46.5t52 -67.5q20 2 30 2t30 -2q51 71 92 112l6 2q4 0 124 -70q4 -3 4 -7q0 -25 -51 -138q17 -23 30 -52q149 -15 149 -31zM1920 1222v-140q0 -16 -149 -31q-12 -27 -30 -52q51 -113 51 -138q0 -4 -4 -7q-122 -71 -124 -71q-8 0 -46 47t-52 68 q-20 -2 -30 -2t-30 2q-14 -21 -52 -68t-46 -47q-2 0 -124 71q-4 3 -4 7q0 25 51 138q-18 25 -30 52q-149 15 -149 31v140q0 16 149 31q13 29 30 52q-51 113 -51 138q0 4 4 7q4 2 35 20t59 34t30 16q8 0 46 -46.5t52 -67.5q20 2 30 2t30 -2q51 71 92 112l6 2q4 0 124 -70 q4 -3 4 -7q0 -25 -51 -138q17 -23 30 -52q149 -15 149 -31z" />
+<glyph unicode="&#xf086;" horiz-adv-x="1792" d="M1408 768q0 -139 -94 -257t-256.5 -186.5t-353.5 -68.5q-86 0 -176 16q-124 -88 -278 -128q-36 -9 -86 -16h-3q-11 0 -20.5 8t-11.5 21q-1 3 -1 6.5t0.5 6.5t2 6l2.5 5t3.5 5.5t4 5t4.5 5t4 4.5q5 6 23 25t26 29.5t22.5 29t25 38.5t20.5 44q-124 72 -195 177t-71 224 q0 139 94 257t256.5 186.5t353.5 68.5t353.5 -68.5t256.5 -186.5t94 -257zM1792 512q0 -120 -71 -224.5t-195 -176.5q10 -24 20.5 -44t25 -38.5t22.5 -29t26 -29.5t23 -25q1 -1 4 -4.5t4.5 -5t4 -5t3.5 -5.5l2.5 -5t2 -6t0.5 -6.5t-1 -6.5q-3 -14 -13 -22t-22 -7 q-50 7 -86 16q-154 40 -278 128q-90 -16 -176 -16q-271 0 -472 132q58 -4 88 -4q161 0 309 45t264 129q125 92 192 212t67 254q0 77 -23 152q129 -71 204 -178t75 -230z" />
+<glyph unicode="&#xf087;" d="M256 192q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1408 768q0 51 -39 89.5t-89 38.5h-352q0 58 48 159.5t48 160.5q0 98 -32 145t-128 47q-26 -26 -38 -85t-30.5 -125.5t-59.5 -109.5q-22 -23 -77 -91q-4 -5 -23 -30t-31.5 -41t-34.5 -42.5 t-40 -44t-38.5 -35.5t-40 -27t-35.5 -9h-32v-640h32q13 0 31.5 -3t33 -6.5t38 -11t35 -11.5t35.5 -12.5t29 -10.5q211 -73 342 -73h121q192 0 192 167q0 26 -5 56q30 16 47.5 52.5t17.5 73.5t-18 69q53 50 53 119q0 25 -10 55.5t-25 47.5q32 1 53.5 47t21.5 81zM1536 769 q0 -89 -49 -163q9 -33 9 -69q0 -77 -38 -144q3 -21 3 -43q0 -101 -60 -178q1 -139 -85 -219.5t-227 -80.5h-36h-93q-96 0 -189.5 22.5t-216.5 65.5q-116 40 -138 40h-288q-53 0 -90.5 37.5t-37.5 90.5v640q0 53 37.5 90.5t90.5 37.5h274q36 24 137 155q58 75 107 128 q24 25 35.5 85.5t30.5 126.5t62 108q39 37 90 37q84 0 151 -32.5t102 -101.5t35 -186q0 -93 -48 -192h176q104 0 180 -76t76 -179z" />
+<glyph unicode="&#xf088;" d="M256 1088q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1408 512q0 35 -21.5 81t-53.5 47q15 17 25 47.5t10 55.5q0 69 -53 119q18 32 18 69t-17.5 73.5t-47.5 52.5q5 30 5 56q0 85 -49 126t-136 41h-128q-131 0 -342 -73q-5 -2 -29 -10.5 t-35.5 -12.5t-35 -11.5t-38 -11t-33 -6.5t-31.5 -3h-32v-640h32q16 0 35.5 -9t40 -27t38.5 -35.5t40 -44t34.5 -42.5t31.5 -41t23 -30q55 -68 77 -91q41 -43 59.5 -109.5t30.5 -125.5t38 -85q96 0 128 47t32 145q0 59 -48 160.5t-48 159.5h352q50 0 89 38.5t39 89.5z M1536 511q0 -103 -76 -179t-180 -76h-176q48 -99 48 -192q0 -118 -35 -186q-35 -69 -102 -101.5t-151 -32.5q-51 0 -90 37q-34 33 -54 82t-25.5 90.5t-17.5 84.5t-31 64q-48 50 -107 127q-101 131 -137 155h-274q-53 0 -90.5 37.5t-37.5 90.5v640q0 53 37.5 90.5t90.5 37.5 h288q22 0 138 40q128 44 223 66t200 22h112q140 0 226.5 -79t85.5 -216v-5q60 -77 60 -178q0 -22 -3 -43q38 -67 38 -144q0 -36 -9 -69q49 -74 49 -163z" />
+<glyph unicode="&#xf089;" horiz-adv-x="896" d="M832 1504v-1339l-449 -236q-22 -12 -40 -12q-21 0 -31.5 14.5t-10.5 35.5q0 6 2 20l86 500l-364 354q-25 27 -25 48q0 37 56 46l502 73l225 455q19 41 49 41z" />
+<glyph unicode="&#xf08a;" horiz-adv-x="1792" d="M1664 940q0 81 -21.5 143t-55 98.5t-81.5 59.5t-94 31t-98 8t-112 -25.5t-110.5 -64t-86.5 -72t-60 -61.5q-18 -22 -49 -22t-49 22q-24 28 -60 61.5t-86.5 72t-110.5 64t-112 25.5t-98 -8t-94 -31t-81.5 -59.5t-55 -98.5t-21.5 -143q0 -168 187 -355l581 -560l580 559 q188 188 188 356zM1792 940q0 -221 -229 -450l-623 -600q-18 -18 -44 -18t-44 18l-624 602q-10 8 -27.5 26t-55.5 65.5t-68 97.5t-53.5 121t-23.5 138q0 220 127 344t351 124q62 0 126.5 -21.5t120 -58t95.5 -68.5t76 -68q36 36 76 68t95.5 68.5t120 58t126.5 21.5 q224 0 351 -124t127 -344z" />
+<glyph unicode="&#xf08b;" horiz-adv-x="1664" d="M640 96q0 -4 1 -20t0.5 -26.5t-3 -23.5t-10 -19.5t-20.5 -6.5h-320q-119 0 -203.5 84.5t-84.5 203.5v704q0 119 84.5 203.5t203.5 84.5h320q13 0 22.5 -9.5t9.5 -22.5q0 -4 1 -20t0.5 -26.5t-3 -23.5t-10 -19.5t-20.5 -6.5h-320q-66 0 -113 -47t-47 -113v-704 q0 -66 47 -113t113 -47h288h11h13t11.5 -1t11.5 -3t8 -5.5t7 -9t2 -13.5zM1568 640q0 -26 -19 -45l-544 -544q-19 -19 -45 -19t-45 19t-19 45v288h-448q-26 0 -45 19t-19 45v384q0 26 19 45t45 19h448v288q0 26 19 45t45 19t45 -19l544 -544q19 -19 19 -45z" />
+<glyph unicode="&#xf08c;" d="M512 160v640q0 13 -9.5 22.5t-22.5 9.5h-192q-13 0 -22.5 -9.5t-9.5 -22.5v-640q0 -13 9.5 -22.5t22.5 -9.5h192q13 0 22.5 9.5t9.5 22.5zM503 1028q0 51 -36 87.5t-88 36.5q-51 0 -87 -36.5t-36 -87.5t36 -87.5t87 -36.5q52 0 88 36.5t36 87.5zM1280 160v435 q0 127 -73.5 192.5t-202.5 65.5q-90 0 -158 -45q-12 -8 -14 -12q0 36 -35 36h-176q-14 0 -29.5 -7.5t-15.5 -20.5v-644q0 -13 15.5 -22.5t29.5 -9.5h182q12 0 20.5 9.5t8.5 22.5v349q0 140 114 140q49 0 63.5 -22.5t14.5 -73.5v-393q0 -13 12 -22.5t26 -9.5h186 q13 0 22.5 9.5t9.5 22.5zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
+<glyph unicode="&#xf08d;" horiz-adv-x="1152" d="M480 672v448q0 14 -9 23t-23 9t-23 -9t-9 -23v-448q0 -14 9 -23t23 -9t23 9t9 23zM1152 320q0 -26 -19 -45t-45 -19h-429l-51 -483q-2 -12 -10.5 -20.5t-20.5 -8.5h-1q-27 0 -32 27l-76 485h-404q-26 0 -45 19t-19 45q0 123 78.5 221.5t177.5 98.5v512q-52 0 -90 38 t-38 90t38 90t90 38h640q52 0 90 -38t38 -90t-38 -90t-90 -38v-512q99 0 177.5 -98.5t78.5 -221.5z" />
+<glyph unicode="&#xf08e;" horiz-adv-x="1792" d="M1408 608v-320q0 -119 -84.5 -203.5t-203.5 -84.5h-832q-119 0 -203.5 84.5t-84.5 203.5v832q0 119 84.5 203.5t203.5 84.5h704q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-704q-66 0 -113 -47t-47 -113v-832q0 -66 47 -113t113 -47h832q66 0 113 47t47 113v320 q0 14 9 23t23 9h64q14 0 23 -9t9 -23zM1792 1472v-512q0 -26 -19 -45t-45 -19t-45 19l-176 176l-652 -652q-10 -10 -23 -10t-23 10l-114 114q-10 10 -10 23t10 23l652 652l-176 176q-19 19 -19 45t19 45t45 19h512q26 0 45 -19t19 -45z" />
+<glyph unicode="&#xf090;" d="M1184 640q0 -26 -19 -45l-544 -544q-19 -19 -45 -19t-45 19t-19 45v288h-448q-26 0 -45 19t-19 45v384q0 26 19 45t45 19h448v288q0 26 19 45t45 19t45 -19l544 -544q19 -19 19 -45zM1536 992v-704q0 -119 -84.5 -203.5t-203.5 -84.5h-320q-13 0 -22.5 9.5t-9.5 22.5 q0 4 -1 20t-0.5 26.5t3 23.5t10 19.5t20.5 6.5h320q66 0 113 47t47 113v704q0 66 -47 113t-113 47h-288h-11h-13t-11.5 1t-11.5 3t-8 5.5t-7 9t-2 13.5q0 4 -1 20t-0.5 26.5t3 23.5t10 19.5t20.5 6.5h320q119 0 203.5 -84.5t84.5 -203.5z" />
+<glyph unicode="&#xf091;" horiz-adv-x="1664" d="M458 653q-74 162 -74 371h-256v-96q0 -78 94.5 -162t235.5 -113zM1536 928v96h-256q0 -209 -74 -371q141 29 235.5 113t94.5 162zM1664 1056v-128q0 -71 -41.5 -143t-112 -130t-173 -97.5t-215.5 -44.5q-42 -54 -95 -95q-38 -34 -52.5 -72.5t-14.5 -89.5q0 -54 30.5 -91 t97.5 -37q75 0 133.5 -45.5t58.5 -114.5v-64q0 -14 -9 -23t-23 -9h-832q-14 0 -23 9t-9 23v64q0 69 58.5 114.5t133.5 45.5q67 0 97.5 37t30.5 91q0 51 -14.5 89.5t-52.5 72.5q-53 41 -95 95q-113 5 -215.5 44.5t-173 97.5t-112 130t-41.5 143v128q0 40 28 68t68 28h288v96 q0 66 47 113t113 47h576q66 0 113 -47t47 -113v-96h288q40 0 68 -28t28 -68z" />
+<glyph unicode="&#xf092;" d="M582 228q0 -66 -93 -66q-107 0 -107 63q0 64 98 64q102 0 102 -61zM546 694q0 -85 -74 -85q-77 0 -77 84q0 90 77 90q36 0 55 -26t19 -63zM712 769v125q-78 -29 -135 -29q-50 29 -110 29q-86 0 -145 -57t-59 -143q0 -50 29.5 -102t73.5 -67v-3q-38 -17 -38 -85 q0 -52 41 -77v-3q-113 -37 -113 -139q0 -60 36 -98t84 -51t107 -13q224 0 224 187q0 48 -25.5 78t-62.5 42.5t-74 21.5t-62.5 23.5t-25.5 39.5q0 44 49 52q77 15 122 70t45 134q0 24 -10 52q30 7 49 13zM771 350h137q-2 20 -2 90v372q0 59 2 76h-137q3 -26 3 -79v-377 q0 -55 -3 -82zM1280 366v121q-30 -21 -68 -21q-53 0 -53 82v225h52q9 0 26.5 -1t26.5 -1v117h-105q0 82 3 102h-140q4 -24 4 -55v-47h-60v-117q36 3 37 3q4 0 11.5 -0.5t11.5 -0.5v-2h-2v-217q0 -37 2.5 -64t11.5 -56.5t24.5 -48.5t43.5 -31t66 -12q64 0 108 24zM924 1072 q0 36 -24 63.5t-60 27.5t-60.5 -27t-24.5 -64q0 -36 25 -62.5t60 -26.5t59.5 27t24.5 62zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t8
 4.5 -203.5z" />
+<glyph unicode="&#xf093;" horiz-adv-x="1664" d="M1664 480v-576q0 -13 -9.5 -22.5t-22.5 -9.5h-1600q-13 0 -22.5 9.5t-9.5 22.5v576q0 13 9.5 22.5t22.5 9.5h192q13 0 22.5 -9.5t9.5 -22.5v-352h1152v352q0 13 9.5 22.5t22.5 9.5h192q13 0 22.5 -9.5t9.5 -22.5zM1344 832q0 -26 -19 -45t-45 -19h-256v-448 q0 -26 -19 -45t-45 -19h-256q-26 0 -45 19t-19 45v448h-256q-26 0 -45 19t-19 45t19 45l448 448q19 19 45 19t45 -19l448 -448q19 -19 19 -45z" />
+<glyph unicode="&#xf094;" d="M1407 710q0 44 -7 113.5t-18 96.5q-12 30 -17 44t-9 36.5t-4 48.5q0 23 5 68.5t5 67.5q0 37 -10 55q-4 1 -13 1q-19 0 -58 -4.5t-59 -4.5q-60 0 -176 24t-175 24q-43 0 -94.5 -11.5t-85 -23.5t-89.5 -34q-137 -54 -202 -103q-96 -73 -159.5 -189.5t-88 -236t-24.5 -248.5 q0 -40 12.5 -120t12.5 -121q0 -23 -11 -66.5t-11 -65.5t12 -36.5t34 -14.5q24 0 72.5 11t73.5 11q57 0 169.5 -15.5t169.5 -15.5q181 0 284 36q129 45 235.5 152.5t166 245.5t59.5 275zM1535 712q0 -165 -70 -327.5t-196 -288t-281 -180.5q-124 -44 -326 -44 q-57 0 -170 14.5t-169 14.5q-24 0 -72.5 -14.5t-73.5 -14.5q-73 0 -123.5 55.5t-50.5 128.5q0 24 11 68t11 67q0 40 -12.5 120.5t-12.5 121.5q0 111 18 217.5t54.5 209.5t100.5 194t150 156q78 59 232 120q194 78 316 78q60 0 175.5 -24t173.5 -24q19 0 57 5t58 5 q81 0 118 -50.5t37 -134.5q0 -23 -5 -68t-5 -68q0 -10 1 -18.5t3 -17t4 -13.5t6.5 -16t6.5 -17q16 -40 25 -118.5t9 -136.5z" />
+<glyph unicode="&#xf095;" horiz-adv-x="1408" d="M1408 296q0 -27 -10 -70.5t-21 -68.5q-21 -50 -122 -106q-94 -51 -186 -51q-27 0 -52.5 3.5t-57.5 12.5t-47.5 14.5t-55.5 20.5t-49 18q-98 35 -175 83q-128 79 -264.5 215.5t-215.5 264.5q-48 77 -83 175q-3 9 -18 49t-20.5 55.5t-14.5 47.5t-12.5 57.5t-3.5 52.5 q0 92 51 186q56 101 106 122q25 11 68.5 21t70.5 10q14 0 21 -3q18 -6 53 -76q11 -19 30 -54t35 -63.5t31 -53.5q3 -4 17.5 -25t21.5 -35.5t7 -28.5q0 -20 -28.5 -50t-62 -55t-62 -53t-28.5 -46q0 -9 5 -22.5t8.5 -20.5t14 -24t11.5 -19q76 -137 174 -235t235 -174 q2 -1 19 -11.5t24 -14t20.5 -8.5t22.5 -5q18 0 46 28.5t53 62t55 62t50 28.5q14 0 28.5 -7t35.5 -21.5t25 -17.5q25 -15 53.5 -31t63.5 -35t54 -30q70 -35 76 -53q3 -7 3 -21z" />
+<glyph unicode="&#xf096;" horiz-adv-x="1664" d="M1120 1280h-832q-66 0 -113 -47t-47 -113v-832q0 -66 47 -113t113 -47h832q66 0 113 47t47 113v832q0 66 -47 113t-113 47zM1408 1120v-832q0 -119 -84.5 -203.5t-203.5 -84.5h-832q-119 0 -203.5 84.5t-84.5 203.5v832q0 119 84.5 203.5t203.5 84.5h832 q119 0 203.5 -84.5t84.5 -203.5z" />
+<glyph unicode="&#xf097;" horiz-adv-x="1280" d="M1152 1280h-1024v-1242l423 406l89 85l89 -85l423 -406v1242zM1164 1408q23 0 44 -9q33 -13 52.5 -41t19.5 -62v-1289q0 -34 -19.5 -62t-52.5 -41q-19 -8 -44 -8q-48 0 -83 32l-441 424l-441 -424q-36 -33 -83 -33q-23 0 -44 9q-33 13 -52.5 41t-19.5 62v1289 q0 34 19.5 62t52.5 41q21 9 44 9h1048z" />
+<glyph unicode="&#xf098;" d="M1280 343q0 11 -2 16q-3 8 -38.5 29.5t-88.5 49.5l-53 29q-5 3 -19 13t-25 15t-21 5q-18 0 -47 -32.5t-57 -65.5t-44 -33q-7 0 -16.5 3.5t-15.5 6.5t-17 9.5t-14 8.5q-99 55 -170.5 126.5t-126.5 170.5q-2 3 -8.5 14t-9.5 17t-6.5 15.5t-3.5 16.5q0 13 20.5 33.5t45 38.5 t45 39.5t20.5 36.5q0 10 -5 21t-15 25t-13 19q-3 6 -15 28.5t-25 45.5t-26.5 47.5t-25 40.5t-16.5 18t-16 2q-48 0 -101 -22q-46 -21 -80 -94.5t-34 -130.5q0 -16 2.5 -34t5 -30.5t9 -33t10 -29.5t12.5 -33t11 -30q60 -164 216.5 -320.5t320.5 -216.5q6 -2 30 -11t33 -12.5 t29.5 -10t33 -9t30.5 -5t34 -2.5q57 0 130.5 34t94.5 80q22 53 22 101zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
+<glyph unicode="&#xf099;" horiz-adv-x="1920" d="M1875 1202q0 -10 -5 -18q-64 -104 -179 -190v-33q4 -227 -100 -457q-134 -297 -397.5 -464.5t-591.5 -167.5q-265 0 -500 122q-64 33 -87 50q-15 12 -15 27q0 13 9.5 22.5t22.5 9.5q14 0 44 -2.5t45 -2.5q204 0 375 106q-103 24 -181 96t-111 173q-2 8 -2 11q0 12 9 21.5 t22 9.5q5 0 14 -2t12 -2q-89 55 -142 147t-53 196q0 15 11.5 25.5t27.5 10.5q10 0 35 -11.5t30 -13.5q-92 110 -92 256q0 51 14.5 108t40.5 95q10 16 25 16q16 0 27 -12q76 -84 110 -115q123 -111 276 -177.5t317 -80.5q-4 21 -4 49q0 167 118.5 285.5t285.5 118.5 q163 0 282 -114q95 20 209 82q8 5 16 5q13 0 22.5 -9.5t9.5 -22.5q0 -24 -28 -73t-51 -76q7 2 30 10.5t43 16t24 7.5q13 0 22.5 -9.5t9.5 -22.5z" />
+<glyph unicode="&#xf09a;" horiz-adv-x="768" d="M560 1125q-49 0 -62 -15.5t-13 -66.5v-88h217q16 0 27 -12q11 -13 10 -29l-14 -200q-2 -15 -12.5 -25.5t-25.5 -10.5h-202v-768q0 -16 -11 -27t-26 -11h-250q-16 0 -27 11t-11 27v768h-122q-16 0 -27 11.5t-11 27.5v200q0 16 11 27t27 11h122v103q0 177 88 263.5 t267 86.5q120 0 225 -30q14 -4 22 -16t6 -26l-27 -195q-2 -16 -16 -26q-14 -9 -30 -6q-76 16 -135 16z" />
+<glyph unicode="&#xf09b;" d="M1408 640q0 130 -51 248.5t-136.5 204t-204 136.5t-248.5 51t-248.5 -51t-204 -136.5t-136.5 -204t-51 -248.5q0 -209 124.5 -378.5t323.5 -231.5v169q-54 -7 -69 -7q-110 0 -153 100q-15 38 -36 63q-5 6 -21 19t-28.5 24t-12.5 16q0 12 28 12q29 0 51.5 -14.5t38 -35 t31.5 -41.5t40.5 -35.5t56.5 -14.5q42 0 81 14q16 57 63 89q-166 16 -246 83.5t-80 224.5q0 118 73 198q-14 42 -14 84q0 58 27 109q57 0 101 -19.5t101 -60.5q76 18 169 18q80 0 153 -16q57 40 100.5 59t99.5 19q27 -51 27 -109q0 -43 -14 -83q73 -82 73 -199 q0 -157 -80 -225.5t-245 -83.5q69 -47 69 -131v-226q199 62 323.5 231.5t124.5 378.5zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+<glyph unicode="&#xf09c;" horiz-adv-x="1664" d="M704 160q0 6 -15 57t-35 115.5t-20 65.5q32 16 51 47t19 67q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5q0 -36 19 -66.5t51 -47.5q0 -2 -20 -66t-35 -115t-15 -57q0 -13 9.5 -22.5t22.5 -9.5h192q13 0 22.5 9.5t9.5 22.5zM1664 960v-256q0 -26 -19 -45t-45 -19 h-64q-26 0 -45 19t-19 45v256q0 106 -75 181t-181 75t-181 -75t-75 -181v-192h96q40 0 68 -28t28 -68v-576q0 -40 -28 -68t-68 -28h-960q-40 0 -68 28t-28 68v576q0 40 28 68t68 28h672v192q0 185 131.5 316.5t316.5 131.5t316.5 -131.5t131.5 -316.5z" />
+<glyph unicode="&#xf09d;" horiz-adv-x="1920" d="M1760 1408q66 0 113 -47t47 -113v-1216q0 -66 -47 -113t-113 -47h-1600q-66 0 -113 47t-47 113v1216q0 66 47 113t113 47h1600zM160 1280q-13 0 -22.5 -9.5t-9.5 -22.5v-224h1664v224q0 13 -9.5 22.5t-22.5 9.5h-1600zM1760 0q13 0 22.5 9.5t9.5 22.5v608h-1664v-608 q0 -13 9.5 -22.5t22.5 -9.5h1600zM256 128v128h256v-128h-256zM640 128v128h384v-128h-384z" />
+<glyph unicode="&#xf09e;" horiz-adv-x="1408" d="M384 192q0 -80 -56 -136t-136 -56t-136 56t-56 136t56 136t136 56t136 -56t56 -136zM896 69q2 -28 -17 -48q-18 -21 -47 -21h-135q-25 0 -43 16.5t-20 41.5q-22 229 -184.5 391.5t-391.5 184.5q-25 2 -41.5 20t-16.5 43v135q0 29 21 47q17 17 43 17h5q160 -13 306 -80.5 t259 -181.5q114 -113 181.5 -259t80.5 -306zM1408 67q2 -27 -18 -47q-18 -20 -46 -20h-143q-26 0 -44.5 17.5t-19.5 42.5q-12 215 -101 408.5t-231.5 336t-336 231.5t-408.5 102q-25 1 -42.5 19.5t-17.5 43.5v143q0 28 20 46q18 18 44 18h3q262 -13 501.5 -120t425.5 -294 q187 -186 294 -425.5t120 -501.5z" />
+<glyph unicode="&#xf0a0;" d="M1040 320q0 -33 -23.5 -56.5t-56.5 -23.5t-56.5 23.5t-23.5 56.5t23.5 56.5t56.5 23.5t56.5 -23.5t23.5 -56.5zM1296 320q0 -33 -23.5 -56.5t-56.5 -23.5t-56.5 23.5t-23.5 56.5t23.5 56.5t56.5 23.5t56.5 -23.5t23.5 -56.5zM1408 160v320q0 13 -9.5 22.5t-22.5 9.5 h-1216q-13 0 -22.5 -9.5t-9.5 -22.5v-320q0 -13 9.5 -22.5t22.5 -9.5h1216q13 0 22.5 9.5t9.5 22.5zM178 640h1180l-157 482q-4 13 -16 21.5t-26 8.5h-782q-14 0 -26 -8.5t-16 -21.5zM1536 480v-320q0 -66 -47 -113t-113 -47h-1216q-66 0 -113 47t-47 113v320q0 25 16 75 l197 606q17 53 63 86t101 33h782q55 0 101 -33t63 -86l197 -606q16 -50 16 -75z" />
+<glyph unicode="&#xf0a1;" horiz-adv-x="1792" d="M1664 896q53 0 90.5 -37.5t37.5 -90.5t-37.5 -90.5t-90.5 -37.5v-384q0 -52 -38 -90t-90 -38q-417 347 -812 380q-58 -19 -91 -66t-31 -100.5t40 -92.5q-20 -33 -23 -65.5t6 -58t33.5 -55t48 -50t61.5 -50.5q-29 -58 -111.5 -83t-168.5 -11.5t-132 55.5q-7 23 -29.5 87.5 t-32 94.5t-23 89t-15 101t3.5 98.5t22 110.5h-122q-66 0 -113 47t-47 113v192q0 66 47 113t113 47h480q435 0 896 384q52 0 90 -38t38 -90v-384zM1536 292v954q-394 -302 -768 -343v-270q377 -42 768 -341z" />
+<glyph unicode="&#xf0a2;" horiz-adv-x="1664" d="M848 -160q0 16 -16 16q-59 0 -101.5 42.5t-42.5 101.5q0 16 -16 16t-16 -16q0 -73 51.5 -124.5t124.5 -51.5q16 0 16 16zM183 128h1298q-164 181 -246.5 411.5t-82.5 484.5q0 256 -320 256t-320 -256q0 -254 -82.5 -484.5t-246.5 -411.5zM1664 128q0 -52 -38 -90t-90 -38 h-448q0 -106 -75 -181t-181 -75t-181 75t-75 181h-448q-52 0 -90 38t-38 90q190 161 287 397.5t97 498.5q0 165 96 262t264 117q-8 18 -8 37q0 40 28 68t68 28t68 -28t28 -68q0 -19 -8 -37q168 -20 264 -117t96 -262q0 -262 97 -498.5t287 -397.5z" />
+<glyph unicode="&#xf0a3;" d="M1376 640l138 -135q30 -28 20 -70q-12 -41 -52 -51l-188 -48l53 -186q12 -41 -19 -70q-29 -31 -70 -19l-186 53l-48 -188q-10 -40 -51 -52q-12 -2 -19 -2q-31 0 -51 22l-135 138l-135 -138q-28 -30 -70 -20q-41 11 -51 52l-48 188l-186 -53q-41 -12 -70 19q-31 29 -19 70 l53 186l-188 48q-40 10 -52 51q-10 42 20 70l138 135l-138 135q-30 28 -20 70q12 41 52 51l188 48l-53 186q-12 41 19 70q29 31 70 19l186 -53l48 188q10 41 51 51q41 12 70 -19l135 -139l135 139q29 30 70 19q41 -10 51 -51l48 -188l186 53q41 12 70 -19q31 -29 19 -70 l-53 -186l188 -48q40 -10 52 -51q10 -42 -20 -70z" />
+<glyph unicode="&#xf0a4;" horiz-adv-x="1792" d="M256 192q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1664 768q0 51 -39 89.5t-89 38.5h-576q0 20 15 48.5t33 55t33 68t15 84.5q0 67 -44.5 97.5t-115.5 30.5q-24 0 -90 -139q-24 -44 -37 -65q-40 -64 -112 -145q-71 -81 -101 -106 q-69 -57 -140 -57h-32v-640h32q72 0 167 -32t193.5 -64t179.5 -32q189 0 189 167q0 26 -5 56q30 16 47.5 52.5t17.5 73.5t-18 69q53 50 53 119q0 25 -10 55.5t-25 47.5h331q52 0 90 38t38 90zM1792 769q0 -105 -75.5 -181t-180.5 -76h-169q-4 -62 -37 -119q3 -21 3 -43 q0 -101 -60 -178q1 -139 -85 -219.5t-227 -80.5q-133 0 -322 69q-164 59 -223 59h-288q-53 0 -90.5 37.5t-37.5 90.5v640q0 53 37.5 90.5t90.5 37.5h288q10 0 21.5 4.5t23.5 14t22.5 18t24 22.5t20.5 21.5t19 21.5t14 17q65 74 100 129q13 21 33 62t37 72t40.5 63t55 49.5 t69.5 17.5q125 0 206.5 -67t81.5 -189q0 -68 -22 -128h374q104 0 180 -76t76 -179z" />
+<glyph unicode="&#xf0a5;" horiz-adv-x="1792" d="M1376 128h32v640h-32q-35 0 -67 11.5t-64 38.5t-48 44t-50 55q-2 3 -3.5 4.5t-4 4.5t-4.5 5q-72 81 -112 145q-14 22 -38 68q-1 3 -10.5 22.5t-18.5 36t-20 35.5t-21.5 30.5t-18.5 11.5q-71 0 -115.5 -30.5t-44.5 -97.5q0 -43 15 -84.5t33 -68t33 -55t15 -48.5h-576 q-50 0 -89 -38.5t-39 -89.5q0 -52 38 -90t90 -38h331q-15 -17 -25 -47.5t-10 -55.5q0 -69 53 -119q-18 -32 -18 -69t17.5 -73.5t47.5 -52.5q-4 -24 -4 -56q0 -85 48.5 -126t135.5 -41q84 0 183 32t194 64t167 32zM1664 192q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45 t45 -19t45 19t19 45zM1792 768v-640q0 -53 -37.5 -90.5t-90.5 -37.5h-288q-59 0 -223 -59q-190 -69 -317 -69q-142 0 -230 77.5t-87 217.5l1 5q-61 76 -61 178q0 22 3 43q-33 57 -37 119h-169q-105 0 -180.5 76t-75.5 181q0 103 76 179t180 76h374q-22 60 -22 128 q0 122 81.5 189t206.5 67q38 0 69.5 -17.5t55 -49.5t40.5 -63t37 -72t33 -62q35 -55 100 -129q2 -3 14 -17t19 -21.5t20.5 -21.5t24 -22.5t22.5 -18t23.5 -14t21.5 -4.5h288q53 0 90.5 -37.5t37.5 -90.5z" />
+<glyph unicode="&#xf0a6;" d="M1280 -64q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1408 700q0 189 -167 189q-26 0 -56 -5q-16 30 -52.5 47.5t-73.5 17.5t-69 -18q-50 53 -119 53q-25 0 -55.5 -10t-47.5 -25v331q0 52 -38 90t-90 38q-51 0 -89.5 -39t-38.5 -89v-576 q-20 0 -48.5 15t-55 33t-68 33t-84.5 15q-67 0 -97.5 -44.5t-30.5 -115.5q0 -24 139 -90q44 -24 65 -37q64 -40 145 -112q81 -71 106 -101q57 -69 57 -140v-32h640v32q0 72 32 167t64 193.5t32 179.5zM1536 705q0 -133 -69 -322q-59 -164 -59 -223v-288q0 -53 -37.5 -90.5 t-90.5 -37.5h-640q-53 0 -90.5 37.5t-37.5 90.5v288q0 10 -4.5 21.5t-14 23.5t-18 22.5t-22.5 24t-21.5 20.5t-21.5 19t-17 14q-74 65 -129 100q-21 13 -62 33t-72 37t-63 40.5t-49.5 55t-17.5 69.5q0 125 67 206.5t189 81.5q68 0 128 -22v374q0 104 76 180t179 76 q105 0 181 -75.5t76 -180.5v-169q62 -4 119 -37q21 3 43 3q101 0 178 -60q139 1 219.5 -85t80.5 -227z" />
+<glyph unicode="&#xf0a7;" d="M1408 576q0 84 -32 183t-64 194t-32 167v32h-640v-32q0 -46 -25 -91t-52 -72t-72 -66q-9 -8 -14 -12q-81 -72 -145 -112q-22 -14 -68 -38q-3 -1 -22.5 -10.5t-36 -18.5t-35.5 -20t-30.5 -21.5t-11.5 -18.5q0 -71 30.5 -115.5t97.5 -44.5q43 0 84.5 15t68 33t55 33 t48.5 15v-576q0 -50 38.5 -89t89.5 -39q52 0 90 38t38 90v331q46 -35 103 -35q69 0 119 53q32 -18 69 -18t73.5 17.5t52.5 47.5q24 -4 56 -4q85 0 126 48.5t41 135.5zM1280 1344q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1536 580q0 -142 -77.5 -230 t-217.5 -87l-5 1q-76 -61 -178 -61q-22 0 -43 3q-54 -30 -119 -37v-169q0 -105 -76 -180.5t-181 -75.5q-103 0 -179 76t-76 180v374q-54 -22 -128 -22q-121 0 -188.5 81.5t-67.5 206.5q0 38 17.5 69.5t49.5 55t63 40.5t72 37t62 33q55 35 129 100q3 2 17 14t21.5 19 t21.5 20.5t22.5 24t18 22.5t14 23.5t4.5 21.5v288q0 53 37.5 90.5t90.5 37.5h640q53 0 90.5 -37.5t37.5 -90.5v-288q0 -59 59 -223q69 -190 69 -317z" />
+<glyph unicode="&#xf0a8;" d="M1280 576v128q0 26 -19 45t-45 19h-502l189 189q19 19 19 45t-19 45l-91 91q-18 18 -45 18t-45 -18l-362 -362l-91 -91q-18 -18 -18 -45t18 -45l91 -91l362 -362q18 -18 45 -18t45 18l91 91q18 18 18 45t-18 45l-189 189h502q26 0 45 19t19 45zM1536 640 q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+<glyph unicode="&#xf0a9;" d="M1285 640q0 27 -18 45l-91 91l-362 362q-18 18 -45 18t-45 -18l-91 -91q-18 -18 -18 -45t18 -45l189 -189h-502q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h502l-189 -189q-19 -19 -19 -45t19 -45l91 -91q18 -18 45 -18t45 18l362 362l91 91q18 18 18 45zM1536 640 q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+<glyph unicode="&#xf0aa;" d="M1284 641q0 27 -18 45l-362 362l-91 91q-18 18 -45 18t-45 -18l-91 -91l-362 -362q-18 -18 -18 -45t18 -45l91 -91q18 -18 45 -18t45 18l189 189v-502q0 -26 19 -45t45 -19h128q26 0 45 19t19 45v502l189 -189q19 -19 45 -19t45 19l91 91q18 18 18 45zM1536 640 q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+<glyph unicode="&#xf0ab;" d="M1284 639q0 27 -18 45l-91 91q-18 18 -45 18t-45 -18l-189 -189v502q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-502l-189 189q-19 19 -45 19t-45 -19l-91 -91q-18 -18 -18 -45t18 -45l362 -362l91 -91q18 -18 45 -18t45 18l91 91l362 362q18 18 18 45zM1536 640 q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+<glyph unicode="&#xf0ac;" d="M1193 993q11 7 25 22v-1q0 -2 -9.5 -10t-11.5 -12q-1 1 -4 1zM1187 992q-1 1 -2.5 3t-1.5 3q3 -2 10 -5q-6 -4 -6 -1zM728 1175q-16 2 -26 5q1 0 6.5 -1t10.5 -2t9 -2zM773 1212q7 4 13.5 2.5t7.5 -7.5q-5 3 -21 5zM765 1206l-3 2q-2 3 -5.5 5t-4.5 2q2 -1 21 -3 q-6 -4 -8 -6zM663 1290v2q1 -2 3 -5.5t3 -5.5zM558 1250q0 -2 -1 -2l-1 2h2zM933 206v-1v1zM768 1408q209 0 385.5 -103t279.5 -279.5t103 -385.5t-103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103zM1240 162 l5 5q-7 10 -29 12q1 12 -14 26.5t-27 15.5q0 4 -10.5 11t-17.5 8q-9 2 -27 -9q-7 -3 -4 -5q-3 3 -12 11t-16 11q-2 1 -7.5 1t-8.5 2q-1 1 -6 4.5t-7 4.5t-6.5 3t-7.5 1.5t-7.5 -2.5t-8.5 -6t-4.5 -15.5t-2.5 -14.5q-8 6 -0.5 20t1.5 20q-7 7 -21 0.5t-21 -15.5 q-1 -1 -9.5 -5.5t-11.5 -7.5q-4 -6 -9 -17.5t-6 -13.5q0 2 -2.5 6.5t-2.5 6.5q-12 -2 -16 3q5 -16 8 -17l-4 2q-1 -6 3 -15t4 -11q1 -5 -1.5 -13t-2.5 -11q0 -2 5 -11q4 -19 -2 -32q0 -1 -3.5 -7t-6.5 -11l-2 -5l-2 1q-1 1 -2 0q-1 -6 -9 -13t-10 -
 11q-15 -23 -9 -38 q3 -8 10 -10q3 -1 3 2q1 -9 -11 -27q1 -1 4 -3q-17 0 -10 -14q202 36 352 181h-3zM680 347q16 3 30.5 -16t22.5 -23q41 -20 59 -11q0 -9 14 -28q3 -4 6.5 -11.5t5.5 -10.5q5 -7 19 -16t19 -16q6 3 9 9q13 -35 24 -34q5 0 8 8q0 -1 -0.5 -3t-1.5 -3q7 15 5 26l6 4q5 4 5 5 q-6 6 -9 -3q-30 -14 -48 22q-2 3 -4.5 8t-5 12t-1.5 11.5t6 4.5q11 0 12.5 1.5t-2.5 6t-4 7.5q-1 4 -1.5 12.5t-1.5 12.5l-5 6q-5 6 -11.5 13.5t-7.5 9.5q-4 -10 -16.5 -8.5t-18.5 9.5q1 -2 -0.5 -6.5t-1.5 -6.5q-14 0 -17 1q1 6 3 21t4 22q1 5 5.5 13.5t8 15.5t4.5 14 t-4.5 10.5t-18.5 2.5q-20 -1 -29 -22q-1 -3 -3 -11.5t-5 -12.5t-9 -7q-8 -3 -27 -2t-26 5q-14 8 -24 30.5t-11 41.5q0 10 3 27.5t3 27t-6 26.5q3 2 10 10.5t11 11.5q2 2 5 2h5t4 2t3 6q-1 1 -4 3q-3 3 -4 3q4 -3 19 -1t19 2q0 1 22 0q17 -13 24 2q0 1 -2.5 10.5t-0.5 14.5 q5 -29 32 -10q3 -4 16.5 -6t18.5 -5q3 -2 7 -5.5t6 -5t6 -0.5t9 7q11 -17 13 -25q11 -43 20 -48q8 -2 12.5 -2t5 10.5t0 15.5t-1.5 13l-2 37q-16 3 -20 12.5t1.5 20t16.5 19.5q1 1 16.5 8t21.5 12q24 19 17 39q9 -2 11 9l-5 3q-4 3 -8 5.5t-5
  1.5q11 7 2 18q5 3 8 11.5 t9 11.5q9 -14 22 -3q8 9 2 18q5 8 22 11.5t20 9.5q5 -1 7 0t2 4.5

<TRUNCATED>

[25/51] [abbrv] [partial] Adding Jinwon's custom RCMET

Posted by jo...@apache.org.
http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/app/js/.svn/text-base/leaflet.js.svn-base
----------------------------------------------------------------------
diff --git a/src/main/ui/app/js/.svn/text-base/leaflet.js.svn-base b/src/main/ui/app/js/.svn/text-base/leaflet.js.svn-base
new file mode 100755
index 0000000..4875188
--- /dev/null
+++ b/src/main/ui/app/js/.svn/text-base/leaflet.js.svn-base
@@ -0,0 +1,8 @@
+/*
+ Leaflet, a JavaScript library for mobile-friendly interactive maps. http://leafletjs.com
+ (c) 2010-2013, Vladimir Agafonkin, CloudMade
+*/
+(function(t,e,i){var n,o;typeof exports!=i+""?n=exports:(o=t.L,n={},n.noConflict=function(){return t.L=o,this},t.L=n),n.version="0.5",n.Util={extend:function(t){var e,i,n,o,s=Array.prototype.slice.call(arguments,1);for(i=0,n=s.length;n>i;i++){o=s[i]||{};for(e in o)o.hasOwnProperty(e)&&(t[e]=o[e])}return t},bind:function(t,e){var i=arguments.length>2?Array.prototype.slice.call(arguments,2):null;return function(){return t.apply(e,i||arguments)}},stamp:function(){var t=0,e="_leaflet_id";return function(i){return i[e]=i[e]||++t,i[e]}}(),limitExecByInterval:function(t,e,n){var o,s;return function a(){var r=arguments;return o?(s=!0,i):(o=!0,setTimeout(function(){o=!1,s&&(a.apply(n,r),s=!1)},e),t.apply(n,r),i)}},falseFn:function(){return!1},formatNum:function(t,e){var i=Math.pow(10,e||5);return Math.round(t*i)/i},splitWords:function(t){return t.replace(/^\s+|\s+$/g,"").split(/\s+/)},setOptions:function(t,e){return t.options=n.extend({},t.options,e),t.options},getParamString:function(t,e){v
 ar i=[];for(var n in t)t.hasOwnProperty(n)&&i.push(n+"="+t[n]);return(e&&-1!==e.indexOf("?")?"&":"?")+i.join("&")},template:function(t,e){return t.replace(/\{ *([\w_]+) *\}/g,function(t,i){var n=e[i];if(!e.hasOwnProperty(i))throw Error("No value provided for variable "+t);return n})},isArray:function(t){return"[object Array]"===Object.prototype.toString.call(t)},emptyImageUrl:"data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs="},function(){function e(e){var i,n,o=["webkit","moz","o","ms"];for(i=0;o.length>i&&!n;i++)n=t[o[i]+e];return n}function o(e){var i=+new Date,n=Math.max(0,16-(i-s));return s=i+n,t.setTimeout(e,n)}var s=0,a=t.requestAnimationFrame||e("RequestAnimationFrame")||o,r=t.cancelAnimationFrame||e("CancelAnimationFrame")||e("CancelRequestAnimationFrame")||function(e){t.clearTimeout(e)};n.Util.requestAnimFrame=function(e,s,r,h){return e=n.bind(e,s),r&&a===o?(e(),i):a.call(t,e,h)},n.Util.cancelAnimFrame=function(e){e&&r.call(t,e)}}(),n.extend=n.Util.extend,n.bind=n
 .Util.bind,n.stamp=n.Util.stamp,n.setOptions=n.Util.setOptions,n.Class=function(){},n.Class.extend=function(t){var e=function(){this.initialize&&this.initialize.apply(this,arguments),this._initHooks&&this.callInitHooks()},i=function(){};i.prototype=this.prototype;var o=new i;o.constructor=e,e.prototype=o;for(var s in this)this.hasOwnProperty(s)&&"prototype"!==s&&(e[s]=this[s]);t.statics&&(n.extend(e,t.statics),delete t.statics),t.includes&&(n.Util.extend.apply(null,[o].concat(t.includes)),delete t.includes),t.options&&o.options&&(t.options=n.extend({},o.options,t.options)),n.extend(o,t),o._initHooks=[];var a=this;return o.callInitHooks=function(){if(!this._initHooksCalled){a.prototype.callInitHooks&&a.prototype.callInitHooks.call(this),this._initHooksCalled=!0;for(var t=0,e=o._initHooks.length;e>t;t++)o._initHooks[t].call(this)}},e},n.Class.include=function(t){n.extend(this.prototype,t)},n.Class.mergeOptions=function(t){n.extend(this.prototype.options,t)},n.Class.addInitHook=functio
 n(t){var e=Array.prototype.slice.call(arguments,1),i="function"==typeof t?t:function(){this[t].apply(this,e)};this.prototype._initHooks=this.prototype._initHooks||[],this.prototype._initHooks.push(i)};var s="_leaflet_events";n.Mixin={},n.Mixin.Events={addEventListener:function(t,e,i){var o,a,r,h=this[s]=this[s]||{};if("object"==typeof t){for(o in t)t.hasOwnProperty(o)&&this.addEventListener(o,t[o],e);return this}for(t=n.Util.splitWords(t),a=0,r=t.length;r>a;a++)h[t[a]]=h[t[a]]||[],h[t[a]].push({action:e,context:i||this});return this},hasEventListeners:function(t){return s in this&&t in this[s]&&this[s][t].length>0},removeEventListener:function(t,e,i){var o,a,r,h,l,u=this[s];if("object"==typeof t){for(o in t)t.hasOwnProperty(o)&&this.removeEventListener(o,t[o],e);return this}for(t=n.Util.splitWords(t),a=0,r=t.length;r>a;a++)if(this.hasEventListeners(t[a]))for(h=u[t[a]],l=h.length-1;l>=0;l--)e&&h[l].action!==e||i&&h[l].context!==i||h.splice(l,1);return this},fireEvent:function(t,e){if
 (!this.hasEventListeners(t))return this;for(var i=n.extend({type:t,target:this},e),o=this[s][t].slice(),a=0,r=o.length;r>a;a++)o[a].action.call(o[a].context||this,i);return this}},n.Mixin.Events.on=n.Mixin.Events.addEventListener,n.Mixin.Events.off=n.Mixin.Events.removeEventListener,n.Mixin.Events.fire=n.Mixin.Events.fireEvent,function(){var o=!!t.ActiveXObject,s=o&&!t.XMLHttpRequest,a=o&&!e.querySelector,r=navigator.userAgent.toLowerCase(),h=-1!==r.indexOf("webkit"),l=-1!==r.indexOf("chrome"),u=-1!==r.indexOf("android"),c=-1!==r.search("android [23]"),_=typeof orientation!=i+"",d=t.navigator&&t.navigator.msPointerEnabled&&t.navigator.msMaxTouchPoints,p="devicePixelRatio"in t&&t.devicePixelRatio>1||"matchMedia"in t&&t.matchMedia("(min-resolution:144dpi)")&&t.matchMedia("(min-resolution:144dpi)").matches,m=e.documentElement,f=o&&"transition"in m.style,g="WebKitCSSMatrix"in t&&"m11"in new t.WebKitCSSMatrix,v="MozPerspective"in m.style,y="OTransition"in m.style,L=!t.L_DISABLE_3D&&(f||g
 ||v||y),P=!t.L_NO_TOUCH&&function(){var t="ontouchstart";if(d||t in m)return!0;var i=e.createElement("div"),n=!1;return i.setAttribute?(i.setAttribute(t,"return;"),"function"==typeof i[t]&&(n=!0),i.removeAttribute(t),i=null,n):!1}();n.Browser={ie:o,ie6:s,ie7:a,webkit:h,android:u,android23:c,chrome:l,ie3d:f,webkit3d:g,gecko3d:v,opera3d:y,any3d:L,mobile:_,mobileWebkit:_&&h,mobileWebkit3d:_&&g,mobileOpera:_&&t.opera,touch:P,msTouch:d,retina:p}}(),n.Point=function(t,e,i){this.x=i?Math.round(t):t,this.y=i?Math.round(e):e},n.Point.prototype={clone:function(){return new n.Point(this.x,this.y)},add:function(t){return this.clone()._add(n.point(t))},_add:function(t){return this.x+=t.x,this.y+=t.y,this},subtract:function(t){return this.clone()._subtract(n.point(t))},_subtract:function(t){return this.x-=t.x,this.y-=t.y,this},divideBy:function(t){return this.clone()._divideBy(t)},_divideBy:function(t){return this.x/=t,this.y/=t,this},multiplyBy:function(t){return this.clone()._multiplyBy(t)},_mu
 ltiplyBy:function(t){return this.x*=t,this.y*=t,this},round:function(){return this.clone()._round()},_round:function(){return this.x=Math.round(this.x),this.y=Math.round(this.y),this},floor:function(){return this.clone()._floor()},_floor:function(){return this.x=Math.floor(this.x),this.y=Math.floor(this.y),this},distanceTo:function(t){t=n.point(t);var e=t.x-this.x,i=t.y-this.y;return Math.sqrt(e*e+i*i)},equals:function(t){return t.x===this.x&&t.y===this.y},toString:function(){return"Point("+n.Util.formatNum(this.x)+", "+n.Util.formatNum(this.y)+")"}},n.point=function(t,e,i){return t instanceof n.Point?t:n.Util.isArray(t)?new n.Point(t[0],t[1]):isNaN(t)?t:new n.Point(t,e,i)},n.Bounds=function(t,e){if(t)for(var i=e?[t,e]:t,n=0,o=i.length;o>n;n++)this.extend(i[n])},n.Bounds.prototype={extend:function(t){return t=n.point(t),this.min||this.max?(this.min.x=Math.min(t.x,this.min.x),this.max.x=Math.max(t.x,this.max.x),this.min.y=Math.min(t.y,this.min.y),this.max.y=Math.max(t.y,this.max.y)):
 (this.min=t.clone(),this.max=t.clone()),this},getCenter:function(t){return new n.Point((this.min.x+this.max.x)/2,(this.min.y+this.max.y)/2,t)},getBottomLeft:function(){return new n.Point(this.min.x,this.max.y)},getTopRight:function(){return new n.Point(this.max.x,this.min.y)},getSize:function(){return this.max.subtract(this.min)},contains:function(t){var e,i;return t="number"==typeof t[0]||t instanceof n.Point?n.point(t):n.bounds(t),t instanceof n.Bounds?(e=t.min,i=t.max):e=i=t,e.x>=this.min.x&&i.x<=this.max.x&&e.y>=this.min.y&&i.y<=this.max.y},intersects:function(t){t=n.bounds(t);var e=this.min,i=this.max,o=t.min,s=t.max,a=s.x>=e.x&&o.x<=i.x,r=s.y>=e.y&&o.y<=i.y;return a&&r},isValid:function(){return!(!this.min||!this.max)}},n.bounds=function(t,e){return!t||t instanceof n.Bounds?t:new n.Bounds(t,e)},n.Transformation=function(t,e,i,n){this._a=t,this._b=e,this._c=i,this._d=n},n.Transformation.prototype={transform:function(t,e){return this._transform(t.clone(),e)},_transform:function(
 t,e){return e=e||1,t.x=e*(this._a*t.x+this._b),t.y=e*(this._c*t.y+this._d),t},untransform:function(t,e){return e=e||1,new n.Point((t.x/e-this._b)/this._a,(t.y/e-this._d)/this._c)}},n.DomUtil={get:function(t){return"string"==typeof t?e.getElementById(t):t},getStyle:function(t,i){var n=t.style[i];if(!n&&t.currentStyle&&(n=t.currentStyle[i]),(!n||"auto"===n)&&e.defaultView){var o=e.defaultView.getComputedStyle(t,null);n=o?o[i]:null}return"auto"===n?null:n},getViewportOffset:function(t){var i,o=0,s=0,a=t,r=e.body,h=n.Browser.ie7;do{if(o+=a.offsetTop||0,s+=a.offsetLeft||0,o+=parseInt(n.DomUtil.getStyle(a,"borderTopWidth"),10)||0,s+=parseInt(n.DomUtil.getStyle(a,"borderLeftWidth"),10)||0,i=n.DomUtil.getStyle(a,"position"),a.offsetParent===r&&"absolute"===i)break;if("fixed"===i){o+=r.scrollTop||0,s+=r.scrollLeft||0;break}a=a.offsetParent}while(a);a=t;do{if(a===r)break;o-=a.scrollTop||0,s-=a.scrollLeft||0,n.DomUtil.documentIsLtr()||!n.Browser.webkit&&!h||(s+=a.scrollWidth-a.clientWidth,h&&"
 hidden"!==n.DomUtil.getStyle(a,"overflow-y")&&"hidden"!==n.DomUtil.getStyle(a,"overflow")&&(s+=17)),a=a.parentNode}while(a);return new n.Point(s,o)},documentIsLtr:function(){return n.DomUtil._docIsLtrCached||(n.DomUtil._docIsLtrCached=!0,n.DomUtil._docIsLtr="ltr"===n.DomUtil.getStyle(e.body,"direction")),n.DomUtil._docIsLtr},create:function(t,i,n){var o=e.createElement(t);return o.className=i,n&&n.appendChild(o),o},disableTextSelection:function(){e.selection&&e.selection.empty&&e.selection.empty(),this._onselectstart||(this._onselectstart=e.onselectstart||null,e.onselectstart=n.Util.falseFn)},enableTextSelection:function(){e.onselectstart===n.Util.falseFn&&(e.onselectstart=this._onselectstart,this._onselectstart=null)},hasClass:function(t,e){return t.className.length>0&&RegExp("(^|\\s)"+e+"(\\s|$)").test(t.className)},addClass:function(t,e){n.DomUtil.hasClass(t,e)||(t.className+=(t.className?" ":"")+e)},removeClass:function(t,e){function i(t,i){return i===e?"":t}t.className=t.classN
 ame.replace(/(\S+)\s*/g,i).replace(/(^\s+|\s+$)/,"")},setOpacity:function(t,e){if("opacity"in t.style)t.style.opacity=e;else if("filter"in t.style){var i=!1,n="DXImageTransform.Microsoft.Alpha";try{i=t.filters.item(n)}catch(o){}e=Math.round(100*e),i?(i.Enabled=100!==e,i.Opacity=e):t.style.filter+=" progid:"+n+"(opacity="+e+")"}},testProp:function(t){for(var i=e.documentElement.style,n=0;t.length>n;n++)if(t[n]in i)return t[n];return!1},getTranslateString:function(t){var e=n.Browser.webkit3d,i="translate"+(e?"3d":"")+"(",o=(e?",0":"")+")";return i+t.x+"px,"+t.y+"px"+o},getScaleString:function(t,e){var i=n.DomUtil.getTranslateString(e.add(e.multiplyBy(-1*t))),o=" scale("+t+") ";return i+o},setPosition:function(t,e,i){t._leaflet_pos=e,!i&&n.Browser.any3d?(t.style[n.DomUtil.TRANSFORM]=n.DomUtil.getTranslateString(e),n.Browser.mobileWebkit3d&&(t.style.WebkitBackfaceVisibility="hidden")):(t.style.left=e.x+"px",t.style.top=e.y+"px")},getPosition:function(t){return t._leaflet_pos}},n.DomUtil
 .TRANSFORM=n.DomUtil.testProp(["transform","WebkitTransform","OTransform","MozTransform","msTransform"]),n.DomUtil.TRANSITION=n.DomUtil.testProp(["webkitTransition","transition","OTransition","MozTransition","msTransition"]),n.DomUtil.TRANSITION_END="webkitTransition"===n.DomUtil.TRANSITION||"OTransition"===n.DomUtil.TRANSITION?n.DomUtil.TRANSITION+"End":"transitionend",n.LatLng=function(t,e){var i=parseFloat(t),n=parseFloat(e);if(isNaN(i)||isNaN(n))throw Error("Invalid LatLng object: ("+t+", "+e+")");this.lat=i,this.lng=n},n.extend(n.LatLng,{DEG_TO_RAD:Math.PI/180,RAD_TO_DEG:180/Math.PI,MAX_MARGIN:1e-9}),n.LatLng.prototype={equals:function(t){if(!t)return!1;t=n.latLng(t);var e=Math.max(Math.abs(this.lat-t.lat),Math.abs(this.lng-t.lng));return n.LatLng.MAX_MARGIN>=e},toString:function(t){return"LatLng("+n.Util.formatNum(this.lat,t)+", "+n.Util.formatNum(this.lng,t)+")"},distanceTo:function(t){t=n.latLng(t);var e=6378137,i=n.LatLng.DEG_TO_RAD,o=(t.lat-this.lat)*i,s=(t.lng-this.lng)*i
 ,a=this.lat*i,r=t.lat*i,h=Math.sin(o/2),l=Math.sin(s/2),u=h*h+l*l*Math.cos(a)*Math.cos(r);return 2*e*Math.atan2(Math.sqrt(u),Math.sqrt(1-u))},wrap:function(t,e){var i=this.lng;return t=t||-180,e=e||180,i=(i+e)%(e-t)+(t>i||i===e?e:t),new n.LatLng(this.lat,i)}},n.latLng=function(t,e){return t instanceof n.LatLng?t:n.Util.isArray(t)?new n.LatLng(t[0],t[1]):isNaN(t)?t:new n.LatLng(t,e)},n.LatLngBounds=function(t,e){if(t)for(var i=e?[t,e]:t,n=0,o=i.length;o>n;n++)this.extend(i[n])},n.LatLngBounds.prototype={extend:function(t){return t="number"==typeof t[0]||"string"==typeof t[0]||t instanceof n.LatLng?n.latLng(t):n.latLngBounds(t),t instanceof n.LatLng?this._southWest||this._northEast?(this._southWest.lat=Math.min(t.lat,this._southWest.lat),this._southWest.lng=Math.min(t.lng,this._southWest.lng),this._northEast.lat=Math.max(t.lat,this._northEast.lat),this._northEast.lng=Math.max(t.lng,this._northEast.lng)):(this._southWest=new n.LatLng(t.lat,t.lng),this._northEast=new n.LatLng(t.lat,t.ln
 g)):t instanceof n.LatLngBounds&&(this.extend(t._southWest),this.extend(t._northEast)),this},pad:function(t){var e=this._southWest,i=this._northEast,o=Math.abs(e.lat-i.lat)*t,s=Math.abs(e.lng-i.lng)*t;return new n.LatLngBounds(new n.LatLng(e.lat-o,e.lng-s),new n.LatLng(i.lat+o,i.lng+s))},getCenter:function(){return new n.LatLng((this._southWest.lat+this._northEast.lat)/2,(this._southWest.lng+this._northEast.lng)/2)},getSouthWest:function(){return this._southWest},getNorthEast:function(){return this._northEast},getNorthWest:function(){return new n.LatLng(this._northEast.lat,this._southWest.lng)},getSouthEast:function(){return new n.LatLng(this._southWest.lat,this._northEast.lng)},contains:function(t){t="number"==typeof t[0]||t instanceof n.LatLng?n.latLng(t):n.latLngBounds(t);var e,i,o=this._southWest,s=this._northEast;return t instanceof n.LatLngBounds?(e=t.getSouthWest(),i=t.getNorthEast()):e=i=t,e.lat>=o.lat&&i.lat<=s.lat&&e.lng>=o.lng&&i.lng<=s.lng},intersects:function(t){t=n.lat
 LngBounds(t);var e=this._southWest,i=this._northEast,o=t.getSouthWest(),s=t.getNorthEast(),a=s.lat>=e.lat&&o.lat<=i.lat,r=s.lng>=e.lng&&o.lng<=i.lng;return a&&r},toBBoxString:function(){var t=this._southWest,e=this._northEast;return[t.lng,t.lat,e.lng,e.lat].join(",")},equals:function(t){return t?(t=n.latLngBounds(t),this._southWest.equals(t.getSouthWest())&&this._northEast.equals(t.getNorthEast())):!1},isValid:function(){return!(!this._southWest||!this._northEast)}},n.latLngBounds=function(t,e){return!t||t instanceof n.LatLngBounds?t:new n.LatLngBounds(t,e)},n.Projection={},n.Projection.SphericalMercator={MAX_LATITUDE:85.0511287798,project:function(t){var e=n.LatLng.DEG_TO_RAD,i=this.MAX_LATITUDE,o=Math.max(Math.min(i,t.lat),-i),s=t.lng*e,a=o*e;return a=Math.log(Math.tan(Math.PI/4+a/2)),new n.Point(s,a)},unproject:function(t){var e=n.LatLng.RAD_TO_DEG,i=t.x*e,o=(2*Math.atan(Math.exp(t.y))-Math.PI/2)*e;return new n.LatLng(o,i)}},n.Projection.LonLat={project:function(t){return new n.P
 oint(t.lng,t.lat)},unproject:function(t){return new n.LatLng(t.y,t.x)}},n.CRS={latLngToPoint:function(t,e){var i=this.projection.project(t),n=this.scale(e);return this.transformation._transform(i,n)},pointToLatLng:function(t,e){var i=this.scale(e),n=this.transformation.untransform(t,i);return this.projection.unproject(n)},project:function(t){return this.projection.project(t)},scale:function(t){return 256*Math.pow(2,t)}},n.CRS.Simple=n.extend({},n.CRS,{projection:n.Projection.LonLat,transformation:new n.Transformation(1,0,-1,0),scale:function(t){return Math.pow(2,t)}}),n.CRS.EPSG3857=n.extend({},n.CRS,{code:"EPSG:3857",projection:n.Projection.SphericalMercator,transformation:new n.Transformation(.5/Math.PI,.5,-.5/Math.PI,.5),project:function(t){var e=this.projection.project(t),i=6378137;return e.multiplyBy(i)}}),n.CRS.EPSG900913=n.extend({},n.CRS.EPSG3857,{code:"EPSG:900913"}),n.CRS.EPSG4326=n.extend({},n.CRS,{code:"EPSG:4326",projection:n.Projection.LonLat,transformation:new n.Trans
 formation(1/360,.5,-1/360,.5)}),n.Map=n.Class.extend({includes:n.Mixin.Events,options:{crs:n.CRS.EPSG3857,fadeAnimation:n.DomUtil.TRANSITION&&!n.Browser.android23,trackResize:!0,markerZoomAnimation:n.DomUtil.TRANSITION&&n.Browser.any3d},initialize:function(t,e){e=n.setOptions(this,e),this._initContainer(t),this._initLayout(),this.callInitHooks(),this._initEvents(),e.maxBounds&&this.setMaxBounds(e.maxBounds),e.center&&e.zoom!==i&&this.setView(n.latLng(e.center),e.zoom,!0),this._initLayers(e.layers)},setView:function(t,e){return this._resetView(n.latLng(t),this._limitZoom(e)),this},setZoom:function(t){return this.setView(this.getCenter(),t)},zoomIn:function(t){return this.setZoom(this._zoom+(t||1))},zoomOut:function(t){return this.setZoom(this._zoom-(t||1))},fitBounds:function(t){var e=this.getBoundsZoom(t);return this.setView(n.latLngBounds(t).getCenter(),e)},fitWorld:function(){var t=new n.LatLng(-60,-170),e=new n.LatLng(85,179);return this.fitBounds(new n.LatLngBounds(t,e))},panTo:
 function(t){return this.setView(t,this._zoom)},panBy:function(t){return this.fire("movestart"),this._rawPanBy(n.point(t)),this.fire("move"),this.fire("moveend")},setMaxBounds:function(t){if(t=n.latLngBounds(t),this.options.maxBounds=t,!t)return this._boundsMinZoom=null,this;var e=this.getBoundsZoom(t,!0);return this._boundsMinZoom=e,this._loaded&&(e>this._zoom?this.setView(t.getCenter(),e):this.panInsideBounds(t)),this},panInsideBounds:function(t){t=n.latLngBounds(t);var e=this.getBounds(),i=this.project(e.getSouthWest()),o=this.project(e.getNorthEast()),s=this.project(t.getSouthWest()),a=this.project(t.getNorthEast()),r=0,h=0;return o.y<a.y&&(h=a.y-o.y),o.x>a.x&&(r=a.x-o.x),i.y>s.y&&(h=s.y-i.y),i.x<s.x&&(r=s.x-i.x),this.panBy(new n.Point(r,h,!0))},addLayer:function(t){var e=n.stamp(t);return this._layers[e]?this:(this._layers[e]=t,!t.options||isNaN(t.options.maxZoom)&&isNaN(t.options.minZoom)||(this._zoomBoundLayers[e]=t,this._updateZoomLevels()),this.options.zoomAnimation&&n.TileL
 ayer&&t instanceof n.TileLayer&&(this._tileLayersNum++,this._tileLayersToLoad++,t.on("load",this._onTileLayerLoad,this)),this.whenReady(function(){t.onAdd(this),this.fire("layeradd",{layer:t})},this),this)},removeLayer:function(t){var e=n.stamp(t);if(this._layers[e])return t.onRemove(this),delete this._layers[e],this._zoomBoundLayers[e]&&(delete this._zoomBoundLayers[e],this._updateZoomLevels()),this.options.zoomAnimation&&n.TileLayer&&t instanceof n.TileLayer&&(this._tileLayersNum--,this._tileLayersToLoad--,t.off("load",this._onTileLayerLoad,this)),this.fire("layerremove",{layer:t})},hasLayer:function(t){var e=n.stamp(t);return this._layers.hasOwnProperty(e)},invalidateSize:function(t){var e=this.getSize();if(this._sizeChanged=!0,this.options.maxBounds&&this.setMaxBounds(this.options.maxBounds),!this._loaded)return this;var i=e._subtract(this.getSize())._divideBy(2)._round();return t===!0?this.panBy(i):(this._rawPanBy(i),this.fire("move"),clearTimeout(this._sizeTimer),this._sizeTim
 er=setTimeout(n.bind(this.fire,this,"moveend"),200)),this},addHandler:function(t,e){return e?(this[t]=new e(this),this.options[t]&&this[t].enable(),this):i},getCenter:function(){return this.layerPointToLatLng(this._getCenterLayerPoint())},getZoom:function(){return this._zoom},getBounds:function(){var t=this.getPixelBounds(),e=this.unproject(t.getBottomLeft()),i=this.unproject(t.getTopRight());return new n.LatLngBounds(e,i)},getMinZoom:function(){var t=this.options.minZoom||0,e=this._layersMinZoom||0,i=this._boundsMinZoom||0;return Math.max(t,e,i)},getMaxZoom:function(){var t=this.options.maxZoom===i?1/0:this.options.maxZoom,e=this._layersMaxZoom===i?1/0:this._layersMaxZoom;return Math.min(t,e)},getBoundsZoom:function(t,e){t=n.latLngBounds(t);var i,o,s,a=this.getSize(),r=this.options.minZoom||0,h=this.getMaxZoom(),l=t.getNorthEast(),u=t.getSouthWest(),c=!0;e&&r--;do r++,o=this.project(l,r),s=this.project(u,r),i=new n.Point(Math.abs(o.x-s.x),Math.abs(s.y-o.y)),c=e?i.x<a.x||i.y<a.y:i.x
 <=a.x&&i.y<=a.y;while(c&&h>=r);return c&&e?null:e?r:r-1},getSize:function(){return(!this._size||this._sizeChanged)&&(this._size=new n.Point(this._container.clientWidth,this._container.clientHeight),this._sizeChanged=!1),this._size.clone()},getPixelBounds:function(){var t=this._getTopLeftPoint();return new n.Bounds(t,t.add(this.getSize()))},getPixelOrigin:function(){return this._initialTopLeftPoint},getPanes:function(){return this._panes},getContainer:function(){return this._container},getZoomScale:function(t){var e=this.options.crs;return e.scale(t)/e.scale(this._zoom)},getScaleZoom:function(t){return this._zoom+Math.log(t)/Math.LN2},project:function(t,e){return e=e===i?this._zoom:e,this.options.crs.latLngToPoint(n.latLng(t),e)},unproject:function(t,e){return e=e===i?this._zoom:e,this.options.crs.pointToLatLng(n.point(t),e)},layerPointToLatLng:function(t){var e=n.point(t).add(this._initialTopLeftPoint);return this.unproject(e)},latLngToLayerPoint:function(t){var e=this.project(n.lat
 Lng(t))._round();return e._subtract(this._initialTopLeftPoint)},containerPointToLayerPoint:function(t){return n.point(t).subtract(this._getMapPanePos())},layerPointToContainerPoint:function(t){return n.point(t).add(this._getMapPanePos())},containerPointToLatLng:function(t){var e=this.containerPointToLayerPoint(n.point(t));return this.layerPointToLatLng(e)},latLngToContainerPoint:function(t){return this.layerPointToContainerPoint(this.latLngToLayerPoint(n.latLng(t)))},mouseEventToContainerPoint:function(t){return n.DomEvent.getMousePosition(t,this._container)},mouseEventToLayerPoint:function(t){return this.containerPointToLayerPoint(this.mouseEventToContainerPoint(t))},mouseEventToLatLng:function(t){return this.layerPointToLatLng(this.mouseEventToLayerPoint(t))},_initContainer:function(t){var e=this._container=n.DomUtil.get(t);if(e._leaflet)throw Error("Map container is already initialized.");e._leaflet=!0},_initLayout:function(){var t=this._container;n.DomUtil.addClass(t,"leaflet-co
 ntainer"),n.Browser.touch&&n.DomUtil.addClass(t,"leaflet-touch"),this.options.fadeAnimation&&n.DomUtil.addClass(t,"leaflet-fade-anim");var e=n.DomUtil.getStyle(t,"position");"absolute"!==e&&"relative"!==e&&"fixed"!==e&&(t.style.position="relative"),this._initPanes(),this._initControlPos&&this._initControlPos()},_initPanes:function(){var t=this._panes={};this._mapPane=t.mapPane=this._createPane("leaflet-map-pane",this._container),this._tilePane=t.tilePane=this._createPane("leaflet-tile-pane",this._mapPane),t.objectsPane=this._createPane("leaflet-objects-pane",this._mapPane),t.shadowPane=this._createPane("leaflet-shadow-pane"),t.overlayPane=this._createPane("leaflet-overlay-pane"),t.markerPane=this._createPane("leaflet-marker-pane"),t.popupPane=this._createPane("leaflet-popup-pane");var e=" leaflet-zoom-hide";this.options.markerZoomAnimation||(n.DomUtil.addClass(t.markerPane,e),n.DomUtil.addClass(t.shadowPane,e),n.DomUtil.addClass(t.popupPane,e))},_createPane:function(t,e){return n.Do
 mUtil.create("div",t,e||this._panes.objectsPane)},_initLayers:function(t){t=t?n.Util.isArray(t)?t:[t]:[],this._layers={},this._zoomBoundLayers={},this._tileLayersNum=0;var e,i;for(e=0,i=t.length;i>e;e++)this.addLayer(t[e])},_resetView:function(t,e,i,o){var s=this._zoom!==e;o||(this.fire("movestart"),s&&this.fire("zoomstart")),this._zoom=e,this._initialTopLeftPoint=this._getNewTopLeftPoint(t),i?this._initialTopLeftPoint._add(this._getMapPanePos()):n.DomUtil.setPosition(this._mapPane,new n.Point(0,0)),this._tileLayersToLoad=this._tileLayersNum;var a=!this._loaded;this._loaded=!0,this.fire("viewreset",{hard:!i}),this.fire("move"),(s||o)&&this.fire("zoomend"),this.fire("moveend",{hard:!i}),a&&this.fire("load")},_rawPanBy:function(t){n.DomUtil.setPosition(this._mapPane,this._getMapPanePos().subtract(t))},_updateZoomLevels:function(){var t,e=1/0,n=-1/0;for(t in this._zoomBoundLayers)if(this._zoomBoundLayers.hasOwnProperty(t)){var o=this._zoomBoundLayers[t];isNaN(o.options.minZoom)||(e=Mat
 h.min(e,o.options.minZoom)),isNaN(o.options.maxZoom)||(n=Math.max(n,o.options.maxZoom))}t===i?this._layersMaxZoom=this._layersMinZoom=i:(this._layersMaxZoom=n,this._layersMinZoom=e)},_initEvents:function(){if(n.DomEvent){n.DomEvent.on(this._container,"click",this._onMouseClick,this);var e,i,o=["dblclick","mousedown","mouseup","mouseenter","mouseleave","mousemove","contextmenu"];for(e=0,i=o.length;i>e;e++)n.DomEvent.on(this._container,o[e],this._fireMouseEvent,this);this.options.trackResize&&n.DomEvent.on(t,"resize",this._onResize,this)}},_onResize:function(){n.Util.cancelAnimFrame(this._resizeRequest),this._resizeRequest=n.Util.requestAnimFrame(this.invalidateSize,this,!1,this._container)},_onMouseClick:function(t){!this._loaded||this.dragging&&this.dragging.moved()||(this.fire("preclick"),this._fireMouseEvent(t))},_fireMouseEvent:function(t){if(this._loaded){var e=t.type;if(e="mouseenter"===e?"mouseover":"mouseleave"===e?"mouseout":e,this.hasEventListeners(e)){"contextmenu"===e&&n.
 DomEvent.preventDefault(t);var i=this.mouseEventToContainerPoint(t),o=this.containerPointToLayerPoint(i),s=this.layerPointToLatLng(o);this.fire(e,{latlng:s,layerPoint:o,containerPoint:i,originalEvent:t})}}},_onTileLayerLoad:function(){this._tileLayersToLoad--,this._tileLayersNum&&!this._tileLayersToLoad&&this._tileBg&&(clearTimeout(this._clearTileBgTimer),this._clearTileBgTimer=setTimeout(n.bind(this._clearTileBg,this),500))},whenReady:function(t,e){return this._loaded?t.call(e||this,this):this.on("load",t,e),this},_getMapPanePos:function(){return n.DomUtil.getPosition(this._mapPane)},_getTopLeftPoint:function(){if(!this._loaded)throw Error("Set map center and zoom first.");return this._initialTopLeftPoint.subtract(this._getMapPanePos())},_getNewTopLeftPoint:function(t,e){var i=this.getSize()._divideBy(2);return this.project(t,e)._subtract(i)._round()},_latLngToNewLayerPoint:function(t,e,i){var n=this._getNewTopLeftPoint(i,e).add(this._getMapPanePos());return this.project(t,e)._subt
 ract(n)},_getCenterLayerPoint:function(){return this.containerPointToLayerPoint(this.getSize()._divideBy(2))},_getCenterOffset:function(t){return this.latLngToLayerPoint(t).subtract(this._getCenterLayerPoint())},_limitZoom:function(t){var e=this.getMinZoom(),i=this.getMaxZoom();return Math.max(e,Math.min(i,t))}}),n.map=function(t,e){return new n.Map(t,e)},n.Projection.Mercator={MAX_LATITUDE:85.0840591556,R_MINOR:6356752.3142,R_MAJOR:6378137,project:function(t){var e=n.LatLng.DEG_TO_RAD,i=this.MAX_LATITUDE,o=Math.max(Math.min(i,t.lat),-i),s=this.R_MAJOR,a=this.R_MINOR,r=t.lng*e*s,h=o*e,l=a/s,u=Math.sqrt(1-l*l),c=u*Math.sin(h);c=Math.pow((1-c)/(1+c),.5*u);var _=Math.tan(.5*(.5*Math.PI-h))/c;return h=-a*Math.log(_),new n.Point(r,h)},unproject:function(t){for(var e,i=n.LatLng.RAD_TO_DEG,o=this.R_MAJOR,s=this.R_MINOR,a=t.x*i/o,r=s/o,h=Math.sqrt(1-r*r),l=Math.exp(-t.y/s),u=Math.PI/2-2*Math.atan(l),c=15,_=1e-7,d=c,p=.1;Math.abs(p)>_&&--d>0;)e=h*Math.sin(u),p=Math.PI/2-2*Math.atan(l*Math.po
 w((1-e)/(1+e),.5*h))-u,u+=p;return new n.LatLng(u*i,a)}},n.CRS.EPSG3395=n.extend({},n.CRS,{code:"EPSG:3395",projection:n.Projection.Mercator,transformation:function(){var t=n.Projection.Mercator,e=t.R_MAJOR,i=t.R_MINOR;return new n.Transformation(.5/(Math.PI*e),.5,-.5/(Math.PI*i),.5)}()}),n.TileLayer=n.Class.extend({includes:n.Mixin.Events,options:{minZoom:0,maxZoom:18,tileSize:256,subdomains:"abc",errorTileUrl:"",attribution:"",zoomOffset:0,opacity:1,unloadInvisibleTiles:n.Browser.mobile,updateWhenIdle:n.Browser.mobile},initialize:function(t,e){e=n.setOptions(this,e),e.detectRetina&&n.Browser.retina&&e.maxZoom>0&&(e.tileSize=Math.floor(e.tileSize/2),e.zoomOffset++,e.minZoom>0&&e.minZoom--,this.options.maxZoom--),this._url=t;var i=this.options.subdomains;"string"==typeof i&&(this.options.subdomains=i.split(""))},onAdd:function(t){this._map=t,this._initContainer(),this._createTileProto(),t.on({viewreset:this._resetCallback,moveend:this._update},this),this.options.updateWhenIdle||(thi
 s._limitedUpdate=n.Util.limitExecByInterval(this._update,150,this),t.on("move",this._limitedUpdate,this)),this._reset(),this._update()},addTo:function(t){return t.addLayer(this),this},onRemove:function(t){this._container.parentNode.removeChild(this._container),t.off({viewreset:this._resetCallback,moveend:this._update},this),this.options.updateWhenIdle||t.off("move",this._limitedUpdate,this),this._container=null,this._map=null},bringToFront:function(){var t=this._map._panes.tilePane;return this._container&&(t.appendChild(this._container),this._setAutoZIndex(t,Math.max)),this},bringToBack:function(){var t=this._map._panes.tilePane;return this._container&&(t.insertBefore(this._container,t.firstChild),this._setAutoZIndex(t,Math.min)),this},getAttribution:function(){return this.options.attribution},setOpacity:function(t){return this.options.opacity=t,this._map&&this._updateOpacity(),this},setZIndex:function(t){return this.options.zIndex=t,this._updateZIndex(),this},setUrl:function(t,e){r
 eturn this._url=t,e||this.redraw(),this},redraw:function(){return this._map&&(this._map._panes.tilePane.empty=!1,this._reset(!0),this._update()),this},_updateZIndex:function(){this._container&&this.options.zIndex!==i&&(this._container.style.zIndex=this.options.zIndex)},_setAutoZIndex:function(t,e){var i,n,o,s=t.children,a=-e(1/0,-1/0);for(n=0,o=s.length;o>n;n++)s[n]!==this._container&&(i=parseInt(s[n].style.zIndex,10),isNaN(i)||(a=e(a,i)));this.options.zIndex=this._container.style.zIndex=(isFinite(a)?a:0)+e(1,-1)},_updateOpacity:function(){n.DomUtil.setOpacity(this._container,this.options.opacity);var t,e=this._tiles;if(n.Browser.webkit)for(t in e)e.hasOwnProperty(t)&&(e[t].style.webkitTransform+=" translate(0,0)")},_initContainer:function(){var t=this._map._panes.tilePane;(!this._container||t.empty)&&(this._container=n.DomUtil.create("div","leaflet-layer"),this._updateZIndex(),t.appendChild(this._container),1>this.options.opacity&&this._updateOpacity())},_resetCallback:function(t){
 this._reset(t.hard)},_reset:function(t){var e=this._tiles;for(var i in e)e.hasOwnProperty(i)&&this.fire("tileunload",{tile:e[i]});this._tiles={},this._tilesToLoad=0,this.options.reuseTiles&&(this._unusedTiles=[]),t&&this._container&&(this._container.innerHTML=""),this._initContainer()},_update:function(){if(this._map){var t=this._map.getPixelBounds(),e=this._map.getZoom(),i=this.options.tileSize;if(!(e>this.options.maxZoom||this.options.minZoom>e)){var o=new n.Point(Math.floor(t.min.x/i),Math.floor(t.min.y/i)),s=new n.Point(Math.floor(t.max.x/i),Math.floor(t.max.y/i)),a=new n.Bounds(o,s);this._addTilesFromCenterOut(a),(this.options.unloadInvisibleTiles||this.options.reuseTiles)&&this._removeOtherTiles(a)}}},_addTilesFromCenterOut:function(t){var i,o,s,a=[],r=t.getCenter();for(i=t.min.y;t.max.y>=i;i++)for(o=t.min.x;t.max.x>=o;o++)s=new n.Point(o,i),this._tileShouldBeLoaded(s)&&a.push(s);var h=a.length;if(0!==h){a.sort(function(t,e){return t.distanceTo(r)-e.distanceTo(r)});var l=e.cre
 ateDocumentFragment();for(this._tilesToLoad||this.fire("loading"),this._tilesToLoad+=h,o=0;h>o;o++)this._addTile(a[o],l);this._container.appendChild(l)}},_tileShouldBeLoaded:function(t){if(t.x+":"+t.y in this._tiles)return!1;if(!this.options.continuousWorld){var e=this._getWrapTileNum();if(this.options.noWrap&&(0>t.x||t.x>=e)||0>t.y||t.y>=e)return!1}return!0},_removeOtherTiles:function(t){var e,i,n,o;for(o in this._tiles)this._tiles.hasOwnProperty(o)&&(e=o.split(":"),i=parseInt(e[0],10),n=parseInt(e[1],10),(t.min.x>i||i>t.max.x||t.min.y>n||n>t.max.y)&&this._removeTile(o))},_removeTile:function(t){var e=this._tiles[t];this.fire("tileunload",{tile:e,url:e.src}),this.options.reuseTiles?(n.DomUtil.removeClass(e,"leaflet-tile-loaded"),this._unusedTiles.push(e)):e.parentNode===this._container&&this._container.removeChild(e),n.Browser.android||(e.src=n.Util.emptyImageUrl),delete this._tiles[t]},_addTile:function(t,e){var i=this._getTilePos(t),o=this._getTile();n.DomUtil.setPosition(o,i,n.B
 rowser.chrome||n.Browser.android23),this._tiles[t.x+":"+t.y]=o,this._loadTile(o,t),o.parentNode!==this._container&&e.appendChild(o)
+},_getZoomForUrl:function(){var t=this.options,e=this._map.getZoom();return t.zoomReverse&&(e=t.maxZoom-e),e+t.zoomOffset},_getTilePos:function(t){var e=this._map.getPixelOrigin(),i=this.options.tileSize;return t.multiplyBy(i).subtract(e)},getTileUrl:function(t){return this._adjustTilePoint(t),n.Util.template(this._url,n.extend({s:this._getSubdomain(t),z:this._getZoomForUrl(),x:t.x,y:t.y},this.options))},_getWrapTileNum:function(){return Math.pow(2,this._getZoomForUrl())},_adjustTilePoint:function(t){var e=this._getWrapTileNum();this.options.continuousWorld||this.options.noWrap||(t.x=(t.x%e+e)%e),this.options.tms&&(t.y=e-t.y-1)},_getSubdomain:function(t){var e=(t.x+t.y)%this.options.subdomains.length;return this.options.subdomains[e]},_createTileProto:function(){var t=this._tileImg=n.DomUtil.create("img","leaflet-tile");t.style.width=t.style.height=this.options.tileSize+"px",t.galleryimg="no"},_getTile:function(){if(this.options.reuseTiles&&this._unusedTiles.length>0){var t=this._un
 usedTiles.pop();return this._resetTile(t),t}return this._createTile()},_resetTile:function(){},_createTile:function(){var t=this._tileImg.cloneNode(!1);return t.onselectstart=t.onmousemove=n.Util.falseFn,t},_loadTile:function(t,e){t._layer=this,t.onload=this._tileOnLoad,t.onerror=this._tileOnError,t.src=this.getTileUrl(e)},_tileLoaded:function(){this._tilesToLoad--,this._tilesToLoad||this.fire("load")},_tileOnLoad:function(){var t=this._layer;this.src!==n.Util.emptyImageUrl&&(n.DomUtil.addClass(this,"leaflet-tile-loaded"),t.fire("tileload",{tile:this,url:this.src})),t._tileLoaded()},_tileOnError:function(){var t=this._layer;t.fire("tileerror",{tile:this,url:this.src});var e=t.options.errorTileUrl;e&&(this.src=e),t._tileLoaded()}}),n.tileLayer=function(t,e){return new n.TileLayer(t,e)},n.TileLayer.WMS=n.TileLayer.extend({defaultWmsParams:{service:"WMS",request:"GetMap",version:"1.1.1",layers:"",styles:"",format:"image/jpeg",transparent:!1},initialize:function(t,e){this._url=t;var i=n
 .extend({},this.defaultWmsParams);i.width=i.height=e.detectRetina&&n.Browser.retina?2*this.options.tileSize:this.options.tileSize;for(var o in e)this.options.hasOwnProperty(o)||(i[o]=e[o]);this.wmsParams=i,n.setOptions(this,e)},onAdd:function(t){var e=parseFloat(this.wmsParams.version)>=1.3?"crs":"srs";this.wmsParams[e]=t.options.crs.code,n.TileLayer.prototype.onAdd.call(this,t)},getTileUrl:function(t,e){this._adjustTilePoint(t);var i=this._map,o=i.options.crs,s=this.options.tileSize,a=t.multiplyBy(s),r=a.add(new n.Point(s,s)),h=o.project(i.unproject(a,e)),l=o.project(i.unproject(r,e)),u=[h.x,l.y,l.x,h.y].join(","),c=n.Util.template(this._url,{s:this._getSubdomain(t)});return c+n.Util.getParamString(this.wmsParams,c)+"&bbox="+u},setParams:function(t,e){return n.extend(this.wmsParams,t),e||this.redraw(),this}}),n.tileLayer.wms=function(t,e){return new n.TileLayer.WMS(t,e)},n.TileLayer.Canvas=n.TileLayer.extend({options:{async:!1},initialize:function(t){n.setOptions(this,t)},redraw:fu
 nction(){var t=this._tiles;for(var e in t)t.hasOwnProperty(e)&&this._redrawTile(t[e])},_redrawTile:function(t){this.drawTile(t,t._tilePoint,this._map._zoom)},_createTileProto:function(){var t=this._canvasProto=n.DomUtil.create("canvas","leaflet-tile");t.width=t.height=this.options.tileSize},_createTile:function(){var t=this._canvasProto.cloneNode(!1);return t.onselectstart=t.onmousemove=n.Util.falseFn,t},_loadTile:function(t,e){t._layer=this,t._tilePoint=e,this._redrawTile(t),this.options.async||this.tileDrawn(t)},drawTile:function(){},tileDrawn:function(t){this._tileOnLoad.call(t)}}),n.tileLayer.canvas=function(t){return new n.TileLayer.Canvas(t)},n.ImageOverlay=n.Class.extend({includes:n.Mixin.Events,options:{opacity:1},initialize:function(t,e,i){this._url=t,this._bounds=n.latLngBounds(e),n.setOptions(this,i)},onAdd:function(t){this._map=t,this._image||this._initImage(),t._panes.overlayPane.appendChild(this._image),t.on("viewreset",this._reset,this),t.options.zoomAnimation&&n.Brow
 ser.any3d&&t.on("zoomanim",this._animateZoom,this),this._reset()},onRemove:function(t){t.getPanes().overlayPane.removeChild(this._image),t.off("viewreset",this._reset,this),t.options.zoomAnimation&&t.off("zoomanim",this._animateZoom,this)},addTo:function(t){return t.addLayer(this),this},setOpacity:function(t){return this.options.opacity=t,this._updateOpacity(),this},bringToFront:function(){return this._image&&this._map._panes.overlayPane.appendChild(this._image),this},bringToBack:function(){var t=this._map._panes.overlayPane;return this._image&&t.insertBefore(this._image,t.firstChild),this},_initImage:function(){this._image=n.DomUtil.create("img","leaflet-image-layer"),this._map.options.zoomAnimation&&n.Browser.any3d?n.DomUtil.addClass(this._image,"leaflet-zoom-animated"):n.DomUtil.addClass(this._image,"leaflet-zoom-hide"),this._updateOpacity(),n.extend(this._image,{galleryimg:"no",onselectstart:n.Util.falseFn,onmousemove:n.Util.falseFn,onload:n.bind(this._onImageLoad,this),src:this
 ._url})},_animateZoom:function(t){var e=this._map,i=this._image,o=e.getZoomScale(t.zoom),s=this._bounds.getNorthWest(),a=this._bounds.getSouthEast(),r=e._latLngToNewLayerPoint(s,t.zoom,t.center),h=e._latLngToNewLayerPoint(a,t.zoom,t.center)._subtract(r),l=r._add(h._multiplyBy(.5*(1-1/o)));i.style[n.DomUtil.TRANSFORM]=n.DomUtil.getTranslateString(l)+" scale("+o+") "},_reset:function(){var t=this._image,e=this._map.latLngToLayerPoint(this._bounds.getNorthWest()),i=this._map.latLngToLayerPoint(this._bounds.getSouthEast())._subtract(e);n.DomUtil.setPosition(t,e),t.style.width=i.x+"px",t.style.height=i.y+"px"},_onImageLoad:function(){this.fire("load")},_updateOpacity:function(){n.DomUtil.setOpacity(this._image,this.options.opacity)}}),n.imageOverlay=function(t,e,i){return new n.ImageOverlay(t,e,i)},n.Icon=n.Class.extend({options:{className:""},initialize:function(t){n.setOptions(this,t)},createIcon:function(){return this._createIcon("icon")},createShadow:function(){return this._createIco
 n("shadow")},_createIcon:function(t){var e=this._getIconUrl(t);if(!e){if("icon"===t)throw Error("iconUrl not set in Icon options (see the docs).");return null}var i=this._createImg(e);return this._setIconStyles(i,t),i},_setIconStyles:function(t,e){var i,o=this.options,s=n.point(o[e+"Size"]);i="shadow"===e?n.point(o.shadowAnchor||o.iconAnchor):n.point(o.iconAnchor),!i&&s&&(i=s.divideBy(2,!0)),t.className="leaflet-marker-"+e+" "+o.className,i&&(t.style.marginLeft=-i.x+"px",t.style.marginTop=-i.y+"px"),s&&(t.style.width=s.x+"px",t.style.height=s.y+"px")},_createImg:function(t){var i;return n.Browser.ie6?(i=e.createElement("div"),i.style.filter='progid:DXImageTransform.Microsoft.AlphaImageLoader(src="'+t+'")'):(i=e.createElement("img"),i.src=t),i},_getIconUrl:function(t){return n.Browser.retina&&this.options[t+"RetinaUrl"]?this.options[t+"RetinaUrl"]:this.options[t+"Url"]}}),n.icon=function(t){return new n.Icon(t)},n.Icon.Default=n.Icon.extend({options:{iconSize:new n.Point(25,41),iconA
 nchor:new n.Point(12,41),popupAnchor:new n.Point(1,-34),shadowSize:new n.Point(41,41)},_getIconUrl:function(t){var e=t+"Url";if(this.options[e])return this.options[e];n.Browser.retina&&"icon"===t&&(t+="@2x");var i=n.Icon.Default.imagePath;if(!i)throw Error("Couldn't autodetect L.Icon.Default.imagePath, set it manually.");return i+"/marker-"+t+".png"}}),n.Icon.Default.imagePath=function(){var t,i,n,o,s=e.getElementsByTagName("script"),a=/\/?leaflet[\-\._]?([\w\-\._]*)\.js\??/;for(t=0,i=s.length;i>t;t++)if(n=s[t].src,o=n.match(a))return n.split(a)[0]+"/images"}(),n.Marker=n.Class.extend({includes:n.Mixin.Events,options:{icon:new n.Icon.Default,title:"",clickable:!0,draggable:!1,zIndexOffset:0,opacity:1,riseOnHover:!1,riseOffset:250},initialize:function(t,e){n.setOptions(this,e),this._latlng=n.latLng(t)},onAdd:function(t){this._map=t,t.on("viewreset",this.update,this),this._initIcon(),this.update(),t.options.zoomAnimation&&t.options.markerZoomAnimation&&t.on("zoomanim",this._animateZoo
 m,this)},addTo:function(t){return t.addLayer(this),this},onRemove:function(t){this._removeIcon(),this.fire("remove"),t.off({viewreset:this.update,zoomanim:this._animateZoom},this),this._map=null},getLatLng:function(){return this._latlng},setLatLng:function(t){return this._latlng=n.latLng(t),this.update(),this.fire("move",{latlng:this._latlng})},setZIndexOffset:function(t){return this.options.zIndexOffset=t,this.update(),this},setIcon:function(t){return this._map&&this._removeIcon(),this.options.icon=t,this._map&&(this._initIcon(),this.update()),this},update:function(){if(this._icon){var t=this._map.latLngToLayerPoint(this._latlng).round();this._setPos(t)}return this},_initIcon:function(){var t=this.options,e=this._map,i=e.options.zoomAnimation&&e.options.markerZoomAnimation,o=i?"leaflet-zoom-animated":"leaflet-zoom-hide",s=!1;this._icon||(this._icon=t.icon.createIcon(),t.title&&(this._icon.title=t.title),this._initInteraction(),s=1>this.options.opacity,n.DomUtil.addClass(this._icon,
 o),t.riseOnHover&&n.DomEvent.on(this._icon,"mouseover",this._bringToFront,this).on(this._icon,"mouseout",this._resetZIndex,this)),this._shadow||(this._shadow=t.icon.createShadow(),this._shadow&&(n.DomUtil.addClass(this._shadow,o),s=1>this.options.opacity)),s&&this._updateOpacity();var a=this._map._panes;a.markerPane.appendChild(this._icon),this._shadow&&a.shadowPane.appendChild(this._shadow)},_removeIcon:function(){var t=this._map._panes;this.options.riseOnHover&&n.DomEvent.off(this._icon,"mouseover",this._bringToFront).off(this._icon,"mouseout",this._resetZIndex),t.markerPane.removeChild(this._icon),this._shadow&&t.shadowPane.removeChild(this._shadow),this._icon=this._shadow=null},_setPos:function(t){n.DomUtil.setPosition(this._icon,t),this._shadow&&n.DomUtil.setPosition(this._shadow,t),this._zIndex=t.y+this.options.zIndexOffset,this._resetZIndex()},_updateZIndex:function(t){this._icon.style.zIndex=this._zIndex+t},_animateZoom:function(t){var e=this._map._latLngToNewLayerPoint(this
 ._latlng,t.zoom,t.center);this._setPos(e)},_initInteraction:function(){if(this.options.clickable){var t=this._icon,e=["dblclick","mousedown","mouseover","mouseout","contextmenu"];n.DomUtil.addClass(t,"leaflet-clickable"),n.DomEvent.on(t,"click",this._onMouseClick,this);for(var i=0;e.length>i;i++)n.DomEvent.on(t,e[i],this._fireMouseEvent,this);n.Handler.MarkerDrag&&(this.dragging=new n.Handler.MarkerDrag(this),this.options.draggable&&this.dragging.enable())}},_onMouseClick:function(t){var e=this.dragging&&this.dragging.moved();(this.hasEventListeners(t.type)||e)&&n.DomEvent.stopPropagation(t),e||(this.dragging&&this.dragging._enabled||!this._map.dragging||!this._map.dragging.moved())&&this.fire(t.type,{originalEvent:t})},_fireMouseEvent:function(t){this.fire(t.type,{originalEvent:t}),"contextmenu"===t.type&&this.hasEventListeners(t.type)&&n.DomEvent.preventDefault(t),"mousedown"!==t.type&&n.DomEvent.stopPropagation(t)},setOpacity:function(t){this.options.opacity=t,this._map&&this._up
 dateOpacity()},_updateOpacity:function(){n.DomUtil.setOpacity(this._icon,this.options.opacity),this._shadow&&n.DomUtil.setOpacity(this._shadow,this.options.opacity)},_bringToFront:function(){this._updateZIndex(this.options.riseOffset)},_resetZIndex:function(){this._updateZIndex(0)}}),n.marker=function(t,e){return new n.Marker(t,e)},n.DivIcon=n.Icon.extend({options:{iconSize:new n.Point(12,12),className:"leaflet-div-icon"},createIcon:function(){var t=e.createElement("div"),i=this.options;return i.html&&(t.innerHTML=i.html),i.bgPos&&(t.style.backgroundPosition=-i.bgPos.x+"px "+-i.bgPos.y+"px"),this._setIconStyles(t,"icon"),t},createShadow:function(){return null}}),n.divIcon=function(t){return new n.DivIcon(t)},n.Map.mergeOptions({closePopupOnClick:!0}),n.Popup=n.Class.extend({includes:n.Mixin.Events,options:{minWidth:50,maxWidth:300,maxHeight:null,autoPan:!0,closeButton:!0,offset:new n.Point(0,6),autoPanPadding:new n.Point(5,5),className:"",zoomAnimation:!0},initialize:function(t,e){n
 .setOptions(this,t),this._source=e,this._animated=n.Browser.any3d&&this.options.zoomAnimation},onAdd:function(t){this._map=t,this._container||this._initLayout(),this._updateContent();var e=t.options.fadeAnimation;e&&n.DomUtil.setOpacity(this._container,0),t._panes.popupPane.appendChild(this._container),t.on("viewreset",this._updatePosition,this),this._animated&&t.on("zoomanim",this._zoomAnimation,this),t.options.closePopupOnClick&&t.on("preclick",this._close,this),this._update(),e&&n.DomUtil.setOpacity(this._container,1)},addTo:function(t){return t.addLayer(this),this},openOn:function(t){return t.openPopup(this),this},onRemove:function(t){t._panes.popupPane.removeChild(this._container),n.Util.falseFn(this._container.offsetWidth),t.off({viewreset:this._updatePosition,preclick:this._close,zoomanim:this._zoomAnimation},this),t.options.fadeAnimation&&n.DomUtil.setOpacity(this._container,0),this._map=null},setLatLng:function(t){return this._latlng=n.latLng(t),this._update(),this},setCont
 ent:function(t){return this._content=t,this._update(),this},_close:function(){var t=this._map;t&&(t._popup=null,t.removeLayer(this).fire("popupclose",{popup:this}))},_initLayout:function(){var t,e="leaflet-popup",i=e+" "+this.options.className+" leaflet-zoom-"+(this._animated?"animated":"hide"),o=this._container=n.DomUtil.create("div",i);this.options.closeButton&&(t=this._closeButton=n.DomUtil.create("a",e+"-close-button",o),t.href="#close",t.innerHTML="&#215;",n.DomEvent.on(t,"click",this._onCloseButtonClick,this));var s=this._wrapper=n.DomUtil.create("div",e+"-content-wrapper",o);n.DomEvent.disableClickPropagation(s),this._contentNode=n.DomUtil.create("div",e+"-content",s),n.DomEvent.on(this._contentNode,"mousewheel",n.DomEvent.stopPropagation),this._tipContainer=n.DomUtil.create("div",e+"-tip-container",o),this._tip=n.DomUtil.create("div",e+"-tip",this._tipContainer)},_update:function(){this._map&&(this._container.style.visibility="hidden",this._updateContent(),this._updateLayout
 (),this._updatePosition(),this._container.style.visibility="",this._adjustPan())},_updateContent:function(){if(this._content){if("string"==typeof this._content)this._contentNode.innerHTML=this._content;else{for(;this._contentNode.hasChildNodes();)this._contentNode.removeChild(this._contentNode.firstChild);this._contentNode.appendChild(this._content)}this.fire("contentupdate")}},_updateLayout:function(){var t=this._contentNode,e=t.style;e.width="",e.whiteSpace="nowrap";var i=t.offsetWidth;i=Math.min(i,this.options.maxWidth),i=Math.max(i,this.options.minWidth),e.width=i+1+"px",e.whiteSpace="",e.height="";var o=t.offsetHeight,s=this.options.maxHeight,a="leaflet-popup-scrolled";s&&o>s?(e.height=s+"px",n.DomUtil.addClass(t,a)):n.DomUtil.removeClass(t,a),this._containerWidth=this._container.offsetWidth},_updatePosition:function(){if(this._map){var t=this._map.latLngToLayerPoint(this._latlng),e=this._animated,i=this.options.offset;e&&n.DomUtil.setPosition(this._container,t),this._container
 Bottom=-i.y-(e?0:t.y),this._containerLeft=-Math.round(this._containerWidth/2)+i.x+(e?0:t.x),this._container.style.bottom=this._containerBottom+"px",this._container.style.left=this._containerLeft+"px"}},_zoomAnimation:function(t){var e=this._map._latLngToNewLayerPoint(this._latlng,t.zoom,t.center);n.DomUtil.setPosition(this._container,e)},_adjustPan:function(){if(this.options.autoPan){var t=this._map,e=this._container.offsetHeight,i=this._containerWidth,o=new n.Point(this._containerLeft,-e-this._containerBottom);this._animated&&o._add(n.DomUtil.getPosition(this._container));var s=t.layerPointToContainerPoint(o),a=this.options.autoPanPadding,r=t.getSize(),h=0,l=0;0>s.x&&(h=s.x-a.x),s.x+i>r.x&&(h=s.x+i-r.x+a.x),0>s.y&&(l=s.y-a.y),s.y+e>r.y&&(l=s.y+e-r.y+a.y),(h||l)&&t.panBy(new n.Point(h,l))}},_onCloseButtonClick:function(t){this._close(),n.DomEvent.stop(t)}}),n.popup=function(t,e){return new n.Popup(t,e)},n.Marker.include({openPopup:function(){return this._popup&&this._map&&(this._pop
 up.setLatLng(this._latlng),this._map.openPopup(this._popup)),this},closePopup:function(){return this._popup&&this._popup._close(),this},bindPopup:function(t,e){var i=n.point(this.options.icon.options.popupAnchor)||new n.Point(0,0);return i=i.add(n.Popup.prototype.options.offset),e&&e.offset&&(i=i.add(e.offset)),e=n.extend({offset:i},e),this._popup||this.on("click",this.openPopup,this).on("remove",this.closePopup,this).on("move",this._movePopup,this),this._popup=new n.Popup(e,this).setContent(t),this},unbindPopup:function(){return this._popup&&(this._popup=null,this.off("click",this.openPopup).off("remove",this.closePopup).off("move",this._movePopup)),this},_movePopup:function(t){this._popup.setLatLng(t.latlng)}}),n.Map.include({openPopup:function(t){return this.closePopup(),this._popup=t,this.addLayer(t).fire("popupopen",{popup:this._popup})},closePopup:function(){return this._popup&&this._popup._close(),this}}),n.LayerGroup=n.Class.extend({initialize:function(t){this._layers={};var
  e,i;if(t)for(e=0,i=t.length;i>e;e++)this.addLayer(t[e])},addLayer:function(t){var e=n.stamp(t);return this._layers[e]=t,this._map&&this._map.addLayer(t),this},removeLayer:function(t){var e=n.stamp(t);return delete this._layers[e],this._map&&this._map.removeLayer(t),this},clearLayers:function(){return this.eachLayer(this.removeLayer,this),this},invoke:function(t){var e,i,n=Array.prototype.slice.call(arguments,1);for(e in this._layers)this._layers.hasOwnProperty(e)&&(i=this._layers[e],i[t]&&i[t].apply(i,n));return this},onAdd:function(t){this._map=t,this.eachLayer(t.addLayer,t)},onRemove:function(t){this.eachLayer(t.removeLayer,t),this._map=null},addTo:function(t){return t.addLayer(this),this},eachLayer:function(t,e){for(var i in this._layers)this._layers.hasOwnProperty(i)&&t.call(e,this._layers[i])},setZIndex:function(t){return this.invoke("setZIndex",t)}}),n.layerGroup=function(t){return new n.LayerGroup(t)},n.FeatureGroup=n.LayerGroup.extend({includes:n.Mixin.Events,statics:{EVENT
 S:"click dblclick mouseover mouseout mousemove contextmenu"},addLayer:function(t){return this._layers[n.stamp(t)]?this:(t.on(n.FeatureGroup.EVENTS,this._propagateEvent,this),n.LayerGroup.prototype.addLayer.call(this,t),this._popupContent&&t.bindPopup&&t.bindPopup(this._popupContent,this._popupOptions),this.fire("layeradd",{layer:t}))},removeLayer:function(t){return t.off(n.FeatureGroup.EVENTS,this._propagateEvent,this),n.LayerGroup.prototype.removeLayer.call(this,t),this._popupContent&&this.invoke("unbindPopup"),this.fire("layerremove",{layer:t})},bindPopup:function(t,e){return this._popupContent=t,this._popupOptions=e,this.invoke("bindPopup",t,e)},setStyle:function(t){return this.invoke("setStyle",t)},bringToFront:function(){return this.invoke("bringToFront")},bringToBack:function(){return this.invoke("bringToBack")},getBounds:function(){var t=new n.LatLngBounds;return this.eachLayer(function(e){t.extend(e instanceof n.Marker?e.getLatLng():e.getBounds())}),t},_propagateEvent:functi
 on(t){t.layer=t.target,t.target=this,this.fire(t.type,t)}}),n.featureGroup=function(t){return new n.FeatureGroup(t)},n.Path=n.Class.extend({includes:[n.Mixin.Events],statics:{CLIP_PADDING:n.Browser.mobile?Math.max(0,Math.min(.5,(1280/Math.max(t.innerWidth,t.innerHeight)-1)/2)):.5},options:{stroke:!0,color:"#0033ff",dashArray:null,weight:5,opacity:.5,fill:!1,fillColor:null,fillOpacity:.2,clickable:!0},initialize:function(t){n.setOptions(this,t)},onAdd:function(t){this._map=t,this._container||(this._initElements(),this._initEvents()),this.projectLatlngs(),this._updatePath(),this._container&&this._map._pathRoot.appendChild(this._container),this.fire("add"),t.on({viewreset:this.projectLatlngs,moveend:this._updatePath},this)},addTo:function(t){return t.addLayer(this),this},onRemove:function(t){t._pathRoot.removeChild(this._container),this.fire("remove"),this._map=null,n.Browser.vml&&(this._container=null,this._stroke=null,this._fill=null),t.off({viewreset:this.projectLatlngs,moveend:this
 ._updatePath},this)},projectLatlngs:function(){},setStyle:function(t){return n.setOptions(this,t),this._container&&this._updateStyle(),this},redraw:function(){return this._map&&(this.projectLatlngs(),this._updatePath()),this}}),n.Map.include({_updatePathViewport:function(){var t=n.Path.CLIP_PADDING,e=this.getSize(),i=n.DomUtil.getPosition(this._mapPane),o=i.multiplyBy(-1)._subtract(e.multiplyBy(t)._round()),s=o.add(e.multiplyBy(1+2*t)._round());this._pathViewport=new n.Bounds(o,s)}}),n.Path.SVG_NS="http://www.w3.org/2000/svg",n.Browser.svg=!(!e.createElementNS||!e.createElementNS(n.Path.SVG_NS,"svg").createSVGRect),n.Path=n.Path.extend({statics:{SVG:n.Browser.svg},bringToFront:function(){var t=this._map._pathRoot,e=this._container;return e&&t.lastChild!==e&&t.appendChild(e),this},bringToBack:function(){var t=this._map._pathRoot,e=this._container,i=t.firstChild;return e&&i!==e&&t.insertBefore(e,i),this},getPathString:function(){},_createElement:function(t){return e.createElementNS(n.
 Path.SVG_NS,t)},_initElements:function(){this._map._initPathRoot(),this._initPath(),this._initStyle()},_initPath:function(){this._container=this._createElement("g"),this._path=this._createElement("path"),this._container.appendChild(this._path)},_initStyle:function(){this.options.stroke&&(this._path.setAttribute("stroke-linejoin","round"),this._path.setAttribute("stroke-linecap","round")),this.options.fill&&this._path.setAttribute("fill-rule","evenodd"),this._updateStyle()},_updateStyle:function(){this.options.stroke?(this._path.setAttribute("stroke",this.options.color),this._path.setAttribute("stroke-opacity",this.options.opacity),this._path.setAttribute("stroke-width",this.options.weight),this.options.dashArray?this._path.setAttribute("stroke-dasharray",this.options.dashArray):this._path.removeAttribute("stroke-dasharray")):this._path.setAttribute("stroke","none"),this.options.fill?(this._path.setAttribute("fill",this.options.fillColor||this.options.color),this._path.setAttribute("
 fill-opacity",this.options.fillOpacity)):this._path.setAttribute("fill","none")},_updatePath:function(){var t=this.getPathString();t||(t="M0 0"),this._path.setAttribute("d",t)},_initEvents:function(){if(this.options.clickable){(n.Browser.svg||!n.Browser.vml)&&this._path.setAttribute("class","leaflet-clickable"),n.DomEvent.on(this._container,"click",this._onMouseClick,this);for(var t=["dblclick","mousedown","mouseover","mouseout","mousemove","contextmenu"],e=0;t.length>e;e++)n.DomEvent.on(this._container,t[e],this._fireMouseEvent,this)}},_onMouseClick:function(t){this._map.dragging&&this._map.dragging.moved()||this._fireMouseEvent(t)},_fireMouseEvent:function(t){if(this.hasEventListeners(t.type)){var e=this._map,i=e.mouseEventToContainerPoint(t),o=e.containerPointToLayerPoint(i),s=e.layerPointToLatLng(o);this.fire(t.type,{latlng:s,layerPoint:o,containerPoint:i,originalEvent:t}),"contextmenu"===t.type&&n.DomEvent.preventDefault(t),"mousemove"!==t.type&&n.DomEvent.stopPropagation(t)}}}
 ),n.Map.include({_initPathRoot:function(){this._pathRoot||(this._pathRoot=n.Path.prototype._createElement("svg"),this._panes.overlayPane.appendChild(this._pathRoot),this.options.zoomAnimation&&n.Browser.any3d?(this._pathRoot.setAttribute("class"," leaflet-zoom-animated"),this.on({zoomanim:this._animatePathZoom,zoomend:this._endPathZoom})):this._pathRoot.setAttribute("class"," leaflet-zoom-hide"),this.on("moveend",this._updateSvgViewport),this._updateSvgViewport())},_animatePathZoom:function(t){var e=this.getZoomScale(t.zoom),i=this._getCenterOffset(t.center)._multiplyBy(-e)._add(this._pathViewport.min);this._pathRoot.style[n.DomUtil.TRANSFORM]=n.DomUtil.getTranslateString(i)+" scale("+e+") ",this._pathZooming=!0},_endPathZoom:function(){this._pathZooming=!1},_updateSvgViewport:function(){if(!this._pathZooming){this._updatePathViewport();var t=this._pathViewport,e=t.min,i=t.max,o=i.x-e.x,s=i.y-e.y,a=this._pathRoot,r=this._panes.overlayPane;n.Browser.mobileWebkit&&r.removeChild(a),n.D
 omUtil.setPosition(a,e),a.setAttribute("width",o),a.setAttribute("height",s),a.setAttribute("viewBox",[e.x,e.y,o,s].join(" ")),n.Browser.mobileWebkit&&r.appendChild(a)}}}),n.Path.include({bindPopup:function(t,e){return(!this._popup||e)&&(this._popup=new n.Popup(e,this)),this._popup.setContent(t),this._popupHandlersAdded||(this.on("click",this._openPopup,this).on("remove",this.closePopup,this),this._popupHandlersAdded=!0),this},unbindPopup:function(){return this._popup&&(this._popup=null,this.off("click",this._openPopup).off("remove",this.closePopup),this._popupHandlersAdded=!1),this},openPopup:function(t){return this._popup&&(t=t||this._latlng||this._latlngs[Math.floor(this._latlngs.length/2)],this._openPopup({latlng:t})),this},closePopup:function(){return this._popup&&this._popup._close(),this},_openPopup:function(t){this._popup.setLatLng(t.latlng),this._map.openPopup(this._popup)}}),n.Browser.vml=!n.Browser.svg&&function(){try{var t=e.createElement("div");t.innerHTML='<v:shape adj
 ="1"/>';var i=t.firstChild;return i.style.behavior="url(#default#VML)",i&&"object"==typeof i.adj}catch(n){return!1}}(),n.Path=n.Browser.svg||!n.Browser.vml?n.Path:n.Path.extend({statics:{VML:!0,CLIP_PADDING:.02},_createElement:function(){try{return e.namespaces.add("lvml","urn:schemas-microsoft-com:vml"),function(t){return e.createElement("<lvml:"+t+' class="lvml">')}}catch(t){return function(t){return e.createElement("<"+t+' xmlns="urn:schemas-microsoft.com:vml" class="lvml">')}}}(),_initPath:function(){var t=this._container=this._createElement("shape");n.DomUtil.addClass(t,"leaflet-vml-shape"),this.options.clickable&&n.DomUtil.addClass(t,"leaflet-clickable"),t.coordsize="1 1",this._path=this._createElement("path"),t.appendChild(this._path),this._map._pathRoot.appendChild(t)},_initStyle:function(){this._updateStyle()},_updateStyle:function(){var t=this._stroke,e=this._fill,i=this.options,n=this._container;n.stroked=i.stroke,n.filled=i.fill,i.stroke?(t||(t=this._stroke=this._createE
 lement("stroke"),t.endcap="round",n.appendChild(t)),t.weight=i.weight+"px",t.color=i.color,t.opacity=i.opacity,t.dashStyle=i.dashArray?i.dashArray instanceof Array?i.dashArray.join(" "):i.dashArray.replace(/ *, */g," "):""):t&&(n.removeChild(t),this._stroke=null),i.fill?(e||(e=this._fill=this._createElement("fill"),n.appendChild(e)),e.color=i.fillColor||i.color,e.opacity=i.fillOpacity):e&&(n.removeChild(e),this._fill=null)},_updatePath:function(){var t=this._container.style;t.display="none",this._path.v=this.getPathString()+" ",t.display=""}}),n.Map.include(n.Browser.svg||!n.Browser.vml?{}:{_initPathRoot:function(){if(!this._pathRoot){var t=this._pathRoot=e.createElement("div");t.className="leaflet-vml-container",this._panes.overlayPane.appendChild(t),this.on("moveend",this._updatePathViewport),this._updatePathViewport()}}}),n.Browser.canvas=function(){return!!e.createElement("canvas").getContext}(),n.Path=n.Path.SVG&&!t.L_PREFER_CANVAS||!n.Browser.canvas?n.Path:n.Path.extend({stati
 cs:{CANVAS:!0,SVG:!1},redraw:function(){return this._map&&(this.projectLatlngs(),this._requestUpdate()),this},setStyle:function(t){return n.setOptions(this,t),this._map&&(this._updateStyle(),this._requestUpdate()),this},onRemove:function(t){t.off("viewreset",this.projectLatlngs,this).off("moveend",this._updatePath,this),this.options.clickable&&this._map.off("click",this._onClick,this),this._requestUpdate(),this._map=null},_requestUpdate:function(){this._map&&!n.Path._updateRequest&&(n.Path._updateRequest=n.Util.requestAnimFrame(this._fireMapMoveEnd,this._map))},_fireMapMoveEnd:function(){n.Path._updateRequest=null,this.fire("moveend")},_initElements:function(){this._map._initPathRoot(),this._ctx=this._map._canvasCtx},_updateStyle:function(){var t=this.options;t.stroke&&(this._ctx.lineWidth=t.weight,this._ctx.strokeStyle=t.color),t.fill&&(this._ctx.fillStyle=t.fillColor||t.color)},_drawPath:function(){var t,e,i,o,s,a;for(this._ctx.beginPath(),t=0,i=this._parts.length;i>t;t++){for(e=0
 ,o=this._parts[t].length;o>e;e++)s=this._parts[t][e],a=(0===e?"move":"line")+"To",this._ctx[a](s.x,s.y);this instanceof n.Polygon&&this._ctx.closePath()}},_checkIfEmpty:function(){return!this._parts.length},_updatePath:function(){if(!this._checkIfEmpty()){var t=this._ctx,e=this.options;this._drawPath(),t.save(),this._updateStyle(),e.fill&&(t.globalAlpha=e.fillOpacity,t.fill()),e.stroke&&(t.globalAlpha=e.opacity,t.stroke()),t.restore()}},_initEvents:function(){this.options.clickable&&this._map.on("click",this._onClick,this)},_onClick:function(t){this._containsPoint(t.layerPoint)&&this.fire("click",{latlng:t.latlng,layerPoint:t.layerPoint,containerPoint:t.containerPoint,originalEvent:t})}}),n.Map.include(n.Path.SVG&&!t.L_PREFER_CANVAS||!n.Browser.canvas?{}:{_initPathRoot:function(){var t,i=this._pathRoot;i||(i=this._pathRoot=e.createElement("canvas"),i.style.position="absolute",t=this._canvasCtx=i.getContext("2d"),t.lineCap="round",t.lineJoin="round",this._panes.overlayPane.appendChil
 d(i),this.options.zoomAnimation&&(this._pathRoot.className="leaflet-zoom-animated",this.on("zoomanim",this._animatePathZoom),this.on("zoomend",this._endPathZoom)),this.on("moveend",this._updateCanvasViewport),this._updateCanvasViewport())},_updateCanvasViewport:function(){if(!this._pathZooming){this._updatePathViewport();var t=this._pathViewport,e=t.min,i=t.max.subtract(e),o=this._pathRoot;n.DomUtil.setPosition(o,e),o.width=i.x,o.height=i.y,o.getContext("2d").translate(-e.x,-e.y)}}}),n.LineUtil={simplify:function(t,e){if(!e||!t.length)return t.slice();var i=e*e;return t=this._reducePoints(t,i),t=this._simplifyDP(t,i)},pointToSegmentDistance:function(t,e,i){return Math.sqrt(this._sqClosestPointOnSegment(t,e,i,!0))},closestPointOnSegment:function(t,e,i){return this._sqClosestPointOnSegment(t,e,i)},_simplifyDP:function(t,e){var n=t.length,o=typeof Uint8Array!=i+""?Uint8Array:Array,s=new o(n);s[0]=s[n-1]=1,this._simplifyDPStep(t,s,e,0,n-1);var a,r=[];for(a=0;n>a;a++)s[a]&&r.push(t[a]);r
 eturn r},_simplifyDPStep:function(t,e,i,n,o){var s,a,r,h=0;for(a=n+1;o-1>=a;a++)r=this._sqClosestPointOnSegment(t[a],t[n],t[o],!0),r>h&&(s=a,h=r);h>i&&(e[s]=1,this._simplifyDPStep(t,e,i,n,s),this._simplifyDPStep(t,e,i,s,o))},_reducePoints:function(t,e){for(var i=[t[0]],n=1,o=0,s=t.length;s>n;n++)this._sqDist(t[n],t[o])>e&&(i.push(t[n]),o=n);return s-1>o&&i.push(t[s-1]),i},clipSegment:function(t,e,i,n){var o,s,a,r=n?this._lastCode:this._getBitCode(t,i),h=this._getBitCode(e,i);for(this._lastCode=h;;){if(!(r|h))return[t,e];if(r&h)return!1;o=r||h,s=this._getEdgeIntersection(t,e,o,i),a=this._getBitCode(s,i),o===r?(t=s,r=a):(e=s,h=a)}},_getEdgeIntersection:function(t,e,o,s){var a=e.x-t.x,r=e.y-t.y,h=s.min,l=s.max;return 8&o?new n.Point(t.x+a*(l.y-t.y)/r,l.y):4&o?new n.Point(t.x+a*(h.y-t.y)/r,h.y):2&o?new n.Point(l.x,t.y+r*(l.x-t.x)/a):1&o?new n.Point(h.x,t.y+r*(h.x-t.x)/a):i},_getBitCode:function(t,e){var i=0;return t.x<e.min.x?i|=1:t.x>e.max.x&&(i|=2),t.y<e.min.y?i|=4:t.y>e.max.y&&(i|=8)
 ,i},_sqDist:function(t,e){var i=e.x-t.x,n=e.y-t.y;return i*i+n*n},_sqClosestPointOnSegment:function(t,e,i,o){var s,a=e.x,r=e.y,h=i.x-a,l=i.y-r,u=h*h+l*l;return u>0&&(s=((t.x-a)*h+(t.y-r)*l)/u,s>1?(a=i.x,r=i.y):s>0&&(a+=h*s,r+=l*s)),h=t.x-a,l=t.y-r,o?h*h+l*l:new n.Point(a,r)}},n.Polyline=n.Path.extend({initialize:function(t,e){n.Path.prototype.initialize.call(this,e),this._latlngs=this._convertLatLngs(t)},options:{smoothFactor:1,noClip:!1},projectLatlngs:function(){this._originalPoints=[];for(var t=0,e=this._latlngs.length;e>t;t++)this._originalPoints[t]=this._map.latLngToLayerPoint(this._latlngs[t])},getPathString:function(){for(var t=0,e=this._parts.length,i="";e>t;t++)i+=this._getPathPartStr(this._parts[t]);return i},getLatLngs:function(){return this._latlngs},setLatLngs:function(t){return this._latlngs=this._convertLatLngs(t),this.redraw()},addLatLng:function(t){return this._latlngs.push(n.latLng(t)),this.redraw()},spliceLatLngs:function(){var t=[].splice.apply(this._latlngs,argu
 ments);return this._convertLatLngs(this._latlngs),this.redraw(),t},closestLayerPoint:function(t){for(var e,i,o=1/0,s=this._parts,a=null,r=0,h=s.length;h>r;r++)for(var l=s[r],u=1,c=l.length;c>u;u++){e=l[u-1],i=l[u];
+var _=n.LineUtil._sqClosestPointOnSegment(t,e,i,!0);o>_&&(o=_,a=n.LineUtil._sqClosestPointOnSegment(t,e,i))}return a&&(a.distance=Math.sqrt(o)),a},getBounds:function(){var t,e,i=new n.LatLngBounds,o=this.getLatLngs();for(t=0,e=o.length;e>t;t++)i.extend(o[t]);return i},_convertLatLngs:function(t){var e,i;for(e=0,i=t.length;i>e;e++){if(n.Util.isArray(t[e])&&"number"!=typeof t[e][0])return;t[e]=n.latLng(t[e])}return t},_initEvents:function(){n.Path.prototype._initEvents.call(this)},_getPathPartStr:function(t){for(var e,i=n.Path.VML,o=0,s=t.length,a="";s>o;o++)e=t[o],i&&e._round(),a+=(o?"L":"M")+e.x+" "+e.y;return a},_clipPoints:function(){var t,e,o,s=this._originalPoints,a=s.length;if(this.options.noClip)return this._parts=[s],i;this._parts=[];var r=this._parts,h=this._map._pathViewport,l=n.LineUtil;for(t=0,e=0;a-1>t;t++)o=l.clipSegment(s[t],s[t+1],h,t),o&&(r[e]=r[e]||[],r[e].push(o[0]),(o[1]!==s[t+1]||t===a-2)&&(r[e].push(o[1]),e++))},_simplifyPoints:function(){for(var t=this._parts,e
 =n.LineUtil,i=0,o=t.length;o>i;i++)t[i]=e.simplify(t[i],this.options.smoothFactor)},_updatePath:function(){this._map&&(this._clipPoints(),this._simplifyPoints(),n.Path.prototype._updatePath.call(this))}}),n.polyline=function(t,e){return new n.Polyline(t,e)},n.PolyUtil={},n.PolyUtil.clipPolygon=function(t,e){var i,o,s,a,r,h,l,u,c,_=[1,4,2,8],d=n.LineUtil;for(o=0,l=t.length;l>o;o++)t[o]._code=d._getBitCode(t[o],e);for(a=0;4>a;a++){for(u=_[a],i=[],o=0,l=t.length,s=l-1;l>o;s=o++)r=t[o],h=t[s],r._code&u?h._code&u||(c=d._getEdgeIntersection(h,r,u,e),c._code=d._getBitCode(c,e),i.push(c)):(h._code&u&&(c=d._getEdgeIntersection(h,r,u,e),c._code=d._getBitCode(c,e),i.push(c)),i.push(r));t=i}return t},n.Polygon=n.Polyline.extend({options:{fill:!0},initialize:function(t,e){n.Polyline.prototype.initialize.call(this,t,e),t&&n.Util.isArray(t[0])&&"number"!=typeof t[0][0]&&(this._latlngs=this._convertLatLngs(t[0]),this._holes=t.slice(1))},projectLatlngs:function(){if(n.Polyline.prototype.projectLatln
 gs.call(this),this._holePoints=[],this._holes){var t,e,i,o;for(t=0,i=this._holes.length;i>t;t++)for(this._holePoints[t]=[],e=0,o=this._holes[t].length;o>e;e++)this._holePoints[t][e]=this._map.latLngToLayerPoint(this._holes[t][e])}},_clipPoints:function(){var t=this._originalPoints,e=[];if(this._parts=[t].concat(this._holePoints),!this.options.noClip){for(var i=0,o=this._parts.length;o>i;i++){var s=n.PolyUtil.clipPolygon(this._parts[i],this._map._pathViewport);s.length&&e.push(s)}this._parts=e}},_getPathPartStr:function(t){var e=n.Polyline.prototype._getPathPartStr.call(this,t);return e+(n.Browser.svg?"z":"x")}}),n.polygon=function(t,e){return new n.Polygon(t,e)},function(){function t(t){return n.FeatureGroup.extend({initialize:function(t,e){this._layers={},this._options=e,this.setLatLngs(t)},setLatLngs:function(e){var i=0,n=e.length;for(this.eachLayer(function(t){n>i?t.setLatLngs(e[i++]):this.removeLayer(t)},this);n>i;)this.addLayer(new t(e[i++],this._options));return this}})}n.Mult
 iPolyline=t(n.Polyline),n.MultiPolygon=t(n.Polygon),n.multiPolyline=function(t,e){return new n.MultiPolyline(t,e)},n.multiPolygon=function(t,e){return new n.MultiPolygon(t,e)}}(),n.Rectangle=n.Polygon.extend({initialize:function(t,e){n.Polygon.prototype.initialize.call(this,this._boundsToLatLngs(t),e)},setBounds:function(t){this.setLatLngs(this._boundsToLatLngs(t))},_boundsToLatLngs:function(t){return t=n.latLngBounds(t),[t.getSouthWest(),t.getNorthWest(),t.getNorthEast(),t.getSouthEast()]}}),n.rectangle=function(t,e){return new n.Rectangle(t,e)},n.Circle=n.Path.extend({initialize:function(t,e,i){n.Path.prototype.initialize.call(this,i),this._latlng=n.latLng(t),this._mRadius=e},options:{fill:!0},setLatLng:function(t){return this._latlng=n.latLng(t),this.redraw()},setRadius:function(t){return this._mRadius=t,this.redraw()},projectLatlngs:function(){var t=this._getLngRadius(),e=new n.LatLng(this._latlng.lat,this._latlng.lng-t),i=this._map.latLngToLayerPoint(e);this._point=this._map.la
 tLngToLayerPoint(this._latlng),this._radius=Math.max(Math.round(this._point.x-i.x),1)},getBounds:function(){var t=this._getLngRadius(),e=360*(this._mRadius/40075017),i=this._latlng,o=new n.LatLng(i.lat-e,i.lng-t),s=new n.LatLng(i.lat+e,i.lng+t);return new n.LatLngBounds(o,s)},getLatLng:function(){return this._latlng},getPathString:function(){var t=this._point,e=this._radius;return this._checkIfEmpty()?"":n.Browser.svg?"M"+t.x+","+(t.y-e)+"A"+e+","+e+",0,1,1,"+(t.x-.1)+","+(t.y-e)+" z":(t._round(),e=Math.round(e),"AL "+t.x+","+t.y+" "+e+","+e+" 0,"+23592600)},getRadius:function(){return this._mRadius},_getLatRadius:function(){return 360*(this._mRadius/40075017)},_getLngRadius:function(){return this._getLatRadius()/Math.cos(n.LatLng.DEG_TO_RAD*this._latlng.lat)},_checkIfEmpty:function(){if(!this._map)return!1;var t=this._map._pathViewport,e=this._radius,i=this._point;return i.x-e>t.max.x||i.y-e>t.max.y||i.x+e<t.min.x||i.y+e<t.min.y}}),n.circle=function(t,e,i){return new n.Circle(t,e,i
 )},n.CircleMarker=n.Circle.extend({options:{radius:10,weight:2},initialize:function(t,e){n.Circle.prototype.initialize.call(this,t,null,e),this._radius=this.options.radius},projectLatlngs:function(){this._point=this._map.latLngToLayerPoint(this._latlng)},_updateStyle:function(){n.Circle.prototype._updateStyle.call(this),this.setRadius(this.options.radius)},setRadius:function(t){return this._radius=t,this.redraw()}}),n.circleMarker=function(t,e){return new n.CircleMarker(t,e)},n.Polyline.include(n.Path.CANVAS?{_containsPoint:function(t,e){var i,o,s,a,r,h,l,u=this.options.weight/2;for(n.Browser.touch&&(u+=10),i=0,a=this._parts.length;a>i;i++)for(l=this._parts[i],o=0,r=l.length,s=r-1;r>o;s=o++)if((e||0!==o)&&(h=n.LineUtil.pointToSegmentDistance(t,l[s],l[o]),u>=h))return!0;return!1}}:{}),n.Polygon.include(n.Path.CANVAS?{_containsPoint:function(t){var e,i,o,s,a,r,h,l,u=!1;if(n.Polyline.prototype._containsPoint.call(this,t,!0))return!0;for(s=0,h=this._parts.length;h>s;s++)for(e=this._part
 s[s],a=0,l=e.length,r=l-1;l>a;r=a++)i=e[a],o=e[r],i.y>t.y!=o.y>t.y&&t.x<(o.x-i.x)*(t.y-i.y)/(o.y-i.y)+i.x&&(u=!u);return u}}:{}),n.Circle.include(n.Path.CANVAS?{_drawPath:function(){var t=this._point;this._ctx.beginPath(),this._ctx.arc(t.x,t.y,this._radius,0,2*Math.PI,!1)},_containsPoint:function(t){var e=this._point,i=this.options.stroke?this.options.weight/2:0;return t.distanceTo(e)<=this._radius+i}}:{}),n.GeoJSON=n.FeatureGroup.extend({initialize:function(t,e){n.setOptions(this,e),this._layers={},t&&this.addData(t)},addData:function(t){var e,i,o=n.Util.isArray(t)?t:t.features;if(o){for(e=0,i=o.length;i>e;e++)(o[e].geometries||o[e].geometry)&&this.addData(o[e]);return this}var s=this.options;if(!s.filter||s.filter(t)){var a=n.GeoJSON.geometryToLayer(t,s.pointToLayer);return a.feature=t,a.defaultOptions=a.options,this.resetStyle(a),s.onEachFeature&&s.onEachFeature(t,a),this.addLayer(a)}},resetStyle:function(t){var e=this.options.style;e&&(n.Util.extend(t.options,t.defaultOptions),t
 his._setLayerStyle(t,e))},setStyle:function(t){this.eachLayer(function(e){this._setLayerStyle(e,t)},this)},_setLayerStyle:function(t,e){"function"==typeof e&&(e=e(t.feature)),t.setStyle&&t.setStyle(e)}}),n.extend(n.GeoJSON,{geometryToLayer:function(t,e){var i,o,s,a,r,h="Feature"===t.type?t.geometry:t,l=h.coordinates,u=[];switch(h.type){case"Point":return i=this.coordsToLatLng(l),e?e(t,i):new n.Marker(i);case"MultiPoint":for(s=0,a=l.length;a>s;s++)i=this.coordsToLatLng(l[s]),r=e?e(t,i):new n.Marker(i),u.push(r);return new n.FeatureGroup(u);case"LineString":return o=this.coordsToLatLngs(l),new n.Polyline(o);case"Polygon":return o=this.coordsToLatLngs(l,1),new n.Polygon(o);case"MultiLineString":return o=this.coordsToLatLngs(l,1),new n.MultiPolyline(o);case"MultiPolygon":return o=this.coordsToLatLngs(l,2),new n.MultiPolygon(o);case"GeometryCollection":for(s=0,a=h.geometries.length;a>s;s++)r=this.geometryToLayer({geometry:h.geometries[s],type:"Feature",properties:t.properties},e),u.push(
 r);return new n.FeatureGroup(u);default:throw Error("Invalid GeoJSON object.")}},coordsToLatLng:function(t,e){var i=parseFloat(t[e?0:1]),o=parseFloat(t[e?1:0]);return new n.LatLng(i,o)},coordsToLatLngs:function(t,e,i){var n,o,s,a=[];for(o=0,s=t.length;s>o;o++)n=e?this.coordsToLatLngs(t[o],e-1,i):this.coordsToLatLng(t[o],i),a.push(n);return a}}),n.geoJson=function(t,e){return new n.GeoJSON(t,e)},n.DomEvent={addListener:function(t,e,o,s){var a,r,h,l=n.stamp(o),u="_leaflet_"+e+l;return t[u]?this:(a=function(e){return o.call(s||t,e||n.DomEvent._getEvent())},n.Browser.msTouch&&0===e.indexOf("touch")?this.addMsTouchListener(t,e,a,l):(n.Browser.touch&&"dblclick"===e&&this.addDoubleTapListener&&this.addDoubleTapListener(t,a,l),"addEventListener"in t?"mousewheel"===e?(t.addEventListener("DOMMouseScroll",a,!1),t.addEventListener(e,a,!1)):"mouseenter"===e||"mouseleave"===e?(r=a,h="mouseenter"===e?"mouseover":"mouseout",a=function(e){return n.DomEvent._checkMouse(t,e)?r(e):i},t.addEventListener
 (h,a,!1)):t.addEventListener(e,a,!1):"attachEvent"in t&&t.attachEvent("on"+e,a),t[u]=a,this))},removeListener:function(t,e,i){var o=n.stamp(i),s="_leaflet_"+e+o,a=t[s];if(a)return n.Browser.msTouch&&0===e.indexOf("touch")?this.removeMsTouchListener(t,e,o):n.Browser.touch&&"dblclick"===e&&this.removeDoubleTapListener?this.removeDoubleTapListener(t,o):"removeEventListener"in t?"mousewheel"===e?(t.removeEventListener("DOMMouseScroll",a,!1),t.removeEventListener(e,a,!1)):"mouseenter"===e||"mouseleave"===e?t.removeEventListener("mouseenter"===e?"mouseover":"mouseout",a,!1):t.removeEventListener(e,a,!1):"detachEvent"in t&&t.detachEvent("on"+e,a),t[s]=null,this},stopPropagation:function(t){return t.stopPropagation?t.stopPropagation():t.cancelBubble=!0,this},disableClickPropagation:function(t){for(var e=n.DomEvent.stopPropagation,i=n.Draggable.START.length-1;i>=0;i--)n.DomEvent.addListener(t,n.Draggable.START[i],e);return n.DomEvent.addListener(t,"click",e).addListener(t,"dblclick",e)},prev
 entDefault:function(t){return t.preventDefault?t.preventDefault():t.returnValue=!1,this},stop:function(t){return n.DomEvent.preventDefault(t).stopPropagation(t)},getMousePosition:function(t,i){var o=e.body,s=e.documentElement,a=t.pageX?t.pageX:t.clientX+o.scrollLeft+s.scrollLeft,r=t.pageY?t.pageY:t.clientY+o.scrollTop+s.scrollTop,h=new n.Point(a,r);return i?h._subtract(n.DomUtil.getViewportOffset(i)):h},getWheelDelta:function(t){var e=0;return t.wheelDelta&&(e=t.wheelDelta/120),t.detail&&(e=-t.detail/3),e},_checkMouse:function(t,e){var i=e.relatedTarget;if(!i)return!0;try{for(;i&&i!==t;)i=i.parentNode}catch(n){return!1}return i!==t},_getEvent:function(){var e=t.event;if(!e)for(var i=arguments.callee.caller;i&&(e=i.arguments[0],!e||t.Event!==e.constructor);)i=i.caller;return e}},n.DomEvent.on=n.DomEvent.addListener,n.DomEvent.off=n.DomEvent.removeListener,n.Draggable=n.Class.extend({includes:n.Mixin.Events,statics:{START:n.Browser.touch?["touchstart","mousedown"]:["mousedown"],END:{m
 ousedown:"mouseup",touchstart:"touchend",MSPointerDown:"touchend"},MOVE:{mousedown:"mousemove",touchstart:"touchmove",MSPointerDown:"touchmove"},TAP_TOLERANCE:15},initialize:function(t,e,i){this._element=t,this._dragStartTarget=e||t,this._longPress=i&&!n.Browser.msTouch},enable:function(){if(!this._enabled){for(var t=n.Draggable.START.length-1;t>=0;t--)n.DomEvent.on(this._dragStartTarget,n.Draggable.START[t],this._onDown,this);this._enabled=!0}},disable:function(){if(this._enabled){for(var t=n.Draggable.START.length-1;t>=0;t--)n.DomEvent.off(this._dragStartTarget,n.Draggable.START[t],this._onDown,this);this._enabled=!1,this._moved=!1}},_onDown:function(t){if(!(!n.Browser.touch&&t.shiftKey||1!==t.which&&1!==t.button&&!t.touches||(n.DomEvent.preventDefault(t),n.DomEvent.stopPropagation(t),n.Draggable._disabled))){if(this._simulateClick=!0,t.touches&&t.touches.length>1)return this._simulateClick=!1,clearTimeout(this._longPressTimeout),i;var o=t.touches&&1===t.touches.length?t.touches[0
 ]:t,s=o.target;n.Browser.touch&&"a"===s.tagName.toLowerCase()&&n.DomUtil.addClass(s,"leaflet-active"),this._moved=!1,this._moving||(this._startPoint=new n.Point(o.clientX,o.clientY),this._startPos=this._newPos=n.DomUtil.getPosition(this._element),t.touches&&1===t.touches.length&&n.Browser.touch&&this._longPress&&(this._longPressTimeout=setTimeout(n.bind(function(){var t=this._newPos&&this._newPos.distanceTo(this._startPos)||0;n.Draggable.TAP_TOLERANCE>t&&(this._simulateClick=!1,this._onUp(),this._simulateEvent("contextmenu",o))},this),1e3)),n.DomEvent.on(e,n.Draggable.MOVE[t.type],this._onMove,this),n.DomEvent.on(e,n.Draggable.END[t.type],this._onUp,this))}},_onMove:function(t){if(!(t.touches&&t.touches.length>1)){var e=t.touches&&1===t.touches.length?t.touches[0]:t,i=new n.Point(e.clientX,e.clientY),o=i.subtract(this._startPoint);(o.x||o.y)&&(n.DomEvent.preventDefault(t),this._moved||(this.fire("dragstart"),this._moved=!0,this._startPos=n.DomUtil.getPosition(this._element).subtract
 (o),n.Browser.touch||(n.DomUtil.disableTextSelection(),this._setMovingCursor())),this._newPos=this._startPos.add(o),this._moving=!0,n.Util.cancelAnimFrame(this._animRequest),this._animRequest=n.Util.requestAnimFrame(this._updatePosition,this,!0,this._dragStartTarget))}},_updatePosition:function(){this.fire("predrag"),n.DomUtil.setPosition(this._element,this._newPos),this.fire("drag")},_onUp:function(t){var i;if(clearTimeout(this._longPressTimeout),this._simulateClick&&t.changedTouches){var o=t.changedTouches[0],s=o.target,a=this._newPos&&this._newPos.distanceTo(this._startPos)||0;"a"===s.tagName.toLowerCase()&&n.DomUtil.removeClass(s,"leaflet-active"),n.Draggable.TAP_TOLERANCE>a&&(i=o)}n.Browser.touch||(n.DomUtil.enableTextSelection(),this._restoreCursor());for(var r in n.Draggable.MOVE)n.Draggable.MOVE.hasOwnProperty(r)&&(n.DomEvent.off(e,n.Draggable.MOVE[r],this._onMove),n.DomEvent.off(e,n.Draggable.END[r],this._onUp));this._moved&&(n.Util.cancelAnimFrame(this._animRequest),this.f
 ire("dragend")),this._moving=!1,i&&(this._moved=!1,this._simulateEvent("click",i))},_setMovingCursor:function(){n.DomUtil.addClass(e.body,"leaflet-dragging")},_restoreCursor:function(){n.DomUtil.removeClass(e.body,"leaflet-dragging")},_simulateEvent:function(i,n){var o=e.createEvent("MouseEvents");o.initMouseEvent(i,!0,!0,t,1,n.screenX,n.screenY,n.clientX,n.clientY,!1,!1,!1,!1,0,null),n.target.dispatchEvent(o)}}),n.Handler=n.Class.extend({initialize:function(t){this._map=t},enable:function(){this._enabled||(this._enabled=!0,this.addHooks())},disable:function(){this._enabled&&(this._enabled=!1,this.removeHooks())},enabled:function(){return!!this._enabled}}),n.Map.mergeOptions({dragging:!0,inertia:!n.Browser.android23,inertiaDeceleration:3400,inertiaMaxSpeed:1/0,inertiaThreshold:n.Browser.touch?32:18,easeLinearity:.25,longPress:!0,worldCopyJump:!1}),n.Map.Drag=n.Handler.extend({addHooks:function(){if(!this._draggable){var t=this._map;this._draggable=new n.Draggable(t._mapPane,t._conta
 iner,t.options.longPress),this._draggable.on({dragstart:this._onDragStart,drag:this._onDrag,dragend:this._onDragEnd},this),t.options.worldCopyJump&&(this._draggable.on("predrag",this._onPreDrag,this),t.on("viewreset",this._onViewReset,this))}this._draggable.enable()},removeHooks:function(){this._draggable.disable()},moved:function(){return this._draggable&&this._draggable._moved},_onDragStart:function(){var t=this._map;t._panAnim&&t._panAnim.stop(),t.fire("movestart").fire("dragstart"),t.options.inertia&&(this._positions=[],this._times=[])},_onDrag:function(){if(this._map.options.inertia){var t=this._lastTime=+new Date,e=this._lastPos=this._draggable._newPos;this._positions.push(e),this._times.push(t),t-this._times[0]>200&&(this._positions.shift(),this._times.shift())}this._map.fire("move").fire("drag")},_onViewReset:function(){var t=this._map.getSize()._divideBy(2),e=this._map.latLngToLayerPoint(new n.LatLng(0,0));this._initialWorldOffset=e.subtract(t).x,this._worldWidth=this._map.
 project(new n.LatLng(0,180)).x},_onPreDrag:function(){var t=this._worldWidth,e=Math.round(t/2),i=this._initialWorldOffset,n=this._draggable._newPos.x,o=(n-e+i)%t+e-i,s=(n+e+i)%t-e-i,a=Math.abs(o+i)<Math.abs(s+i)?o:s;this._draggable._newPos.x=a},_onDragEnd:function(){var t=this._map,e=t.options,i=+new Date-this._lastTime,o=!e.inertia||i>e.inertiaThreshold||!this._positions[0];if(o)t.fire("moveend");else{var s=this._lastPos.subtract(this._positions[0]),a=(this._lastTime+i-this._times[0])/1e3,r=e.easeLinearity,h=s.multiplyBy(r/a),l=h.distanceTo(new n.Point(0,0)),u=Math.min(e.inertiaMaxSpeed,l),c=h.multiplyBy(u/l),_=u/(e.inertiaDeceleration*r),d=c.multiplyBy(-_/2).round();n.Util.requestAnimFrame(function(){t.panBy(d,_,r)})}t.fire("dragend"),e.maxBounds&&n.Util.requestAnimFrame(this._panInsideMaxBounds,t,!0,t._container)},_panInsideMaxBounds:function(){this.panInsideBounds(this.options.maxBounds)}}),n.Map.addInitHook("addHandler","dragging",n.Map.Drag),n.Map.mergeOptions({doubleClickZoom
 :!0}),n.Map.DoubleClickZoom=n.Handler.extend({addHooks:function(){this._map.on("dblclick",this._onDoubleClick)},removeHooks:function(){this._map.off("dblclick",this._onDoubleClick)},_onDoubleClick:function(t){this.setView(t.latlng,this._zoom+1)}}),n.Map.addInitHook("addHandler","doubleClickZoom",n.Map.DoubleClickZoom),n.Map.mergeOptions({scrollWheelZoom:!0}),n.Map.ScrollWheelZoom=n.Handler.extend({addHooks:function(){n.DomEvent.on(this._map._container,"mousewheel",this._onWheelScroll,this),this._delta=0},removeHooks:function(){n.DomEvent.off(this._map._container,"mousewheel",this._onWheelScroll)},_onWheelScroll:function(t){var e=n.DomEvent.getWheelDelta(t);this._delta+=e,this._lastMousePos=this._map.mouseEventToContainerPoint(t),this._startTime||(this._startTime=+new Date);var i=Math.max(40-(+new Date-this._startTime),0);clearTimeout(this._timer),this._timer=setTimeout(n.bind(this._performZoom,this),i),n.DomEvent.preventDefault(t),n.DomEvent.stopPropagation(t)},_performZoom:function
 (){var t=this._map,e=this._delta,i=t.getZoom();if(e=e>0?Math.ceil(e):Math.round(e),e=Math.max(Math.min(e,4),-4),e=t._limitZoom(i+e)-i,this._delta=0,this._startTime=null,e){var n=i+e,o=this._getCenterForScrollWheelZoom(n);t.setView(o,n)}},_getCenterForScrollWheelZoom:function(t){var e=this._map,i=e.getZoomScale(t),n=e.getSize()._divideBy(2),o=this._lastMousePos._subtract(n)._multiplyBy(1-1/i),s=e._getTopLeftPoint()._add(n)._add(o);return e.unproject(s)}}),n.Map.addInitHook("addHandler","scrollWheelZoom",n.Map.ScrollWheelZoom),n.extend(n.DomEvent,{_touchstart:n.Browser.msTouch?"MSPointerDown":"touchstart",_touchend:n.Browser.msTouch?"MSPointerUp":"touchend",addDoubleTapListener:function(t,i,o){function s(t){var e;if(n.Browser.msTouch?(p.push(t.pointerId),e=p.length):e=t.touches.length,!(e>1)){var i=Date.now(),o=i-(r||i);h=t.touches?t.touches[0]:t,l=o>0&&u>=o,r=i}}function a(t){if(n.Browser.msTouch){var e=p.indexOf(t.pointerId);if(-1===e)return;p.splice(e,1)}if(l){if(n.Browser.msTouch)
 {var o,s={};for(var a in h)o=h[a],s[a]="function"==typeof o?o.bind(h):o;h=s}h.type="dblclick",i(h),r=null}}var r,h,l=!1,u=250,c="_leaflet_",_=this._touchstart,d=this._touchend,p=[];t[c+_+o]=s,t[c+d+o]=a;var m=n.Browser.msTouch?e.documentElement:t;return t.addEventListener(_,s,!1),m.addEventListener(d,a,!1),n.Browser.msTouch&&m.addEventListener("MSPointerCancel",a,!1),this},removeDoubleTapListener:function(t,i){var o="_leaflet_";return t.removeEventListener(this._touchstart,t[o+this._touchstart+i],!1),(n.Browser.msTouch?e.documentElement:t).removeEventListener(this._touchend,t[o+this._touchend+i],!1),n.Browser.msTouch&&e.documentElement.removeEventListener("MSPointerCancel",t[o+this._touchend+i],!1),this}}),n.extend(n.DomEvent,{_msTouches:[],_msDocumentListener:!1,addMsTouchListener:function(t,e,i,n){switch(e){case"touchstart":return this.addMsTouchListenerStart(t,e,i,n);case"touchend":return this.addMsTouchListenerEnd(t,e,i,n);case"touchmove":return this.addMsTouchListenerMove(t,e,i
 ,n);default:throw"Unknown touch event type"}},addMsTouchListenerStart:function(t,i,n,o){var s="_leaflet_",a=this._msTouches,r=function(t){for(var e=!1,i=0;a.length>i;i++)if(a[i].pointerId===t.pointerId){e=!0;break}e||a.push(t),t.touches=a.slice(),t.changedTouches=[t],n(t)};if(t[s+"touchstart"+o]=r,t.addEventListener("MSPointerDown",r,!1),!this._msDocumentListener){var h=function(t){for(var e=0;a.length>e;e++)if(a[e].pointerId===t.pointerId){a.splice(e,1);break}};e.documentElement.addEventListener("MSPointerUp",h,!1),e.documentElement.addEventListener("MSPointerCancel",h,!1),this._msDocumentListener=!0}return this},addMsTouchListenerMove:function(t,e,i,n){function o(t){if(t.pointerType!==t.MSPOINTER_TYPE_MOUSE||0!==t.buttons){for(var e=0;a.length>e;e++)if(a[e].pointerId===t.pointerId){a[e]=t;break}t.touches=a.slice(),t.changedTouches=[t],i(t)}}var s="_leaflet_",a=this._msTouches;return t[s+"touchmove"+n]=o,t.addEventListener("MSPointerMove",o,!1),this},addMsTouchListenerEnd:function(
 t,e,i,n){var o="_leaflet_",s=this._msTouches,a=function(t){for(var e=0;s.length>e;e++)if(s[e].pointerId===t.pointerId){s.splice(e,1);break}t.touches=s.slice(),t.changedTouches=[t],i(t)};return t[o+"touchend"+n]=a,t.addEventListener("MSPointerUp",a,!1),t.addEventListener("MSPointerCancel",a,!1),this},removeMsTouchListener:function(t,e,i){var n="_leaflet_",o=t[n+e+i];switch(e){case"touchstart":t.removeEventListener("MSPointerDown",o,!1);break;case"touchmove":t.removeEventListener("MSPointerMove",o,!1);break;case"touchend":t.removeEventListener("MSPointerUp",o,!1),t.removeEventListener("MSPointerCancel",o,!1)}return this}}),n.Map.mergeOptions({touchZoom:n.Browser.touch&&!n.Browser.android23}),n.Map.TouchZoom=n.Handler.extend({addHooks:function(){n.DomEvent.on(this._map._container,"touchstart",this._onTouchStart,this)},removeHooks:function(){n.DomEvent.off(this._map._container,"touchstart",this._onTouchStart,this)},_onTouchStart:function(t){var i=this._map;if(t.touches&&2===t.touches.le
 ngth&&!i._animatingZoom&&!this._zooming){var o=i.mouseEventToLayerPoint(t.touches[0]),s=i.mouseEventToLayerPoint(t.touches[1]),a=i._getCenterLayerPoint();this._startCenter=o.add(s)._divideBy(2),this._startDist=o.distanceTo(s),this._moved=!1,this._zooming=!0,this._centerOffset=a.subtract(this._startCenter),i._panAnim&&i._panAnim.stop(),n.DomEvent.on(e,"touchmove",this._onTouchMove,this).on(e,"touchend",this._onTouchEnd,this),n.DomEvent.preventDefault(t)}},_onTouchMove:function(t){if(t.touches&&2===t.touches.length){var e=this._map,i=e.mouseEventToLayerPoint(t.touches[0]),o=e.mouseEventToLayerPoint(t.touches[1]);this._scale=i.distanceTo(o)/this._startDist,this._delta=i._add(o)._divideBy(2)._subtract(this._startCenter),1!==this._scale&&(this._moved||(n.DomUtil.addClass(e._mapPane,"leaflet-zoom-anim leaflet-touching"),e.fire("movestart").fire("zoomstart")._prepareTileBg(),this._moved=!0),n.Util.cancelAnimFrame(this._animRequest),this._animRequest=n.Util.requestAnimFrame(this._updateOnMo
 ve,this,!0,this._map._container),n.DomEvent.preventDefault(t))}},_updateOnMove:function(){var t=this._map,e=this._getScaleOrigin(),i=t.layerPointToLatLng(e);t.fire("zoomanim",{center:i,zoom:t.getScaleZoom(this._scale)}),t._tileBg.style[n.DomUtil.TRANSFORM]=n.DomUtil.getTranslateString(this._delta)+" "+n.DomUtil.getScaleString(this._scale,this._startCenter)},_onTouchEnd:function(){if(this._moved&&this._zooming){var t=this._map;this._zooming=!1,n.DomUtil.removeClass(t._mapPane,"leaflet-touching"),n.DomEvent.off(e,"touchmove",this._onTouchMove).off(e,"touchend",this._onTouchEnd);var i=this._getScaleOrigin(),o=t.layerPointToLatLng(i),s=t.getZoom(),a=t.getScaleZoom(this._scale)-s,r=a>0?Math.ceil(a):Math.floor(a),h=t._limitZoom(s+r);t.fire("zoomanim",{center:o,zoom:h}),t._runAnimation(o,h,t.getZoomScale(h)/this._scale,i,!0)}},_getScaleOrigin:function(){var t=this._centerOffset.subtract(this._delta).divideBy(this._scale);return this._startCenter.add(t)}}),n.Map.addInitHook("addHandler","to
 uchZoom",n.Map.TouchZoom),n.Map.mergeOptions({boxZoom:!0}),n.Map.BoxZoom=n.Handler.extend({initialize:function(t){this._map=t,this._container=t._container,this._pane=t._panes.overlayPane},addHooks:function(){n.DomEvent.on(this._container,"mousedown",this._onMouseDown,this)},removeHooks:function(){n.DomEvent.off(this._container,"mousedown",this._onMouseDown)},_onMouseDown:function(t){return!t.shiftKey||1!==t.which&&1!==t.button?!1:(n.DomUtil.disableTextSelection(),this._startLayerPoint=this._map.mouseEventToLayerPoint(t),this._box=n.DomUtil.create("div","leaflet-zoom-box",this._pane),n.DomUtil.setPosition(this._box,this._startLayerPoint),this._container.style.cursor="crosshair",n.DomEvent.on(e,"mousemove",this._onMouseMove,this).on(e,"mouseup",this._onMouseUp,this).preventDefault(t),this._map.fire("

<TRUNCATED>

[45/51] [abbrv] [partial] Adding Jinwon's custom RCMET

Posted by jo...@apache.org.
http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/rcmes/services/.svn/text-base/run_rcmes_processing.py.svn-base
----------------------------------------------------------------------
diff --git a/src/main/python/rcmes/services/.svn/text-base/run_rcmes_processing.py.svn-base b/src/main/python/rcmes/services/.svn/text-base/run_rcmes_processing.py.svn-base
new file mode 100755
index 0000000..31c3efc
--- /dev/null
+++ b/src/main/python/rcmes/services/.svn/text-base/run_rcmes_processing.py.svn-base
@@ -0,0 +1,114 @@
+#!/usr/local/bin/python
+"""Module used to launch the RESTful API"""
+import sys
+sys.path.append('../../.')
+from bottle import route, request
+import json
+import cli.do_rcmes_processing_sub as awesome
+import time
+import datetime
+import os
+time_format_new = '%Y-%m-%d %H:%M:%S'
+
+#Static Default params
+cachedir = '/tmp/rcmet/cache/'
+workdir = '/tmp/rcmet/'
+precipFlag =False
+seasonalCycleOption=0
+maskOption=False
+maskLatMin=0         # float (only used if maskOption=1)
+maskLatMax=0         # float (only used if maskOption=1)
+maskLonMin=0         # float (only used if maskOption=1)
+maskLonMax=0         # float (only used if maskOption=1)
+
+###########################################################
+##OPEN FOR DISCUSSION
+titleOption = 'default'   #this means that ' model vs obs :' will be used
+plotFileNameOption = 'default'  #another good option we can use.
+###########################################################
+
+@route('/rcmes/run/', method='POST')
+def rcmes_go():
+    print "**********\nBEGIN RCMES2.0_RUN\n**********"
+    print 'cachedir', cachedir
+    print 'workdir', workdir
+    
+    try:
+        if not os.path.exists(cachedir):
+            os.makedirs(cachedir)
+    except Error as e:
+        print "I/O error({0}: {1}".format(e.errno, e.strerror)
+        sys.exit(1)
+
+    obsDatasetId = int(request.POST.get('obsDatasetId', '').strip())
+    print 'obsDatasetId', obsDatasetId
+    obsParameterId = int(request.POST.get('obsParameterId', '').strip())
+    print 'obsParameterId', obsParameterId
+
+    #reformat DateTime after pulling it out of the POST
+    POSTstartTime = str(request.POST.get('startTime', '').strip())
+    startTime = datetime.datetime.fromtimestamp(time.mktime(time.strptime(POSTstartTime, time_format_new)))
+    print 'startTime', startTime
+    #reformat DateTime after pulling it out of the POST
+    POSTendTime = str(request.POST.get('endTime', '').strip())
+    endTime = datetime.datetime.fromtimestamp(time.mktime(time.strptime(POSTendTime, time_format_new)))
+    print 'endTime', endTime
+
+    latMin = float(request.POST.get('latMin', '').strip())
+    print 'latMin', latMin
+    latMax = float(request.POST.get('latMax', '').strip())
+    print 'latMax', latMax 
+    lonMin = float(request.POST.get('lonMin', '').strip())
+    print 'lonMin', lonMin
+    lonMax = float(request.POST.get('lonMax', '').strip())
+    print 'lonMax', lonMax
+
+    filelist = [request.POST.get('filelist', '').strip()]
+    print 'filelist', filelist[0]
+
+    modelVarName = str(request.POST.get('modelVarName', '').strip())
+    print 'modelVarName', modelVarName
+    precipFlag = request.POST.get('precipFlag', '').strip()
+    print 'precipFlag', precipFlag
+    modelTimeVarName = str(request.POST.get('modelTimeVarName', '').strip())
+    print 'modelTimeVarName', modelTimeVarName
+    modelLatVarName = str(request.POST.get('modelLatVarName', '').strip())
+    print 'modelLatVarName', modelLatVarName
+    modelLonVarName = str(request.POST.get('modelLonVarName', '').strip())
+    print 'modelLonVarName', modelLonVarName
+
+    regridOption = str(request.POST.get('regridOption', '').strip())
+    print 'regridOption', regridOption
+    timeRegridOption = str(request.POST.get('timeRegridOption', '').strip())
+    print 'timeRegridOption', timeRegridOption
+    seasonalCycleOption = request.POST.get('seasonalCycleOption', '').strip()
+    print 'seasonalCycleOption', seasonalCycleOption
+    metricOption = str(request.POST.get('metricOption', '').strip())
+    print 'metricOption', metricOption    
+    
+    settings = {"cacheDir": cachedir, "workDir": workdir, "fileList": filelist}
+    params = {"obsDatasetId": obsDatasetId, "obsParamId": obsParameterId, 
+              "startTime": startTime, "endTime": endTime, "latMin": latMin, 
+              "latMax": latMax, "lonMin": lonMin, "lonMax": lonMax}
+    model = {"varName": modelVarName, "timeVariable": modelTimeVarName, 
+             "latVariable": modelLatVarName, "lonVariable": modelLonVarName}
+    mask = {"latMin": latMin, "latMax": latMax, "lonMin": lonMin, "lonMax": lonMax}
+    options = {"regrid": regridOption, "timeRegrid": timeRegridOption, 
+               "seasonalCycle": seasonalCycleOption, "metric": metricOption, 
+               "plotTitle": titleOption, "plotFilename": plotFileNameOption, 
+               "mask": maskOption, "precip": precipFlag}
+    
+    awesome.do_rcmes(settings, params, model, mask, options)
+    
+    model_path = os.path.join(workdir, plotFileNameOption + "model.png")
+    obs_path = os.path.join(workdir, plotFileNameOption + "obs.png")
+    comp_path = os.path.join(workdir, plotFileNameOption + ".png")
+
+    product_dict = {'modelPath':model_path,
+                    'obsPath': obs_path,
+                    'comparisonPath':comp_path}
+    
+    #Extra Code in case bottle has an issue with my Dictionary
+    #json_output = json.dumps(product_dict, sort_keys=True, indent=4)
+    
+    return product_dict

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/rcmes/services/README.txt
----------------------------------------------------------------------
diff --git a/src/main/python/rcmes/services/README.txt b/src/main/python/rcmes/services/README.txt
new file mode 100755
index 0000000..27622ab
--- /dev/null
+++ b/src/main/python/rcmes/services/README.txt
@@ -0,0 +1,68 @@
+RCMET Client API Web Service README
+===========================================================
+
+Prerequisites:
+
+ * Python 2.6+ with easy_install
+ * Bottle (http://bottlepy.org) Web Framework 
+
+Usage:
+
+ ./python main_ws.py
+
+
+Hints:
+
+  Changing the port Bottle runs on
+  --------------------------------
+  The port Bottle starts up on can be changed by editing
+  the last line in the ./main_ws.py file as follows:
+
+  if __name__ == "__main__":
+    run(host='localhost', port=*NEWPORT*)
+
+
+API Documentation:
+=================================================================
+
+Extract Model File Variables
+--------------------------------
+http://<webserviceUrl>/list/vars/"<PATH>"
+
+  INPUTS: 
+    PATH: the fully qualified path to the model file to use. Note 
+          that the path must be enclosed in double quotes.
+
+  RETURN:
+    SUCCESS: {"variables": ["tas", "level", "lon", "time", "lat"]}
+    FAILURE: []   <-- should probably be {}
+
+
+Extract Model Latitude and Longitude Variables and Bounds
+---------------------------------------------------------
+http://<webserviceUrl>/list/latlon/"<PATH>"
+
+  INPUTS: 
+    PATH: the fully qualified path to the model file to use. Note 
+    	  that the path must be enclosed in double quotes.
+
+  RETURN:
+    SUCCESS: {"latMax": "42.24", "success": 1, "latname": "lat", 
+              "lonMax": "60.28", "lonMin": "-24.64", 
+	      "lonname": "lon", "latMin": "-45.76"}
+    FAILURE: ?
+
+
+Extract Model Time Variable and Bounds
+--------------------------------------
+http://<webserviceUrl>/list/time/"<PATH>"
+
+  INPUTS: 
+    PATH: the fully qualified path to the model file to use. Note 
+          that the path must be enclosed in double quotes.
+
+  RETURN:
+    SUCCESS:  {"start_time": "1989-01-15 00:00:00", 
+    	       "timename": "time", "success": 1, 
+	       "end_time": "2008-12-15 00:00:00"}
+    FAILURE: ?

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/rcmes/services/__init__.py
----------------------------------------------------------------------
diff --git a/src/main/python/rcmes/services/__init__.py b/src/main/python/rcmes/services/__init__.py
new file mode 100755
index 0000000..9a00597
--- /dev/null
+++ b/src/main/python/rcmes/services/__init__.py
@@ -0,0 +1,2 @@
+"""The Services Package is a collection of RESTful Web Service modules that can
+be used to create custom User Interfaces to RCMES"""
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/rcmes/services/bottlemet.py
----------------------------------------------------------------------
diff --git a/src/main/python/rcmes/services/bottlemet.py b/src/main/python/rcmes/services/bottlemet.py
new file mode 100755
index 0000000..0bcefb8
--- /dev/null
+++ b/src/main/python/rcmes/services/bottlemet.py
@@ -0,0 +1,599 @@
+'''
+ Module to create a web service for RCMET statistical metrics
+'''
+
+
+
+
+##########################################################################################
+#setting up bottle and importing metrics
+##########################################################################################
+
+#sets up bottle and necessary methods.
+from bottle import route, run, post, request, redirect, debug 
+
+#temporary quick-fix to track errors, not for publication 
+debug(True)
+
+#imports pickle
+import pickle
+
+#imports metrics from RCMET
+import rcmes.metrics as mtx
+
+
+
+
+##########################################################################################
+#error-catching dictionaries 
+##########################################################################################
+
+#dictionary of MetricNames and their number of variables. Useful later on
+HowManyVariables={
+	"calc_stdev" :1,
+	"calc_annual_cycle_means" : 2,
+	"calc_annual_cycle_std" : 2,
+	"calc_annual_cycle_domain_means" : 2,
+	"calc_annual_cycle_domain_std" : 2,
+	"calc_bias" : 2,
+	"calc_bias_dom" : 2,
+	"calc_difference" : 2,
+	"calc_mae" : 2,
+	"calc_mae_dom" :2,
+	"calc_rms" : 2,
+	"calc_rms_dom" : 2,
+	"calc_temporal_pat_cor" : 2,
+	"calc_pat_cor" : 2,
+	"calc_nash_sutcliff" : 2,
+	"calc_pdf" : 2,
+	"calc_anom_corn" : 3
+}		
+	
+#dictionary of metric names and the names of their variables.
+NameOfVariables={
+	"calc_stdev":['t1'],
+	"calc_annual_cycle_means" :['data','time'],
+	"calc_annual_cycle_std" :['data','time'],
+	"calc_annual_cycle_domain_means" :['data','time'],
+	"calc_annual_cycle_domain_std" :['data','time'],
+	"calc_bias" :['t1','t2'],
+	"calc_bias_dom" :['t1','t2'],
+	"calc_difference" :['t1','t2'], 
+	"calc_mae" :['t1','t2'],
+	"calc_mae_dom" : ['t1','t2'],
+	"calc_rms" :['t1','t2'],
+	"calc_rms_dom" :['t1','t2'],
+	"calc_temporal_pat_cor" :['t1','t2'],
+	"calc_pat_cor" :['t1','t2'],
+	"calc_nash_sutcliff" :['t1','t2'],
+	"calc_pdf" :['t1','t2'],
+	"calc_anom_corn" :['t1','t2','t4']
+}				
+
+#two lists that will help with user explanation later
+
+ArrayNames=[]	   
+
+ListOfArrays=[]
+	
+	
+	
+##########################################################################################
+
+#Running the metrics through interactive web pages
+
+##########################################################################################
+
+
+
+##########################################################################################
+#First parts: introduction and identification of user's needs
+##########################################################################################
+
+#basic first page. Explanation could be more comprehensive
+@route('/rcmet/metrics/online')	
+def ShowPossibleMetrics():
+	'''
+	Returns a page in html that allows the user to select a metric through links
+	'''
+	return '''<html>
+		<head> RCMET Metrics through Bottle </head>
+		<body>
+		<p>Please select the metric you will use.</p>
+		
+		<p> Metrics with one variable: 
+		<a href='/rcmet/metrics/online/calc_stdev'>"calc_stdev" to return standard deviation</a>
+		</p>
+	
+		<p> Metrics with two variables: 
+		<a href='/rcmet/metrics/online/calc_annual_cycle_means'>"calc_annual_cycle_means" to return monthly means</a>
+		<a href='/rcmet/metrics/online/calc_annual_cycle_std'>""calc_annual_cycle_std" to return monthly standard deviation</a>  
+		<a href='/rcmet/metrics/online/calc_annual_cycle_domain_means'>"calc_annual_cycle_domain_ means" to return monthly 
+		domain means</a>   
+		<a href='/rcmet/metrics/online/calc_annual_cycle_domain_std'>"calc_annual_cycle_domain_std" to return monthly standard 
+		deviation</a>	
+		<a href='/rcmet/metrics/online/calc_bias'>"calc_bias" to return mean difference</a>	
+		<a href='/rcmet/metrics/online/calc_bias_dom'>"calc_bias_dom" to return domain mean difference</a>	 
+		<a href='/rcmet/metrics/online/calc_difference'>"calc_difference" to return difference</a>
+		<a href='/rcmet/metrics/online/calc_mae'>"calc_mae" to return mean absolute error</a>	
+		<a href='/rcmet/metrics/online/calc_mae_dom'>"calc_mae_dom" to return domain mean difference over time</a>
+		<a href='/rcmet/metrics/online/calc_rms'>"calc_rms" to return root mean square error
+		</a>	
+		<a href='/rcmet/metrics/online/calc_rms_dom'>"calc_rms_dom" to return domain root mean square error</a>	
+		<a href='/rcmet/metrics/online/calc_temporal_pat_cor'>"calc_temporal_pat_cor" to return temporal pattern correlation</a>
+		<a href='/rcmet/metrics/online/calc_pat_cor'>"calc_pat_cor" to return pattern correlation</a>
+		<a href='/rcmet/metrics/online/calc_nash_sutcliff'>"calc_nash_sutcliff" to return Nash-Sutcliff coefficient of 
+		efficiency</a>
+		<a href='/rcmet/metrics/online/calc_pdf'>"calc_pdf" to return probability distribution function</a>
+		
+		<p> Metrics with three variables:
+		<a href='/rcmet/metrics/online/calc_anom_corn'>"calc_anom_corn" to return anomaly correlation</a> </p>
+		</body>
+		<html>'''
+
+#creates introductory page to explain how to use bottle
+@route('/rcmet/metrics/online/<MetricNameHere>')
+def VariableSubmission(MetricNameHere):
+	'''
+	Returns a page in html that allows the user to choose between submitting variables on the command line or searching 
+	RCMED
+	'''	  
+	
+	global MetricName
+	
+	MetricName=MetricNameHere
+	
+	if MetricName in HowManyVariables:
+		return "For metric %s , you need %d variable(s), which will represent: %s" %(MetricName, 
+			HowManyVariables[MetricName], NameOfVariables[MetricName][:]), '''<html>
+			<body>
+			<p>Will you enter variables (which are arrays) through the command line or 
+			will you search the RCMES Database?</p>
+			<a href="/rcmet/metrics/online/commandline">command line</a>
+			<a href="/rcmet/metrics/online/rcmed">RCMED</a>
+			</body>
+			</html>''',
+			'''<a href='/rcmet/metrics/online/methods'>Run Methods</a>'''
+	
+	else:
+		return "The metric you entered doesn't exist."
+
+
+##########################################################################################
+#getting arrays through the command line
+##########################################################################################
+
+#Tells the user how to send variables from the command line
+@route('/rcmet/metrics/online/commandline')
+def ArraysFromCommandLine():
+	'''
+	Explains to the user how to submit a variable through POST on the command line
+	'''
+	if HowManyVariables[MetricName]-count<=0:
+		print "You have already submitted all the needed variables for this metric."
+		redirect('/rcmet/metrics/online/calculate')
+	else:
+		return "Please use your command line to POST a form with the array. Send either a pickled file or serialized ",
+		"string. Name the form: array. Include also, a form that describes/names the array. Call this form: name. A ",
+		"sample would be array=array_here and name=array_name_here. Send the form to: ",
+		"http://.../rcmet/metrics/<metric_name>/commandline. Once the computer receives all variables, you may ", 
+		"move on to the metrics portion of the website. Currently, you have submitted %d variable(s) and need %d ",
+		"more. The next variable you submit will represent the variable %s in %s" %(count, 
+		(HowManyVariables[MetricName]-count),NameOfVariables[MetricName][count], MetricName)
+	
+#this function	gets the array from the command line
+@route('/rcmet/metrics/online/commandline', method='POST') 
+def ReceivingArrays():
+	'''
+	Uses the POST method to retrieve any arrays sent by the user, and proceed to deserialize them. Also adds each
+	variable to the appropriate list, and proceeds to offer the user the option to add more variables or else move
+	on to calculating the value of the metric;
+	'''
+		
+	try:
+		BottleMetrics.GetVariablesFromCommandLine()
+			
+		return "Variable received as %s. Will represent %s" % (ArrayNames[count-1], 
+		NameOfVariables[MetricName][count-1]), "Submit more variables?",
+		'''<a href='/rcmet/metrics/online/rcmed'>Online</a>''',
+		'''<a href='/rcmet/metrics/online/commandline'>Command Line</a>''',
+		'''<a href='/rcmet/metrics/online/calculate'>No More Variables</a>''',
+		'''<a href='/rcmet/metrics/online/methods'>Run Methods</a>'''
+	
+	except pickle.UnpicklingError:
+		return "This object cannot be unpickled. Send only a file or serialized string.",
+		'''<a href='/rcmet/metrics/online/commandline'>Re-submit Variable</a>''',
+		'''<a href='/rcmet/metrics/online/methods'>Run Methods</a>'''
+		
+
+##########################################################################################
+#getting variables through RCMED
+##########################################################################################
+
+#explains how to enter information into a dynamic link
+@route('/rcmet/metrics/online/rcmed')
+def QueryRcmed():
+	'''
+	Returns a page in html that explains to the user how to search RCMED for the desired arrays, and offers the
+	user multiple forms in which to enter search parameters
+	'''
+	
+	#I was unclear what type the dataset ID and paramID were supposed to be. This may need to change
+	
+	return "Currently, you have submitted %d variable(s) and need %d more. The next"\
+	" variable you submit will represent the variable %s in %s" %(count, 
+	(HowManyVariables[MetricName]-count),NameOfVariables[MetricName][count], MetricName),'''<html>
+	<head> Query RCMED for Array Data </head>
+	<body>
+	<p>Enter the parameters into the appropriate boxes.</p>
+	<form method="POST">
+		<p>Dataset ID</p>
+		<input name="datasetID"	 type="string" />
+		<p>Parameter ID</p>
+		<input name="paramID"	 type="string" />
+		<p>latMin, float</p>
+		<input name="latMin"	 type="float" />
+		<p>latMax, float</p>
+		<input name="latMax"	 type="float" />
+		<p>lonMin, float</p>
+		<input name="lonMin"	 type="float" />
+		<p>lonMax, float</p>
+		<input name="lonMax"	 type="float" />
+		<p>startTime, datetime object</p>
+		<input name="startTime"	 type="datetime" />
+		<p>endTime, datetime object</p>
+		<input name="endTime"	 type="datetime" />
+		<p>cachedir, string</p>
+		<input name="cachedir"	 type="string" />
+		<p>Array Name, string</p>
+		<input name="ArrayName"	 type="string" />
+		<input type="Submit" /> </form>
+	</body>
+	</html>''' 
+	
+	
+@route('/rcmet/metrics/online/rcmed', method='POST')
+def GetVariablesFromDatabase():
+	'''
+	Gets data from forms, searches the database, processes the variables, and prompts the user to submit more.
+	'''
+	BottleMetrics.GetVariablesFromRcmed()	 
+
+
+	return "Submit more variables?",'''<a href='/rcmet/metrics/online/rcmed'>Online</a>''',
+	'''<a href='/rcmet/metrics/online/commandline'>Command Line</a>''',
+	'''<a href='/rcmet/metrics/online/calculate'>No More Variables</a>''',
+	'''<a href='/rcmet/metrics/online/methods'>Run Methods</a>'''
+
+
+##########################################################################################
+#running the metrics online
+##########################################################################################
+
+#this function actually runs the metrics
+@route('/rcmet/metrics/online/calculate')
+def Calculate(MetricName):
+	'''
+	Uses variables from the lists to return the answer for the metric. Also returns a brief description of the metric performed. 
+	'''
+		
+	if HowManyVariables[MetricName]<count:
+		return "You have too few variables to run this metric.",'''<a href='/rcmet/metrics/online/commandline'>Command Line</a>,
+		<a href='/rcmet/metrics/online/rcmed'>Online</a>''','''<a href='/rcmet/metrics/online/methods'>Run Methods</a>'''
+	
+	else:
+		return BottleMetrics.ExplainMetric(), str(result), '''<a href='/rcmet/metrics/online/methods'>Run Methods</a>''',
+		'''<a href='/rcmet/metrics/online'>Start Over</a>'''
+			
+	
+	'''<a href='/rcmet/metrics/online/methods'>Run Methods</a>'''
+	
+@route('/rcmet/metrics/online/methods')
+def ChooseMethodOnline():
+	'''
+	Allows an online user to access any method in the class
+	'''
+	
+	return "Which method?", '''<html>
+	<a href='/rcmet/metrics/online/methods/Status'>Status</a>
+	<a href='/rcmet/metrics/online/methods/ExplainMetric'>ExplainMetric</a>
+	<a href='/rcmet/metrics/online/methods/VariableCount'>VariableCount</a>
+	<a href='/rcmet/metrics/online/methods/ReturnResult'>ReturnResult</a>
+	<a href='/rcmet/metrics/online/methods/CleanUp'>CleanUp</a>'''
+	
+@route('/rcmet/metrics/online/methods/<MethodName>)
+def RunMethodOnline(MethodName):
+	'''
+	Runs any method in class MetricWebService() chosen by an online user
+	'''
+		
+	MetricWebServiceMethod=getattr(BottleMetrics, MethodName)
+	
+	return BottleMetrics.MetricWebServiceMethod(), '''<a href='/rcmet/metrics/online'>Back to Beginning</a>'''
+	
+
+##########################################################################################	
+##########################################################################################
+
+#creating a class for the Web Service 
+
+##########################################################################################
+##########################################################################################
+
+class MetricWebService(object):
+	'''
+	Class containing all of the necessary functions to find, process, and use the variables to run metrics. Also allows
+	the user to see the state of the metric, i.e. how many variables have been entered. 
+	'''
+		
+	def __init__(self):
+
+		global count
+		count=0
+
+##########################################################################################
+
+	def Status(self):
+		'''
+		Provides a standardized system for showing how many variables are submitted, allowing the user to 
+		check their progress 
+		'''
+		print "For metric %s , you need %d variable(s): %s. Currently, you have submitted "\
+		"%d variable(s) and need %d more. The values you have submitted, %s, will represent %s respectively." 
+		%(MetricName, HowManyVariables[MetricName], NameOfVariables[MetricName][:], count, 
+		(HowManyVariables[MetricName]-count),ArrayNames[:],NameOfVariables[MetricName][:])
+		
+		return "For metric %s , you need %d variable(s): %s. Currently, you have submitted "\
+		"%d variable(s) and need %d more. The values you have submitted, %s, will represent %s respectively." 
+		%(MetricName, HowManyVariables[MetricName], NameOfVariables[MetricName][:], count, 
+		(HowManyVariables[MetricName]-count),ArrayNames[:],NameOfVariables[MetricName][:])
+		
+##########################################################################################
+
+	def ExplainMetric(self):
+		'''
+		Provides a standardized means of returning a metric's docstring and thus describing the metric
+		'''
+		method=getattr(mt, MetricName)
+
+		print method.__doc__
+
+		return method.__doc__
+##########################################################################################
+
+	def VariableCount(self):
+		'''
+		Determines how many variables have been submitted, and if the right number has, this function runs the RunMetrics() method
+		'''
+			
+		if HowManyVariables[MetricName]-count>0:
+		
+			print "Please add more variables"
+			
+			return "Please add more variables"
+					
+		if HowManyVariables[MetricName]-count<0:
+			print "You have added too many variables"
+			
+			return "Please add more variabels"
+			
+		else:
+			print "You have added all necessary metrics. The program will now run your metric."
+			
+			self.RunMetrics()
+			
+
+##########################################################################################
+	
+	def ProcessVariables(self, array, ArrayName):	
+		'''
+		adds the variables posted by the user to the appropriate lists, raises count to indicate this addition, and
+		starts VariableCount()
+		'''			
+		ListOfArrays.append(array)
+		ArrayNames.append(ArrayName)
+			
+		global count
+		count=count+1
+			
+		print "Variable received as %s. Will represent %s" % (ArrayName, 
+		NameOfVariables[MetricName][count-1])
+			
+		self.VariableCount()
+		
+##########################################################################################
+
+	def GetVariablesFromCommandLine(self):	
+		'''
+		Gets array and array name from forms, deserializes them with unpickle, and runs ProcessVariables()
+		'''	
+		
+		if HowManyVariables[MetricName]-count>0:
+			array=request.forms.get('array')
+			ArrayName=request.forms.get('name')
+			
+			if type(array)==str:
+				array=pickle.loads(array)	   
+			
+			else:
+				array=pickle.load(array)
+		
+			self.ProcessVariables(array, ArrayName)
+		
+		else:
+			self.VariableCount()
+	
+##########################################################################################
+	
+	def GetVariablesFromRcmed(self):	
+		'''
+		Gets search parameters from forms, runs a search of RCMED, and returns the array mdata
+		'''
+		
+		if HowManyVariables[MetricName]-count>0:
+		
+			import rcmes.db as db
+	
+			datasetID=request.forms.get('datasetID')
+			paramID=request.forms.get('paramID')
+			latMin=request.forms.get('latMin')
+			latMax=request.forms.get('latMax')
+			lonMin=request.forms.get('lonMin')
+			lonMax=request.forms.get('lonMax')
+			startTime=request.forms.get('startTime')
+			endTime=request.forms.get('endTime')
+			cachedir=request.forms.get('cachedir')
+	
+			ArrayName=request.forms.get('name')				
+					
+			try:
+			
+				db.extract_data_from_db(datasetID, paramID, latMin, latMax, lonMin, lonMax, startTime, endTime, cachedir)
+				
+				#I don't think this will work
+				array=mdata
+				
+				self.ProcessVariables(array,ArrayName)
+										
+			except TypeError:
+				print "One of your variables was not entered in the correct format or was not entered at all"
+			
+		else:
+			self.VariableCount()	
+			
+##########################################################################################
+	
+	def GetVariables(self):
+		'''
+		Runs two links that connect with functions meant to handle the variables posted to the links
+		'''
+####################
+		
+		@route('/rcmet/metrics/get/variables/commandline', method='POST') 
+		def VariablesPostedToCommandline():
+			'''
+			runs the method GetVariablesFromCommandLine() at the URL, allowing the user to post their forms to this url and have
+			them handled by GetVariablesFromCommandLine().
+			'''
+			
+			try:
+				self.GetVariablesFromCommandLine()
+					
+			except pickle.UnpicklingError:
+				print "This object cannot be unpickled. Send only a file or serialized string."
+	
+
+####################
+
+		@route('/rcmet/metrics/get/variables/rcmed', method='POST')
+		def GetVariablesFromRCMED(self):
+			'''
+			runs the method GetVariablesFromRcmed() at the URL, allowing the user to post their forms to this url and have
+			them handled by GetVariablesFromRcmed().
+			'''
+			
+			self.GetVariablesFromRcmed()	 
+				
+##########################################################################################
+				
+	def RunMetrics(self):
+		'''
+		Calls to metrics.py and runs the desired metric using variables submitted by the user. Returns a string of the 
+		value returned by the metric
+		'''
+		
+		print "Running metric"	
+		  
+		method=getattr(mtx, MetricName)
+	
+		global result
+	
+		if HowManyVariables[MetricName]==1:
+			result=method(ListOfArrays[0])
+			
+		if HowManyVariables[MetricName]==2:
+			result=method(ListOfArrays[0], ListOfArrays[1])
+				
+		if HowManyVariables[MetricName]==3:
+			result=method(ListOfArrays[0], ListOfArrays[1], ListOfArrays[2])
+		
+##########################################################################################
+		
+	@route('/rcmet/metrics/commandline/return/result')
+	def ReturnResult():
+		'''
+		links the result to a uri from which the user can easily fetch it. Note, the result is returned as a string
+		'''	
+	#If the result of the metrics is an array, I would recommend including a provision in 
+	#ReturnResult() that pickles or somehow serializes the result, and then, upon getting 
+	#the pickled string from the URL, the user could unpickle it and use it as an array. 	
+	
+		return str(result)
+		
+##########################################################################################
+
+	def CleanUp(self, name):
+		'''
+		resets the lists, the count, and the variable MetricName back to zero, enabling a user to in effect start over, without
+		re-creating the instance of the class. 
+		'''
+		
+		global ArrayNames
+		ArrayNames=[]
+		
+		global ListOfArrays
+		ListOfArrays=[]
+		
+		global count
+		count=0	
+		
+		global MetricName
+		name=MetricName
+
+##########################################################################################
+#final commands to tie everything together 
+##########################################################################################
+
+#allows the command line user to remotely create an instance of the class
+@route('/rcmet/metrics/commandline', method='POST')
+def CreateAnInstance():
+	'''
+	Sets up a POST page that creates an instance of the class for a user on the command line. The user does not need
+	to open this page for it to function; they need only post the name of the metric they want. 
+	'''
+	
+	NameOfMetric=request.forms.get('NameOfMetric')
+	
+	global MetricName
+	
+	MetricName=NameOfMetric
+
+	if name in HowManyVariables:
+		BottleMetrics.GetVariables()
+	
+	else:
+		print "The metric you entered, %s, does not exist" %name	
+
+
+
+@route('/rcmet/metrics/commandline/methods', method='POST')
+def RunAMethod():
+	'''
+	Allows a command line user to access any method in class MetricWebService() by sending a form
+	'''
+	MethodName=request.forms.get('MethodName')
+	
+	MetricWebServiceMethod=getattr(BottleMetrics, MethodName)
+	
+	BottleMetrics.MetricWebServiceMethod()
+	 
+
+BottleMetrics=MetricWebService()
+
+#final function starts up bottle at http://localhost:8080
+#note: localhost:8080 may need to be changed eventually 
+run(host='localhost', port=8080)
+
+
+
+

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/rcmes/services/dataset_helpers.py
----------------------------------------------------------------------
diff --git a/src/main/python/rcmes/services/dataset_helpers.py b/src/main/python/rcmes/services/dataset_helpers.py
new file mode 100755
index 0000000..2031caf
--- /dev/null
+++ b/src/main/python/rcmes/services/dataset_helpers.py
@@ -0,0 +1,32 @@
+#!/usr/bin/env python
+"""
+    Provides Bottle services for interacting with RCMED
+"""
+
+from bottle import request, route
+
+import requests
+import Nio
+
+@route('/getObsDatasets')
+def getObservationDatasetData():
+    r = requests.get('http://rcmes.jpl.nasa.gov/query-api/datasets.php')
+
+    # Handle JSONP requests
+    if (request.query.callback):
+        return "%s(%s)" % (request.query.callback, r.text)
+    # Otherwise, just return JSON
+    else:
+        return r.text
+
+@route('/getDatasetParam')
+def getDatasetParameters():
+    url = 'http://rcmes.jpl.nasa.gov/query-api/parameters.php?dataset=' + request.query.dataset
+    r = requests.get(url)
+
+    # Handle JSONP requests
+    if (request.query.callback):
+        return "%s(%s)" % (request.query.callback, r.text)
+    # Otherwise, just return JSON
+    else:
+        return r.text

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/rcmes/services/decode_model_times.py
----------------------------------------------------------------------
diff --git a/src/main/python/rcmes/services/decode_model_times.py b/src/main/python/rcmes/services/decode_model_times.py
new file mode 100755
index 0000000..ae7974d
--- /dev/null
+++ b/src/main/python/rcmes/services/decode_model_times.py
@@ -0,0 +1,185 @@
+#!/usr/local/bin/python
+"""Module to simplify handling of model times """
+def decodeTimeFromString(time_string):
+    '''
+    # Decodes string into a python datetime object
+    # Method: tries a bunch of different time format possibilities and hopefully one of them will hit.
+    # 
+    #   Input:  time_string - a string that represents a date/time
+    #   Output: mytime - a python datetime object
+    #
+    #   Peter Lean   February 2011
+    '''
+    import time
+    import datetime
+
+    try:
+        mytime = time.strptime(time_string, '%Y-%m-%d %H:%M:%S')
+        mytime = datetime.datetime(*mytime[0:6])
+        return mytime
+
+    except ValueError:
+        pass
+
+    try:
+        mytime = time.strptime(time_string, '%Y/%m/%d %H:%M:%S')
+        mytime = datetime.datetime(*mytime[0:6])
+        return mytime
+
+    except ValueError:
+        pass
+
+    try:
+        mytime = time.strptime(time_string, '%Y%m%d %H:%M:%S')
+        mytime = datetime.datetime(*mytime[0:6])
+        return mytime
+
+    except ValueError:
+        pass
+
+    try:
+        mytime = time.strptime(time_string, '%Y:%m:%d %H:%M:%S')
+        mytime = datetime.datetime(*mytime[0:6])
+        return mytime
+
+    except ValueError:
+        pass
+
+    try:
+        mytime = time.strptime(time_string, '%Y%m%d%H%M%S')
+        mytime = datetime.datetime(*mytime[0:6])
+        return mytime
+
+    except ValueError:
+        pass
+
+    try:
+        mytime = time.strptime(time_string, '%Y-%m-%d %H:%M')
+        mytime = datetime.datetime(*mytime[0:6])
+        return mytime
+
+    except ValueError:
+        pass
+
+
+    print 'Error decoding time string: string does not match a predefined time format'
+    return 0
+
+
+
+def decode_model_times(filelist,timeVarName):
+   '''
+   #  Routine to convert from model times ('hours since 1900...', 'days since ...') 
+   #  into a python datetime structure
+   #
+   #  Input:
+   #      filelist - list of model files
+   #      timeVarName - name of the time variable in the model files
+   #
+   #  Output:
+   #      times  - list of python datetime objects describing model data times
+   #
+   #
+   #     Peter Lean February 2011
+   #
+   '''
+   import datetime
+   import re
+   import string
+   import math
+   import numpy
+   import Nio
+
+   f = Nio.open_file(filelist[0])
+   xtimes = f.variables[timeVarName]
+   timeFormat = xtimes.units
+
+   # search to check if 'since' appears in units
+   try:
+     sinceLoc = re.search('since',timeFormat).end()
+
+   except:
+     print 'Error decoding model times: time variable attributes do not contain "since"'
+     return 0
+
+   # search for 'seconds','minutes','hours', 'days', 'months', 'years' so know units
+   units = ''
+   try:
+     mysearch = re.search('minutes',timeFormat).end()
+     units = 'minutes'
+   except:
+     pass
+   try:
+     mysearch = re.search('hours',timeFormat).end()
+     units = 'hours'
+   except:
+     pass
+   try:
+     mysearch = re.search('days',timeFormat).end()
+     units = 'days'
+   except:
+     pass
+   try:
+     mysearch = re.search('months',timeFormat).end()
+     units = 'months'
+   except:
+     pass
+   try:
+     mysearch = re.search('years',timeFormat).end()
+     units = 'years'
+   except:
+     pass
+   
+   # cut out base time (the bit following 'since')
+   base_time_string = string.lstrip(timeFormat[sinceLoc:])
+
+   # decode base time
+   base_time = decodeTimeFromString(base_time_string)
+
+
+   times=[]
+   for xtime in xtimes[:]:
+      if(units=='minutes'):  
+         dt = datetime.timedelta(minutes=xtime)
+         new_time = base_time + dt
+
+      if(units=='hours'):  
+         dt = datetime.timedelta(hours=xtime)
+         new_time = base_time + dt
+
+      if(units=='days'):  
+         dt = datetime.timedelta(days=xtime)
+         new_time = base_time + dt
+
+      if(units=='months'):   # NB. adding months in python is complicated as month length varies and hence ambigous.
+         # Perform date arithmatic manually
+         #  Assumption: the base_date will usually be the first of the month
+         #              NB. this method will fail if the base time is on the 29th or higher day of month
+         #                      -as can't have, e.g. Feb 31st.
+         new_month = int(base_time.month + xtime % 12)
+         new_year = int(math.floor(base_time.year + xtime / 12.))
+         new_time = datetime.datetime(new_year,new_month,base_time.day,base_time.hour,base_time.second,0)
+
+      if(units=='years'):
+         dt = datetime.timedelta(years=xtime)
+         new_time = base_time + dt
+         
+      times.append(new_time)
+
+   return times
+
+
+''' NOT USED BY BOTTLE WS CALLS
+import sys
+import datetime 
+filename = [sys.argv[1]]
+time_var_name = sys.argv[2]
+
+print filename, type(filename)
+print time_var_name
+
+times = decode_model_times(filename,time_var_name)
+
+for time in times:
+  print time.strftime('%Y-%m-%d %H:%M:%S')
+'''

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/rcmes/services/directory_helpers.py
----------------------------------------------------------------------
diff --git a/src/main/python/rcmes/services/directory_helpers.py b/src/main/python/rcmes/services/directory_helpers.py
new file mode 100755
index 0000000..70147c4
--- /dev/null
+++ b/src/main/python/rcmes/services/directory_helpers.py
@@ -0,0 +1,42 @@
+#!/usr/bin/env python
+"""
+    Provides helpers for listing retrieving directory information from the server.
+"""
+
+from bottle import request, route
+import os
+import json
+
+PATH_LEADER = "/usr/local/rcmes"
+
+@route('/getDirInfo/<dirPath:path>')
+def getDirectoryInfo(dirPath):
+    dirPath = PATH_LEADER + dirPath
+    dirPath = dirPath.replace('/../', '/')
+    dirPath = dirPath.replace('/./', '/')
+
+    if os.path.isdir(dirPath):
+        listing = os.listdir(dirPath)
+        listingNoHidden = [f for f in listing if f[0] != '.']
+        joinedPaths = [os.path.join(dirPath, f) for f in listingNoHidden]
+        joinedPaths = [f + "/" if os.path.isdir(f) else f for f in joinedPaths]
+        finalPaths = [p.replace(PATH_LEADER, '') for p in joinedPaths]
+        sorted(finalPaths, key=lambda s: s.lower())
+        returnJSON = finalPaths
+    else:
+        returnJSON = []
+
+    returnJSON = json.dumps(returnJSON)
+    if request.query.callback:
+        return "%s(%s)" % (request.query.callback, returnJSON)
+    else:
+        return returnJSON
+
+@route('/getPathLeader/')
+def getPathLeader():
+    returnJSON = {"leader": PATH_LEADER}
+
+    if request.query.callback:
+        return "%s(%s)" % (request.query.callback, returnJSON)
+    else:
+        return returnJSON

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/rcmes/services/find_latlon_var.py
----------------------------------------------------------------------
diff --git a/src/main/python/rcmes/services/find_latlon_var.py b/src/main/python/rcmes/services/find_latlon_var.py
new file mode 100755
index 0000000..f46e8d4
--- /dev/null
+++ b/src/main/python/rcmes/services/find_latlon_var.py
@@ -0,0 +1,136 @@
+#!/usr/local/bin/python
+"""
+    Small command line utility to find what the latitude and longitude variables are called in a model file.
+
+    Background::  
+        Model output files tend not to follow any defined standard in terms of 
+        variable naming conventions.  One model may call the latitude "lat", 
+        another one may call it "Latitudes".  This script looks for the 
+        existence of any of a predefined list of synonyms for lat and long.
+
+    This script should be run from the command line (i.e. not called from 
+    within python)
+
+    Input::
+        -filename
+    
+    Output::
+        -success flag (1 or 0): were both latitude and longitude variable names found in the file?
+    
+    if successful::
+        -name of latitude variable
+        -name of longitude variable
+        -latMin -descriptions of lat/lon ranges in data files
+        -latMax
+        -lonMin
+        -lonMax
+    
+    if unsuccessful:
+        -list of variable names in file
+    
+    (NB. all printed to standar output)
+    
+"""
+
+import sys
+import Nio
+import bottle
+from bottle import request
+import json
+
+#filename = sys.argv[1]
+
+@bottle.route('/list/latlon/:filename#".*"#')
+def find_latlon(filename):
+  success = 0
+  filename = filename.strip('"')
+  f = Nio.open_file(filename)
+  var_name_list = f.variables.keys()
+
+  # convert all variable names into lower case
+  var_name_list_lower = [x.lower() for x in var_name_list]
+
+  # create a "set" from this list of names
+  varset = set(var_name_list_lower)
+
+  # Use "set" types for finding common variable name from in the file and from the list of possibilities
+  lat_possible_names = set(['latitude','lat','lats','latitudes'])
+  lon_possible_names = set(['longitude','lon','lons','longitudes'])
+
+  # Search for common latitude name variants:
+  # Find the intersection of two sets, i.e. find what latitude is called in this file.
+  
+  try:
+    print 'hello from inside try block'
+    lat_var_name = list(varset & lat_possible_names)[0]
+    successlat = 1
+    index = 0
+    for i in var_name_list_lower: 
+     if i==lat_var_name:
+          whlat = index
+     index += 1
+    latname = var_name_list[whlat]
+
+    lats = f.variables[latname][:]
+    latMin = lats.min()
+    latMax = lats.max()
+
+  except:
+    print 'exception happens'
+    latname = 'not_found'
+    successlat = 0
+
+  # Search for common longitude name variants:
+  # Find the intersection of two sets, i.e. find what longitude
+  # is called in this file.
+  try:
+    lon_var_name = list(varset & lon_possible_names)[0]
+    successlon = 1
+    index = 0
+    for i in var_name_list_lower:
+     if i==lon_var_name:
+          whlon = index
+     index += 1
+    lonname = var_name_list[whlon]
+
+    lons = f.variables[lonname][:]
+    #this will correct all lons to -180 , 180
+    lons[lons>180]=lons[lons>180]-360
+    
+    lonMin = lons.min()
+    lonMax = lons.max()
+
+  except:
+    lonname = 'not_found'
+    successlon = 0
+
+  
+  if(successlat & successlon): 
+     success = 1
+  
+  
+  if success:
+    print success, latname, lonname, latMin, latMax, lonMin, lonMax
+    val_types= [int,str,str,str,str,str,str]
+    success_values = [success, latname, lonname, latMin, latMax, lonMin, lonMax]
+    value_names = ['success','latname','lonname','latMin','latMax','lonMin','lonMax']
+    values = [vtypes(svalues) for vtypes,svalues in zip(val_types,success_values)]
+    print values
+    output = dict(zip(value_names,values))
+    #json_output = json.dumps({'success':success,'latname':latname, \
+    #                          'lonname':lonname,'latMin':latMin, \
+    #                           'latMax':latMax,'lonMin':lonMin, \
+    #                           'lonMax':lonMax }, sort_keys=True, indent=4)
+    if (request.query.callback):
+      return "%s(%s)" % (request.query.callback, output)
+    return output
+
+  if success==0:
+    json_output = json.dumps({'success':success,
+                                 'variables':var_name_list }, \
+                                sort_keys=True, indent=4)
+    if (request.query.callback):
+      return "%s(%s)" % (request.query.callback, json_output)
+    return json_output
+    #print success, var_name_list
+

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/rcmes/services/find_time_var.py
----------------------------------------------------------------------
diff --git a/src/main/python/rcmes/services/find_time_var.py b/src/main/python/rcmes/services/find_time_var.py
new file mode 100755
index 0000000..b099553
--- /dev/null
+++ b/src/main/python/rcmes/services/find_time_var.py
@@ -0,0 +1,87 @@
+#!/usr/local/bin/python
+"""
+    Small command line utility to find what the time variable is called in a model file.
+    
+    Background::  
+        Model output files tend not to follow any defined standard in terms of 
+        variable naming conventions.  One model may call the time "time", 
+        another one may call it "t".  This script looks for the existence of 
+        any of a predefined list of synonyms for time.
+    
+    This script should be run from the command line (i.e. not called from within python)
+    
+    Input::
+        -filename
+    
+    Output::
+        -success flag (1 or 0): were both latitude and longitude variable names found in the file?
+        
+        if successful:
+            -name of time variable
+            -(TODO) modelStartTime -descriptions of time ranges in data files
+            -(TODO) modelEndTime
+        if unsuccessful:
+            -list of variable names in file
+    
+    (NB. all printed to standar output)
+"""
+
+import sys
+import bottle
+from bottle import request
+import Nio
+import json
+import decode_model_times as dmt
+
+
+#filename = sys.argv[1]
+
+
+@bottle.route('/list/time/:filename#".*"#')
+def list_time(filename):
+    filename = filename.strip('"')
+    success = 0
+    f = Nio.open_file(filename)
+    var_name_list = f.variables.keys()
+    # convert all variable names into lower case
+    var_name_list_lower = [x.lower() for x in var_name_list]
+    # create a "set" from this list of names
+    varset = set(var_name_list_lower)
+    # Use "set" types for finding common variable name from in the file and from the list of possibilities
+    time_possible_names = set(['time','t','times','date','dates','julian'])
+    # Search for common latitude name variants:
+    # Find the intersection of two sets, i.e. find what latitude is called in this file.
+    try:
+      time_var_name = list(varset & time_possible_names)[0]
+      success = 1
+      index = 0
+      for i in var_name_list_lower:
+       if i==time_var_name:
+            wh = index
+       index += 1
+      timename = var_name_list[wh]
+      
+    except:
+      timename = 'not_found'
+      success = 0
+    
+    if success:
+        print 'timename is '+timename
+        times = dmt.decode_model_times([filename],timename)
+        start_time = str(min(times))
+        end_time = str(max(times))
+        time_var = json.dumps({'success':success,'timename':timename,
+                               'start_time':start_time,'end_time':end_time})
+        #return time_var
+        if (request.query.callback):
+            return "%s(%s)" % (request.query.callback, time_var)
+        return time_var
+        
+    if success==0:
+        json_output = json.dumps({'success':success,'variables':var_name_list })
+    if (request.query.callback):
+        return "%s(%s)" % (request.query.callback, json_output)
+    return json_output
+       
+    #print success, var_name_list
+

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/rcmes/services/list_vars_in_file.py
----------------------------------------------------------------------
diff --git a/src/main/python/rcmes/services/list_vars_in_file.py b/src/main/python/rcmes/services/list_vars_in_file.py
new file mode 100755
index 0000000..43da7e6
--- /dev/null
+++ b/src/main/python/rcmes/services/list_vars_in_file.py
@@ -0,0 +1,59 @@
+#!/usr/local/bin/python
+"""
+ Small command line utility to list the variables contained within a model file.
+
+  This script should be run from the command line (i.e. not called from within python)
+
+       Input: 
+               -filename
+
+       Output: 
+               -list of variable names in file
+
+       (NB. all printed to standar output)
+
+       Peter Lean   February 2011
+
+ WEBSERVICE PLAN
+
+    URL:  localhost:9999/list_vars/:filename    (full file path plus file name)
+    Example:  localhost:9999/list/vars/"/usr/local/wrm/modeldata/wrf.nc"
+
+    Return:  JSON Array of Variable Names
+    Example:  { "variables": [ "time_bnds", "tas", "level", "lon", "time", "lat" ] }
+"""
+
+import sys
+import Nio
+import bottle
+from bottle import request
+import json
+#filename = sys.argv[1]
+
+
+@bottle.route('/list/vars/:filename#".*"#')
+def list_vars(filename):
+    success = 0
+    filename = filename.strip('"')
+    print filename + ' is filename variable'
+    try:
+      f = Nio.open_file(filename)
+      success = 1
+    except:
+      print 'Error_reading_file '+filename
+    
+    if success:  #make some json
+      var_name_list = json.dumps({'variables':f.variables.keys() }, \
+                                 sort_keys=True, indent=2)
+      if (request.query.callback):
+          return "%s(%s)" % (request.query.callback, var_name_list)
+      return var_name_list
+  
+    else:
+      failRet = "{\"FAIL\": \""+filename+"\"}"
+      if (request.query.callback):
+          return "%s(%s)" % (request.query.callback, failRet)
+      return failRet
+  
+
+

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/rcmes/services/main_ws.py
----------------------------------------------------------------------
diff --git a/src/main/python/rcmes/services/main_ws.py b/src/main/python/rcmes/services/main_ws.py
new file mode 100755
index 0000000..4d78f4d
--- /dev/null
+++ b/src/main/python/rcmes/services/main_ws.py
@@ -0,0 +1,36 @@
+"""Module that demonstrates how to initialize the RESTful web services that 
+power the RCMET GUI"""
+
+from bottle import route, response, run, static_file, hook
+import list_vars_in_file
+import find_latlon_var
+import find_time_var
+import decode_model_times as dmt
+import run_rcmes_processing
+import dataset_helpers
+import directory_helpers
+
+@route('/')
+@route('/index.html')
+def index():
+    return "<a href='/hello'>Go to Hello World page</a>"
+
+@route('/hello')
+def hello():
+    return "Hello World!"
+
+@route('/api/status')
+def api_status():
+    return {'status':'online', 'key':'value'}
+
+@route('/static/evalResults/<filename>')
+def get_eval_result_image(filename):
+    return static_file(filename, root="/tmp/rcmet")
+
+@hook('after_request')
+def enable_cors():
+    response.headers['Access-Control-Allow-Origin'] = '*'
+
+if __name__ == "__main__":
+    run(host='localhost', port=8082)
+    

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/rcmes/services/run_rcmes_processing.py
----------------------------------------------------------------------
diff --git a/src/main/python/rcmes/services/run_rcmes_processing.py b/src/main/python/rcmes/services/run_rcmes_processing.py
new file mode 100755
index 0000000..31c3efc
--- /dev/null
+++ b/src/main/python/rcmes/services/run_rcmes_processing.py
@@ -0,0 +1,114 @@
+#!/usr/local/bin/python
+"""Module used to launch the RESTful API"""
+import sys
+sys.path.append('../../.')
+from bottle import route, request
+import json
+import cli.do_rcmes_processing_sub as awesome
+import time
+import datetime
+import os
+time_format_new = '%Y-%m-%d %H:%M:%S'
+
+#Static Default params
+cachedir = '/tmp/rcmet/cache/'
+workdir = '/tmp/rcmet/'
+precipFlag =False
+seasonalCycleOption=0
+maskOption=False
+maskLatMin=0         # float (only used if maskOption=1)
+maskLatMax=0         # float (only used if maskOption=1)
+maskLonMin=0         # float (only used if maskOption=1)
+maskLonMax=0         # float (only used if maskOption=1)
+
+###########################################################
+##OPEN FOR DISCUSSION
+titleOption = 'default'   #this means that ' model vs obs :' will be used
+plotFileNameOption = 'default'  #another good option we can use.
+###########################################################
+
+@route('/rcmes/run/', method='POST')
+def rcmes_go():
+    print "**********\nBEGIN RCMES2.0_RUN\n**********"
+    print 'cachedir', cachedir
+    print 'workdir', workdir
+    
+    try:
+        if not os.path.exists(cachedir):
+            os.makedirs(cachedir)
+    except Error as e:
+        print "I/O error({0}: {1}".format(e.errno, e.strerror)
+        sys.exit(1)
+
+    obsDatasetId = int(request.POST.get('obsDatasetId', '').strip())
+    print 'obsDatasetId', obsDatasetId
+    obsParameterId = int(request.POST.get('obsParameterId', '').strip())
+    print 'obsParameterId', obsParameterId
+
+    #reformat DateTime after pulling it out of the POST
+    POSTstartTime = str(request.POST.get('startTime', '').strip())
+    startTime = datetime.datetime.fromtimestamp(time.mktime(time.strptime(POSTstartTime, time_format_new)))
+    print 'startTime', startTime
+    #reformat DateTime after pulling it out of the POST
+    POSTendTime = str(request.POST.get('endTime', '').strip())
+    endTime = datetime.datetime.fromtimestamp(time.mktime(time.strptime(POSTendTime, time_format_new)))
+    print 'endTime', endTime
+
+    latMin = float(request.POST.get('latMin', '').strip())
+    print 'latMin', latMin
+    latMax = float(request.POST.get('latMax', '').strip())
+    print 'latMax', latMax 
+    lonMin = float(request.POST.get('lonMin', '').strip())
+    print 'lonMin', lonMin
+    lonMax = float(request.POST.get('lonMax', '').strip())
+    print 'lonMax', lonMax
+
+    filelist = [request.POST.get('filelist', '').strip()]
+    print 'filelist', filelist[0]
+
+    modelVarName = str(request.POST.get('modelVarName', '').strip())
+    print 'modelVarName', modelVarName
+    precipFlag = request.POST.get('precipFlag', '').strip()
+    print 'precipFlag', precipFlag
+    modelTimeVarName = str(request.POST.get('modelTimeVarName', '').strip())
+    print 'modelTimeVarName', modelTimeVarName
+    modelLatVarName = str(request.POST.get('modelLatVarName', '').strip())
+    print 'modelLatVarName', modelLatVarName
+    modelLonVarName = str(request.POST.get('modelLonVarName', '').strip())
+    print 'modelLonVarName', modelLonVarName
+
+    regridOption = str(request.POST.get('regridOption', '').strip())
+    print 'regridOption', regridOption
+    timeRegridOption = str(request.POST.get('timeRegridOption', '').strip())
+    print 'timeRegridOption', timeRegridOption
+    seasonalCycleOption = request.POST.get('seasonalCycleOption', '').strip()
+    print 'seasonalCycleOption', seasonalCycleOption
+    metricOption = str(request.POST.get('metricOption', '').strip())
+    print 'metricOption', metricOption    
+    
+    settings = {"cacheDir": cachedir, "workDir": workdir, "fileList": filelist}
+    params = {"obsDatasetId": obsDatasetId, "obsParamId": obsParameterId, 
+              "startTime": startTime, "endTime": endTime, "latMin": latMin, 
+              "latMax": latMax, "lonMin": lonMin, "lonMax": lonMax}
+    model = {"varName": modelVarName, "timeVariable": modelTimeVarName, 
+             "latVariable": modelLatVarName, "lonVariable": modelLonVarName}
+    mask = {"latMin": latMin, "latMax": latMax, "lonMin": lonMin, "lonMax": lonMax}
+    options = {"regrid": regridOption, "timeRegrid": timeRegridOption, 
+               "seasonalCycle": seasonalCycleOption, "metric": metricOption, 
+               "plotTitle": titleOption, "plotFilename": plotFileNameOption, 
+               "mask": maskOption, "precip": precipFlag}
+    
+    awesome.do_rcmes(settings, params, model, mask, options)
+    
+    model_path = os.path.join(workdir, plotFileNameOption + "model.png")
+    obs_path = os.path.join(workdir, plotFileNameOption + "obs.png")
+    comp_path = os.path.join(workdir, plotFileNameOption + ".png")
+
+    product_dict = {'modelPath':model_path,
+                    'obsPath': obs_path,
+                    'comparisonPath':comp_path}
+    
+    #Extra Code in case bottle has an issue with my Dictionary
+    #json_output = json.dumps(product_dict, sort_keys=True, indent=4)
+    
+    return product_dict

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/rcmes/storage/.svn/all-wcprops
----------------------------------------------------------------------
diff --git a/src/main/python/rcmes/storage/.svn/all-wcprops b/src/main/python/rcmes/storage/.svn/all-wcprops
new file mode 100755
index 0000000..d794986
--- /dev/null
+++ b/src/main/python/rcmes/storage/.svn/all-wcprops
@@ -0,0 +1,29 @@
+K 25
+svn:wc:ra_dav:version-url
+V 87
+/repos/asf/!svn/ver/1480068/incubator/climate/trunk/rcmet/src/main/python/rcmes/storage
+END
+rcmed.py
+K 25
+svn:wc:ra_dav:version-url
+V 96
+/repos/asf/!svn/ver/1478642/incubator/climate/trunk/rcmet/src/main/python/rcmes/storage/rcmed.py
+END
+__init__.py
+K 25
+svn:wc:ra_dav:version-url
+V 99
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/python/rcmes/storage/__init__.py
+END
+files.py
+K 25
+svn:wc:ra_dav:version-url
+V 96
+/repos/asf/!svn/ver/1480068/incubator/climate/trunk/rcmet/src/main/python/rcmes/storage/files.py
+END
+db.py
+K 25
+svn:wc:ra_dav:version-url
+V 93
+/repos/asf/!svn/ver/1477399/incubator/climate/trunk/rcmet/src/main/python/rcmes/storage/db.py
+END

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/rcmes/storage/.svn/entries
----------------------------------------------------------------------
diff --git a/src/main/python/rcmes/storage/.svn/entries b/src/main/python/rcmes/storage/.svn/entries
new file mode 100755
index 0000000..8c1aa46
--- /dev/null
+++ b/src/main/python/rcmes/storage/.svn/entries
@@ -0,0 +1,164 @@
+10
+
+dir
+1485921
+https://svn.apache.org/repos/asf/incubator/climate/trunk/rcmet/src/main/python/rcmes/storage
+https://svn.apache.org/repos/asf
+
+
+
+2013-05-07T20:50:17.582309Z
+1480068
+joyce
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+13f79535-47bb-0310-9956-ffa450edef68
+
+rcmed.py
+file
+
+
+
+
+2013-05-24T10:13:49.000000Z
+803407ad94184e2f6239d2682702efac
+2013-05-03T04:58:26.210742Z
+1478642
+goodale
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+4021
+
+__init__.py
+file
+
+
+
+
+2013-05-24T10:13:49.000000Z
+4e9dbfccef9ab4a276f07ade07aff258
+2012-08-16T14:18:52.441820Z
+1473884
+cgoodale
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+155
+
+files.py
+file
+
+
+
+
+2013-05-24T10:13:49.000000Z
+cf3619b65673cad26da99ec2db890e0b
+2013-05-07T20:50:17.582309Z
+1480068
+joyce
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+26761
+
+db.py
+file
+
+
+
+
+2013-05-24T10:13:49.000000Z
+eb9168618a22875ffe95233be228ccea
+2013-04-29T22:53:37.442679Z
+1477399
+boustani
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+13777
+

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/rcmes/storage/.svn/prop-base/__init__.py.svn-base
----------------------------------------------------------------------
diff --git a/src/main/python/rcmes/storage/.svn/prop-base/__init__.py.svn-base b/src/main/python/rcmes/storage/.svn/prop-base/__init__.py.svn-base
new file mode 100755
index 0000000..614166f
--- /dev/null
+++ b/src/main/python/rcmes/storage/.svn/prop-base/__init__.py.svn-base
@@ -0,0 +1,5 @@
+K 12
+svn:keywords
+V 11
+Id Revision
+END

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/rcmes/storage/.svn/text-base/__init__.py.svn-base
----------------------------------------------------------------------
diff --git a/src/main/python/rcmes/storage/.svn/text-base/__init__.py.svn-base b/src/main/python/rcmes/storage/.svn/text-base/__init__.py.svn-base
new file mode 100755
index 0000000..a1d4f62
--- /dev/null
+++ b/src/main/python/rcmes/storage/.svn/text-base/__init__.py.svn-base
@@ -0,0 +1,2 @@
+"""This Package is used to handle various forms of data storage from opening
+files to accessing the RCMED and returning data in the form of numpy arrays"""
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/rcmes/storage/.svn/text-base/db.py.svn-base
----------------------------------------------------------------------
diff --git a/src/main/python/rcmes/storage/.svn/text-base/db.py.svn-base b/src/main/python/rcmes/storage/.svn/text-base/db.py.svn-base
new file mode 100755
index 0000000..d34e4fe
--- /dev/null
+++ b/src/main/python/rcmes/storage/.svn/text-base/db.py.svn-base
@@ -0,0 +1,343 @@
+"""Collection of functions used to interface with the database and to create netCDF file
+"""
+import os
+import urllib2
+import re
+import numpy as np
+import numpy.ma as ma
+import json
+import Nio
+
+from classes import RCMED
+from toolkit import process
+from datetime import timedelta ,datetime
+from calendar import monthrange
+
+def reorderXYT(lons, lats, times, values):
+    # Re-order values in values array such that when reshaped everywhere is where it should be
+    #  (as DB doesn't necessarily return everything in order)
+    order = np.lexsort((lons, lats, times))
+    counter = 0
+    sortedValues = np.zeros_like(values)
+    sortedLats = np.zeros_like(lats)
+    sortedLons = np.zeros_like(lons)
+    for i in order:
+        sortedValues[counter] = values[i]
+        sortedLats[counter] = lats[i]
+        sortedLons[counter] = lons[i]
+        counter += 1
+    
+    return sortedValues, sortedLats, sortedLons
+
+def findUnique(seq, idfun=None):
+    """
+     Function to find unique values (used in construction of unique datetime list)
+     NB. order preserving
+     Input: seq  - a list of randomly ordered values
+     Output: result - list of ordered values
+    """
+    if idfun is None:
+        def idfun(x): 
+            return x
+
+    seen = {};
+    result = []
+    
+    for item in seq:
+        marker = idfun(item)
+        # in old Python versions:
+        # if seen.has_key(marker)
+        # but in new ones:
+        if marker in seen: continue
+        seen[marker] = 1
+        result.append(item)
+    return result
+
+def get_param_info(url):
+
+    '''
+    This function will get the general information by given URL from the parameter table.
+    '''
+    url = url + "&info=yes"
+    result = urllib2.urlopen(url)
+    datastring = result.read()
+    datastring=json.loads(datastring)
+    database=datastring["database"]
+    timestep=datastring["timestep"]
+    realm=datastring["realm"]
+    instrument=datastring["instrument"]
+    start_date=datastring["start_date"]
+    end_date=datastring["end_date"]
+    unit=datastring["units"]
+    
+    return database, timestep, realm, instrument, start_date, end_date, unit
+
+def get_data(url):
+    
+    '''
+    This function will get the url, query from database and will return datapoints' latitude, longitude, level, time and value.
+    '''
+
+    result = urllib2.urlopen(url)
+    datastring = result.read()    
+    d = re.search('data: \r\n', datastring)
+    data = datastring[d.end():len(datastring)]
+    
+    # To create a list of all datapoints
+    data=data.split('\r\n')    
+            
+    latitudes = []
+    longitudes = []
+    levels = []
+    values = []
+    timestamps = []
+    
+    # To make a series of lists from datapoints
+    for i in range(len(data)-1):  # Because the last row is empty, "len(data)-1" is used.
+        row=data[i].split(',')
+        latitudes.append(np.float32(row[0]))
+        longitudes.append(np.float32(row[1]))
+        levels.append(np.float32(row[2]))
+        # timestamps are strings so we will leave them alone for now
+        timestamps.append(row[3])
+        values.append(np.float32(row[4]))
+        
+    return latitudes, longitudes, levels, values, timestamps
+    
+
+def create_netCDF(latitudes, longitudes, levels, values, timestamps, database, latMin, latMax, lonMin, lonMax, startTime, endTime, unit, netCD_fileName):
+    
+    '''
+    This function will generate netCDF files.
+    '''
+        
+    # To generate netCDF file from database
+    netcdf =  Nio.open_file(netCD_fileName,'w')
+    string="The netCDF file for parameter: " + database + ", latMin: " + str(latMin) + ", latMax: " + str(latMax) + ", lonMin: " + str(lonMin) + ", lonMax: " + str(lonMax) + " startTime: " + str(startTime) + " and endTime: " + str(endTime) + "."
+    netcdf.globalAttName = str(string)
+    netcdf.create_dimension('dim', len(latitudes))
+    latitude = netcdf.create_variable('lat', 'd', ('dim',))
+    longitude = netcdf.create_variable('lon', 'd', ('dim',))
+    level = netcdf.create_variable('lev', 'd', ('dim',))
+    time = netcdf.create_variable('time', 'd', ('dim',))
+    value = netcdf.create_variable('value', 'd', ('dim',))
+    
+    netcdf.variables['lat'].varAttName = 'latitude'
+    netcdf.variables['lat'].units = 'degrees_north'
+    netcdf.variables['lon'].varAttName = 'longitude'
+    netcdf.variables['lon'].units = 'degrees_east'
+    netcdf.variables['time'].varAttName = 'time'
+    netcdf.variables['time'].units = 'hours since ' + str(startTime)
+    netcdf.variables['value'].varAttName = 'value'
+    netcdf.variables['value'].units = str(unit)
+    netcdf.variables['lev'].varAttName = 'level'
+    netcdf.variables['lev'].units = 'hPa'
+
+    hours=[]
+    timeFormat = "%Y-%m-%d %H:%M:%S"
+    base_date=startTime
+    # To convert the date to hours 
+    for t in timestamps:
+        date=datetime.strptime(t, timeFormat)
+        diff=date-base_date
+        hours.append(diff.days*24)
+        
+    latitude[:]=latitudes[:]
+    longitude[:]=longitudes[:]
+    level[:]=levels[:]
+    time[:]=hours[:]
+    value[:]=values[:]
+    netcdf.close()
+        
+def read_netcdf(netCD_fileName):
+    
+    '''
+    This function will read the existed netCDF file, convert the hours from netCDF time variable
+    and return latitudes, longitudes, levels, times and values.
+    '''
+    # To use the created netCDF file
+    netcdf = Nio.open_file(netCD_fileName , 'r')
+    # To get all data from netCDF file
+    latitudes = netcdf.variables['lat'][:]
+    longitudes = netcdf.variables['lon'][:]
+    levels = netcdf.variables['lev'][:]
+    hours = netcdf.variables['time'][:]
+    values = netcdf.variables['value'][:]
+    
+    # To get the base date
+    time_unit=netcdf.variables['time'].units
+    time_unit=time_unit.split(' ')
+    base_date=time_unit[2] + " " + time_unit[3]
+    
+    netcdf.close()
+    
+    timeFormat = "%Y-%m-%d %H:%M:%S"
+    
+    # Because time in netCDF file is based on hours since a specific date, it needs to be converted to date format
+    times=[]
+    # To convert the base date to the python datetime format
+    base_date = datetime.strptime(base_date, timeFormat)
+    for each in range(len(hours)): 
+        hour=timedelta(hours[each]/24)    
+        eachTime=base_date + hour
+        times.append(str(eachTime.year) + '-' + str("%02d" % (eachTime.month)) + '-' + str("%02d" % (eachTime.day)) + ' ' + str("%02d" % (eachTime.hour)) + ':' + str("%02d" % (eachTime.minute)) + ':' + str("%02d" % (eachTime.second)))
+
+    return latitudes, longitudes, levels, times, values
+
+
+def improve_data(latitudes, longitudes, levels, times, values, timestep):
+    
+    # Make arrays of unique latitudes, longitudes, levels and times
+    uniqueLatitudes = np.unique(latitudes)
+    uniqueLongitudes = np.unique(longitudes)
+    uniqueLevels = np.unique(levels)
+    uniqueTimestamps = np.unique(times)
+    
+    # Calculate nx and ny
+    uniqueLongitudeCount = len(uniqueLongitudes)
+    uniqueLatitudeCount = len(uniqueLatitudes)
+    uniqueLevelCount = len(uniqueLevels)
+    uniqueTimeCount = len(uniqueTimestamps)
+
+    values, latitudes, longitudes = reorderXYT(longitudes, latitudes, times, values)
+
+    # Convert each unique time from strings into list of Python datetime objects
+    # TODO - LIST COMPS!
+    timeFormat = "%Y-%m-%d %H:%M:%S"
+    timesUnique = [datetime.strptime(t, timeFormat) for t in uniqueTimestamps]
+    timesUnique.sort()
+    timesUnique = process.normalizeDatetimes(timesUnique, timestep)
+
+    # Reshape arrays
+    latitudes = latitudes.reshape(uniqueTimeCount, uniqueLatitudeCount, uniqueLongitudeCount, uniqueLevelCount)
+    longitudes = longitudes.reshape(uniqueTimeCount, uniqueLatitudeCount, uniqueLongitudeCount, uniqueLevelCount)
+    levels = np.array(levels).reshape(uniqueTimeCount, uniqueLatitudeCount, uniqueLongitudeCount, uniqueLevelCount)
+    values = values.reshape(uniqueTimeCount, uniqueLatitudeCount, uniqueLongitudeCount, uniqueLevelCount)
+
+    # Flatten dimension if only single level
+    if uniqueLevelCount == 1:
+        values = values[:, :, :, 0]
+        latitudes = latitudes[0, :, :, 0]
+        longitudes = longitudes[0, :, :, 0]
+
+    # Created masked array to deal with missing values
+    #  -these make functions like values.mean(), values.max() etc ignore missing values
+    mdi = -9999  # TODO: extract this value from the DB retrieval metadata
+    mdata = ma.masked_array(values, mask=(values == mdi))
+
+
+    return latitudes, longitudes, uniqueLevels, timesUnique, mdata
+    
+    
+def extractData ( datasetID, paramID, latMin, latMax, lonMin, lonMax, userStartTime, userEndTime, cachedir, timestep ):
+    
+    """
+    Main function to extract data from DB into numpy masked arrays, and also to create monthly netCDF file as cache
+    
+    Input::
+        datasetID, paramID: required identifiers of data in database
+        latMin, latMax, lonMin, lonMax: location range to extract data for
+        startTime, endTime: python datetime objects describing required time range to extract
+        cachedir: directory path used to store temporary cache files
+        timestep: "daily" | "monthly" so we can be sure to query the RCMED properly
+    Output:
+        uniqueLatitudes,uniqueLongitudes: 1d-numpy array of latitude and longitude grid values
+        uniqueLevels:	1d-numpy array of vertical level values
+        timesUnique: list of python datetime objects describing times of returned data
+        mdata: masked numpy arrays of data values
+    """
+
+    url = RCMED.jplUrl(datasetID, paramID, latMin, latMax, lonMin, lonMax, userStartTime, userEndTime, cachedir, timestep) 
+    
+    # To get the parameter's information from parameter table
+    database, timestep, realm, instrument, dbStartDate, dbEndDate, unit = get_param_info(url)
+        
+    # Create a directory inside the cache directory
+    name = []
+    # activity is a fix value
+    activity = "obs4cmip5"
+    name.append(activity)
+    # product is a fix value
+    product = "observations"
+    name.append(product)
+    # realm, variable,frequency and instrument will be get from parameter table
+    realm = realm
+    name.append(realm)
+    variable = database
+    name.append(variable)
+    frequency = timestep
+    name.append(frequency)
+    data_structure = "grid"
+    name.append(data_structure)
+    institution = "NASA"
+    name.append(institution)
+    project = "RCMES"
+    name.append(project)
+    instrument = instrument
+    name.append(instrument)
+    version = "v1"
+    name.append(version)
+    
+    # Check to see whether the folder is already created for netCDF or not, then it will be created
+    os.chdir(cachedir)
+    path=os.getcwd()
+    for n in name:
+        if os.path.exists(path + "/" + n):
+            os.chdir(path + "/" + n)
+            path=os.getcwd()
+        else:
+            os.mkdir(n)
+            os.chdir(path + "/" + n)
+            path=os.getcwd()
+
+    processing_level = 'L3'
+    processing_version = "processing_version"  # the processing version is still unknown and can be added later
+    
+    timeFormat = "%Y-%m-%d %H:%M:%S"
+   
+    date_list, lats, longs, uniqueLevls, uniqueTimes, vals = [], [], [], [], [], []
+
+    # To make a list (date_list) of all months available based on user time request
+    while userStartTime <= userEndTime:
+        #To get the beginning of month
+        beginningOfMonth = str("%04d" % userStartTime.year) + "-" + str("%02d" % userStartTime.month) + "-" + "01 00:00:00"
+        #To get the end of month
+        endOfMonth = str("%04d" % userStartTime.year) + "-" + str("%02d" % userStartTime.month) + "-" + str(monthrange(userStartTime.year,userStartTime.month)[1]) + " 00:00:00"
+        #To convert both beginning and end of month from string to Python datetime format
+        beginningOfMonth = datetime.strptime(beginningOfMonth, timeFormat)
+        endOfMonth = datetime.strptime(endOfMonth, timeFormat)
+        #To add beginning and end of month as a list to the date_list list
+        date_list.append([beginningOfMonth, endOfMonth])
+        #To get the beginning of next month
+        userStartTime= endOfMonth + timedelta(days=1)
+
+    print 'Starting retrieval data (this may take several minutes) ...... ' 
+    # To loop over all months and return data
+    for date in date_list:
+        netCDF_name = variable + '_' + project + '_' + processing_level + '_' + processing_version + '_' + str(latMin) + '_' + str(latMax) + '_' + str(lonMin) + '_' + str(lonMax) + '_' + str("%04d" % date[0].year) + str("%02d" % date[0].month) + '.nc'
+        
+        # To check if netCDF file  exists, then use it
+        if os.path.exists(path+"/"+ netCDF_name):
+            latitudes, longitudes, levels, times, values = read_netcdf(path + "/" + netCDF_name)  
+        
+        # If the netCDF file does not exist, then create one and read it.
+        else:            
+            # To just query for one year of data
+            url = RCMED.jplUrl(datasetID, paramID, latMin, latMax, lonMin, lonMax, date[0], date[1], cachedir, timestep)
+            
+            # To get data from DB
+            latitudes, longitudes, levels, values, timestamps = get_data(url)
+            create_netCDF(latitudes, longitudes, levels, values, timestamps, database, latMin, latMax, lonMin, lonMax, date[0], date[1], unit, path + "/" + netCDF_name)
+
+            # To read from netCDF files
+            latitudes, longitudes, levels, times, values = read_netcdf(path + "/" + netCDF_name)            
+
+        lats=np.append(lats,latitudes)
+        longs=np.append(longs,longitudes)
+        uniqueLevls=np.append(uniqueLevls,levels)
+        uniqueTimes=np.append(uniqueTimes,times)
+        vals=np.append(vals,values)
+        
+    latitudes, longitudes, uniqueLevels, timesUnique, mdata = improve_data(lats, longs, uniqueLevls, uniqueTimes, vals, timestep)
+        
+    return latitudes, longitudes, uniqueLevels, timesUnique, mdata


[38/51] [abbrv] [partial] Adding Jinwon's custom RCMET

Posted by jo...@apache.org.
http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/rcmes/utils/.svn/text-base/misc.py.svn-base
----------------------------------------------------------------------
diff --git a/src/main/python/rcmes/utils/.svn/text-base/misc.py.svn-base b/src/main/python/rcmes/utils/.svn/text-base/misc.py.svn-base
new file mode 100755
index 0000000..7b9c215
--- /dev/null
+++ b/src/main/python/rcmes/utils/.svn/text-base/misc.py.svn-base
@@ -0,0 +1,1326 @@
+"""Module with a collection of helper functions"""
+
+
+import ConfigParser
+import datetime
+import glob
+import json
+import os
+import sys
+
+import numpy as np
+import numpy.ma as ma
+import Nio
+
+import classes
+
+from fortranfile import FortranFile
+
+
+def configToDict(config):
+    """
+    Helper function to parse a configuration input and return a python dictionary
+    
+    Input::  
+        config - list of ('key', 'value') tuples from ConfigParser.
+            key01 - string i.e. 'value01'
+            key-2 - string i.e. 'value02'
+    Output::
+        configDict - Dictionary of Key/Value pairs
+    """
+    configDict = {}
+    for entry in config:
+        configDict[entry[0]] = entry[1]
+
+    return configDict
+
+
+def readSubRegionsFile(regionsFile):
+    """
+    Input::
+        regionsFile - Path to a subRegion configuration file
+        
+    Output::
+        Ordered List of SubRegion Objects decoded from regionsFile
+    """
+    if os.path.exists(regionsFile):
+        regionsConfig = ConfigParser.SafeConfigParser()
+        regionsConfig.optionxform = str
+        regionsConfig.read(regionsFile)
+        regions = generateSubRegions(regionsConfig.items('REGIONS'))
+
+        return regions
+    else:
+        raise IOError
+
+def getSubRegionsInteractively(counts, workdir):
+    """
+    Purpose::
+        This function provides a commandline Q&A session to help users define 
+        SubRegion Objects.
+    Input::
+        counts - dictionary with int counts of various metric inputs
+            i.e. {'observations': 3,
+                  'models'      : 1,
+                  'times'       : 120}
+        workdir - string of the current working directory where auxillary files
+        can be found.  In this case the directory will be used to locate an 
+        existing sub_regions.txt file.
+
+    Output:: 
+        subRegions = List of Parsed SubRegion Objects based on User inputs 
+    """
+    do_timeseries = None
+    yes_no_list = ['y', 'n', '']
+    
+    while do_timeseries not in yes_no_list:
+        do_timeseries = raw_input('Calculate area-mean timeseries for subregions? y/n: [n] \n>>>')
+        if do_timeseries not in yes_no_list:
+            print("'%s' is not a valid answer please try again" % do_timeseries)
+
+    if do_timeseries == 'y':
+        interactive_subregions = None
+        while interactive_subregions not in yes_no_list:
+            interactive_subregions = raw_input('Input Sub Region info interactively? y/n: [n] \n>>>')
+            if interactive_subregions not in yes_no_list:
+                print("'%s' is not a valid answer please try again" % interactive_subregions)
+            
+        if interactive_subregions == 'y':
+            while interactive_subregions == 'y':
+                regions = []
+                region = createSubRegionObjectInteractively()
+                regions.append(region)
+                anotherRegion = None
+                while anotherRegion == None:
+                    another = raw_input("Would you like to add another sub region? y/n [n] \n>>>")
+                    if another not in yes_no_list:
+                        print("'%s' is not a valid answer please try again" % another)
+                    elif another in ['', 'n']:
+                        anotherRegion = 'n'
+                        interactive_subregions = 'n'
+                    else:
+                        anotherRegion = 'y'
+
+        else:
+            subRegionFilename = None
+            while subRegionFilename == None:
+                readDefault = raw_input('Read from a default file (workdir + "/sub_regions.txt")? y/n: [y] \n>>>')
+
+                if readDefault == 'y' or readDefault == '':
+                    subRegionFilename = workdir + "/sub_regions.txt"
+                    print("Attempting to parse %s..." % subRegionFilename)
+                    regions = readSubRegionsFile(subRegionFilename)
+
+                elif readDefault == 'n':
+                    while subRegionFilename == None:
+                        # ask about using a non default filename
+                        subRegionFilename = raw_input('Enter the full path to the Sub Region file to read from:\n>>>')
+                        print("Attempting to parse %s..." % subRegionFilename)
+                        regions = readSubRegionsFile(subRegionFilename)
+
+                elif readDefault == 'NONE':
+                    subRegionFilename = 'NONE'
+                    regions = []
+            
+                else:
+                    print("'%'s is not a valid selection.  Please try again.  To proceed without Sub Regions defined enter NONE at the prompt" % readDefault)
+
+        return regions
+
+def generateSubRegions(regions):
+    """ Takes in a list of ConfigParser tuples and returns a list of SubRegion objects
+    
+    Input::
+        regions - Config Tuple: [('Region01', '["R01", 36.5, 29, 0.0, -10]'), ('Region02',....]
+
+    Output::
+        subRegions - list of SubRegion objects
+    """
+    subRegions = []
+    for region in regions:
+        name, latMax, latMin, lonMax, lonMin = json.loads(region[1])
+        subRegion = classes.SubRegion(name, latMin, lonMin, latMax, lonMax)
+        subRegions.append(subRegion)
+
+    return subRegions
+
+def parseSubRegions(subRegionConfig):
+    """
+    Input::
+        subRegionConfig - ConfigParser object
+    
+    Output::
+        subRegions - List of SubRegion Objects.  This could return an empty List if unable to parse subRegionConfig
+    """
+    subRegions = []
+    try:
+        if os.path.exists(subRegionConfig['subRegionFile']):
+            subRegions = readSubRegionsFile(subRegionConfig['subRegionFile'])
+            
+        else:
+            print "SubRegion Filepath: [%s] does not exist.  Check your configuration file, or comment out the SUB_REGION Section." % (subRegionConfig['subRegionFile'],)
+            print "Processing without SubRegion support"
+
+
+    except IOError:
+        print "Unable to open %s.  Running without SubRegions" % (subRegionConfig['subRegionFile'],)
+    except KeyError:
+        print "subRegionFile parameter was not provided.  Processing without SubRegion support"
+
+    return subRegions
+
+
+def decode_wrf_times(xtimes, base_time):
+    '''
+      Routine to convert from WRF time ('minutes since simulation start....') 
+      into a python datetime structure
+    
+      Input:
+          xtimes - list of wrf 'XTIME' in units of 'minutes since simulation start'
+          base_time - a python datetime object describing simulation start date/time
+    
+      Output:
+          times  - list of python datetime objects describing model data times
+    
+    
+         Peter Lean August 2010
+    
+    '''
+    times = []
+    for xtime in xtimes:
+        dt = datetime.timedelta(minutes=xtime)
+        times.append(base_time + dt)
+    
+    return times
+
+def calc_base_time_wrf(filename):
+    '''
+      Routine to calculate base_time (i.e. model initialization time)
+       for wrf files with timestamp in their filenames.
+      
+        NB. Only works if includes a timestamp in format 'YYYY-MM-DD_HH:MM:SS'
+        TODO: work out a more general way of doing this...
+      Input:
+          filename - full path to WRF netCDF file.
+    
+      Output:
+          base_time  - a python datetime object describing model start time
+    
+         Peter Lean August 2010
+    
+    '''
+    
+    # Extract time from netCDF file (in units of 'minutes since beginning of simulation')
+    f = Nio.open_file(filename, format='nc')
+    timesraw = f.variables["XTIME"]
+    model_time = timesraw[0]
+    
+    dt = datetime.timedelta(minutes=int(model_time))
+           
+    # Extract and decode timestamp from filename
+    
+    filename = os.path.basename(filename)  # strip off the filepath
+    
+    timestamp_string = filename[11:30]   # cut out the date time stamp
+    DATE_FORMAT = '%Y-%m-%d_%H:%M:%S'  
+    
+    timestamp = datetime.datetime(*time.strptime(timestamp_string, DATE_FORMAT)[:6])
+    
+    # Base Time = timestamp - 'minutes since beginning of simulation'
+    base_time = timestamp - dt
+    
+    print 'Base Time calculated as: ', base_time
+    
+    return base_time
+
+def calc_period_precip_from_running_tot(running_precip):
+    '''
+     WRF precipitation accumulations are stored as running totals from the start of the model run
+     To find out values during each output time period, you must subtract the previous total
+    
+       e.g. running tot = 0,0,1,1,1,2,2,4,7,9,9,11 
+            period accu = 0,0,1,0,0,1,0,2,3,2,0,2
+    
+      Input: 
+         running_precip   - numpy array containing precipitation data at more than one time level
+                             NB. assumes time dimension is the first one precip[time, lat, lon, level] 
+    
+      Output:
+         acc_precip       - numpy array of same dimensions as input, 
+                            but with period accumulations instead of running total.
+    
+    
+        Peter Lean August 2010
+    
+    '''
+    
+    print 'Calculating period precip accumulations from running total'
+    shifted_running_precip = np.roll(running_precip, -1, axis=0)
+    nt = running_precip.shape[0]
+    # avoid wrapping from the end time to the start time by forcing the accumulation at final time=0
+    shifted_running_precip[nt - 1, :, :] = running_precip[nt - 1, :, :]
+    acc_precip = shifted_running_precip - running_precip 
+
+    # NB. sometimes rounding errors in the model lead to very small negative period accumulations
+    #     These are removed and set to zero here.
+    acc_precip = np.maximum(acc_precip, 0)
+
+    return acc_precip
+
+def decode_eraint_surf_times(xtimes):
+    '''
+      Routine to convert from ERA-Interim time ('hours since 1900...') 
+      into a python datetime structure
+    
+      Input:
+          xtimes - list of ERA-Interim times in units of 'hours since 1900'
+    
+      Output:
+          times  - list of python datetime objects describing model data times
+    
+    
+         Peter Lean August 2010
+    
+    '''
+    base_time = datetime.datetime(1900, 1, 1, 0, 0, 0, 0)
+    times = []
+    
+    for xtime in xtimes:
+        dt = datetime.timedelta(hours=xtime)
+        times.append(base_time + dt)
+    
+    return times
+
+def read_total_precip_from_filelist(myfilelist):
+    '''
+     WRF outputs precipitation data under several variables:
+     
+         **RAINC** =  convective total precip
+         
+         **RAINNC** = large scale total precip  ("no convective")
+         
+         **SNOWC** =  convective snow
+         
+         **SNOWNC** = large scale snow  ("no convective")
+     
+     Therefore: 
+         real rain = (rainc+rainnc)-(snowc+snownc)
+         total precip = rainc+rainnc+snowc+snownc
+         
+     Input:
+         myfilelist - a list of filename (including full path)
+           
+     Output:
+         precip - a numpy array of total precip values
+         lat, lon - 2D array of latitude and longitude values
+         times    - list of times
+     
+     NB. THIS ROUTINE IS NO LONGER NEEDED... I HAD MISUNDERSTOOD HOW PRECIP DATA WAS STORED IN WRF
+     TOTAL PRECIP  = RAINNC
+     **A SIMILAR ROUTINE MAY BE REQUIRED TO FIND THE INDIVIDUAL COMPONENTS THOUGH..**
+    
+    '''
+    myfilelist.sort()
+
+    print 'Calculating total precipitation from individual rain/snow, convective/ls components'
+    lat, lon, times, rainnc = read_data_from_file_list(myfilelist, 'RAINC')
+    lat, lon, times, rainc = read_data_from_file_list(myfilelist, 'RAINNC')
+    precip = rainnc + rainc
+    # reset negative values to zero
+    precip[precip < 0] = 0.0
+
+    return lat, lon, times, precip
+
+
+def isDirGood(directory):
+    """
+    Purpose::
+        This function will check if a directory exists and is writeable.  If the directory doesn't exist it is created.
+    Input::
+        directory - Path we need to check 
+    Output::
+        directoryStatus - Boolean
+    """
+    directoryStatus = False
+    
+    if os.path.exists(directory):
+        directoryStatus = os.access(directory, os.W_OK | os.X_OK)
+        if directoryStatus:
+            pass
+        else:
+            raise OSError("Unable to access the directory: %s.  Check that you have the proper permissions to read and write to that directory." % directory)
+            #directoryStatus = False
+    else:
+        try:
+            os.mkdir(directory)
+            directoryStatus = True
+        except OSError:
+            raise
+
+    return directoryStatus
+    
+
+def read_trmm_3b42_files(filelist, latMin, latMax, lonMin, lonMax):
+    '''
+     ** Alternate method of getting TRMM data from local repository if DB not available **
+     Reads TRMM gridded precipitation data from netCDF files in local repository.
+    
+     Input:
+        filelist - list of filenames (including path)
+        latMin,latMax,lonMin,lonMax - define region to extract (in degrees)
+     Output:
+        lat, lon   - 1D array of latitude and longitude values
+        timestore  - list of python datetime objects
+        mdata      - numpy masked array containing data from all files    
+    
+      NB. written specific for TRMM netCDF output files
+    
+       Peter Lean June 2010 
+    '''
+    filelist.sort()
+
+    # Crash nicely if 'filelist' is zero length
+    if len(filelist) == 0:
+        print 'Error: no files have been passed to read_data_from_file_list()'
+        sys.exit()
+    
+    # Open the first file in the list to:
+    #    i) read in lats, lons
+    #    ii) find out how many timesteps in the file 
+    #        (assume same ntimes in each file in list)
+    #     -allows you to create an empty array to store variable data for all times
+    tmp = Nio.open_file(filelist[0], format='nc')
+    latsraw = tmp.variables["latitude"]
+    lonsraw = tmp.variables["longitude"]
+    lat = latsraw[:]
+    lon = lonsraw[:]
+    print 'Lats and lons read in for first file in filelist'
+
+    # Find out how many times there are in the file (should always be 1 for these TRMM files)
+    timesraw = tmp.variables["time"]
+    ntimes = len(timesraw)
+    
+    
+    # Convert specified longitudes into 0-360 format if required
+    if(lonMin < 0):
+        lonMin = lonMin + 360
+    if(lonMax < 0):
+        lonMax = lonMax + 360
+
+    # Create mask to extract required region only
+    #  NB. longitude is slightly more complicated as can wrap the prime meridion
+    print 'Extracting for :- lats:', latMin, latMax, ' lons: ', lonMin, lonMax
+    wh_lat = np.logical_and((lat > latMin), (lat < latMax))
+    if(lonMin <= lonMax):
+        wh_lon = np.logical_and((lon > lonMin), (lon < lonMax))
+    if(lonMin > lonMax):
+        wh_lon = np.logical_or((lon > lonMin), (lon < lonMax))
+    
+    sublat = lat[wh_lat]
+    sublon = lon[wh_lon]
+    
+    wh_true1, wh_true2 = np.meshgrid(wh_lon, wh_lat)
+    wh = np.logical_and(wh_true1, wh_true2)
+    
+    # Create empty array to store data
+    t2store = np.empty((ntimes * len(filelist), sublat.size, sublon.size))
+    timestore = []
+
+    # Now load in the data for real
+    #  NB. no need to reload in the latitudes and longitudes -assume invariant
+    i = 0
+    timesaccu = 0 # a counter for number of times stored so far in t2store 
+    #  NB. this method allows for missing times in data files 
+    #      as no assumption made that same number of times in each file...
+    for ifile in filelist:
+        print 'Loading data from file: ', filelist[i]
+        f = Nio.open_file(ifile, format='nc')
+        t2raw = f.variables['hrf']
+        
+        # Read time from filename (NB. 'time' variable in netCDF always set to zero)
+        filename = os.path.basename(ifile)  # strip off the filepath
+        timestamp_string = filename[11:23]   # cut out the date time stamp
+        DATE_FORMAT = '%Y.%m.%d.%H'  
+        mytime = datetime.datetime(*time.strptime(timestamp_string, DATE_FORMAT)[:4])
+        ntimes = 1
+        t2tmp = t2raw[0, :, :]
+        sub = t2tmp[wh].reshape(sublat.size, sublon.size)
+        t2store[timesaccu, :, :] = sub
+        timestore.append(mytime)
+        timesaccu = timesaccu + ntimes
+        i += 1 
+    
+    print 'Data read in successfully with dimensions: ', t2store.shape
+    
+    # Create masked array using missing value flag from file
+    mdi = f.variables['hrf'].missing_value[0]
+    mdata = ma.masked_array(t2store, mask=(t2store == mdi))
+    
+    return sublat, sublon, timestore, mdata
+
+def read_airs_lev3_files(filelist, myvar, latMin, latMax, lonMin, lonMax):
+    '''
+     ** For testing work before database was ready. **
+     Reads AIRS level III gridded data from netCDF files.
+    
+     Input:
+        filelist - list of filenames (including path)
+        myvar    - name of variable to load
+        latMin,latMax,lonMin,lonMax - define region to extract (in degrees)
+     Output:
+        lat, lon   - 1D array of latitude and longitude values
+        timestore  - list of python datetime objects
+        mdata      - numpy masked array containing data from all files    
+    
+      NB. written specific for AIRS level III netCDF output files
+    
+      NB. Ascending passes have local time of 1:30pm
+      NB. Descending passes have local time of 1:30am
+    
+       Peter Lean June 2010 
+    '''
+    
+    filelist.sort()
+    
+    # Crash nicely if 'filelist' is zero length
+    if len(filelist) == 0:
+        print 'Error: no files have been passed to read_data_from_file_list()'
+        sys.exit()
+
+    # Open the first file in the list to:
+    #    i) read in lats, lons
+    #    ii) find out how many timesteps in the file 
+    #        (assume same ntimes in each file in list)
+    #     -allows you to create an empty array to store variable data for all times
+    tmp = Nio.open_file(filelist[0], format='nc')
+    latsraw = tmp.variables["lat"]
+    lonsraw = tmp.variables["lon"]
+    lat = latsraw[:]
+    lon = lonsraw[:]
+    print 'Lats and lons read in for first file in filelist'
+
+    # Only one time per file in AIRS level III data
+    ntimes = 1
+    
+    # Create mask to extract required region only
+    #  NB. longitude is slightly more complicated as can wrap the prime meridion
+    print 'Extracting for :- lats:', latMin, latMax, ' lons: ', lonMin, lonMax
+    wh_lat = np.logical_and((lat >= latMin), (lat <= latMax))
+    if(lonMin < lonMax):
+        wh_lon = np.logical_and((lon >= lonMin), (lon <= lonMax))
+    if(lonMin > lonMax):
+        wh_lon = np.logical_or((lon >= lonMin), (lon <= lonMax))
+    
+    sublat = lat[wh_lat]
+    sublon = lon[wh_lon]
+    
+    wh_true1, wh_true2 = np.meshgrid(wh_lon, wh_lat)
+    wh = np.logical_and(wh_true1, wh_true2)
+    
+    # Create empty array to store data
+    t2store = np.empty((ntimes * len(filelist), sublat.size, sublon.size))
+    timestore = []
+
+    # Now load in the data for real
+    #  NB. no need to reload in the latitudes and longitudes -assume invariant
+    i = 0
+    timesaccu = 0 # a counter for number of times stored so far in t2store 
+    #  NB. this method allows for missing times in data files 
+    #      as no assumption made that same number of times in each file...
+    for ifile in filelist:
+        print 'Loading data from file: ', filelist[i]
+        f = Nio.open_file(ifile, format='nc')
+        t2raw = f.variables[myvar]
+        
+        # Read time from filename (NB. 'time' variable in netCDF always set to zero)
+        filename = os.path.basename(ifile)  # strip off the filepath
+        timestamp_string = filename[5:15]   # cut out the date time stamp
+        DATE_FORMAT = '%Y.%m.%d'  
+        mytime = datetime.datetime(*time.strptime(timestamp_string, DATE_FORMAT)[:4])
+        print mytime
+        ntimes = 1
+        t2tmp = t2raw[:, :]
+        sub = t2tmp[wh].reshape(sublat.size, sublon.size)
+        t2store[timesaccu, :, :] = sub
+        timestore.append(mytime)
+        timesaccu = timesaccu + ntimes
+        i += 1 
+
+
+    print 'Data read in successfully with dimensions: ', t2store.shape
+
+    # Create masked array using missing value flag from file
+    mdi = f.variables[myvar]._FillValue[0]
+    mdata = ma.masked_array(t2store, mask=(t2store == mdi))
+    # Rearrange array so data match lat lon values
+    mdata = np.flipud(mdata[:, ::-1])
+
+    return sublat, sublon, timestore, mdata
+
+def read_urd_files(filelist, latMin, latMax, lonMin, lonMax):
+    '''
+     Routine to load in NCEP Unified Raingauge Database binary files
+    
+      Input:
+         filelist - a list of URD data files
+    
+    
+      Output:
+         sublats, sublons: 2d arrays of latitude and longitude values for user selected region.
+         times - a list of python datetime objects
+         subdata - precipitation data for user selected region
+    
+      Peter Lean  August 2010
+    '''
+    
+    repository_path = '/nas/share1-hp/jinwonki/data/obs/pr25urd/daily/'
+    
+    # NB. Domain: 140W - 60W; 20N - 60N; Resolution: 0.25x0.25 degrees.
+    #     The grids are arranged such that
+    #     longitude is from 140W eastward to 60W and latitude from 20N northward
+    #     to 60N, so that the first grid is (140W,20N), the second is 
+    #     (139.75W,20N)......
+    
+    # Parameters specific to the URD dataset
+    nlat = 161
+    nlon = 321
+    
+    # Calculate the latitude and longitude arrays
+    lat = np.arange(20, 60.25, 0.25)  # Hard wired lat,lon extent values for URD data files
+    lon = np.arange(-140, -59.75, 0.25)
+    
+    lons, lats = np.meshgrid(lon, lat)
+
+    # Define sub-region mask 
+    #  NB. longitude is slightly more complicated as can wrap the prime meridion
+    print 'Extracting for :- lats:', latMin, latMax, ' lons: ', lonMin, lonMax
+    wh_lat = np.logical_and((lats >= latMin), (lats <= latMax))
+    if(lonMin < lonMax):
+        wh_lon = np.logical_and((lons >= lonMin), (lons <= lonMax))
+    if(lonMin > lonMax):
+        wh_lon = np.logical_or((lons >= lonMin), (lons <= lonMax))
+    
+    # count number of latitude values in subselection (for redimensioning array)
+    wh_true = np.logical_and(wh_lat, wh_lon)
+    nsublat = np.where(np.logical_and((lat >= latMin), (lat <= latMax)))[0].size
+    
+    sublats = lats[wh_true].reshape(nsublat, -1)  # infers longitude dimension given latitude dimension
+    sublons = lons[wh_true].reshape(nsublat, -1)  # infers longitude dimension given latitude dimension
+    nsublon = sublats.shape[1]
+
+    # Load in the daily data
+    datastore = []
+    for myfile in filelist:
+        f = FortranFile(repository_path + myfile)
+    
+        # Extract month and year from filename
+        yearmonth = int(myfile[7:13])
+        year = int(str(yearmonth)[0:4])
+        month = int(str(yearmonth)[4:6])
+        
+        # Find out how many days there are in that month
+        nt = calendar.monthrange(year, month)[1]
+        
+        data = np.zeros((nt, nsublat, nsublon))
+        for t in np.arange(nt):
+            precip = f.readReals()
+            precip.shape = [nlat, nlon]
+            data[t, :, :] = precip[wh_true].reshape(nsublat, nsublon) 
+        
+        datastore.append(data)
+
+    # Make a single 3d numpy array out of my list of numpy arrays
+    nt = 0
+    for i in range(len(datastore)):
+        nt = nt + datastore[i].shape[0]
+    
+    final_data = np.zeros((nt, nsublat, nsublon))
+    t = 0
+    for i in range(len(datastore)):
+        nt = datastore[i].shape[0]
+        final_data[t:t + nt, :, :] = datastore[i]
+        t = t + nt
+
+    # Load in land/sea mask
+    ls = np.fromfile("/nas/share1-hp/jinwonki/data/obs/pr25urd/s/d/lsm25.usa", sep=" ")
+    ls.shape = [nlat, nlon]
+    # Extract subregion from land/sea mask
+    subls = np.ones(final_data.shape)
+    for t in np.arange(final_data.shape[0]):
+        subls[t, :, :] = ls[wh_true].reshape(nsublat, nsublon) 
+    
+    # Construct a masked array of data i.e. only using data from land points
+    mdi = -1
+    mdata = ma.masked_array(final_data, mask=(subls == mdi))
+
+    # Construct datetime list from dates in filenames.
+    yearmonth = np.zeros(len(filelist))
+    i = 0
+    for filename in filelist:
+        # Extract month and year from filename
+        yearmonth[i] = int(filename[7:13])
+        i += 1
+    
+    # Construct a list of datetimes between the earliest and latest yearmonth
+    firstyear = int(str(yearmonth.min())[0:4])
+    firstmonth = int(str(yearmonth.min())[4:6])
+    times = []
+
+    cur_time = datetime.datetime(firstyear, firstmonth, 1, 0, 0, 0, 0)
+    
+    for i in range(final_data.shape[0]):
+        times.append(cur_time)
+        dt = datetime.timedelta(days=1)
+        cur_time = cur_time + dt
+    
+    return sublats, sublons, times, mdata
+
+def read_tmp_watershed(myfile, dom_num):
+    '''
+     Routine to read watershed weighting file mapped onto WRF model grids.
+      NB.this will be superceded by proper routines to read shape files and regrid onto any model grid.
+    
+      Input:
+         myfile - file name of the watershed ascii file to load
+         dom_num - WRF domain number (specific to this experiment)
+    
+      Output:
+         mymask - boolean mask array saying where the watershed is
+    
+       Peter Lean    September 2010
+    '''
+    
+    # Parameters specific to WRF domain setup required for these files
+    if(dom_num == 1):
+        nx = 190
+        ny = 130
+    
+    if(dom_num == 2):
+        nx = 192
+        ny = 180
+      
+    # Create an empty array to store the weights
+    myweights = np.zeros((ny, nx))
+    
+    # Load in data from the mask file
+    i, j, w = np.loadtxt("/home/plean/demo/rcmes/watersheds/" + myfile, unpack=True)
+    
+    for q in np.arange(len(i)):
+        myweights[j[q], i[q]] = w[q]
+    
+    mymask = np.empty((ny, nx))
+    mymask[:] = True
+    mymask[(myweights > 0.5)] = False
+    
+    return mymask
+
+def read_eraint_surf_files(filelist, myvar, latMin, latMax, lonMin, lonMax):
+    '''
+     ** For testing work before database was ready. **
+     Reads ERA-Interim surface netCDF files.
+    
+     Input:
+        filelist - list of filenames (including path)
+        myvar    - name of variable to load
+        latMin,latMax,lonMin,lonMax - define region to extract (in degrees)
+     Output:
+        lat, lon   - 1D array of latitude and longitude values
+        timestore  - list of python datetime objects
+        mdata      - numpy masked array containing data from all files    
+    
+       Peter Lean September 2010 
+    '''
+    
+    
+    # Crash nicely if 'filelist' is zero length
+    if len(filelist) == 0:
+        print 'Error: no files have been passed to read_data_from_file_list()'
+        sys.exit()
+
+    # Open the first file in the list to:
+    #    i) read in lats, lons
+    #    ii) find out how many timesteps in the file 
+    #        (assume same ntimes in each file in list)
+    #     -allows you to create an empty array to store variable data for all times
+    tmp = Nio.open_file(filelist[0])
+    latsraw = tmp.variables["latitude"]
+    lonsraw = tmp.variables["longitude"]
+    lat = latsraw[:]
+    lon = lonsraw[:]
+    print 'Lats and lons read in for first file in filelist'
+    
+    # Create mask to extract required region only
+    #  NB. longitude is slightly more complicated as can wrap the prime meridion
+    print 'Extracting for :- lats:', latMin, latMax, ' lons: ', lonMin, lonMax
+    wh_lat = np.logical_and((lat >= latMin), (lat <= latMax))
+    if(lonMin < lonMax):
+        wh_lon = np.logical_and((lon >= lonMin), (lon <= lonMax))
+    if(lonMin > lonMax):
+        wh_lon = np.logical_or((lon >= lonMin), (lon <= lonMax))
+    
+    sublat = lat[wh_lat]
+    sublon = lon[wh_lon]
+    
+    wh_true1, wh_true2 = np.meshgrid(wh_lon, wh_lat)
+    wh = np.logical_and(wh_true1, wh_true2)
+    
+    # Create storage lists
+    datastore = []
+    timestore = []
+
+    # Now load in the data for real
+    #  NB. no need to reload in the latitudes and longitudes -assume invariant
+    i = 0
+    timesaccu = 0 # a counter for number of times stored so far in t2store 
+    #  NB. this method allows for missing times in data files 
+    #      as no assumption made that same number of times in each file...
+    for ifile in filelist:
+        print 'Loading data from file: ', filelist[i]
+        f = Nio.open_file(ifile, format='nc')
+        data = f.variables[myvar][:]
+        scale = f.variables[myvar].scale_factor
+        offset = f.variables[myvar].add_offset
+        data = data * scale + offset
+        times = f.variables["time"][:]
+        ntimes = times.size
+        # Decode times into python datetime object
+        sub = data[:, wh].reshape(ntimes, sublat.size, sublon.size)
+        datastore.append(sub)
+        timestore.append(times)
+        timesaccu = timesaccu + ntimes
+        i += 1 
+
+    # move data from lists into correctly dimensioned arrays
+    final_data = np.zeros((timesaccu, sublat.size, sublon.size))
+    t = 0
+    for i in range(len(datastore)):
+        nt = datastore[i].shape[0]
+        final_data[t:t + nt, :, :] = datastore[i]
+        t = t + nt
+    
+    times = np.zeros((timesaccu))
+    t = 0
+    for i in range(len(timestore)):
+        nt = timestore[i].shape[0]
+        times[t:t + nt] = timestore[i]
+        t = t + nt
+  
+    # Decode times into python datetime objects
+    times = rcmes.process.decode_eraint_surf_times(times)
+    
+    print 'Data read in successfully with dimensions: ', final_data.shape
+    
+    # Create masked array using missing value flag from file
+    mdi = f.variables[myvar]._FillValue[0]
+    mdata = ma.masked_array(final_data, mask=(final_data == mdi))
+
+    # Rearrange array so data match lat lon values
+    mdata = np.flipud(mdata[:, ::-1])
+    
+    return sublat, sublon, times, mdata
+
+def make_list_of_wrf_files(firstTime, lastTime, ident):
+    '''
+     Routine to make list of WRF filenames given time period.
+    
+      Input:
+          firstTime - datetime object specifying start time
+          lastTime  - datetime object specifying end time
+          ident     - identifier for model run, e.g. 'd01'
+    
+      Output:
+          filelist  - list of standard format WRF filenames
+    
+          Peter Lean
+    '''
+
+    dt = datetime.timedelta(hours=6)
+    filenamelist = []
+    curTime = firstTime
+
+    while curTime <= lastTime:
+        curTimeString = curTime.strftime("%Y-%m-%d_%H:%M:%S")
+        filenamelist.append('wrfout_' + ident + '_' + curTimeString)
+        curTime += dt
+    
+    return filenamelist
+
+def make_list_of_trmm_files(firstTime, lastTime):
+    '''
+     Routine to make list of TRMM filenames given time period.
+    
+      Input:
+          firstTime - datetime object specifying start time
+          lastTime  - datetime object specifying end time
+    
+      Output:
+          filelist  - list of standard format WRF filenames
+    
+          Peter Lean
+    '''
+    trmm_repository = '/nas/share4-cf/plean/TRMM/'
+    dt = datetime.timedelta(hours=24)
+    filenamelist = []
+    curTime = firstTime
+    while curTime <= lastTime:
+        curTimeString = curTime.strftime("%Y.%m.%d")
+        filenamelist.append(trmm_repository + '3B42_daily.' + curTimeString + '.6.nc')
+        
+        curTime += dt
+    
+    return filenamelist
+
+def make_list_of_airs_files(firstTime, lastTime):
+    '''
+     Routine to make list of AIRS filenames given time period.
+    
+      Input:
+          firstTime - datetime object specifying start time
+          lastTime  - datetime object specifying end time
+    
+      Output:
+          filelist  - list of standard format WRF filenames
+    
+          Peter Lean
+    '''
+
+
+    airs_repository = '/nas/share4-cf/plean/AIRX3STD/'
+    dt = datetime.timedelta(hours=24)
+    filenamelist = []
+    curTime = firstTime
+    while curTime <= lastTime:
+        curTimeString = curTime.strftime("%Y.%m.%d")
+        filenamelist.append(glob.glob(airs_repository + 'AIRS.' + curTimeString + '.L3.*.nc')[0])
+        
+        curTime += dt
+    
+    return filenamelist
+
+def make_list_of_urd_files(firstTime, lastTime):
+    '''
+     Routine to make list of URD filenames given time period.
+    
+      Input:
+          firstTime - datetime object specifying start time
+          lastTime  - datetime object specifying end time
+    
+      Output:
+          filelist  - list of standard format WRF filenames
+    
+          Peter Lean
+    '''
+    
+    dt = datetime.timedelta(days=30)
+    filenamelist = []
+    newfirstTime = datetime.datetime(firstTime.year, firstTime.month, 15, 0, 0, 0)
+    newlastTime = datetime.datetime(lastTime.year, lastTime.month, 15, 0, 0, 0)
+    
+    curTime = newfirstTime
+    while curTime <= newlastTime:
+        curTimeString = curTime.strftime("%Y%m")
+        filenamelist.append('pr_ncep' + curTimeString)
+        if(curTime.month == 1):
+            curTime = datetime.datetime(curTime.year, curTime.month, 15, 00, 00, 00, 00)
+        
+        curTime += dt
+    
+    return filenamelist
+
+def make_list_of_era_surf_files(firstTime, lastTime):
+    '''
+     Routine to make list of ERA-Interim surface filenames given time period.
+    
+      Input:
+          firstTime - datetime object specifying start time
+          lastTime  - datetime object specifying end time
+    
+      Output:
+          filelist  - list of standard format WRF filenames
+    
+          Peter Lean
+    '''
+
+    import datetime
+    eraint_repository = '/data/plean/era-int/surf/'
+    filenamelist = []
+    dt = datetime.timedelta(days=30)
+    newfirstTime = datetime.datetime(firstTime.year, firstTime.month, 15, 0, 0, 0)
+    newlastTime = datetime.datetime(lastTime.year, lastTime.month, 15, 0, 0, 0)
+    curTime = newfirstTime
+
+    while curTime <= newlastTime:
+        curTimeString = curTime.strftime("%b%Y")
+        filenamelist.append(eraint_repository + 'sfc.' + curTimeString.lower() + '.nc')
+        if(curTime.month == 1):
+            curTime = datetime.datetime(curTime.year, curTime.month, 15, 00, 00, 00, 00)
+        
+        curTime += dt
+    
+    return filenamelist
+
+
+#
+
+def assign_subRgns_from_a_text_file(infile):
+    # Read pre-fabricated sugregion information from a text file
+    # Note: python indexing includes the beginning point but excludes the ending point
+    f = open(infile, 'r')
+    for i in np.arange(8):
+        string = f.readline()
+        print 'Line ', i, ': Content ', string
+    string = f.readline()
+    numSubRgn = int(string[20:22])
+    print 'numSubRgn = ', numSubRgn
+    for i in np.arange(3):
+        string = f.readline()
+    # Read input string and extract subRegion info (name, longs, lats) from the string
+    subRgnName = []
+    subRgnLon0 = ma.zeros((numSubRgn))
+    subRgnLon1 = ma.zeros((numSubRgn))
+    subRgnLat0 = ma.zeros((numSubRgn))
+    subRgnLat1 = ma.zeros((numSubRgn))
+    for i in np.arange(numSubRgn):
+        string = f.readline()
+        subRgnName.append(string[0:19])
+        subRgnLon0[i] = float(string[30:37])
+        subRgnLon1[i] = float(string[40:47])
+        subRgnLat0[i] = float(string[50:55])
+        subRgnLat1[i] = float(string[60:65])
+    f.close()
+    print 'subRgnName: ', subRgnName
+    print 'subRgnLon0: ', subRgnLon0
+    print 'subRgnLon1: ', subRgnLon1
+    print 'subRgnLat0: ', subRgnLat0
+    print 'subRgnLat1: ', subRgnLat1
+    return numSubRgn, subRgnName, subRgnLon0, subRgnLon1, subRgnLat0, subRgnLat1
+
+def createSubRegionObjectInteractively():
+    """
+    Purpose::
+        Mini command line program to enable users to enter SubRegion Information
+    Input::
+        None
+    Output::
+        SubRegion Object
+    """
+    rawInput = None
+    while rawInput == None:
+        userMessage = ("Enter information for 1 Sub Region using the following "
+                       "pipe '|' separated format: \n"
+                       "RegionName | Degrees North | Degrees South | Degrees East | Degrees West \n>>>")
+        userInput = raw_input(userMessage)
+        inputList = userInput.split('|')
+        if len(inputList) != 5:
+            badLengthMessage = ("Unable to parse %s.  You should have 5 inputs "
+                                "separated by 4 pipe characters. \n"
+                                "Example:  Region Name | 85 | 80 | 10 | -30" % userInput)
+            print(badLengthMessage)
+        else:
+            name = str(inputList[0]).strip()
+            latMax = str(inputList[1]).strip()
+            latMin = str(inputList[2]).strip()
+            lonMax = str(inputList[3]).strip()
+            lonMin = str(inputList[4]).strip()
+            subRegion = classes.SubRegion(name, latMin, lonMin, latMax, lonMax)
+            rawInput = True
+
+    return subRegion
+
+def selectSubRegion(subRegions):
+    # interactively select the sub-region ID for area-mean time-series evaluation
+    print '-'*59
+    columnTemplate = "|{0:2}|{1:10}|{2:10}|{3:10}|{4:10}|{5:10}|"
+    print columnTemplate.format("ID", "Name", "LonMin", "LonMax", "LatMin", "LatMax")
+    counter = 0
+    for subRegion in subRegions:
+        print columnTemplate.format(counter, subRegion.name, subRegion.lonMin, subRegion.lonMax, subRegion.latMin, subRegion.latMax)
+        counter += 1
+
+    print '-'*59
+    ask = 'Enter the sub-region ID to be evaluated. -9 for all sub-regions (-9 is not active yet): \n'
+    rgnSelect = int(raw_input(ask))
+    if rgnSelect >= len(subRegions):
+        print 'sub-region ID out of range. Max = %s' % len(subRegions)
+        sys.exit()
+    return rgnSelect
+
+def getStartEndTimes(status, startOverLapTime, endOverLapTime):
+    '''
+    This function will get the start and end time from user.
+    It also check whether or not user enters the proper time for both start and end.
+    If user leaves the start and end time empty, it will get the largest time range as default (overlap).
+    '''
+
+    if status == "start":
+        try:
+            time = raw_input("Please Enter a Start Date [%s]: " % startOverLapTime.strftime('%Y-%m-%d'))
+            if not time:
+                time = startOverLapTime
+                print "Your time starts from [%s] " % time.strftime('%Y-%m-%d')
+                return time
+            time = datetime.datetime.strptime(time, '%Y-%m-%d')
+            if time < startOverLapTime:
+                print "WARNING: The time you inputted [%s] " % time.strftime('%Y-%m-%d') + " is before the minimum start time [%s]."  % startOverLapTime.strftime('%Y-%m-%d')
+                time = getStartEndTimes("start", startOverLapTime, endOverLapTime)
+                return time
+            elif time > endOverLapTime:
+                print "WARNING: The time you inputted [%s] " % time.strftime('%Y-%m-%d') + " is after the maximum end time [%s]. " % endOverLapTime.strftime('%Y-%m-%d')
+                time = getStartEndTimes("start", startOverLapTime, endOverLapTime)
+                return time
+            else:
+                return time
+        except ValueError:
+            getStartEndTimes(status, startOverLapTime, endOverLapTime)
+    
+    if status == "end":
+        try:
+            time = raw_input("Please Enter an End Date [%s]: " % endOverLapTime.strftime('%Y-%m-%d'))
+            if not time:
+                time = endOverLapTime
+                print "Your time ends by [%s] " % time.strftime('%Y-%m-%d')
+                return time
+            time = datetime.datetime.strptime(time, '%Y-%m-%d')
+            if time > endOverLapTime:
+                print "WARNING: The time you inputted [%s] " % time.strftime('%Y-%m-%d') + " is after the maximum end time [%s]. " % endOverLapTime.strftime('%Y-%m-%d')
+                time = getStartEndTimes("end", startOverLapTime, endOverLapTime)
+                return time
+            elif time < startOverLapTime:
+                print "WARNING: The time you inputted [%s] " % time.strftime('%Y-%m-%d') + " is before the minimum start time [%s]."  % startOverLapTime.strftime('%Y-%m-%d')
+                time = getStartEndTimes("end", startOverLapTime, endOverLapTime)
+                return time
+            else:
+                return time
+        except ValueError:
+            getStartEndTimes(status, startOverLapTime, endOverLapTime)
+
+
+def getDirSettings():
+    """
+    This function will collect 2 parameters from the user about the RCMET run they have started.
+    
+    Output::
+        dirs - Tuple of strings i.e. ('workDirPath', 'cacheDirPath')
+    """
+    workDir = os.path.abspath(raw_input('Please enter workDir:\n> '))
+    if os.path.isdir(workDir):
+        pass
+    else:
+        makeDirectory(workDir)
+    
+    cacheDir= os.path.abspath(raw_input('Please enter cacheDir:\n> '))
+    if os.path.isdir(cacheDir):
+        pass
+    else:
+        makeDirectory(cacheDir)
+    
+    return (workDir, cacheDir)
+
+def getModelFiles():
+    modelList = []
+    while len(modelList) < 1:
+        userInput = raw_input('Please enter model file (or specify multiple files using wildcard):\n> ')
+        modelList = glob.glob(userInput)
+        if len(modelList) == 0:
+            print("Sorry we were unable to find any files at - %s" % userInput)
+            print("Please try again, and use the asterisk * for the wildcard")
+        
+    return modelList
+
+def getTemporalGrid():
+    options = ['annual', 'monthly', 'daily']
+    print("Please select one of the following Temporal Grid Options:\n")
+    for key, option in enumerate(options):
+        print("[%s] - %s" % (key, option))
+    choice = int(raw_input(">>>"))
+    try:
+        temporalGrid = options[choice]
+    except IndexError:
+        getTemporalGrid()
+    else:
+        return temporalGrid
+
+def getSpatialGrid():
+    options = ['obs', 'model', 'user']
+    print("Please select one of the following Spatial Grid Options:\n")
+    for key, option in enumerate(options):
+        print("[%s] - %s" % (key, option))
+
+    choice = int(raw_input(">>>"))
+    try:
+        spatialGrid = options[choice]
+    except IndexError:
+        getSpatialGrid()
+
+    return spatialGrid
+
+def askUserForVariableName(variableNames, targetName):
+    if targetName == "analysis":
+        print("Select the variable you want to use for analysis/metrics:")
+    else:
+        print("Select the variable that corresponds to %s:" % targetName)
+
+    for idx, variable in enumerate(variableNames):
+        print("[%s] - %s" % (idx, variable))
+    userChoice = int(raw_input(">>>"))
+    try:
+        variableName = variableNames[userChoice]
+    except IndexError:
+        askUserForVariableName(variableNames, targetName)
+    
+    return variableName
+        
+        
+
+def getLatLonStep(settings):
+    pass
+
+def getSpatialBounds(settings):
+    pass
+
+
+def getUserSpatialSettings(settings):
+    getLatLonStep(settings)
+    getSpatialBounds(settings)
+
+def makeDirectory(directory):
+    print "%s doesn't exist.  Trying to create it now." % directory
+    try:
+        os.mkdir(directory)
+        print("Created %s successfully" % directory)
+    except OSError:
+        print "This program cannot create dir: %s due to permission issues." % directory
+        sys.exit()
+
+
+def userDefinedStartEndTimes(obsList, modelList):
+    """
+    The function will interactively ask the user to select a start and end time based on the start/end times
+    of the supplied observation and model objects
+     
+    Input::
+        obsList - List of Observation Objects
+        modelList - List of Model Objects
+    
+    Output::
+        startTime - Python datetime object from User Input
+        endTime - Python datetime object from User Input
+    """
+    startTimes = []
+    endTimes = []
+    print '='*94
+    template = "|{0:60}|{1:15}|{2:15}|"
+    print template.format('Dataset - NAME', 'START DATE', 'END DATE')
+    for observation in obsList:
+        startTimes.append(datetime.datetime.strptime(observation['start_date'],'%Y-%m-%d'))
+        endTimes.append(datetime.datetime.strptime(observation['end_date'],'%Y-%m-%d'))
+        print template.format(observation['longname'], observation['start_date'], observation['end_date'])
+    print '-'*94
+    for model in modelList:
+        startTimes.append(model.minTime)
+        endTimes.append(model.maxTime)
+        print template.format(model.name, model.minTime.strftime('%Y-%m-%d'), model.maxTime.strftime('%Y-%m-%d'))
+    print '='*94
+    
+    # Compute Overlap
+    maxstartTimes=max(startTimes)
+    minendTimes=min(endTimes)
+    # TODO:  Do we need to start on JAN and end on DEC?  Do we know someone is doing ANNUAL analysis at this point?
+#    if maxstartTimes.month != 1:
+#        maxstartTimes = datetime.datetime(maxstartTimes.year+1,1,maxstartTimes.day)
+#    if minendTimes.month != 12:
+#        minendTimes = datetime.datetime(minendTimes.year-1,12,minendTimes.day)
+    if minendTimes.year < maxstartTimes.year:
+        print 'Not enough data for overlapping years'
+        sys.exit()
+    overLap = (maxstartTimes.strftime('%Y-%m-%d'), minendTimes.strftime('%Y-%m-%d'))
+    # Present default overlap to user as default value
+    print 'Standard Overlap in the selected datasets are %s through %s' % (overLap)
+
+    startOverLapTime = datetime.datetime.strptime(overLap[0],'%Y-%m-%d')
+    endOverLapTime = datetime.datetime.strptime(overLap[1],'%Y-%m-%d')
+
+    # Enter Start Date
+    startTime = getStartEndTimes("start", startOverLapTime, endOverLapTime)    
+    # Enter End Date
+    endTime = getStartEndTimes("end", startOverLapTime, endOverLapTime)
+        
+    if startTime > endTime:
+        print "WARNING: The start time you entered [%s]" % startTime.strftime('%Y-%m-%d') + " is after the end time you entered [%s]." % endTime.strftime('%Y-%m-%d')
+        startTime = getStartEndTimes("start", startOverLapTime, endOverLapTime)
+        endTime = getStartEndTimes("end", startOverLapTime, endOverLapTime)
+
+    return startTime, endTime
+
+
+def select_timOpt():
+    #---------------------------------------------
+    # Interacrively select the time scale to be evaluated
+    # e.g., the means over annual, seasonal, monthly, or a specified period (e.g., JJAS for Indian monsoon)
+    #------------------------------------------------------------------------------------
+    print 'Select the time-mean properties to be evaluated: Enter'
+    timeOption = \
+      int(raw_input('1=annual mean, 2=seasonal mean (define "season", e.g., JJAS for Indian monsoon), 3=monthly \n> '))
+    return timeOption
+
+def select_data(nDat, Times, List, sourceDat):
+    #---------------------------------------------
+    # Interacrively select a model or models for evaluation
+    #----------------------------------------------------------------------------
+    print '-----------------------------------------------'
+    if sourceDat == 'mdl':
+        print 'mdlID  mdlName numMOs  mdlStartTime mdlEndTime fileName'
+    elif sourceDat == 'obs':
+        print 'obsID  obsName obsMOs  obsStartTime obsEndTime fileName'
+    else:
+        print 'not valid data source: CRASH and restart'
+        sys.exit()
+    print '-----------------------------------------------'
+
+    for n in np.arange(len(List)):
+        print n, List[n], Times[0], Times[-1]
+        n += 1
+    print '-----------------------------------------------'
+    if sourceDat == 'mdl':
+        ask = 'Enter the model ID to be evaluated. -9 for all models (-9 is not active yet): \n'
+    elif sourceDat == 'obs':
+        ask = 'Enter the obs ID to be evaluated. -9 for all models (-9 is not active yet): \n'
+    datSelect = int(raw_input(ask))
+    if datSelect > nDat - 1:
+        print 'Data ID out of range: CRASH'
+        sys.exit()
+    return datSelect
+
+def select_metrics():
+    #---------------------------------------------
+    # Interacrively select an evaluation metric
+    # Input : none
+    # Output: metricOption, the indicator for selecting the metric to be calculated
+    #------------------------------------------------------------------------------
+    print 'Metric options'
+    print '[0] Bias: mean bias across full time range'
+    print '[1] Mean Absolute Error: across full time range'
+    print '[2] Spatial Pattern Correlation: results in a time series of spatial correlation coeff'
+    print '[3] Temporal Correlation: results in 2-d array of temporal correlation coefficient'
+    print '[4] Spatial Pattern Correlation between averaged fields: results in a single correlation coeff'
+    print '[5] RMSE in time: results in a 2-d array of RMSE over two time series'
+    print '[6] TODO: Probability Distribution Function similarity score'
+    choice = int(raw_input('Please make a selection from the options above\n> '))
+    # assign the evaluation metric to be calculated
+    if choice == 0:
+        metricOption = 'BIAS'
+    elif choice == 1:
+        metricOption = 'MAE'
+    elif choice == 2:
+        metricOption = 'PCt'
+    elif choice == 3:
+        metricOption = 'TC'
+    elif choice == 4:
+        metricOption = 'PCC'
+    elif choice == 5:
+        metricOption = 'RMSt'
+    elif choice == 6:
+        metricOption = 'pdfSkillScore'
+    print 'in subroutine metricOption = ', metricOption
+    return metricOption
+

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/rcmes/utils/Taylor.py
----------------------------------------------------------------------
diff --git a/src/main/python/rcmes/utils/Taylor.py b/src/main/python/rcmes/utils/Taylor.py
new file mode 100755
index 0000000..d7dfd2d
--- /dev/null
+++ b/src/main/python/rcmes/utils/Taylor.py
@@ -0,0 +1,126 @@
+"""
+Taylor diagram (Taylor, 2001) test implementation.
+ 
+http://www-pcmdi.llnl.gov/about/staff/Taylor/CV/Taylor_diagram_primer.htm
+"""
+ 
+__version__ = "Time-stamp: <2012-02-17 20:59:35 ycopin>"
+__author__ = "Yannick Copin <ya...@laposte.net>"
+ 
+import numpy as NP
+import matplotlib.pyplot as PLT
+ 
+class TaylorDiagram(object):
+    """Taylor diagram: plot model standard deviation and correlation
+    to reference (data) sample in a single-quadrant polar plot, with
+    r=stddev and theta=arccos(correlation).
+    """
+ 
+    def __init__(self, refstd, radMax = 1.5, fig=None, rect=111, label='_'):
+        """Set up Taylor diagram axes, i.e. single quadrant polar
+        plot, using mpl_toolkits.axisartist.floating_axes. refstd is
+        the reference standard deviation to be compared to.
+        """
+ 
+        from matplotlib.projections import PolarAxes
+        import mpl_toolkits.axisartist.floating_axes as FA
+        import mpl_toolkits.axisartist.grid_finder as GF
+ 
+        self.refstd = refstd            # Reference standard deviation
+ 
+        tr = PolarAxes.PolarTransform()
+ 
+        # Correlation labels
+        rlocs = NP.concatenate((NP.arange(10)/10.,[0.95,0.99]))
+        tlocs = NP.arccos(rlocs)        # Conversion to polar angles
+        gl1 = GF.FixedLocator(tlocs)    # Positions
+        tf1 = GF.DictFormatter(dict(zip(tlocs, map(str,rlocs))))
+ 
+        # Standard deviation axis extent
+        self.smin = 0
+        self.smax = radMax * self.refstd
+ 
+        ghelper = FA.GridHelperCurveLinear(tr,
+                                           extremes=(0,NP.pi/2, # 1st quadrant
+                                                     self.smin,self.smax),
+                                           grid_locator1=gl1,
+                                           tick_formatter1=tf1,
+                                           )
+ 
+        if fig is None:
+            fig = PLT.figure()
+ 
+        ax = FA.FloatingSubplot(fig, rect, grid_helper=ghelper)
+        fig.add_subplot(ax)
+ 
+        # Adjust axes
+        ax.axis["top"].set_axis_direction("bottom")  # "Angle axis"
+        ax.axis["top"].toggle(ticklabels=True, label=True)
+        ax.axis["top"].major_ticklabels.set_axis_direction("top")
+        ax.axis["top"].label.set_axis_direction("top")
+        ax.axis["top"].label.set_text("Correlation")
+ 
+        ax.axis["left"].set_axis_direction("bottom") # "X axis"
+        ax.axis["left"].label.set_text("Standardized deviation")
+ 
+        ax.axis["right"].set_axis_direction("top")   # "Y axis"
+        ax.axis["right"].toggle(ticklabels=True)
+        ax.axis["right"].major_ticklabels.set_axis_direction("left")
+ 
+        ax.axis["bottom"].set_visible(False)         # Useless
+        
+        # Contours along standard deviations
+        ax.grid(False)
+ 
+        self._ax = ax                   # Graphical axes
+        self.ax = ax.get_aux_axes(tr)   # Polar coordinates
+ 
+        # Add reference point and stddev contour
+        # print "Reference std:", self.refstd
+        l, = self.ax.plot([0], self.refstd, 'k*',
+                          ls='', ms=10, label=label)
+        t = NP.linspace(0, NP.pi/2)
+        r = NP.zeros_like(t) + self.refstd
+        self.ax.plot(t,r, 'k--', label='_')
+ 
+        # Collect sample points for latter use (e.g. legend)
+        self.samplePoints = [l]
+ 
+    def add_sample(self, stddev, corrcoef, *args, **kwargs):
+        """Add sample (stddev,corrcoeff) to the Taylor diagram. args
+        and kwargs are directly propagated to the Figure.plot
+        command."""
+ 
+        l, = self.ax.plot(NP.arccos(corrcoef), stddev,
+                          *args, **kwargs) # (theta,radius)
+        self.samplePoints.append(l)
+ 
+        return l
+ 
+    def add_rms_contours(self, levels=5, **kwargs):
+        """Add constant centered RMS difference contours."""
+ 
+        rs,ts = NP.meshgrid(NP.linspace(self.smin,self.smax),
+                            NP.linspace(0,NP.pi/2))
+        # Compute centered RMS difference
+        rms = NP.sqrt(self.refstd**2 + rs**2 - 2*self.refstd*rs*NP.cos(ts))
+        
+        contours = self.ax.contour(ts, rs, rms, levels, **kwargs)
+    
+    def add_stddev_contours(self, std, corr1, corr2, **kwargs):
+        """Add a curved line with a radius of std between two points
+        [std, corr1] and [std, corr2]"""
+
+        t = NP.linspace(NP.arccos(corr1), NP.arccos(corr2)) 
+        r = NP.zeros_like(t) + std
+        return self.ax.plot(t,r,'red', linewidth=2)
+    
+    def add_contours(self,std1,corr1,std2,corr2, **kwargs):
+        """Add a line between two points
+        [std1, corr1] and [std2, corr2]"""
+        
+        t = NP.linspace(NP.arccos(corr1), NP.arccos(corr2)) 
+        r = NP.linspace(std1, std2)
+
+        return self.ax.plot(t,r,'red',linewidth=2)
+ 

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/rcmes/utils/Taylor.pyc
----------------------------------------------------------------------
diff --git a/src/main/python/rcmes/utils/Taylor.pyc b/src/main/python/rcmes/utils/Taylor.pyc
new file mode 100644
index 0000000..ff95a04
Binary files /dev/null and b/src/main/python/rcmes/utils/Taylor.pyc differ

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/rcmes/utils/__init__.py
----------------------------------------------------------------------
diff --git a/src/main/python/rcmes/utils/__init__.py b/src/main/python/rcmes/utils/__init__.py
new file mode 100755
index 0000000..fbe6d4e
--- /dev/null
+++ b/src/main/python/rcmes/utils/__init__.py
@@ -0,0 +1,2 @@
+"""Collection of modules that provide functionality across all of the RCMES
+sub-packages"""
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/rcmes/utils/__init__.pyc
----------------------------------------------------------------------
diff --git a/src/main/python/rcmes/utils/__init__.pyc b/src/main/python/rcmes/utils/__init__.pyc
new file mode 100644
index 0000000..03fe471
Binary files /dev/null and b/src/main/python/rcmes/utils/__init__.pyc differ

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/rcmes/utils/fortranfile.py
----------------------------------------------------------------------
diff --git a/src/main/python/rcmes/utils/fortranfile.py b/src/main/python/rcmes/utils/fortranfile.py
new file mode 100755
index 0000000..7ff7850
--- /dev/null
+++ b/src/main/python/rcmes/utils/fortranfile.py
@@ -0,0 +1,274 @@
+# Copyright 2008, 2009 Neil Martinsen-Burrell
+
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+# THE SOFTWARE.
+
+
+"""
+Defines a file-derived class to read/write Fortran unformatted files.
+
+The assumption is that a Fortran unformatted file is being written by
+the Fortran runtime as a sequence of records.  Each record consists of
+an integer (of the default size [usually 32 or 64 bits]) giving the
+length of the following data in bytes, then the data itself, then the
+same integer as before.
+
+Examples
+--------
+
+To use the default endian and size settings, one can just do::
+
+    >>> f = FortranFile('filename')
+    >>> x = f.readReals()
+
+One can read arrays with varying precisions::
+
+    >>> f = FortranFile('filename')
+    >>> x = f.readInts('h')
+    >>> y = f.readInts('q')
+    >>> z = f.readReals('f')
+
+Where the format codes are those used by Python's struct module.
+
+One can change the default endian-ness and header precision::
+
+    >>> f = FortranFile('filename', endian='>', header_prec='l')
+    
+for a file with little-endian data whose record headers are long
+integers.
+"""
+
+__docformat__ = "restructuredtext en"
+
+import struct
+import numpy
+
+class FortranFile(file):
+
+    """File with methods for dealing with fortran unformatted data files"""
+
+    def _get_header_length(self):
+        return struct.calcsize(self._header_prec)
+    _header_length = property(fget=_get_header_length)
+
+    def _set_endian(self,c):
+        """
+        Set endian to big (c='>') or little (c='<') or native (c='@')
+
+        Parameters:
+          `c` : string
+            The endian-ness to use when reading from this file.
+        """
+        if c in '<>@=':
+            self._endian = c
+        else:
+            raise ValueError('Cannot set endian-ness')
+    def _get_endian(self):
+        return self._endian
+    ENDIAN = property(fset=_set_endian,
+                      fget=_get_endian,
+                      doc="Possible endian values are '<', '>', '@', '='"
+                     )
+
+    def _set_header_prec(self, prec):
+        if prec in 'hilq':
+            self._header_prec = prec
+        else:
+            raise ValueError('Cannot set header precision')
+    def _get_header_prec(self):
+        return self._header_prec
+    HEADER_PREC = property(fset=_set_header_prec,
+                           fget=_get_header_prec,
+                           doc="Possible header precisions are 'h', 'i', 'l', 'q'"
+                          )
+
+    def __init__(self, fname, endian='@', header_prec='i', *args, **kwargs):
+        """Open a Fortran unformatted file for writing.
+        
+        Parameters
+        ----------
+        endian : character, optional
+            Specify the endian-ness of the file.  Possible values are
+            '>', '<', '@' and '='.  See the documentation of Python's
+            struct module for their meanings.  The deafult is '@' (native
+            byte order)
+        header_prec : character, optional
+            Specify the precision used for the record headers.  Possible
+            values are 'h', 'i', 'l' and 'q' with their meanings from
+            Python's struct module.  The default is 'i' (the system's
+            default integer).
+
+        """
+        file.__init__(self, fname, *args, **kwargs)
+        self.ENDIAN = endian
+        self.HEADER_PREC = header_prec
+
+    def _read_exactly(self, num_bytes):
+        """Read in exactly num_bytes, raising an error if it can't be done."""
+        data = ''
+        while True:
+            l = len(data)
+            if l == num_bytes:
+                return data
+            else:
+                read_data = self.read(num_bytes - l)
+            if read_data == '':
+                raise IOError('Could not read enough data.'
+                              '  Wanted %d bytes, got %d.' % (num_bytes, l))
+            data += read_data
+
+    def _read_check(self):
+        return struct.unpack(self.ENDIAN+self.HEADER_PREC,
+                             self._read_exactly(self._header_length)
+                            )[0]
+
+    def _write_check(self, number_of_bytes):
+        """Write the header for the given number of bytes"""
+        self.write(struct.pack(self.ENDIAN+self.HEADER_PREC,
+                               number_of_bytes))
+
+    def readRecord(self):
+        """Read a single fortran record"""
+        l = self._read_check()
+        data_str = self._read_exactly(l)
+        check_size = self._read_check()
+        if check_size != l:
+            raise IOError('Error reading record from data file')
+        return data_str
+
+    def writeRecord(self,s):
+        """Write a record with the given bytes.
+
+        Parameters
+        
+            s : the string to write
+
+        """
+        length_bytes = len(s)
+        self._write_check(length_bytes)
+        self.write(s)
+        self._write_check(length_bytes)
+
+    def readString(self):
+        """Read a string."""
+        return self.readRecord()
+
+    def writeString(self,s):
+        """Write a string
+
+        Parameters
+        
+            s : the string to write
+        
+        """
+        self.writeRecord(s)
+
+    _real_precisions = 'df'
+
+    def readReals(self, prec='f'):
+        """
+        Read in an array of real numbers.
+        
+        Parameters
+        
+            prec : character, optional
+            
+            Specify the precision of the array using character codes from
+            Python's struct module.  Possible values are 'd' and 'f'.
+            
+        """
+        
+        _numpy_precisions = {'d': numpy.float64,
+                             'f': numpy.float32
+                            }
+
+        if prec not in self._real_precisions:
+            raise ValueError('Not an appropriate precision')
+            
+        data_str = self.readRecord()
+        num = len(data_str)/struct.calcsize(prec)
+        numbers =struct.unpack(self.ENDIAN+str(num)+prec,data_str) 
+        return numpy.array(numbers, dtype=_numpy_precisions[prec])
+
+    def writeReals(self, reals, prec='f'):
+        """
+        Write an array of floats in given precision
+
+        Parameters
+        
+        reals : array
+            Data to write
+        prec` : string
+            Character code for the precision to use in writing
+        
+        """
+        if prec not in self._real_precisions:
+            raise ValueError('Not an appropriate precision')
+        
+        # Don't use writeRecord to avoid having to form a
+        # string as large as the array of numbers
+        length_bytes = len(reals)*struct.calcsize(prec)
+        self._write_check(length_bytes)
+        _fmt = self.ENDIAN + prec
+        for r in reals:
+            self.write(struct.pack(_fmt,r))
+        self._write_check(length_bytes)
+    
+    _int_precisions = 'hilq'
+
+    def readInts(self, prec='i'):
+        """
+        Read an array of integers.
+        
+        Parameters
+        
+            prec : character, optional
+                Specify the precision of the data to be read using 
+                character codes from Python's struct module.  Possible
+                values are 'h', 'i', 'l' and 'q'
+            
+        """
+        if prec not in self._int_precisions:
+            raise ValueError('Not an appropriate precision')
+            
+        data_str = self.readRecord()
+        num = len(data_str)/struct.calcsize(prec)
+        return numpy.array(struct.unpack(self.ENDIAN+str(num)+prec,data_str))
+
+    def writeInts(self, ints, prec='i'):
+        """
+        Write an array of integers in given precision
+
+        Parameters
+        
+            reals : array
+                Data to write
+            prec : string
+                Character code for the precision to use in writing
+        """
+        if prec not in self._int_precisions:
+            raise ValueError('Not an appropriate precision')
+        
+        # Don't use writeRecord to avoid having to form a
+        # string as large as the array of numbers
+        length_bytes = len(ints)*struct.calcsize(prec)
+        self._write_check(length_bytes)
+        _fmt = self.ENDIAN + prec
+        for item in ints:
+            self.write(struct.pack(_fmt,item))
+        self._write_check(length_bytes)

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/rcmes/utils/fortranfile.pyc
----------------------------------------------------------------------
diff --git a/src/main/python/rcmes/utils/fortranfile.pyc b/src/main/python/rcmes/utils/fortranfile.pyc
new file mode 100644
index 0000000..d145137
Binary files /dev/null and b/src/main/python/rcmes/utils/fortranfile.pyc differ


[43/51] [abbrv] [partial] Adding Jinwon's custom RCMET

Posted by jo...@apache.org.
http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/rcmes/storage/rcmed.py
----------------------------------------------------------------------
diff --git a/src/main/python/rcmes/storage/rcmed.py b/src/main/python/rcmes/storage/rcmed.py
new file mode 100755
index 0000000..39a235c
--- /dev/null
+++ b/src/main/python/rcmes/storage/rcmed.py
@@ -0,0 +1,349 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#    http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+'''
+Classes:
+    RCMED - A class for retrieving data from Regional Climate Model Evalutaion Database (JPL).
+'''
+
+import urllib, urllib2
+import re
+import json
+import numpy as np
+import numpy.ma as ma
+from datetime import datetime
+import calendar
+#from ocw.dataset import Dataset
+
+
+URL = 'http://rcmes.jpl.nasa.gov/query-api/query.php?'
+
+
+def get_parameters_metadata():
+    '''Get the metadata of all parameter from RCMED.
+
+    :returns: Dictionary of information for each parameter stored in one list
+    :rtype: List of dictionaries
+    '''
+
+    param_info_list = []
+    url = URL + "&param_info=yes"
+    string = urllib2.urlopen(url)
+    data_string = string.read()
+    json_format_data = json.loads(data_string)
+    fields_name = json_format_data['fields_name']
+    data = json_format_data['data']
+    for row in data:
+        dic = {}
+        for name in fields_name:
+            dic[name] = row[fields_name.index(name)]
+        param_info_list.append(dic)
+
+    return param_info_list
+
+
+def _make_mask_array(values, parameter_id, parameters_metadata):  
+    '''Created masked array to deal with missing values
+
+    :param values: Numpy array of values which may contain missing values
+    :type values: Numpy array
+    :param parameter_id: Parameter's id
+    :type parameter_id: Integer
+    :param parameters_metadata: Metadata for all parameters
+    :type parameters_metadata: List of dictionaries
+
+    :returns: Masked array of values
+    :rtype: Masked array
+    '''
+
+    for each in parameters_metadata:
+        if each['parameter_id'].encode() == str(parameter_id):
+            missing_values = each['missingdataflag'].encode()
+            break
+    # Need to encode the string to proper dtype so the mask is applied
+    if 'float' in str(values.dtype):
+        missing_values = float(missing_values)
+    if 'int' in str(values.dtype):
+        missing_values = int(missing_values)
+
+    values = ma.masked_array(values, mask=(values == missing_values))
+
+    return values
+
+
+def _reshape_values(values, unique_values):
+    '''Reshape values into 4D array.
+
+    :param values: Raw values data
+    :type values: numpy array
+    :param unique_values: Tuple of unique latitudes, longitudes and times data.
+    :type unique_values: Tuple 
+    
+    :returns: Reshaped values data
+    :rtype: Numpy array
+    '''
+
+    lats_len = len(unique_values[0])
+    lons_len = len(unique_values[1])
+    times_len = len(unique_values[2])
+
+    values = values.reshape(times_len, lats_len, lons_len)
+
+    return values
+
+
+def _calculate_time(unique_times, time_step):
+    '''Convert each time to the datetime object.
+
+    :param unique_times: Unique time data
+    :type unique_times: String
+    :param time_step: Time step
+    :type time_step: String
+
+    :returns: Unique datetime objects of time data
+    :rtype: Numpy array
+    '''
+
+    time_format = "%Y-%m-%d %H:%M:%S"
+    unique_times = np.array([datetime.strptime(time, time_format) for time in unique_times])
+    #There is no need to sort time.
+    #This function may required still in RCMES
+    #unique_times.sort()
+    #This function should be moved to the data_process.
+
+    return unique_times
+
+
+def _make_unique(lats, lons, times):
+    '''Find the unique values of input data.
+
+    :param lats: lats
+    :type lats: Numpy array
+    :param lons: lons
+    :type lons: Numpy array
+    :param times: times
+    :type times: Numpy array
+
+    :returns: Unique numpy arrays of latitudes, longitudes and times
+    :rtype: Tuple
+    '''
+
+    unique_lats = np.unique(lats)
+    unique_lons = np.unique(lons)
+    unique_times = np.unique(times)
+
+    return (unique_lats, unique_lons, unique_times)
+
+
+def _get_data(url):
+    '''Reterive data from database.
+
+    :param url: url to query from database
+    :type url: String
+
+    :returns: Latitudes, longitudes, times and values data
+    :rtype: (Numpy array, Numpy array, Numpy array, Numpy array)
+    '''
+
+    string = urllib2.urlopen(url)
+    data_string = string.read()    
+    index_of_data = re.search('data: \r\n', data_string)
+    data = data_string[index_of_data.end():len(data_string)]
+    data = data.split('\r\n') 
+
+    lats = []
+    lons = []
+    #levels = []
+    values = []
+    times = []
+
+    for i in range(len(data) - 1):  # Because the last row is empty, "len(data)-1" is used.
+        row = data[i].split(',')
+        lats.append(np.float32(row[0]))
+        lons.append(np.float32(row[1]))
+        # Level is not currently supported in Dataset class.
+        #levels.append(np.float32(row[2]))
+        times.append(row[3])
+        values.append(np.float32(row[4]))
+    
+    lats = np.array(lats)
+    lons = np.array(lons)
+    times = np.array(times)
+    values = np.array(values)
+
+    return lats, lons, times, values
+
+
+def _beginning_of_date(time, time_step):
+    '''Calculate the beginning of given time, based on time step.
+
+    :param time: Given time
+    :type time: Datetime
+    :param time_step: Time step (monthly or daily)
+    :type time_step: String
+
+    :returns: Beginning of given time
+    :rtype: Datetime
+    '''
+
+    if time_step.lower() == 'monthly':
+        if time.day != 1:
+            start_time_string = time.strftime('%Y%m%d')
+            start_time_string = start_time_string[:6] + '01'
+            time = datetime.strptime(start_time_string, '%Y%m%d')
+            ##TODO: Change the 3 lines above with this line:
+            ##time = datetime(time.year, time.month, 1)
+    elif time_step.lower() == 'daily':
+        if time.hour != 0 or time.minute != 0 or time.second != 0:
+            start_time_string = time.strftime('%Y%m%d%H%M%S')
+            start_time_string = start_time_string[:8] + '000000'
+            time = datetime.strptime(start_time_string, '%Y%m%d%H%M%S')
+            ##TODO: Change the 3 lines above with this line:
+            ##time = datetime(time.year, time.month, time.day, 00, 00, 00)
+
+    return time
+
+
+def _end_of_date(time, time_step):
+    '''Calculate the end of given time, based on time step.
+
+    :param time: Given time
+    :type time: Datetime
+    :param time_step: Time step (monthly or daily)
+    :type time_step: String
+
+    :returns: End of given time
+    :rtype: Datetime
+    '''
+
+    last_day_of_month = calendar.monthrange(time.year, time.month)[1]
+    if time.day != last_day_of_month:
+        end_time_string = time.strftime('%Y%m%d')
+        end_time_string = end_time_string[:6] + str(last_day_of_month)
+        time = datetime.strptime(end_time_string, '%Y%m%d')
+        ##TODO: Change the 3 lines above with this line:
+        ##time = datetime(time.year, time.month, lastDayOfMonth)
+    elif time_step.lower() == 'daily':
+        end_time_string = time.strftime('%Y%m%d%H%M%S')
+        end_time_string = end_time_string[:8] + '235959'
+        time = datetime.strptime(end_time_string, '%Y%m%d%H%M%S')
+        ##TODO: Change the 3 lines above with this line:
+        ##time = datetime(time.year, time.month, end_time.day, 23, 59, 59)
+
+    return time
+
+
+def _generate_query_url(dataset_id, parameter_id, min_lat, max_lat, min_lon, max_lon, start_time, end_time, time_step):
+    '''Generate the url to query from database
+
+    :param dataset_id: Dataset id.
+    :type dataset_id: Integer
+    :param parameter_id: Parameter id
+    :type parameter_id: Integer
+    :param min_lat: Minimum latitude
+    :type min_lat: Float
+    :param max_lat: Maximum latitude
+    :type max_lat: Float
+    :param min_lon: Minimum longitude
+    :type min_lon: Float
+    :param max_lon: Maximum longitude
+    :type max_lon: Float
+    :param start_time: Start time
+    :type start_time: Datetime
+    :param end_time: End time 
+    :type end_time: Datetime
+    :param time_step: Time step
+    :type time_step: String
+
+    :returns: url to query from database
+    :rtype: String
+    '''
+
+    start_time = _beginning_of_date(start_time, time_step)
+    end_time = _end_of_date(end_time, time_step)
+    start_time = start_time.strftime("%Y%m%dT%H%MZ")
+    end_time = end_time.strftime("%Y%m%dT%H%MZ")
+
+    query = [('datasetId',dataset_id), ('parameterId',parameter_id), ('latMin',min_lat), ('latMax',max_lat),
+             ('lonMin', min_lon), ('lonMax',max_lon), ('timeStart', start_time), ('timeEnd', end_time)]
+
+    query_url = urllib.urlencode(query)
+    url_request = URL + query_url
+    
+    return url_request
+
+
+def _get_parameter_info(parameters_metadata, parameter_id):
+    '''General information for given parameter id.
+
+    :param parameters_metadata: Metadata for all parameters
+    :type parameters_metadata: List of dictionaries
+    :param parameter_id: Parameter id
+    :type parameter_id: Integer
+
+    :returns: Database name, time step, realm, instrument, start_date, end_date and unit for given parameter
+    :rtype: (string, string, string, string, string, string, string)
+    '''
+
+    for dic in parameters_metadata:
+        if int(dic['parameter_id']) == parameter_id:
+            database = dic['database']
+            time_step = dic['timestep']
+            realm = dic['realm']
+            instrument = dic['instrument']
+            start_date = dic['start_date']
+            end_date = dic['end_date']
+            unit = dic['units']
+
+    return (database, time_step, realm, instrument, start_date, end_date, unit)
+
+
+def parameter_dataset(dataset_id, parameter_id, min_lat, max_lat, min_lon, max_lon, start_time, end_time):
+    '''Get data from one database(parameter).
+
+    :param dataset_id: Dataset id.
+    :type dataset_id: Integer
+    :param parameter_id: Parameter id
+    :type parameter_id: Integer
+    :param min_lat: Minimum latitude
+    :type min_lat: Float
+    :param max_lat: Maximum latitude
+    :type max_lat: Float
+    :param min_lon: Minimum longitude
+    :type min_lon: Float
+    :param max_lon: Maximum longitude
+    :type max_lon: Float
+    :param start_time: Start time
+    :type start_time: Datetime
+    :param end_time: End time 
+    :type end_time: Datetime
+
+    :returns: Dataset object
+    :rtype: Object
+    '''
+    
+    parameters_metadata = get_parameters_metadata()
+    parameter_name, time_step, _, _, _, _, _= _get_parameter_info(parameters_metadata, parameter_id)
+    url = _generate_query_url(dataset_id, parameter_id, min_lat, max_lat, min_lon, max_lon, start_time, end_time, time_step)
+    lats, lons, times, values = _get_data(url)
+
+    unique_lats_lons_times = _make_unique(lats, lons, times)
+    unique_times = _calculate_time(unique_lats_lons_times[2], time_step)
+    values = _reshape_values(values, unique_lats_lons_times)
+    values = _make_mask_array(values, parameter_id, parameters_metadata)
+    
+    return Dataset(unique_lats_lons_times[0], unique_lats_lons_times[1], unique_times, values, parameter_name)

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/rcmes/storage/rcmed.pyc
----------------------------------------------------------------------
diff --git a/src/main/python/rcmes/storage/rcmed.pyc b/src/main/python/rcmes/storage/rcmed.pyc
new file mode 100644
index 0000000..5b4e858
Binary files /dev/null and b/src/main/python/rcmes/storage/rcmed.pyc differ

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/rcmes/toolkit/.svn/all-wcprops
----------------------------------------------------------------------
diff --git a/src/main/python/rcmes/toolkit/.svn/all-wcprops b/src/main/python/rcmes/toolkit/.svn/all-wcprops
new file mode 100755
index 0000000..70196a3
--- /dev/null
+++ b/src/main/python/rcmes/toolkit/.svn/all-wcprops
@@ -0,0 +1,41 @@
+K 25
+svn:wc:ra_dav:version-url
+V 87
+/repos/asf/!svn/ver/1485875/incubator/climate/trunk/rcmet/src/main/python/rcmes/toolkit
+END
+visualize.py
+K 25
+svn:wc:ra_dav:version-url
+V 100
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/python/rcmes/toolkit/visualize.py
+END
+process.py
+K 25
+svn:wc:ra_dav:version-url
+V 98
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/python/rcmes/toolkit/process.py
+END
+__init__.py
+K 25
+svn:wc:ra_dav:version-url
+V 99
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/python/rcmes/toolkit/__init__.py
+END
+do_data_prep.py
+K 25
+svn:wc:ra_dav:version-url
+V 103
+/repos/asf/!svn/ver/1485875/incubator/climate/trunk/rcmet/src/main/python/rcmes/toolkit/do_data_prep.py
+END
+plots.py
+K 25
+svn:wc:ra_dav:version-url
+V 96
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/python/rcmes/toolkit/plots.py
+END
+metrics.py
+K 25
+svn:wc:ra_dav:version-url
+V 98
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/python/rcmes/toolkit/metrics.py
+END

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/rcmes/toolkit/.svn/entries
----------------------------------------------------------------------
diff --git a/src/main/python/rcmes/toolkit/.svn/entries b/src/main/python/rcmes/toolkit/.svn/entries
new file mode 100755
index 0000000..0aec30c
--- /dev/null
+++ b/src/main/python/rcmes/toolkit/.svn/entries
@@ -0,0 +1,232 @@
+10
+
+dir
+1485921
+https://svn.apache.org/repos/asf/incubator/climate/trunk/rcmet/src/main/python/rcmes/toolkit
+https://svn.apache.org/repos/asf
+
+
+
+2013-05-23T22:20:38.670815Z
+1485875
+goodale
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+13f79535-47bb-0310-9956-ffa450edef68
+
+visualize.py
+file
+
+
+
+
+2013-05-24T10:13:49.000000Z
+6f61f99e6bb37b883ce3bb0470cd2545
+2012-08-16T14:36:57.243978Z
+1473887
+cgoodale
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+77
+
+process.py
+file
+
+
+
+
+2013-05-24T10:13:49.000000Z
+6172bcb1200fef493d541d93407c12ed
+2013-02-20T16:20:33.453039Z
+1474977
+cgoodale
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+46769
+
+__init__.py
+file
+
+
+
+
+2013-05-24T10:13:49.000000Z
+8761fbbcde9579ef3c42e09923e56f93
+2012-08-16T14:36:57.243978Z
+1473887
+cgoodale
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+148
+
+do_data_prep.py
+file
+
+
+
+
+2013-05-24T10:13:49.000000Z
+881100e684bbad5dffcaa35da3d4a216
+2013-05-23T22:20:38.670815Z
+1485875
+goodale
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+16200
+
+plots.py
+file
+
+
+
+
+2013-05-24T10:13:49.000000Z
+16d8de7760d609df6373d15fee4cffe6
+2013-03-05T16:58:18.846251Z
+1475040
+mjjoyce
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+16323
+
+metrics.py
+file
+
+
+
+
+2013-05-24T10:13:49.000000Z
+8dbdd12fc067e73c0ae2c5f48c7245a7
+2013-02-10T21:47:51.341146Z
+1474940
+cgoodale
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+58120
+

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/rcmes/toolkit/.svn/prop-base/__init__.py.svn-base
----------------------------------------------------------------------
diff --git a/src/main/python/rcmes/toolkit/.svn/prop-base/__init__.py.svn-base b/src/main/python/rcmes/toolkit/.svn/prop-base/__init__.py.svn-base
new file mode 100755
index 0000000..614166f
--- /dev/null
+++ b/src/main/python/rcmes/toolkit/.svn/prop-base/__init__.py.svn-base
@@ -0,0 +1,5 @@
+K 12
+svn:keywords
+V 11
+Id Revision
+END

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/rcmes/toolkit/.svn/prop-base/visualize.py.svn-base
----------------------------------------------------------------------
diff --git a/src/main/python/rcmes/toolkit/.svn/prop-base/visualize.py.svn-base b/src/main/python/rcmes/toolkit/.svn/prop-base/visualize.py.svn-base
new file mode 100755
index 0000000..614166f
--- /dev/null
+++ b/src/main/python/rcmes/toolkit/.svn/prop-base/visualize.py.svn-base
@@ -0,0 +1,5 @@
+K 12
+svn:keywords
+V 11
+Id Revision
+END

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/rcmes/toolkit/.svn/text-base/__init__.py.svn-base
----------------------------------------------------------------------
diff --git a/src/main/python/rcmes/toolkit/.svn/text-base/__init__.py.svn-base b/src/main/python/rcmes/toolkit/.svn/text-base/__init__.py.svn-base
new file mode 100755
index 0000000..11548e6
--- /dev/null
+++ b/src/main/python/rcmes/toolkit/.svn/text-base/__init__.py.svn-base
@@ -0,0 +1,2 @@
+"""The toolkit Package is a collection of modules that provide a set of tools
+that can be used to process, analyze and plot the analysis results."""
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/rcmes/toolkit/.svn/text-base/do_data_prep.py.svn-base
----------------------------------------------------------------------
diff --git a/src/main/python/rcmes/toolkit/.svn/text-base/do_data_prep.py.svn-base b/src/main/python/rcmes/toolkit/.svn/text-base/do_data_prep.py.svn-base
new file mode 100755
index 0000000..1b5c545
--- /dev/null
+++ b/src/main/python/rcmes/toolkit/.svn/text-base/do_data_prep.py.svn-base
@@ -0,0 +1,370 @@
+"""Prepare Datasets both model and observations for analysis using metrics"""
+
+
+import numpy as np
+import numpy.ma as ma
+import sys, os
+
+import Nio
+
+from storage import db, files
+import process
+from utils import misc
+
+# TODO:  swap gridBox for Domain
+def prep_data(settings, obsDatasetList, gridBox, modelList):
+    """
+    
+    returns numOBSs,numMDLs,nT,ngrdY,ngrdX,Times,lons,lats,obsData,modelData,obsList
+    
+        numOBSs - number of Observational Datasets.  Really need to look at using len(obsDatasetList) instead
+        numMDLs - number of Models used.  Again should use the len(modelList) instead
+        nT - Time value count after temporal regridding. Should use length of the time axis for a given dataset
+        ngrdY - size of the Y-Axis grid after spatial regridding
+        ngrdX - size of the X-Axis grid after spatial regridding
+        Times - list of python datetime objects the represent the list of time to be used in further calculations
+        lons - 
+        lats - 
+        obsData - 
+        modelData - 
+        obsList - 
+        
+    
+    """
+    
+    # TODO:  Stop the object Deserialization and work on refactoring the core code here
+    cachedir = settings.cacheDir
+    workdir = settings.workDir
+
+    # Use list comprehensions to deconstruct obsDatasetList
+    #  ['TRMM_pr_mon', 'CRU3.1_pr']    Basically a list of Dataset NAME +'_' + parameter name - THE 'CRU*' one triggers unit conversion issues later
+    # the plan here is to use the obsDatasetList which contains a longName key we can use.
+    obsList = [str(x['longname']) for x in obsDatasetList]
+    # Also using the obsDatasetList with a key of ['dataset_id']
+    obsDatasetId = [str(x['dataset_id']) for x in obsDatasetList]
+    # obsDatasetList ['paramter_id'] list
+    obsParameterId = [str(x['parameter_id']) for x in obsDatasetList]
+    obsTimestep = [str(x['timestep']) for x in obsDatasetList]
+    mdlList = [model.filename for model in modelList]
+
+    # Since all of the model objects in the modelList have the same Varnames and Precip Flag, I am going to merely 
+    # pull this from modelList[0] for now
+    modelVarName = modelList[0].varName
+    precipFlag = modelList[0].precipFlag
+    modelTimeVarName = modelList[0].timeVariable
+    modelLatVarName = modelList[0].latVariable
+    modelLonVarName = modelList[0].lonVariable
+    regridOption = settings.spatialGrid
+    timeRegridOption = settings.temporalGrid
+    
+    """
+     Routine to read-in and re-grid both obs and mdl datasets.
+     Processes both single and multiple files of obs and mdl or combinations in a general way.
+           i)    retrieve observations from the database
+           ii)   load in model data
+           iii)  temporal regridding
+           iv)   spatial regridding
+           v)    area-averaging
+           Input:
+                   cachedir 	- string describing directory path
+                   workdir 	- string describing directory path
+                   obsList        - string describing the observation data files
+                   obsDatasetId 	- int, db dataset id
+                   obsParameterId	- int, db parameter id 
+                   latMin, latMax, lonMin, lonMax, dLat, dLon, naLats, naLons: define the evaluation/analysis domain/grid system
+    	         latMin		- float
+                   latMax		- float
+                   lonMin		- float
+                   lonMax		- float
+                   dLat  		- float
+                   dLon  		- float
+                   naLats		- integer
+                   naLons		- integer
+                   mdlList	- string describing model file name + path
+                   modelVarName	- string describing name of variable to evaluate (as written in model file)
+    	         precipFlag	- bool  (is this precipitation data? True/False)
+                   modelTimeVarName - string describing name of time variable in model file 	
+                   modelLatVarName  - string describing name of latitude variable in model file 
+                   modelLonVarName  - string describing name of longitude variable in model file 
+                   regridOption 	 - string: 'obs'|'model'|'user'
+                   timeRegridOption -string: 'full'|'annual'|'monthly'|'daily'
+                   maskOption - Boolean
+                   
+                   # TODO:  This isn't true in the current codebase.
+                   Instead the SubRegion's are being used.  You can see that these values are not
+                   being used in the code, at least they are not being passed in from the function
+                   
+                   maskLatMin - float (only used if maskOption=1)
+                   maskLatMax - float (only used if maskOption=1)
+    	         maskLonMin - float (only used if maskOption=1)
+                   maskLonMax - float (only used if maskOption=1)
+           Output: image files of plots + possibly data
+           Jinwon Kim, 7/11/2012
+    """
+
+
+    # check the number of obs & model data files
+    numOBSs = len(obsList)
+    numMDLs = len(mdlList)
+    
+    # assign parameters that must be preserved throughout the process
+    
+    print 'start & end time = ', settings.startDate, settings.endDate
+    yymm0 = settings.startDate.strftime("%Y%m")
+    yymm1 = settings.endDate.strftime("%Y%m")
+    print 'start & end eval period = ', yymm0, yymm1
+
+
+
+    #TODO: Wrap in try except blocks instead
+    if numMDLs < 1: 
+        print 'No input model data file. EXIT'
+        sys.exit()
+    if numOBSs < 1: 
+        print 'No input observation data file. EXIT'
+        sys.exit()
+
+    ## Part 1: retrieve observation data from the database and regrid them
+    ##       NB. automatically uses local cache if already retrieved.
+
+    # preparation for spatial re-gridding: define the size of horizontal array of the target interpolation grid system (ngrdX and ngrdY)
+    print 'regridOption in prep_data= ', regridOption
+    if regridOption == 'model':
+        ifile = mdlList[0]
+        typeF = 'nc'
+        lats, lons, mTimes = files.read_lolaT_from_file(ifile, modelLatVarName, modelLonVarName, modelTimeVarName, typeF)
+        modelObject = modelList[0]
+        latMin = modelObject.latMin
+        latMax = modelObject.latMax
+        lonMin = modelObject.lonMin
+        lonMax = modelObject.lonMax
+    elif regridOption == 'user':
+        # Use the GridBox Object
+        latMin = gridBox.latMin
+        latMax = gridBox.latMax
+        lonMin = gridBox.lonMin
+        lonMax = gridBox.lonMax
+        naLats = gridBox.latCount
+        naLons = gridBox.lonCount
+        dLat = gridBox.latStep
+        dLon = gridBox.lonStep
+        lat = np.arange(naLats) * dLat + latMin
+        lon = np.arange(naLons) * dLon + lonMin
+        lons, lats = np.meshgrid(lon, lat)
+        lon = 0.
+        lat = 0.
+    else:
+        print "INVALID REGRID OPTION USED"
+        sys.exit()
+        
+    ngrdY = lats.shape[0]
+    ngrdX = lats.shape[1]
+
+    regObsData = []
+    
+    for n in np.arange(numOBSs):
+        # spatial regridding
+        oLats, oLons, _, oTimes, oData = db.extractData(obsDatasetId[n],
+                                                        obsParameterId[n],
+                                                        latMin, latMax,
+                                                        lonMin, lonMax,
+                                                        settings.startDate, settings.endDate,
+                                                        cachedir, obsTimestep[n])
+        
+        # TODO: modify this if block with new metadata usage.
+        if precipFlag == True and obsList[n][0:3] == 'CRU':
+            oData = 86400.0 * oData
+
+        nstOBSs = oData.shape[0]         # note that the length of obs data can vary for different obs intervals (e.g., daily vs. monthly)
+        print 'Regrid OBS dataset onto the ', regridOption, ' grid system: ngrdY, ngrdX, nstOBSs= ', ngrdY, ngrdX, nstOBSs
+        print 'For dataset: %s' % obsList[n]
+        
+        tmpOBS = ma.zeros((nstOBSs, ngrdY, ngrdX))
+        
+        print 'tmpOBS shape = ', tmpOBS.shape
+        
+        for t in np.arange(nstOBSs):
+            tmpOBS[t, :, :] = process.do_regrid(oData[t, :, :], oLats, oLons, lats, lons)
+            
+        # TODO:  Not sure this is needed with Python Garbage Collector
+        # The used memory should be freed when the objects are no longer referenced.  If this continues to be an issue we may need to look
+        # at using generators where possible.
+        oLats = 0.0
+        oLons = 0.0       # release the memory occupied by the temporary variables oLats and oLons.
+        
+        # temporally regrid the spatially regridded obs data
+        oData, newObsTimes = process.calc_average_on_new_time_unit_K(tmpOBS, oTimes, unit=timeRegridOption)
+
+        tmpOBS = 0.0
+        
+        # check the consistency of temporally regridded obs data
+        if n == 0:
+            oldObsTimes = newObsTimes
+        else:
+            if oldObsTimes != newObsTimes:
+                print 'temporally regridded obs data time levels do not match at ', n - 1, n
+                print '%s Time through Loop' % (n + 1)
+                print 'oldObsTimes Count: %s' % len(oldObsTimes)
+                print 'newObsTimes Count: %s' % len(newObsTimes)
+                # TODO:  We need to handle these cases using Try Except Blocks or insert a sys.exit if appropriate
+                sys.exit()
+            else:
+                oldObsTimes = newObsTimes
+        # if everything's fine, append the spatially and temporally regridded data in the obs data array (obsData)
+        regObsData.append(oData)
+
+
+    """ all obs datasets have been read-in and regridded. convert the regridded obs data from 'list' to 'array'
+    also finalize 'obsTimes', the time coordinate values of the regridded obs data.
+    NOTE: using 'list_to_array' assigns values to the missing points; this has become a problem in handling the CRU data.
+          this problem disappears by using 'ma.array'."""
+
+    obsData = ma.array(regObsData)
+    obsTimes = newObsTimes
+    regObsData = 0
+    oldObsTimes = 0
+    nT = len(obsTimes)
+
+    # TODO:  Refactor this into a function within the toolkit module
+    # compute the simple multi-obs ensemble if multiple obs are used
+    if numOBSs > 1:
+        print 'numOBSs = ', numOBSs
+        oData = obsData
+        print 'oData shape = ', oData.shape
+        obsData = ma.zeros((numOBSs + 1, nT, ngrdY, ngrdX))
+        print 'obsData shape = ', obsData.shape
+        avg = ma.zeros((nT, ngrdY, ngrdX))
+        
+        for i in np.arange(numOBSs):
+            obsData[i, :, :, :] = oData[i, :, :, :]
+            avg[:, :, :] = avg[:, :, :] + oData[i, :, :, :]
+
+        avg = avg / float(numOBSs)
+        obsData[numOBSs, :, :, :] = avg[:, :, :]     # store the model-ensemble data
+        numOBSs = numOBSs + 1                     # update the number of obs data to include the model ensemble
+        obsList.append('ENS-OBS')
+    print 'OBS regridded: ', obsData.shape
+
+
+    ## Part 2: load in and regrid model data from file(s)
+    ## NOTE: tthe wo parameters, numMDLs and numMOmx are defined to represent the number of models (w/ all 240 mos) &
+    ##       the total number of months, respectively, in later multi-model calculations.
+
+    typeF = 'nc'
+    regridMdlData = []
+    # extract the model names and store them in the list 'mdlList'
+    mdlName = []
+    mdlListReversed=[]
+    if len(mdlList) >1:
+       for element in mdlList:
+           mdlListReversed.append(element[::-1])
+       prefix=os.path.commonprefix(mdlList)
+       postfix=os.path.commonprefix(mdlListReversed)[::-1]
+       for element in mdlList:
+           mdlName.append(element.replace(prefix,'').replace(postfix,''))
+    else:
+        mdlName.append('model') 
+
+    
+    for n in np.arange(numMDLs):
+        # read model grid info, then model data
+        ifile = mdlList[n]
+        print 'ifile= ', ifile
+        modelLats, modelLons, mTimes = files.read_lolaT_from_file(ifile, modelLatVarName, modelLonVarName, modelTimeVarName, typeF)
+        mTime, mdlDat, mvUnit = files.read_data_from_one_file(ifile, modelVarName, modelTimeVarName, modelLats, typeF)
+        mdlT = []
+        mStep = len(mTimes)
+
+        for i in np.arange(mStep):
+            mdlT.append(mTimes[i].strftime("%Y%m"))
+
+        wh = (np.array(mdlT) >= yymm0) & (np.array(mdlT) <= yymm1)
+        modelTimes = list(np.array(mTimes)[wh])
+        mData = mdlDat[wh, :, :]
+   
+        # determine the dimension size from the model time and latitude data.
+        nT = len(modelTimes)
+        
+        # UNUSED VARIABLES - WILL DELETE AFTER TESTING
+        # nmdlY=modelLats.shape[0]
+        # nmdlX=modelLats.shape[1]
+        #print 'nT, ngrdY, ngrdX = ',nT,ngrdY, ngrdX,min(modelTimes),max(modelTimes)
+        print '  The shape of model data to be processed= ', mData.shape, ' for the period ', min(modelTimes), max(modelTimes)
+        # spatial regridding of the modl data
+        tmpMDL = ma.zeros((nT, ngrdY, ngrdX))
+
+        if regridOption != 'model':
+            for t in np.arange(nT):
+                tmpMDL[t, :, :] = process.do_regrid(mData[t, :, :], modelLats, modelLons, lats, lons)
+        else:
+            tmpMDL = mData
+
+        # temporally regrid the model data
+        mData, newMdlTimes = process.regrid_in_time(tmpMDL, modelTimes, unit=timeRegridOption)
+        tmpMDL = 0.0
+        
+        # check data consistency for all models 
+        if n == 0:
+            oldMdlTimes = newMdlTimes
+        else:
+            if oldMdlTimes != newMdlTimes:
+                print 'temporally regridded mdl data time levels do not match at ', n - 1, n
+                print len(oldMdlTimes), len(newMdlTimes)
+                sys.exit()
+            else:
+                oldMdlTimes = newMdlTimes
+
+        # if everything's fine, append the spatially and temporally regridded data in the obs data array (obsData)
+        regridMdlData.append(mData)
+
+    modelData = ma.array(regridMdlData)
+    modelTimes = newMdlTimes
+    regridMdlData = 0
+    oldMdlTimes = 0
+    newMdlTimes = 0
+    if (precipFlag == True) & (mvUnit == 'KG M-2 S-1'):
+        print 'convert model variable unit from mm/s to mm/day'
+        modelData = 86400.*modelData
+    
+    # check consistency between the time levels of the model and obs data
+    #   this is the final update of time levels: 'Times' and 'nT'
+    if obsTimes != modelTimes:
+        print 'time levels of the obs and model data are not consistent. EXIT'
+        print 'obsTimes'
+        print obsTimes
+        print 'modelTimes'
+        print modelTimes
+        sys.exit()
+    #  'Times = modelTimes = obsTimes' has been established and modelTimes and obsTimes will not be used hereafter. (de-allocated)
+    Times = modelTimes
+    nT = len(modelTimes)
+    modelTimes = 0
+    obsTimes = 0
+
+    print 'Reading and regridding model data are completed'
+    print 'numMDLs, modelData.shape= ', numMDLs, modelData.shape
+    
+    # TODO: Do we need to make this a user supplied flag, or do we just create an ensemble ALWAYS
+    # TODO: Add in Kyo's code here as well
+    # TODO:  Commented out until I can talk with Jinwon about this
+    # compute the simple multi-model ensemble if multiple models are evaluated
+    if numMDLs > 1:
+        mdlData=modelData
+        modelData=ma.zeros((numMDLs+1,nT,ngrdY,ngrdX))
+        avg=ma.zeros((nT,ngrdY,ngrdX))
+        for i in np.arange(numMDLs):
+            modelData[i,:,:,:]=mdlData[i,:,:,:]
+            avg[:,:,:]=avg[:,:,:]+mdlData[i,:,:,:]
+        avg=avg/float(numMDLs)
+        modelData[numMDLs,:,:,:]=avg[:,:,:]     # store the model-ensemble data
+        # THESE ARE NOT USED.  WILL DELETE AFTER TESTING
+        # i0mdl=0
+        # i1mdl=numMDLs
+        numMDLs=numMDLs+1
+        mdlList.append('ENS-MODEL')
+        print 'Eval mdl-mean timeseries for the obs periods: modelData.shape= ',modelData.shape
+    # GOODALE:  This ensemble code should be refactored into process.py module since it's purpose is data processing
+
+    # Processing complete
+    print 'data_prep is completed: both obs and mdl data are re-gridded to a common analysis grid'
+    return numOBSs, numMDLs, nT, ngrdY, ngrdX, Times, lons, lats, obsData, modelData, obsList, mdlName


[51/51] [abbrv] [partial] git commit: Adding Jinwon's custom RCMET

Posted by jo...@apache.org.
Adding Jinwon's custom RCMET


Project: http://git-wip-us.apache.org/repos/asf/climate/repo
Commit: http://git-wip-us.apache.org/repos/asf/climate/commit/a6aa1cd2
Tree: http://git-wip-us.apache.org/repos/asf/climate/tree/a6aa1cd2
Diff: http://git-wip-us.apache.org/repos/asf/climate/diff/a6aa1cd2

Branch: refs/heads/jinwon-rcmet-2.1.3
Commit: a6aa1cd2b87e8f702b96329652ab413d137bf1d8
Parents: d4e954a
Author: Michael Joyce <jo...@apache.org>
Authored: Thu May 8 19:01:48 2014 -0700
Committer: Michael Joyce <jo...@apache.org>
Committed: Thu May 8 19:01:48 2014 -0700

----------------------------------------------------------------------
 LICENSE.txt                                     |   202 +
 readme_v2.1.3                                   |   278 +
 src/.svn/all-wcprops                            |     5 +
 src/.svn/entries                                |    31 +
 src/main/.svn/all-wcprops                       |     5 +
 src/main/.svn/entries                           |    43 +
 src/main/python/.svn/all-wcprops                |     5 +
 src/main/python/.svn/entries                    |    40 +
 src/main/python/bin/.svn/all-wcprops            |    11 +
 src/main/python/bin/.svn/entries                |    62 +
 .../python/bin/.svn/prop-base/rcmet.py.svn-base |     5 +
 .../python/bin/.svn/text-base/rcmet.py.svn-base |   247 +
 src/main/python/bin/rcmet.py                    |   305 +
 src/main/python/docs/.svn/all-wcprops           |    77 +
 src/main/python/docs/.svn/dir-prop-base         |     6 +
 src/main/python/docs/.svn/entries               |   442 +
 ...ttle Web Service Documentation.docx.svn-base |     5 +
 .../prop-base/RCMET_documentation.docx.svn-base |     5 +
 .../python/docs/.svn/prop-base/conf.py.svn-base |     5 +
 .../docs/.svn/prop-base/index.rst.svn-base      |     5 +
 .../docs/.svn/prop-base/make.bat.svn-base       |     5 +
 .../docs/.svn/prop-base/rcmes.cli.rst.svn-base  |     5 +
 .../docs/.svn/prop-base/rcmes.rst.svn-base      |     5 +
 .../.svn/prop-base/rcmes.services.rst.svn-base  |     5 +
 .../.svn/prop-base/rcmes.storage.rst.svn-base   |     5 +
 .../.svn/prop-base/rcmes.toolkit.rst.svn-base   |     5 +
 .../.svn/prop-base/rcmes.utils.rst.svn-base     |     5 +
 ...ttle Web Service Documentation.docx.svn-base |   Bin 0 -> 179630 bytes
 .../docs/.svn/text-base/Makefile.svn-base       |   153 +
 .../text-base/RCMET_documentation.docx.svn-base |   Bin 0 -> 190254 bytes
 .../python/docs/.svn/text-base/conf.py.svn-base |   242 +
 .../docs/.svn/text-base/index.rst.svn-base      |    22 +
 .../docs/.svn/text-base/make.bat.svn-base       |   190 +
 .../docs/.svn/text-base/rcmes.cli.rst.svn-base  |    19 +
 .../docs/.svn/text-base/rcmes.rst.svn-base      |    22 +
 .../.svn/text-base/rcmes.services.rst.svn-base  |    51 +
 .../.svn/text-base/rcmes.storage.rst.svn-base   |    27 +
 .../.svn/text-base/rcmes.toolkit.rst.svn-base   |    27 +
 .../.svn/text-base/rcmes.utils.rst.svn-base     |    19 +
 .../docs/Bottle Web Service Documentation.docx  |   Bin 0 -> 179630 bytes
 src/main/python/docs/Makefile                   |   153 +
 src/main/python/docs/RCMET_documentation.docx   |   Bin 0 -> 190254 bytes
 src/main/python/docs/_static/.svn/all-wcprops   |     5 +
 src/main/python/docs/_static/.svn/entries       |    28 +
 .../python/docs/_templates/.svn/all-wcprops     |     5 +
 src/main/python/docs/_templates/.svn/entries    |    28 +
 src/main/python/docs/conf.py                    |   242 +
 src/main/python/docs/index.rst                  |    22 +
 src/main/python/docs/make.bat                   |   190 +
 src/main/python/docs/rcmes.cli.rst              |    19 +
 src/main/python/docs/rcmes.rst                  |    22 +
 src/main/python/docs/rcmes.services.rst         |    51 +
 src/main/python/docs/rcmes.storage.rst          |    27 +
 src/main/python/docs/rcmes.toolkit.rst          |    27 +
 src/main/python/docs/rcmes.utils.rst            |    19 +
 src/main/python/rcmes/.rcmet.py.swp             |   Bin 0 -> 28672 bytes
 src/main/python/rcmes/.svn/all-wcprops          |    23 +
 src/main/python/rcmes/.svn/dir-prop-base        |     6 +
 src/main/python/rcmes/.svn/entries              |   148 +
 .../python/rcmes/.svn/text-base/README.svn-base |     8 +
 .../rcmes/.svn/text-base/__init__.py.svn-base   |     1 +
 .../rcmes/.svn/text-base/classes.py.svn-base    |   211 +
 src/main/python/rcmes/__init__.py               |     1 +
 src/main/python/rcmes/classes.py                |   208 +
 src/main/python/rcmes/classes.pyc               |   Bin 0 -> 10429 bytes
 src/main/python/rcmes/cli/.svn/all-wcprops      |    29 +
 src/main/python/rcmes/cli/.svn/entries          |   164 +
 .../cli/.svn/prop-base/__init__.py.svn-base     |     5 +
 .../.svn/prop-base/rcmet20_cordexAF.py.svn-base |     5 +
 .../cli/.svn/prop-base/rcmet_ui.py.svn-base     |     5 +
 .../cli/.svn/text-base/__init__.py.svn-base     |    11 +
 .../do_rcmes_processing_sub.py.svn-base         |   730 +
 .../.svn/text-base/rcmet20_cordexAF.py.svn-base |   980 +
 .../cli/.svn/text-base/rcmet_ui.py.svn-base     |    91 +
 src/main/python/rcmes/cli/__init__.py           |    11 +
 src/main/python/rcmes/cli/__init__.pyc          |   Bin 0 -> 387 bytes
 .../python/rcmes/cli/do_rcmes_processing_sub.py |   730 +
 src/main/python/rcmes/cli/rcmet20_cordexAF.py   |   980 +
 src/main/python/rcmes/cli/rcmet_ui.py           |    91 +
 src/main/python/rcmes/cli/rcmet_ui.pyc          |   Bin 0 -> 3037 bytes
 src/main/python/rcmes/rcmet.py                  |   305 +
 .../python/rcmes/resources/.svn/all-wcprops     |    17 +
 src/main/python/rcmes/resources/.svn/entries    |    99 +
 .../.svn/text-base/cordexAF.cfg.svn-base        |    30 +
 .../text-base/cordexSubRegions.txt.svn-base     |    25 +
 src/main/python/rcmes/resources/cordexAF.cfg    |    55 +
 src/main/python/rcmes/resources/cordexIndia.cfg |    56 +
 src/main/python/rcmes/resources/narccap.cfg     |    55 +
 src/main/python/rcmes/services/.svn/all-wcprops |    71 +
 src/main/python/rcmes/services/.svn/entries     |   402 +
 .../.svn/prop-base/__init__.py.svn-base         |     5 +
 .../prop-base/decode_model_times.py.svn-base    |     5 +
 .../.svn/prop-base/find_latlon_var.py.svn-base  |     5 +
 .../.svn/prop-base/find_time_var.py.svn-base    |     5 +
 .../prop-base/list_vars_in_file.py.svn-base     |     5 +
 .../services/.svn/text-base/README.txt.svn-base |    68 +
 .../.svn/text-base/__init__.py.svn-base         |     2 +
 .../.svn/text-base/bottlemet.py.svn-base        |   599 +
 .../.svn/text-base/dataset_helpers.py.svn-base  |    32 +
 .../text-base/decode_model_times.py.svn-base    |   185 +
 .../text-base/directory_helpers.py.svn-base     |    42 +
 .../.svn/text-base/find_latlon_var.py.svn-base  |   136 +
 .../.svn/text-base/find_time_var.py.svn-base    |    87 +
 .../text-base/list_vars_in_file.py.svn-base     |    59 +
 .../services/.svn/text-base/main_ws.py.svn-base |    36 +
 .../text-base/run_rcmes_processing.py.svn-base  |   114 +
 src/main/python/rcmes/services/README.txt       |    68 +
 src/main/python/rcmes/services/__init__.py      |     2 +
 src/main/python/rcmes/services/bottlemet.py     |   599 +
 .../python/rcmes/services/dataset_helpers.py    |    32 +
 .../python/rcmes/services/decode_model_times.py |   185 +
 .../python/rcmes/services/directory_helpers.py  |    42 +
 .../python/rcmes/services/find_latlon_var.py    |   136 +
 src/main/python/rcmes/services/find_time_var.py |    87 +
 .../python/rcmes/services/list_vars_in_file.py  |    59 +
 src/main/python/rcmes/services/main_ws.py       |    36 +
 .../rcmes/services/run_rcmes_processing.py      |   114 +
 src/main/python/rcmes/storage/.svn/all-wcprops  |    29 +
 src/main/python/rcmes/storage/.svn/entries      |   164 +
 .../storage/.svn/prop-base/__init__.py.svn-base |     5 +
 .../storage/.svn/text-base/__init__.py.svn-base |     2 +
 .../rcmes/storage/.svn/text-base/db.py.svn-base |   343 +
 .../storage/.svn/text-base/files.py.svn-base    |   692 +
 .../storage/.svn/text-base/rcmed.py.svn-base    |   113 +
 src/main/python/rcmes/storage/__init__.py       |     2 +
 src/main/python/rcmes/storage/__init__.pyc      |   Bin 0 -> 349 bytes
 src/main/python/rcmes/storage/db.py             |   359 +
 src/main/python/rcmes/storage/db.pyc            |   Bin 0 -> 10714 bytes
 src/main/python/rcmes/storage/files.py          |   861 +
 src/main/python/rcmes/storage/files.pyc         |   Bin 0 -> 24663 bytes
 src/main/python/rcmes/storage/rcmed.py          |   349 +
 src/main/python/rcmes/storage/rcmed.pyc         |   Bin 0 -> 10360 bytes
 src/main/python/rcmes/toolkit/.svn/all-wcprops  |    41 +
 src/main/python/rcmes/toolkit/.svn/entries      |   232 +
 .../toolkit/.svn/prop-base/__init__.py.svn-base |     5 +
 .../.svn/prop-base/visualize.py.svn-base        |     5 +
 .../toolkit/.svn/text-base/__init__.py.svn-base |     2 +
 .../.svn/text-base/do_data_prep.py.svn-base     |   370 +
 .../toolkit/.svn/text-base/metrics.py.svn-base  |  1345 +
 .../toolkit/.svn/text-base/plots.py.svn-base    |   443 +
 .../toolkit/.svn/text-base/process.py.svn-base  |  1263 +
 .../.svn/text-base/visualize.py.svn-base        |     1 +
 src/main/python/rcmes/toolkit/__init__.py       |     2 +
 src/main/python/rcmes/toolkit/__init__.pyc      |   Bin 0 -> 342 bytes
 src/main/python/rcmes/toolkit/do_data_prep.py   |   461 +
 src/main/python/rcmes/toolkit/do_data_prep.pyc  |   Bin 0 -> 9966 bytes
 src/main/python/rcmes/toolkit/metrics.py        |  2550 ++
 src/main/python/rcmes/toolkit/metrics.pyc       |   Bin 0 -> 74993 bytes
 src/main/python/rcmes/toolkit/process.py        |  1270 +
 src/main/python/rcmes/toolkit/process.pyc       |   Bin 0 -> 30596 bytes
 src/main/python/rcmes/utils/.svn/all-wcprops    |    23 +
 src/main/python/rcmes/utils/.svn/entries        |   130 +
 .../utils/.svn/prop-base/__init__.py.svn-base   |     5 +
 .../utils/.svn/text-base/__init__.py.svn-base   |     2 +
 .../.svn/text-base/fortranfile.py.svn-base      |   274 +
 .../rcmes/utils/.svn/text-base/misc.py.svn-base |  1326 +
 src/main/python/rcmes/utils/Taylor.py           |   126 +
 src/main/python/rcmes/utils/Taylor.pyc          |   Bin 0 -> 5234 bytes
 src/main/python/rcmes/utils/__init__.py         |     2 +
 src/main/python/rcmes/utils/__init__.pyc        |   Bin 0 -> 283 bytes
 src/main/python/rcmes/utils/fortranfile.py      |   274 +
 src/main/python/rcmes/utils/fortranfile.pyc     |   Bin 0 -> 9905 bytes
 src/main/python/rcmes/utils/misc.py             |  1385 +
 src/main/python/rcmes/utils/misc.pyc            |   Bin 0 -> 42484 bytes
 src/main/resources/.svn/all-wcprops             |    23 +
 src/main/resources/.svn/entries                 |   130 +
 .../.svn/text-base/PyLintREADME.txt.svn-base    |    26 +
 .../.svn/text-base/pyLintRcFile.txt.svn-base    |   249 +
 .../.svn/text-base/rcmet_use_case.txt.svn-base  |    57 +
 src/main/resources/PyLintREADME.txt             |    26 +
 src/main/resources/pyLintRcFile.txt             |   249 +
 src/main/resources/rcmet_use_case.txt           |    57 +
 src/main/ui/.svn/all-wcprops                    |     5 +
 src/main/ui/.svn/entries                        |    43 +
 src/main/ui/app/.svn/all-wcprops                |    17 +
 src/main/ui/app/.svn/entries                    |   114 +
 .../.svn/prop-base/index-async.html.svn-base    |     5 +
 .../ui/app/.svn/prop-base/index.html.svn-base   |     5 +
 .../.svn/text-base/index-async.html.svn-base    |    57 +
 .../ui/app/.svn/text-base/index.html.svn-base   |   192 +
 src/main/ui/app/css/.svn/all-wcprops            |    41 +
 src/main/ui/app/css/.svn/entries                |   232 +
 .../ui/app/css/.svn/prop-base/app.css.svn-base  |     5 +
 .../prop-base/font-awesome.min.css.svn-base     |     5 +
 .../ui/app/css/.svn/text-base/app.css.svn-base  |    27 +
 .../bootstrap-responsive.min.css.svn-base       |     9 +
 .../.svn/text-base/bootstrap.min.css.svn-base   |     9 +
 .../text-base/font-awesome.min.css.svn-base     |    33 +
 .../jasny-bootstrap-responsive.min.css.svn-base |     9 +
 .../text-base/jasny-bootstrap.min.css.svn-base  |     9 +
 src/main/ui/app/css/app.css                     |    27 +
 .../ui/app/css/bootstrap-responsive.min.css     |     9 +
 src/main/ui/app/css/bootstrap.min.css           |     9 +
 src/main/ui/app/css/font-awesome.min.css        |    33 +
 .../app/css/jasny-bootstrap-responsive.min.css  |     9 +
 src/main/ui/app/css/jasny-bootstrap.min.css     |     9 +
 src/main/ui/app/font/.svn/all-wcprops           |    35 +
 src/main/ui/app/font/.svn/entries               |   198 +
 .../.svn/prop-base/FontAwesome.otf.svn-base     |     9 +
 .../prop-base/fontawesome-webfont.eot.svn-base  |     9 +
 .../prop-base/fontawesome-webfont.svg.svn-base  |     5 +
 .../prop-base/fontawesome-webfont.ttf.svn-base  |     9 +
 .../prop-base/fontawesome-webfont.woff.svn-base |     9 +
 .../.svn/text-base/FontAwesome.otf.svn-base     |   Bin 0 -> 48748 bytes
 .../text-base/fontawesome-webfont.eot.svn-base  |   Bin 0 -> 25395 bytes
 .../text-base/fontawesome-webfont.svg.svn-base  |   284 +
 .../text-base/fontawesome-webfont.ttf.svn-base  |   Bin 0 -> 55096 bytes
 .../text-base/fontawesome-webfont.woff.svn-base |   Bin 0 -> 29380 bytes
 src/main/ui/app/font/FontAwesome.otf            |   Bin 0 -> 48748 bytes
 src/main/ui/app/font/fontawesome-webfont.eot    |   Bin 0 -> 25395 bytes
 src/main/ui/app/font/fontawesome-webfont.svg    |   284 +
 src/main/ui/app/font/fontawesome-webfont.ttf    |   Bin 0 -> 55096 bytes
 src/main/ui/app/font/fontawesome-webfont.woff   |   Bin 0 -> 29380 bytes
 src/main/ui/app/img/.svn/all-wcprops            |    17 +
 src/main/ui/app/img/.svn/entries                |    96 +
 .../glyphicons-halflings-white.png.svn-base     |   Bin 0 -> 8777 bytes
 .../text-base/glyphicons-halflings.png.svn-base |   Bin 0 -> 12799 bytes
 .../ui/app/img/glyphicons-halflings-white.png   |   Bin 0 -> 8777 bytes
 src/main/ui/app/img/glyphicons-halflings.png    |   Bin 0 -> 12799 bytes
 src/main/ui/app/index-async.html                |    57 +
 src/main/ui/app/index.html                      |   192 +
 src/main/ui/app/js/.svn/all-wcprops             |    65 +
 src/main/ui/app/js/.svn/entries                 |   368 +
 .../ui/app/js/.svn/prop-base/app.js.svn-base    |     5 +
 .../js/.svn/prop-base/bootstrap.min.js.svn-base |     5 +
 .../js/.svn/prop-base/controllers.js.svn-base   |     5 +
 .../js/.svn/prop-base/directives.js.svn-base    |     5 +
 .../app/js/.svn/prop-base/filters.js.svn-base   |     5 +
 .../app/js/.svn/prop-base/services.js.svn-base  |     5 +
 .../ui/app/js/.svn/text-base/app.js.svn-base    |    53 +
 .../app/js/.svn/text-base/bootstrap.js.svn-base |  2276 ++
 .../js/.svn/text-base/bootstrap.min.js.svn-base |     6 +
 .../js/.svn/text-base/controllers.js.svn-base   |   572 +
 .../js/.svn/text-base/directives.js.svn-base    |   374 +
 .../app/js/.svn/text-base/filters.js.svn-base   |    10 +
 .../text-base/jasny-bootstrap.min.js.svn-base   |     6 +
 .../.svn/text-base/jquery-1.9.1.min.js.svn-base |     5 +
 .../app/js/.svn/text-base/leaflet.js.svn-base   |     8 +
 .../app/js/.svn/text-base/services.js.svn-base  |     9 +
 src/main/ui/app/js/app.js                       |    53 +
 src/main/ui/app/js/bootstrap.js                 |  2276 ++
 src/main/ui/app/js/bootstrap.min.js             |     6 +
 src/main/ui/app/js/controllers.js               |   572 +
 src/main/ui/app/js/directives.js                |   374 +
 src/main/ui/app/js/filters.js                   |    10 +
 src/main/ui/app/js/jasny-bootstrap.min.js       |     6 +
 src/main/ui/app/js/jquery-1.9.1.min.js          |     5 +
 src/main/ui/app/js/leaflet.js                   |     8 +
 src/main/ui/app/js/services.js                  |     9 +
 src/main/ui/app/lib/.svn/all-wcprops            |     5 +
 src/main/ui/app/lib/.svn/entries                |    31 +
 src/main/ui/app/lib/angular/.svn/all-wcprops    |    71 +
 src/main/ui/app/lib/angular/.svn/entries        |   402 +
 .../.svn/prop-base/angular-cookies.js.svn-base  |     5 +
 .../prop-base/angular-cookies.min.js.svn-base   |     5 +
 .../.svn/prop-base/angular-loader.js.svn-base   |     5 +
 .../prop-base/angular-loader.min.js.svn-base    |     5 +
 .../.svn/prop-base/angular-resource.js.svn-base |     5 +
 .../prop-base/angular-resource.min.js.svn-base  |     5 +
 .../.svn/prop-base/angular-sanitize.js.svn-base |     5 +
 .../prop-base/angular-sanitize.min.js.svn-base  |     5 +
 .../angular/.svn/prop-base/angular.js.svn-base  |     5 +
 .../.svn/prop-base/angular.min.js.svn-base      |     5 +
 .../angular/.svn/prop-base/version.txt.svn-base |     5 +
 .../.svn/text-base/angular-cookies.js.svn-base  |   183 +
 .../text-base/angular-cookies.min.js.svn-base   |     7 +
 .../.svn/text-base/angular-loader.js.svn-base   |   276 +
 .../text-base/angular-loader.min.js.svn-base    |     7 +
 .../.svn/text-base/angular-resource.js.svn-base |   445 +
 .../text-base/angular-resource.min.js.svn-base  |    10 +
 .../.svn/text-base/angular-sanitize.js.svn-base |   535 +
 .../text-base/angular-sanitize.min.js.svn-base  |    13 +
 .../angular/.svn/text-base/angular.js.svn-base  | 14733 +++++++++
 .../.svn/text-base/angular.min.js.svn-base      |   161 +
 .../angular/.svn/text-base/version.txt.svn-base |     1 +
 src/main/ui/app/lib/angular/angular-cookies.js  |   183 +
 .../ui/app/lib/angular/angular-cookies.min.js   |     7 +
 src/main/ui/app/lib/angular/angular-loader.js   |   276 +
 .../ui/app/lib/angular/angular-loader.min.js    |     7 +
 src/main/ui/app/lib/angular/angular-resource.js |   445 +
 .../ui/app/lib/angular/angular-resource.min.js  |    10 +
 src/main/ui/app/lib/angular/angular-sanitize.js |   535 +
 .../ui/app/lib/angular/angular-sanitize.min.js  |    13 +
 src/main/ui/app/lib/angular/angular.js          | 14733 +++++++++
 src/main/ui/app/lib/angular/angular.min.js      |   161 +
 src/main/ui/app/lib/angular/version.txt         |     1 +
 src/main/ui/app/partials/.svn/all-wcprops       |    35 +
 src/main/ui/app/partials/.svn/entries           |   198 +
 .../.svn/prop-base/partial1.html.svn-base       |     5 +
 .../.svn/prop-base/partial2.html.svn-base       |     5 +
 .../.svn/text-base/modelSelect.html.svn-base    |    67 +
 .../.svn/text-base/partial1.html.svn-base       |     1 +
 .../.svn/text-base/partial2.html.svn-base       |     5 +
 .../text-base/selectObservation.html.svn-base   |    44 +
 .../.svn/text-base/selectRcmed.html.svn-base    |    30 +
 src/main/ui/app/partials/modelSelect.html       |    67 +
 src/main/ui/app/partials/partial1.html          |     1 +
 src/main/ui/app/partials/partial2.html          |     5 +
 src/main/ui/app/partials/selectObservation.html |    44 +
 src/main/ui/app/partials/selectRcmed.html       |    30 +
 src/main/ui/config/.svn/all-wcprops             |    17 +
 src/main/ui/config/.svn/entries                 |    96 +
 .../prop-base/testacular-e2e.conf.js.svn-base   |     5 +
 .../.svn/prop-base/testacular.conf.js.svn-base  |     5 +
 .../text-base/testacular-e2e.conf.js.svn-base   |    22 +
 .../.svn/text-base/testacular.conf.js.svn-base  |    23 +
 src/main/ui/config/testacular-e2e.conf.js       |    22 +
 src/main/ui/config/testacular.conf.js           |    23 +
 src/main/ui/logs/.svn/all-wcprops               |     5 +
 src/main/ui/logs/.svn/entries                   |    28 +
 src/main/ui/scripts/.svn/all-wcprops            |    53 +
 src/main/ui/scripts/.svn/entries                |   300 +
 .../.svn/prop-base/e2e-test.bat.svn-base        |     5 +
 .../scripts/.svn/prop-base/e2e-test.sh.svn-base |     5 +
 .../ui/scripts/.svn/prop-base/test.bat.svn-base |     5 +
 .../ui/scripts/.svn/prop-base/test.sh.svn-base  |     5 +
 .../prop-base/testacular-e2e.conf.js.svn-base   |     5 +
 .../.svn/prop-base/testacular.conf.js.svn-base  |     5 +
 .../scripts/.svn/prop-base/watchr.rb.svn-base   |     5 +
 .../.svn/prop-base/web-server.js.svn-base       |     5 +
 .../.svn/text-base/e2e-test.bat.svn-base        |    11 +
 .../scripts/.svn/text-base/e2e-test.sh.svn-base |     9 +
 .../ui/scripts/.svn/text-base/test.bat.svn-base |    11 +
 .../ui/scripts/.svn/text-base/test.sh.svn-base  |     9 +
 .../text-base/testacular-e2e.conf.js.svn-base   |    22 +
 .../.svn/text-base/testacular.conf.js.svn-base  |    23 +
 .../scripts/.svn/text-base/watchr.rb.svn-base   |    19 +
 .../.svn/text-base/web-server.js.svn-base       |   295 +
 src/main/ui/scripts/e2e-test.bat                |    11 +
 src/main/ui/scripts/e2e-test.sh                 |     9 +
 src/main/ui/scripts/test.bat                    |    11 +
 src/main/ui/scripts/test.sh                     |     9 +
 src/main/ui/scripts/testacular-e2e.conf.js      |    22 +
 src/main/ui/scripts/testacular.conf.js          |    23 +
 src/main/ui/scripts/watchr.rb                   |    19 +
 src/main/ui/scripts/web-server.js               |   295 +
 src/main/ui/test/.svn/all-wcprops               |     5 +
 src/main/ui/test/.svn/entries                   |    37 +
 src/main/ui/test/e2e/.svn/all-wcprops           |    17 +
 src/main/ui/test/e2e/.svn/entries               |    96 +
 .../e2e/.svn/prop-base/runner.html.svn-base     |     5 +
 .../e2e/.svn/prop-base/scenarios.js.svn-base    |     5 +
 .../e2e/.svn/text-base/runner.html.svn-base     |    10 +
 .../e2e/.svn/text-base/scenarios.js.svn-base    |    45 +
 src/main/ui/test/e2e/runner.html                |    10 +
 src/main/ui/test/e2e/scenarios.js               |    45 +
 src/main/ui/test/lib/.svn/all-wcprops           |     5 +
 src/main/ui/test/lib/.svn/entries               |    31 +
 src/main/ui/test/lib/angular/.svn/all-wcprops   |    23 +
 src/main/ui/test/lib/angular/.svn/entries       |   130 +
 .../.svn/prop-base/angular-mocks.js.svn-base    |     5 +
 .../.svn/prop-base/angular-scenario.js.svn-base |     5 +
 .../angular/.svn/prop-base/version.txt.svn-base |     5 +
 .../.svn/text-base/angular-mocks.js.svn-base    |  1764 ++
 .../.svn/text-base/angular-scenario.js.svn-base | 26195 +++++++++++++++++
 .../angular/.svn/text-base/version.txt.svn-base |     1 +
 src/main/ui/test/lib/angular/angular-mocks.js   |  1764 ++
 .../ui/test/lib/angular/angular-scenario.js     | 26195 +++++++++++++++++
 src/main/ui/test/lib/angular/version.txt        |     1 +
 src/main/ui/test/unit/.svn/all-wcprops          |    29 +
 src/main/ui/test/unit/.svn/entries              |   164 +
 .../.svn/prop-base/controllersSpec.js.svn-base  |     5 +
 .../.svn/prop-base/directivesSpec.js.svn-base   |     5 +
 .../unit/.svn/prop-base/filtersSpec.js.svn-base |     5 +
 .../.svn/prop-base/servicesSpec.js.svn-base     |     5 +
 .../.svn/text-base/controllersSpec.js.svn-base  |    44 +
 .../.svn/text-base/directivesSpec.js.svn-base   |    36 +
 .../unit/.svn/text-base/filtersSpec.js.svn-base |    22 +
 .../.svn/text-base/servicesSpec.js.svn-base     |    17 +
 src/main/ui/test/unit/controllersSpec.js        |    44 +
 src/main/ui/test/unit/directivesSpec.js         |    36 +
 src/main/ui/test/unit/filtersSpec.js            |    22 +
 src/main/ui/test/unit/servicesSpec.js           |    17 +
 src/main/vm/.svn/all-wcprops                    |     5 +
 src/main/vm/.svn/entries                        |    34 +
 src/main/vm/build/.svn/all-wcprops              |    11 +
 src/main/vm/build/.svn/entries                  |    62 +
 .../build/.svn/text-base/Vagrantfile.svn-base   |   110 +
 src/main/vm/build/Vagrantfile                   |   110 +
 src/main/vm/src/.svn/all-wcprops                |     5 +
 src/main/vm/src/.svn/entries                    |    34 +
 src/main/vm/src/cookbooks/.svn/all-wcprops      |     5 +
 src/main/vm/src/cookbooks/.svn/entries          |    43 +
 .../vm/src/cookbooks/apache2/.svn/all-wcprops   |    23 +
 src/main/vm/src/cookbooks/apache2/.svn/entries  |   145 +
 .../apache2/.svn/text-base/README.rdoc.svn-base |    78 +
 .../.svn/text-base/metadata.json.svn-base       |   497 +
 .../apache2/.svn/text-base/metadata.rb.svn-base |   197 +
 src/main/vm/src/cookbooks/apache2/README.rdoc   |    78 +
 .../apache2/attributes/.svn/all-wcprops         |    11 +
 .../cookbooks/apache2/attributes/.svn/entries   |    62 +
 .../.svn/text-base/default.rb.svn-base          |    77 +
 .../src/cookbooks/apache2/attributes/default.rb |    77 +
 .../apache2/definitions/.svn/all-wcprops        |    29 +
 .../cookbooks/apache2/definitions/.svn/entries  |   164 +
 .../.svn/text-base/apache_conf.rb.svn-base      |    25 +
 .../.svn/text-base/apache_module.rb.svn-base    |    43 +
 .../.svn/text-base/apache_site.rb.svn-base      |    40 +
 .../.svn/text-base/web_app.rb.svn-base          |    49 +
 .../apache2/definitions/apache_conf.rb          |    25 +
 .../apache2/definitions/apache_module.rb        |    43 +
 .../apache2/definitions/apache_site.rb          |    40 +
 .../cookbooks/apache2/definitions/web_app.rb    |    49 +
 .../cookbooks/apache2/files/.svn/all-wcprops    |     5 +
 .../vm/src/cookbooks/apache2/files/.svn/entries |    31 +
 .../apache2/files/default/.svn/all-wcprops      |    11 +
 .../apache2/files/default/.svn/entries          |    62 +
 .../apache2_module_conf_generate.pl.svn-base    |    41 +
 .../default/apache2_module_conf_generate.pl     |    41 +
 src/main/vm/src/cookbooks/apache2/metadata.json |   497 +
 src/main/vm/src/cookbooks/apache2/metadata.rb   |   197 +
 .../cookbooks/apache2/recipes/.svn/all-wcprops  |   233 +
 .../src/cookbooks/apache2/recipes/.svn/entries  |  1320 +
 .../recipes/.svn/text-base/default.rb.svn-base  |   191 +
 .../.svn/text-base/god_monitor.rb.svn-base      |    33 +
 .../.svn/text-base/mod_alias.rb.svn-base        |    22 +
 .../.svn/text-base/mod_auth_basic.rb.svn-base   |    20 +
 .../.svn/text-base/mod_auth_digest.rb.svn-base  |    20 +
 .../.svn/text-base/mod_auth_openid.rb.svn-base  |    59 +
 .../.svn/text-base/mod_authn_file.rb.svn-base   |    20 +
 .../.svn/text-base/mod_authnz_ldap.rb.svn-base  |    20 +
 .../text-base/mod_authz_default.rb.svn-base     |    20 +
 .../text-base/mod_authz_groupfile.rb.svn-base   |    20 +
 .../.svn/text-base/mod_authz_host.rb.svn-base   |    20 +
 .../.svn/text-base/mod_authz_user.rb.svn-base   |    20 +
 .../.svn/text-base/mod_autoindex.rb.svn-base    |    22 +
 .../recipes/.svn/text-base/mod_cgi.rb.svn-base  |    20 +
 .../recipes/.svn/text-base/mod_dav.rb.svn-base  |    20 +
 .../.svn/text-base/mod_dav_svn.rb.svn-base      |    22 +
 .../.svn/text-base/mod_deflate.rb.svn-base      |    22 +
 .../recipes/.svn/text-base/mod_dir.rb.svn-base  |    22 +
 .../recipes/.svn/text-base/mod_env.rb.svn-base  |    20 +
 .../.svn/text-base/mod_expires.rb.svn-base      |    20 +
 .../.svn/text-base/mod_fcgid.rb.svn-base        |    46 +
 .../.svn/text-base/mod_headers.rb.svn-base      |    20 +
 .../recipes/.svn/text-base/mod_ldap.rb.svn-base |    20 +
 .../.svn/text-base/mod_log_config.rb.svn-base   |    24 +
 .../recipes/.svn/text-base/mod_mime.rb.svn-base |    22 +
 .../.svn/text-base/mod_negotiation.rb.svn-base  |    22 +
 .../recipes/.svn/text-base/mod_php5.rb.svn-base |    32 +
 .../.svn/text-base/mod_proxy.rb.svn-base        |    22 +
 .../.svn/text-base/mod_proxy_ajp.rb.svn-base    |    20 +
 .../text-base/mod_proxy_balancer.rb.svn-base    |    20 +
 .../text-base/mod_proxy_connect.rb.svn-base     |    20 +
 .../.svn/text-base/mod_proxy_http.rb.svn-base   |    20 +
 .../.svn/text-base/mod_python.rb.svn-base       |    22 +
 .../.svn/text-base/mod_rewrite.rb.svn-base      |    20 +
 .../.svn/text-base/mod_setenvif.rb.svn-base     |    22 +
 .../recipes/.svn/text-base/mod_ssl.rb.svn-base  |    42 +
 .../.svn/text-base/mod_status.rb.svn-base       |    22 +
 .../recipes/.svn/text-base/mod_wsgi.rb.svn-base |    27 +
 .../vm/src/cookbooks/apache2/recipes/default.rb |   191 +
 .../cookbooks/apache2/recipes/god_monitor.rb    |    33 +
 .../src/cookbooks/apache2/recipes/mod_alias.rb  |    22 +
 .../cookbooks/apache2/recipes/mod_auth_basic.rb |    20 +
 .../apache2/recipes/mod_auth_digest.rb          |    20 +
 .../apache2/recipes/mod_auth_openid.rb          |    59 +
 .../cookbooks/apache2/recipes/mod_authn_file.rb |    20 +
 .../apache2/recipes/mod_authnz_ldap.rb          |    20 +
 .../apache2/recipes/mod_authz_default.rb        |    20 +
 .../apache2/recipes/mod_authz_groupfile.rb      |    20 +
 .../cookbooks/apache2/recipes/mod_authz_host.rb |    20 +
 .../cookbooks/apache2/recipes/mod_authz_user.rb |    20 +
 .../cookbooks/apache2/recipes/mod_autoindex.rb  |    22 +
 .../vm/src/cookbooks/apache2/recipes/mod_cgi.rb |    20 +
 .../vm/src/cookbooks/apache2/recipes/mod_dav.rb |    20 +
 .../cookbooks/apache2/recipes/mod_dav_svn.rb    |    22 +
 .../cookbooks/apache2/recipes/mod_deflate.rb    |    22 +
 .../vm/src/cookbooks/apache2/recipes/mod_dir.rb |    22 +
 .../vm/src/cookbooks/apache2/recipes/mod_env.rb |    20 +
 .../cookbooks/apache2/recipes/mod_expires.rb    |    20 +
 .../src/cookbooks/apache2/recipes/mod_fcgid.rb  |    46 +
 .../cookbooks/apache2/recipes/mod_headers.rb    |    20 +
 .../src/cookbooks/apache2/recipes/mod_ldap.rb   |    20 +
 .../cookbooks/apache2/recipes/mod_log_config.rb |    24 +
 .../src/cookbooks/apache2/recipes/mod_mime.rb   |    22 +
 .../apache2/recipes/mod_negotiation.rb          |    22 +
 .../src/cookbooks/apache2/recipes/mod_php5.rb   |    32 +
 .../src/cookbooks/apache2/recipes/mod_proxy.rb  |    22 +
 .../cookbooks/apache2/recipes/mod_proxy_ajp.rb  |    20 +
 .../apache2/recipes/mod_proxy_balancer.rb       |    20 +
 .../apache2/recipes/mod_proxy_connect.rb        |    20 +
 .../cookbooks/apache2/recipes/mod_proxy_http.rb |    20 +
 .../src/cookbooks/apache2/recipes/mod_python.rb |    22 +
 .../cookbooks/apache2/recipes/mod_rewrite.rb    |    20 +
 .../cookbooks/apache2/recipes/mod_setenvif.rb   |    22 +
 .../vm/src/cookbooks/apache2/recipes/mod_ssl.rb |    42 +
 .../src/cookbooks/apache2/recipes/mod_status.rb |    22 +
 .../src/cookbooks/apache2/recipes/mod_wsgi.rb   |    27 +
 .../apache2/templates/.svn/all-wcprops          |     5 +
 .../cookbooks/apache2/templates/.svn/entries    |    31 +
 .../apache2/templates/default/.svn/all-wcprops  |    83 +
 .../apache2/templates/default/.svn/entries      |   473 +
 .../.svn/text-base/a2dismod.erb.svn-base        |    22 +
 .../.svn/text-base/a2dissite.erb.svn-base       |    29 +
 .../default/.svn/text-base/a2enmod.erb.svn-base |    37 +
 .../.svn/text-base/a2ensite.erb.svn-base        |    38 +
 .../.svn/text-base/apache2.conf.erb.svn-base    |   230 +
 .../.svn/text-base/apache2.god.erb.svn-base     |    19 +
 .../default/.svn/text-base/charset.erb.svn-base |     6 +
 .../.svn/text-base/default-site.erb.svn-base    |    57 +
 .../text-base/mod_auth_openid.rb.erb.svn-base   |    12 +
 .../.svn/text-base/port_apache.erb.svn-base     |     2 +
 .../.svn/text-base/ports.conf.erb.svn-base      |     6 +
 .../.svn/text-base/security.erb.svn-base        |    50 +
 .../.svn/text-base/web_app.conf.erb.svn-base    |    43 +
 .../apache2/templates/default/a2dismod.erb      |    22 +
 .../apache2/templates/default/a2dissite.erb     |    29 +
 .../apache2/templates/default/a2enmod.erb       |    37 +
 .../apache2/templates/default/a2ensite.erb      |    38 +
 .../apache2/templates/default/apache2.conf.erb  |   230 +
 .../apache2/templates/default/apache2.god.erb   |    19 +
 .../apache2/templates/default/charset.erb       |     6 +
 .../apache2/templates/default/default-site.erb  |    57 +
 .../templates/default/mod_auth_openid.rb.erb    |    12 +
 .../templates/default/mods/.svn/all-wcprops     |    83 +
 .../apache2/templates/default/mods/.svn/entries |   470 +
 .../default/mods/.svn/text-base/README.svn-base |     2 +
 .../mods/.svn/text-base/alias.conf.erb.svn-base |    24 +
 .../.svn/text-base/authopenid.load.erb.svn-base |     1 +
 .../.svn/text-base/autoindex.conf.erb.svn-base  |   101 +
 .../.svn/text-base/deflate.conf.erb.svn-base    |    16 +
 .../mods/.svn/text-base/dir.conf.erb.svn-base   |     5 +
 .../mods/.svn/text-base/fcgid.conf.erb.svn-base |    10 +
 .../mods/.svn/text-base/mime.conf.erb.svn-base  |   191 +
 .../text-base/negotiation.conf.erb.svn-base     |    18 +
 .../mods/.svn/text-base/proxy.conf.erb.svn-base |    19 +
 .../.svn/text-base/setenvif.conf.erb.svn-base   |    28 +
 .../mods/.svn/text-base/ssl.conf.erb.svn-base   |    72 +
 .../.svn/text-base/status.conf.erb.svn-base     |    16 +
 .../apache2/templates/default/mods/README       |     2 +
 .../templates/default/mods/alias.conf.erb       |    24 +
 .../templates/default/mods/authopenid.load.erb  |     1 +
 .../templates/default/mods/autoindex.conf.erb   |   101 +
 .../templates/default/mods/deflate.conf.erb     |    16 +
 .../apache2/templates/default/mods/dir.conf.erb |     5 +
 .../templates/default/mods/fcgid.conf.erb       |    10 +
 .../templates/default/mods/mime.conf.erb        |   191 +
 .../templates/default/mods/negotiation.conf.erb |    18 +
 .../templates/default/mods/proxy.conf.erb       |    19 +
 .../templates/default/mods/setenvif.conf.erb    |    28 +
 .../apache2/templates/default/mods/ssl.conf.erb |    72 +
 .../templates/default/mods/status.conf.erb      |    16 +
 .../apache2/templates/default/port_apache.erb   |     2 +
 .../apache2/templates/default/ports.conf.erb    |     6 +
 .../apache2/templates/default/security.erb      |    50 +
 .../apache2/templates/default/web_app.conf.erb  |    43 +
 src/main/vm/src/cookbooks/apt/.svn/all-wcprops  |    17 +
 src/main/vm/src/cookbooks/apt/.svn/entries      |   102 +
 .../apt/.svn/text-base/metadata.json.svn-base   |    37 +
 .../apt/.svn/text-base/metadata.rb.svn-base     |    11 +
 .../vm/src/cookbooks/apt/files/.svn/all-wcprops |     5 +
 .../vm/src/cookbooks/apt/files/.svn/entries     |    31 +
 .../apt/files/default/.svn/all-wcprops          |    23 +
 .../cookbooks/apt/files/default/.svn/entries    |   130 +
 .../.svn/text-base/apt-cacher.conf.svn-base     |   144 +
 .../default/.svn/text-base/apt-cacher.svn-base  |     9 +
 .../.svn/text-base/apt-proxy-v2.conf.svn-base   |    50 +
 .../src/cookbooks/apt/files/default/apt-cacher  |     9 +
 .../cookbooks/apt/files/default/apt-cacher.conf |   144 +
 .../apt/files/default/apt-proxy-v2.conf         |    50 +
 src/main/vm/src/cookbooks/apt/metadata.json     |    37 +
 src/main/vm/src/cookbooks/apt/metadata.rb       |    11 +
 .../src/cookbooks/apt/recipes/.svn/all-wcprops  |    23 +
 .../vm/src/cookbooks/apt/recipes/.svn/entries   |   130 +
 .../recipes/.svn/text-base/cacher.rb.svn-base   |    42 +
 .../recipes/.svn/text-base/default.rb.svn-base  |    33 +
 .../recipes/.svn/text-base/proxy.rb.svn-base    |    34 +
 src/main/vm/src/cookbooks/apt/recipes/cacher.rb |    42 +
 .../vm/src/cookbooks/apt/recipes/default.rb     |    33 +
 src/main/vm/src/cookbooks/apt/recipes/proxy.rb  |    34 +
 .../cookbooks/build-essential/.svn/all-wcprops  |    41 +
 .../src/cookbooks/build-essential/.svn/entries  |   238 +
 .../.svn/text-base/CHANGELOG.md.svn-base        |    15 +
 .../.svn/text-base/CONTRIBUTING.svn-base        |    29 +
 .../.svn/text-base/LICENSE.svn-base             |   201 +
 .../.svn/text-base/README.md.svn-base           |   124 +
 .../.svn/text-base/metadata.json.svn-base       |    37 +
 .../.svn/text-base/metadata.rb.svn-base         |    12 +
 .../src/cookbooks/build-essential/CHANGELOG.md  |    15 +
 .../src/cookbooks/build-essential/CONTRIBUTING  |    29 +
 .../vm/src/cookbooks/build-essential/LICENSE    |   201 +
 .../vm/src/cookbooks/build-essential/README.md  |   124 +
 .../build-essential/attributes/.svn/all-wcprops |    11 +
 .../build-essential/attributes/.svn/entries     |    62 +
 .../.svn/text-base/default.rb.svn-base          |    33 +
 .../build-essential/attributes/default.rb       |    33 +
 .../src/cookbooks/build-essential/metadata.json |    37 +
 .../src/cookbooks/build-essential/metadata.rb   |    12 +
 .../build-essential/recipes/.svn/all-wcprops    |    11 +
 .../build-essential/recipes/.svn/entries        |    62 +
 .../recipes/.svn/text-base/default.rb.svn-base  |    79 +
 .../build-essential/recipes/default.rb          |    79 +
 .../vm/src/cookbooks/python/.svn/all-wcprops    |    41 +
 src/main/vm/src/cookbooks/python/.svn/entries   |   244 +
 .../python/.svn/text-base/CHANGELOG.md.svn-base |    21 +
 .../python/.svn/text-base/CONTRIBUTING.svn-base |    29 +
 .../python/.svn/text-base/LICENSE.svn-base      |   201 +
 .../python/.svn/text-base/README.md.svn-base    |   176 +
 .../.svn/text-base/metadata.json.svn-base       |    42 +
 .../python/.svn/text-base/metadata.rb.svn-base  |    18 +
 src/main/vm/src/cookbooks/python/CHANGELOG.md   |    21 +
 src/main/vm/src/cookbooks/python/CONTRIBUTING   |    29 +
 src/main/vm/src/cookbooks/python/LICENSE        |   201 +
 src/main/vm/src/cookbooks/python/README.md      |   176 +
 .../python/attributes/.svn/all-wcprops          |    11 +
 .../cookbooks/python/attributes/.svn/entries    |    62 +
 .../.svn/text-base/default.rb.svn-base          |    42 +
 .../src/cookbooks/python/attributes/default.rb  |    42 +
 src/main/vm/src/cookbooks/python/metadata.json  |    42 +
 src/main/vm/src/cookbooks/python/metadata.rb    |    18 +
 .../cookbooks/python/providers/.svn/all-wcprops |    17 +
 .../src/cookbooks/python/providers/.svn/entries |    96 +
 .../providers/.svn/text-base/pip.rb.svn-base    |   167 +
 .../.svn/text-base/virtualenv.rb.svn-base       |    68 +
 .../vm/src/cookbooks/python/providers/pip.rb    |   167 +
 .../cookbooks/python/providers/virtualenv.rb    |    68 +
 .../cookbooks/python/recipes/.svn/all-wcprops   |    35 +
 .../src/cookbooks/python/recipes/.svn/entries   |   198 +
 .../recipes/.svn/text-base/default.rb.svn-base  |    23 +
 .../recipes/.svn/text-base/package.rb.svn-base  |    58 +
 .../recipes/.svn/text-base/pip.rb.svn-base      |    41 +
 .../recipes/.svn/text-base/source.rb.svn-base   |    52 +
 .../.svn/text-base/virtualenv.rb.svn-base       |    25 +
 .../vm/src/cookbooks/python/recipes/default.rb  |    23 +
 .../vm/src/cookbooks/python/recipes/package.rb  |    58 +
 src/main/vm/src/cookbooks/python/recipes/pip.rb |    41 +
 .../vm/src/cookbooks/python/recipes/source.rb   |    52 +
 .../src/cookbooks/python/recipes/virtualenv.rb  |    25 +
 .../cookbooks/python/resources/.svn/all-wcprops |    17 +
 .../src/cookbooks/python/resources/.svn/entries |    96 +
 .../resources/.svn/text-base/pip.rb.svn-base    |    27 +
 .../.svn/text-base/virtualenv.rb.svn-base       |    27 +
 .../vm/src/cookbooks/python/resources/pip.rb    |    27 +
 .../cookbooks/python/resources/virtualenv.rb    |    27 +
 .../src/cookbooks/vagrant_main/.svn/all-wcprops |     5 +
 .../vm/src/cookbooks/vagrant_main/.svn/entries  |    34 +
 .../vagrant_main/recipes/.svn/all-wcprops       |    11 +
 .../cookbooks/vagrant_main/recipes/.svn/entries |    62 +
 .../recipes/.svn/text-base/default.rb.svn-base  |    56 +
 .../cookbooks/vagrant_main/recipes/default.rb   |    56 +
 .../vagrant_main/templates/.svn/all-wcprops     |     5 +
 .../vagrant_main/templates/.svn/entries         |    31 +
 .../templates/default/.svn/all-wcprops          |    17 +
 .../vagrant_main/templates/default/.svn/entries |    96 +
 .../.svn/text-base/project.conf.erb.svn-base    |     3 +
 .../.svn/text-base/rcmet.conf.erb.svn-base      |     3 +
 .../templates/default/project.conf.erb          |     3 +
 .../templates/default/rcmet.conf.erb            |     3 +
 src/main/vm/src/scripts/.svn/all-wcprops        |     5 +
 src/main/vm/src/scripts/.svn/entries            |    31 +
 src/main/vm/src/scripts/ncl/.svn/all-wcprops    |    11 +
 src/main/vm/src/scripts/ncl/.svn/entries        |    62 +
 .../.svn/text-base/wget-download.sh.svn-base    |   263 +
 src/main/vm/src/scripts/ncl/wget-download.sh    |   263 +
 src/main/webapp/.htaccess                       |    45 +
 src/main/webapp/.svn/all-wcprops                |    29 +
 src/main/webapp/.svn/entries                    |   179 +
 .../webapp/.svn/text-base/.htaccess.svn-base    |    45 +
 .../webapp/.svn/text-base/config.ini.svn-base   |    66 +
 .../webapp/.svn/text-base/hooks.php.svn-base    |    83 +
 .../webapp/.svn/text-base/index.php.svn-base    |    48 +
 src/main/webapp/classes/.svn/all-wcprops        |    17 +
 src/main/webapp/classes/.svn/entries            |    96 +
 .../RCMETWizardTask.class.php.svn-base          |   125 +
 .../text-base/WizardTask.class.php.svn-base     |    55 +
 .../webapp/classes/RCMETWizardTask.class.php    |   125 +
 src/main/webapp/classes/WizardTask.class.php    |    55 +
 src/main/webapp/config.ini                      |    66 +
 src/main/webapp/hooks.php                       |    83 +
 src/main/webapp/index.php                       |    48 +
 src/main/webapp/modules/.svn/all-wcprops        |     5 +
 src/main/webapp/modules/.svn/entries            |    28 +
 src/main/webapp/scripts/.svn/all-wcprops        |    29 +
 src/main/webapp/scripts/.svn/entries            |   167 +
 .../scripts/.svn/text-base/dirlist.php.svn-base |    25 +
 .../.svn/text-base/plotView.php.svn-base        |    13 +
 .../scripts/.svn/text-base/plots.php.svn-base   |    35 +
 .../scripts/.svn/text-base/rcmed.php.svn-base   |    23 +
 src/main/webapp/scripts/dirlist.php             |    25 +
 src/main/webapp/scripts/plotView.php            |    13 +
 src/main/webapp/scripts/plots.php               |    35 +
 src/main/webapp/scripts/rcmed.php               |    23 +
 .../webapp/scripts/widgets/.svn/all-wcprops     |     5 +
 src/main/webapp/scripts/widgets/.svn/entries    |    28 +
 src/main/webapp/static/.svn/all-wcprops         |     5 +
 src/main/webapp/static/.svn/entries             |    40 +
 .../webapp/static/bootstrap/.svn/all-wcprops    |     5 +
 src/main/webapp/static/bootstrap/.svn/entries   |    37 +
 .../static/bootstrap/css/.svn/all-wcprops       |    29 +
 .../webapp/static/bootstrap/css/.svn/entries    |   164 +
 .../text-base/bootstrap-responsive.css.svn-base |  1040 +
 .../bootstrap-responsive.min.css.svn-base       |     9 +
 .../css/.svn/text-base/bootstrap.css.svn-base   |  5624 ++++
 .../.svn/text-base/bootstrap.min.css.svn-base   |     9 +
 .../bootstrap/css/bootstrap-responsive.css      |  1040 +
 .../bootstrap/css/bootstrap-responsive.min.css  |     9 +
 .../webapp/static/bootstrap/css/bootstrap.css   |  5624 ++++
 .../static/bootstrap/css/bootstrap.min.css      |     9 +
 .../static/bootstrap/img/.svn/all-wcprops       |    17 +
 .../webapp/static/bootstrap/img/.svn/entries    |    96 +
 .../glyphicons-halflings-white.png.svn-base     |     5 +
 .../prop-base/glyphicons-halflings.png.svn-base |     5 +
 .../glyphicons-halflings-white.png.svn-base     |   Bin 0 -> 8777 bytes
 .../text-base/glyphicons-halflings.png.svn-base |   Bin 0 -> 12799 bytes
 .../img/glyphicons-halflings-white.png          |   Bin 0 -> 8777 bytes
 .../bootstrap/img/glyphicons-halflings.png      |   Bin 0 -> 12799 bytes
 .../webapp/static/bootstrap/js/.svn/all-wcprops |    17 +
 .../webapp/static/bootstrap/js/.svn/entries     |    96 +
 .../js/.svn/text-base/bootstrap.js.svn-base     |  2027 ++
 .../js/.svn/text-base/bootstrap.min.js.svn-base |     6 +
 .../webapp/static/bootstrap/js/bootstrap.js     |  2027 ++
 .../webapp/static/bootstrap/js/bootstrap.min.js |     6 +
 src/main/webapp/static/css/.svn/all-wcprops     |    23 +
 src/main/webapp/static/css/.svn/entries         |   136 +
 .../jquery-ui-1.7.1.custom.css.svn-base         |   404 +
 .../static/css/.svn/text-base/site.css.svn-base |    19 +
 .../css/.svn/text-base/style.css.svn-base       |   102 +
 .../webapp/static/css/balance/.svn/all-wcprops  |    11 +
 src/main/webapp/static/css/balance/.svn/entries |    62 +
 .../balance/.svn/text-base/balance.css.svn-base |    16 +
 src/main/webapp/static/css/balance/balance.css  |    16 +
 .../static/css/blueprint/.svn/all-wcprops       |    29 +
 .../webapp/static/css/blueprint/.svn/entries    |   164 +
 .../blueprint/.svn/text-base/LICENSE.svn-base   |    22 +
 .../blueprint/.svn/text-base/ie.css.svn-base    |    29 +
 .../blueprint/.svn/text-base/print.css.svn-base |    23 +
 .../.svn/text-base/screen.css.svn-base          |   252 +
 src/main/webapp/static/css/blueprint/LICENSE    |    22 +
 src/main/webapp/static/css/blueprint/ie.css     |    29 +
 src/main/webapp/static/css/blueprint/print.css  |    23 +
 src/main/webapp/static/css/blueprint/screen.css |   252 +
 .../static/css/jquery-ui-1.7.1.custom.css       |   404 +
 src/main/webapp/static/css/site.css             |    19 +
 src/main/webapp/static/css/style.css            |   102 +
 src/main/webapp/static/img/.svn/all-wcprops     |    23 +
 src/main/webapp/static/img/.svn/entries         |   130 +
 .../img/.svn/prop-base/hexabump-bg.png.svn-base |     5 +
 .../img/.svn/prop-base/rcmes-logo.png.svn-base  |     5 +
 .../img/.svn/prop-base/wrm-badge.png.svn-base   |     5 +
 .../img/.svn/text-base/hexabump-bg.png.svn-base |   Bin 0 -> 218 bytes
 .../img/.svn/text-base/rcmes-logo.png.svn-base  |   Bin 0 -> 36578 bytes
 .../img/.svn/text-base/wrm-badge.png.svn-base   |   Bin 0 -> 36578 bytes
 src/main/webapp/static/img/hexabump-bg.png      |   Bin 0 -> 218 bytes
 src/main/webapp/static/img/rcmes-logo.png       |   Bin 0 -> 36578 bytes
 src/main/webapp/static/img/wrm-badge.png        |   Bin 0 -> 36578 bytes
 src/main/webapp/static/js/.svn/all-wcprops      |    23 +
 src/main/webapp/static/js/.svn/entries          |   130 +
 .../.svn/text-base/jquery-1.4.2.min.js.svn-base |   154 +
 .../.svn/text-base/jquery-1.8.0.min.js.svn-base |     2 +
 .../jquery-ui-1.7.1.custom.min.js.svn-base      |   298 +
 src/main/webapp/static/js/jquery-1.4.2.min.js   |   154 +
 src/main/webapp/static/js/jquery-1.8.0.min.js   |     2 +
 .../static/js/jquery-ui-1.7.1.custom.min.js     |   298 +
 src/main/webapp/views/.svn/all-wcprops          |    11 +
 src/main/webapp/views/.svn/entries              |    71 +
 .../views/.svn/text-base/index.php.svn-base     |    42 +
 src/main/webapp/views/common/.svn/all-wcprops   |    17 +
 src/main/webapp/views/common/.svn/entries       |    96 +
 .../common/.svn/text-base/footer.php.svn-base   |    17 +
 .../common/.svn/text-base/header.php.svn-base   |    35 +
 src/main/webapp/views/common/footer.php         |    17 +
 src/main/webapp/views/common/header.php         |    35 +
 src/main/webapp/views/errors/.svn/all-wcprops   |    11 +
 src/main/webapp/views/errors/.svn/entries       |    62 +
 .../errors/.svn/text-base/404.php.svn-base      |     5 +
 src/main/webapp/views/errors/404.php            |     5 +
 src/main/webapp/views/index.php                 |    42 +
 src/main/webapp/views/wizard/.svn/all-wcprops   |    23 +
 src/main/webapp/views/wizard/.svn/entries       |   133 +
 .../wizard/.svn/text-base/help.php.svn-base     |    17 +
 .../wizard/.svn/text-base/init.php.svn-base     |    32 +
 .../wizard/.svn/text-base/step.php.svn-base     |    26 +
 src/main/webapp/views/wizard/help.php           |    17 +
 src/main/webapp/views/wizard/init.php           |    32 +
 src/main/webapp/views/wizard/step.php           |    26 +
 .../webapp/views/wizard/steps/.svn/all-wcprops  |    71 +
 src/main/webapp/views/wizard/steps/.svn/entries |   402 +
 .../.svn/text-base/generatePlots.php.svn-base   |   125 +
 .../text-base/selectLatLonVars.php.svn-base     |    63 +
 .../text-base/selectMetricOptions.php.svn-base  |    49 +
 .../text-base/selectModelFiles.php.svn-base     |    75 +
 .../.svn/text-base/selectModelVar.php.svn-base  |    53 +
 .../selectObservationalData.php.svn-base        |    86 +
 .../text-base/selectOptionalTasks.php.svn-base  |    45 +
 .../text-base/selectPlotOptions.php.svn-base    |    42 +
 .../.svn/text-base/selectRegrid.php.svn-base    |    58 +
 .../.svn/text-base/selectTimeRange.php.svn-base |    83 +
 .../.svn/text-base/selectTimeVars.php.svn-base  |    52 +
 .../webapp/views/wizard/steps/generatePlots.php |   125 +
 .../views/wizard/steps/selectLatLonVars.php     |    63 +
 .../views/wizard/steps/selectMetricOptions.php  |    49 +
 .../views/wizard/steps/selectModelFiles.php     |    75 +
 .../views/wizard/steps/selectModelVar.php       |    53 +
 .../wizard/steps/selectObservationalData.php    |    86 +
 .../views/wizard/steps/selectOptionalTasks.php  |    45 +
 .../views/wizard/steps/selectPlotOptions.php    |    42 +
 .../webapp/views/wizard/steps/selectRegrid.php  |    58 +
 .../views/wizard/steps/selectTimeRange.php      |    83 +
 .../views/wizard/steps/selectTimeVars.php       |    52 +
 800 files changed, 170559 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/LICENSE.txt
----------------------------------------------------------------------
diff --git a/LICENSE.txt b/LICENSE.txt
new file mode 100755
index 0000000..d645695
--- /dev/null
+++ b/LICENSE.txt
@@ -0,0 +1,202 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/readme_v2.1.3
----------------------------------------------------------------------
diff --git a/readme_v2.1.3 b/readme_v2.1.3
new file mode 100755
index 0000000..9b46ee7
--- /dev/null
+++ b/readme_v2.1.3
@@ -0,0 +1,278 @@
+=====================================================================================================================================
+++++++++++++++++++++++++++++++++++++++++++++++++++ Configure file for running RCMES +++++++++++++++++++++++++++++++++++++++++++++++++
+=====================================================================================================================================
+# An example of the configuration file to run RCMES version 2.1.2
+[SETTINGS]
+# Assign the work (workDir) and cache (cacheDir) directories for this run.
+#   The work directory stores the results including the interpolated obs and model data and figures. Please make sure to save
+#     these files in different names before making a new run. Existing files that are not renamed are overwritten by the new run.
+#   The cashe directory stoes the refrence data file retrieved from the database (i.e., RCMED) for later use. If the same domain/period
+#     are run repeatedly, data retrieval from RCMED occurs only in the first run and the subsequent runs utilize the data stored in
+#     the cache directory.
+workDir=/Volumes/rcmes2t/rcmet/cases/narccap/work
+cacheDir=/Volumes/rcmes2t/rcmet/cases/narccap/cache
+
+# temporalGrid assigns the data time step to be temporally regridded: Choices = full (entire period), annual, monthly, daily
+temporalGrid=monthly
+# Choices, obs, model, user
+#   gridLonStep, gridLatStep, latMin, latMax, lonMin, lonMax are used only with 'user' spatial grid option
+#   Selecting either 'obs' or 'model' will utilize the grid structure of the observational or model data, respectively,
+#     in the subsequent anlaysis/evaluation.
+#   Using the 'user' option is recommended due to the following reasons:
+#     (1) 'obs' may be useful for only a single reference data case. Multiple obs data usually come in different grid systems;
+#         there is no provision to handle such a case.
+#     (2) It was observed that different model data files prepared for the same grid nest often has different long,lat values,
+#         perhaps because of truncations in different systems.
+spatialGrid=user
+gridLonStep=0.5
+gridLatStep=0.5
+latMin=23.75            ; for NARCCAP-ConterminousUS / WUS
+latMax=49.75            ; for NARCCAP-ConterminousUS / WUS
+lonMin=-125.75          ; for NARCCAP-ConterminousUS / WUS
+lonMax=-66.75           ; for NARCCAP-Conterminous US
+#lonMax=-100.75          ; for NARCCAP-WUS.
+# Choices: False, NetCDF
+outputFile=NetCDF
+
+[MODEL]
+# The model data file(s) to be evaluated is(are) assinged here. Note that the current convention is for easy handling of
+#   multiple model datasets from coordinated experiments such as CORDEX that tend to assign a data file with a name that
+#   follows pre-determined convention (a combination of model name, institution, variable name, experiment name, etc.).
+#   In case only one model is evaluated, a user can specify the full file name for 'filenamePattern'
+# variableType (reference units): 'precipitation' (mm/day); 'temperature' (K); 'cloudiness' (%); 'radiation' (W/m^2);
+#                                 'evaporation' (mm/day); 'runoff' (mm/day); 'SMC' (fraction)'; 'SWE' (mm); heatFlux (W/m^2)
+#filenamePattern = none           # option currently not working; 2b added for obs-only processing
+filenamePattern=/Volumes/rcmes2t/rcmet/cases/narccap/mdlData/mon/prec*.nc
+latVariable=lat
+lonVariable=lon
+timeVariable=time
+varName=prec
+#precipFlag=True ; This is just used to support an unknown UNITS in precip data
+variableType='precipitation'
+
+[RCMED]
+# obsParamId designates the reference data file. see http://rcmes.jpl.nasa.gov/rcmed/parameters
+# for multiple ref datasets, provide the id separated by ',' (e.g., 36,37 for TRMM and CRU3.1).
+# obsSource specifies the source of the reference data: 0 = RCMED, 1 = user's local disk, -9 = no obs data
+#   For obsSource == 1, obsInputFile, the file that provides the list of users' own reference data
+obsSource = 0
+obsInputFile = /nas/share1-hp/jinwonki/data/rean/narr/day_narccap_domain/NARR_prec.nc,/nas/share1-hp/jinwonki/data/obs/cpc/netcdf/cpc_1979_present.nc
+obsVarName = pr,pr
+obsFileName = NARR,CPC
+obsDltaTime = daily,daily
+obsTimeVar = time,time
+obsLonVar = lon,longitude
+obsLatVar = lat,latitude
+# if obsSource = 0, the lines from 'obsSource' to 'obsLatVar' above are inactive
+#obsParamId=37,72,81,36,74
+obsParamId=37
+obsTimeStep=monthly,monthly,monthly,monthly,monthly ; WITH THE PARAMETER SERVICE THIS WILL GO AWAY
+
+[SUB_REGION]
+# Sub Region(s) Full File Path
+# Blak line will result in no region-specific analyses/evaluation (e.g., annual cycle for the Pacific Northwest region).
+subRegionFile=/Volumes/rcmes2t/rcmet/cases/narccap/work/inputs/subRgnsNARCCAP.US
+
+=====================================================================================================================================
++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Evaluation metrics ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+=====================================================================================================================================
+(1) Domain-wide metrics
+ ID   Metric
+[0]   Bias: mean bias over the full time range
+            METRIC(i,j) = M(i,j) - O(i,j), wehre M and O are the time mean of the model and obs data, respectively.
+[1]   Mean absolute error over the full time range
+            METRIC(i,j) = AVG[abs( m(i,j,t) - o(i,j,t) )]
+[2]   Temporal anomaly correlation: Eval local interannual variability
+            METRIC(i,j) = CORR[ ( m(i,j,t)-O(i,j) ), ( o(i,j,t)-O(i,j)) ]
+[3]   Temporal correlation: Eval localinterannual variability
+            METRIC(i,j) = CORR[ m(i,j,t), o(i,j,t) ]
+[5]   Spatial correlation between the REF and model climatology: a single correlation coeff
+            METRIC(model) = CORR[ O(i,j), M(i,j)]
+[6]   RMSE in time over the entire time step values: Eval local interannual variability
+            METRIC(i,j) = RMSE[ m(i,j,t), o(i,j,t) ]
+[7]   RMSE between the REF and model climatology: a single correlation coeff
+            METRIC(model) = RMSE[ M(i,j,), O(i,j,) ]_model
+[8]   Taylor diagram for spatial variability
+            Plot standardized deviation and correlations using a Taylor diagram
+[10]  Signal-to-noise ratio
+             METRIC(i,j)_model-or-obs = ENSEMBLE(i,j)_model-or-obs/Sigma(i,j)_model-or-obs
+
+(2) Time series for subregions
+RMSE and CORRELATION between the model and obs annual cycle using portrait diagrams and x-y plots.
+
+===================================================================================================================
+++++++++++++++++++++++++++++++++++++++  RCMES code modification history  ++++++++++++++++++++++++++++++++++++++++++
+===================================================================================================================
+5/28/2013
+Updates to /nas/share3-wf/jinwonki/rcmet/rcmet2.1/src/main/python/rcmes/storage/db.py by Cam has been implemented.
+7/06/2013
+Updated to version 2.1 with the feature to read reference data from users' own data files.
+This code has been tested with daily precipitation data (both model and reference) for the NARCCAP domain
+NOTE: * This version still have problem in regridding daily data into monthly - most likely due to the memory management problem.
+          Will be fixed in the next modification for generalized handling of both reference and model datasets.
+
+-----------    History of code modification    ----------------
+
+Log for the creation of rcmet2.1 from rcmet version latest on 5/28/2013
+
+(001) Modification: Implement an option to read reference data from users' local disk.
+  * Add entries into the configuration file (e.g.,resources/cordexAF.cfg):
+        obsSource, obsInputFile, obsFileName, obsLonVar, obsLatVar, obsTimeVar, obsDltaTime
+
+  * Modify 'rcmet.runUsingConfig' to read extra config parameters 'obsSource' (source indicator), 'obsInputfile'
+        (user-provided reference data file name), 'obsVarName' (the name of obs variable in the obs data file), 
+        'obsFileName' (data file identifier), 'obsTimeVar' (name of the time variable in the obs data file),
+        'obsLonVar' and 'obsLatVar' (the names indicating longitude and latititude variables in the obs data file), and
+        'obsDltaTime' (time step increment of the observed data). All these fields are read in from meta data if the reference
+        data are read from RCMED.
+        - create additional parameters & lists to be passed into do_data_prep.prep_data: obsSource,obsList,obsTimestep
+        - create obsDatasetList according to the specified reference data source
+        - pass 'obsSource' into misc.userDefinedStartEndTimes(obsSource,obsDatasetList,models)
+        - pass additional arguments into do_data_prep.prep_data \
+            (jobProperties,obsSource,obsDatasetList,obsList,obsVarName,obsLonName,obsLatName,obsTimeName,obsTimestep,gridBox,models)
+          note: arguments "obsSource, obsList, obsVarName, obsLonName, obsLatName, obsTimeName, obsTimestep" may be passed via "jobProperties"
+
+  * Modify 'utils.misc.py'
+        - add 'import toolkit.process'
+        - modify 'userDefinedStartEndTimes' so that the observational inputs from RCMED and user's own files can be handled separately.
+
+  * Modify 'do_data_prep'
+        - Additional arguments from the calling routine (see the modification to 'rcmet.runUsingConfig' above)
+        - 'obsSource' is used throughout 'do_data_prep' to indicate the source of reference data. Follow this index to identify
+          the features specific to the source of reference data (RCMED or users' own file(s))
+        - All user-provided ref data must be netCDF files. This is hardwired before the loop in which the ref data files are read & regridded.
+        - User-provided data files are read in using the same routine that is used to read model data files.
+        - Extraction of the reference data for the user-specified is done in the same way as for the model data.
+        - BUG! In the current code, 'mdlList' is updated to store model ensemble (ENS-MDL). This is WRONG. Update 'mdlName' instead of 'mdlList'
+
+  * Modify 'metrics.metrics_plots'
+        - If 'maskLonMin' or 'maskLonMax' exceeds 180, subtract 360 to be consistent with defauls longitude order (from -180 to 180)
+
+(002) Combined handling of the reference and model data in metrics calculations
+  * Modify 'rcmet.runUsingConfig' to combine the reference and model data
+        - Cosmetic: 'obsList' in the line to receive the names of the reference datasets in the 'do_data_prep.prep_data' string has been replaced with
+                    'obsName' for a better consistency with 'mdlName' in the same string that are used to store the names of the model datasets
+        - import numpy and numpy.ma
+        - Pack the data in the order: All reference data sets + Ref ensemble (if any) + all model datasets + model ensemble (if any)
+        - New vars introduced for handling the combined variable:
+          ^ numDatasets = numOBS + numMDL is the tot no. of datasets of the combined ref and mdl data including the ref and mdl ens, if exist.
+          ^ dataName = obsName + mdlName contains the names of all reference and model datasets
+          ^ allData = obsData[for 0:numOBS] + mdlData[for numOBS:numDatasets]
+        -  Modify the line to call 'metrics.metrics_plots' to pass the combined variable and related parameters:
+          ^ OLD: metrics.metrics_plots(modelVarName,numOBS,numMDL,nT,ngrdY,ngrdX,Times,lons,lats,obsData,mdlData,obsList,mdlName,workdir,subRegions,fileOutputOption)
+            NEW: metrics.metrics_plots(modelVarName,numOBS,numMDL,nT,ngrdY,ngrdX,Times,lons,lats,allData,dataName,workdir,subRegions,fileOutputOption)
+
+  * Modify metrics.py
+        - Note that the changes to handle multiple data evaluation makes all metrics to be either 3-d or 4-d (monthly) fields. Modify
+               'elif metricDat.ndim == 2' with 'elif metricDat.ndim == 3' and 'elif metricDat.ndim == 4'
+        - import additional libraries
+          ^ import matplotlib
+          ^ import matplotlib.dates
+          ^ import matplotlib.pyplot as plt
+          ^ from matplotlib.font_manager import FontProperties
+          ^ from utils.Taylor import TaylorDiagram
+        - Modify the argument list for 'calling metrics_plots' to be consistent with the changes in 'rcmet.runUsingConfig'
+        - Modify the line to call 'files.writeNCfile' --> 'files.writeNCfile1'.
+        - Modify the (mp.004) Select the model/obs data for evaluation.
+          Also use modified 'misc.select_data_combined' in the place of 'misc.select_data'
+        - Modify the calculation of obs and model time series & climatology to accommodate the evaluation of multiple model datasets (mp.005)
+        - Modify calc_pat_cor in such as way that the correlation can be calculated for both 1d vs 1d, 2d vs 2d and 3d vs 3d cases
+        - Modify calc_spatial_pat_cor to ensure that std dev and corrln are calculated over the same set of unmasked (i.e., good) data
+          (a) first find masks for both variables
+          (b) re-define the input data in such a way that the data at the location of the masked values in either var are masked.
+        - Make sure to use masked array whenever calculations are performed over the domain
+        - 2-d contour plotting
+          todo: the current multi-frame plot routine (drawCntrMap) must be replaced with a matlab-based routine (remove Ngl dependence)
+        - x-y plot routine has been updated
+          can select axis options between 'log' and 'linear'
+        - Procedure to calculate & plot portrait diagrams for the anaual cycle of multiple obs and/or multiple models in multiple subregions.
+
+  * Bug fix:
+        - calc_clim_mo in metrics.py
+            replace 'mm = months[t]' with 'mm = months[t] - 1' (otherwise mm=12 is out of bound)
+        - calc_spatial_anom_cor
+            replace the string 'd1 = ((oD - mo)*(oD - mo)).sum()' --> 'd2 = ((oD - mo)*(oD - mo)).sum()'
+
+  * Modify storage/files.py
+        - Create 'files.writeNCfile1' in'storage/files.py' with the argument list consistent with the combined datasets handling.
+        - Create 'files.loadDataIntoNetCDF1' for handling the unified datasets.
+
+  * Modify misc.select_metrics
+        - Add an option to draw a Taylor diagram
+
+  * Modify utils/misc.py
+        - Add a new routine 'reshapeMonthlyData' introduced by Alex Goodman
+
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++  7/11/2013:                                                                                         +
++  This version modifies the release version rcmet2.1 with features specific for the cordex-sa study  +
++  Need to implement the changes in the hydro version                                                 +
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+  * Add options to enter any combinations of data for evaluation
+      - modify metrics.py in the data selection block [e.g., refID = int(misc.select_data_combined(numDatasets, Times, dataList, 'ref'))]
+      - modify misc.select_data_combined
+  * New inpterpolation scheme "scipy.interpolate.griddata" replaces old "process.do_regrid".
+      - Inputs (x and y coordinates, data values) can be either regular grid on irregular grid.
+        Must specify masked values as "np.nan" to properly handle missing data.
+
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++  8/21/2013:                                                                                         +
++  Changes in data retrieval and model data reading (also applies to the reading of user-provided     +
++    observation data) in the latest release [08-21-2013] trunk version has been implemented.         +
++  Note: the changes below also modifies the sub-directory sturcture in the 'cache' directory.        +
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+  * Changes:
+    (1) replace db.py and files.py in storage/ with the updated ones.
+    (2) modify toolkit/do_data_prep.py:
+        'read_lolaT_from_file' has been removed and combined with 'read_data_from_one_file' in the new files.py
+
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++++++++++++++++++++++++++++  NOTE: RELEASE VERSION 2.1.2, 10/20/2013  ++++++++++++++++++++++++++++++
+++ ------------------------------------------------------------------------------------------------ ++
++  * Add:                                                                                            +
++  (1) Calculation of the coeff of variation, active only for inter-obs & inter-model comparisons    +
++  (2) PDF and quantile value calculations                                                           +
++  (3) Update the creation of output file to be consistent with the combined data structure          +
++  (4) Fix: All metrics calculations in the metrics calculation option now work properly.            +
++  (5) Writing the netCDF file of re-gridded data has been fixed to conform with the new data        +
++      structure (unified treatment of the REF and MDL variables in "allData")                       +
++  For more details of the updates, please refer to the work note above.                             +
++  * Known problems:                                                                                 +
++  (a) The code does not work if numMDL = 0 (i.e., model data must present all the time)             +
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+  * Changes:
+    (1) modify utils/misc.select_metrics to pass mdlSelect (CV and S2N applicaiton only to the all-obs or all-mdl)
+    (2) Related to (1), modify the string 'misc.select_metrics()' -> 'misc.select_metrics(mdlSelect)'
+    (3) Modify metrics.py to call writeNCfile1.
+        Also add "writeNCfile1" and "loadDataIntoNetCDF1" to "storage/files.py" to handle the combined data structure.
+        Note that the old routines "writeNCfile" and "loadDataIntoNetCDF" are now obsolete (inconsistent)
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++++++++++++++++++++++++++++  NOTE: RELEASE VERSION 2.1.3, 3/28/2014  +++++++++++++++++++++++++++++++
+*****************************           Crucial Release                *******************************
+++ ------------------------------------------------------------------------------------------------ ++
+  * Updates from the release version 2.1.2:
+  (1) increase the number of data to be plotted in pltXY in toolkit/metrics.py.
+  (2) handle wider variety of variable types by re-using precipFlag in the configure file.
+      purpose: The variable provisions in the version 2.1.2 are designed to handle precipitation data using "precipFlag".
+               As more variables are being processed, this procedure is expanded in the version 2.1.3 to handle more data
+               types including water fluxes, energy fluxes and the amount of water supstances.
+               See the [MODEL] section of the sample configure file in the beginning of this readme file.
+      (2.1) Modify the config file by removing "precipFlag" (boolean) and adding "variableType" (string)
+      (2.2) Modify "classes.py" - replace two lines in "class Model(object)" that are related with "precipFlag"
+            with the lines for handling "variableType".
+      (2.3) Modify "prep_data" in the module "do_data_prep.py"
+            (a) Replace "precipFlag" with "variableType" in converting the units of specific 
+                observation data (CRU3.1 precipitation) read from RCMED.
+            (b) Replace "precipFlag" with "variableType" in converting the units of specific 
+                observation data (CRU3.1 precipitation) read from users' own local files.
+            (c) Replace "precipFlag" with "variableType" in converting the model data units
+                (e.g., all water fluxes are in mm/day)
+  (3) plot frame arrangement is fixed in metrics.py for multiple plots in the same page
+      *** curical *** crucial *** crucial *** crucial *** crucial *** crucial *** crucial *** crucial ***
+  (4) updated to conform with the new RCMED access modules
+      NOTE: versions earlier than this code do not work.
+      (4.1) Replaced storage/rcmed.py with a new module.
+      (4.2) Modify rcmet.py
+            Line 194: db.get_params() --> db.get_parameters_metadata()
+            Line 217: param['parameter_id'] --> int(param['parameter_id'])
+**********  End of Release note for 2.1.3  ***  End of Release note for 2.1.3  ***************

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/.svn/all-wcprops
----------------------------------------------------------------------
diff --git a/src/.svn/all-wcprops b/src/.svn/all-wcprops
new file mode 100755
index 0000000..29436cf
--- /dev/null
+++ b/src/.svn/all-wcprops
@@ -0,0 +1,5 @@
+K 25
+svn:wc:ra_dav:version-url
+V 61
+/repos/asf/!svn/ver/1485875/incubator/climate/trunk/rcmet/src
+END

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/.svn/entries
----------------------------------------------------------------------
diff --git a/src/.svn/entries b/src/.svn/entries
new file mode 100755
index 0000000..31a0f09
--- /dev/null
+++ b/src/.svn/entries
@@ -0,0 +1,31 @@
+10
+
+dir
+1485921
+https://svn.apache.org/repos/asf/incubator/climate/trunk/rcmet/src
+https://svn.apache.org/repos/asf
+
+
+
+2013-05-23T22:20:38.670815Z
+1485875
+goodale
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+13f79535-47bb-0310-9956-ffa450edef68
+
+main
+dir
+

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/.svn/all-wcprops
----------------------------------------------------------------------
diff --git a/src/main/.svn/all-wcprops b/src/main/.svn/all-wcprops
new file mode 100755
index 0000000..028a7ed
--- /dev/null
+++ b/src/main/.svn/all-wcprops
@@ -0,0 +1,5 @@
+K 25
+svn:wc:ra_dav:version-url
+V 66
+/repos/asf/!svn/ver/1485875/incubator/climate/trunk/rcmet/src/main
+END

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/.svn/entries
----------------------------------------------------------------------
diff --git a/src/main/.svn/entries b/src/main/.svn/entries
new file mode 100755
index 0000000..ceff464
--- /dev/null
+++ b/src/main/.svn/entries
@@ -0,0 +1,43 @@
+10
+
+dir
+1485921
+https://svn.apache.org/repos/asf/incubator/climate/trunk/rcmet/src/main
+https://svn.apache.org/repos/asf
+
+
+
+2013-05-23T22:20:38.670815Z
+1485875
+goodale
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+13f79535-47bb-0310-9956-ffa450edef68
+
+python
+dir
+
+vm
+dir
+
+resources
+dir
+
+ui
+dir
+
+webapp
+dir
+

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/.svn/all-wcprops
----------------------------------------------------------------------
diff --git a/src/main/python/.svn/all-wcprops b/src/main/python/.svn/all-wcprops
new file mode 100755
index 0000000..78da14a
--- /dev/null
+++ b/src/main/python/.svn/all-wcprops
@@ -0,0 +1,5 @@
+K 25
+svn:wc:ra_dav:version-url
+V 73
+/repos/asf/!svn/ver/1485875/incubator/climate/trunk/rcmet/src/main/python
+END

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/.svn/entries
----------------------------------------------------------------------
diff --git a/src/main/python/.svn/entries b/src/main/python/.svn/entries
new file mode 100755
index 0000000..66d9ae4
--- /dev/null
+++ b/src/main/python/.svn/entries
@@ -0,0 +1,40 @@
+10
+
+dir
+1485921
+https://svn.apache.org/repos/asf/incubator/climate/trunk/rcmet/src/main/python
+https://svn.apache.org/repos/asf
+
+
+
+2013-05-23T22:20:38.670815Z
+1485875
+goodale
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+13f79535-47bb-0310-9956-ffa450edef68
+
+tests
+dir
+
+bin
+dir
+
+docs
+dir
+
+rcmes
+dir
+

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/bin/.svn/all-wcprops
----------------------------------------------------------------------
diff --git a/src/main/python/bin/.svn/all-wcprops b/src/main/python/bin/.svn/all-wcprops
new file mode 100755
index 0000000..b3eb738
--- /dev/null
+++ b/src/main/python/bin/.svn/all-wcprops
@@ -0,0 +1,11 @@
+K 25
+svn:wc:ra_dav:version-url
+V 77
+/repos/asf/!svn/ver/1485875/incubator/climate/trunk/rcmet/src/main/python/bin
+END
+rcmet.py
+K 25
+svn:wc:ra_dav:version-url
+V 86
+/repos/asf/!svn/ver/1485875/incubator/climate/trunk/rcmet/src/main/python/bin/rcmet.py
+END

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/bin/.svn/entries
----------------------------------------------------------------------
diff --git a/src/main/python/bin/.svn/entries b/src/main/python/bin/.svn/entries
new file mode 100755
index 0000000..bd64aea
--- /dev/null
+++ b/src/main/python/bin/.svn/entries
@@ -0,0 +1,62 @@
+10
+
+dir
+1485921
+https://svn.apache.org/repos/asf/incubator/climate/trunk/rcmet/src/main/python/bin
+https://svn.apache.org/repos/asf
+
+
+
+2013-05-23T22:20:38.670815Z
+1485875
+goodale
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+13f79535-47bb-0310-9956-ffa450edef68
+
+rcmet.py
+file
+
+
+
+
+2013-05-24T10:13:48.000000Z
+5a161d9dbb49ac552cae701088634d5e
+2013-05-23T22:20:38.670815Z
+1485875
+goodale
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+8370
+

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/bin/.svn/prop-base/rcmet.py.svn-base
----------------------------------------------------------------------
diff --git a/src/main/python/bin/.svn/prop-base/rcmet.py.svn-base b/src/main/python/bin/.svn/prop-base/rcmet.py.svn-base
new file mode 100755
index 0000000..869ac71
--- /dev/null
+++ b/src/main/python/bin/.svn/prop-base/rcmet.py.svn-base
@@ -0,0 +1,5 @@
+K 14
+svn:executable
+V 1
+*
+END


[10/51] [abbrv] [partial] Adding Jinwon's custom RCMET

Posted by jo...@apache.org.
http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/test/lib/angular/angular-scenario.js
----------------------------------------------------------------------
diff --git a/src/main/ui/test/lib/angular/angular-scenario.js b/src/main/ui/test/lib/angular/angular-scenario.js
new file mode 100755
index 0000000..538a799
--- /dev/null
+++ b/src/main/ui/test/lib/angular/angular-scenario.js
@@ -0,0 +1,26195 @@
+/*!
+ * jQuery JavaScript Library v1.7.2
+ * http://jquery.com/
+ *
+ * Copyright 2011, John Resig
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * Includes Sizzle.js
+ * http://sizzlejs.com/
+ * Copyright 2011, The Dojo Foundation
+ * Released under the MIT, BSD, and GPL Licenses.
+ *
+ * Date: Wed Mar 21 12:46:34 2012 -0700
+ */
+(function( window, undefined ) {
+'use strict';
+
+// Use the correct document accordingly with window argument (sandbox)
+var document = window.document,
+	navigator = window.navigator,
+	location = window.location;
+var jQuery = (function() {
+
+// Define a local copy of jQuery
+var jQuery = function( selector, context ) {
+		// The jQuery object is actually just the init constructor 'enhanced'
+		return new jQuery.fn.init( selector, context, rootjQuery );
+	},
+
+	// Map over jQuery in case of overwrite
+	_jQuery = window.jQuery,
+
+	// Map over the $ in case of overwrite
+	_$ = window.$,
+
+	// A central reference to the root jQuery(document)
+	rootjQuery,
+
+	// A simple way to check for HTML strings or ID strings
+	// Prioritize #id over <tag> to avoid XSS via location.hash (#9521)
+	quickExpr = /^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,
+
+	// Check if a string has a non-whitespace character in it
+	rnotwhite = /\S/,
+
+	// Used for trimming whitespace
+	trimLeft = /^\s+/,
+	trimRight = /\s+$/,
+
+	// Match a standalone tag
+	rsingleTag = /^<(\w+)\s*\/?>(?:<\/\1>)?$/,
+
+	// JSON RegExp
+	rvalidchars = /^[\],:{}\s]*$/,
+	rvalidescape = /\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,
+	rvalidtokens = /"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,
+	rvalidbraces = /(?:^|:|,)(?:\s*\[)+/g,
+
+	// Useragent RegExp
+	rwebkit = /(webkit)[ \/]([\w.]+)/,
+	ropera = /(opera)(?:.*version)?[ \/]([\w.]+)/,
+	rmsie = /(msie) ([\w.]+)/,
+	rmozilla = /(mozilla)(?:.*? rv:([\w.]+))?/,
+
+	// Matches dashed string for camelizing
+	rdashAlpha = /-([a-z]|[0-9])/ig,
+	rmsPrefix = /^-ms-/,
+
+	// Used by jQuery.camelCase as callback to replace()
+	fcamelCase = function( all, letter ) {
+		return ( letter + "" ).toUpperCase();
+	},
+
+	// Keep a UserAgent string for use with jQuery.browser
+	userAgent = navigator.userAgent,
+
+	// For matching the engine and version of the browser
+	browserMatch,
+
+	// The deferred used on DOM ready
+	readyList,
+
+	// The ready event handler
+	DOMContentLoaded,
+
+	// Save a reference to some core methods
+	toString = Object.prototype.toString,
+	hasOwn = Object.prototype.hasOwnProperty,
+	push = Array.prototype.push,
+	slice = Array.prototype.slice,
+	trim = String.prototype.trim,
+	indexOf = Array.prototype.indexOf,
+
+	// [[Class]] -> type pairs
+	class2type = {};
+
+jQuery.fn = jQuery.prototype = {
+	constructor: jQuery,
+	init: function( selector, context, rootjQuery ) {
+		var match, elem, ret, doc;
+
+		// Handle $(""), $(null), or $(undefined)
+		if ( !selector ) {
+			return this;
+		}
+
+		// Handle $(DOMElement)
+		if ( selector.nodeType ) {
+			this.context = this[0] = selector;
+			this.length = 1;
+			return this;
+		}
+
+		// The body element only exists once, optimize finding it
+		if ( selector === "body" && !context && document.body ) {
+			this.context = document;
+			this[0] = document.body;
+			this.selector = selector;
+			this.length = 1;
+			return this;
+		}
+
+		// Handle HTML strings
+		if ( typeof selector === "string" ) {
+			// Are we dealing with HTML string or an ID?
+			if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) {
+				// Assume that strings that start and end with <> are HTML and skip the regex check
+				match = [ null, selector, null ];
+
+			} else {
+				match = quickExpr.exec( selector );
+			}
+
+			// Verify a match, and that no context was specified for #id
+			if ( match && (match[1] || !context) ) {
+
+				// HANDLE: $(html) -> $(array)
+				if ( match[1] ) {
+					context = context instanceof jQuery ? context[0] : context;
+					doc = ( context ? context.ownerDocument || context : document );
+
+					// If a single string is passed in and it's a single tag
+					// just do a createElement and skip the rest
+					ret = rsingleTag.exec( selector );
+
+					if ( ret ) {
+						if ( jQuery.isPlainObject( context ) ) {
+							selector = [ document.createElement( ret[1] ) ];
+							jQuery.fn.attr.call( selector, context, true );
+
+						} else {
+							selector = [ doc.createElement( ret[1] ) ];
+						}
+
+					} else {
+						ret = jQuery.buildFragment( [ match[1] ], [ doc ] );
+						selector = ( ret.cacheable ? jQuery.clone(ret.fragment) : ret.fragment ).childNodes;
+					}
+
+					return jQuery.merge( this, selector );
+
+				// HANDLE: $("#id")
+				} else {
+					elem = document.getElementById( match[2] );
+
+					// Check parentNode to catch when Blackberry 4.6 returns
+					// nodes that are no longer in the document #6963
+					if ( elem && elem.parentNode ) {
+						// Handle the case where IE and Opera return items
+						// by name instead of ID
+						if ( elem.id !== match[2] ) {
+							return rootjQuery.find( selector );
+						}
+
+						// Otherwise, we inject the element directly into the jQuery object
+						this.length = 1;
+						this[0] = elem;
+					}
+
+					this.context = document;
+					this.selector = selector;
+					return this;
+				}
+
+			// HANDLE: $(expr, $(...))
+			} else if ( !context || context.jquery ) {
+				return ( context || rootjQuery ).find( selector );
+
+			// HANDLE: $(expr, context)
+			// (which is just equivalent to: $(context).find(expr)
+			} else {
+				return this.constructor( context ).find( selector );
+			}
+
+		// HANDLE: $(function)
+		// Shortcut for document ready
+		} else if ( jQuery.isFunction( selector ) ) {
+			return rootjQuery.ready( selector );
+		}
+
+		if ( selector.selector !== undefined ) {
+			this.selector = selector.selector;
+			this.context = selector.context;
+		}
+
+		return jQuery.makeArray( selector, this );
+	},
+
+	// Start with an empty selector
+	selector: "",
+
+	// The current version of jQuery being used
+	jquery: "1.7.2",
+
+	// The default length of a jQuery object is 0
+	length: 0,
+
+	// The number of elements contained in the matched element set
+	size: function() {
+		return this.length;
+	},
+
+	toArray: function() {
+		return slice.call( this, 0 );
+	},
+
+	// Get the Nth element in the matched element set OR
+	// Get the whole matched element set as a clean array
+	get: function( num ) {
+		return num == null ?
+
+			// Return a 'clean' array
+			this.toArray() :
+
+			// Return just the object
+			( num < 0 ? this[ this.length + num ] : this[ num ] );
+	},
+
+	// Take an array of elements and push it onto the stack
+	// (returning the new matched element set)
+	pushStack: function( elems, name, selector ) {
+		// Build a new jQuery matched element set
+		var ret = this.constructor();
+
+		if ( jQuery.isArray( elems ) ) {
+			push.apply( ret, elems );
+
+		} else {
+			jQuery.merge( ret, elems );
+		}
+
+		// Add the old object onto the stack (as a reference)
+		ret.prevObject = this;
+
+		ret.context = this.context;
+
+		if ( name === "find" ) {
+			ret.selector = this.selector + ( this.selector ? " " : "" ) + selector;
+		} else if ( name ) {
+			ret.selector = this.selector + "." + name + "(" + selector + ")";
+		}
+
+		// Return the newly-formed element set
+		return ret;
+	},
+
+	// Execute a callback for every element in the matched set.
+	// (You can seed the arguments with an array of args, but this is
+	// only used internally.)
+	each: function( callback, args ) {
+		return jQuery.each( this, callback, args );
+	},
+
+	ready: function( fn ) {
+		// Attach the listeners
+		jQuery.bindReady();
+
+		// Add the callback
+		readyList.add( fn );
+
+		return this;
+	},
+
+	eq: function( i ) {
+		i = +i;
+		return i === -1 ?
+			this.slice( i ) :
+			this.slice( i, i + 1 );
+	},
+
+	first: function() {
+		return this.eq( 0 );
+	},
+
+	last: function() {
+		return this.eq( -1 );
+	},
+
+	slice: function() {
+		return this.pushStack( slice.apply( this, arguments ),
+			"slice", slice.call(arguments).join(",") );
+	},
+
+	map: function( callback ) {
+		return this.pushStack( jQuery.map(this, function( elem, i ) {
+			return callback.call( elem, i, elem );
+		}));
+	},
+
+	end: function() {
+		return this.prevObject || this.constructor(null);
+	},
+
+	// For internal use only.
+	// Behaves like an Array's method, not like a jQuery method.
+	push: push,
+	sort: [].sort,
+	splice: [].splice
+};
+
+// Give the init function the jQuery prototype for later instantiation
+jQuery.fn.init.prototype = jQuery.fn;
+
+jQuery.extend = jQuery.fn.extend = function() {
+	var options, name, src, copy, copyIsArray, clone,
+		target = arguments[0] || {},
+		i = 1,
+		length = arguments.length,
+		deep = false;
+
+	// Handle a deep copy situation
+	if ( typeof target === "boolean" ) {
+		deep = target;
+		target = arguments[1] || {};
+		// skip the boolean and the target
+		i = 2;
+	}
+
+	// Handle case when target is a string or something (possible in deep copy)
+	if ( typeof target !== "object" && !jQuery.isFunction(target) ) {
+		target = {};
+	}
+
+	// extend jQuery itself if only one argument is passed
+	if ( length === i ) {
+		target = this;
+		--i;
+	}
+
+	for ( ; i < length; i++ ) {
+		// Only deal with non-null/undefined values
+		if ( (options = arguments[ i ]) != null ) {
+			// Extend the base object
+			for ( name in options ) {
+				src = target[ name ];
+				copy = options[ name ];
+
+				// Prevent never-ending loop
+				if ( target === copy ) {
+					continue;
+				}
+
+				// Recurse if we're merging plain objects or arrays
+				if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) {
+					if ( copyIsArray ) {
+						copyIsArray = false;
+						clone = src && jQuery.isArray(src) ? src : [];
+
+					} else {
+						clone = src && jQuery.isPlainObject(src) ? src : {};
+					}
+
+					// Never move original objects, clone them
+					target[ name ] = jQuery.extend( deep, clone, copy );
+
+				// Don't bring in undefined values
+				} else if ( copy !== undefined ) {
+					target[ name ] = copy;
+				}
+			}
+		}
+	}
+
+	// Return the modified object
+	return target;
+};
+
+jQuery.extend({
+	noConflict: function( deep ) {
+		if ( window.$ === jQuery ) {
+			window.$ = _$;
+		}
+
+		if ( deep && window.jQuery === jQuery ) {
+			window.jQuery = _jQuery;
+		}
+
+		return jQuery;
+	},
+
+	// Is the DOM ready to be used? Set to true once it occurs.
+	isReady: false,
+
+	// A counter to track how many items to wait for before
+	// the ready event fires. See #6781
+	readyWait: 1,
+
+	// Hold (or release) the ready event
+	holdReady: function( hold ) {
+		if ( hold ) {
+			jQuery.readyWait++;
+		} else {
+			jQuery.ready( true );
+		}
+	},
+
+	// Handle when the DOM is ready
+	ready: function( wait ) {
+		// Either a released hold or an DOMready/load event and not yet ready
+		if ( (wait === true && !--jQuery.readyWait) || (wait !== true && !jQuery.isReady) ) {
+			// Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).
+			if ( !document.body ) {
+				return setTimeout( jQuery.ready, 1 );
+			}
+
+			// Remember that the DOM is ready
+			jQuery.isReady = true;
+
+			// If a normal DOM Ready event fired, decrement, and wait if need be
+			if ( wait !== true && --jQuery.readyWait > 0 ) {
+				return;
+			}
+
+			// If there are functions bound, to execute
+			readyList.fireWith( document, [ jQuery ] );
+
+			// Trigger any bound ready events
+			if ( jQuery.fn.trigger ) {
+				jQuery( document ).trigger( "ready" ).off( "ready" );
+			}
+		}
+	},
+
+	bindReady: function() {
+		if ( readyList ) {
+			return;
+		}
+
+		readyList = jQuery.Callbacks( "once memory" );
+
+		// Catch cases where $(document).ready() is called after the
+		// browser event has already occurred.
+		if ( document.readyState === "complete" ) {
+			// Handle it asynchronously to allow scripts the opportunity to delay ready
+			return setTimeout( jQuery.ready, 1 );
+		}
+
+		// Mozilla, Opera and webkit nightlies currently support this event
+		if ( document.addEventListener ) {
+			// Use the handy event callback
+			document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false );
+
+			// A fallback to window.onload, that will always work
+			window.addEventListener( "load", jQuery.ready, false );
+
+		// If IE event model is used
+		} else if ( document.attachEvent ) {
+			// ensure firing before onload,
+			// maybe late but safe also for iframes
+			document.attachEvent( "onreadystatechange", DOMContentLoaded );
+
+			// A fallback to window.onload, that will always work
+			window.attachEvent( "onload", jQuery.ready );
+
+			// If IE and not a frame
+			// continually check to see if the document is ready
+			var toplevel = false;
+
+			try {
+				toplevel = window.frameElement == null;
+			} catch(e) {}
+
+			if ( document.documentElement.doScroll && toplevel ) {
+				doScrollCheck();
+			}
+		}
+	},
+
+	// See test/unit/core.js for details concerning isFunction.
+	// Since version 1.3, DOM methods and functions like alert
+	// aren't supported. They return false on IE (#2968).
+	isFunction: function( obj ) {
+		return jQuery.type(obj) === "function";
+	},
+
+	isArray: Array.isArray || function( obj ) {
+		return jQuery.type(obj) === "array";
+	},
+
+	isWindow: function( obj ) {
+		return obj != null && obj == obj.window;
+	},
+
+	isNumeric: function( obj ) {
+		return !isNaN( parseFloat(obj) ) && isFinite( obj );
+	},
+
+	type: function( obj ) {
+		return obj == null ?
+			String( obj ) :
+			class2type[ toString.call(obj) ] || "object";
+	},
+
+	isPlainObject: function( obj ) {
+		// Must be an Object.
+		// Because of IE, we also have to check the presence of the constructor property.
+		// Make sure that DOM nodes and window objects don't pass through, as well
+		if ( !obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) {
+			return false;
+		}
+
+		try {
+			// Not own constructor property must be Object
+			if ( obj.constructor &&
+				!hasOwn.call(obj, "constructor") &&
+				!hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) {
+				return false;
+			}
+		} catch ( e ) {
+			// IE8,9 Will throw exceptions on certain host objects #9897
+			return false;
+		}
+
+		// Own properties are enumerated firstly, so to speed up,
+		// if last one is own, then all properties are own.
+
+		var key;
+		for ( key in obj ) {}
+
+		return key === undefined || hasOwn.call( obj, key );
+	},
+
+	isEmptyObject: function( obj ) {
+		for ( var name in obj ) {
+			return false;
+		}
+		return true;
+	},
+
+	error: function( msg ) {
+		throw new Error( msg );
+	},
+
+	parseJSON: function( data ) {
+		if ( typeof data !== "string" || !data ) {
+			return null;
+		}
+
+		// Make sure leading/trailing whitespace is removed (IE can't handle it)
+		data = jQuery.trim( data );
+
+		// Attempt to parse using the native JSON parser first
+		if ( window.JSON && window.JSON.parse ) {
+			return window.JSON.parse( data );
+		}
+
+		// Make sure the incoming data is actual JSON
+		// Logic borrowed from http://json.org/json2.js
+		if ( rvalidchars.test( data.replace( rvalidescape, "@" )
+			.replace( rvalidtokens, "]" )
+			.replace( rvalidbraces, "")) ) {
+
+			return ( new Function( "return " + data ) )();
+
+		}
+		jQuery.error( "Invalid JSON: " + data );
+	},
+
+	// Cross-browser xml parsing
+	parseXML: function( data ) {
+		if ( typeof data !== "string" || !data ) {
+			return null;
+		}
+		var xml, tmp;
+		try {
+			if ( window.DOMParser ) { // Standard
+				tmp = new DOMParser();
+				xml = tmp.parseFromString( data , "text/xml" );
+			} else { // IE
+				xml = new ActiveXObject( "Microsoft.XMLDOM" );
+				xml.async = "false";
+				xml.loadXML( data );
+			}
+		} catch( e ) {
+			xml = undefined;
+		}
+		if ( !xml || !xml.documentElement || xml.getElementsByTagName( "parsererror" ).length ) {
+			jQuery.error( "Invalid XML: " + data );
+		}
+		return xml;
+	},
+
+	noop: function() {},
+
+	// Evaluates a script in a global context
+	// Workarounds based on findings by Jim Driscoll
+	// http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context
+	globalEval: function( data ) {
+		if ( data && rnotwhite.test( data ) ) {
+			// We use execScript on Internet Explorer
+			// We use an anonymous function so that context is window
+			// rather than jQuery in Firefox
+			( window.execScript || function( data ) {
+				window[ "eval" ].call( window, data );
+			} )( data );
+		}
+	},
+
+	// Convert dashed to camelCase; used by the css and data modules
+	// Microsoft forgot to hump their vendor prefix (#9572)
+	camelCase: function( string ) {
+		return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase );
+	},
+
+	nodeName: function( elem, name ) {
+		return elem.nodeName && elem.nodeName.toUpperCase() === name.toUpperCase();
+	},
+
+	// args is for internal usage only
+	each: function( object, callback, args ) {
+		var name, i = 0,
+			length = object.length,
+			isObj = length === undefined || jQuery.isFunction( object );
+
+		if ( args ) {
+			if ( isObj ) {
+				for ( name in object ) {
+					if ( callback.apply( object[ name ], args ) === false ) {
+						break;
+					}
+				}
+			} else {
+				for ( ; i < length; ) {
+					if ( callback.apply( object[ i++ ], args ) === false ) {
+						break;
+					}
+				}
+			}
+
+		// A special, fast, case for the most common use of each
+		} else {
+			if ( isObj ) {
+				for ( name in object ) {
+					if ( callback.call( object[ name ], name, object[ name ] ) === false ) {
+						break;
+					}
+				}
+			} else {
+				for ( ; i < length; ) {
+					if ( callback.call( object[ i ], i, object[ i++ ] ) === false ) {
+						break;
+					}
+				}
+			}
+		}
+
+		return object;
+	},
+
+	// Use native String.trim function wherever possible
+	trim: trim ?
+		function( text ) {
+			return text == null ?
+				"" :
+				trim.call( text );
+		} :
+
+		// Otherwise use our own trimming functionality
+		function( text ) {
+			return text == null ?
+				"" :
+				text.toString().replace( trimLeft, "" ).replace( trimRight, "" );
+		},
+
+	// results is for internal usage only
+	makeArray: function( array, results ) {
+		var ret = results || [];
+
+		if ( array != null ) {
+			// The window, strings (and functions) also have 'length'
+			// Tweaked logic slightly to handle Blackberry 4.7 RegExp issues #6930
+			var type = jQuery.type( array );
+
+			if ( array.length == null || type === "string" || type === "function" || type === "regexp" || jQuery.isWindow( array ) ) {
+				push.call( ret, array );
+			} else {
+				jQuery.merge( ret, array );
+			}
+		}
+
+		return ret;
+	},
+
+	inArray: function( elem, array, i ) {
+		var len;
+
+		if ( array ) {
+			if ( indexOf ) {
+				return indexOf.call( array, elem, i );
+			}
+
+			len = array.length;
+			i = i ? i < 0 ? Math.max( 0, len + i ) : i : 0;
+
+			for ( ; i < len; i++ ) {
+				// Skip accessing in sparse arrays
+				if ( i in array && array[ i ] === elem ) {
+					return i;
+				}
+			}
+		}
+
+		return -1;
+	},
+
+	merge: function( first, second ) {
+		var i = first.length,
+			j = 0;
+
+		if ( typeof second.length === "number" ) {
+			for ( var l = second.length; j < l; j++ ) {
+				first[ i++ ] = second[ j ];
+			}
+
+		} else {
+			while ( second[j] !== undefined ) {
+				first[ i++ ] = second[ j++ ];
+			}
+		}
+
+		first.length = i;
+
+		return first;
+	},
+
+	grep: function( elems, callback, inv ) {
+		var ret = [], retVal;
+		inv = !!inv;
+
+		// Go through the array, only saving the items
+		// that pass the validator function
+		for ( var i = 0, length = elems.length; i < length; i++ ) {
+			retVal = !!callback( elems[ i ], i );
+			if ( inv !== retVal ) {
+				ret.push( elems[ i ] );
+			}
+		}
+
+		return ret;
+	},
+
+	// arg is for internal usage only
+	map: function( elems, callback, arg ) {
+		var value, key, ret = [],
+			i = 0,
+			length = elems.length,
+			// jquery objects are treated as arrays
+			isArray = elems instanceof jQuery || length !== undefined && typeof length === "number" && ( ( length > 0 && elems[ 0 ] && elems[ length -1 ] ) || length === 0 || jQuery.isArray( elems ) ) ;
+
+		// Go through the array, translating each of the items to their
+		if ( isArray ) {
+			for ( ; i < length; i++ ) {
+				value = callback( elems[ i ], i, arg );
+
+				if ( value != null ) {
+					ret[ ret.length ] = value;
+				}
+			}
+
+		// Go through every key on the object,
+		} else {
+			for ( key in elems ) {
+				value = callback( elems[ key ], key, arg );
+
+				if ( value != null ) {
+					ret[ ret.length ] = value;
+				}
+			}
+		}
+
+		// Flatten any nested arrays
+		return ret.concat.apply( [], ret );
+	},
+
+	// A global GUID counter for objects
+	guid: 1,
+
+	// Bind a function to a context, optionally partially applying any
+	// arguments.
+	proxy: function( fn, context ) {
+		if ( typeof context === "string" ) {
+			var tmp = fn[ context ];
+			context = fn;
+			fn = tmp;
+		}
+
+		// Quick check to determine if target is callable, in the spec
+		// this throws a TypeError, but we will just return undefined.
+		if ( !jQuery.isFunction( fn ) ) {
+			return undefined;
+		}
+
+		// Simulated bind
+		var args = slice.call( arguments, 2 ),
+			proxy = function() {
+				return fn.apply( context, args.concat( slice.call( arguments ) ) );
+			};
+
+		// Set the guid of unique handler to the same of original handler, so it can be removed
+		proxy.guid = fn.guid = fn.guid || proxy.guid || jQuery.guid++;
+
+		return proxy;
+	},
+
+	// Mutifunctional method to get and set values to a collection
+	// The value/s can optionally be executed if it's a function
+	access: function( elems, fn, key, value, chainable, emptyGet, pass ) {
+		var exec,
+			bulk = key == null,
+			i = 0,
+			length = elems.length;
+
+		// Sets many values
+		if ( key && typeof key === "object" ) {
+			for ( i in key ) {
+				jQuery.access( elems, fn, i, key[i], 1, emptyGet, value );
+			}
+			chainable = 1;
+
+		// Sets one value
+		} else if ( value !== undefined ) {
+			// Optionally, function values get executed if exec is true
+			exec = pass === undefined && jQuery.isFunction( value );
+
+			if ( bulk ) {
+				// Bulk operations only iterate when executing function values
+				if ( exec ) {
+					exec = fn;
+					fn = function( elem, key, value ) {
+						return exec.call( jQuery( elem ), value );
+					};
+
+				// Otherwise they run against the entire set
+				} else {
+					fn.call( elems, value );
+					fn = null;
+				}
+			}
+
+			if ( fn ) {
+				for (; i < length; i++ ) {
+					fn( elems[i], key, exec ? value.call( elems[i], i, fn( elems[i], key ) ) : value, pass );
+				}
+			}
+
+			chainable = 1;
+		}
+
+		return chainable ?
+			elems :
+
+			// Gets
+			bulk ?
+				fn.call( elems ) :
+				length ? fn( elems[0], key ) : emptyGet;
+	},
+
+	now: function() {
+		return ( new Date() ).getTime();
+	},
+
+	// Use of jQuery.browser is frowned upon.
+	// More details: http://docs.jquery.com/Utilities/jQuery.browser
+	uaMatch: function( ua ) {
+		ua = ua.toLowerCase();
+
+		var match = rwebkit.exec( ua ) ||
+			ropera.exec( ua ) ||
+			rmsie.exec( ua ) ||
+			ua.indexOf("compatible") < 0 && rmozilla.exec( ua ) ||
+			[];
+
+		return { browser: match[1] || "", version: match[2] || "0" };
+	},
+
+	sub: function() {
+		function jQuerySub( selector, context ) {
+			return new jQuerySub.fn.init( selector, context );
+		}
+		jQuery.extend( true, jQuerySub, this );
+		jQuerySub.superclass = this;
+		jQuerySub.fn = jQuerySub.prototype = this();
+		jQuerySub.fn.constructor = jQuerySub;
+		jQuerySub.sub = this.sub;
+		jQuerySub.fn.init = function init( selector, context ) {
+			if ( context && context instanceof jQuery && !(context instanceof jQuerySub) ) {
+				context = jQuerySub( context );
+			}
+
+			return jQuery.fn.init.call( this, selector, context, rootjQuerySub );
+		};
+		jQuerySub.fn.init.prototype = jQuerySub.fn;
+		var rootjQuerySub = jQuerySub(document);
+		return jQuerySub;
+	},
+
+	browser: {}
+});
+
+// Populate the class2type map
+jQuery.each("Boolean Number String Function Array Date RegExp Object".split(" "), function(i, name) {
+	class2type[ "[object " + name + "]" ] = name.toLowerCase();
+});
+
+browserMatch = jQuery.uaMatch( userAgent );
+if ( browserMatch.browser ) {
+	jQuery.browser[ browserMatch.browser ] = true;
+	jQuery.browser.version = browserMatch.version;
+}
+
+// Deprecated, use jQuery.browser.webkit instead
+if ( jQuery.browser.webkit ) {
+	jQuery.browser.safari = true;
+}
+
+// IE doesn't match non-breaking spaces with \s
+if ( rnotwhite.test( "\xA0" ) ) {
+	trimLeft = /^[\s\xA0]+/;
+	trimRight = /[\s\xA0]+$/;
+}
+
+// All jQuery objects should point back to these
+rootjQuery = jQuery(document);
+
+// Cleanup functions for the document ready method
+if ( document.addEventListener ) {
+	DOMContentLoaded = function() {
+		document.removeEventListener( "DOMContentLoaded", DOMContentLoaded, false );
+		jQuery.ready();
+	};
+
+} else if ( document.attachEvent ) {
+	DOMContentLoaded = function() {
+		// Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).
+		if ( document.readyState === "complete" ) {
+			document.detachEvent( "onreadystatechange", DOMContentLoaded );
+			jQuery.ready();
+		}
+	};
+}
+
+// The DOM ready check for Internet Explorer
+function doScrollCheck() {
+	if ( jQuery.isReady ) {
+		return;
+	}
+
+	try {
+		// If IE is used, use the trick by Diego Perini
+		// http://javascript.nwbox.com/IEContentLoaded/
+		document.documentElement.doScroll("left");
+	} catch(e) {
+		setTimeout( doScrollCheck, 1 );
+		return;
+	}
+
+	// and execute any waiting functions
+	jQuery.ready();
+}
+
+return jQuery;
+
+})();
+
+
+// String to Object flags format cache
+var flagsCache = {};
+
+// Convert String-formatted flags into Object-formatted ones and store in cache
+function createFlags( flags ) {
+	var object = flagsCache[ flags ] = {},
+		i, length;
+	flags = flags.split( /\s+/ );
+	for ( i = 0, length = flags.length; i < length; i++ ) {
+		object[ flags[i] ] = true;
+	}
+	return object;
+}
+
+/*
+ * Create a callback list using the following parameters:
+ *
+ *	flags:	an optional list of space-separated flags that will change how
+ *			the callback list behaves
+ *
+ * By default a callback list will act like an event callback list and can be
+ * "fired" multiple times.
+ *
+ * Possible flags:
+ *
+ *	once:			will ensure the callback list can only be fired once (like a Deferred)
+ *
+ *	memory:			will keep track of previous values and will call any callback added
+ *					after the list has been fired right away with the latest "memorized"
+ *					values (like a Deferred)
+ *
+ *	unique:			will ensure a callback can only be added once (no duplicate in the list)
+ *
+ *	stopOnFalse:	interrupt callings when a callback returns false
+ *
+ */
+jQuery.Callbacks = function( flags ) {
+
+	// Convert flags from String-formatted to Object-formatted
+	// (we check in cache first)
+	flags = flags ? ( flagsCache[ flags ] || createFlags( flags ) ) : {};
+
+	var // Actual callback list
+		list = [],
+		// Stack of fire calls for repeatable lists
+		stack = [],
+		// Last fire value (for non-forgettable lists)
+		memory,
+		// Flag to know if list was already fired
+		fired,
+		// Flag to know if list is currently firing
+		firing,
+		// First callback to fire (used internally by add and fireWith)
+		firingStart,
+		// End of the loop when firing
+		firingLength,
+		// Index of currently firing callback (modified by remove if needed)
+		firingIndex,
+		// Add one or several callbacks to the list
+		add = function( args ) {
+			var i,
+				length,
+				elem,
+				type,
+				actual;
+			for ( i = 0, length = args.length; i < length; i++ ) {
+				elem = args[ i ];
+				type = jQuery.type( elem );
+				if ( type === "array" ) {
+					// Inspect recursively
+					add( elem );
+				} else if ( type === "function" ) {
+					// Add if not in unique mode and callback is not in
+					if ( !flags.unique || !self.has( elem ) ) {
+						list.push( elem );
+					}
+				}
+			}
+		},
+		// Fire callbacks
+		fire = function( context, args ) {
+			args = args || [];
+			memory = !flags.memory || [ context, args ];
+			fired = true;
+			firing = true;
+			firingIndex = firingStart || 0;
+			firingStart = 0;
+			firingLength = list.length;
+			for ( ; list && firingIndex < firingLength; firingIndex++ ) {
+				if ( list[ firingIndex ].apply( context, args ) === false && flags.stopOnFalse ) {
+					memory = true; // Mark as halted
+					break;
+				}
+			}
+			firing = false;
+			if ( list ) {
+				if ( !flags.once ) {
+					if ( stack && stack.length ) {
+						memory = stack.shift();
+						self.fireWith( memory[ 0 ], memory[ 1 ] );
+					}
+				} else if ( memory === true ) {
+					self.disable();
+				} else {
+					list = [];
+				}
+			}
+		},
+		// Actual Callbacks object
+		self = {
+			// Add a callback or a collection of callbacks to the list
+			add: function() {
+				if ( list ) {
+					var length = list.length;
+					add( arguments );
+					// Do we need to add the callbacks to the
+					// current firing batch?
+					if ( firing ) {
+						firingLength = list.length;
+					// With memory, if we're not firing then
+					// we should call right away, unless previous
+					// firing was halted (stopOnFalse)
+					} else if ( memory && memory !== true ) {
+						firingStart = length;
+						fire( memory[ 0 ], memory[ 1 ] );
+					}
+				}
+				return this;
+			},
+			// Remove a callback from the list
+			remove: function() {
+				if ( list ) {
+					var args = arguments,
+						argIndex = 0,
+						argLength = args.length;
+					for ( ; argIndex < argLength ; argIndex++ ) {
+						for ( var i = 0; i < list.length; i++ ) {
+							if ( args[ argIndex ] === list[ i ] ) {
+								// Handle firingIndex and firingLength
+								if ( firing ) {
+									if ( i <= firingLength ) {
+										firingLength--;
+										if ( i <= firingIndex ) {
+											firingIndex--;
+										}
+									}
+								}
+								// Remove the element
+								list.splice( i--, 1 );
+								// If we have some unicity property then
+								// we only need to do this once
+								if ( flags.unique ) {
+									break;
+								}
+							}
+						}
+					}
+				}
+				return this;
+			},
+			// Control if a given callback is in the list
+			has: function( fn ) {
+				if ( list ) {
+					var i = 0,
+						length = list.length;
+					for ( ; i < length; i++ ) {
+						if ( fn === list[ i ] ) {
+							return true;
+						}
+					}
+				}
+				return false;
+			},
+			// Remove all callbacks from the list
+			empty: function() {
+				list = [];
+				return this;
+			},
+			// Have the list do nothing anymore
+			disable: function() {
+				list = stack = memory = undefined;
+				return this;
+			},
+			// Is it disabled?
+			disabled: function() {
+				return !list;
+			},
+			// Lock the list in its current state
+			lock: function() {
+				stack = undefined;
+				if ( !memory || memory === true ) {
+					self.disable();
+				}
+				return this;
+			},
+			// Is it locked?
+			locked: function() {
+				return !stack;
+			},
+			// Call all callbacks with the given context and arguments
+			fireWith: function( context, args ) {
+				if ( stack ) {
+					if ( firing ) {
+						if ( !flags.once ) {
+							stack.push( [ context, args ] );
+						}
+					} else if ( !( flags.once && memory ) ) {
+						fire( context, args );
+					}
+				}
+				return this;
+			},
+			// Call all the callbacks with the given arguments
+			fire: function() {
+				self.fireWith( this, arguments );
+				return this;
+			},
+			// To know if the callbacks have already been called at least once
+			fired: function() {
+				return !!fired;
+			}
+		};
+
+	return self;
+};
+
+
+
+
+var // Static reference to slice
+	sliceDeferred = [].slice;
+
+jQuery.extend({
+
+	Deferred: function( func ) {
+		var doneList = jQuery.Callbacks( "once memory" ),
+			failList = jQuery.Callbacks( "once memory" ),
+			progressList = jQuery.Callbacks( "memory" ),
+			state = "pending",
+			lists = {
+				resolve: doneList,
+				reject: failList,
+				notify: progressList
+			},
+			promise = {
+				done: doneList.add,
+				fail: failList.add,
+				progress: progressList.add,
+
+				state: function() {
+					return state;
+				},
+
+				// Deprecated
+				isResolved: doneList.fired,
+				isRejected: failList.fired,
+
+				then: function( doneCallbacks, failCallbacks, progressCallbacks ) {
+					deferred.done( doneCallbacks ).fail( failCallbacks ).progress( progressCallbacks );
+					return this;
+				},
+				always: function() {
+					deferred.done.apply( deferred, arguments ).fail.apply( deferred, arguments );
+					return this;
+				},
+				pipe: function( fnDone, fnFail, fnProgress ) {
+					return jQuery.Deferred(function( newDefer ) {
+						jQuery.each( {
+							done: [ fnDone, "resolve" ],
+							fail: [ fnFail, "reject" ],
+							progress: [ fnProgress, "notify" ]
+						}, function( handler, data ) {
+							var fn = data[ 0 ],
+								action = data[ 1 ],
+								returned;
+							if ( jQuery.isFunction( fn ) ) {
+								deferred[ handler ](function() {
+									returned = fn.apply( this, arguments );
+									if ( returned && jQuery.isFunction( returned.promise ) ) {
+										returned.promise().then( newDefer.resolve, newDefer.reject, newDefer.notify );
+									} else {
+										newDefer[ action + "With" ]( this === deferred ? newDefer : this, [ returned ] );
+									}
+								});
+							} else {
+								deferred[ handler ]( newDefer[ action ] );
+							}
+						});
+					}).promise();
+				},
+				// Get a promise for this deferred
+				// If obj is provided, the promise aspect is added to the object
+				promise: function( obj ) {
+					if ( obj == null ) {
+						obj = promise;
+					} else {
+						for ( var key in promise ) {
+							obj[ key ] = promise[ key ];
+						}
+					}
+					return obj;
+				}
+			},
+			deferred = promise.promise({}),
+			key;
+
+		for ( key in lists ) {
+			deferred[ key ] = lists[ key ].fire;
+			deferred[ key + "With" ] = lists[ key ].fireWith;
+		}
+
+		// Handle state
+		deferred.done( function() {
+			state = "resolved";
+		}, failList.disable, progressList.lock ).fail( function() {
+			state = "rejected";
+		}, doneList.disable, progressList.lock );
+
+		// Call given func if any
+		if ( func ) {
+			func.call( deferred, deferred );
+		}
+
+		// All done!
+		return deferred;
+	},
+
+	// Deferred helper
+	when: function( firstParam ) {
+		var args = sliceDeferred.call( arguments, 0 ),
+			i = 0,
+			length = args.length,
+			pValues = new Array( length ),
+			count = length,
+			pCount = length,
+			deferred = length <= 1 && firstParam && jQuery.isFunction( firstParam.promise ) ?
+				firstParam :
+				jQuery.Deferred(),
+			promise = deferred.promise();
+		function resolveFunc( i ) {
+			return function( value ) {
+				args[ i ] = arguments.length > 1 ? sliceDeferred.call( arguments, 0 ) : value;
+				if ( !( --count ) ) {
+					deferred.resolveWith( deferred, args );
+				}
+			};
+		}
+		function progressFunc( i ) {
+			return function( value ) {
+				pValues[ i ] = arguments.length > 1 ? sliceDeferred.call( arguments, 0 ) : value;
+				deferred.notifyWith( promise, pValues );
+			};
+		}
+		if ( length > 1 ) {
+			for ( ; i < length; i++ ) {
+				if ( args[ i ] && args[ i ].promise && jQuery.isFunction( args[ i ].promise ) ) {
+					args[ i ].promise().then( resolveFunc(i), deferred.reject, progressFunc(i) );
+				} else {
+					--count;
+				}
+			}
+			if ( !count ) {
+				deferred.resolveWith( deferred, args );
+			}
+		} else if ( deferred !== firstParam ) {
+			deferred.resolveWith( deferred, length ? [ firstParam ] : [] );
+		}
+		return promise;
+	}
+});
+
+
+
+
+jQuery.support = (function() {
+
+	var support,
+		all,
+		a,
+		select,
+		opt,
+		input,
+		fragment,
+		tds,
+		events,
+		eventName,
+		i,
+		isSupported,
+		div = document.createElement( "div" ),
+		documentElement = document.documentElement;
+
+	// Preliminary tests
+	div.setAttribute("className", "t");
+	div.innerHTML = "   <link/><table></table><a href='/a' style='top:1px;float:left;opacity:.55;'>a</a><input type='checkbox'/>";
+
+	all = div.getElementsByTagName( "*" );
+	a = div.getElementsByTagName( "a" )[ 0 ];
+
+	// Can't get basic test support
+	if ( !all || !all.length || !a ) {
+		return {};
+	}
+
+	// First batch of supports tests
+	select = document.createElement( "select" );
+	opt = select.appendChild( document.createElement("option") );
+	input = div.getElementsByTagName( "input" )[ 0 ];
+
+	support = {
+		// IE strips leading whitespace when .innerHTML is used
+		leadingWhitespace: ( div.firstChild.nodeType === 3 ),
+
+		// Make sure that tbody elements aren't automatically inserted
+		// IE will insert them into empty tables
+		tbody: !div.getElementsByTagName("tbody").length,
+
+		// Make sure that link elements get serialized correctly by innerHTML
+		// This requires a wrapper element in IE
+		htmlSerialize: !!div.getElementsByTagName("link").length,
+
+		// Get the style information from getAttribute
+		// (IE uses .cssText instead)
+		style: /top/.test( a.getAttribute("style") ),
+
+		// Make sure that URLs aren't manipulated
+		// (IE normalizes it by default)
+		hrefNormalized: ( a.getAttribute("href") === "/a" ),
+
+		// Make sure that element opacity exists
+		// (IE uses filter instead)
+		// Use a regex to work around a WebKit issue. See #5145
+		opacity: /^0.55/.test( a.style.opacity ),
+
+		// Verify style float existence
+		// (IE uses styleFloat instead of cssFloat)
+		cssFloat: !!a.style.cssFloat,
+
+		// Make sure that if no value is specified for a checkbox
+		// that it defaults to "on".
+		// (WebKit defaults to "" instead)
+		checkOn: ( input.value === "on" ),
+
+		// Make sure that a selected-by-default option has a working selected property.
+		// (WebKit defaults to false instead of true, IE too, if it's in an optgroup)
+		optSelected: opt.selected,
+
+		// Test setAttribute on camelCase class. If it works, we need attrFixes when doing get/setAttribute (ie6/7)
+		getSetAttribute: div.className !== "t",
+
+		// Tests for enctype support on a form(#6743)
+		enctype: !!document.createElement("form").enctype,
+
+		// Makes sure cloning an html5 element does not cause problems
+		// Where outerHTML is undefined, this still works
+		html5Clone: document.createElement("nav").cloneNode( true ).outerHTML !== "<:nav></:nav>",
+
+		// Will be defined later
+		submitBubbles: true,
+		changeBubbles: true,
+		focusinBubbles: false,
+		deleteExpando: true,
+		noCloneEvent: true,
+		inlineBlockNeedsLayout: false,
+		shrinkWrapBlocks: false,
+		reliableMarginRight: true,
+		pixelMargin: true
+	};
+
+	// jQuery.boxModel DEPRECATED in 1.3, use jQuery.support.boxModel instead
+	jQuery.boxModel = support.boxModel = (document.compatMode === "CSS1Compat");
+
+	// Make sure checked status is properly cloned
+	input.checked = true;
+	support.noCloneChecked = input.cloneNode( true ).checked;
+
+	// Make sure that the options inside disabled selects aren't marked as disabled
+	// (WebKit marks them as disabled)
+	select.disabled = true;
+	support.optDisabled = !opt.disabled;
+
+	// Test to see if it's possible to delete an expando from an element
+	// Fails in Internet Explorer
+	try {
+		delete div.test;
+	} catch( e ) {
+		support.deleteExpando = false;
+	}
+
+	if ( !div.addEventListener && div.attachEvent && div.fireEvent ) {
+		div.attachEvent( "onclick", function() {
+			// Cloning a node shouldn't copy over any
+			// bound event handlers (IE does this)
+			support.noCloneEvent = false;
+		});
+		div.cloneNode( true ).fireEvent( "onclick" );
+	}
+
+	// Check if a radio maintains its value
+	// after being appended to the DOM
+	input = document.createElement("input");
+	input.value = "t";
+	input.setAttribute("type", "radio");
+	support.radioValue = input.value === "t";
+
+	input.setAttribute("checked", "checked");
+
+	// #11217 - WebKit loses check when the name is after the checked attribute
+	input.setAttribute( "name", "t" );
+
+	div.appendChild( input );
+	fragment = document.createDocumentFragment();
+	fragment.appendChild( div.lastChild );
+
+	// WebKit doesn't clone checked state correctly in fragments
+	support.checkClone = fragment.cloneNode( true ).cloneNode( true ).lastChild.checked;
+
+	// Check if a disconnected checkbox will retain its checked
+	// value of true after appended to the DOM (IE6/7)
+	support.appendChecked = input.checked;
+
+	fragment.removeChild( input );
+	fragment.appendChild( div );
+
+	// Technique from Juriy Zaytsev
+	// http://perfectionkills.com/detecting-event-support-without-browser-sniffing/
+	// We only care about the case where non-standard event systems
+	// are used, namely in IE. Short-circuiting here helps us to
+	// avoid an eval call (in setAttribute) which can cause CSP
+	// to go haywire. See: https://developer.mozilla.org/en/Security/CSP
+	if ( div.attachEvent ) {
+		for ( i in {
+			submit: 1,
+			change: 1,
+			focusin: 1
+		}) {
+			eventName = "on" + i;
+			isSupported = ( eventName in div );
+			if ( !isSupported ) {
+				div.setAttribute( eventName, "return;" );
+				isSupported = ( typeof div[ eventName ] === "function" );
+			}
+			support[ i + "Bubbles" ] = isSupported;
+		}
+	}
+
+	fragment.removeChild( div );
+
+	// Null elements to avoid leaks in IE
+	fragment = select = opt = div = input = null;
+
+	// Run tests that need a body at doc ready
+	jQuery(function() {
+		var container, outer, inner, table, td, offsetSupport,
+			marginDiv, conMarginTop, style, html, positionTopLeftWidthHeight,
+			paddingMarginBorderVisibility, paddingMarginBorder,
+			body = document.getElementsByTagName("body")[0];
+
+		if ( !body ) {
+			// Return for frameset docs that don't have a body
+			return;
+		}
+
+		conMarginTop = 1;
+		paddingMarginBorder = "padding:0;margin:0;border:";
+		positionTopLeftWidthHeight = "position:absolute;top:0;left:0;width:1px;height:1px;";
+		paddingMarginBorderVisibility = paddingMarginBorder + "0;visibility:hidden;";
+		style = "style='" + positionTopLeftWidthHeight + paddingMarginBorder + "5px solid #000;";
+		html = "<div " + style + "display:block;'><div style='" + paddingMarginBorder + "0;display:block;overflow:hidden;'></div></div>" +
+			"<table " + style + "' cellpadding='0' cellspacing='0'>" +
+			"<tr><td></td></tr></table>";
+
+		container = document.createElement("div");
+		container.style.cssText = paddingMarginBorderVisibility + "width:0;height:0;position:static;top:0;margin-top:" + conMarginTop + "px";
+		body.insertBefore( container, body.firstChild );
+
+		// Construct the test element
+		div = document.createElement("div");
+		container.appendChild( div );
+
+		// Check if table cells still have offsetWidth/Height when they are set
+		// to display:none and there are still other visible table cells in a
+		// table row; if so, offsetWidth/Height are not reliable for use when
+		// determining if an element has been hidden directly using
+		// display:none (it is still safe to use offsets if a parent element is
+		// hidden; don safety goggles and see bug #4512 for more information).
+		// (only IE 8 fails this test)
+		div.innerHTML = "<table><tr><td style='" + paddingMarginBorder + "0;display:none'></td><td>t</td></tr></table>";
+		tds = div.getElementsByTagName( "td" );
+		isSupported = ( tds[ 0 ].offsetHeight === 0 );
+
+		tds[ 0 ].style.display = "";
+		tds[ 1 ].style.display = "none";
+
+		// Check if empty table cells still have offsetWidth/Height
+		// (IE <= 8 fail this test)
+		support.reliableHiddenOffsets = isSupported && ( tds[ 0 ].offsetHeight === 0 );
+
+		// Check if div with explicit width and no margin-right incorrectly
+		// gets computed margin-right based on width of container. For more
+		// info see bug #3333
+		// Fails in WebKit before Feb 2011 nightlies
+		// WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right
+		if ( window.getComputedStyle ) {
+			div.innerHTML = "";
+			marginDiv = document.createElement( "div" );
+			marginDiv.style.width = "0";
+			marginDiv.style.marginRight = "0";
+			div.style.width = "2px";
+			div.appendChild( marginDiv );
+			support.reliableMarginRight =
+				( parseInt( ( window.getComputedStyle( marginDiv, null ) || { marginRight: 0 } ).marginRight, 10 ) || 0 ) === 0;
+		}
+
+		if ( typeof div.style.zoom !== "undefined" ) {
+			// Check if natively block-level elements act like inline-block
+			// elements when setting their display to 'inline' and giving
+			// them layout
+			// (IE < 8 does this)
+			div.innerHTML = "";
+			div.style.width = div.style.padding = "1px";
+			div.style.border = 0;
+			div.style.overflow = "hidden";
+			div.style.display = "inline";
+			div.style.zoom = 1;
+			support.inlineBlockNeedsLayout = ( div.offsetWidth === 3 );
+
+			// Check if elements with layout shrink-wrap their children
+			// (IE 6 does this)
+			div.style.display = "block";
+			div.style.overflow = "visible";
+			div.innerHTML = "<div style='width:5px;'></div>";
+			support.shrinkWrapBlocks = ( div.offsetWidth !== 3 );
+		}
+
+		div.style.cssText = positionTopLeftWidthHeight + paddingMarginBorderVisibility;
+		div.innerHTML = html;
+
+		outer = div.firstChild;
+		inner = outer.firstChild;
+		td = outer.nextSibling.firstChild.firstChild;
+
+		offsetSupport = {
+			doesNotAddBorder: ( inner.offsetTop !== 5 ),
+			doesAddBorderForTableAndCells: ( td.offsetTop === 5 )
+		};
+
+		inner.style.position = "fixed";
+		inner.style.top = "20px";
+
+		// safari subtracts parent border width here which is 5px
+		offsetSupport.fixedPosition = ( inner.offsetTop === 20 || inner.offsetTop === 15 );
+		inner.style.position = inner.style.top = "";
+
+		outer.style.overflow = "hidden";
+		outer.style.position = "relative";
+
+		offsetSupport.subtractsBorderForOverflowNotVisible = ( inner.offsetTop === -5 );
+		offsetSupport.doesNotIncludeMarginInBodyOffset = ( body.offsetTop !== conMarginTop );
+
+		if ( window.getComputedStyle ) {
+			div.style.marginTop = "1%";
+			support.pixelMargin = ( window.getComputedStyle( div, null ) || { marginTop: 0 } ).marginTop !== "1%";
+		}
+
+		if ( typeof container.style.zoom !== "undefined" ) {
+			container.style.zoom = 1;
+		}
+
+		body.removeChild( container );
+		marginDiv = div = container = null;
+
+		jQuery.extend( support, offsetSupport );
+	});
+
+	return support;
+})();
+
+
+
+
+var rbrace = /^(?:\{.*\}|\[.*\])$/,
+	rmultiDash = /([A-Z])/g;
+
+jQuery.extend({
+	cache: {},
+
+	// Please use with caution
+	uuid: 0,
+
+	// Unique for each copy of jQuery on the page
+	// Non-digits removed to match rinlinejQuery
+	expando: "jQuery" + ( jQuery.fn.jquery + Math.random() ).replace( /\D/g, "" ),
+
+	// The following elements throw uncatchable exceptions if you
+	// attempt to add expando properties to them.
+	noData: {
+		"embed": true,
+		// Ban all objects except for Flash (which handle expandos)
+		"object": "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",
+		"applet": true
+	},
+
+	hasData: function( elem ) {
+		elem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ];
+		return !!elem && !isEmptyDataObject( elem );
+	},
+
+	data: function( elem, name, data, pvt /* Internal Use Only */ ) {
+		if ( !jQuery.acceptData( elem ) ) {
+			return;
+		}
+
+		var privateCache, thisCache, ret,
+			internalKey = jQuery.expando,
+			getByName = typeof name === "string",
+
+			// We have to handle DOM nodes and JS objects differently because IE6-7
+			// can't GC object references properly across the DOM-JS boundary
+			isNode = elem.nodeType,
+
+			// Only DOM nodes need the global jQuery cache; JS object data is
+			// attached directly to the object so GC can occur automatically
+			cache = isNode ? jQuery.cache : elem,
+
+			// Only defining an ID for JS objects if its cache already exists allows
+			// the code to shortcut on the same path as a DOM node with no cache
+			id = isNode ? elem[ internalKey ] : elem[ internalKey ] && internalKey,
+			isEvents = name === "events";
+
+		// Avoid doing any more work than we need to when trying to get data on an
+		// object that has no data at all
+		if ( (!id || !cache[id] || (!isEvents && !pvt && !cache[id].data)) && getByName && data === undefined ) {
+			return;
+		}
+
+		if ( !id ) {
+			// Only DOM nodes need a new unique ID for each element since their data
+			// ends up in the global cache
+			if ( isNode ) {
+				elem[ internalKey ] = id = ++jQuery.uuid;
+			} else {
+				id = internalKey;
+			}
+		}
+
+		if ( !cache[ id ] ) {
+			cache[ id ] = {};
+
+			// Avoids exposing jQuery metadata on plain JS objects when the object
+			// is serialized using JSON.stringify
+			if ( !isNode ) {
+				cache[ id ].toJSON = jQuery.noop;
+			}
+		}
+
+		// An object can be passed to jQuery.data instead of a key/value pair; this gets
+		// shallow copied over onto the existing cache
+		if ( typeof name === "object" || typeof name === "function" ) {
+			if ( pvt ) {
+				cache[ id ] = jQuery.extend( cache[ id ], name );
+			} else {
+				cache[ id ].data = jQuery.extend( cache[ id ].data, name );
+			}
+		}
+
+		privateCache = thisCache = cache[ id ];
+
+		// jQuery data() is stored in a separate object inside the object's internal data
+		// cache in order to avoid key collisions between internal data and user-defined
+		// data.
+		if ( !pvt ) {
+			if ( !thisCache.data ) {
+				thisCache.data = {};
+			}
+
+			thisCache = thisCache.data;
+		}
+
+		if ( data !== undefined ) {
+			thisCache[ jQuery.camelCase( name ) ] = data;
+		}
+
+		// Users should not attempt to inspect the internal events object using jQuery.data,
+		// it is undocumented and subject to change. But does anyone listen? No.
+		if ( isEvents && !thisCache[ name ] ) {
+			return privateCache.events;
+		}
+
+		// Check for both converted-to-camel and non-converted data property names
+		// If a data property was specified
+		if ( getByName ) {
+
+			// First Try to find as-is property data
+			ret = thisCache[ name ];
+
+			// Test for null|undefined property data
+			if ( ret == null ) {
+
+				// Try to find the camelCased property
+				ret = thisCache[ jQuery.camelCase( name ) ];
+			}
+		} else {
+			ret = thisCache;
+		}
+
+		return ret;
+	},
+
+	removeData: function( elem, name, pvt /* Internal Use Only */ ) {
+		if ( !jQuery.acceptData( elem ) ) {
+			return;
+		}
+
+		var thisCache, i, l,
+
+			// Reference to internal data cache key
+			internalKey = jQuery.expando,
+
+			isNode = elem.nodeType,
+
+			// See jQuery.data for more information
+			cache = isNode ? jQuery.cache : elem,
+
+			// See jQuery.data for more information
+			id = isNode ? elem[ internalKey ] : internalKey;
+
+		// If there is already no cache entry for this object, there is no
+		// purpose in continuing
+		if ( !cache[ id ] ) {
+			return;
+		}
+
+		if ( name ) {
+
+			thisCache = pvt ? cache[ id ] : cache[ id ].data;
+
+			if ( thisCache ) {
+
+				// Support array or space separated string names for data keys
+				if ( !jQuery.isArray( name ) ) {
+
+					// try the string as a key before any manipulation
+					if ( name in thisCache ) {
+						name = [ name ];
+					} else {
+
+						// split the camel cased version by spaces unless a key with the spaces exists
+						name = jQuery.camelCase( name );
+						if ( name in thisCache ) {
+							name = [ name ];
+						} else {
+							name = name.split( " " );
+						}
+					}
+				}
+
+				for ( i = 0, l = name.length; i < l; i++ ) {
+					delete thisCache[ name[i] ];
+				}
+
+				// If there is no data left in the cache, we want to continue
+				// and let the cache object itself get destroyed
+				if ( !( pvt ? isEmptyDataObject : jQuery.isEmptyObject )( thisCache ) ) {
+					return;
+				}
+			}
+		}
+
+		// See jQuery.data for more information
+		if ( !pvt ) {
+			delete cache[ id ].data;
+
+			// Don't destroy the parent cache unless the internal data object
+			// had been the only thing left in it
+			if ( !isEmptyDataObject(cache[ id ]) ) {
+				return;
+			}
+		}
+
+		// Browsers that fail expando deletion also refuse to delete expandos on
+		// the window, but it will allow it on all other JS objects; other browsers
+		// don't care
+		// Ensure that `cache` is not a window object #10080
+		if ( jQuery.support.deleteExpando || !cache.setInterval ) {
+			delete cache[ id ];
+		} else {
+			cache[ id ] = null;
+		}
+
+		// We destroyed the cache and need to eliminate the expando on the node to avoid
+		// false lookups in the cache for entries that no longer exist
+		if ( isNode ) {
+			// IE does not allow us to delete expando properties from nodes,
+			// nor does it have a removeAttribute function on Document nodes;
+			// we must handle all of these cases
+			if ( jQuery.support.deleteExpando ) {
+				delete elem[ internalKey ];
+			} else if ( elem.removeAttribute ) {
+				elem.removeAttribute( internalKey );
+			} else {
+				elem[ internalKey ] = null;
+			}
+		}
+	},
+
+	// For internal use only.
+	_data: function( elem, name, data ) {
+		return jQuery.data( elem, name, data, true );
+	},
+
+	// A method for determining if a DOM node can handle the data expando
+	acceptData: function( elem ) {
+		if ( elem.nodeName ) {
+			var match = jQuery.noData[ elem.nodeName.toLowerCase() ];
+
+			if ( match ) {
+				return !(match === true || elem.getAttribute("classid") !== match);
+			}
+		}
+
+		return true;
+	}
+});
+
+jQuery.fn.extend({
+	data: function( key, value ) {
+		var parts, part, attr, name, l,
+			elem = this[0],
+			i = 0,
+			data = null;
+
+		// Gets all values
+		if ( key === undefined ) {
+			if ( this.length ) {
+				data = jQuery.data( elem );
+
+				if ( elem.nodeType === 1 && !jQuery._data( elem, "parsedAttrs" ) ) {
+					attr = elem.attributes;
+					for ( l = attr.length; i < l; i++ ) {
+						name = attr[i].name;
+
+						if ( name.indexOf( "data-" ) === 0 ) {
+							name = jQuery.camelCase( name.substring(5) );
+
+							dataAttr( elem, name, data[ name ] );
+						}
+					}
+					jQuery._data( elem, "parsedAttrs", true );
+				}
+			}
+
+			return data;
+		}
+
+		// Sets multiple values
+		if ( typeof key === "object" ) {
+			return this.each(function() {
+				jQuery.data( this, key );
+			});
+		}
+
+		parts = key.split( ".", 2 );
+		parts[1] = parts[1] ? "." + parts[1] : "";
+		part = parts[1] + "!";
+
+		return jQuery.access( this, function( value ) {
+
+			if ( value === undefined ) {
+				data = this.triggerHandler( "getData" + part, [ parts[0] ] );
+
+				// Try to fetch any internally stored data first
+				if ( data === undefined && elem ) {
+					data = jQuery.data( elem, key );
+					data = dataAttr( elem, key, data );
+				}
+
+				return data === undefined && parts[1] ?
+					this.data( parts[0] ) :
+					data;
+			}
+
+			parts[1] = value;
+			this.each(function() {
+				var self = jQuery( this );
+
+				self.triggerHandler( "setData" + part, parts );
+				jQuery.data( this, key, value );
+				self.triggerHandler( "changeData" + part, parts );
+			});
+		}, null, value, arguments.length > 1, null, false );
+	},
+
+	removeData: function( key ) {
+		return this.each(function() {
+			jQuery.removeData( this, key );
+		});
+	}
+});
+
+function dataAttr( elem, key, data ) {
+	// If nothing was found internally, try to fetch any
+	// data from the HTML5 data-* attribute
+	if ( data === undefined && elem.nodeType === 1 ) {
+
+		var name = "data-" + key.replace( rmultiDash, "-$1" ).toLowerCase();
+
+		data = elem.getAttribute( name );
+
+		if ( typeof data === "string" ) {
+			try {
+				data = data === "true" ? true :
+				data === "false" ? false :
+				data === "null" ? null :
+				jQuery.isNumeric( data ) ? +data :
+					rbrace.test( data ) ? jQuery.parseJSON( data ) :
+					data;
+			} catch( e ) {}
+
+			// Make sure we set the data so it isn't changed later
+			jQuery.data( elem, key, data );
+
+		} else {
+			data = undefined;
+		}
+	}
+
+	return data;
+}
+
+// checks a cache object for emptiness
+function isEmptyDataObject( obj ) {
+	for ( var name in obj ) {
+
+		// if the public data object is empty, the private is still empty
+		if ( name === "data" && jQuery.isEmptyObject( obj[name] ) ) {
+			continue;
+		}
+		if ( name !== "toJSON" ) {
+			return false;
+		}
+	}
+
+	return true;
+}
+
+
+
+
+function handleQueueMarkDefer( elem, type, src ) {
+	var deferDataKey = type + "defer",
+		queueDataKey = type + "queue",
+		markDataKey = type + "mark",
+		defer = jQuery._data( elem, deferDataKey );
+	if ( defer &&
+		( src === "queue" || !jQuery._data(elem, queueDataKey) ) &&
+		( src === "mark" || !jQuery._data(elem, markDataKey) ) ) {
+		// Give room for hard-coded callbacks to fire first
+		// and eventually mark/queue something else on the element
+		setTimeout( function() {
+			if ( !jQuery._data( elem, queueDataKey ) &&
+				!jQuery._data( elem, markDataKey ) ) {
+				jQuery.removeData( elem, deferDataKey, true );
+				defer.fire();
+			}
+		}, 0 );
+	}
+}
+
+jQuery.extend({
+
+	_mark: function( elem, type ) {
+		if ( elem ) {
+			type = ( type || "fx" ) + "mark";
+			jQuery._data( elem, type, (jQuery._data( elem, type ) || 0) + 1 );
+		}
+	},
+
+	_unmark: function( force, elem, type ) {
+		if ( force !== true ) {
+			type = elem;
+			elem = force;
+			force = false;
+		}
+		if ( elem ) {
+			type = type || "fx";
+			var key = type + "mark",
+				count = force ? 0 : ( (jQuery._data( elem, key ) || 1) - 1 );
+			if ( count ) {
+				jQuery._data( elem, key, count );
+			} else {
+				jQuery.removeData( elem, key, true );
+				handleQueueMarkDefer( elem, type, "mark" );
+			}
+		}
+	},
+
+	queue: function( elem, type, data ) {
+		var q;
+		if ( elem ) {
+			type = ( type || "fx" ) + "queue";
+			q = jQuery._data( elem, type );
+
+			// Speed up dequeue by getting out quickly if this is just a lookup
+			if ( data ) {
+				if ( !q || jQuery.isArray(data) ) {
+					q = jQuery._data( elem, type, jQuery.makeArray(data) );
+				} else {
+					q.push( data );
+				}
+			}
+			return q || [];
+		}
+	},
+
+	dequeue: function( elem, type ) {
+		type = type || "fx";
+
+		var queue = jQuery.queue( elem, type ),
+			fn = queue.shift(),
+			hooks = {};
+
+		// If the fx queue is dequeued, always remove the progress sentinel
+		if ( fn === "inprogress" ) {
+			fn = queue.shift();
+		}
+
+		if ( fn ) {
+			// Add a progress sentinel to prevent the fx queue from being
+			// automatically dequeued
+			if ( type === "fx" ) {
+				queue.unshift( "inprogress" );
+			}
+
+			jQuery._data( elem, type + ".run", hooks );
+			fn.call( elem, function() {
+				jQuery.dequeue( elem, type );
+			}, hooks );
+		}
+
+		if ( !queue.length ) {
+			jQuery.removeData( elem, type + "queue " + type + ".run", true );
+			handleQueueMarkDefer( elem, type, "queue" );
+		}
+	}
+});
+
+jQuery.fn.extend({
+	queue: function( type, data ) {
+		var setter = 2;
+
+		if ( typeof type !== "string" ) {
+			data = type;
+			type = "fx";
+			setter--;
+		}
+
+		if ( arguments.length < setter ) {
+			return jQuery.queue( this[0], type );
+		}
+
+		return data === undefined ?
+			this :
+			this.each(function() {
+				var queue = jQuery.queue( this, type, data );
+
+				if ( type === "fx" && queue[0] !== "inprogress" ) {
+					jQuery.dequeue( this, type );
+				}
+			});
+	},
+	dequeue: function( type ) {
+		return this.each(function() {
+			jQuery.dequeue( this, type );
+		});
+	},
+	// Based off of the plugin by Clint Helfers, with permission.
+	// http://blindsignals.com/index.php/2009/07/jquery-delay/
+	delay: function( time, type ) {
+		time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time;
+		type = type || "fx";
+
+		return this.queue( type, function( next, hooks ) {
+			var timeout = setTimeout( next, time );
+			hooks.stop = function() {
+				clearTimeout( timeout );
+			};
+		});
+	},
+	clearQueue: function( type ) {
+		return this.queue( type || "fx", [] );
+	},
+	// Get a promise resolved when queues of a certain type
+	// are emptied (fx is the type by default)
+	promise: function( type, object ) {
+		if ( typeof type !== "string" ) {
+			object = type;
+			type = undefined;
+		}
+		type = type || "fx";
+		var defer = jQuery.Deferred(),
+			elements = this,
+			i = elements.length,
+			count = 1,
+			deferDataKey = type + "defer",
+			queueDataKey = type + "queue",
+			markDataKey = type + "mark",
+			tmp;
+		function resolve() {
+			if ( !( --count ) ) {
+				defer.resolveWith( elements, [ elements ] );
+			}
+		}
+		while( i-- ) {
+			if (( tmp = jQuery.data( elements[ i ], deferDataKey, undefined, true ) ||
+					( jQuery.data( elements[ i ], queueDataKey, undefined, true ) ||
+						jQuery.data( elements[ i ], markDataKey, undefined, true ) ) &&
+					jQuery.data( elements[ i ], deferDataKey, jQuery.Callbacks( "once memory" ), true ) )) {
+				count++;
+				tmp.add( resolve );
+			}
+		}
+		resolve();
+		return defer.promise( object );
+	}
+});
+
+
+
+
+var rclass = /[\n\t\r]/g,
+	rspace = /\s+/,
+	rreturn = /\r/g,
+	rtype = /^(?:button|input)$/i,
+	rfocusable = /^(?:button|input|object|select|textarea)$/i,
+	rclickable = /^a(?:rea)?$/i,
+	rboolean = /^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i,
+	getSetAttribute = jQuery.support.getSetAttribute,
+	nodeHook, boolHook, fixSpecified;
+
+jQuery.fn.extend({
+	attr: function( name, value ) {
+		return jQuery.access( this, jQuery.attr, name, value, arguments.length > 1 );
+	},
+
+	removeAttr: function( name ) {
+		return this.each(function() {
+			jQuery.removeAttr( this, name );
+		});
+	},
+
+	prop: function( name, value ) {
+		return jQuery.access( this, jQuery.prop, name, value, arguments.length > 1 );
+	},
+
+	removeProp: function( name ) {
+		name = jQuery.propFix[ name ] || name;
+		return this.each(function() {
+			// try/catch handles cases where IE balks (such as removing a property on window)
+			try {
+				this[ name ] = undefined;
+				delete this[ name ];
+			} catch( e ) {}
+		});
+	},
+
+	addClass: function( value ) {
+		var classNames, i, l, elem,
+			setClass, c, cl;
+
+		if ( jQuery.isFunction( value ) ) {
+			return this.each(function( j ) {
+				jQuery( this ).addClass( value.call(this, j, this.className) );
+			});
+		}
+
+		if ( value && typeof value === "string" ) {
+			classNames = value.split( rspace );
+
+			for ( i = 0, l = this.length; i < l; i++ ) {
+				elem = this[ i ];
+
+				if ( elem.nodeType === 1 ) {
+					if ( !elem.className && classNames.length === 1 ) {
+						elem.className = value;
+
+					} else {
+						setClass = " " + elem.className + " ";
+
+						for ( c = 0, cl = classNames.length; c < cl; c++ ) {
+							if ( !~setClass.indexOf( " " + classNames[ c ] + " " ) ) {
+								setClass += classNames[ c ] + " ";
+							}
+						}
+						elem.className = jQuery.trim( setClass );
+					}
+				}
+			}
+		}
+
+		return this;
+	},
+
+	removeClass: function( value ) {
+		var classNames, i, l, elem, className, c, cl;
+
+		if ( jQuery.isFunction( value ) ) {
+			return this.each(function( j ) {
+				jQuery( this ).removeClass( value.call(this, j, this.className) );
+			});
+		}
+
+		if ( (value && typeof value === "string") || value === undefined ) {
+			classNames = ( value || "" ).split( rspace );
+
+			for ( i = 0, l = this.length; i < l; i++ ) {
+				elem = this[ i ];
+
+				if ( elem.nodeType === 1 && elem.className ) {
+					if ( value ) {
+						className = (" " + elem.className + " ").replace( rclass, " " );
+						for ( c = 0, cl = classNames.length; c < cl; c++ ) {
+							className = className.replace(" " + classNames[ c ] + " ", " ");
+						}
+						elem.className = jQuery.trim( className );
+
+					} else {
+						elem.className = "";
+					}
+				}
+			}
+		}
+
+		return this;
+	},
+
+	toggleClass: function( value, stateVal ) {
+		var type = typeof value,
+			isBool = typeof stateVal === "boolean";
+
+		if ( jQuery.isFunction( value ) ) {
+			return this.each(function( i ) {
+				jQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal );
+			});
+		}
+
+		return this.each(function() {
+			if ( type === "string" ) {
+				// toggle individual class names
+				var className,
+					i = 0,
+					self = jQuery( this ),
+					state = stateVal,
+					classNames = value.split( rspace );
+
+				while ( (className = classNames[ i++ ]) ) {
+					// check each className given, space seperated list
+					state = isBool ? state : !self.hasClass( className );
+					self[ state ? "addClass" : "removeClass" ]( className );
+				}
+
+			} else if ( type === "undefined" || type === "boolean" ) {
+				if ( this.className ) {
+					// store className if set
+					jQuery._data( this, "__className__", this.className );
+				}
+
+				// toggle whole className
+				this.className = this.className || value === false ? "" : jQuery._data( this, "__className__" ) || "";
+			}
+		});
+	},
+
+	hasClass: function( selector ) {
+		var className = " " + selector + " ",
+			i = 0,
+			l = this.length;
+		for ( ; i < l; i++ ) {
+			if ( this[i].nodeType === 1 && (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) > -1 ) {
+				return true;
+			}
+		}
+
+		return false;
+	},
+
+	val: function( value ) {
+		var hooks, ret, isFunction,
+			elem = this[0];
+
+		if ( !arguments.length ) {
+			if ( elem ) {
+				hooks = jQuery.valHooks[ elem.type ] || jQuery.valHooks[ elem.nodeName.toLowerCase() ];
+
+				if ( hooks && "get" in hooks && (ret = hooks.get( elem, "value" )) !== undefined ) {
+					return ret;
+				}
+
+				ret = elem.value;
+
+				return typeof ret === "string" ?
+					// handle most common string cases
+					ret.replace(rreturn, "") :
+					// handle cases where value is null/undef or number
+					ret == null ? "" : ret;
+			}
+
+			return;
+		}
+
+		isFunction = jQuery.isFunction( value );
+
+		return this.each(function( i ) {
+			var self = jQuery(this), val;
+
+			if ( this.nodeType !== 1 ) {
+				return;
+			}
+
+			if ( isFunction ) {
+				val = value.call( this, i, self.val() );
+			} else {
+				val = value;
+			}
+
+			// Treat null/undefined as ""; convert numbers to string
+			if ( val == null ) {
+				val = "";
+			} else if ( typeof val === "number" ) {
+				val += "";
+			} else if ( jQuery.isArray( val ) ) {
+				val = jQuery.map(val, function ( value ) {
+					return value == null ? "" : value + "";
+				});
+			}
+
+			hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ];
+
+			// If set returns undefined, fall back to normal setting
+			if ( !hooks || !("set" in hooks) || hooks.set( this, val, "value" ) === undefined ) {
+				this.value = val;
+			}
+		});
+	}
+});
+
+jQuery.extend({
+	valHooks: {
+		option: {
+			get: function( elem ) {
+				// attributes.value is undefined in Blackberry 4.7 but
+				// uses .value. See #6932
+				var val = elem.attributes.value;
+				return !val || val.specified ? elem.value : elem.text;
+			}
+		},
+		select: {
+			get: function( elem ) {
+				var value, i, max, option,
+					index = elem.selectedIndex,
+					values = [],
+					options = elem.options,
+					one = elem.type === "select-one";
+
+				// Nothing was selected
+				if ( index < 0 ) {
+					return null;
+				}
+
+				// Loop through all the selected options
+				i = one ? index : 0;
+				max = one ? index + 1 : options.length;
+				for ( ; i < max; i++ ) {
+					option = options[ i ];
+
+					// Don't return options that are disabled or in a disabled optgroup
+					if ( option.selected && (jQuery.support.optDisabled ? !option.disabled : option.getAttribute("disabled") === null) &&
+							(!option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" )) ) {
+
+						// Get the specific value for the option
+						value = jQuery( option ).val();
+
+						// We don't need an array for one selects
+						if ( one ) {
+							return value;
+						}
+
+						// Multi-Selects return an array
+						values.push( value );
+					}
+				}
+
+				// Fixes Bug #2551 -- select.val() broken in IE after form.reset()
+				if ( one && !values.length && options.length ) {
+					return jQuery( options[ index ] ).val();
+				}
+
+				return values;
+			},
+
+			set: function( elem, value ) {
+				var values = jQuery.makeArray( value );
+
+				jQuery(elem).find("option").each(function() {
+					this.selected = jQuery.inArray( jQuery(this).val(), values ) >= 0;
+				});
+
+				if ( !values.length ) {
+					elem.selectedIndex = -1;
+				}
+				return values;
+			}
+		}
+	},
+
+	attrFn: {
+		val: true,
+		css: true,
+		html: true,
+		text: true,
+		data: true,
+		width: true,
+		height: true,
+		offset: true
+	},
+
+	attr: function( elem, name, value, pass ) {
+		var ret, hooks, notxml,
+			nType = elem.nodeType;
+
+		// don't get/set attributes on text, comment and attribute nodes
+		if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
+			return;
+		}
+
+		if ( pass && name in jQuery.attrFn ) {
+			return jQuery( elem )[ name ]( value );
+		}
+
+		// Fallback to prop when attributes are not supported
+		if ( typeof elem.getAttribute === "undefined" ) {
+			return jQuery.prop( elem, name, value );
+		}
+
+		notxml = nType !== 1 || !jQuery.isXMLDoc( elem );
+
+		// All attributes are lowercase
+		// Grab necessary hook if one is defined
+		if ( notxml ) {
+			name = name.toLowerCase();
+			hooks = jQuery.attrHooks[ name ] || ( rboolean.test( name ) ? boolHook : nodeHook );
+		}
+
+		if ( value !== undefined ) {
+
+			if ( value === null ) {
+				jQuery.removeAttr( elem, name );
+				return;
+
+			} else if ( hooks && "set" in hooks && notxml && (ret = hooks.set( elem, value, name )) !== undefined ) {
+				return ret;
+
+			} else {
+				elem.setAttribute( name, "" + value );
+				return value;
+			}
+
+		} else if ( hooks && "get" in hooks && notxml && (ret = hooks.get( elem, name )) !== null ) {
+			return ret;
+
+		} else {
+
+			ret = elem.getAttribute( name );
+
+			// Non-existent attributes return null, we normalize to undefined
+			return ret === null ?
+				undefined :
+				ret;
+		}
+	},
+
+	removeAttr: function( elem, value ) {
+		var propName, attrNames, name, l, isBool,
+			i = 0;
+
+		if ( value && elem.nodeType === 1 ) {
+			attrNames = value.toLowerCase().split( rspace );
+			l = attrNames.length;
+
+			for ( ; i < l; i++ ) {
+				name = attrNames[ i ];
+
+				if ( name ) {
+					propName = jQuery.propFix[ name ] || name;
+					isBool = rboolean.test( name );
+
+					// See #9699 for explanation of this approach (setting first, then removal)
+					// Do not do this for boolean attributes (see #10870)
+					if ( !isBool ) {
+						jQuery.attr( elem, name, "" );
+					}
+					elem.removeAttribute( getSetAttribute ? name : propName );
+
+					// Set corresponding property to false for boolean attributes
+					if ( isBool && propName in elem ) {
+						elem[ propName ] = false;
+					}
+				}
+			}
+		}
+	},
+
+	attrHooks: {
+		type: {
+			set: function( elem, value ) {
+				// We can't allow the type property to be changed (since it causes problems in IE)
+				if ( rtype.test( elem.nodeName ) && elem.parentNode ) {
+					jQuery.error( "type property can't be changed" );
+				} else if ( !jQuery.support.radioValue && value === "radio" && jQuery.nodeName(elem, "input") ) {
+					// Setting the type on a radio button after the value resets the value in IE6-9
+					// Reset value to it's default in case type is set after value
+					// This is for element creation
+					var val = elem.value;
+					elem.setAttribute( "type", value );
+					if ( val ) {
+						elem.value = val;
+					}
+					return value;
+				}
+			}
+		},
+		// Use the value property for back compat
+		// Use the nodeHook for button elements in IE6/7 (#1954)
+		value: {
+			get: function( elem, name ) {
+				if ( nodeHook && jQuery.nodeName( elem, "button" ) ) {
+					return nodeHook.get( elem, name );
+				}
+				return name in elem ?
+					elem.value :
+					null;
+			},
+			set: function( elem, value, name ) {
+				if ( nodeHook && jQuery.nodeName( elem, "button" ) ) {
+					return nodeHook.set( elem, value, name );
+				}
+				// Does not return so that setAttribute is also used
+				elem.value = value;
+			}
+		}
+	},
+
+	propFix: {
+		tabindex: "tabIndex",
+		readonly: "readOnly",
+		"for": "htmlFor",
+		"class": "className",
+		maxlength: "maxLength",
+		cellspacing: "cellSpacing",
+		cellpadding: "cellPadding",
+		rowspan: "rowSpan",
+		colspan: "colSpan",
+		usemap: "useMap",
+		frameborder: "frameBorder",
+		contenteditable: "contentEditable"
+	},
+
+	prop: function( elem, name, value ) {
+		var ret, hooks, notxml,
+			nType = elem.nodeType;
+
+		// don't get/set properties on text, comment and attribute nodes
+		if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
+			return;
+		}
+
+		notxml = nType !== 1 || !jQuery.isXMLDoc( elem );
+
+		if ( notxml ) {
+			// Fix name and attach hooks
+			name = jQuery.propFix[ name ] || name;
+			hooks = jQuery.propHooks[ name ];
+		}
+
+		if ( value !== undefined ) {
+			if ( hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) {
+				return ret;
+
+			} else {
+				return ( elem[ name ] = value );
+			}
+
+		} else {
+			if ( hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ) {
+				return ret;
+
+			} else {
+				return elem[ name ];
+			}
+		}
+	},
+
+	propHooks: {
+		tabIndex: {
+			get: function( elem ) {
+				// elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set
+				// http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/
+				var attributeNode = elem.getAttributeNode("tabindex");
+
+				return attributeNode && attributeNode.specified ?
+					parseInt( attributeNode.value, 10 ) :
+					rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ?
+						0 :
+						undefined;
+			}
+		}
+	}
+});
+
+// Add the tabIndex propHook to attrHooks for back-compat (different case is intentional)
+jQuery.attrHooks.tabindex = jQuery.propHooks.tabIndex;
+
+// Hook for boolean attributes
+boolHook = {
+	get: function( elem, name ) {
+		// Align boolean attributes with corresponding properties
+		// Fall back to attribute presence where some booleans are not supported
+		var attrNode,
+			property = jQuery.prop( elem, name );
+		return property === true || typeof property !== "boolean" && ( attrNode = elem.getAttributeNode(name) ) && attrNode.nodeValue !== false ?
+			name.toLowerCase() :
+			undefined;
+	},
+	set: function( elem, value, name ) {
+		var propName;
+		if ( value === false ) {
+			// Remove boolean attributes when set to false
+			jQuery.removeAttr( elem, name );
+		} else {
+			// value is true since we know at this point it's type boolean and not false
+			// Set boolean attributes to the same name and set the DOM property
+			propName = jQuery.propFix[ name ] || name;
+			if ( propName in elem ) {
+				// Only set the IDL specifically if it already exists on the element
+				elem[ propName ] = true;
+			}
+
+			elem.setAttribute( name, name.toLowerCase() );
+		}
+		return name;
+	}
+};
+
+// IE6/7 do not support getting/setting some attributes with get/setAttribute
+if ( !getSetAttribute ) {
+
+	fixSpecified = {
+		name: true,
+		id: true,
+		coords: true
+	};
+
+	// Use this for any attribute in IE6/7
+	// This fixes almost every IE6/7 issue
+	nodeHook = jQuery.valHooks.button = {
+		get: function( elem, name ) {
+			var ret;
+			ret = elem.getAttributeNode( name );
+			return ret && ( fixSpecified[ name ] ? ret.nodeValue !== "" : ret.specified ) ?
+				ret.nodeValue :
+				undefined;
+		},
+		set: function( elem, value, name ) {
+			// Set the existing or create a new attribute node
+			var ret = elem.getAttributeNode( name );
+			if ( !ret ) {
+				ret = document.createAttribute( name );
+				elem.setAttributeNode( ret );
+			}
+			return ( ret.nodeValue = value + "" );
+		}
+	};
+
+	// Apply the nodeHook to tabindex
+	jQuery.attrHooks.tabindex.set = nodeHook.set;
+
+	// Set width and height to auto instead of 0 on empty string( Bug #8150 )
+	// This is for removals
+	jQuery.each([ "width", "height" ], function( i, name ) {
+		jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], {
+			set: function( elem, value ) {
+				if ( value === "" ) {
+					elem.setAttribute( name, "auto" );
+					return value;
+				}
+			}
+		});
+	});
+
+	// Set contenteditable to false on removals(#10429)
+	// Setting to empty string throws an error as an invalid value
+	jQuery.attrHooks.contenteditable = {
+		get: nodeHook.get,
+		set: function( elem, value, name ) {
+			if ( value === "" ) {
+				value = "false";
+			}
+			nodeHook.set( elem, value, name );
+		}
+	};
+}
+
+
+// Some attributes require a special call on IE
+if ( !jQuery.support.hrefNormalized ) {
+	jQuery.each([ "href", "src", "width", "height" ], function( i, name ) {
+		jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], {
+			get: function( elem ) {
+				var ret = elem.getAttribute( name, 2 );
+				return ret === null ? undefined : ret;
+			}
+		});
+	});
+}
+
+if ( !jQuery.support.style ) {
+	jQuery.attrHooks.style = {
+		get: function( elem ) {
+			// Return undefined in the case of empty string
+			// Normalize to lowercase since IE uppercases css property names
+			return elem.style.cssText.toLowerCase() || undefined;
+		},
+		set: function( elem, value ) {
+			return ( elem.style.cssText = "" + value );
+		}
+	};
+}
+
+// Safari mis-reports the default selected property of an option
+// Accessing the parent's selectedIndex property fixes it
+if ( !jQuery.support.optSelected ) {
+	jQuery.propHooks.selected = jQuery.extend( jQuery.propHooks.selected, {
+		get: function( elem ) {
+			var parent = elem.parentNode;
+
+			if ( parent ) {
+				parent.selectedIndex;
+
+				// Make sure that it also works with optgroups, see #5701
+				if ( parent.parentNode ) {
+					parent.parentNode.selectedIndex;
+				}
+			}
+			return null;
+		}
+	});
+}
+
+// IE6/7 call enctype encoding
+if ( !jQuery.support.enctype ) {
+	jQuery.propFix.enctype = "encoding";
+}
+
+// Radios and checkboxes getter/setter
+if ( !jQuery.support.checkOn ) {
+	jQuery.each([ "radio", "checkbox" ], function() {
+		jQuery.valHooks[ this ] = {
+			get: function( elem ) {
+				// Handle the case where in Webkit "" is returned instead of "on" if a value isn't specified
+				return elem.getAttribute("value") === null ? "on" : elem.value;
+			}
+		};
+	});
+}
+jQuery.each([ "radio", "checkbox" ], function() {
+	jQuery.valHooks[ this ] = jQuery.extend( jQuery.valHooks[ this ], {
+		set: function( elem, value ) {
+			if ( jQuery.isArray( value ) ) {
+				return ( elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0 );
+			}
+		}
+	});
+});
+
+
+
+
+var rformElems = /^(?:textarea|input|select)$/i,
+	rtypenamespace = /^([^\.]*)?(?:\.(.+))?$/,
+	rhoverHack = /(?:^|\s)hover(\.\S+)?\b/,
+	rkeyEvent = /^key/,
+	rmouseEvent = /^(?:mouse|contextmenu)|click/,
+	rfocusMorph = /^(?:focusinfocus|focusoutblur)$/,
+	rquickIs = /^(\w*)(?:#([\w\-]+))?(?:\.([\w\-]+))?$/,
+	quickParse = function( selector ) {
+		var quick = rquickIs.exec( selector );
+		if ( quick ) {
+			//   0  1    2   3
+			// [ _, tag, id, class ]
+			quick[1] = ( quick[1] || "" ).toLowerCase();
+			quick[3] = quick[3] && new RegExp( "(?:^|\\s)" + quick[3] + "(?:\\s|$)" );
+		}
+		return quick;
+	},
+	quickIs = function( elem, m ) {
+		var attrs = elem.attributes || {};
+		return (
+			(!m[1] || elem.nodeName.toLowerCase() === m[1]) &&
+			(!m[2] || (attrs.id || {}).value === m[2]) &&
+			(!m[3] || m[3].test( (attrs[ "class" ] || {}).value ))
+		);
+	},
+	hoverHack = function( events ) {
+		return jQuery.event.special.hover ? events : events.replace( rhoverHack, "mouseenter$1 mouseleave$1" );
+	};
+
+/*
+ * Helper functions for managing events -- not part of the public interface.
+ * Props to Dean Edwards' addEvent library for many of the ideas.
+ */
+jQuery.event = {
+
+	add: function( elem, types, handler, data, selector ) {
+
+		var elemData, eventHandle, events,
+			t, tns, type, namespaces, handleObj,
+			handleObjIn, quick, handlers, special;
+
+		// Don't attach events to noData or text/comment nodes (allow plain objects tho)
+		if ( elem.nodeType === 3 || elem.nodeType === 8 || !types || !handler || !(elemData = jQuery._data( elem )) ) {
+			return;
+		}
+
+		// Caller can pass in an object of custom data in lieu of the handler
+		if ( handler.handler ) {
+			handleObjIn = handler;
+			handler = handleObjIn.handler;
+			selector = handleObjIn.selector;
+		}
+
+		// Make sure that the handler has a unique ID, used to find/remove it later
+		if ( !handler.guid ) {
+			handler.guid = jQuery.guid++;
+		}
+
+		// Init the element's event structure and main handler, if this is the first
+		events = elemData.events;
+		if ( !events ) {
+			elemData.events = events = {};
+		}
+		eventHandle = elemData.handle;
+		if ( !eventHandle ) {
+			elemData.handle = eventHandle = function( e ) {
+				// Discard the second event of a jQuery.event.trigger() and
+				// when an event is called after a page has unloaded
+				return typeof jQuery !== "undefined" && (!e || jQuery.event.triggered !== e.type) ?
+					jQuery.event.dispatch.apply( eventHandle.elem, arguments ) :
+					undefined;
+			};
+			// Add elem as a property of the handle fn to prevent a memory leak with IE non-native events
+			eventHandle.elem = elem;
+		}
+
+		// Handle multiple events separated by a space
+		// jQuery(...).bind("mouseover mouseout", fn);
+		types = jQuery.trim( hoverHack(types) ).split( " " );
+		for ( t = 0; t < types.length; t++ ) {
+
+			tns = rtypenamespace.exec( types[t] ) || [];
+			type = tns[1];
+			namespaces = ( tns[2] || "" ).split( "." ).sort();
+
+			// If event changes its type, use the special event handlers for the changed type
+			special = jQuery.event.special[ type ] || {};
+
+			// If selector defined, determine special event api type, otherwise given type
+			type = ( selector ? special.delegateType : special.bindType ) || type;
+
+			// Update special based on newly reset type
+			special = jQuery.event.special[ type ] || {};
+
+			// handleObj is passed to all event handlers
+			handleObj = jQuery.extend({
+				type: type,
+				origType: tns[1],
+				data: data,
+				handler: handler,
+				guid: handler.guid,
+				selector: selector,
+				quick: selector && quickParse( selector ),
+				namespace: namespaces.join(".")
+			}, handleObjIn );
+
+			// Init the event handler queue if we're the first
+			handlers = events[ type ];
+			if ( !handlers ) {
+				handlers = events[ type ] = [];
+				handlers.delegateCount = 0;
+
+				// Only use addEventListener/attachEvent if the special events handler returns false
+				if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) {
+					// Bind the global event handler to the element
+					if ( elem.addEventListener ) {
+						elem.addEventListener( type, eventHandle, false );
+
+					} else if ( elem.attachEvent ) {
+						elem.attachEvent( "on" + type, eventHandle );
+					}
+				}
+			}
+
+			if ( special.add ) {
+				special.add.call( elem, handleObj );
+
+				if ( !handleObj.handler.guid ) {
+					handleObj.handler.guid = handler.guid;
+				}
+			}
+
+			// Add to the element's handler list, delegates in front
+			if ( selector ) {
+				handlers.splice( handlers.delegateCount++, 0, handleObj );
+			} else {
+				handlers.push( handleObj );
+			}
+
+			// Keep track of which events have ever been used, for event optimization
+			jQuery.event.global[ type ] = true;
+		}
+
+		// Nullify elem to prevent memory leaks in IE
+		elem = null;
+	},
+
+	global: {},
+
+	// Detach an event or set of events from an element
+	remove: function( elem, types, handler, selector, mappedTypes ) {
+
+		var elemData = jQuery.hasData( elem ) && jQuery._data( elem ),
+			t, tns, type, origType, namespaces, origCount,
+			j, events, special, handle, eventType, handleObj;
+
+		if ( !elemData || !(events = elemData.events) ) {
+			return;
+		}
+
+		// Once for each type.namespace in types; type may be omitted
+		types = jQuery.trim( hoverHack( types || "" ) ).split(" ");
+		for ( t = 0; t < types.length; t++ ) {
+			tns = rtypenamespace.exec( types[t] ) || [];
+			type = origType = tns[1];
+			namespaces = tns[2];
+
+			// Unbind all events (on this namespace, if provided) for the element
+			if ( !type ) {
+				for ( type in events ) {
+					jQuery.event.remove( elem, type + types[ t ], handler, selector, true );
+				}
+				continue;
+			}
+
+			special = jQuery.event.special[ type ] || {};
+			type = ( selector? special.delegateType : special.bindType ) || type;
+			eventType = events[ type ] || [];
+			origCount = eventType.length;
+			namespaces = namespaces ? new RegExp("(^|\\.)" + namespaces.split(".").sort().join("\\.(?:.*\\.)?") + "(\\.|$)") : null;
+
+			// Remove matching events
+			for ( j = 0; j < eventType.length; j++ ) {
+				handleObj = eventType[ j ];
+
+				if ( ( mappedTypes || origType === handleObj.origType ) &&
+					 ( !handler || handler.guid === handleObj.guid ) &&
+					 ( !namespaces || namespaces.test( handleObj.namespace ) ) &&
+					 ( !selector || selector === handleObj.selector || selector === "**" && handleObj.selector ) ) {
+					eventType.splice( j--, 1 );
+
+					if ( handleObj.selector ) {
+						eventType.delegateCount--;
+					}
+					if ( special.remove ) {
+						special.remove.call( elem, handleObj );
+					}
+				}
+			}
+
+			// Remove generic event handler if we removed something and no more handlers exist
+			// (avoids potential for endless recursion during removal of special event handlers)
+			if ( eventType.length === 0 && origCount !== eventType.length ) {
+				if ( !special.teardown || special.teardown.call( elem, namespaces ) === false ) {
+					jQuery.removeEvent( elem, type, elemData.handle );
+				}
+
+				delete events[ type ];
+			}
+		}
+
+		// Remove the expando if it's no longer used
+		if ( jQuery.isEmptyObject( events ) ) {
+			handle = elemData.handle;
+			if ( handle ) {
+				handle.elem = null;
+			}
+
+			// removeData also checks for emptiness and clears the expando if empty
+			// so use it instead of delete
+			jQuery.removeData( elem, [ "events", "handle" ], true );
+		}
+	},
+
+	// Events that are safe to short-circuit if no handlers are attached.
+	// Native DOM events should not be added, they may have inline handlers.
+	customEvent: {
+		"getData": true,
+		"setData": true,
+		"changeData": true
+	},
+
+	trigger: function( event, data, elem, onlyHandlers ) {
+		// Don't do events on text and comment nodes
+		if ( elem && (elem.nodeType === 3 || elem.nodeType === 8) ) {
+			return;
+		}
+
+		// Event object or event type
+		var type = event.type || event,
+			namespaces = [],
+			cache, exclusive, i, cur, old, ontype, special, handle, eventPath, bubbleType;
+
+		// focus/blur morphs to focusin/out; ensure we're not firing them right now
+		if ( rfocusMorph.test( type + jQuery.event.triggered ) ) {
+			return;
+		}
+
+		if ( type.indexOf( "!" ) >= 0 ) {
+			// Exclusive events trigger only for the exact event (no namespaces)
+			type = type.slice(0, -1);
+			exclusive = true;
+		}
+
+		if ( type.indexOf( "." ) >= 0 ) {
+			// Namespaced trigger; create a regexp to match event type in handle()
+			namespaces = type.split(".");
+			type = namespaces.shift();
+			namespaces.sort();
+		}
+
+		if ( (!elem || jQuery.event.customEvent[ type ]) && !jQuery.event.global[ type ] ) {
+			// No jQuery handlers for this event type, and it can't have inline handlers
+			return;
+		}
+
+		// Caller can pass in an Event, Object, or just an event type string
+		event = typeof event === "object" ?
+			// jQuery.Event object
+			event[ jQuery.expando ] ? event :
+			// Object literal
+			new jQuery.Event( type, event ) :
+			// Just the event type (string)
+			new jQuery.Event( type );
+
+		event.type = type;
+		event.isTrigger = true;
+		event.exclusive = exclusive;
+		event.namespace = namespaces.join( "." );
+		event.namespace_re = event.namespace? new RegExp("(^|\\.)" + namespaces.join("\\.(?:.*\\.)?") + "(\\.|$)") : null;
+		ontype = type.indexOf( ":" ) < 0 ? "on" + type : "";
+
+		// Handle a global trigger
+		if ( !elem ) {
+
+			// TODO: Stop taunting the data cache; remove global events and always attach to document
+			cache = jQuery.cache;
+			for ( i in cache ) {
+				if ( cache[ i ].events && cache[ i ].events[ type ] ) {
+					jQuery.event.trigger( event, data, cache[ i ].handle.elem, true );
+				}
+			}
+			return;
+		}
+
+		// Cle

<TRUNCATED>
http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/test/lib/angular/version.txt
----------------------------------------------------------------------
diff --git a/src/main/ui/test/lib/angular/version.txt b/src/main/ui/test/lib/angular/version.txt
new file mode 100755
index 0000000..90a27f9
--- /dev/null
+++ b/src/main/ui/test/lib/angular/version.txt
@@ -0,0 +1 @@
+1.0.5


[09/51] [abbrv] [partial] Adding Jinwon's custom RCMET

Posted by jo...@apache.org.
http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/test/unit/.svn/all-wcprops
----------------------------------------------------------------------
diff --git a/src/main/ui/test/unit/.svn/all-wcprops b/src/main/ui/test/unit/.svn/all-wcprops
new file mode 100755
index 0000000..02131ff
--- /dev/null
+++ b/src/main/ui/test/unit/.svn/all-wcprops
@@ -0,0 +1,29 @@
+K 25
+svn:wc:ra_dav:version-url
+V 79
+/repos/asf/!svn/ver/1480068/incubator/climate/trunk/rcmet/src/main/ui/test/unit
+END
+directivesSpec.js
+K 25
+svn:wc:ra_dav:version-url
+V 97
+/repos/asf/!svn/ver/1480068/incubator/climate/trunk/rcmet/src/main/ui/test/unit/directivesSpec.js
+END
+servicesSpec.js
+K 25
+svn:wc:ra_dav:version-url
+V 95
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/ui/test/unit/servicesSpec.js
+END
+controllersSpec.js
+K 25
+svn:wc:ra_dav:version-url
+V 98
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/ui/test/unit/controllersSpec.js
+END
+filtersSpec.js
+K 25
+svn:wc:ra_dav:version-url
+V 94
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/ui/test/unit/filtersSpec.js
+END

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/test/unit/.svn/entries
----------------------------------------------------------------------
diff --git a/src/main/ui/test/unit/.svn/entries b/src/main/ui/test/unit/.svn/entries
new file mode 100755
index 0000000..a7392cb
--- /dev/null
+++ b/src/main/ui/test/unit/.svn/entries
@@ -0,0 +1,164 @@
+10
+
+dir
+1485921
+https://svn.apache.org/repos/asf/incubator/climate/trunk/rcmet/src/main/ui/test/unit
+https://svn.apache.org/repos/asf
+
+
+
+2013-05-07T20:50:17.582309Z
+1480068
+joyce
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+13f79535-47bb-0310-9956-ffa450edef68
+
+directivesSpec.js
+file
+
+
+
+
+2013-05-24T10:13:55.000000Z
+f88c3770e99a824db7558b7005e7eaaf
+2013-05-07T20:50:17.582309Z
+1480068
+joyce
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+1297
+
+servicesSpec.js
+file
+
+
+
+
+2013-05-24T10:13:55.000000Z
+cc3e85c89433b8f4c8fecc58792ca666
+2013-03-13T02:34:45.561716Z
+1475145
+mjjoyce
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+331
+
+controllersSpec.js
+file
+
+
+
+
+2013-05-24T10:13:55.000000Z
+8a2008f2d6598af9b85d31eaa0620141
+2013-03-25T17:12:07.323566Z
+1475248
+mjjoyce
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+1367
+
+filtersSpec.js
+file
+
+
+
+
+2013-05-24T10:13:55.000000Z
+5c57870ff7bc7a8a819880bc0c0dbab6
+2013-03-13T02:34:45.561716Z
+1475145
+mjjoyce
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+487
+

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/test/unit/.svn/prop-base/controllersSpec.js.svn-base
----------------------------------------------------------------------
diff --git a/src/main/ui/test/unit/.svn/prop-base/controllersSpec.js.svn-base b/src/main/ui/test/unit/.svn/prop-base/controllersSpec.js.svn-base
new file mode 100755
index 0000000..869ac71
--- /dev/null
+++ b/src/main/ui/test/unit/.svn/prop-base/controllersSpec.js.svn-base
@@ -0,0 +1,5 @@
+K 14
+svn:executable
+V 1
+*
+END

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/test/unit/.svn/prop-base/directivesSpec.js.svn-base
----------------------------------------------------------------------
diff --git a/src/main/ui/test/unit/.svn/prop-base/directivesSpec.js.svn-base b/src/main/ui/test/unit/.svn/prop-base/directivesSpec.js.svn-base
new file mode 100755
index 0000000..869ac71
--- /dev/null
+++ b/src/main/ui/test/unit/.svn/prop-base/directivesSpec.js.svn-base
@@ -0,0 +1,5 @@
+K 14
+svn:executable
+V 1
+*
+END

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/test/unit/.svn/prop-base/filtersSpec.js.svn-base
----------------------------------------------------------------------
diff --git a/src/main/ui/test/unit/.svn/prop-base/filtersSpec.js.svn-base b/src/main/ui/test/unit/.svn/prop-base/filtersSpec.js.svn-base
new file mode 100755
index 0000000..869ac71
--- /dev/null
+++ b/src/main/ui/test/unit/.svn/prop-base/filtersSpec.js.svn-base
@@ -0,0 +1,5 @@
+K 14
+svn:executable
+V 1
+*
+END

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/test/unit/.svn/prop-base/servicesSpec.js.svn-base
----------------------------------------------------------------------
diff --git a/src/main/ui/test/unit/.svn/prop-base/servicesSpec.js.svn-base b/src/main/ui/test/unit/.svn/prop-base/servicesSpec.js.svn-base
new file mode 100755
index 0000000..869ac71
--- /dev/null
+++ b/src/main/ui/test/unit/.svn/prop-base/servicesSpec.js.svn-base
@@ -0,0 +1,5 @@
+K 14
+svn:executable
+V 1
+*
+END

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/test/unit/.svn/text-base/controllersSpec.js.svn-base
----------------------------------------------------------------------
diff --git a/src/main/ui/test/unit/.svn/text-base/controllersSpec.js.svn-base b/src/main/ui/test/unit/.svn/text-base/controllersSpec.js.svn-base
new file mode 100755
index 0000000..527d1bc
--- /dev/null
+++ b/src/main/ui/test/unit/.svn/text-base/controllersSpec.js.svn-base
@@ -0,0 +1,44 @@
+'use strict';
+
+/* jasmine specs for controllers go here */
+
+describe('RCMES Controllers', function() {
+
+	describe('ParameterSelectCtrl', function() {
+		it('should create a ParameterSelectCtrl with 0 datasets', function() {
+			var scope = {},
+				ctrl = new ParameterSelectCtrl(scope);
+
+				expect(scope.numberOfDatasets).toBe(0);
+		});
+
+		it('should not activate controls unless there are at least 2 datasets', function() {
+			var scope = {},
+				ctrl = new ParameterSelectCtrl(scope);
+
+				// Test default case of 0 datasets
+				expect(scope.shouldDisableControls()).toBe(true);
+
+				// Push up to the minimum number of datasets and test validity
+				scope.numberOfDatasets = 2;
+				expect(scope.shouldDisableControls()).toBe(false);
+		});
+	});
+
+	describe('ObservationSelectCtrl', function() {
+		it('should initialize observation variable parameters correctly', function() {
+			var scope = {},
+				ctrl = new ObservationSelectCtrl(scope);
+
+				expect(scope.params.length).toBe(1);
+				expect(scope.lats.length).toBe(1);
+				expect(scope.lons.length).toBe(1);
+				expect(scope.times.length).toBe(1);
+
+				expect(scope.params[0]).toBe("Please select a file above");
+				expect(scope.lats[0]).toBe("Please select a file above");
+				expect(scope.lons[0]).toBe("Please select a file above");
+				expect(scope.times[0]).toBe("Please select a file above");
+		});
+	});
+});

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/test/unit/.svn/text-base/directivesSpec.js.svn-base
----------------------------------------------------------------------
diff --git a/src/main/ui/test/unit/.svn/text-base/directivesSpec.js.svn-base b/src/main/ui/test/unit/.svn/text-base/directivesSpec.js.svn-base
new file mode 100755
index 0000000..c7d20b6
--- /dev/null
+++ b/src/main/ui/test/unit/.svn/text-base/directivesSpec.js.svn-base
@@ -0,0 +1,36 @@
+'use strict';
+
+describe('directives', function() {
+	beforeEach(module('rcmes'));
+
+	// Testing Leaflet map directive
+	/*
+	describe('Testing Leaflet map directive', function() {
+		it('should create the leaflet dir for proper injection into the page', function() {
+			inject(function($compile, $rootScope) {
+				var element = $compile('<sap id="map"></sap>')($rootScope);
+				expect(element.className).toBe('leaflet-container leaflet-fade-anim');
+			})
+		});
+	});
+	//*/
+	
+	// Testing the Bootstrap Modal directive
+	describe('bootstrap-modal directive', function() {
+		it('should create a div element of the correct form', function() {
+			inject(function($compile, $rootScope) {
+				var element = $compile('<bootstrap-modal modal-id="testmodal"></bootstrap-modal>')($rootScope);
+				expect(element.hasClass("modal")).toBeTruthy();
+				expect(element.hasClass("hide")).toBeTruthy();
+				expect(element.attr("id")).toEqual('{{modalId}}');
+			});
+		});
+
+		it('should properly wrap the interior html content' , function() {
+			inject(function($compile, $rootScope) {
+				var element = $compile('<bootstrap-modal modal-id="testmodal"><h3>Hello</h3></bootstrap-modal>')($rootScope);
+				expect(element.html()).toEqual("<div ng-transclude=\"\"><h3 class=\"ng-scope\">Hello</h3></div>");
+			})
+		});
+	});
+});

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/test/unit/.svn/text-base/filtersSpec.js.svn-base
----------------------------------------------------------------------
diff --git a/src/main/ui/test/unit/.svn/text-base/filtersSpec.js.svn-base b/src/main/ui/test/unit/.svn/text-base/filtersSpec.js.svn-base
new file mode 100755
index 0000000..cba9096
--- /dev/null
+++ b/src/main/ui/test/unit/.svn/text-base/filtersSpec.js.svn-base
@@ -0,0 +1,22 @@
+'use strict';
+
+/* jasmine specs for filters go here */
+
+/* Example code for filter tests
+ *
+describe('filter', function() {
+  beforeEach(module('myApp.filters'));
+
+
+  describe('interpolate', function() {
+    beforeEach(module(function($provide) {
+      $provide.value('version', 'TEST_VER');
+    }));
+
+
+    it('should replace VERSION', inject(function(interpolateFilter) {
+      expect(interpolateFilter('before %VERSION% after')).toEqual('before TEST_VER after');
+    }));
+  });
+});
+*/

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/test/unit/.svn/text-base/servicesSpec.js.svn-base
----------------------------------------------------------------------
diff --git a/src/main/ui/test/unit/.svn/text-base/servicesSpec.js.svn-base b/src/main/ui/test/unit/.svn/text-base/servicesSpec.js.svn-base
new file mode 100755
index 0000000..a2110b4
--- /dev/null
+++ b/src/main/ui/test/unit/.svn/text-base/servicesSpec.js.svn-base
@@ -0,0 +1,17 @@
+'use strict';
+
+/* jasmine specs for services go here */
+
+/* Example code for service tests
+ *
+describe('service', function() {
+  beforeEach(module('myApp.services'));
+
+
+  describe('version', function() {
+    it('should return current version', inject(function(version) {
+      expect(version).toEqual('0.1');
+    }));
+  });
+});
+*/

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/test/unit/controllersSpec.js
----------------------------------------------------------------------
diff --git a/src/main/ui/test/unit/controllersSpec.js b/src/main/ui/test/unit/controllersSpec.js
new file mode 100755
index 0000000..527d1bc
--- /dev/null
+++ b/src/main/ui/test/unit/controllersSpec.js
@@ -0,0 +1,44 @@
+'use strict';
+
+/* jasmine specs for controllers go here */
+
+describe('RCMES Controllers', function() {
+
+	describe('ParameterSelectCtrl', function() {
+		it('should create a ParameterSelectCtrl with 0 datasets', function() {
+			var scope = {},
+				ctrl = new ParameterSelectCtrl(scope);
+
+				expect(scope.numberOfDatasets).toBe(0);
+		});
+
+		it('should not activate controls unless there are at least 2 datasets', function() {
+			var scope = {},
+				ctrl = new ParameterSelectCtrl(scope);
+
+				// Test default case of 0 datasets
+				expect(scope.shouldDisableControls()).toBe(true);
+
+				// Push up to the minimum number of datasets and test validity
+				scope.numberOfDatasets = 2;
+				expect(scope.shouldDisableControls()).toBe(false);
+		});
+	});
+
+	describe('ObservationSelectCtrl', function() {
+		it('should initialize observation variable parameters correctly', function() {
+			var scope = {},
+				ctrl = new ObservationSelectCtrl(scope);
+
+				expect(scope.params.length).toBe(1);
+				expect(scope.lats.length).toBe(1);
+				expect(scope.lons.length).toBe(1);
+				expect(scope.times.length).toBe(1);
+
+				expect(scope.params[0]).toBe("Please select a file above");
+				expect(scope.lats[0]).toBe("Please select a file above");
+				expect(scope.lons[0]).toBe("Please select a file above");
+				expect(scope.times[0]).toBe("Please select a file above");
+		});
+	});
+});

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/test/unit/directivesSpec.js
----------------------------------------------------------------------
diff --git a/src/main/ui/test/unit/directivesSpec.js b/src/main/ui/test/unit/directivesSpec.js
new file mode 100755
index 0000000..c7d20b6
--- /dev/null
+++ b/src/main/ui/test/unit/directivesSpec.js
@@ -0,0 +1,36 @@
+'use strict';
+
+describe('directives', function() {
+	beforeEach(module('rcmes'));
+
+	// Testing Leaflet map directive
+	/*
+	describe('Testing Leaflet map directive', function() {
+		it('should create the leaflet dir for proper injection into the page', function() {
+			inject(function($compile, $rootScope) {
+				var element = $compile('<sap id="map"></sap>')($rootScope);
+				expect(element.className).toBe('leaflet-container leaflet-fade-anim');
+			})
+		});
+	});
+	//*/
+	
+	// Testing the Bootstrap Modal directive
+	describe('bootstrap-modal directive', function() {
+		it('should create a div element of the correct form', function() {
+			inject(function($compile, $rootScope) {
+				var element = $compile('<bootstrap-modal modal-id="testmodal"></bootstrap-modal>')($rootScope);
+				expect(element.hasClass("modal")).toBeTruthy();
+				expect(element.hasClass("hide")).toBeTruthy();
+				expect(element.attr("id")).toEqual('{{modalId}}');
+			});
+		});
+
+		it('should properly wrap the interior html content' , function() {
+			inject(function($compile, $rootScope) {
+				var element = $compile('<bootstrap-modal modal-id="testmodal"><h3>Hello</h3></bootstrap-modal>')($rootScope);
+				expect(element.html()).toEqual("<div ng-transclude=\"\"><h3 class=\"ng-scope\">Hello</h3></div>");
+			})
+		});
+	});
+});

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/test/unit/filtersSpec.js
----------------------------------------------------------------------
diff --git a/src/main/ui/test/unit/filtersSpec.js b/src/main/ui/test/unit/filtersSpec.js
new file mode 100755
index 0000000..cba9096
--- /dev/null
+++ b/src/main/ui/test/unit/filtersSpec.js
@@ -0,0 +1,22 @@
+'use strict';
+
+/* jasmine specs for filters go here */
+
+/* Example code for filter tests
+ *
+describe('filter', function() {
+  beforeEach(module('myApp.filters'));
+
+
+  describe('interpolate', function() {
+    beforeEach(module(function($provide) {
+      $provide.value('version', 'TEST_VER');
+    }));
+
+
+    it('should replace VERSION', inject(function(interpolateFilter) {
+      expect(interpolateFilter('before %VERSION% after')).toEqual('before TEST_VER after');
+    }));
+  });
+});
+*/

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/test/unit/servicesSpec.js
----------------------------------------------------------------------
diff --git a/src/main/ui/test/unit/servicesSpec.js b/src/main/ui/test/unit/servicesSpec.js
new file mode 100755
index 0000000..a2110b4
--- /dev/null
+++ b/src/main/ui/test/unit/servicesSpec.js
@@ -0,0 +1,17 @@
+'use strict';
+
+/* jasmine specs for services go here */
+
+/* Example code for service tests
+ *
+describe('service', function() {
+  beforeEach(module('myApp.services'));
+
+
+  describe('version', function() {
+    it('should return current version', inject(function(version) {
+      expect(version).toEqual('0.1');
+    }));
+  });
+});
+*/

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/.svn/all-wcprops
----------------------------------------------------------------------
diff --git a/src/main/vm/.svn/all-wcprops b/src/main/vm/.svn/all-wcprops
new file mode 100755
index 0000000..88a317d
--- /dev/null
+++ b/src/main/vm/.svn/all-wcprops
@@ -0,0 +1,5 @@
+K 25
+svn:wc:ra_dav:version-url
+V 69
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/vm
+END

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/.svn/entries
----------------------------------------------------------------------
diff --git a/src/main/vm/.svn/entries b/src/main/vm/.svn/entries
new file mode 100755
index 0000000..8e7bb9e
--- /dev/null
+++ b/src/main/vm/.svn/entries
@@ -0,0 +1,34 @@
+10
+
+dir
+1485921
+https://svn.apache.org/repos/asf/incubator/climate/trunk/rcmet/src/main/vm
+https://svn.apache.org/repos/asf
+
+
+
+2012-12-07T19:44:54.983182Z
+1474607
+ahart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+13f79535-47bb-0310-9956-ffa450edef68
+
+build
+dir
+
+src
+dir
+

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/build/.svn/all-wcprops
----------------------------------------------------------------------
diff --git a/src/main/vm/build/.svn/all-wcprops b/src/main/vm/build/.svn/all-wcprops
new file mode 100755
index 0000000..a5416fd
--- /dev/null
+++ b/src/main/vm/build/.svn/all-wcprops
@@ -0,0 +1,11 @@
+K 25
+svn:wc:ra_dav:version-url
+V 75
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/vm/build
+END
+Vagrantfile
+K 25
+svn:wc:ra_dav:version-url
+V 87
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/vm/build/Vagrantfile
+END

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/build/.svn/entries
----------------------------------------------------------------------
diff --git a/src/main/vm/build/.svn/entries b/src/main/vm/build/.svn/entries
new file mode 100755
index 0000000..40e2b47
--- /dev/null
+++ b/src/main/vm/build/.svn/entries
@@ -0,0 +1,62 @@
+10
+
+dir
+1485921
+https://svn.apache.org/repos/asf/incubator/climate/trunk/rcmet/src/main/vm/build
+https://svn.apache.org/repos/asf
+
+
+
+2012-10-10T00:59:09.182709Z
+1474267
+ahart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+13f79535-47bb-0310-9956-ffa450edef68
+
+Vagrantfile
+file
+
+
+
+
+2013-05-24T10:13:50.000000Z
+2ed7ba53e26541de333293af815b77a7
+2012-10-10T00:59:09.182709Z
+1474267
+ahart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+4554
+

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/build/.svn/text-base/Vagrantfile.svn-base
----------------------------------------------------------------------
diff --git a/src/main/vm/build/.svn/text-base/Vagrantfile.svn-base b/src/main/vm/build/.svn/text-base/Vagrantfile.svn-base
new file mode 100755
index 0000000..e9a05b1
--- /dev/null
+++ b/src/main/vm/build/.svn/text-base/Vagrantfile.svn-base
@@ -0,0 +1,110 @@
+# -*- mode: ruby -*-
+# vi: set ft=ruby :
+
+## ----------------------------------------------------------------------
+## Regional Climate Model Evaluation System - Toolkit Virtual Machine
+## 
+## This Vagrantfile, in combination with a set of Chef cookbooks for RCMES,
+## will generate a fully-functioning virtual machine containing the 
+## RCMES Python libraries, the RCMET web interface wizards, as well as
+## documentation and user manuals to help users acclimate to RCMES.
+##
+## @author ahart
+## ----------------------------------------------------------------------
+
+Vagrant::Config.run do |config|
+  # All Vagrant configuration is done here. The most common configuration
+  # options are documented and commented below. For a complete reference,
+  # please see the online documentation at vagrantup.com.
+
+  # Every Vagrant virtual environment requires a box to build off of.
+  config.vm.box = "lucid32"
+
+  # The url from where the 'config.vm.box' box will be fetched if it
+  # doesn't already exist on the user's system.
+  # config.vm.box_url = "http://domain.com/path/to/above.box"
+
+  # Boot with a GUI so you can see the screen. (Default is headless)
+  # config.vm.boot_mode = :gui
+
+  # Assign this VM to a host-only network IP, allowing you to access it
+  # via the IP. Host-only networks can talk to the host machine as well as
+  # any other machines on the same network, but cannot be accessed (through this
+  # network interface) by any external networks.
+  # config.vm.network :hostonly, "192.168.33.10"
+
+  # Assign this VM to a bridged network, allowing you to connect directly to a
+  # network using the host's network device. This makes the VM appear as another
+  # physical device on your network.
+  # config.vm.network :bridged
+
+  # Forward a port from the guest to the host, which allows for outside
+  # computers to access the VM, whereas host only networking does not.
+  # config.vm.forward_port 80, 8080
+
+  # Share an additional folder to the guest VM. The first argument is
+  # an identifier, the second is the path on the guest to mount the
+  # folder, and the third is the path on the host to the actual folder.
+  # config.vm.share_folder "v-data", "/vagrant_data", "../data"
+
+  # Enable provisioning with Puppet stand alone.  Puppet manifests
+  # are contained in a directory path relative to this Vagrantfile.
+  # You will need to create the manifests directory and a manifest in
+  # the file base.pp in the manifests_path directory.
+  #
+  # An example Puppet manifest to provision the message of the day:
+  #
+  # # group { "puppet":
+  # #   ensure => "present",
+  # # }
+  # #
+  # # File { owner => 0, group => 0, mode => 0644 }
+  # #
+  # # file { '/etc/motd':
+  # #   content => "Welcome to your Vagrant-built virtual machine!
+  # #               Managed by Puppet.\n"
+  # # }
+  #
+  # config.vm.provision :puppet do |puppet|
+  #   puppet.manifests_path = "manifests"
+  #   puppet.manifest_file  = "base.pp"
+  # end
+
+  # Enable provisioning with chef solo, specifying a cookbooks path, roles
+  # path, and data_bags path (all relative to this Vagrantfile), and adding 
+  # some recipes and/or roles.
+  #
+  config.vm.provision :chef_solo do |chef|
+    chef.cookbooks_path = "../src/cookbooks"
+    chef.add_recipe("vagrant_main")
+  end
+
+  # Change the following to "true" to auto-check that the version of Guest Additions
+  # matches the version of your VirtualBox install. For production this is a GOOD
+  # idea, but it increases the build time considerably, so for development it is 
+  # turned off.
+  config.vbguest.auto_update = false;
+
+  # Enable provisioning with chef server, specifying the chef server URL,
+  # and the path to the validation key (relative to this Vagrantfile).
+  #
+  # The Opscode Platform uses HTTPS. Substitute your organization for
+  # ORGNAME in the URL and validation key.
+  #
+  # If you have your own Chef Server, use the appropriate URL, which may be
+  # HTTP instead of HTTPS depending on your configuration. Also change the
+  # validation key to validation.pem.
+  #
+  # config.vm.provision :chef_client do |chef|
+  #   chef.chef_server_url = "https://api.opscode.com/organizations/ORGNAME"
+  #   chef.validation_key_path = "ORGNAME-validator.pem"
+  # end
+  #
+  # If you're using the Opscode platform, your validator client is
+  # ORGNAME-validator, replacing ORGNAME with your organization name.
+  #
+  # IF you have your own Chef Server, the default validation client name is
+  # chef-validator, unless you changed the configuration.
+  #
+  #   chef.validation_client_name = "ORGNAME-validator"
+end

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/build/Vagrantfile
----------------------------------------------------------------------
diff --git a/src/main/vm/build/Vagrantfile b/src/main/vm/build/Vagrantfile
new file mode 100755
index 0000000..e9a05b1
--- /dev/null
+++ b/src/main/vm/build/Vagrantfile
@@ -0,0 +1,110 @@
+# -*- mode: ruby -*-
+# vi: set ft=ruby :
+
+## ----------------------------------------------------------------------
+## Regional Climate Model Evaluation System - Toolkit Virtual Machine
+## 
+## This Vagrantfile, in combination with a set of Chef cookbooks for RCMES,
+## will generate a fully-functioning virtual machine containing the 
+## RCMES Python libraries, the RCMET web interface wizards, as well as
+## documentation and user manuals to help users acclimate to RCMES.
+##
+## @author ahart
+## ----------------------------------------------------------------------
+
+Vagrant::Config.run do |config|
+  # All Vagrant configuration is done here. The most common configuration
+  # options are documented and commented below. For a complete reference,
+  # please see the online documentation at vagrantup.com.
+
+  # Every Vagrant virtual environment requires a box to build off of.
+  config.vm.box = "lucid32"
+
+  # The url from where the 'config.vm.box' box will be fetched if it
+  # doesn't already exist on the user's system.
+  # config.vm.box_url = "http://domain.com/path/to/above.box"
+
+  # Boot with a GUI so you can see the screen. (Default is headless)
+  # config.vm.boot_mode = :gui
+
+  # Assign this VM to a host-only network IP, allowing you to access it
+  # via the IP. Host-only networks can talk to the host machine as well as
+  # any other machines on the same network, but cannot be accessed (through this
+  # network interface) by any external networks.
+  # config.vm.network :hostonly, "192.168.33.10"
+
+  # Assign this VM to a bridged network, allowing you to connect directly to a
+  # network using the host's network device. This makes the VM appear as another
+  # physical device on your network.
+  # config.vm.network :bridged
+
+  # Forward a port from the guest to the host, which allows for outside
+  # computers to access the VM, whereas host only networking does not.
+  # config.vm.forward_port 80, 8080
+
+  # Share an additional folder to the guest VM. The first argument is
+  # an identifier, the second is the path on the guest to mount the
+  # folder, and the third is the path on the host to the actual folder.
+  # config.vm.share_folder "v-data", "/vagrant_data", "../data"
+
+  # Enable provisioning with Puppet stand alone.  Puppet manifests
+  # are contained in a directory path relative to this Vagrantfile.
+  # You will need to create the manifests directory and a manifest in
+  # the file base.pp in the manifests_path directory.
+  #
+  # An example Puppet manifest to provision the message of the day:
+  #
+  # # group { "puppet":
+  # #   ensure => "present",
+  # # }
+  # #
+  # # File { owner => 0, group => 0, mode => 0644 }
+  # #
+  # # file { '/etc/motd':
+  # #   content => "Welcome to your Vagrant-built virtual machine!
+  # #               Managed by Puppet.\n"
+  # # }
+  #
+  # config.vm.provision :puppet do |puppet|
+  #   puppet.manifests_path = "manifests"
+  #   puppet.manifest_file  = "base.pp"
+  # end
+
+  # Enable provisioning with chef solo, specifying a cookbooks path, roles
+  # path, and data_bags path (all relative to this Vagrantfile), and adding 
+  # some recipes and/or roles.
+  #
+  config.vm.provision :chef_solo do |chef|
+    chef.cookbooks_path = "../src/cookbooks"
+    chef.add_recipe("vagrant_main")
+  end
+
+  # Change the following to "true" to auto-check that the version of Guest Additions
+  # matches the version of your VirtualBox install. For production this is a GOOD
+  # idea, but it increases the build time considerably, so for development it is 
+  # turned off.
+  config.vbguest.auto_update = false;
+
+  # Enable provisioning with chef server, specifying the chef server URL,
+  # and the path to the validation key (relative to this Vagrantfile).
+  #
+  # The Opscode Platform uses HTTPS. Substitute your organization for
+  # ORGNAME in the URL and validation key.
+  #
+  # If you have your own Chef Server, use the appropriate URL, which may be
+  # HTTP instead of HTTPS depending on your configuration. Also change the
+  # validation key to validation.pem.
+  #
+  # config.vm.provision :chef_client do |chef|
+  #   chef.chef_server_url = "https://api.opscode.com/organizations/ORGNAME"
+  #   chef.validation_key_path = "ORGNAME-validator.pem"
+  # end
+  #
+  # If you're using the Opscode platform, your validator client is
+  # ORGNAME-validator, replacing ORGNAME with your organization name.
+  #
+  # IF you have your own Chef Server, the default validation client name is
+  # chef-validator, unless you changed the configuration.
+  #
+  #   chef.validation_client_name = "ORGNAME-validator"
+end

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/.svn/all-wcprops
----------------------------------------------------------------------
diff --git a/src/main/vm/src/.svn/all-wcprops b/src/main/vm/src/.svn/all-wcprops
new file mode 100755
index 0000000..1be6828
--- /dev/null
+++ b/src/main/vm/src/.svn/all-wcprops
@@ -0,0 +1,5 @@
+K 25
+svn:wc:ra_dav:version-url
+V 73
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/vm/src
+END

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/.svn/entries
----------------------------------------------------------------------
diff --git a/src/main/vm/src/.svn/entries b/src/main/vm/src/.svn/entries
new file mode 100755
index 0000000..e8c9f0e
--- /dev/null
+++ b/src/main/vm/src/.svn/entries
@@ -0,0 +1,34 @@
+10
+
+dir
+1485921
+https://svn.apache.org/repos/asf/incubator/climate/trunk/rcmet/src/main/vm/src
+https://svn.apache.org/repos/asf
+
+
+
+2012-12-07T19:44:54.983182Z
+1474607
+ahart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+13f79535-47bb-0310-9956-ffa450edef68
+
+scripts
+dir
+
+cookbooks
+dir
+

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/.svn/all-wcprops
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/.svn/all-wcprops b/src/main/vm/src/cookbooks/.svn/all-wcprops
new file mode 100755
index 0000000..968495a
--- /dev/null
+++ b/src/main/vm/src/cookbooks/.svn/all-wcprops
@@ -0,0 +1,5 @@
+K 25
+svn:wc:ra_dav:version-url
+V 83
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks
+END

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/.svn/entries
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/.svn/entries b/src/main/vm/src/cookbooks/.svn/entries
new file mode 100755
index 0000000..dea652e
--- /dev/null
+++ b/src/main/vm/src/cookbooks/.svn/entries
@@ -0,0 +1,43 @@
+10
+
+dir
+1485921
+https://svn.apache.org/repos/asf/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks
+https://svn.apache.org/repos/asf
+
+
+
+2012-12-07T19:15:28.460275Z
+1474605
+ahart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+13f79535-47bb-0310-9956-ffa450edef68
+
+python
+dir
+
+apache2
+dir
+
+apt
+dir
+
+build-essential
+dir
+
+vagrant_main
+dir
+

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/.svn/all-wcprops
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/.svn/all-wcprops b/src/main/vm/src/cookbooks/apache2/.svn/all-wcprops
new file mode 100755
index 0000000..c848e0b
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/.svn/all-wcprops
@@ -0,0 +1,23 @@
+K 25
+svn:wc:ra_dav:version-url
+V 91
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks/apache2
+END
+metadata.rb
+K 25
+svn:wc:ra_dav:version-url
+V 103
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks/apache2/metadata.rb
+END
+README.rdoc
+K 25
+svn:wc:ra_dav:version-url
+V 103
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks/apache2/README.rdoc
+END
+metadata.json
+K 25
+svn:wc:ra_dav:version-url
+V 105
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks/apache2/metadata.json
+END

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/.svn/entries
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/.svn/entries b/src/main/vm/src/cookbooks/apache2/.svn/entries
new file mode 100755
index 0000000..57e121c
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/.svn/entries
@@ -0,0 +1,145 @@
+10
+
+dir
+1485921
+https://svn.apache.org/repos/asf/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks/apache2
+https://svn.apache.org/repos/asf
+
+
+
+2012-10-10T00:49:17.045897Z
+1474264
+ahart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+13f79535-47bb-0310-9956-ffa450edef68
+
+files
+dir
+
+metadata.rb
+file
+
+
+
+
+2013-05-24T10:13:54.000000Z
+f3b7d34019679fcf1379fbbdc05fd890
+2012-10-10T00:49:17.045897Z
+1474264
+ahart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+8093
+
+README.rdoc
+file
+
+
+
+
+2013-05-24T10:13:54.000000Z
+6494b0001dfd9943f71c6d9ddf73ba59
+2012-10-10T00:49:17.045897Z
+1474264
+ahart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+3835
+
+attributes
+dir
+
+metadata.json
+file
+
+
+
+
+2013-05-24T10:13:54.000000Z
+6b43415b5e190e43e5f7f54ba7177570
+2012-10-10T00:49:17.045897Z
+1474264
+ahart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+17036
+
+recipes
+dir
+
+definitions
+dir
+
+templates
+dir
+

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/.svn/text-base/README.rdoc.svn-base
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/.svn/text-base/README.rdoc.svn-base b/src/main/vm/src/cookbooks/apache2/.svn/text-base/README.rdoc.svn-base
new file mode 100755
index 0000000..db31d20
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/.svn/text-base/README.rdoc.svn-base
@@ -0,0 +1,78 @@
+= DESCRIPTION:
+
+Complete Debian/Ubuntu style Apache2 configuration.
+
+= REQUIREMENTS:
+
+Debian or Ubuntu preferred.
+
+Red Hat/CentOS and Fedora can be used but will be converted to a Debian/Ubuntu style Apache as it's far easier to manage with chef. 
+
+= ATTRIBUTES:
+
+The file attributes/apache.rb contains the following attribute types:
+
+* platform specific locations and settings.
+* general settings
+* prefork attributes
+* worker attributes
+
+General settings and prefork/worker attributes are tunable.
+
+= USAGE:
+
+Include the apache2 recipe to install Apache2 and get 'sane' default settings. Configuration is modularized through Apache vhost sites a la Debian style configuration.
+
+For Red Hat, CentOS and Fedora you should first disable selinux as it's not supported (yet), then remove the stock httpd and all it's dependencies prior to attempting to use this recipe. Many packages in these distributions drop conflicting configs into conf.d, all of which haven't been accounted for yet. Starting from scratch will also make it far easier to debug.
+
+== Defines:
+
+* apache_module: sets up an Apache module.
+* apache_conf: sets up a config file for an apache module.
+* apache_site: sets up a vhost site. The conf file must be available.
+* web_app: copies the template for a web app and enables it as a site via apache_site.
+
+== Web Apps:
+
+Various applications that can be set up with Apache as the front end, such as PHP, Django, Rails and others can use the web_app define to set up the template and the Apache site. The define is kind of dumb, so the template needs have the application implementation settings, since we don't know what your app is or what is needed from Apache.
+
+We only prototype one parameter for the web_app define, "template". This is used to specify the name of the template to use in the current cookbook. When you use web_app, you can set up any parameters you want to use in your template. They will get passed to the template through the params hash. For example, the sample web_app.conf.erb template in this cookbook makes use of these.
+
+* docroot
+* server_name
+* server_aliases
+
+These are available as @params[:docroot], @params[:server_name], @params[:server_aliases] within the template. 
+
+If 'cookbook' and 'template' are not specified, the current cookbook's templates/default/web_app.conf.erb will be used. If this template is not suitable for your application, copy it to your cookbook and customize as needed.
+
+== God Monitor:
+
+There's a new recipe, apache2::god_monitor. You will need to make sure to include the 'god' recipe before using the apache2::god_monitor recipe in your cookbook.
+
+== OpenID Auth
+
+Installs the mod_auth_openid module from source. Specify an array of OpenIDs that are allowed to authenticate with the attribute apache[:allowed_openids]. Use the following in a vhost to protect with OpenID authentication:
+
+    AuthOpenIDEnabled On
+    AuthOpenIDDBLocation /var/cache/apache2/mod_auth_openid.db
+    AuthOpenIDUserProgram /usr/local/bin/mod_auth_openid.rb
+
+Change the DBLocation as appropriate for your platform. You'll need to change the file in the recipe to match. The UserProgram is optional if you don't want to limit access by certain OpenIDs.
+
+= LICENSE & AUTHOR:
+
+Author:: Joshua Timberman (<jo...@opscode.com>)
+Copyright:: 2009, Opscode, Inc
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/.svn/text-base/metadata.json.svn-base
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/.svn/text-base/metadata.json.svn-base b/src/main/vm/src/cookbooks/apache2/.svn/text-base/metadata.json.svn-base
new file mode 100755
index 0000000..a9280ea
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/.svn/text-base/metadata.json.svn-base
@@ -0,0 +1,497 @@
+{
+    "suggestions": {
+    },
+    "attributes": {
+      "apache/traceenable": {
+        "required": "optional",
+        "calculated": false,
+        "choice": [
+
+        ],
+        "default": "On",
+        "type": "string",
+        "recipes": [
+
+        ],
+        "description": "Determine behavior of TRACE requests",
+        "display_name": "Apache Trace Enable"
+      },
+      "apache/serversignature": {
+        "required": "optional",
+        "calculated": false,
+        "choice": [
+
+        ],
+        "default": "On",
+        "type": "string",
+        "recipes": [
+
+        ],
+        "description": "Configure footer on server-generated documents",
+        "display_name": "Apache Server Signature"
+      },
+      "apache/contact": {
+        "required": "optional",
+        "calculated": false,
+        "choice": [
+
+        ],
+        "default": "ops@example.com",
+        "type": "string",
+        "recipes": [
+
+        ],
+        "description": "Email address of webmaster",
+        "display_name": "Apache Contact"
+      },
+      "apache/icondir": {
+        "required": "optional",
+        "calculated": false,
+        "choice": [
+
+        ],
+        "default": "/usr/share/apache2/icons",
+        "type": "string",
+        "recipes": [
+
+        ],
+        "description": "Directory location for icons",
+        "display_name": "Apache Icondir"
+      },
+      "apache/user": {
+        "required": "optional",
+        "calculated": false,
+        "choice": [
+
+        ],
+        "default": "www-data",
+        "type": "string",
+        "recipes": [
+
+        ],
+        "description": "User Apache runs as",
+        "display_name": "Apache User"
+      },
+      "apache/worker/threadsperchild": {
+        "required": "optional",
+        "calculated": false,
+        "choice": [
+
+        ],
+        "default": "64",
+        "type": "string",
+        "recipes": [
+
+        ],
+        "description": "Constant number of worker threads in each server process",
+        "display_name": "Apache Worker MPM ThreadsPerChild"
+      },
+      "apache/worker/maxclients": {
+        "required": "optional",
+        "calculated": false,
+        "choice": [
+
+        ],
+        "default": "1024",
+        "type": "string",
+        "recipes": [
+
+        ],
+        "description": "Maximum number of simultaneous connections",
+        "display_name": "Apache Worker MPM MaxClients"
+      },
+      "apache/worker": {
+        "required": "optional",
+        "calculated": false,
+        "choice": [
+
+        ],
+        "type": "hash",
+        "recipes": [
+
+        ],
+        "description": "Hash of Apache prefork tuning attributes.",
+        "display_name": "Apache Worker"
+      },
+      "apache/keepaliverequests": {
+        "required": "optional",
+        "calculated": false,
+        "choice": [
+
+        ],
+        "default": "100",
+        "type": "string",
+        "recipes": [
+
+        ],
+        "description": "Number of requests allowed on a persistent connection",
+        "display_name": "Apache Keepalive Requests"
+      },
+      "apache/timeout": {
+        "required": "optional",
+        "calculated": false,
+        "choice": [
+
+        ],
+        "default": "300",
+        "type": "string",
+        "recipes": [
+
+        ],
+        "description": "Connection timeout value",
+        "display_name": "Apache Timeout"
+      },
+      "apache/worker/maxrequestsperchild": {
+        "required": "optional",
+        "calculated": false,
+        "choice": [
+
+        ],
+        "default": "0",
+        "type": "string",
+        "recipes": [
+
+        ],
+        "description": "Maximum number of request a child process will handle",
+        "display_name": "Apache Worker MPM MaxRequestsPerChild"
+      },
+      "apache/dir": {
+        "required": "optional",
+        "calculated": false,
+        "choice": [
+
+        ],
+        "default": "/etc/apache2",
+        "type": "string",
+        "recipes": [
+
+        ],
+        "description": "Location for Apache configuration",
+        "display_name": "Apache Directory"
+      },
+      "apache/prefork/serverlimit": {
+        "required": "optional",
+        "calculated": false,
+        "choice": [
+
+        ],
+        "default": "400",
+        "type": "string",
+        "recipes": [
+
+        ],
+        "description": "Upper limit on configurable server processes",
+        "display_name": "Apache Prefork MPM ServerLimit"
+      },
+      "apache/prefork/minspareservers": {
+        "required": "optional",
+        "calculated": false,
+        "choice": [
+
+        ],
+        "default": "16",
+        "type": "string",
+        "recipes": [
+
+        ],
+        "description": "Minimum number of spare server processes",
+        "display_name": "Apache Prefork MPM MinSpareServers"
+      },
+      "apache/allowed_openids": {
+        "required": "optional",
+        "calculated": false,
+        "choice": [
+
+        ],
+        "default": "",
+        "type": "string",
+        "recipes": [
+
+        ],
+        "description": "Array of OpenIDs allowed to authenticate",
+        "display_name": "Apache Allowed OpenIDs"
+      },
+      "apache/binary": {
+        "required": "optional",
+        "calculated": false,
+        "choice": [
+
+        ],
+        "default": "/usr/sbin/apache2",
+        "type": "string",
+        "recipes": [
+
+        ],
+        "description": "Apache server daemon program",
+        "display_name": "Apache Binary"
+      },
+      "apache/prefork/startservers": {
+        "required": "optional",
+        "calculated": false,
+        "choice": [
+
+        ],
+        "default": "16",
+        "type": "string",
+        "recipes": [
+
+        ],
+        "description": "Number of MPM servers to start",
+        "display_name": "Apache Prefork MPM StartServers"
+      },
+      "apache/listen_ports": {
+        "required": "optional",
+        "calculated": false,
+        "choice": [
+
+        ],
+        "default": [
+          "80",
+          "443"
+        ],
+        "type": "array",
+        "recipes": [
+
+        ],
+        "description": "Ports that Apache should listen on",
+        "display_name": "Apache Listen Ports"
+      },
+      "apache/prefork/maxrequestsperchild": {
+        "required": "optional",
+        "calculated": false,
+        "choice": [
+
+        ],
+        "default": "10000",
+        "type": "string",
+        "recipes": [
+
+        ],
+        "description": "Maximum number of request a child process will handle",
+        "display_name": "Apache Prefork MPM MaxRequestsPerChild"
+      },
+      "apache/keepalivetimeout": {
+        "required": "optional",
+        "calculated": false,
+        "choice": [
+
+        ],
+        "default": "5",
+        "type": "string",
+        "recipes": [
+
+        ],
+        "description": "Time to wait for requests on persistent connection",
+        "display_name": "Apache Keepalive Timeout"
+      },
+      "apache/keepalive": {
+        "required": "optional",
+        "calculated": false,
+        "choice": [
+
+        ],
+        "default": "On",
+        "type": "string",
+        "recipes": [
+
+        ],
+        "description": "HTTP persistent connections",
+        "display_name": "Apache Keepalive"
+      },
+      "apache": {
+        "required": "optional",
+        "calculated": false,
+        "choice": [
+
+        ],
+        "type": "hash",
+        "recipes": [
+
+        ],
+        "description": "Hash of Apache attributes",
+        "display_name": "Apache Hash"
+      },
+      "apache/worker/maxsparethreads": {
+        "required": "optional",
+        "calculated": false,
+        "choice": [
+
+        ],
+        "default": "192",
+        "type": "string",
+        "recipes": [
+
+        ],
+        "description": "Maximum number of spare worker threads",
+        "display_name": "Apache Worker MPM MaxSpareThreads"
+      },
+      "apache/worker/startservers": {
+        "required": "optional",
+        "calculated": false,
+        "choice": [
+
+        ],
+        "default": "4",
+        "type": "string",
+        "recipes": [
+
+        ],
+        "description": "Initial number of server processes to start",
+        "display_name": "Apache Worker MPM StartServers"
+      },
+      "apache/prefork/maxclients": {
+        "required": "optional",
+        "calculated": false,
+        "choice": [
+
+        ],
+        "default": "400",
+        "type": "string",
+        "recipes": [
+
+        ],
+        "description": "Maximum number of simultaneous connections",
+        "display_name": "Apache Prefork MPM MaxClients"
+      },
+      "apache/prefork": {
+        "required": "optional",
+        "calculated": false,
+        "choice": [
+
+        ],
+        "type": "hash",
+        "recipes": [
+
+        ],
+        "description": "Hash of Apache prefork tuning attributes.",
+        "display_name": "Apache Prefork"
+      },
+      "apache/servertokens": {
+        "required": "optional",
+        "calculated": false,
+        "choice": [
+
+        ],
+        "default": "Prod",
+        "type": "string",
+        "recipes": [
+
+        ],
+        "description": "Server response header",
+        "display_name": "Apache Server Tokens"
+      },
+      "apache/log_dir": {
+        "required": "optional",
+        "calculated": false,
+        "choice": [
+
+        ],
+        "default": "/etc/apache2",
+        "type": "string",
+        "recipes": [
+
+        ],
+        "description": "Location for Apache logs",
+        "display_name": "Apache Log Directory"
+      },
+      "apache/worker/minsparethreads": {
+        "required": "optional",
+        "calculated": false,
+        "choice": [
+
+        ],
+        "default": "64",
+        "type": "string",
+        "recipes": [
+
+        ],
+        "description": "Minimum number of spare worker threads",
+        "display_name": "Apache Worker MPM MinSpareThreads"
+      },
+      "apache/prefork/maxspareservers": {
+        "required": "optional",
+        "calculated": false,
+        "choice": [
+
+        ],
+        "default": "32",
+        "type": "string",
+        "recipes": [
+
+        ],
+        "description": "Maximum number of spare server processes",
+        "display_name": "Apache Prefork MPM MaxSpareServers"
+      }
+    },
+    "maintainer_email": "cookbooks@opscode.com",
+    "conflicting": {
+    },
+    "dependencies": {
+    },
+    "recipes": {
+      "apache2::mod_dav": "Apache module 'dav'",
+      "apache2::mod_proxy_ajp": "Apache module 'proxy_ajp'",
+      "apache2::mod_php5": "Apache module 'php5'",
+      "apache2::mod_mime": "Apache module 'mime' with config file",
+      "apache2::mod_deflate": "Apache module 'deflate' with config file",
+      "apache2::mod_ssl": "Apache module 'ssl' with config file, adds port 443 to listen_ports",
+      "apache2::mod_setenvif": "Apache module 'setenvif' with config file",
+      "apache2::mod_python": "Apache module 'python'",
+      "apache2::mod_negotiation": "Apache module 'negotiation' with config file",
+      "apache2::mod_cgi": "Apache module 'cgi'",
+      "apache2::mod_authz_groupfile": "Apache module 'authz_groupfile'",
+      "apache2::mod_auth_basic": "Apache module 'auth_basic'",
+      "apache2::mod_rewrite": "Apache module 'rewrite'",
+      "apache2::mod_dav_svn": "Apache module 'dav_svn'",
+      "apache2::mod_autoindex": "Apache module 'autoindex' with config file",
+      "apache2::mod_authz_host": "Apache module 'authz_host'",
+      "apache2::mod_headers": "Apache module 'headers'",
+      "apache2::mod_authz_user": "Apache module 'authz_user'",
+      "apache2::mod_proxy_connect": "Apache module 'proxy_connect'",
+      "apache2::mod_proxy": "Apache module 'proxy' with config file",
+      "apache2::mod_fcgid": "Apache module 'fcgid', package on ubuntu/debian, rhel/centos, compile source on suse; with config file",
+      "apache2::mod_authnz_ldap": "Apache module 'authnz_ldap'",
+      "apache2::mod_auth_digest": "Apache module 'auth_digest'",
+      "apache2::mod_env": "Apache module 'env'",
+      "apache2::mod_status": "Apache module 'status' with config file",
+      "apache2::mod_proxy_http": "Apache module 'proxy_http'",
+      "apache2::mod_log_config": "Apache module 'log_config'",
+      "apache2::mod_ldap": "Apache module 'ldap'",
+      "apache2::mod_expires": "Apache module 'expires'",
+      "apache2::mod_alias": "Apache module 'alias' with config file",
+      "apache2": "Main Apache configuration",
+      "apache2::mod_authn_file": "Apache module 'authn_file'",
+      "apache2::mod_auth_openid": "Apache module 'authopenid'",
+      "apache2::mod_proxy_balancer": "Apache module 'proxy_balancer'",
+      "apache2::mod_dir": "Apache module 'dir' with config file",
+      "apache2::mod_authz_default": "Apache module 'authz_default'"
+    },
+    "providing": {
+    },
+    "platforms": {
+      "debian": [
+
+      ],
+      "centos": [
+
+      ],
+      "ubuntu": [
+
+      ],
+      "redhat": [
+
+      ]
+    },
+    "license": "Apache 2.0",
+    "version": "0.12.2",
+    "replacing": {
+    },
+    "groupings": {
+    },
+    "name": "apache2",
+    "recommendations": {
+    },
+    "description": "Installs and configures all aspects of apache2 using Debian style symlinks with helper definitions",
+    "maintainer": "Opscode, Inc.",
+    "long_description": "= DESCRIPTION:\n\nComplete Debian/Ubuntu style Apache2 configuration.\n\n= REQUIREMENTS:\n\nDebian or Ubuntu preferred.\n\nRed Hat/CentOS and Fedora can be used but will be converted to a Debian/Ubuntu style Apache as it's far easier to manage with chef. \n\n= ATTRIBUTES:\n\nThe file attributes/apache.rb contains the following attribute types:\n\n* platform specific locations and settings.\n* general settings\n* prefork attributes\n* worker attributes\n\nGeneral settings and prefork/worker attributes are tunable.\n\n= USAGE:\n\nInclude the apache2 recipe to install Apache2 and get 'sane' default settings. Configuration is modularized through Apache vhost sites a la Debian style configuration.\n\nFor Red Hat, CentOS and Fedora you should first disable selinux as it's not supported (yet), then remove the stock httpd and all it's dependencies prior to attempting to use this recipe. Many packages in these distributions drop conflicting configs into conf.d, all o
 f which haven't been accounted for yet. Starting from scratch will also make it far easier to debug.\n\n== Defines:\n\n* apache_module: sets up an Apache module.\n* apache_conf: sets up a config file for an apache module.\n* apache_site: sets up a vhost site. The conf file must be available.\n* web_app: copies the template for a web app and enables it as a site via apache_site.\n\n== Web Apps:\n\nVarious applications that can be set up with Apache as the front end, such as PHP, Django, Rails and others can use the web_app define to set up the template and the Apache site. The define is kind of dumb, so the template needs have the application implementation settings, since we don't know what your app is or what is needed from Apache.\n\nWe only prototype one parameter for the web_app define, \"template\". This is used to specify the name of the template to use in the current cookbook. When you use web_app, you can set up any parameters you want to use in your template. They will get 
 passed to the template through the params hash. For example, the sample web_app.conf.erb template in this cookbook makes use of these.\n\n* docroot\n* server_name\n* server_aliases\n\nThese are available as @params[:docroot], @params[:server_name], @params[:server_aliases] within the template. \n\nIf 'cookbook' and 'template' are not specified, the current cookbook's templates/default/web_app.conf.erb will be used. If this template is not suitable for your application, copy it to your cookbook and customize as needed.\n\n== God Monitor:\n\nThere's a new recipe, apache2::god_monitor. You will need to make sure to include the 'god' recipe before using the apache2::god_monitor recipe in your cookbook.\n\n== OpenID Auth\n\nInstalls the mod_auth_openid module from source. Specify an array of OpenIDs that are allowed to authenticate with the attribute apache[:allowed_openids]. Use the following in a vhost to protect with OpenID authentication:\n\n    AuthOpenIDEnabled On\n    AuthOpenIDDB
 Location /var/cache/apache2/mod_auth_openid.db\n    AuthOpenIDUserProgram /usr/local/bin/mod_auth_openid.rb\n\nChange the DBLocation as appropriate for your platform. You'll need to change the file in the recipe to match. The UserProgram is optional if you don't want to limit access by certain OpenIDs.\n\n= LICENSE & AUTHOR:\n\nAuthor:: Joshua Timberman (<jo...@opscode.com>)\nCopyright:: 2009, Opscode, Inc\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n    http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n"
+  }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/.svn/text-base/metadata.rb.svn-base
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/.svn/text-base/metadata.rb.svn-base b/src/main/vm/src/cookbooks/apache2/.svn/text-base/metadata.rb.svn-base
new file mode 100755
index 0000000..51f2977
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/.svn/text-base/metadata.rb.svn-base
@@ -0,0 +1,197 @@
+maintainer        "Opscode, Inc."
+maintainer_email  "cookbooks@opscode.com"
+license           "Apache 2.0"
+description       "Installs and configures all aspects of apache2 using Debian style symlinks with helper definitions"
+long_description  IO.read(File.join(File.dirname(__FILE__), 'README.rdoc'))
+version           "0.12.2"
+recipe            "apache2", "Main Apache configuration"
+recipe            "apache2::mod_alias", "Apache module 'alias' with config file"
+recipe            "apache2::mod_auth_basic", "Apache module 'auth_basic'"
+recipe            "apache2::mod_auth_digest", "Apache module 'auth_digest'"
+recipe            "apache2::mod_auth_openid", "Apache module 'authopenid'"
+recipe            "apache2::mod_authn_file", "Apache module 'authn_file'"
+recipe            "apache2::mod_authnz_ldap", "Apache module 'authnz_ldap'"
+recipe            "apache2::mod_authz_default", "Apache module 'authz_default'"
+recipe            "apache2::mod_authz_groupfile", "Apache module 'authz_groupfile'"
+recipe            "apache2::mod_authz_host", "Apache module 'authz_host'"
+recipe            "apache2::mod_authz_user", "Apache module 'authz_user'"
+recipe            "apache2::mod_autoindex", "Apache module 'autoindex' with config file"
+recipe            "apache2::mod_cgi", "Apache module 'cgi'"
+recipe            "apache2::mod_dav", "Apache module 'dav'"
+recipe            "apache2::mod_dav_svn", "Apache module 'dav_svn'"
+recipe            "apache2::mod_deflate", "Apache module 'deflate' with config file"
+recipe            "apache2::mod_dir", "Apache module 'dir' with config file"
+recipe            "apache2::mod_env", "Apache module 'env'"
+recipe            "apache2::mod_expires", "Apache module 'expires'"
+recipe            "apache2::mod_fcgid", "Apache module 'fcgid', package on ubuntu/debian, rhel/centos, compile source on suse; with config file"
+recipe            "apache2::mod_headers", "Apache module 'headers'"
+recipe            "apache2::mod_ldap", "Apache module 'ldap'"
+recipe            "apache2::mod_log_config", "Apache module 'log_config'"
+recipe            "apache2::mod_mime", "Apache module 'mime' with config file"
+recipe            "apache2::mod_negotiation", "Apache module 'negotiation' with config file"
+recipe            "apache2::mod_php5", "Apache module 'php5'"
+recipe            "apache2::mod_proxy", "Apache module 'proxy' with config file"
+recipe            "apache2::mod_proxy_ajp", "Apache module 'proxy_ajp'"
+recipe            "apache2::mod_proxy_balancer", "Apache module 'proxy_balancer'"
+recipe            "apache2::mod_proxy_connect", "Apache module 'proxy_connect'"
+recipe            "apache2::mod_proxy_http", "Apache module 'proxy_http'"
+recipe            "apache2::mod_python", "Apache module 'python'"
+recipe            "apache2::mod_rewrite", "Apache module 'rewrite'"
+recipe            "apache2::mod_setenvif", "Apache module 'setenvif' with config file"
+recipe            "apache2::mod_ssl", "Apache module 'ssl' with config file, adds port 443 to listen_ports"
+recipe            "apache2::mod_status", "Apache module 'status' with config file"
+
+%w{redhat centos debian ubuntu}.each do |os|
+  supports os
+end
+
+attribute "apache",
+  :display_name => "Apache Hash",
+  :description => "Hash of Apache attributes",
+  :type => "hash"
+
+attribute "apache/dir",
+  :display_name => "Apache Directory",
+  :description => "Location for Apache configuration",
+  :default => "/etc/apache2"
+
+attribute "apache/log_dir",
+  :display_name => "Apache Log Directory",
+  :description => "Location for Apache logs",
+  :default => "/etc/apache2"
+
+attribute "apache/user",
+  :display_name => "Apache User",
+  :description => "User Apache runs as",
+  :default => "www-data"
+
+attribute "apache/binary",
+  :display_name => "Apache Binary",
+  :description => "Apache server daemon program",
+  :default => "/usr/sbin/apache2"
+
+attribute "apache/icondir", 
+  :display_name => "Apache Icondir",
+  :description => "Directory location for icons",
+  :default => "/usr/share/apache2/icons"
+
+attribute "apache/listen_ports",
+  :display_name => "Apache Listen Ports",
+  :description => "Ports that Apache should listen on",
+  :type => "array",
+  :default => [ "80", "443" ]
+
+attribute "apache/contact",
+  :display_name => "Apache Contact",
+  :description => "Email address of webmaster",
+  :default => "ops@example.com"
+
+attribute "apache/timeout",
+  :display_name => "Apache Timeout",
+  :description => "Connection timeout value",
+  :default => "300"
+
+attribute "apache/keepalive",
+  :display_name => "Apache Keepalive",
+  :description => "HTTP persistent connections",
+  :default => "On"
+
+attribute "apache/keepaliverequests",
+  :display_name => "Apache Keepalive Requests",
+  :description => "Number of requests allowed on a persistent connection",
+  :default => "100"
+
+attribute "apache/keepalivetimeout",
+  :display_name => "Apache Keepalive Timeout",
+  :description => "Time to wait for requests on persistent connection",
+  :default => "5"
+
+attribute "apache/servertokens",
+  :display_name => "Apache Server Tokens",
+  :description => "Server response header",
+  :default => "Prod"
+
+attribute "apache/serversignature",
+  :display_name => "Apache Server Signature",
+  :description => "Configure footer on server-generated documents",
+  :default => "On"
+
+attribute "apache/traceenable",
+  :display_name => "Apache Trace Enable",
+  :description => "Determine behavior of TRACE requests",
+  :default => "On"
+
+attribute "apache/allowed_openids",
+  :display_name => "Apache Allowed OpenIDs",
+  :description => "Array of OpenIDs allowed to authenticate",
+  :default => ""
+
+attribute "apache/prefork",
+  :display_name => "Apache Prefork",
+  :description => "Hash of Apache prefork tuning attributes.",
+  :type => "hash"
+
+attribute "apache/prefork/startservers",
+  :display_name => "Apache Prefork MPM StartServers",
+  :description => "Number of MPM servers to start",
+  :default => "16"
+
+attribute "apache/prefork/minspareservers",
+  :display_name => "Apache Prefork MPM MinSpareServers",
+  :description => "Minimum number of spare server processes",
+  :default => "16"
+
+attribute "apache/prefork/maxspareservers",
+  :display_name => "Apache Prefork MPM MaxSpareServers",
+  :description => "Maximum number of spare server processes",
+  :default => "32"
+
+attribute "apache/prefork/serverlimit",
+  :display_name => "Apache Prefork MPM ServerLimit",
+  :description => "Upper limit on configurable server processes",
+  :default => "400"
+
+attribute "apache/prefork/maxclients",
+  :display_name => "Apache Prefork MPM MaxClients",
+  :description => "Maximum number of simultaneous connections",
+  :default => "400"
+
+attribute "apache/prefork/maxrequestsperchild",
+  :display_name => "Apache Prefork MPM MaxRequestsPerChild",
+  :description => "Maximum number of request a child process will handle",
+  :default => "10000"
+
+attribute "apache/worker",
+  :display_name => "Apache Worker",
+  :description => "Hash of Apache prefork tuning attributes.",
+  :type => "hash"
+
+attribute "apache/worker/startservers",
+  :display_name => "Apache Worker MPM StartServers",
+  :description => "Initial number of server processes to start",
+  :default => "4"
+
+attribute "apache/worker/maxclients",
+  :display_name => "Apache Worker MPM MaxClients",
+  :description => "Maximum number of simultaneous connections",
+  :default => "1024"
+
+attribute "apache/worker/minsparethreads",
+  :display_name => "Apache Worker MPM MinSpareThreads",
+  :description => "Minimum number of spare worker threads",
+  :default => "64"
+
+attribute "apache/worker/maxsparethreads",
+  :display_name => "Apache Worker MPM MaxSpareThreads",
+  :description => "Maximum number of spare worker threads",
+  :default => "192"
+
+attribute "apache/worker/threadsperchild",
+  :display_name => "Apache Worker MPM ThreadsPerChild",
+  :description => "Constant number of worker threads in each server process",
+  :default => "64"
+
+attribute "apache/worker/maxrequestsperchild",
+  :display_name => "Apache Worker MPM MaxRequestsPerChild",
+  :description => "Maximum number of request a child process will handle",
+  :default => "0"

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/README.rdoc
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/README.rdoc b/src/main/vm/src/cookbooks/apache2/README.rdoc
new file mode 100755
index 0000000..db31d20
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/README.rdoc
@@ -0,0 +1,78 @@
+= DESCRIPTION:
+
+Complete Debian/Ubuntu style Apache2 configuration.
+
+= REQUIREMENTS:
+
+Debian or Ubuntu preferred.
+
+Red Hat/CentOS and Fedora can be used but will be converted to a Debian/Ubuntu style Apache as it's far easier to manage with chef. 
+
+= ATTRIBUTES:
+
+The file attributes/apache.rb contains the following attribute types:
+
+* platform specific locations and settings.
+* general settings
+* prefork attributes
+* worker attributes
+
+General settings and prefork/worker attributes are tunable.
+
+= USAGE:
+
+Include the apache2 recipe to install Apache2 and get 'sane' default settings. Configuration is modularized through Apache vhost sites a la Debian style configuration.
+
+For Red Hat, CentOS and Fedora you should first disable selinux as it's not supported (yet), then remove the stock httpd and all it's dependencies prior to attempting to use this recipe. Many packages in these distributions drop conflicting configs into conf.d, all of which haven't been accounted for yet. Starting from scratch will also make it far easier to debug.
+
+== Defines:
+
+* apache_module: sets up an Apache module.
+* apache_conf: sets up a config file for an apache module.
+* apache_site: sets up a vhost site. The conf file must be available.
+* web_app: copies the template for a web app and enables it as a site via apache_site.
+
+== Web Apps:
+
+Various applications that can be set up with Apache as the front end, such as PHP, Django, Rails and others can use the web_app define to set up the template and the Apache site. The define is kind of dumb, so the template needs have the application implementation settings, since we don't know what your app is or what is needed from Apache.
+
+We only prototype one parameter for the web_app define, "template". This is used to specify the name of the template to use in the current cookbook. When you use web_app, you can set up any parameters you want to use in your template. They will get passed to the template through the params hash. For example, the sample web_app.conf.erb template in this cookbook makes use of these.
+
+* docroot
+* server_name
+* server_aliases
+
+These are available as @params[:docroot], @params[:server_name], @params[:server_aliases] within the template. 
+
+If 'cookbook' and 'template' are not specified, the current cookbook's templates/default/web_app.conf.erb will be used. If this template is not suitable for your application, copy it to your cookbook and customize as needed.
+
+== God Monitor:
+
+There's a new recipe, apache2::god_monitor. You will need to make sure to include the 'god' recipe before using the apache2::god_monitor recipe in your cookbook.
+
+== OpenID Auth
+
+Installs the mod_auth_openid module from source. Specify an array of OpenIDs that are allowed to authenticate with the attribute apache[:allowed_openids]. Use the following in a vhost to protect with OpenID authentication:
+
+    AuthOpenIDEnabled On
+    AuthOpenIDDBLocation /var/cache/apache2/mod_auth_openid.db
+    AuthOpenIDUserProgram /usr/local/bin/mod_auth_openid.rb
+
+Change the DBLocation as appropriate for your platform. You'll need to change the file in the recipe to match. The UserProgram is optional if you don't want to limit access by certain OpenIDs.
+
+= LICENSE & AUTHOR:
+
+Author:: Joshua Timberman (<jo...@opscode.com>)
+Copyright:: 2009, Opscode, Inc
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/attributes/.svn/all-wcprops
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/attributes/.svn/all-wcprops b/src/main/vm/src/cookbooks/apache2/attributes/.svn/all-wcprops
new file mode 100755
index 0000000..8e1f8a0
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/attributes/.svn/all-wcprops
@@ -0,0 +1,11 @@
+K 25
+svn:wc:ra_dav:version-url
+V 102
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks/apache2/attributes
+END
+default.rb
+K 25
+svn:wc:ra_dav:version-url
+V 113
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks/apache2/attributes/default.rb
+END

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/attributes/.svn/entries
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/attributes/.svn/entries b/src/main/vm/src/cookbooks/apache2/attributes/.svn/entries
new file mode 100755
index 0000000..5690c5f
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/attributes/.svn/entries
@@ -0,0 +1,62 @@
+10
+
+dir
+1485921
+https://svn.apache.org/repos/asf/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks/apache2/attributes
+https://svn.apache.org/repos/asf
+
+
+
+2012-10-10T00:49:17.045897Z
+1474264
+ahart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+13f79535-47bb-0310-9956-ffa450edef68
+
+default.rb
+file
+
+
+
+
+2013-05-24T10:13:51.000000Z
+6ba6bdd800c67b1e77c3a8e5361c388c
+2012-10-10T00:49:17.045897Z
+1474264
+ahart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+2648
+

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/attributes/.svn/text-base/default.rb.svn-base
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/attributes/.svn/text-base/default.rb.svn-base b/src/main/vm/src/cookbooks/apache2/attributes/.svn/text-base/default.rb.svn-base
new file mode 100755
index 0000000..18212f9
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/attributes/.svn/text-base/default.rb.svn-base
@@ -0,0 +1,77 @@
+#
+# Cookbook Name:: apache2
+# Attributes:: apache
+#
+# Copyright 2008-2009, Opscode, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+# Where the various parts of apache are
+case platform
+when "redhat","centos","fedora","suse"
+  set[:apache][:dir]     = "/etc/httpd"
+  set[:apache][:log_dir] = "/var/log/httpd"
+  set[:apache][:user]    = "apache"
+  set[:apache][:binary]  = "/usr/sbin/httpd"
+  set[:apache][:icondir] = "/var/www/icons/"
+when "debian","ubuntu"
+  set[:apache][:dir]     = "/etc/apache2"
+  set[:apache][:log_dir] = "/var/log/apache2"
+  set[:apache][:user]    = "www-data"
+  set[:apache][:binary]  = "/usr/sbin/apache2"
+  set[:apache][:icondir] = "/usr/share/apache2/icons"
+else
+  set[:apache][:dir]     = "/etc/apache2"
+  set[:apache][:log_dir] = "/var/log/apache2"
+  set[:apache][:user]    = "www-data"
+  set[:apache][:binary]  = "/usr/sbin/apache2"
+  set[:apache][:icondir] = "/usr/share/apache2/icons"
+end
+
+###
+# These settings need the unless, since we want them to be tunable,
+# and we don't want to override the tunings.
+###
+
+# General settings
+default[:apache][:listen_ports] = [ "80","443" ]
+default[:apache][:contact] = "ops@example.com"
+default[:apache][:timeout] = 300
+default[:apache][:keepalive] = "On"
+default[:apache][:keepaliverequests] = 100
+default[:apache][:keepalivetimeout] = 5
+
+# Security
+default[:apache][:servertokens] = "Prod"
+default[:apache][:serversignature] = "On"
+default[:apache][:traceenable] = "On"
+
+# mod_auth_openids
+default[:apache][:allowed_openids] = Array.new
+
+# Prefork Attributes
+default[:apache][:prefork][:startservers] = 16
+default[:apache][:prefork][:minspareservers] = 16
+default[:apache][:prefork][:maxspareservers] = 32
+default[:apache][:prefork][:serverlimit] = 400
+default[:apache][:prefork][:maxclients] = 400
+default[:apache][:prefork][:maxrequestsperchild] = 10000
+
+# Worker Attributes
+default[:apache][:worker][:startservers] = 4
+default[:apache][:worker][:maxclients] = 1024
+default[:apache][:worker][:minsparethreads] = 64
+default[:apache][:worker][:maxsparethreads] = 192
+default[:apache][:worker][:threadsperchild] = 64
+default[:apache][:worker][:maxrequestsperchild] = 0

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/attributes/default.rb
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/attributes/default.rb b/src/main/vm/src/cookbooks/apache2/attributes/default.rb
new file mode 100755
index 0000000..18212f9
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/attributes/default.rb
@@ -0,0 +1,77 @@
+#
+# Cookbook Name:: apache2
+# Attributes:: apache
+#
+# Copyright 2008-2009, Opscode, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+# Where the various parts of apache are
+case platform
+when "redhat","centos","fedora","suse"
+  set[:apache][:dir]     = "/etc/httpd"
+  set[:apache][:log_dir] = "/var/log/httpd"
+  set[:apache][:user]    = "apache"
+  set[:apache][:binary]  = "/usr/sbin/httpd"
+  set[:apache][:icondir] = "/var/www/icons/"
+when "debian","ubuntu"
+  set[:apache][:dir]     = "/etc/apache2"
+  set[:apache][:log_dir] = "/var/log/apache2"
+  set[:apache][:user]    = "www-data"
+  set[:apache][:binary]  = "/usr/sbin/apache2"
+  set[:apache][:icondir] = "/usr/share/apache2/icons"
+else
+  set[:apache][:dir]     = "/etc/apache2"
+  set[:apache][:log_dir] = "/var/log/apache2"
+  set[:apache][:user]    = "www-data"
+  set[:apache][:binary]  = "/usr/sbin/apache2"
+  set[:apache][:icondir] = "/usr/share/apache2/icons"
+end
+
+###
+# These settings need the unless, since we want them to be tunable,
+# and we don't want to override the tunings.
+###
+
+# General settings
+default[:apache][:listen_ports] = [ "80","443" ]
+default[:apache][:contact] = "ops@example.com"
+default[:apache][:timeout] = 300
+default[:apache][:keepalive] = "On"
+default[:apache][:keepaliverequests] = 100
+default[:apache][:keepalivetimeout] = 5
+
+# Security
+default[:apache][:servertokens] = "Prod"
+default[:apache][:serversignature] = "On"
+default[:apache][:traceenable] = "On"
+
+# mod_auth_openids
+default[:apache][:allowed_openids] = Array.new
+
+# Prefork Attributes
+default[:apache][:prefork][:startservers] = 16
+default[:apache][:prefork][:minspareservers] = 16
+default[:apache][:prefork][:maxspareservers] = 32
+default[:apache][:prefork][:serverlimit] = 400
+default[:apache][:prefork][:maxclients] = 400
+default[:apache][:prefork][:maxrequestsperchild] = 10000
+
+# Worker Attributes
+default[:apache][:worker][:startservers] = 4
+default[:apache][:worker][:maxclients] = 1024
+default[:apache][:worker][:minsparethreads] = 64
+default[:apache][:worker][:maxsparethreads] = 192
+default[:apache][:worker][:threadsperchild] = 64
+default[:apache][:worker][:maxrequestsperchild] = 0

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/definitions/.svn/all-wcprops
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/definitions/.svn/all-wcprops b/src/main/vm/src/cookbooks/apache2/definitions/.svn/all-wcprops
new file mode 100755
index 0000000..12331d3
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/definitions/.svn/all-wcprops
@@ -0,0 +1,29 @@
+K 25
+svn:wc:ra_dav:version-url
+V 103
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks/apache2/definitions
+END
+web_app.rb
+K 25
+svn:wc:ra_dav:version-url
+V 114
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks/apache2/definitions/web_app.rb
+END
+apache_site.rb
+K 25
+svn:wc:ra_dav:version-url
+V 118
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks/apache2/definitions/apache_site.rb
+END
+apache_conf.rb
+K 25
+svn:wc:ra_dav:version-url
+V 118
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks/apache2/definitions/apache_conf.rb
+END
+apache_module.rb
+K 25
+svn:wc:ra_dav:version-url
+V 120
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks/apache2/definitions/apache_module.rb
+END

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/definitions/.svn/entries
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/definitions/.svn/entries b/src/main/vm/src/cookbooks/apache2/definitions/.svn/entries
new file mode 100755
index 0000000..d697e74
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/definitions/.svn/entries
@@ -0,0 +1,164 @@
+10
+
+dir
+1485921
+https://svn.apache.org/repos/asf/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks/apache2/definitions
+https://svn.apache.org/repos/asf
+
+
+
+2012-10-10T00:49:17.045897Z
+1474264
+ahart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+13f79535-47bb-0310-9956-ffa450edef68
+
+web_app.rb
+file
+
+
+
+
+2013-05-24T10:13:53.000000Z
+cd28945f2de113e10735088dbde9ca9c
+2012-10-10T00:49:17.045897Z
+1474264
+ahart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+1439
+
+apache_site.rb
+file
+
+
+
+
+2013-05-24T10:13:53.000000Z
+64894cde2300960a3e0fec415ed5e9c4
+2012-10-10T00:49:17.045897Z
+1474264
+ahart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+1454
+
+apache_conf.rb
+file
+
+
+
+
+2013-05-24T10:13:53.000000Z
+ccfabf2717d38070e0ac445d4cde66f4
+2012-10-10T00:49:17.045897Z
+1474264
+ahart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+852
+
+apache_module.rb
+file
+
+
+
+
+2013-05-24T10:13:53.000000Z
+2d9d53447dfef7b9b9d3f8b955359e59
+2012-10-10T00:49:17.045897Z
+1474264
+ahart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+1545
+

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/definitions/.svn/text-base/apache_conf.rb.svn-base
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/definitions/.svn/text-base/apache_conf.rb.svn-base b/src/main/vm/src/cookbooks/apache2/definitions/.svn/text-base/apache_conf.rb.svn-base
new file mode 100755
index 0000000..2439289
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/definitions/.svn/text-base/apache_conf.rb.svn-base
@@ -0,0 +1,25 @@
+#
+# Cookbook Name:: apache2
+# Definition:: apache_conf
+#
+# Copyright 2008-2009, Opscode, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+define :apache_conf do
+  template "#{node[:apache][:dir]}/mods-available/#{params[:name]}.conf" do
+    source "mods/#{params[:name]}.conf.erb"
+    notifies :restart, resources(:service => "apache2")
+  end
+end

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/definitions/.svn/text-base/apache_module.rb.svn-base
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/definitions/.svn/text-base/apache_module.rb.svn-base b/src/main/vm/src/cookbooks/apache2/definitions/.svn/text-base/apache_module.rb.svn-base
new file mode 100755
index 0000000..2bd739e
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/definitions/.svn/text-base/apache_module.rb.svn-base
@@ -0,0 +1,43 @@
+#
+# Cookbook Name:: apache2
+# Definition:: apache_module
+#
+# Copyright 2008-2009, Opscode, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+define :apache_module, :enable => true, :conf => false do
+  include_recipe "apache2"
+ 
+  if params[:conf]
+    apache_conf params[:name]
+  end
+ 
+  if params[:enable]
+    execute "a2enmod #{params[:name]}" do
+      command "/usr/sbin/a2enmod #{params[:name]}"
+      notifies :restart, resources(:service => "apache2")
+      not_if do (File.symlink?("#{node[:apache][:dir]}/mods-enabled/#{params[:name]}.load") and
+            ((File.exists?("#{node[:apache][:dir]}/mods-available/#{params[:name]}.conf"))?
+              (File.symlink?("#{node[:apache][:dir]}/mods-enabled/#{params[:name]}.conf")):(true)))
+      end
+    end    
+  else
+    execute "a2dismod #{params[:name]}" do
+      command "/usr/sbin/a2dismod #{params[:name]}"
+      notifies :restart, resources(:service => "apache2")
+      only_if do File.symlink?("#{node[:apache][:dir]}/mods-enabled/#{params[:name]}.load") end
+    end
+  end
+end

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/definitions/.svn/text-base/apache_site.rb.svn-base
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/definitions/.svn/text-base/apache_site.rb.svn-base b/src/main/vm/src/cookbooks/apache2/definitions/.svn/text-base/apache_site.rb.svn-base
new file mode 100755
index 0000000..7316e01
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/definitions/.svn/text-base/apache_site.rb.svn-base
@@ -0,0 +1,40 @@
+#
+# Cookbook Name:: apache2
+# Definition:: apache_site
+#
+# Copyright 2008-2009, Opscode, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+define :apache_site, :enable => true do
+  include_recipe "apache2"
+  
+  if params[:enable]
+    execute "a2ensite #{params[:name]}" do
+      command "/usr/sbin/a2ensite #{params[:name]}"
+      notifies :restart, resources(:service => "apache2")
+      not_if do 
+        File.symlink?("#{node[:apache][:dir]}/sites-enabled/#{params[:name]}") or
+          File.symlink?("#{node[:apache][:dir]}/sites-enabled/000-#{params[:name]}")
+      end
+      only_if do File.exists?("#{node[:apache][:dir]}/sites-available/#{params[:name]}") end
+    end
+  else
+    execute "a2dissite #{params[:name]}" do
+      command "/usr/sbin/a2dissite #{params[:name]}"
+      notifies :restart, resources(:service => "apache2")
+      only_if do File.symlink?("#{node[:apache][:dir]}/sites-enabled/#{params[:name]}") end
+    end
+  end
+end

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/definitions/.svn/text-base/web_app.rb.svn-base
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/definitions/.svn/text-base/web_app.rb.svn-base b/src/main/vm/src/cookbooks/apache2/definitions/.svn/text-base/web_app.rb.svn-base
new file mode 100755
index 0000000..b532708
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/definitions/.svn/text-base/web_app.rb.svn-base
@@ -0,0 +1,49 @@
+#
+# Cookbook Name:: apache2
+# Definition:: web_app
+#
+# Copyright 2008-2009, Opscode, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+define :web_app, :template => "web_app.conf.erb" do
+  
+  application_name = params[:name]
+
+  include_recipe "apache2"
+  include_recipe "apache2::mod_rewrite"
+  include_recipe "apache2::mod_deflate"
+  include_recipe "apache2::mod_headers"
+  
+  template "#{node[:apache][:dir]}/sites-available/#{application_name}.conf" do
+    source params[:template]
+    owner "root"
+    group "root"
+    mode 0644
+    if params[:cookbook]
+      cookbook params[:cookbook]
+    end
+    variables(
+      :application_name => application_name,
+      :params => params
+    )
+    if File.exists?("#{node[:apache][:dir]}/sites-enabled/#{application_name}.conf")
+      notifies :reload, resources(:service => "apache2"), :delayed
+    end
+  end
+  
+  apache_site "#{params[:name]}.conf" do
+    enable enable_setting
+  end
+end

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/definitions/apache_conf.rb
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/definitions/apache_conf.rb b/src/main/vm/src/cookbooks/apache2/definitions/apache_conf.rb
new file mode 100755
index 0000000..2439289
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/definitions/apache_conf.rb
@@ -0,0 +1,25 @@
+#
+# Cookbook Name:: apache2
+# Definition:: apache_conf
+#
+# Copyright 2008-2009, Opscode, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+define :apache_conf do
+  template "#{node[:apache][:dir]}/mods-available/#{params[:name]}.conf" do
+    source "mods/#{params[:name]}.conf.erb"
+    notifies :restart, resources(:service => "apache2")
+  end
+end


[29/51] [abbrv] [partial] Adding Jinwon's custom RCMET

Posted by jo...@apache.org.
http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/app/font/fontawesome-webfont.svg
----------------------------------------------------------------------
diff --git a/src/main/ui/app/font/fontawesome-webfont.svg b/src/main/ui/app/font/fontawesome-webfont.svg
new file mode 100755
index 0000000..ba0afe5
--- /dev/null
+++ b/src/main/ui/app/font/fontawesome-webfont.svg
@@ -0,0 +1,284 @@
+<?xml version="1.0" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
+<svg xmlns="http://www.w3.org/2000/svg">
+<metadata></metadata>
+<defs>
+<font id="fontawesomeregular" horiz-adv-x="1536" >
+<font-face units-per-em="1792" ascent="1536" descent="-256" />
+<missing-glyph horiz-adv-x="448" />
+<glyph unicode=" "  horiz-adv-x="448" />
+<glyph unicode="&#x09;" horiz-adv-x="448" />
+<glyph unicode="&#xa0;" horiz-adv-x="448" />
+<glyph unicode="&#xa8;" horiz-adv-x="1792" />
+<glyph unicode="&#xa9;" horiz-adv-x="1792" />
+<glyph unicode="&#xae;" horiz-adv-x="1792" />
+<glyph unicode="&#xb4;" horiz-adv-x="1792" />
+<glyph unicode="&#xc6;" horiz-adv-x="1792" />
+<glyph unicode="&#x2000;" horiz-adv-x="768" />
+<glyph unicode="&#x2001;" />
+<glyph unicode="&#x2002;" horiz-adv-x="768" />
+<glyph unicode="&#x2003;" />
+<glyph unicode="&#x2004;" horiz-adv-x="512" />
+<glyph unicode="&#x2005;" horiz-adv-x="384" />
+<glyph unicode="&#x2006;" horiz-adv-x="256" />
+<glyph unicode="&#x2007;" horiz-adv-x="256" />
+<glyph unicode="&#x2008;" horiz-adv-x="192" />
+<glyph unicode="&#x2009;" horiz-adv-x="307" />
+<glyph unicode="&#x200a;" horiz-adv-x="85" />
+<glyph unicode="&#x202f;" horiz-adv-x="307" />
+<glyph unicode="&#x205f;" horiz-adv-x="384" />
+<glyph unicode="&#x2122;" horiz-adv-x="1792" />
+<glyph unicode="&#x221e;" horiz-adv-x="1792" />
+<glyph unicode="&#x2260;" horiz-adv-x="1792" />
+<glyph unicode="&#xe000;" horiz-adv-x="500" d="M0 0z" />
+<glyph unicode="&#xf000;" horiz-adv-x="1792" d="M1699 1350q0 -35 -43 -78l-632 -632v-768h320q26 0 45 -19t19 -45t-19 -45t-45 -19h-896q-26 0 -45 19t-19 45t19 45t45 19h320v768l-632 632q-43 43 -43 78q0 23 18 36.5t38 17.5t43 4h1408q23 0 43 -4t38 -17.5t18 -36.5z" />
+<glyph unicode="&#xf001;" d="M1536 1312v-1120q0 -50 -34 -89t-86 -60.5t-103.5 -32t-96.5 -10.5t-96.5 10.5t-103.5 32t-86 60.5t-34 89t34 89t86 60.5t103.5 32t96.5 10.5q105 0 192 -39v537l-768 -237v-709q0 -50 -34 -89t-86 -60.5t-103.5 -32t-96.5 -10.5t-96.5 10.5t-103.5 32t-86 60.5t-34 89 t34 89t86 60.5t103.5 32t96.5 10.5q105 0 192 -39v967q0 31 19 56.5t49 35.5l832 256q12 4 28 4q40 0 68 -28t28 -68z" />
+<glyph unicode="&#xf002;" horiz-adv-x="1664" d="M1152 704q0 185 -131.5 316.5t-316.5 131.5t-316.5 -131.5t-131.5 -316.5t131.5 -316.5t316.5 -131.5t316.5 131.5t131.5 316.5zM1664 -128q0 -52 -38 -90t-90 -38q-54 0 -90 38l-343 342q-179 -124 -399 -124q-143 0 -273.5 55.5t-225 150t-150 225t-55.5 273.5 t55.5 273.5t150 225t225 150t273.5 55.5t273.5 -55.5t225 -150t150 -225t55.5 -273.5q0 -220 -124 -399l343 -343q37 -37 37 -90z" />
+<glyph unicode="&#xf003;" horiz-adv-x="1792" d="M1664 32v768q-32 -36 -69 -66q-268 -206 -426 -338q-51 -43 -83 -67t-86.5 -48.5t-102.5 -24.5h-1h-1q-48 0 -102.5 24.5t-86.5 48.5t-83 67q-158 132 -426 338q-37 30 -69 66v-768q0 -13 9.5 -22.5t22.5 -9.5h1472q13 0 22.5 9.5t9.5 22.5zM1664 1083v11v13.5t-0.5 13 t-3 12.5t-5.5 9t-9 7.5t-14 2.5h-1472q-13 0 -22.5 -9.5t-9.5 -22.5q0 -168 147 -284q193 -152 401 -317q6 -5 35 -29.5t46 -37.5t44.5 -31.5t50.5 -27.5t43 -9h1h1q20 0 43 9t50.5 27.5t44.5 31.5t46 37.5t35 29.5q208 165 401 317q54 43 100.5 115.5t46.5 131.5z M1792 1120v-1088q0 -66 -47 -113t-113 -47h-1472q-66 0 -113 47t-47 113v1088q0 66 47 113t113 47h1472q66 0 113 -47t47 -113z" />
+<glyph unicode="&#xf004;" horiz-adv-x="1792" d="M896 -128q-26 0 -44 18l-624 602q-10 8 -27.5 26t-55.5 65.5t-68 97.5t-53.5 121t-23.5 138q0 220 127 344t351 124q62 0 126.5 -21.5t120 -58t95.5 -68.5t76 -68q36 36 76 68t95.5 68.5t120 58t126.5 21.5q224 0 351 -124t127 -344q0 -221 -229 -450l-623 -600 q-18 -18 -44 -18z" />
+<glyph unicode="&#xf005;" horiz-adv-x="1664" d="M1664 889q0 -22 -26 -48l-363 -354l86 -500q1 -7 1 -20q0 -21 -10.5 -35.5t-30.5 -14.5q-19 0 -40 12l-449 236l-449 -236q-22 -12 -40 -12q-21 0 -31.5 14.5t-10.5 35.5q0 6 2 20l86 500l-364 354q-25 27 -25 48q0 37 56 46l502 73l225 455q19 41 49 41t49 -41l225 -455 l502 -73q56 -9 56 -46z" />
+<glyph unicode="&#xf006;" horiz-adv-x="1664" d="M1137 532l306 297l-422 62l-189 382l-189 -382l-422 -62l306 -297l-73 -421l378 199l377 -199zM1664 889q0 -22 -26 -48l-363 -354l86 -500q1 -7 1 -20q0 -50 -41 -50q-19 0 -40 12l-449 236l-449 -236q-22 -12 -40 -12q-21 0 -31.5 14.5t-10.5 35.5q0 6 2 20l86 500 l-364 354q-25 27 -25 48q0 37 56 46l502 73l225 455q19 41 49 41t49 -41l225 -455l502 -73q56 -9 56 -46z" />
+<glyph unicode="&#xf007;" horiz-adv-x="1408" d="M1408 131q0 -120 -73 -189.5t-194 -69.5h-874q-121 0 -194 69.5t-73 189.5q0 53 3.5 103.5t14 109t26.5 108.5t43 97.5t62 81t85.5 53.5t111.5 20q9 0 42 -21.5t74.5 -48t108 -48t133.5 -21.5t133.5 21.5t108 48t74.5 48t42 21.5q61 0 111.5 -20t85.5 -53.5t62 -81 t43 -97.5t26.5 -108.5t14 -109t3.5 -103.5zM1088 1024q0 -159 -112.5 -271.5t-271.5 -112.5t-271.5 112.5t-112.5 271.5t112.5 271.5t271.5 112.5t271.5 -112.5t112.5 -271.5z" />
+<glyph unicode="&#xf008;" horiz-adv-x="1920" d="M384 -64v128q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h128q26 0 45 19t19 45zM384 320v128q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h128q26 0 45 19t19 45zM384 704v128q0 26 -19 45t-45 19h-128 q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h128q26 0 45 19t19 45zM1408 -64v512q0 26 -19 45t-45 19h-768q-26 0 -45 -19t-19 -45v-512q0 -26 19 -45t45 -19h768q26 0 45 19t19 45zM384 1088v128q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45 t45 -19h128q26 0 45 19t19 45zM1792 -64v128q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h128q26 0 45 19t19 45zM1408 704v512q0 26 -19 45t-45 19h-768q-26 0 -45 -19t-19 -45v-512q0 -26 19 -45t45 -19h768q26 0 45 19t19 45zM1792 320v128 q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h128q26 0 45 19t19 45zM1792 704v128q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h128q26 0 45 19t1
 9 45zM1792 1088v128q0 26 -19 45t-45 19h-128q-26 0 -45 -19 t-19 -45v-128q0 -26 19 -45t45 -19h128q26 0 45 19t19 45zM1920 1248v-1344q0 -66 -47 -113t-113 -47h-1600q-66 0 -113 47t-47 113v1344q0 66 47 113t113 47h1600q66 0 113 -47t47 -113z" />
+<glyph unicode="&#xf009;" horiz-adv-x="1664" d="M768 512v-384q0 -52 -38 -90t-90 -38h-512q-52 0 -90 38t-38 90v384q0 52 38 90t90 38h512q52 0 90 -38t38 -90zM768 1280v-384q0 -52 -38 -90t-90 -38h-512q-52 0 -90 38t-38 90v384q0 52 38 90t90 38h512q52 0 90 -38t38 -90zM1664 512v-384q0 -52 -38 -90t-90 -38 h-512q-52 0 -90 38t-38 90v384q0 52 38 90t90 38h512q52 0 90 -38t38 -90zM1664 1280v-384q0 -52 -38 -90t-90 -38h-512q-52 0 -90 38t-38 90v384q0 52 38 90t90 38h512q52 0 90 -38t38 -90z" />
+<glyph unicode="&#xf00a;" horiz-adv-x="1792" d="M512 288v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM512 800v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM1152 288v-192q0 -40 -28 -68t-68 -28h-320 q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM512 1312v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM1152 800v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28 h320q40 0 68 -28t28 -68zM1792 288v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM1152 1312v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM1792 800v-192 q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM1792 1312v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28
 t28 -68z" />
+<glyph unicode="&#xf00b;" horiz-adv-x="1792" d="M512 288v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM512 800v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM1792 288v-192q0 -40 -28 -68t-68 -28h-960 q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h960q40 0 68 -28t28 -68zM512 1312v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM1792 800v-192q0 -40 -28 -68t-68 -28h-960q-40 0 -68 28t-28 68v192q0 40 28 68t68 28 h960q40 0 68 -28t28 -68zM1792 1312v-192q0 -40 -28 -68t-68 -28h-960q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h960q40 0 68 -28t28 -68z" />
+<glyph unicode="&#xf00c;" horiz-adv-x="1792" d="M1671 970q0 -40 -28 -68l-724 -724l-136 -136q-28 -28 -68 -28t-68 28l-136 136l-362 362q-28 28 -28 68t28 68l136 136q28 28 68 28t68 -28l294 -295l656 657q28 28 68 28t68 -28l136 -136q28 -28 28 -68z" />
+<glyph unicode="&#xf00d;" horiz-adv-x="1408" d="M1298 214q0 -40 -28 -68l-136 -136q-28 -28 -68 -28t-68 28l-294 294l-294 -294q-28 -28 -68 -28t-68 28l-136 136q-28 28 -28 68t28 68l294 294l-294 294q-28 28 -28 68t28 68l136 136q28 28 68 28t68 -28l294 -294l294 294q28 28 68 28t68 -28l136 -136q28 -28 28 -68 t-28 -68l-294 -294l294 -294q28 -28 28 -68z" />
+<glyph unicode="&#xf00e;" horiz-adv-x="1664" d="M1024 736v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-224v-224q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v224h-224q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h224v224q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5v-224h224 q13 0 22.5 -9.5t9.5 -22.5zM1152 704q0 185 -131.5 316.5t-316.5 131.5t-316.5 -131.5t-131.5 -316.5t131.5 -316.5t316.5 -131.5t316.5 131.5t131.5 316.5zM1664 -128q0 -53 -37.5 -90.5t-90.5 -37.5q-54 0 -90 38l-343 342q-179 -124 -399 -124q-143 0 -273.5 55.5 t-225 150t-150 225t-55.5 273.5t55.5 273.5t150 225t225 150t273.5 55.5t273.5 -55.5t225 -150t150 -225t55.5 -273.5q0 -220 -124 -399l343 -343q37 -37 37 -90z" />
+<glyph unicode="&#xf010;" horiz-adv-x="1664" d="M1024 736v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-576q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h576q13 0 22.5 -9.5t9.5 -22.5zM1152 704q0 185 -131.5 316.5t-316.5 131.5t-316.5 -131.5t-131.5 -316.5t131.5 -316.5t316.5 -131.5t316.5 131.5t131.5 316.5z M1664 -128q0 -53 -37.5 -90.5t-90.5 -37.5q-54 0 -90 38l-343 342q-179 -124 -399 -124q-143 0 -273.5 55.5t-225 150t-150 225t-55.5 273.5t55.5 273.5t150 225t225 150t273.5 55.5t273.5 -55.5t225 -150t150 -225t55.5 -273.5q0 -220 -124 -399l343 -343q37 -37 37 -90z " />
+<glyph unicode="&#xf011;" d="M1536 640q0 -156 -61 -298t-164 -245t-245 -164t-298 -61t-298 61t-245 164t-164 245t-61 298q0 182 80.5 343t226.5 270q43 32 95.5 25t83.5 -50q32 -42 24.5 -94.5t-49.5 -84.5q-98 -74 -151.5 -181t-53.5 -228q0 -104 40.5 -198.5t109.5 -163.5t163.5 -109.5 t198.5 -40.5t198.5 40.5t163.5 109.5t109.5 163.5t40.5 198.5q0 121 -53.5 228t-151.5 181q-42 32 -49.5 84.5t24.5 94.5q31 43 84 50t95 -25q146 -109 226.5 -270t80.5 -343zM896 1408v-640q0 -52 -38 -90t-90 -38t-90 38t-38 90v640q0 52 38 90t90 38t90 -38t38 -90z" />
+<glyph unicode="&#xf012;" horiz-adv-x="1792" d="M256 96v-192q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h192q14 0 23 -9t9 -23zM640 224v-320q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v320q0 14 9 23t23 9h192q14 0 23 -9t9 -23zM1024 480v-576q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23 v576q0 14 9 23t23 9h192q14 0 23 -9t9 -23zM1408 864v-960q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v960q0 14 9 23t23 9h192q14 0 23 -9t9 -23zM1792 1376v-1472q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v1472q0 14 9 23t23 9h192q14 0 23 -9t9 -23z" />
+<glyph unicode="&#xf013;" d="M1024 640q0 106 -75 181t-181 75t-181 -75t-75 -181t75 -181t181 -75t181 75t75 181zM1536 749v-222q0 -12 -8 -23t-20 -13l-185 -28q-19 -54 -39 -91q35 -50 107 -138q10 -12 10 -25t-9 -23q-27 -37 -99 -108t-94 -71q-12 0 -26 9l-138 108q-44 -23 -91 -38 q-16 -136 -29 -186q-7 -28 -36 -28h-222q-14 0 -24.5 8.5t-11.5 21.5l-28 184q-49 16 -90 37l-141 -107q-10 -9 -25 -9q-14 0 -25 11q-126 114 -165 168q-7 10 -7 23q0 12 8 23q15 21 51 66.5t54 70.5q-27 50 -41 99l-183 27q-13 2 -21 12.5t-8 23.5v222q0 12 8 23t19 13 l186 28q14 46 39 92q-40 57 -107 138q-10 12 -10 24q0 10 9 23q26 36 98.5 107.5t94.5 71.5q13 0 26 -10l138 -107q44 23 91 38q16 136 29 186q7 28 36 28h222q14 0 24.5 -8.5t11.5 -21.5l28 -184q49 -16 90 -37l142 107q9 9 24 9q13 0 25 -10q129 -119 165 -170q7 -8 7 -22 q0 -12 -8 -23q-15 -21 -51 -66.5t-54 -70.5q26 -50 41 -98l183 -28q13 -2 21 -12.5t8 -23.5z" />
+<glyph unicode="&#xf014;" horiz-adv-x="1408" d="M512 800v-576q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v576q0 14 9 23t23 9h64q14 0 23 -9t9 -23zM768 800v-576q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v576q0 14 9 23t23 9h64q14 0 23 -9t9 -23zM1024 800v-576q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v576 q0 14 9 23t23 9h64q14 0 23 -9t9 -23zM1152 76v948h-896v-948q0 -22 7 -40.5t14.5 -27t10.5 -8.5h832q3 0 10.5 8.5t14.5 27t7 40.5zM480 1152h448l-48 117q-7 9 -17 11h-317q-10 -2 -17 -11zM1408 1120v-64q0 -14 -9 -23t-23 -9h-96v-948q0 -83 -47 -143.5t-113 -60.5h-832 q-66 0 -113 58.5t-47 141.5v952h-96q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h309l70 167q15 37 54 63t79 26h320q40 0 79 -26t54 -63l70 -167h309q14 0 23 -9t9 -23z" />
+<glyph unicode="&#xf015;" horiz-adv-x="1664" d="M1408 544v-480q0 -26 -19 -45t-45 -19h-384v384h-256v-384h-384q-26 0 -45 19t-19 45v480q0 1 0.5 3t0.5 3l575 474l575 -474q1 -2 1 -6zM1631 613l-62 -74q-8 -9 -21 -11h-3q-13 0 -21 7l-692 577l-692 -577q-12 -8 -24 -7q-13 2 -21 11l-62 74q-8 10 -7 23.5t11 21.5 l719 599q32 26 76 26t76 -26l244 -204v195q0 14 9 23t23 9h192q14 0 23 -9t9 -23v-408l219 -182q10 -8 11 -21.5t-7 -23.5z" />
+<glyph unicode="&#xf016;" horiz-adv-x="1280" d="M128 0h1024v768h-416q-40 0 -68 28t-28 68v416h-512v-1280zM768 896h299l-299 299v-299zM1280 768v-800q0 -40 -28 -68t-68 -28h-1088q-40 0 -68 28t-28 68v1344q0 40 28 68t68 28h544q40 0 88 -20t76 -48l408 -408q28 -28 48 -76t20 -88z" />
+<glyph unicode="&#xf017;" d="M1088 608v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-384q-13 0 -22.5 9.5t-9.5 22.5v448q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5v-352h288q13 0 22.5 -9.5t9.5 -22.5zM1280 640q0 104 -40.5 198.5t-109.5 163.5t-163.5 109.5t-198.5 40.5t-198.5 -40.5 t-163.5 -109.5t-109.5 -163.5t-40.5 -198.5t40.5 -198.5t109.5 -163.5t163.5 -109.5t198.5 -40.5t198.5 40.5t163.5 109.5t109.5 163.5t40.5 198.5zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5 t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+<glyph unicode="&#xf018;" horiz-adv-x="1920" d="M1111 540v4l-24 320q-1 13 -11 22.5t-23 9.5h-186q-13 0 -23 -9.5t-11 -22.5l-24 -320v-4q-1 -12 8 -20t21 -8h244q12 0 21 8t8 20zM1870 73q0 -73 -46 -73h-704q13 0 22 9.5t8 22.5l-20 256q-1 13 -11 22.5t-23 9.5h-272q-13 0 -23 -9.5t-11 -22.5l-20 -256 q-1 -13 8 -22.5t22 -9.5h-704q-46 0 -46 73q0 54 26 116l417 1044q8 19 26 33t38 14h339q-13 0 -23 -9.5t-11 -22.5l-15 -192q-1 -14 8 -23t22 -9h166q13 0 22 9t8 23l-15 192q-1 13 -11 22.5t-23 9.5h339q20 0 38 -14t26 -33l417 -1044q26 -62 26 -116z" />
+<glyph unicode="&#xf019;" horiz-adv-x="1664" d="M1339 729q17 -41 -14 -70l-448 -448q-18 -19 -45 -19t-45 19l-448 448q-31 29 -14 70q17 39 59 39h256v448q0 26 19 45t45 19h256q26 0 45 -19t19 -45v-448h256q42 0 59 -39zM1632 512q14 0 23 -9t9 -23v-576q0 -14 -9 -23t-23 -9h-1600q-14 0 -23 9t-9 23v576q0 14 9 23 t23 9h192q14 0 23 -9t9 -23v-352h1152v352q0 14 9 23t23 9h192z" />
+<glyph unicode="&#xf01a;" d="M1120 608q0 -12 -10 -24l-319 -319q-9 -9 -23 -9t-23 9l-320 320q-9 9 -9 23q0 13 9.5 22.5t22.5 9.5h192v352q0 13 9.5 22.5t22.5 9.5h192q13 0 22.5 -9.5t9.5 -22.5v-352h192q14 0 23 -9t9 -23zM1280 640q0 104 -40.5 198.5t-109.5 163.5t-163.5 109.5t-198.5 40.5 t-198.5 -40.5t-163.5 -109.5t-109.5 -163.5t-40.5 -198.5t40.5 -198.5t109.5 -163.5t163.5 -109.5t198.5 -40.5t198.5 40.5t163.5 109.5t109.5 163.5t40.5 198.5zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5 t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+<glyph unicode="&#xf01b;" d="M1120 672q0 -13 -9.5 -22.5t-22.5 -9.5h-192v-352q0 -13 -9.5 -22.5t-22.5 -9.5h-192q-13 0 -22.5 9.5t-9.5 22.5v352h-192q-14 0 -23 9t-9 23q0 12 10 24l319 319q9 9 23 9t23 -9l320 -320q9 -9 9 -23zM1280 640q0 104 -40.5 198.5t-109.5 163.5t-163.5 109.5 t-198.5 40.5t-198.5 -40.5t-163.5 -109.5t-109.5 -163.5t-40.5 -198.5t40.5 -198.5t109.5 -163.5t163.5 -109.5t198.5 -40.5t198.5 40.5t163.5 109.5t109.5 163.5t40.5 198.5zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5 t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+<glyph unicode="&#xf01c;" d="M1023 576h316q-1 3 -2.5 8t-2.5 8l-212 496h-708l-212 -496q-1 -2 -2.5 -8t-2.5 -8h316l95 -192h320zM1536 546v-482q0 -26 -19 -45t-45 -19h-1408q-26 0 -45 19t-19 45v482q0 62 25 123l238 552q10 25 36.5 42t52.5 17h832q26 0 52.5 -17t36.5 -42l238 -552 q25 -61 25 -123z" />
+<glyph unicode="&#xf01d;" d="M1152 640q0 -37 -33 -56l-512 -288q-14 -8 -31 -8t-32 9q-32 18 -32 55v576q0 37 32 55q31 20 63 1l512 -288q33 -19 33 -56zM1280 640q0 104 -40.5 198.5t-109.5 163.5t-163.5 109.5t-198.5 40.5t-198.5 -40.5t-163.5 -109.5t-109.5 -163.5t-40.5 -198.5t40.5 -198.5 t109.5 -163.5t163.5 -109.5t198.5 -40.5t198.5 40.5t163.5 109.5t109.5 163.5t40.5 198.5zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+<glyph unicode="&#xf01e;" d="M1536 1280v-448q0 -26 -19 -45t-45 -19h-448q-42 0 -59 40q-17 39 14 69l138 138q-148 137 -349 137q-104 0 -198.5 -40.5t-163.5 -109.5t-109.5 -163.5t-40.5 -198.5t40.5 -198.5t109.5 -163.5t163.5 -109.5t198.5 -40.5q169 0 304 99.5t185 261.5q7 23 30 23h199 q16 0 25 -12q10 -13 7 -27q-39 -175 -147.5 -312t-266 -213t-336.5 -76q-156 0 -298 61t-245 164t-164 245t-61 298t61 298t164 245t245 164t298 61q147 0 284.5 -55.5t244.5 -156.5l130 129q29 31 70 14q39 -17 39 -59z" />
+<glyph unicode="&#xf021;" d="M1511 480q0 -5 -1 -7q-64 -268 -268 -434.5t-478 -166.5q-146 0 -282.5 55t-243.5 157l-129 -129q-19 -19 -45 -19t-45 19t-19 45v448q0 26 19 45t45 19h448q26 0 45 -19t19 -45t-19 -45l-137 -137q71 -66 161 -102t187 -36q134 0 250 65t186 179q11 17 53 117 q8 23 30 23h192q13 0 22.5 -9.5t9.5 -22.5zM1536 1280v-448q0 -26 -19 -45t-45 -19h-448q-26 0 -45 19t-19 45t19 45l138 138q-148 137 -349 137q-134 0 -250 -65t-186 -179q-11 -17 -53 -117q-8 -23 -30 -23h-199q-13 0 -22.5 9.5t-9.5 22.5v7q65 268 270 434.5t480 166.5 q146 0 284 -55.5t245 -156.5l130 129q19 19 45 19t45 -19t19 -45z" />
+<glyph unicode="&#xf022;" horiz-adv-x="1792" d="M384 352v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM384 608v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M384 864v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM1536 352v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-960q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h960q13 0 22.5 -9.5t9.5 -22.5z M1536 608v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-960q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h960q13 0 22.5 -9.5t9.5 -22.5zM1536 864v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-960q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h960q13 0 22.5 -9.5 t9.5 -22.5zM1664 160v832q0 13 -9.5 22.5t-22.5 9.5h-1472q-13 0 -22.5 -9.5t-9.5 -22.5v-832q0 -13 9.5 -22.5t22.5 -9.5h1472q13 0 22.5 9.5t9.5 22.5zM1792 1248v-1088q0 -66 -47 -113t-113 -47h-1472q-66 0 -1
 13 47t-47 113v1088q0 66 47 113t113 47h1472q66 0 113 -47 t47 -113z" />
+<glyph unicode="&#xf023;" horiz-adv-x="1152" d="M704 512q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5q0 -37 19 -67t51 -47l-69 -229q-5 -15 5 -28t26 -13h192q16 0 26 13t5 28l-69 229q32 17 51 47t19 67zM320 768h512v192q0 106 -75 181t-181 75t-181 -75t-75 -181v-192zM1152 672v-576q0 -40 -28 -68 t-68 -28h-960q-40 0 -68 28t-28 68v576q0 40 28 68t68 28h32v192q0 184 132 316t316 132t316 -132t132 -316v-192h32q40 0 68 -28t28 -68z" />
+<glyph unicode="&#xf024;" horiz-adv-x="1792" d="M320 1280q0 -72 -64 -110v-1266q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v1266q-64 38 -64 110q0 53 37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1792 1216v-763q0 -25 -12.5 -38.5t-39.5 -27.5q-215 -116 -369 -116q-61 0 -123.5 22t-108.5 48 t-115.5 48t-142.5 22q-192 0 -464 -146q-17 -9 -33 -9q-26 0 -45 19t-19 45v742q0 32 31 55q21 14 79 43q236 120 421 120q107 0 200 -29t219 -88q38 -19 88 -19q54 0 117.5 21t110 47t88 47t54.5 21q26 0 45 -19t19 -45z" />
+<glyph unicode="&#xf025;" horiz-adv-x="1664" d="M1664 650q0 -166 -60 -314l-20 -49l-185 -33q-22 -83 -90.5 -136.5t-156.5 -53.5v-32q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v576q0 14 9 23t23 9h64q14 0 23 -9t9 -23v-32q71 0 130 -35.5t93 -95.5l68 12q29 95 29 193q0 148 -88 279t-236.5 209t-315.5 78 t-315.5 -78t-236.5 -209t-88 -279q0 -98 29 -193l68 -12q34 60 93 95.5t130 35.5v32q0 14 9 23t23 9h64q14 0 23 -9t9 -23v-576q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v32q-88 0 -156.5 53.5t-90.5 136.5l-185 33l-20 49q-60 148 -60 314q0 151 67 291t179 242.5 t266 163.5t320 61t320 -61t266 -163.5t179 -242.5t67 -291z" />
+<glyph unicode="&#xf026;" horiz-adv-x="768" d="M768 1184v-1088q0 -26 -19 -45t-45 -19t-45 19l-333 333h-262q-26 0 -45 19t-19 45v384q0 26 19 45t45 19h262l333 333q19 19 45 19t45 -19t19 -45z" />
+<glyph unicode="&#xf027;" horiz-adv-x="1152" d="M768 1184v-1088q0 -26 -19 -45t-45 -19t-45 19l-333 333h-262q-26 0 -45 19t-19 45v384q0 26 19 45t45 19h262l333 333q19 19 45 19t45 -19t19 -45zM1152 640q0 -76 -42.5 -141.5t-112.5 -93.5q-10 -5 -25 -5q-26 0 -45 18.5t-19 45.5q0 21 12 35.5t29 25t34 23t29 35.5 t12 57t-12 57t-29 35.5t-34 23t-29 25t-12 35.5q0 27 19 45.5t45 18.5q15 0 25 -5q70 -27 112.5 -93t42.5 -142z" />
+<glyph unicode="&#xf028;" horiz-adv-x="1664" d="M768 1184v-1088q0 -26 -19 -45t-45 -19t-45 19l-333 333h-262q-26 0 -45 19t-19 45v384q0 26 19 45t45 19h262l333 333q19 19 45 19t45 -19t19 -45zM1152 640q0 -76 -42.5 -141.5t-112.5 -93.5q-10 -5 -25 -5q-26 0 -45 18.5t-19 45.5q0 21 12 35.5t29 25t34 23t29 35.5 t12 57t-12 57t-29 35.5t-34 23t-29 25t-12 35.5q0 27 19 45.5t45 18.5q15 0 25 -5q70 -27 112.5 -93t42.5 -142zM1408 640q0 -153 -85 -282.5t-225 -188.5q-13 -5 -25 -5q-27 0 -46 19t-19 45q0 39 39 59q56 29 76 44q74 54 115.5 135.5t41.5 173.5t-41.5 173.5 t-115.5 135.5q-20 15 -76 44q-39 20 -39 59q0 26 19 45t45 19q13 0 26 -5q140 -59 225 -188.5t85 -282.5zM1664 640q0 -230 -127 -422.5t-338 -283.5q-13 -5 -26 -5q-26 0 -45 19t-19 45q0 36 39 59q7 4 22.5 10.5t22.5 10.5q46 25 82 51q123 91 192 227t69 289t-69 289 t-192 227q-36 26 -82 51q-7 4 -22.5 10.5t-22.5 10.5q-39 23 -39 59q0 26 19 45t45 19q13 0 26 -5q211 -91 338 -283.5t127 -422.5z" />
+<glyph unicode="&#xf029;" horiz-adv-x="1408" d="M384 384v-128h-128v128h128zM384 1152v-128h-128v128h128zM1152 1152v-128h-128v128h128zM128 129h384v383h-384v-383zM128 896h384v384h-384v-384zM896 896h384v384h-384v-384zM640 640v-640h-640v640h640zM1152 128v-128h-128v128h128zM1408 128v-128h-128v128h128z M1408 640v-384h-384v128h-128v-384h-128v640h384v-128h128v128h128zM640 1408v-640h-640v640h640zM1408 1408v-640h-640v640h640z" />
+<glyph unicode="&#xf02a;" horiz-adv-x="1792" d="M672 1408v-1536h-64v1536h64zM1408 1408v-1536h-64v1536h64zM1568 1408v-1536h-64v1536h64zM576 1408v-1536h-64v1536h64zM1280 1408v-1536h-256v1536h256zM896 1408v-1536h-128v1536h128zM448 1408v-1536h-128v1536h128zM1792 1408v-1536h-128v1536h128zM256 1408v-1536 h-256v1536h256z" />
+<glyph unicode="&#xf02b;" d="M448 1088q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1515 512q0 -53 -37 -90l-491 -492q-39 -37 -91 -37q-53 0 -90 37l-715 716q-38 37 -64.5 101t-26.5 117v416q0 52 38 90t90 38h416q53 0 117 -26.5t102 -64.5 l715 -714q37 -39 37 -91z" />
+<glyph unicode="&#xf02c;" horiz-adv-x="1920" d="M448 1088q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1515 512q0 -53 -37 -90l-491 -492q-39 -37 -91 -37q-53 0 -90 37l-715 716q-38 37 -64.5 101t-26.5 117v416q0 52 38 90t90 38h416q53 0 117 -26.5t102 -64.5 l715 -714q37 -39 37 -91zM1899 512q0 -53 -37 -90l-491 -492q-39 -37 -91 -37q-36 0 -59 14t-53 45l470 470q37 37 37 90q0 52 -37 91l-715 714q-38 38 -102 64.5t-117 26.5h224q53 0 117 -26.5t102 -64.5l715 -714q37 -39 37 -91z" />
+<glyph unicode="&#xf02d;" horiz-adv-x="1664" d="M1639 1058q40 -57 18 -129l-275 -906q-19 -64 -76.5 -107.5t-122.5 -43.5h-923q-77 0 -148.5 53.5t-99.5 131.5q-24 67 -2 127q0 4 3 27t4 37q1 8 -3 21.5t-3 19.5q2 11 8 21t16.5 23.5t16.5 23.5q23 38 45 91.5t30 91.5q3 10 0.5 30t-0.5 28q3 11 17 28t17 23 q21 36 42 92t25 90q1 9 -2.5 32t0.5 28q4 13 22 30.5t22 22.5q19 26 42.5 84.5t27.5 96.5q1 8 -3 25.5t-2 26.5q2 8 9 18t18 23t17 21q8 12 16.5 30.5t15 35t16 36t19.5 32t26.5 23.5t36 11.5t47.5 -5.5l-1 -3q38 9 51 9h761q74 0 114 -56t18 -130l-274 -906 q-36 -119 -71.5 -153.5t-128.5 -34.5h-869q-27 0 -38 -15q-11 -16 -1 -43q24 -70 144 -70h923q29 0 56 15.5t35 41.5l300 987q7 22 5 57q38 -15 59 -43zM575 1056q-4 -13 2 -22.5t20 -9.5h608q13 0 25.5 9.5t16.5 22.5l21 64q4 13 -2 22.5t-20 9.5h-608q-13 0 -25.5 -9.5 t-16.5 -22.5zM492 800q-4 -13 2 -22.5t20 -9.5h608q13 0 25.5 9.5t16.5 22.5l21 64q4 13 -2 22.5t-20 9.5h-608q-13 0 -25.5 -9.5t-16.5 -22.5z" />
+<glyph unicode="&#xf02e;" horiz-adv-x="1280" d="M1164 1408q23 0 44 -9q33 -13 52.5 -41t19.5 -62v-1289q0 -34 -19.5 -62t-52.5 -41q-19 -8 -44 -8q-48 0 -83 32l-441 424l-441 -424q-36 -33 -83 -33q-23 0 -44 9q-33 13 -52.5 41t-19.5 62v1289q0 34 19.5 62t52.5 41q21 9 44 9h1048z" />
+<glyph unicode="&#xf02f;" horiz-adv-x="1664" d="M384 0h896v256h-896v-256zM384 640h896v384h-160q-40 0 -68 28t-28 68v160h-640v-640zM1536 576q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1664 576v-416q0 -13 -9.5 -22.5t-22.5 -9.5h-224v-160q0 -40 -28 -68t-68 -28h-960q-40 0 -68 28t-28 68 v160h-224q-13 0 -22.5 9.5t-9.5 22.5v416q0 79 56.5 135.5t135.5 56.5h64v544q0 40 28 68t68 28h672q40 0 88 -20t76 -48l152 -152q28 -28 48 -76t20 -88v-256h64q79 0 135.5 -56.5t56.5 -135.5z" />
+<glyph unicode="&#xf030;" horiz-adv-x="1920" d="M960 864q119 0 203.5 -84.5t84.5 -203.5t-84.5 -203.5t-203.5 -84.5t-203.5 84.5t-84.5 203.5t84.5 203.5t203.5 84.5zM1664 1280q106 0 181 -75t75 -181v-896q0 -106 -75 -181t-181 -75h-1408q-106 0 -181 75t-75 181v896q0 106 75 181t181 75h224l51 136 q19 49 69.5 84.5t103.5 35.5h512q53 0 103.5 -35.5t69.5 -84.5l51 -136h224zM960 128q185 0 316.5 131.5t131.5 316.5t-131.5 316.5t-316.5 131.5t-316.5 -131.5t-131.5 -316.5t131.5 -316.5t316.5 -131.5z" />
+<glyph unicode="&#xf031;" horiz-adv-x="1664" d="M725 977l-170 -450q73 -1 153.5 -2t119 -1.5t52.5 -0.5l29 2q-32 95 -92 241q-53 132 -92 211zM21 -128h-21l2 79q22 7 80 18q89 16 110 31q20 16 48 68l237 616l280 724h75h53l11 -21l205 -480q103 -242 124 -297q39 -102 96 -235q26 -58 65 -164q24 -67 65 -149 q22 -49 35 -57q22 -19 69 -23q47 -6 103 -27q6 -39 6 -57q0 -14 -1 -26q-80 0 -192 8q-93 8 -189 8q-79 0 -135 -2l-200 -11l-58 -2q0 45 4 78l131 28q56 13 68 23q12 12 12 27t-6 32l-47 114l-92 228l-450 2q-29 -65 -104 -274q-23 -64 -23 -84q0 -31 17 -43 q26 -21 103 -32q3 0 13.5 -2t30 -5t40.5 -6q1 -28 1 -58q0 -17 -2 -27q-66 0 -349 20l-48 -8q-81 -14 -167 -14z" />
+<glyph unicode="&#xf032;" horiz-adv-x="1408" d="M555 15q76 -32 140 -32q131 0 216 41t122 113q38 70 38 181q0 114 -41 180q-58 94 -141 126q-80 32 -247 32q-74 0 -101 -10v-144l-1 -173l3 -270q0 -15 12 -44zM541 761q43 -7 109 -7q175 0 264 65t89 224q0 112 -85 187q-84 75 -255 75q-52 0 -130 -13q0 -44 2 -77 q7 -122 6 -279l-1 -98q0 -43 1 -77zM0 -128l2 94q45 9 68 12q77 12 123 31q17 27 21 51q9 66 9 194l-2 497q-5 256 -9 404q-1 87 -11 109q-1 4 -12 12q-18 12 -69 15q-30 2 -114 13l-4 83l260 6l380 13l45 1q5 0 14 0.5t14 0.5q1 0 21.5 -0.5t40.5 -0.5h74q88 0 191 -27 q43 -13 96 -39q57 -29 102 -76q44 -47 65 -104t21 -122q0 -70 -32 -128t-95 -105q-26 -20 -150 -77q177 -41 267 -146q92 -106 92 -236q0 -76 -29 -161q-21 -62 -71 -117q-66 -72 -140 -108q-73 -36 -203 -60q-82 -15 -198 -11l-197 4q-84 2 -298 -11q-33 -3 -272 -11z" />
+<glyph unicode="&#xf033;" horiz-adv-x="1024" d="M0 -126l17 85q4 1 77 20q76 19 116 39q29 37 41 101l27 139l56 268l12 64q8 44 17 84.5t16 67t12.5 46.5t9 30.5t3.5 11.5l29 157l16 63l22 135l8 50v38q-41 22 -144 28q-28 2 -38 4l19 103l317 -14q39 -2 73 -2q66 0 214 9q33 2 68 4.5t36 2.5q-2 -19 -6 -38 q-7 -29 -13 -51q-55 -19 -109 -31q-64 -16 -101 -31q-12 -31 -24 -88q-9 -44 -13 -82q-44 -199 -66 -306l-61 -311l-38 -158l-43 -235l-12 -45q-2 -7 1 -27q64 -15 119 -21q36 -5 66 -10q-1 -29 -7 -58q-7 -31 -9 -41q-18 0 -23 -1q-24 -2 -42 -2q-9 0 -28 3q-19 4 -145 17 l-198 2q-41 1 -174 -11q-74 -7 -98 -9z" />
+<glyph unicode="&#xf034;" horiz-adv-x="1792" d="M81 1407l54 -27q20 -5 211 -5h130l19 3l115 1l215 -1h293l34 -2q14 -1 28 7t21 16l7 8l42 1q15 0 28 -1v-104.5t1 -131.5l1 -100l-1 -58q0 -32 -4 -51q-39 -15 -68 -18q-25 43 -54 128q-8 24 -15.5 62.5t-11.5 65.5t-6 29q-13 15 -27 19q-7 2 -42.5 2t-103.5 -1t-111 -1 q-34 0 -67 -5q-10 -97 -8 -136l1 -152v-332l3 -359l-1 -147q-1 -46 11 -85q49 -25 89 -32q2 0 18 -5t44 -13t43 -12q30 -8 50 -18q5 -45 5 -50q0 -10 -3 -29q-14 -1 -34 -1q-110 0 -187 10q-72 8 -238 8q-88 0 -233 -14q-48 -4 -70 -4q-2 22 -2 26l-1 26v9q21 33 79 49 q139 38 159 50q9 21 12 56q8 192 6 433l-5 428q-1 62 -0.5 118.5t0.5 102.5t-2 57t-6 15q-6 5 -14 6q-38 6 -148 6q-43 0 -100 -13.5t-73 -24.5q-13 -9 -22 -33t-22 -75t-24 -84q-6 -19 -19.5 -32t-20.5 -13q-44 27 -56 44v297v86zM1744 128q33 0 42 -18.5t-11 -44.5 l-126 -162q-20 -26 -49 -26t-49 26l-126 162q-20 26 -11 44.5t42 18.5h80v1024h-80q-33 0 -42 18.5t11 44.5l126 162q20 26 49 26t49 -26l126 -162q20 -26 11 -44.5t-42 -18.5h-80v-1024h80z" />
+<glyph unicode="&#xf035;" d="M81 1407l54 -27q20 -5 211 -5h130l19 3l115 1l446 -1h318l34 -2q14 -1 28 7t21 16l7 8l42 1q15 0 28 -1v-104.5t1 -131.5l1 -100l-1 -58q0 -32 -4 -51q-39 -15 -68 -18q-25 43 -54 128q-8 24 -15.5 62.5t-11.5 65.5t-6 29q-13 15 -27 19q-7 2 -58.5 2t-138.5 -1t-128 -1 q-94 0 -127 -5q-10 -97 -8 -136l1 -152v52l3 -359l-1 -147q-1 -46 11 -85q49 -25 89 -32q2 0 18 -5t44 -13t43 -12q30 -8 50 -18q5 -45 5 -50q0 -10 -3 -29q-14 -1 -34 -1q-110 0 -187 10q-72 8 -238 8q-82 0 -233 -13q-45 -5 -70 -5q-2 22 -2 26l-1 26v9q21 33 79 49 q139 38 159 50q9 21 12 56q6 137 6 433l-5 44q0 265 -2 278q-2 11 -6 15q-6 5 -14 6q-38 6 -148 6q-50 0 -168.5 -14t-132.5 -24q-13 -9 -22 -33t-22 -75t-24 -84q-6 -19 -19.5 -32t-20.5 -13q-44 27 -56 44v297v86zM1505 113q26 -20 26 -49t-26 -49l-162 -126 q-26 -20 -44.5 -11t-18.5 42v80h-1024v-80q0 -33 -18.5 -42t-44.5 11l-162 126q-26 20 -26 49t26 49l162 126q26 20 44.5 11t18.5 -42v-80h1024v80q0 33 18.5 42t44.5 -11z" />
+<glyph unicode="&#xf036;" horiz-adv-x="1792" d="M1792 192v-128q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1664q26 0 45 -19t19 -45zM1408 576v-128q0 -26 -19 -45t-45 -19h-1280q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1280q26 0 45 -19t19 -45zM1664 960v-128q0 -26 -19 -45 t-45 -19h-1536q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1536q26 0 45 -19t19 -45zM1280 1344v-128q0 -26 -19 -45t-45 -19h-1152q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1152q26 0 45 -19t19 -45z" />
+<glyph unicode="&#xf037;" horiz-adv-x="1792" d="M1792 192v-128q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1664q26 0 45 -19t19 -45zM1408 576v-128q0 -26 -19 -45t-45 -19h-896q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h896q26 0 45 -19t19 -45zM1664 960v-128q0 -26 -19 -45t-45 -19 h-1408q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1408q26 0 45 -19t19 -45zM1280 1344v-128q0 -26 -19 -45t-45 -19h-640q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h640q26 0 45 -19t19 -45z" />
+<glyph unicode="&#xf038;" horiz-adv-x="1792" d="M1792 192v-128q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1664q26 0 45 -19t19 -45zM1792 576v-128q0 -26 -19 -45t-45 -19h-1280q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1280q26 0 45 -19t19 -45zM1792 960v-128q0 -26 -19 -45 t-45 -19h-1536q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1536q26 0 45 -19t19 -45zM1792 1344v-128q0 -26 -19 -45t-45 -19h-1152q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1152q26 0 45 -19t19 -45z" />
+<glyph unicode="&#xf039;" horiz-adv-x="1792" d="M1792 192v-128q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1664q26 0 45 -19t19 -45zM1792 576v-128q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1664q26 0 45 -19t19 -45zM1792 960v-128q0 -26 -19 -45 t-45 -19h-1664q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1664q26 0 45 -19t19 -45zM1792 1344v-128q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1664q26 0 45 -19t19 -45z" />
+<glyph unicode="&#xf03a;" horiz-adv-x="1792" d="M256 224v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-192q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h192q13 0 22.5 -9.5t9.5 -22.5zM256 608v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-192q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h192q13 0 22.5 -9.5 t9.5 -22.5zM256 992v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-192q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h192q13 0 22.5 -9.5t9.5 -22.5zM1792 224v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1344q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1344 q13 0 22.5 -9.5t9.5 -22.5zM256 1376v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-192q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h192q13 0 22.5 -9.5t9.5 -22.5zM1792 608v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1344q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5 t22.5 9.5h1344q13 0 22.5 -9.5t9.5 -22.5zM1792 992v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1344q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1344q13 0 22.5 -9.5t9.5 -22.5zM1792 1376v-192q0 -13 -9.5 -22.5t
 -22.5 -9.5h-1344q-13 0 -22.5 9.5t-9.5 22.5v192 q0 13 9.5 22.5t22.5 9.5h1344q13 0 22.5 -9.5t9.5 -22.5z" />
+<glyph unicode="&#xf03b;" horiz-adv-x="1792" d="M384 992v-576q0 -13 -9.5 -22.5t-22.5 -9.5q-14 0 -23 9l-288 288q-9 9 -9 23t9 23l288 288q9 9 23 9q13 0 22.5 -9.5t9.5 -22.5zM1792 224v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1728q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1728q13 0 22.5 -9.5 t9.5 -22.5zM1792 608v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1088q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1088q13 0 22.5 -9.5t9.5 -22.5zM1792 992v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1088q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1088 q13 0 22.5 -9.5t9.5 -22.5zM1792 1376v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1728q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1728q13 0 22.5 -9.5t9.5 -22.5z" />
+<glyph unicode="&#xf03c;" horiz-adv-x="1792" d="M352 704q0 -14 -9 -23l-288 -288q-9 -9 -23 -9q-13 0 -22.5 9.5t-9.5 22.5v576q0 13 9.5 22.5t22.5 9.5q14 0 23 -9l288 -288q9 -9 9 -23zM1792 224v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1728q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1728q13 0 22.5 -9.5 t9.5 -22.5zM1792 608v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1088q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1088q13 0 22.5 -9.5t9.5 -22.5zM1792 992v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1088q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1088 q13 0 22.5 -9.5t9.5 -22.5zM1792 1376v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1728q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1728q13 0 22.5 -9.5t9.5 -22.5z" />
+<glyph unicode="&#xf03d;" horiz-adv-x="1920" d="M1900 1278q20 -8 20 -30v-1216q0 -22 -20 -30q-8 -2 -12 -2q-12 0 -23 9l-585 586v-307q0 -119 -84.5 -203.5t-203.5 -84.5h-704q-119 0 -203.5 84.5t-84.5 203.5v704q0 119 84.5 203.5t203.5 84.5h704q119 0 203.5 -84.5t84.5 -203.5v-307l585 586q16 15 35 7z" />
+<glyph unicode="&#xf03e;" horiz-adv-x="1920" d="M640 960q0 -80 -56 -136t-136 -56t-136 56t-56 136t56 136t136 56t136 -56t56 -136zM1664 576v-448h-1408v192l320 320l160 -160l512 512zM1760 1280h-1600q-13 0 -22.5 -9.5t-9.5 -22.5v-1216q0 -13 9.5 -22.5t22.5 -9.5h1600q13 0 22.5 9.5t9.5 22.5v1216 q0 13 -9.5 22.5t-22.5 9.5zM1920 1248v-1216q0 -66 -47 -113t-113 -47h-1600q-66 0 -113 47t-47 113v1216q0 66 47 113t113 47h1600q66 0 113 -47t47 -113z" />
+<glyph unicode="&#xf040;" d="M363 0l91 91l-235 235l-91 -91v-107h128v-128h107zM886 928q0 22 -22 22q-10 0 -17 -7l-542 -542q-7 -7 -7 -17q0 -22 22 -22q10 0 17 7l542 542q7 7 7 17zM832 1120l416 -416l-832 -832h-416v416zM1515 1024q0 -53 -37 -90l-166 -166l-416 416l166 165q36 38 90 38 q53 0 91 -38l235 -234q37 -39 37 -91z" />
+<glyph unicode="&#xf041;" horiz-adv-x="1024" d="M768 896q0 106 -75 181t-181 75t-181 -75t-75 -181t75 -181t181 -75t181 75t75 181zM1024 896q0 -109 -33 -179l-364 -774q-16 -33 -47.5 -52t-67.5 -19t-67.5 19t-46.5 52l-365 774q-33 70 -33 179q0 212 150 362t362 150t362 -150t150 -362z" />
+<glyph unicode="&#xf042;" d="M768 1408q209 0 385.5 -103t279.5 -279.5t103 -385.5t-103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103zM256 640q0 -104 40.5 -198.5t109.5 -163.5t163.5 -109.5t198.5 -40.5v1024q-104 0 -198.5 -40.5 t-163.5 -109.5t-109.5 -163.5t-40.5 -198.5z" />
+<glyph unicode="&#xf043;" horiz-adv-x="1024" d="M512 384q0 36 -20 69q-1 1 -15.5 22.5t-25.5 38t-25 44t-21 50.5q-4 16 -21 16t-21 -16q-7 -23 -21 -50.5t-25 -44t-25.5 -38t-15.5 -22.5q-20 -33 -20 -69q0 -53 37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1024 512q0 -212 -150 -362t-362 -150t-362 150t-150 362 q0 145 81 275q6 9 62.5 90.5t101 151t99.5 178t83 201.5q9 30 34 47t51 17t51.5 -17t33.5 -47q28 -93 83 -201.5t99.5 -178t101 -151t62.5 -90.5q81 -127 81 -275z" />
+<glyph unicode="&#xf044;" horiz-adv-x="1792" d="M888 352l116 116l-152 152l-116 -116v-56h96v-96h56zM1328 1072q-16 16 -33 -1l-350 -350q-17 -17 -1 -33t33 1l350 350q17 17 1 33zM1408 478v-190q0 -119 -84.5 -203.5t-203.5 -84.5h-832q-119 0 -203.5 84.5t-84.5 203.5v832q0 119 84.5 203.5t203.5 84.5h832 q63 0 117 -25q15 -7 18 -23q3 -17 -9 -29l-49 -49q-14 -14 -32 -8q-23 6 -45 6h-832q-66 0 -113 -47t-47 -113v-832q0 -66 47 -113t113 -47h832q66 0 113 47t47 113v126q0 13 9 22l64 64q15 15 35 7t20 -29zM1312 1216l288 -288l-672 -672h-288v288zM1756 1084l-92 -92 l-288 288l92 92q28 28 68 28t68 -28l152 -152q28 -28 28 -68t-28 -68z" />
+<glyph unicode="&#xf045;" horiz-adv-x="1664" d="M1408 547v-259q0 -119 -84.5 -203.5t-203.5 -84.5h-832q-119 0 -203.5 84.5t-84.5 203.5v832q0 119 84.5 203.5t203.5 84.5h255v0q13 0 22.5 -9.5t9.5 -22.5q0 -27 -26 -32q-77 -26 -133 -60q-10 -4 -16 -4h-112q-66 0 -113 -47t-47 -113v-832q0 -66 47 -113t113 -47h832 q66 0 113 47t47 113v214q0 19 18 29q28 13 54 37q16 16 35 8q21 -9 21 -29zM1645 1043l-384 -384q-18 -19 -45 -19q-12 0 -25 5q-39 17 -39 59v192h-160q-323 0 -438 -131q-119 -137 -74 -473q3 -23 -20 -34q-8 -2 -12 -2q-16 0 -26 13q-10 14 -21 31t-39.5 68.5t-49.5 99.5 t-38.5 114t-17.5 122q0 49 3.5 91t14 90t28 88t47 81.5t68.5 74t94.5 61.5t124.5 48.5t159.5 30.5t196.5 11h160v192q0 42 39 59q13 5 25 5q26 0 45 -19l384 -384q19 -19 19 -45t-19 -45z" />
+<glyph unicode="&#xf046;" horiz-adv-x="1664" d="M1408 606v-318q0 -119 -84.5 -203.5t-203.5 -84.5h-832q-119 0 -203.5 84.5t-84.5 203.5v832q0 119 84.5 203.5t203.5 84.5h832q63 0 117 -25q15 -7 18 -23q3 -17 -9 -29l-49 -49q-10 -10 -23 -10q-3 0 -9 2q-23 6 -45 6h-832q-66 0 -113 -47t-47 -113v-832 q0 -66 47 -113t113 -47h832q66 0 113 47t47 113v254q0 13 9 22l64 64q10 10 23 10q6 0 12 -3q20 -8 20 -29zM1639 1095l-814 -814q-24 -24 -57 -24t-57 24l-430 430q-24 24 -24 57t24 57l110 110q24 24 57 24t57 -24l263 -263l647 647q24 24 57 24t57 -24l110 -110 q24 -24 24 -57t-24 -57z" />
+<glyph unicode="&#xf047;" horiz-adv-x="1792" d="M1792 640q0 -26 -19 -45l-256 -256q-19 -19 -45 -19t-45 19t-19 45v128h-384v-384h128q26 0 45 -19t19 -45t-19 -45l-256 -256q-19 -19 -45 -19t-45 19l-256 256q-19 19 -19 45t19 45t45 19h128v384h-384v-128q0 -26 -19 -45t-45 -19t-45 19l-256 256q-19 19 -19 45 t19 45l256 256q19 19 45 19t45 -19t19 -45v-128h384v384h-128q-26 0 -45 19t-19 45t19 45l256 256q19 19 45 19t45 -19l256 -256q19 -19 19 -45t-19 -45t-45 -19h-128v-384h384v128q0 26 19 45t45 19t45 -19l256 -256q19 -19 19 -45z" />
+<glyph unicode="&#xf048;" horiz-adv-x="1024" d="M979 1395q19 19 32 13t13 -32v-1472q0 -26 -13 -32t-32 13l-710 710q-9 9 -13 19v-678q0 -26 -19 -45t-45 -19h-128q-26 0 -45 19t-19 45v1408q0 26 19 45t45 19h128q26 0 45 -19t19 -45v-678q4 11 13 19z" />
+<glyph unicode="&#xf049;" horiz-adv-x="1792" d="M1747 1395q19 19 32 13t13 -32v-1472q0 -26 -13 -32t-32 13l-710 710q-9 9 -13 19v-710q0 -26 -13 -32t-32 13l-710 710q-9 9 -13 19v-678q0 -26 -19 -45t-45 -19h-128q-26 0 -45 19t-19 45v1408q0 26 19 45t45 19h128q26 0 45 -19t19 -45v-678q4 11 13 19l710 710 q19 19 32 13t13 -32v-710q4 11 13 19z" />
+<glyph unicode="&#xf04a;" horiz-adv-x="1664" d="M1619 1395q19 19 32 13t13 -32v-1472q0 -26 -13 -32t-32 13l-710 710q-8 9 -13 19v-710q0 -26 -13 -32t-32 13l-710 710q-19 19 -19 45t19 45l710 710q19 19 32 13t13 -32v-710q5 11 13 19z" />
+<glyph unicode="&#xf04b;" horiz-adv-x="1408" d="M1384 609l-1328 -738q-23 -13 -39.5 -3t-16.5 36v1472q0 26 16.5 36t39.5 -3l1328 -738q23 -13 23 -31t-23 -31z" />
+<glyph unicode="&#xf04c;" d="M1536 1344v-1408q0 -26 -19 -45t-45 -19h-512q-26 0 -45 19t-19 45v1408q0 26 19 45t45 19h512q26 0 45 -19t19 -45zM640 1344v-1408q0 -26 -19 -45t-45 -19h-512q-26 0 -45 19t-19 45v1408q0 26 19 45t45 19h512q26 0 45 -19t19 -45z" />
+<glyph unicode="&#xf04d;" d="M1536 1344v-1408q0 -26 -19 -45t-45 -19h-1408q-26 0 -45 19t-19 45v1408q0 26 19 45t45 19h1408q26 0 45 -19t19 -45z" />
+<glyph unicode="&#xf04e;" horiz-adv-x="1664" d="M45 -115q-19 -19 -32 -13t-13 32v1472q0 26 13 32t32 -13l710 -710q8 -8 13 -19v710q0 26 13 32t32 -13l710 -710q19 -19 19 -45t-19 -45l-710 -710q-19 -19 -32 -13t-13 32v710q-5 -10 -13 -19z" />
+<glyph unicode="&#xf050;" horiz-adv-x="1792" d="M45 -115q-19 -19 -32 -13t-13 32v1472q0 26 13 32t32 -13l710 -710q8 -8 13 -19v710q0 26 13 32t32 -13l710 -710q8 -8 13 -19v678q0 26 19 45t45 19h128q26 0 45 -19t19 -45v-1408q0 -26 -19 -45t-45 -19h-128q-26 0 -45 19t-19 45v678q-5 -10 -13 -19l-710 -710 q-19 -19 -32 -13t-13 32v710q-5 -10 -13 -19z" />
+<glyph unicode="&#xf051;" horiz-adv-x="1024" d="M45 -115q-19 -19 -32 -13t-13 32v1472q0 26 13 32t32 -13l710 -710q8 -8 13 -19v678q0 26 19 45t45 19h128q26 0 45 -19t19 -45v-1408q0 -26 -19 -45t-45 -19h-128q-26 0 -45 19t-19 45v678q-5 -10 -13 -19z" />
+<glyph unicode="&#xf052;" horiz-adv-x="1538" d="M14 557l710 710q19 19 45 19t45 -19l710 -710q19 -19 13 -32t-32 -13h-1472q-26 0 -32 13t13 32zM1473 0h-1408q-26 0 -45 19t-19 45v256q0 26 19 45t45 19h1408q26 0 45 -19t19 -45v-256q0 -26 -19 -45t-45 -19z" />
+<glyph unicode="&#xf053;" horiz-adv-x="1152" d="M742 -37l-652 651q-37 37 -37 90.5t37 90.5l652 651q37 37 90.5 37t90.5 -37l75 -75q37 -37 37 -90.5t-37 -90.5l-486 -486l486 -485q37 -38 37 -91t-37 -90l-75 -75q-37 -37 -90.5 -37t-90.5 37z" />
+<glyph unicode="&#xf054;" horiz-adv-x="1152" d="M1099 704q0 -52 -37 -91l-652 -651q-37 -37 -90 -37t-90 37l-76 75q-37 39 -37 91q0 53 37 90l486 486l-486 485q-37 39 -37 91q0 53 37 90l76 75q36 38 90 38t90 -38l652 -651q37 -37 37 -90z" />
+<glyph unicode="&#xf055;" d="M1216 576v128q0 26 -19 45t-45 19h-256v256q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-256h-256q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h256v-256q0 -26 19 -45t45 -19h128q26 0 45 19t19 45v256h256q26 0 45 19t19 45zM1536 640q0 -209 -103 -385.5 t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+<glyph unicode="&#xf056;" d="M1216 576v128q0 26 -19 45t-45 19h-768q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h768q26 0 45 19t19 45zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5 t103 -385.5z" />
+<glyph unicode="&#xf057;" d="M1149 414q0 26 -19 45l-181 181l181 181q19 19 19 45q0 27 -19 46l-90 90q-19 19 -46 19q-26 0 -45 -19l-181 -181l-181 181q-19 19 -45 19q-27 0 -46 -19l-90 -90q-19 -19 -19 -46q0 -26 19 -45l181 -181l-181 -181q-19 -19 -19 -45q0 -27 19 -46l90 -90q19 -19 46 -19 q26 0 45 19l181 181l181 -181q19 -19 45 -19q27 0 46 19l90 90q19 19 19 46zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+<glyph unicode="&#xf058;" d="M1284 802q0 28 -18 46l-91 90q-19 19 -45 19t-45 -19l-408 -407l-226 226q-19 19 -45 19t-45 -19l-91 -90q-18 -18 -18 -46q0 -27 18 -45l362 -362q19 -19 45 -19q27 0 46 19l543 543q18 18 18 45zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103 t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+<glyph unicode="&#xf059;" d="M896 160v192q0 13 -9.5 22.5t-22.5 9.5h-192q-13 0 -22.5 -9.5t-9.5 -22.5v-192q0 -13 9.5 -22.5t22.5 -9.5h192q13 0 22.5 9.5t9.5 22.5zM1152 832q0 97 -58.5 172t-144.5 111.5t-181 36.5t-181 -36.5t-144.5 -111.5t-58.5 -172v-11v-13t1 -11.5t3 -11.5t5.5 -8t9 -7 t13.5 -2h192q14 0 23 9t9 23q0 12 11 27q19 31 50.5 50t66.5 19q39 0 83 -21.5t44 -57.5q0 -33 -26.5 -58t-63.5 -44t-74.5 -41.5t-64 -63.5t-26.5 -98v-11v-13t1 -11.5t3 -11.5t5.5 -8t9 -7t13.5 -2h192q17 0 24 10.5t8 24.5t13.5 33t37.5 32q60 33 70 39q62 44 98.5 108 t36.5 137zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+<glyph unicode="&#xf05a;" d="M1024 160v64q0 14 -9 23t-23 9h-96v480q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h96v-384h-96q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h448q14 0 23 9t9 23zM896 928v192q0 14 -9 23t-23 9h-192q-14 0 -23 -9t-9 -23v-192q0 -14 9 -23 t23 -9h192q14 0 23 9t9 23zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+<glyph unicode="&#xf05b;" d="M1197 512h-109q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h109q-32 108 -112.5 188.5t-188.5 112.5v-109q0 -26 -19 -45t-45 -19h-128q-26 0 -45 19t-19 45v109q-108 -32 -188.5 -112.5t-112.5 -188.5h109q26 0 45 -19t19 -45v-128q0 -26 -19 -45t-45 -19h-109 q32 -108 112.5 -188.5t188.5 -112.5v109q0 26 19 45t45 19h128q26 0 45 -19t19 -45v-109q108 32 188.5 112.5t112.5 188.5zM1536 704v-128q0 -26 -19 -45t-45 -19h-143q-37 -161 -154.5 -278.5t-278.5 -154.5v-143q0 -26 -19 -45t-45 -19h-128q-26 0 -45 19t-19 45v143 q-161 37 -278.5 154.5t-154.5 278.5h-143q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h143q37 161 154.5 278.5t278.5 154.5v143q0 26 19 45t45 19h128q26 0 45 -19t19 -45v-143q161 -37 278.5 -154.5t154.5 -278.5h143q26 0 45 -19t19 -45z" />
+<glyph unicode="&#xf05c;" d="M1125 448q0 -27 -18 -45l-102 -102q-18 -18 -45 -18t-45 18l-147 147l-147 -147q-18 -18 -45 -18t-45 18l-102 102q-18 18 -18 45t18 45l147 147l-147 147q-18 18 -18 45t18 45l102 102q18 18 45 18t45 -18l147 -147l147 147q18 18 45 18t45 -18l102 -102q18 -18 18 -45 t-18 -45l-147 -147l147 -147q18 -18 18 -45zM1280 640q0 104 -40.5 198.5t-109.5 163.5t-163.5 109.5t-198.5 40.5t-198.5 -40.5t-163.5 -109.5t-109.5 -163.5t-40.5 -198.5t40.5 -198.5t109.5 -163.5t163.5 -109.5t198.5 -40.5t198.5 40.5t163.5 109.5t109.5 163.5 t40.5 198.5zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+<glyph unicode="&#xf05d;" d="M1189 768q0 -27 -18 -45l-320 -320l-102 -102q-18 -18 -45 -18t-45 18l-102 102l-192 192q-18 18 -18 45t18 45l102 102q18 18 45 18t45 -18l147 -147l275 275q18 18 45 18t45 -18l102 -102q18 -18 18 -45zM1280 640q0 104 -40.5 198.5t-109.5 163.5t-163.5 109.5 t-198.5 40.5t-198.5 -40.5t-163.5 -109.5t-109.5 -163.5t-40.5 -198.5t40.5 -198.5t109.5 -163.5t163.5 -109.5t198.5 -40.5t198.5 40.5t163.5 109.5t109.5 163.5t40.5 198.5zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5 t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+<glyph unicode="&#xf05e;" d="M1280 640q0 139 -71 260l-701 -701q121 -71 260 -71q104 0 198.5 40.5t163.5 109.5t109.5 163.5t40.5 198.5zM327 380l701 701q-121 71 -260 71q-104 0 -198.5 -40.5t-163.5 -109.5t-109.5 -163.5t-40.5 -198.5q0 -139 71 -260zM1536 640q0 -209 -103 -385.5 t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+<glyph unicode="&#xf060;" d="M1536 640v-128q0 -53 -32.5 -90.5t-84.5 -37.5h-704l293 -294q38 -36 38 -90t-38 -90l-75 -76q-37 -37 -90 -37q-52 0 -91 37l-651 652q-37 37 -37 90q0 52 37 91l651 650q38 38 91 38q52 0 90 -38l75 -74q38 -38 38 -91t-38 -91l-293 -293h704q52 0 84.5 -37.5 t32.5 -90.5z" />
+<glyph unicode="&#xf061;" d="M1472 576q0 -54 -37 -91l-651 -651q-39 -37 -91 -37q-51 0 -90 37l-75 75q-38 38 -38 91t38 91l293 293h-704q-52 0 -84.5 37.5t-32.5 90.5v128q0 53 32.5 90.5t84.5 37.5h704l-293 294q-38 36 -38 90t38 90l75 75q38 38 90 38q53 0 91 -38l651 -651q37 -35 37 -90z" />
+<glyph unicode="&#xf062;" horiz-adv-x="1664" d="M1611 565q0 -51 -37 -90l-75 -75q-38 -38 -91 -38q-54 0 -90 38l-294 293v-704q0 -52 -37.5 -84.5t-90.5 -32.5h-128q-53 0 -90.5 32.5t-37.5 84.5v704l-294 -293q-36 -38 -90 -38t-90 38l-75 75q-38 38 -38 90q0 53 38 91l651 651q35 37 90 37q54 0 91 -37l651 -651 q37 -39 37 -91z" />
+<glyph unicode="&#xf063;" horiz-adv-x="1664" d="M1611 704q0 -53 -37 -90l-651 -652q-39 -37 -91 -37q-53 0 -90 37l-651 652q-38 36 -38 90q0 53 38 91l74 75q39 37 91 37q53 0 90 -37l294 -294v704q0 52 38 90t90 38h128q52 0 90 -38t38 -90v-704l294 294q37 37 90 37q52 0 91 -37l75 -75q37 -39 37 -91z" />
+<glyph unicode="&#xf064;" horiz-adv-x="1792" d="M1792 896q0 -26 -19 -45l-512 -512q-19 -19 -45 -19t-45 19t-19 45v256h-224q-98 0 -175.5 -6t-154 -21.5t-133 -42.5t-105.5 -69.5t-80 -101t-48.5 -138.5t-17.5 -181q0 -55 5 -123q0 -6 2.5 -23.5t2.5 -26.5q0 -15 -8.5 -25t-23.5 -10q-16 0 -28 17q-7 9 -13 22 t-13.5 30t-10.5 24q-127 285 -127 451q0 199 53 333q162 403 875 403h224v256q0 26 19 45t45 19t45 -19l512 -512q19 -19 19 -45z" />
+<glyph unicode="&#xf065;" d="M755 480q0 -13 -10 -23l-332 -332l144 -144q19 -19 19 -45t-19 -45t-45 -19h-448q-26 0 -45 19t-19 45v448q0 26 19 45t45 19t45 -19l144 -144l332 332q10 10 23 10t23 -10l114 -114q10 -10 10 -23zM1536 1344v-448q0 -26 -19 -45t-45 -19t-45 19l-144 144l-332 -332 q-10 -10 -23 -10t-23 10l-114 114q-10 10 -10 23t10 23l332 332l-144 144q-19 19 -19 45t19 45t45 19h448q26 0 45 -19t19 -45z" />
+<glyph unicode="&#xf066;" d="M768 576v-448q0 -26 -19 -45t-45 -19t-45 19l-144 144l-332 -332q-10 -10 -23 -10t-23 10l-114 114q-10 10 -10 23t10 23l332 332l-144 144q-19 19 -19 45t19 45t45 19h448q26 0 45 -19t19 -45zM1523 1248q0 -13 -10 -23l-332 -332l144 -144q19 -19 19 -45t-19 -45 t-45 -19h-448q-26 0 -45 19t-19 45v448q0 26 19 45t45 19t45 -19l144 -144l332 332q10 10 23 10t23 -10l114 -114q10 -10 10 -23z" />
+<glyph unicode="&#xf067;" horiz-adv-x="1408" d="M1408 800v-192q0 -40 -28 -68t-68 -28h-416v-416q0 -40 -28 -68t-68 -28h-192q-40 0 -68 28t-28 68v416h-416q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h416v416q0 40 28 68t68 28h192q40 0 68 -28t28 -68v-416h416q40 0 68 -28t28 -68z" />
+<glyph unicode="&#xf068;" horiz-adv-x="1408" d="M1408 800v-192q0 -40 -28 -68t-68 -28h-1216q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h1216q40 0 68 -28t28 -68z" />
+<glyph unicode="&#xf069;" horiz-adv-x="1664" d="M1482 486q46 -26 59.5 -77.5t-12.5 -97.5l-64 -110q-26 -46 -77.5 -59.5t-97.5 12.5l-266 153v-307q0 -52 -38 -90t-90 -38h-128q-52 0 -90 38t-38 90v307l-266 -153q-46 -26 -97.5 -12.5t-77.5 59.5l-64 110q-26 46 -12.5 97.5t59.5 77.5l266 154l-266 154 q-46 26 -59.5 77.5t12.5 97.5l64 110q26 46 77.5 59.5t97.5 -12.5l266 -153v307q0 52 38 90t90 38h128q52 0 90 -38t38 -90v-307l266 153q46 26 97.5 12.5t77.5 -59.5l64 -110q26 -46 12.5 -97.5t-59.5 -77.5l-266 -154z" />
+<glyph unicode="&#xf06a;" d="M768 1408q209 0 385.5 -103t279.5 -279.5t103 -385.5t-103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103zM896 161v190q0 14 -9 23.5t-22 9.5h-192q-13 0 -23 -10t-10 -23v-190q0 -13 10 -23t23 -10h192 q13 0 22 9.5t9 23.5zM894 505l18 621q0 12 -10 18q-10 8 -24 8h-220q-14 0 -24 -8q-10 -6 -10 -18l17 -621q0 -10 10 -17.5t24 -7.5h185q14 0 23.5 7.5t10.5 17.5z" />
+<glyph unicode="&#xf06b;" d="M928 180v716h-320v-716q0 -25 18.5 -38.5t45.5 -13.5h192q27 0 45.5 13.5t18.5 38.5zM472 1024h195l-126 161q-24 31 -69 31q-40 0 -68 -28t-28 -68t28 -68t68 -28zM1160 1120q0 40 -28 68t-68 28q-45 0 -69 -31l-125 -161h194q40 0 68 28t28 68zM1536 864v-320 q0 -14 -10 -22t-27 -10.5t-32 -2.5t-34.5 1.5t-24.5 1.5v-416q0 -40 -28 -68t-68 -28h-1088q-40 0 -68 28t-28 68v416q-5 0 -24.5 -1.5t-34.5 -1.5t-32 2.5t-27 10.5t-10 22v320q0 13 9.5 22.5t22.5 9.5h440q-93 0 -158.5 65.5t-65.5 158.5t65.5 158.5t158.5 65.5 q108 0 168 -77l128 -165l128 165q60 77 168 77q93 0 158.5 -65.5t65.5 -158.5t-65.5 -158.5t-158.5 -65.5h440q13 0 22.5 -9.5t9.5 -22.5z" />
+<glyph unicode="&#xf06c;" horiz-adv-x="1792" d="M1280 832q0 26 -19 45t-45 19q-172 0 -318 -49.5t-259.5 -134t-235.5 -219.5q-19 -21 -19 -45q0 -26 19 -45t45 -19q24 0 45 19q27 24 74 71t67 66q137 124 268.5 176t313.5 52q26 0 45 19t19 45zM1792 1030q0 -95 -20 -193q-46 -224 -184.5 -383t-357.5 -268 q-214 -108 -438 -108q-148 0 -286 47q-15 5 -88 42t-96 37q-16 0 -39.5 -32t-45 -70t-52.5 -70t-60 -32q-30 0 -51 11t-31 24t-27 42q-2 4 -6 11t-5.5 10t-3 9.5t-1.5 13.5q0 35 31 73.5t68 65.5t68 56t31 48q0 4 -14 38t-16 44q-9 51 -9 104q0 115 43.5 220t119 184.5 t170.5 139t204 95.5q55 18 145 25.5t179.5 9t178.5 6t163.5 24t113.5 56.5l29.5 29.5t29.5 28t27 20t36.5 16t43.5 4.5q39 0 70.5 -46t47.5 -112t24 -124t8 -96z" />
+<glyph unicode="&#xf06d;" horiz-adv-x="1408" d="M1408 -160v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-1344q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h1344q13 0 22.5 -9.5t9.5 -22.5zM1152 896q0 -78 -24.5 -144t-64 -112.5t-87.5 -88t-96 -77.5t-87.5 -72t-64 -81.5t-24.5 -96.5q0 -96 67 -224l-4 1l1 -1 q-90 41 -160 83t-138.5 100t-113.5 122.5t-72.5 150.5t-27.5 184q0 78 24.5 144t64 112.5t87.5 88t96 77.5t87.5 72t64 81.5t24.5 96.5q0 94 -66 224l3 -1l-1 1q90 -41 160 -83t138.5 -100t113.5 -122.5t72.5 -150.5t27.5 -184z" />
+<glyph unicode="&#xf06e;" horiz-adv-x="1792" d="M1664 576q-152 236 -381 353q61 -104 61 -225q0 -185 -131.5 -316.5t-316.5 -131.5t-316.5 131.5t-131.5 316.5q0 121 61 225q-229 -117 -381 -353q133 -205 333.5 -326.5t434.5 -121.5t434.5 121.5t333.5 326.5zM944 960q0 20 -14 34t-34 14q-125 0 -214.5 -89.5 t-89.5 -214.5q0 -20 14 -34t34 -14t34 14t14 34q0 86 61 147t147 61q20 0 34 14t14 34zM1792 576q0 -34 -20 -69q-140 -230 -376.5 -368.5t-499.5 -138.5t-499.5 139t-376.5 368q-20 35 -20 69t20 69q140 229 376.5 368t499.5 139t499.5 -139t376.5 -368q20 -35 20 -69z" />
+<glyph unicode="&#xf070;" horiz-adv-x="1792" d="M555 201l78 141q-87 63 -136 159t-49 203q0 121 61 225q-229 -117 -381 -353q167 -258 427 -375zM944 960q0 20 -14 34t-34 14q-125 0 -214.5 -89.5t-89.5 -214.5q0 -20 14 -34t34 -14t34 14t14 34q0 86 61 147t147 61q20 0 34 14t14 34zM1307 1151q0 -7 -1 -9 q-105 -188 -315 -566t-316 -567l-49 -89q-10 -16 -28 -16q-12 0 -134 70q-16 10 -16 28q0 12 44 87q-143 65 -263.5 173t-208.5 245q-20 31 -20 69t20 69q153 235 380 371t496 136q89 0 180 -17l54 97q10 16 28 16q5 0 18 -6t31 -15.5t33 -18.5t31.5 -18.5t19.5 -11.5 q16 -10 16 -27zM1344 704q0 -139 -79 -253.5t-209 -164.5l280 502q8 -45 8 -84zM1792 576q0 -35 -20 -69q-39 -64 -109 -145q-150 -172 -347.5 -267t-419.5 -95l74 132q212 18 392.5 137t301.5 307q-115 179 -282 294l63 112q95 -64 182.5 -153t144.5 -184q20 -34 20 -69z " />
+<glyph unicode="&#xf071;" horiz-adv-x="1792" d="M1024 161v190q0 14 -9.5 23.5t-22.5 9.5h-192q-13 0 -22.5 -9.5t-9.5 -23.5v-190q0 -14 9.5 -23.5t22.5 -9.5h192q13 0 22.5 9.5t9.5 23.5zM1022 535l18 459q0 12 -10 19q-13 11 -24 11h-220q-11 0 -24 -11q-10 -7 -10 -21l17 -457q0 -10 10 -16.5t24 -6.5h185 q14 0 23.5 6.5t10.5 16.5zM1008 1469l768 -1408q35 -63 -2 -126q-17 -29 -46.5 -46t-63.5 -17h-1536q-34 0 -63.5 17t-46.5 46q-37 63 -2 126l768 1408q17 31 47 49t65 18t65 -18t47 -49z" />
+<glyph unicode="&#xf072;" horiz-adv-x="1408" d="M1397 1324q0 -87 -149 -236l-240 -240l143 -746l1 -6q0 -14 -9 -23l-64 -64q-9 -9 -23 -9q-21 0 -29 18l-274 575l-245 -245q68 -238 68 -252t-9 -23l-64 -64q-9 -9 -23 -9q-18 0 -28 16l-155 280l-280 155q-17 9 -17 28q0 14 9 23l64 65q9 9 23 9t252 -68l245 245 l-575 274q-18 8 -18 29q0 14 9 23l64 64q9 9 23 9q4 0 6 -1l746 -143l240 240q149 149 236 149q32 0 52.5 -20.5t20.5 -52.5z" />
+<glyph unicode="&#xf073;" horiz-adv-x="1664" d="M128 -128h288v288h-288v-288zM480 -128h320v288h-320v-288zM128 224h288v320h-288v-320zM480 224h320v320h-320v-320zM128 608h288v288h-288v-288zM864 -128h320v288h-320v-288zM480 608h320v288h-320v-288zM1248 -128h288v288h-288v-288zM864 224h320v320h-320v-320z M512 1088v288q0 13 -9.5 22.5t-22.5 9.5h-64q-13 0 -22.5 -9.5t-9.5 -22.5v-288q0 -13 9.5 -22.5t22.5 -9.5h64q13 0 22.5 9.5t9.5 22.5zM1248 224h288v320h-288v-320zM864 608h320v288h-320v-288zM1248 608h288v288h-288v-288zM1280 1088v288q0 13 -9.5 22.5t-22.5 9.5h-64 q-13 0 -22.5 -9.5t-9.5 -22.5v-288q0 -13 9.5 -22.5t22.5 -9.5h64q13 0 22.5 9.5t9.5 22.5zM1664 1152v-1280q0 -52 -38 -90t-90 -38h-1408q-52 0 -90 38t-38 90v1280q0 52 38 90t90 38h128v96q0 66 47 113t113 47h64q66 0 113 -47t47 -113v-96h384v96q0 66 47 113t113 47 h64q66 0 113 -47t47 -113v-96h128q52 0 90 -38t38 -90z" />
+<glyph unicode="&#xf074;" horiz-adv-x="1792" d="M666 1055q-60 -92 -137 -273q-22 45 -37 72.5t-40.5 63.5t-51 56.5t-63 35t-81.5 14.5h-224q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h224q250 0 410 -225zM1792 256q0 -14 -9 -23l-320 -320q-9 -9 -23 -9q-13 0 -22.5 9.5t-9.5 22.5v192q-32 0 -85 -0.5t-81 -1t-73 1 t-71 5t-64 10.5t-63 18.5t-58 28.5t-59 40t-55 53.5t-56 69.5q59 93 136 273q22 -45 37 -72.5t40.5 -63.5t51 -56.5t63 -35t81.5 -14.5h256v192q0 14 9 23t23 9q12 0 24 -10l319 -319q9 -9 9 -23zM1792 1152q0 -14 -9 -23l-320 -320q-9 -9 -23 -9q-13 0 -22.5 9.5t-9.5 22.5 v192h-256q-48 0 -87 -15t-69 -45t-51 -61.5t-45 -77.5q-32 -62 -78 -171q-29 -66 -49.5 -111t-54 -105t-64 -100t-74 -83t-90 -68.5t-106.5 -42t-128 -16.5h-224q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h224q48 0 87 15t69 45t51 61.5t45 77.5q32 62 78 171q29 66 49.5 111 t54 105t64 100t74 83t90 68.5t106.5 42t128 16.5h256v192q0 14 9 23t23 9q12 0 24 -10l319 -319q9 -9 9 -23z" />
+<glyph unicode="&#xf075;" horiz-adv-x="1792" d="M1792 640q0 -174 -120 -321.5t-326 -233t-450 -85.5q-70 0 -145 8q-198 -175 -460 -242q-49 -14 -114 -22q-17 -2 -30.5 9t-17.5 29v1q-3 4 -0.5 12t2 10t4.5 9.5l6 9t7 8.5t8 9q7 8 31 34.5t34.5 38t31 39.5t32.5 51t27 59t26 76q-157 89 -247.5 220t-90.5 281 q0 130 71 248.5t191 204.5t286 136.5t348 50.5q244 0 450 -85.5t326 -233t120 -321.5z" />
+<glyph unicode="&#xf076;" d="M1536 704v-128q0 -201 -98.5 -362t-274 -251.5t-395.5 -90.5t-395.5 90.5t-274 251.5t-98.5 362v128q0 26 19 45t45 19h384q26 0 45 -19t19 -45v-128q0 -52 23.5 -90t53.5 -57t71 -30t64 -13t44 -2t44 2t64 13t71 30t53.5 57t23.5 90v128q0 26 19 45t45 19h384 q26 0 45 -19t19 -45zM512 1344v-384q0 -26 -19 -45t-45 -19h-384q-26 0 -45 19t-19 45v384q0 26 19 45t45 19h384q26 0 45 -19t19 -45zM1536 1344v-384q0 -26 -19 -45t-45 -19h-384q-26 0 -45 19t-19 45v384q0 26 19 45t45 19h384q26 0 45 -19t19 -45z" />
+<glyph unicode="&#xf077;" horiz-adv-x="1664" d="M1611 320q0 -53 -37 -90l-75 -75q-38 -38 -91 -38q-54 0 -90 38l-486 485l-486 -485q-36 -38 -90 -38t-90 38l-75 75q-38 36 -38 90q0 53 38 91l651 651q37 37 90 37q52 0 91 -37l650 -651q38 -38 38 -91z" />
+<glyph unicode="&#xf078;" horiz-adv-x="1664" d="M1611 832q0 -53 -37 -90l-651 -651q-38 -38 -91 -38q-54 0 -90 38l-651 651q-38 36 -38 90q0 53 38 91l74 75q39 37 91 37q53 0 90 -37l486 -486l486 486q37 37 90 37q52 0 91 -37l75 -75q37 -39 37 -91z" />
+<glyph unicode="&#xf079;" horiz-adv-x="1920" d="M1280 32q0 -13 -9.5 -22.5t-22.5 -9.5h-960q-8 0 -13.5 2t-9 7t-5.5 8t-3 11.5t-1 11.5v13v11v160v416h-192q-26 0 -45 19t-19 45q0 24 15 41l320 384q19 22 49 22t49 -22l320 -384q15 -17 15 -41q0 -26 -19 -45t-45 -19h-192v-384h576q16 0 25 -11l160 -192q7 -11 7 -21 zM1920 448q0 -24 -15 -41l-320 -384q-20 -23 -49 -23t-49 23l-320 384q-15 17 -15 41q0 26 19 45t45 19h192v384h-576q-16 0 -25 12l-160 192q-7 9 -7 20q0 13 9.5 22.5t22.5 9.5h960q8 0 13.5 -2t9 -7t5.5 -8t3 -11.5t1 -11.5v-13v-11v-160v-416h192q26 0 45 -19t19 -45z " />
+<glyph unicode="&#xf07a;" horiz-adv-x="1664" d="M640 0q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1536 0q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1664 1088v-512q0 -24 -16 -42.5t-41 -21.5 l-1044 -122q1 -7 4.5 -21.5t6 -26.5t2.5 -22q0 -16 -24 -64h920q26 0 45 -19t19 -45t-19 -45t-45 -19h-1024q-26 0 -45 19t-19 45q0 14 11 39.5t29.5 59.5t20.5 38l-177 823h-204q-26 0 -45 19t-19 45t19 45t45 19h256q16 0 28.5 -6.5t20 -15.5t13 -24.5t7.5 -26.5 t5.5 -29.5t4.5 -25.5h1201q26 0 45 -19t19 -45z" />
+<glyph unicode="&#xf07b;" horiz-adv-x="1664" d="M1664 928v-704q0 -92 -66 -158t-158 -66h-1216q-92 0 -158 66t-66 158v960q0 92 66 158t158 66h320q92 0 158 -66t66 -158v-32h672q92 0 158 -66t66 -158z" />
+<glyph unicode="&#xf07c;" horiz-adv-x="1920" d="M1879 584q0 -31 -31 -66l-336 -396q-43 -51 -120.5 -86.5t-143.5 -35.5h-1088q-34 0 -60.5 13t-26.5 43q0 31 31 66l336 396q43 51 120.5 86.5t143.5 35.5h1088q34 0 60.5 -13t26.5 -43zM1536 928v-160h-832q-94 0 -197 -47.5t-164 -119.5l-337 -396l-5 -6q0 4 -0.5 12.5 t-0.5 12.5v960q0 92 66 158t158 66h320q92 0 158 -66t66 -158v-32h544q92 0 158 -66t66 -158z" />
+<glyph unicode="&#xf07d;" horiz-adv-x="768" d="M704 1216q0 -26 -19 -45t-45 -19h-128v-1024h128q26 0 45 -19t19 -45t-19 -45l-256 -256q-19 -19 -45 -19t-45 19l-256 256q-19 19 -19 45t19 45t45 19h128v1024h-128q-26 0 -45 19t-19 45t19 45l256 256q19 19 45 19t45 -19l256 -256q19 -19 19 -45z" />
+<glyph unicode="&#xf07e;" horiz-adv-x="1792" d="M1792 640q0 -26 -19 -45l-256 -256q-19 -19 -45 -19t-45 19t-19 45v128h-1024v-128q0 -26 -19 -45t-45 -19t-45 19l-256 256q-19 19 -19 45t19 45l256 256q19 19 45 19t45 -19t19 -45v-128h1024v128q0 26 19 45t45 19t45 -19l256 -256q19 -19 19 -45z" />
+<glyph unicode="&#xf080;" horiz-adv-x="1920" d="M512 512v-384h-256v384h256zM896 1024v-896h-256v896h256zM1280 768v-640h-256v640h256zM1664 1152v-1024h-256v1024h256zM1792 32v1216q0 13 -9.5 22.5t-22.5 9.5h-1600q-13 0 -22.5 -9.5t-9.5 -22.5v-1216q0 -13 9.5 -22.5t22.5 -9.5h1600q13 0 22.5 9.5t9.5 22.5z M1920 1248v-1216q0 -66 -47 -113t-113 -47h-1600q-66 0 -113 47t-47 113v1216q0 66 47 113t113 47h1600q66 0 113 -47t47 -113z" />
+<glyph unicode="&#xf081;" d="M1280 958q0 13 -9.5 22.5t-22.5 9.5q-5 0 -15 -4q20 34 20 55q0 13 -9.5 22.5t-22.5 9.5q-7 0 -17 -5q-60 -34 -97 -43q-65 63 -154 63q-98 0 -164.5 -72.5t-64.5 -169.5v-12q-107 14 -187.5 64t-156.5 139q-10 12 -28 12q-26 0 -41 -50.5t-15 -86.5q0 -62 29 -117 q-13 -2 -21.5 -11.5t-8.5 -22.5q0 -112 81 -185q-12 -8 -12 -25q0 -6 1 -9q15 -51 50.5 -91.5t84.5 -60.5q-77 -43 -165 -43q-8 0 -24 1.5t-23 1.5q-13 0 -22.5 -9.5t-9.5 -22.5q0 -17 14 -26q63 -47 150 -73.5t170 -26.5q130 0 248 58q166 79 256 232.5t88 339.5v12 q27 22 62.5 63t35.5 61zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
+<glyph unicode="&#xf082;" d="M1248 1408q119 0 203.5 -84.5t84.5 -203.5v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-350q-2 0 -2 1v671h177q31 0 32 23l12 164q2 15 -8 25q-10 12 -24 12h-189v72q0 44 11.5 57t54.5 13q57 0 117 -13q13 -3 26 5q11 8 13 22l23 166q2 12 -5.5 22.5t-19.5 13.5 q-93 26 -197 26q-311 0 -311 -299v-85h-95q-13 0 -23 -10.5t-10 -24.5v-172q0 -8 5.5 -12t10 -4.5t17.5 -0.5h95v-671l10 -1h-330q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960z" />
+<glyph unicode="&#xf083;" horiz-adv-x="1792" d="M928 704q0 14 -9 23t-23 9q-66 0 -113 -47t-47 -113q0 -14 9 -23t23 -9t23 9t9 23q0 40 28 68t68 28q14 0 23 9t9 23zM1152 574q0 -106 -75 -181t-181 -75t-181 75t-75 181t75 181t181 75t181 -75t75 -181zM128 0h1536v128h-1536v-128zM1280 574q0 159 -112.5 271.5 t-271.5 112.5t-271.5 -112.5t-112.5 -271.5t112.5 -271.5t271.5 -112.5t271.5 112.5t112.5 271.5zM256 1216h384v128h-384v-128zM128 1024h1536v118v138h-828l-64 -128h-644v-128zM1792 1280v-1280q0 -53 -37.5 -90.5t-90.5 -37.5h-1536q-53 0 -90.5 37.5t-37.5 90.5v1280 q0 53 37.5 90.5t90.5 37.5h1536q53 0 90.5 -37.5t37.5 -90.5z" />
+<glyph unicode="&#xf084;" horiz-adv-x="1792" d="M832 1024q0 80 -56 136t-136 56t-136 -56t-56 -136q0 -42 19 -83q-41 19 -83 19q-80 0 -136 -56t-56 -136t56 -136t136 -56t136 56t56 136q0 42 -19 83q41 -19 83 -19q80 0 136 56t56 136zM1683 320q0 -17 -49 -66t-66 -49q-9 0 -28.5 16t-36.5 33t-38.5 40t-24.5 26 l-96 -96l220 -220q28 -28 28 -68q0 -42 -39 -81t-81 -39q-40 0 -68 28l-671 671q-176 -131 -365 -131q-163 0 -265.5 102.5t-102.5 265.5q0 160 95 313t248 248t313 95q163 0 265.5 -102.5t102.5 -265.5q0 -189 -131 -365l355 -355l96 96q-3 3 -26 24.5t-40 38.5t-33 36.5 t-16 28.5q0 17 49 66t66 49q13 0 23 -10q6 -6 46 -44.5t82 -79.5t86.5 -86t73 -78t28.5 -41z" />
+<glyph unicode="&#xf085;" horiz-adv-x="1920" d="M896 640q0 106 -75 181t-181 75t-181 -75t-75 -181t75 -181t181 -75t181 75t75 181zM1664 128q0 52 -38 90t-90 38t-90 -38t-38 -90q0 -53 37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1664 1152q0 52 -38 90t-90 38t-90 -38t-38 -90q0 -53 37.5 -90.5t90.5 -37.5 t90.5 37.5t37.5 90.5zM1280 731v-185q0 -10 -7 -19.5t-16 -10.5l-155 -24q-11 -35 -32 -76q34 -48 90 -115q7 -10 7 -20q0 -12 -7 -19q-23 -30 -82.5 -89.5t-78.5 -59.5q-11 0 -21 7l-115 90q-37 -19 -77 -31q-11 -108 -23 -155q-7 -24 -30 -24h-186q-11 0 -20 7.5t-10 17.5 l-23 153q-34 10 -75 31l-118 -89q-7 -7 -20 -7q-11 0 -21 8q-144 133 -144 160q0 9 7 19q10 14 41 53t47 61q-23 44 -35 82l-152 24q-10 1 -17 9.5t-7 19.5v185q0 10 7 19.5t16 10.5l155 24q11 35 32 76q-34 48 -90 115q-7 11 -7 20q0 12 7 20q22 30 82 89t79 59q11 0 21 -7 l115 -90q34 18 77 32q11 108 23 154q7 24 30 24h186q11 0 20 -7.5t10 -17.5l23 -153q34 -10 75 -31l118 89q8 7 20 7q11 0 21 -8q144 -133 144 -160q0 -9 -7 -19q-12 -16 -42 -54t-45 -60q23 -48 34 -82l152 
 -23q10 -2 17 -10.5t7 -19.5zM1920 198v-140q0 -16 -149 -31 q-12 -27 -30 -52q51 -113 51 -138q0 -4 -4 -7q-122 -71 -124 -71q-8 0 -46 47t-52 68q-20 -2 -30 -2t-30 2q-14 -21 -52 -68t-46 -47q-2 0 -124 71q-4 3 -4 7q0 25 51 138q-18 25 -30 52q-149 15 -149 31v140q0 16 149 31q13 29 30 52q-51 113 -51 138q0 4 4 7q4 2 35 20 t59 34t30 16q8 0 46 -46.5t52 -67.5q20 2 30 2t30 -2q51 71 92 112l6 2q4 0 124 -70q4 -3 4 -7q0 -25 -51 -138q17 -23 30 -52q149 -15 149 -31zM1920 1222v-140q0 -16 -149 -31q-12 -27 -30 -52q51 -113 51 -138q0 -4 -4 -7q-122 -71 -124 -71q-8 0 -46 47t-52 68 q-20 -2 -30 -2t-30 2q-14 -21 -52 -68t-46 -47q-2 0 -124 71q-4 3 -4 7q0 25 51 138q-18 25 -30 52q-149 15 -149 31v140q0 16 149 31q13 29 30 52q-51 113 -51 138q0 4 4 7q4 2 35 20t59 34t30 16q8 0 46 -46.5t52 -67.5q20 2 30 2t30 -2q51 71 92 112l6 2q4 0 124 -70 q4 -3 4 -7q0 -25 -51 -138q17 -23 30 -52q149 -15 149 -31z" />
+<glyph unicode="&#xf086;" horiz-adv-x="1792" d="M1408 768q0 -139 -94 -257t-256.5 -186.5t-353.5 -68.5q-86 0 -176 16q-124 -88 -278 -128q-36 -9 -86 -16h-3q-11 0 -20.5 8t-11.5 21q-1 3 -1 6.5t0.5 6.5t2 6l2.5 5t3.5 5.5t4 5t4.5 5t4 4.5q5 6 23 25t26 29.5t22.5 29t25 38.5t20.5 44q-124 72 -195 177t-71 224 q0 139 94 257t256.5 186.5t353.5 68.5t353.5 -68.5t256.5 -186.5t94 -257zM1792 512q0 -120 -71 -224.5t-195 -176.5q10 -24 20.5 -44t25 -38.5t22.5 -29t26 -29.5t23 -25q1 -1 4 -4.5t4.5 -5t4 -5t3.5 -5.5l2.5 -5t2 -6t0.5 -6.5t-1 -6.5q-3 -14 -13 -22t-22 -7 q-50 7 -86 16q-154 40 -278 128q-90 -16 -176 -16q-271 0 -472 132q58 -4 88 -4q161 0 309 45t264 129q125 92 192 212t67 254q0 77 -23 152q129 -71 204 -178t75 -230z" />
+<glyph unicode="&#xf087;" d="M256 192q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1408 768q0 51 -39 89.5t-89 38.5h-352q0 58 48 159.5t48 160.5q0 98 -32 145t-128 47q-26 -26 -38 -85t-30.5 -125.5t-59.5 -109.5q-22 -23 -77 -91q-4 -5 -23 -30t-31.5 -41t-34.5 -42.5 t-40 -44t-38.5 -35.5t-40 -27t-35.5 -9h-32v-640h32q13 0 31.5 -3t33 -6.5t38 -11t35 -11.5t35.5 -12.5t29 -10.5q211 -73 342 -73h121q192 0 192 167q0 26 -5 56q30 16 47.5 52.5t17.5 73.5t-18 69q53 50 53 119q0 25 -10 55.5t-25 47.5q32 1 53.5 47t21.5 81zM1536 769 q0 -89 -49 -163q9 -33 9 -69q0 -77 -38 -144q3 -21 3 -43q0 -101 -60 -178q1 -139 -85 -219.5t-227 -80.5h-36h-93q-96 0 -189.5 22.5t-216.5 65.5q-116 40 -138 40h-288q-53 0 -90.5 37.5t-37.5 90.5v640q0 53 37.5 90.5t90.5 37.5h274q36 24 137 155q58 75 107 128 q24 25 35.5 85.5t30.5 126.5t62 108q39 37 90 37q84 0 151 -32.5t102 -101.5t35 -186q0 -93 -48 -192h176q104 0 180 -76t76 -179z" />
+<glyph unicode="&#xf088;" d="M256 1088q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1408 512q0 35 -21.5 81t-53.5 47q15 17 25 47.5t10 55.5q0 69 -53 119q18 32 18 69t-17.5 73.5t-47.5 52.5q5 30 5 56q0 85 -49 126t-136 41h-128q-131 0 -342 -73q-5 -2 -29 -10.5 t-35.5 -12.5t-35 -11.5t-38 -11t-33 -6.5t-31.5 -3h-32v-640h32q16 0 35.5 -9t40 -27t38.5 -35.5t40 -44t34.5 -42.5t31.5 -41t23 -30q55 -68 77 -91q41 -43 59.5 -109.5t30.5 -125.5t38 -85q96 0 128 47t32 145q0 59 -48 160.5t-48 159.5h352q50 0 89 38.5t39 89.5z M1536 511q0 -103 -76 -179t-180 -76h-176q48 -99 48 -192q0 -118 -35 -186q-35 -69 -102 -101.5t-151 -32.5q-51 0 -90 37q-34 33 -54 82t-25.5 90.5t-17.5 84.5t-31 64q-48 50 -107 127q-101 131 -137 155h-274q-53 0 -90.5 37.5t-37.5 90.5v640q0 53 37.5 90.5t90.5 37.5 h288q22 0 138 40q128 44 223 66t200 22h112q140 0 226.5 -79t85.5 -216v-5q60 -77 60 -178q0 -22 -3 -43q38 -67 38 -144q0 -36 -9 -69q49 -74 49 -163z" />
+<glyph unicode="&#xf089;" horiz-adv-x="896" d="M832 1504v-1339l-449 -236q-22 -12 -40 -12q-21 0 -31.5 14.5t-10.5 35.5q0 6 2 20l86 500l-364 354q-25 27 -25 48q0 37 56 46l502 73l225 455q19 41 49 41z" />
+<glyph unicode="&#xf08a;" horiz-adv-x="1792" d="M1664 940q0 81 -21.5 143t-55 98.5t-81.5 59.5t-94 31t-98 8t-112 -25.5t-110.5 -64t-86.5 -72t-60 -61.5q-18 -22 -49 -22t-49 22q-24 28 -60 61.5t-86.5 72t-110.5 64t-112 25.5t-98 -8t-94 -31t-81.5 -59.5t-55 -98.5t-21.5 -143q0 -168 187 -355l581 -560l580 559 q188 188 188 356zM1792 940q0 -221 -229 -450l-623 -600q-18 -18 -44 -18t-44 18l-624 602q-10 8 -27.5 26t-55.5 65.5t-68 97.5t-53.5 121t-23.5 138q0 220 127 344t351 124q62 0 126.5 -21.5t120 -58t95.5 -68.5t76 -68q36 36 76 68t95.5 68.5t120 58t126.5 21.5 q224 0 351 -124t127 -344z" />
+<glyph unicode="&#xf08b;" horiz-adv-x="1664" d="M640 96q0 -4 1 -20t0.5 -26.5t-3 -23.5t-10 -19.5t-20.5 -6.5h-320q-119 0 -203.5 84.5t-84.5 203.5v704q0 119 84.5 203.5t203.5 84.5h320q13 0 22.5 -9.5t9.5 -22.5q0 -4 1 -20t0.5 -26.5t-3 -23.5t-10 -19.5t-20.5 -6.5h-320q-66 0 -113 -47t-47 -113v-704 q0 -66 47 -113t113 -47h288h11h13t11.5 -1t11.5 -3t8 -5.5t7 -9t2 -13.5zM1568 640q0 -26 -19 -45l-544 -544q-19 -19 -45 -19t-45 19t-19 45v288h-448q-26 0 -45 19t-19 45v384q0 26 19 45t45 19h448v288q0 26 19 45t45 19t45 -19l544 -544q19 -19 19 -45z" />
+<glyph unicode="&#xf08c;" d="M512 160v640q0 13 -9.5 22.5t-22.5 9.5h-192q-13 0 -22.5 -9.5t-9.5 -22.5v-640q0 -13 9.5 -22.5t22.5 -9.5h192q13 0 22.5 9.5t9.5 22.5zM503 1028q0 51 -36 87.5t-88 36.5q-51 0 -87 -36.5t-36 -87.5t36 -87.5t87 -36.5q52 0 88 36.5t36 87.5zM1280 160v435 q0 127 -73.5 192.5t-202.5 65.5q-90 0 -158 -45q-12 -8 -14 -12q0 36 -35 36h-176q-14 0 -29.5 -7.5t-15.5 -20.5v-644q0 -13 15.5 -22.5t29.5 -9.5h182q12 0 20.5 9.5t8.5 22.5v349q0 140 114 140q49 0 63.5 -22.5t14.5 -73.5v-393q0 -13 12 -22.5t26 -9.5h186 q13 0 22.5 9.5t9.5 22.5zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
+<glyph unicode="&#xf08d;" horiz-adv-x="1152" d="M480 672v448q0 14 -9 23t-23 9t-23 -9t-9 -23v-448q0 -14 9 -23t23 -9t23 9t9 23zM1152 320q0 -26 -19 -45t-45 -19h-429l-51 -483q-2 -12 -10.5 -20.5t-20.5 -8.5h-1q-27 0 -32 27l-76 485h-404q-26 0 -45 19t-19 45q0 123 78.5 221.5t177.5 98.5v512q-52 0 -90 38 t-38 90t38 90t90 38h640q52 0 90 -38t38 -90t-38 -90t-90 -38v-512q99 0 177.5 -98.5t78.5 -221.5z" />
+<glyph unicode="&#xf08e;" horiz-adv-x="1792" d="M1408 608v-320q0 -119 -84.5 -203.5t-203.5 -84.5h-832q-119 0 -203.5 84.5t-84.5 203.5v832q0 119 84.5 203.5t203.5 84.5h704q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-704q-66 0 -113 -47t-47 -113v-832q0 -66 47 -113t113 -47h832q66 0 113 47t47 113v320 q0 14 9 23t23 9h64q14 0 23 -9t9 -23zM1792 1472v-512q0 -26 -19 -45t-45 -19t-45 19l-176 176l-652 -652q-10 -10 -23 -10t-23 10l-114 114q-10 10 -10 23t10 23l652 652l-176 176q-19 19 -19 45t19 45t45 19h512q26 0 45 -19t19 -45z" />
+<glyph unicode="&#xf090;" d="M1184 640q0 -26 -19 -45l-544 -544q-19 -19 -45 -19t-45 19t-19 45v288h-448q-26 0 -45 19t-19 45v384q0 26 19 45t45 19h448v288q0 26 19 45t45 19t45 -19l544 -544q19 -19 19 -45zM1536 992v-704q0 -119 -84.5 -203.5t-203.5 -84.5h-320q-13 0 -22.5 9.5t-9.5 22.5 q0 4 -1 20t-0.5 26.5t3 23.5t10 19.5t20.5 6.5h320q66 0 113 47t47 113v704q0 66 -47 113t-113 47h-288h-11h-13t-11.5 1t-11.5 3t-8 5.5t-7 9t-2 13.5q0 4 -1 20t-0.5 26.5t3 23.5t10 19.5t20.5 6.5h320q119 0 203.5 -84.5t84.5 -203.5z" />
+<glyph unicode="&#xf091;" horiz-adv-x="1664" d="M458 653q-74 162 -74 371h-256v-96q0 -78 94.5 -162t235.5 -113zM1536 928v96h-256q0 -209 -74 -371q141 29 235.5 113t94.5 162zM1664 1056v-128q0 -71 -41.5 -143t-112 -130t-173 -97.5t-215.5 -44.5q-42 -54 -95 -95q-38 -34 -52.5 -72.5t-14.5 -89.5q0 -54 30.5 -91 t97.5 -37q75 0 133.5 -45.5t58.5 -114.5v-64q0 -14 -9 -23t-23 -9h-832q-14 0 -23 9t-9 23v64q0 69 58.5 114.5t133.5 45.5q67 0 97.5 37t30.5 91q0 51 -14.5 89.5t-52.5 72.5q-53 41 -95 95q-113 5 -215.5 44.5t-173 97.5t-112 130t-41.5 143v128q0 40 28 68t68 28h288v96 q0 66 47 113t113 47h576q66 0 113 -47t47 -113v-96h288q40 0 68 -28t28 -68z" />
+<glyph unicode="&#xf092;" d="M582 228q0 -66 -93 -66q-107 0 -107 63q0 64 98 64q102 0 102 -61zM546 694q0 -85 -74 -85q-77 0 -77 84q0 90 77 90q36 0 55 -26t19 -63zM712 769v125q-78 -29 -135 -29q-50 29 -110 29q-86 0 -145 -57t-59 -143q0 -50 29.5 -102t73.5 -67v-3q-38 -17 -38 -85 q0 -52 41 -77v-3q-113 -37 -113 -139q0 -60 36 -98t84 -51t107 -13q224 0 224 187q0 48 -25.5 78t-62.5 42.5t-74 21.5t-62.5 23.5t-25.5 39.5q0 44 49 52q77 15 122 70t45 134q0 24 -10 52q30 7 49 13zM771 350h137q-2 20 -2 90v372q0 59 2 76h-137q3 -26 3 -79v-377 q0 -55 -3 -82zM1280 366v121q-30 -21 -68 -21q-53 0 -53 82v225h52q9 0 26.5 -1t26.5 -1v117h-105q0 82 3 102h-140q4 -24 4 -55v-47h-60v-117q36 3 37 3q4 0 11.5 -0.5t11.5 -0.5v-2h-2v-217q0 -37 2.5 -64t11.5 -56.5t24.5 -48.5t43.5 -31t66 -12q64 0 108 24zM924 1072 q0 36 -24 63.5t-60 27.5t-60.5 -27t-24.5 -64q0 -36 25 -62.5t60 -26.5t59.5 27t24.5 62zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t8
 4.5 -203.5z" />
+<glyph unicode="&#xf093;" horiz-adv-x="1664" d="M1664 480v-576q0 -13 -9.5 -22.5t-22.5 -9.5h-1600q-13 0 -22.5 9.5t-9.5 22.5v576q0 13 9.5 22.5t22.5 9.5h192q13 0 22.5 -9.5t9.5 -22.5v-352h1152v352q0 13 9.5 22.5t22.5 9.5h192q13 0 22.5 -9.5t9.5 -22.5zM1344 832q0 -26 -19 -45t-45 -19h-256v-448 q0 -26 -19 -45t-45 -19h-256q-26 0 -45 19t-19 45v448h-256q-26 0 -45 19t-19 45t19 45l448 448q19 19 45 19t45 -19l448 -448q19 -19 19 -45z" />
+<glyph unicode="&#xf094;" d="M1407 710q0 44 -7 113.5t-18 96.5q-12 30 -17 44t-9 36.5t-4 48.5q0 23 5 68.5t5 67.5q0 37 -10 55q-4 1 -13 1q-19 0 -58 -4.5t-59 -4.5q-60 0 -176 24t-175 24q-43 0 -94.5 -11.5t-85 -23.5t-89.5 -34q-137 -54 -202 -103q-96 -73 -159.5 -189.5t-88 -236t-24.5 -248.5 q0 -40 12.5 -120t12.5 -121q0 -23 -11 -66.5t-11 -65.5t12 -36.5t34 -14.5q24 0 72.5 11t73.5 11q57 0 169.5 -15.5t169.5 -15.5q181 0 284 36q129 45 235.5 152.5t166 245.5t59.5 275zM1535 712q0 -165 -70 -327.5t-196 -288t-281 -180.5q-124 -44 -326 -44 q-57 0 -170 14.5t-169 14.5q-24 0 -72.5 -14.5t-73.5 -14.5q-73 0 -123.5 55.5t-50.5 128.5q0 24 11 68t11 67q0 40 -12.5 120.5t-12.5 121.5q0 111 18 217.5t54.5 209.5t100.5 194t150 156q78 59 232 120q194 78 316 78q60 0 175.5 -24t173.5 -24q19 0 57 5t58 5 q81 0 118 -50.5t37 -134.5q0 -23 -5 -68t-5 -68q0 -10 1 -18.5t3 -17t4 -13.5t6.5 -16t6.5 -17q16 -40 25 -118.5t9 -136.5z" />
+<glyph unicode="&#xf095;" horiz-adv-x="1408" d="M1408 296q0 -27 -10 -70.5t-21 -68.5q-21 -50 -122 -106q-94 -51 -186 -51q-27 0 -52.5 3.5t-57.5 12.5t-47.5 14.5t-55.5 20.5t-49 18q-98 35 -175 83q-128 79 -264.5 215.5t-215.5 264.5q-48 77 -83 175q-3 9 -18 49t-20.5 55.5t-14.5 47.5t-12.5 57.5t-3.5 52.5 q0 92 51 186q56 101 106 122q25 11 68.5 21t70.5 10q14 0 21 -3q18 -6 53 -76q11 -19 30 -54t35 -63.5t31 -53.5q3 -4 17.5 -25t21.5 -35.5t7 -28.5q0 -20 -28.5 -50t-62 -55t-62 -53t-28.5 -46q0 -9 5 -22.5t8.5 -20.5t14 -24t11.5 -19q76 -137 174 -235t235 -174 q2 -1 19 -11.5t24 -14t20.5 -8.5t22.5 -5q18 0 46 28.5t53 62t55 62t50 28.5q14 0 28.5 -7t35.5 -21.5t25 -17.5q25 -15 53.5 -31t63.5 -35t54 -30q70 -35 76 -53q3 -7 3 -21z" />
+<glyph unicode="&#xf096;" horiz-adv-x="1664" d="M1120 1280h-832q-66 0 -113 -47t-47 -113v-832q0 -66 47 -113t113 -47h832q66 0 113 47t47 113v832q0 66 -47 113t-113 47zM1408 1120v-832q0 -119 -84.5 -203.5t-203.5 -84.5h-832q-119 0 -203.5 84.5t-84.5 203.5v832q0 119 84.5 203.5t203.5 84.5h832 q119 0 203.5 -84.5t84.5 -203.5z" />
+<glyph unicode="&#xf097;" horiz-adv-x="1280" d="M1152 1280h-1024v-1242l423 406l89 85l89 -85l423 -406v1242zM1164 1408q23 0 44 -9q33 -13 52.5 -41t19.5 -62v-1289q0 -34 -19.5 -62t-52.5 -41q-19 -8 -44 -8q-48 0 -83 32l-441 424l-441 -424q-36 -33 -83 -33q-23 0 -44 9q-33 13 -52.5 41t-19.5 62v1289 q0 34 19.5 62t52.5 41q21 9 44 9h1048z" />
+<glyph unicode="&#xf098;" d="M1280 343q0 11 -2 16q-3 8 -38.5 29.5t-88.5 49.5l-53 29q-5 3 -19 13t-25 15t-21 5q-18 0 -47 -32.5t-57 -65.5t-44 -33q-7 0 -16.5 3.5t-15.5 6.5t-17 9.5t-14 8.5q-99 55 -170.5 126.5t-126.5 170.5q-2 3 -8.5 14t-9.5 17t-6.5 15.5t-3.5 16.5q0 13 20.5 33.5t45 38.5 t45 39.5t20.5 36.5q0 10 -5 21t-15 25t-13 19q-3 6 -15 28.5t-25 45.5t-26.5 47.5t-25 40.5t-16.5 18t-16 2q-48 0 -101 -22q-46 -21 -80 -94.5t-34 -130.5q0 -16 2.5 -34t5 -30.5t9 -33t10 -29.5t12.5 -33t11 -30q60 -164 216.5 -320.5t320.5 -216.5q6 -2 30 -11t33 -12.5 t29.5 -10t33 -9t30.5 -5t34 -2.5q57 0 130.5 34t94.5 80q22 53 22 101zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
+<glyph unicode="&#xf099;" horiz-adv-x="1920" d="M1875 1202q0 -10 -5 -18q-64 -104 -179 -190v-33q4 -227 -100 -457q-134 -297 -397.5 -464.5t-591.5 -167.5q-265 0 -500 122q-64 33 -87 50q-15 12 -15 27q0 13 9.5 22.5t22.5 9.5q14 0 44 -2.5t45 -2.5q204 0 375 106q-103 24 -181 96t-111 173q-2 8 -2 11q0 12 9 21.5 t22 9.5q5 0 14 -2t12 -2q-89 55 -142 147t-53 196q0 15 11.5 25.5t27.5 10.5q10 0 35 -11.5t30 -13.5q-92 110 -92 256q0 51 14.5 108t40.5 95q10 16 25 16q16 0 27 -12q76 -84 110 -115q123 -111 276 -177.5t317 -80.5q-4 21 -4 49q0 167 118.5 285.5t285.5 118.5 q163 0 282 -114q95 20 209 82q8 5 16 5q13 0 22.5 -9.5t9.5 -22.5q0 -24 -28 -73t-51 -76q7 2 30 10.5t43 16t24 7.5q13 0 22.5 -9.5t9.5 -22.5z" />
+<glyph unicode="&#xf09a;" horiz-adv-x="768" d="M560 1125q-49 0 -62 -15.5t-13 -66.5v-88h217q16 0 27 -12q11 -13 10 -29l-14 -200q-2 -15 -12.5 -25.5t-25.5 -10.5h-202v-768q0 -16 -11 -27t-26 -11h-250q-16 0 -27 11t-11 27v768h-122q-16 0 -27 11.5t-11 27.5v200q0 16 11 27t27 11h122v103q0 177 88 263.5 t267 86.5q120 0 225 -30q14 -4 22 -16t6 -26l-27 -195q-2 -16 -16 -26q-14 -9 -30 -6q-76 16 -135 16z" />
+<glyph unicode="&#xf09b;" d="M1408 640q0 130 -51 248.5t-136.5 204t-204 136.5t-248.5 51t-248.5 -51t-204 -136.5t-136.5 -204t-51 -248.5q0 -209 124.5 -378.5t323.5 -231.5v169q-54 -7 -69 -7q-110 0 -153 100q-15 38 -36 63q-5 6 -21 19t-28.5 24t-12.5 16q0 12 28 12q29 0 51.5 -14.5t38 -35 t31.5 -41.5t40.5 -35.5t56.5 -14.5q42 0 81 14q16 57 63 89q-166 16 -246 83.5t-80 224.5q0 118 73 198q-14 42 -14 84q0 58 27 109q57 0 101 -19.5t101 -60.5q76 18 169 18q80 0 153 -16q57 40 100.5 59t99.5 19q27 -51 27 -109q0 -43 -14 -83q73 -82 73 -199 q0 -157 -80 -225.5t-245 -83.5q69 -47 69 -131v-226q199 62 323.5 231.5t124.5 378.5zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+<glyph unicode="&#xf09c;" horiz-adv-x="1664" d="M704 160q0 6 -15 57t-35 115.5t-20 65.5q32 16 51 47t19 67q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5q0 -36 19 -66.5t51 -47.5q0 -2 -20 -66t-35 -115t-15 -57q0 -13 9.5 -22.5t22.5 -9.5h192q13 0 22.5 9.5t9.5 22.5zM1664 960v-256q0 -26 -19 -45t-45 -19 h-64q-26 0 -45 19t-19 45v256q0 106 -75 181t-181 75t-181 -75t-75 -181v-192h96q40 0 68 -28t28 -68v-576q0 -40 -28 -68t-68 -28h-960q-40 0 -68 28t-28 68v576q0 40 28 68t68 28h672v192q0 185 131.5 316.5t316.5 131.5t316.5 -131.5t131.5 -316.5z" />
+<glyph unicode="&#xf09d;" horiz-adv-x="1920" d="M1760 1408q66 0 113 -47t47 -113v-1216q0 -66 -47 -113t-113 -47h-1600q-66 0 -113 47t-47 113v1216q0 66 47 113t113 47h1600zM160 1280q-13 0 -22.5 -9.5t-9.5 -22.5v-224h1664v224q0 13 -9.5 22.5t-22.5 9.5h-1600zM1760 0q13 0 22.5 9.5t9.5 22.5v608h-1664v-608 q0 -13 9.5 -22.5t22.5 -9.5h1600zM256 128v128h256v-128h-256zM640 128v128h384v-128h-384z" />
+<glyph unicode="&#xf09e;" horiz-adv-x="1408" d="M384 192q0 -80 -56 -136t-136 -56t-136 56t-56 136t56 136t136 56t136 -56t56 -136zM896 69q2 -28 -17 -48q-18 -21 -47 -21h-135q-25 0 -43 16.5t-20 41.5q-22 229 -184.5 391.5t-391.5 184.5q-25 2 -41.5 20t-16.5 43v135q0 29 21 47q17 17 43 17h5q160 -13 306 -80.5 t259 -181.5q114 -113 181.5 -259t80.5 -306zM1408 67q2 -27 -18 -47q-18 -20 -46 -20h-143q-26 0 -44.5 17.5t-19.5 42.5q-12 215 -101 408.5t-231.5 336t-336 231.5t-408.5 102q-25 1 -42.5 19.5t-17.5 43.5v143q0 28 20 46q18 18 44 18h3q262 -13 501.5 -120t425.5 -294 q187 -186 294 -425.5t120 -501.5z" />
+<glyph unicode="&#xf0a0;" d="M1040 320q0 -33 -23.5 -56.5t-56.5 -23.5t-56.5 23.5t-23.5 56.5t23.5 56.5t56.5 23.5t56.5 -23.5t23.5 -56.5zM1296 320q0 -33 -23.5 -56.5t-56.5 -23.5t-56.5 23.5t-23.5 56.5t23.5 56.5t56.5 23.5t56.5 -23.5t23.5 -56.5zM1408 160v320q0 13 -9.5 22.5t-22.5 9.5 h-1216q-13 0 -22.5 -9.5t-9.5 -22.5v-320q0 -13 9.5 -22.5t22.5 -9.5h1216q13 0 22.5 9.5t9.5 22.5zM178 640h1180l-157 482q-4 13 -16 21.5t-26 8.5h-782q-14 0 -26 -8.5t-16 -21.5zM1536 480v-320q0 -66 -47 -113t-113 -47h-1216q-66 0 -113 47t-47 113v320q0 25 16 75 l197 606q17 53 63 86t101 33h782q55 0 101 -33t63 -86l197 -606q16 -50 16 -75z" />
+<glyph unicode="&#xf0a1;" horiz-adv-x="1792" d="M1664 896q53 0 90.5 -37.5t37.5 -90.5t-37.5 -90.5t-90.5 -37.5v-384q0 -52 -38 -90t-90 -38q-417 347 -812 380q-58 -19 -91 -66t-31 -100.5t40 -92.5q-20 -33 -23 -65.5t6 -58t33.5 -55t48 -50t61.5 -50.5q-29 -58 -111.5 -83t-168.5 -11.5t-132 55.5q-7 23 -29.5 87.5 t-32 94.5t-23 89t-15 101t3.5 98.5t22 110.5h-122q-66 0 -113 47t-47 113v192q0 66 47 113t113 47h480q435 0 896 384q52 0 90 -38t38 -90v-384zM1536 292v954q-394 -302 -768 -343v-270q377 -42 768 -341z" />
+<glyph unicode="&#xf0a2;" horiz-adv-x="1664" d="M848 -160q0 16 -16 16q-59 0 -101.5 42.5t-42.5 101.5q0 16 -16 16t-16 -16q0 -73 51.5 -124.5t124.5 -51.5q16 0 16 16zM183 128h1298q-164 181 -246.5 411.5t-82.5 484.5q0 256 -320 256t-320 -256q0 -254 -82.5 -484.5t-246.5 -411.5zM1664 128q0 -52 -38 -90t-90 -38 h-448q0 -106 -75 -181t-181 -75t-181 75t-75 181h-448q-52 0 -90 38t-38 90q190 161 287 397.5t97 498.5q0 165 96 262t264 117q-8 18 -8 37q0 40 28 68t68 28t68 -28t28 -68q0 -19 -8 -37q168 -20 264 -117t96 -262q0 -262 97 -498.5t287 -397.5z" />
+<glyph unicode="&#xf0a3;" d="M1376 640l138 -135q30 -28 20 -70q-12 -41 -52 -51l-188 -48l53 -186q12 -41 -19 -70q-29 -31 -70 -19l-186 53l-48 -188q-10 -40 -51 -52q-12 -2 -19 -2q-31 0 -51 22l-135 138l-135 -138q-28 -30 -70 -20q-41 11 -51 52l-48 188l-186 -53q-41 -12 -70 19q-31 29 -19 70 l53 186l-188 48q-40 10 -52 51q-10 42 20 70l138 135l-138 135q-30 28 -20 70q12 41 52 51l188 48l-53 186q-12 41 19 70q29 31 70 19l186 -53l48 188q10 41 51 51q41 12 70 -19l135 -139l135 139q29 30 70 19q41 -10 51 -51l48 -188l186 53q41 12 70 -19q31 -29 19 -70 l-53 -186l188 -48q40 -10 52 -51q10 -42 -20 -70z" />
+<glyph unicode="&#xf0a4;" horiz-adv-x="1792" d="M256 192q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1664 768q0 51 -39 89.5t-89 38.5h-576q0 20 15 48.5t33 55t33 68t15 84.5q0 67 -44.5 97.5t-115.5 30.5q-24 0 -90 -139q-24 -44 -37 -65q-40 -64 -112 -145q-71 -81 -101 -106 q-69 -57 -140 -57h-32v-640h32q72 0 167 -32t193.5 -64t179.5 -32q189 0 189 167q0 26 -5 56q30 16 47.5 52.5t17.5 73.5t-18 69q53 50 53 119q0 25 -10 55.5t-25 47.5h331q52 0 90 38t38 90zM1792 769q0 -105 -75.5 -181t-180.5 -76h-169q-4 -62 -37 -119q3 -21 3 -43 q0 -101 -60 -178q1 -139 -85 -219.5t-227 -80.5q-133 0 -322 69q-164 59 -223 59h-288q-53 0 -90.5 37.5t-37.5 90.5v640q0 53 37.5 90.5t90.5 37.5h288q10 0 21.5 4.5t23.5 14t22.5 18t24 22.5t20.5 21.5t19 21.5t14 17q65 74 100 129q13 21 33 62t37 72t40.5 63t55 49.5 t69.5 17.5q125 0 206.5 -67t81.5 -189q0 -68 -22 -128h374q104 0 180 -76t76 -179z" />
+<glyph unicode="&#xf0a5;" horiz-adv-x="1792" d="M1376 128h32v640h-32q-35 0 -67 11.5t-64 38.5t-48 44t-50 55q-2 3 -3.5 4.5t-4 4.5t-4.5 5q-72 81 -112 145q-14 22 -38 68q-1 3 -10.5 22.5t-18.5 36t-20 35.5t-21.5 30.5t-18.5 11.5q-71 0 -115.5 -30.5t-44.5 -97.5q0 -43 15 -84.5t33 -68t33 -55t15 -48.5h-576 q-50 0 -89 -38.5t-39 -89.5q0 -52 38 -90t90 -38h331q-15 -17 -25 -47.5t-10 -55.5q0 -69 53 -119q-18 -32 -18 -69t17.5 -73.5t47.5 -52.5q-4 -24 -4 -56q0 -85 48.5 -126t135.5 -41q84 0 183 32t194 64t167 32zM1664 192q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45 t45 -19t45 19t19 45zM1792 768v-640q0 -53 -37.5 -90.5t-90.5 -37.5h-288q-59 0 -223 -59q-190 -69 -317 -69q-142 0 -230 77.5t-87 217.5l1 5q-61 76 -61 178q0 22 3 43q-33 57 -37 119h-169q-105 0 -180.5 76t-75.5 181q0 103 76 179t180 76h374q-22 60 -22 128 q0 122 81.5 189t206.5 67q38 0 69.5 -17.5t55 -49.5t40.5 -63t37 -72t33 -62q35 -55 100 -129q2 -3 14 -17t19 -21.5t20.5 -21.5t24 -22.5t22.5 -18t23.5 -14t21.5 -4.5h288q53 0 90.5 -37.5t37.5 -90.5z" />
+<glyph unicode="&#xf0a6;" d="M1280 -64q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1408 700q0 189 -167 189q-26 0 -56 -5q-16 30 -52.5 47.5t-73.5 17.5t-69 -18q-50 53 -119 53q-25 0 -55.5 -10t-47.5 -25v331q0 52 -38 90t-90 38q-51 0 -89.5 -39t-38.5 -89v-576 q-20 0 -48.5 15t-55 33t-68 33t-84.5 15q-67 0 -97.5 -44.5t-30.5 -115.5q0 -24 139 -90q44 -24 65 -37q64 -40 145 -112q81 -71 106 -101q57 -69 57 -140v-32h640v32q0 72 32 167t64 193.5t32 179.5zM1536 705q0 -133 -69 -322q-59 -164 -59 -223v-288q0 -53 -37.5 -90.5 t-90.5 -37.5h-640q-53 0 -90.5 37.5t-37.5 90.5v288q0 10 -4.5 21.5t-14 23.5t-18 22.5t-22.5 24t-21.5 20.5t-21.5 19t-17 14q-74 65 -129 100q-21 13 -62 33t-72 37t-63 40.5t-49.5 55t-17.5 69.5q0 125 67 206.5t189 81.5q68 0 128 -22v374q0 104 76 180t179 76 q105 0 181 -75.5t76 -180.5v-169q62 -4 119 -37q21 3 43 3q101 0 178 -60q139 1 219.5 -85t80.5 -227z" />
+<glyph unicode="&#xf0a7;" d="M1408 576q0 84 -32 183t-64 194t-32 167v32h-640v-32q0 -46 -25 -91t-52 -72t-72 -66q-9 -8 -14 -12q-81 -72 -145 -112q-22 -14 -68 -38q-3 -1 -22.5 -10.5t-36 -18.5t-35.5 -20t-30.5 -21.5t-11.5 -18.5q0 -71 30.5 -115.5t97.5 -44.5q43 0 84.5 15t68 33t55 33 t48.5 15v-576q0 -50 38.5 -89t89.5 -39q52 0 90 38t38 90v331q46 -35 103 -35q69 0 119 53q32 -18 69 -18t73.5 17.5t52.5 47.5q24 -4 56 -4q85 0 126 48.5t41 135.5zM1280 1344q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1536 580q0 -142 -77.5 -230 t-217.5 -87l-5 1q-76 -61 -178 -61q-22 0 -43 3q-54 -30 -119 -37v-169q0 -105 -76 -180.5t-181 -75.5q-103 0 -179 76t-76 180v374q-54 -22 -128 -22q-121 0 -188.5 81.5t-67.5 206.5q0 38 17.5 69.5t49.5 55t63 40.5t72 37t62 33q55 35 129 100q3 2 17 14t21.5 19 t21.5 20.5t22.5 24t18 22.5t14 23.5t4.5 21.5v288q0 53 37.5 90.5t90.5 37.5h640q53 0 90.5 -37.5t37.5 -90.5v-288q0 -59 59 -223q69 -190 69 -317z" />
+<glyph unicode="&#xf0a8;" d="M1280 576v128q0 26 -19 45t-45 19h-502l189 189q19 19 19 45t-19 45l-91 91q-18 18 -45 18t-45 -18l-362 -362l-91 -91q-18 -18 -18 -45t18 -45l91 -91l362 -362q18 -18 45 -18t45 18l91 91q18 18 18 45t-18 45l-189 189h502q26 0 45 19t19 45zM1536 640 q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+<glyph unicode="&#xf0a9;" d="M1285 640q0 27 -18 45l-91 91l-362 362q-18 18 -45 18t-45 -18l-91 -91q-18 -18 -18 -45t18 -45l189 -189h-502q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h502l-189 -189q-19 -19 -19 -45t19 -45l91 -91q18 -18 45 -18t45 18l362 362l91 91q18 18 18 45zM1536 640 q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+<glyph unicode="&#xf0aa;" d="M1284 641q0 27 -18 45l-362 362l-91 91q-18 18 -45 18t-45 -18l-91 -91l-362 -362q-18 -18 -18 -45t18 -45l91 -91q18 -18 45 -18t45 18l189 189v-502q0 -26 19 -45t45 -19h128q26 0 45 19t19 45v502l189 -189q19 -19 45 -19t45 19l91 91q18 18 18 45zM1536 640 q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+<glyph unicode="&#xf0ab;" d="M1284 639q0 27 -18 45l-91 91q-18 18 -45 18t-45 -18l-189 -189v502q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-502l-189 189q-19 19 -45 19t-45 -19l-91 -91q-18 -18 -18 -45t18 -45l362 -362l91 -91q18 -18 45 -18t45 18l91 91l362 362q18 18 18 45zM1536 640 q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+<glyph unicode="&#xf0ac;" d="M1193 993q11 7 25 22v-1q0 -2 -9.5 -10t-11.5 -12q-1 1 -4 1zM1187 992q-1 1 -2.5 3t-1.5 3q3 -2 10 -5q-6 -4 -6 -1zM728 1175q-16 2 -26 5q1 0 6.5 -1t10.5 -2t9 -2zM773 1212q7 4 13.5 2.5t7.5 -7.5q-5 3 -21 5zM765 1206l-3 2q-2 3 -5.5 5t-4.5 2q2 -1 21 -3 q-6 -4 -8 -6zM663 1290v2q1 -2 3 -5.5t3 -5.5zM558 1250q0 -2 -1 -2l-1 2h2zM933 206v-1v1zM768 1408q209 0 385.5 -103t279.5 -279.5t103 -385.5t-103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103zM1240 162 l5 5q-7 10 -29 12q1 12 -14 26.5t-27 15.5q0 4 -10.5 11t-17.5 8q-9 2 -27 -9q-7 -3 -4 -5q-3 3 -12 11t-16 11q-2 1 -7.5 1t-8.5 2q-1 1 -6 4.5t-7 4.5t-6.5 3t-7.5 1.5t-7.5 -2.5t-8.5 -6t-4.5 -15.5t-2.5 -14.5q-8 6 -0.5 20t1.5 20q-7 7 -21 0.5t-21 -15.5 q-1 -1 -9.5 -5.5t-11.5 -7.5q-4 -6 -9 -17.5t-6 -13.5q0 2 -2.5 6.5t-2.5 6.5q-12 -2 -16 3q5 -16 8 -17l-4 2q-1 -6 3 -15t4 -11q1 -5 -1.5 -13t-2.5 -11q0 -2 5 -11q4 -19 -2 -32q0 -1 -3.5 -7t-6.5 -11l-2 -5l-2 1q-1 1 -2 0q-1 -6 -9 -13t-10 -
 11q-15 -23 -9 -38 q3 -8 10 -10q3 -1 3 2q1 -9 -11 -27q1 -1 4 -3q-17 0 -10 -14q202 36 352 181h-3zM680 347q16 3 30.5 -16t22.5 -23q41 -20 59 -11q0 -9 14 -28q3 -4 6.5 -11.5t5.5 -10.5q5 -7 19 -16t19 -16q6 3 9 9q13 -35 24 -34q5 0 8 8q0 -1 -0.5 -3t-1.5 -3q7 15 5 26l6 4q5 4 5 5 q-6 6 -9 -3q-30 -14 -48 22q-2 3 -4.5 8t-5 12t-1.5 11.5t6 4.5q11 0 12.5 1.5t-2.5 6t-4 7.5q-1 4 -1.5 12.5t-1.5 12.5l-5 6q-5 6 -11.5 13.5t-7.5 9.5q-4 -10 -16.5 -8.5t-18.5 9.5q1 -2 -0.5 -6.5t-1.5 -6.5q-14 0 -17 1q1 6 3 21t4 22q1 5 5.5 13.5t8 15.5t4.5 14 t-4.5 10.5t-18.5 2.5q-20 -1 -29 -22q-1 -3 -3 -11.5t-5 -12.5t-9 -7q-8 -3 -27 -2t-26 5q-14 8 -24 30.5t-11 41.5q0 10 3 27.5t3 27t-6 26.5q3 2 10 10.5t11 11.5q2 2 5 2h5t4 2t3 6q-1 1 -4 3q-3 3 -4 3q4 -3 19 -1t19 2q0 1 22 0q17 -13 24 2q0 1 -2.5 10.5t-0.5 14.5 q5 -29 32 -10q3 -4 16.5 -6t18.5 -5q3 -2 7 -5.5t6 -5t6 -0.5t9 7q11 -17 13 -25q11 -43 20 -48q8 -2 12.5 -2t5 10.5t0 15.5t-1.5 13l-2 37q-16 3 -20 12.5t1.5 20t16.5 19.5q1 1 16.5 8t21.5 12q24 19 17 39q9 -2 11 9l-5 3q-4 3 -8 5.5t-5
  1.5q11 7 2 18q5 3 8 11.5 t9 11.5q9 -14 22 -3q8 9 2 18q5 8 22 11.5t20 9.5q5 -1 7 0t2 4.5v7.5t1 8.5t3 7.5q4 6 16 10.5t14 5.5l19 12q4 4 0 4q18 -2 32 11q13 12 -5 23q2 7 -4 10.5t-16 5.5q3 

<TRUNCATED>
http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/app/font/fontawesome-webfont.ttf
----------------------------------------------------------------------
diff --git a/src/main/ui/app/font/fontawesome-webfont.ttf b/src/main/ui/app/font/fontawesome-webfont.ttf
new file mode 100755
index 0000000..d461724
Binary files /dev/null and b/src/main/ui/app/font/fontawesome-webfont.ttf differ


[46/51] [abbrv] [partial] Adding Jinwon's custom RCMET

Posted by jo...@apache.org.
http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/rcmes/cli/rcmet_ui.py
----------------------------------------------------------------------
diff --git a/src/main/python/rcmes/cli/rcmet_ui.py b/src/main/python/rcmes/cli/rcmet_ui.py
new file mode 100755
index 0000000..ddc11f6
--- /dev/null
+++ b/src/main/python/rcmes/cli/rcmet_ui.py
@@ -0,0 +1,91 @@
+#!/usr/local/bin/python
+""" 
+    Step by Step Wizard that demonstrates how the underlying RCMES code can
+    be used to generate climate dataset intercomparisons
+"""
+# Imports
+# Native Python Module Imports
+import sys
+
+# RCMES Imports
+from classes import Model, JobProperties, GridBox
+import storage.rcmed as rcmed
+import toolkit.metrics
+import toolkit.do_data_prep
+from utils import misc
+
+def rcmetUI():
+    """"
+    Command Line User interface for RCMET.
+    Collects user OPTIONS then runs RCMET to perform processing.
+    
+    Duplicates job of GUI.
+    """
+    print 'Regional Climate Model Evaluation System BETA'
+    print "Querying RCMED for available parameters..."
+
+    try:
+        parameters = rcmed.getParams()
+    except Exception:
+        raise
+        sys.exit()
+
+    # Section 0: Collect directories to store RCMET working files.
+    workDir, cacheDir = misc.getDirSettings()
+    temporalGrid = misc.getTemporalGrid()
+    spatialGrid = misc.getSpatialGrid()
+    jobProperties = JobProperties(workDir, cacheDir, spatialGrid, temporalGrid)
+    
+    # Section 1a: Enter model file/s
+    modelFiles = misc.getModelFiles()
+    # Create a list of model objects for use later
+    models = [Model(modelFile) for modelFile in modelFiles]
+
+    # Section 3b: Select 1 Parameter from list
+    for parameter in parameters:
+        """( 38 ) - CRU3.1 Daily-Mean Temperature : monthly"""
+        print "({:^2}) - {:<54} :: {:<10}".format(parameter['parameter_id'], parameter['longname'], parameter['timestep'])
+
+    obsDatasetList = []
+    validParamIds = [int(p['parameter_id']) for p in parameters]
+    while obsDatasetList == []:
+        print("Please select the available observation you would like to use from the list above:")
+        userChoice = int(raw_input(">>>"))
+        if userChoice in validParamIds:
+            for param in parameters:
+                if param['parameter_id'] == userChoice:
+                    obsDatasetList.append(param)
+                else:
+                    pass
+        else:
+            print("Your selection '%s' is invalid.  Please make another selection." % userChoice)
+    
+
+    # User must provide startTime and endTime if not defined
+    if jobProperties.startDate == None or jobProperties.endDate == None:
+        jobProperties.startDate, jobProperties.endDate = misc.userDefinedStartEndTimes(obsDatasetList, models)
+
+    try:
+        gridBox = GridBox(jobProperties.latMin, jobProperties.lonMin, jobProperties.latMax,
+                          jobProperties.lonMax, jobProperties.gridLonStep, jobProperties.gridLatStep)
+    except:
+        gridBox = None
+
+    numOBS, numMDL, nT, ngrdY, ngrdX, Times, lons, lats, obsData, mdlData, obsList, mdlName = toolkit.do_data_prep.prep_data(jobProperties, obsDatasetList, gridBox, models)
+  
+    counts = {'observations': numOBS,
+              'models'      : numMDL,
+              'times'       : nT}
+    subRegions = misc.getSubRegionsInteractively(counts, jobProperties.workDir)
+
+    # TODO: New function Call
+    fileOutputOption = jobProperties.writeOutFile
+    modelVarName = models[0].varName
+    toolkit.metrics.metrics_plots(modelVarName, numOBS, numMDL, nT, ngrdY, ngrdX, Times, lons, lats, obsData, mdlData, obsList, mdlName, workDir, subRegions, fileOutputOption)
+
+
+
+# Actually call the UI function.
+if __name__ == "__main__":
+    rcmetUI()
+

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/rcmes/cli/rcmet_ui.pyc
----------------------------------------------------------------------
diff --git a/src/main/python/rcmes/cli/rcmet_ui.pyc b/src/main/python/rcmes/cli/rcmet_ui.pyc
new file mode 100644
index 0000000..bc5ed9f
Binary files /dev/null and b/src/main/python/rcmes/cli/rcmet_ui.pyc differ

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/rcmes/rcmet.py
----------------------------------------------------------------------
diff --git a/src/main/python/rcmes/rcmet.py b/src/main/python/rcmes/rcmet.py
new file mode 100755
index 0000000..01799f9
--- /dev/null
+++ b/src/main/python/rcmes/rcmet.py
@@ -0,0 +1,305 @@
+#!/usr/local/python27
+""" DOCSTRING"""
+
+# Python Standard Lib Imports
+import argparse
+import ConfigParser
+import datetime
+import glob
+import os
+import sys
+import numpy as np
+import numpy.ma as ma
+
+
+# RCMES Imports
+import storage.rcmed as db
+from toolkit import do_data_prep, process, metrics
+from utils import misc
+from classes import JobProperties, Model, GridBox
+from cli import rcmet_ui as ui
+
+parser = argparse.ArgumentParser(description='Regional Climate Model Evaluation Toolkit.  Use -h for help and options')
+parser.add_argument('-c', '--config', dest='CONFIG', help='Path to an evaluation configuration file')
+args = parser.parse_args()
+
+def checkConfigSettings(config):
+    """ This function will check the SETTINGS block of the user supplied config file.
+    This will only check if the working and cache dirs are writable from this program.
+    Additional configuration parameters can be checked here later on.
+    
+    Input::
+        config - ConfigParser configuration object
+    
+    Output::
+        none - An exception will be raised if something goes wrong
+    """
+    settings = config.items('SETTINGS')
+    for key_val in settings:
+        # Check the user provided directories are valid
+        if key_val[0] == 'workDir' or key_val[0] == 'cacheDir':
+            _ =  misc.isDirGood(os.path.abspath(key_val[1]))
+
+        else:
+            pass    
+
+def setSettings(settings, config):
+    """
+    This function is used to set the values within the 'SETTINGS' dictionary when a user provides an external
+    configuration file.
+    
+    Input::
+        settings - Python Dictionary object that will collect the key : value pairs
+        config - A configparse object that contains the external config values
+    
+    Output::
+        None - The settings dictionary will be updated in place.
+    """
+    pass
+
+def generateModels(modelConfig):
+    """
+    This function will return a list of Model objects that can easily be used for 
+    metric computation and other processing tasks.
+    
+    Input::  
+        modelConfig - list of ('key', 'value') tuples.  Below is a list of valid keys
+            filenamepattern - string i.e. '/nas/run/model/output/MOD*precip*.nc'
+            latvariable - string i.e. 'latitude'
+            lonvariable - string i.e. 'longitude'
+            timevariable - string i.e. 't'
+            timestep - string 'monthly' | 'daily' | 'annual'
+            varname - string i.e. 'pr'
+
+    Output::
+        modelList - List of Model objects
+    """
+    # Setup the config Data Dictionary to make parsing easier later
+    configData = {}
+    for entry in modelConfig:
+        configData[entry[0]] = entry[1]
+
+    modelFileList = None
+    for keyValTuple in modelConfig:
+        if keyValTuple[0] == 'filenamePattern':
+            modelFileList = glob.glob(keyValTuple[1])
+            modelFileList.sort()
+
+    # Remove the filenamePattern from the dict since it is no longer used
+    configData.pop('filenamePattern')
+    
+    models = []
+    for modelFile in modelFileList:
+        # use getModelTimes(modelFile,timeVarName) to generate the modelTimeStep and time list
+        _ , configData['timeStep'] = process.getModelTimes(modelFile, configData['timeVariable'])
+        configData['filename'] = modelFile
+        model = Model(**configData)
+        models.append(model)
+    
+    return models
+
+def generateSettings(config):
+    """
+    Helper function to decouple the argument parsing from the Settings object creation
+    
+    Input::  
+        config - list of ('key', 'value') tuples.
+            workdir - string i.e. '/nas/run/rcmet/work/'
+            cachedir - string i.e. '/tmp/rcmet/cache/'
+    Output::
+        JobProperties - JobProperties Object
+    """
+    # Setup the config Data Dictionary to make parsing easier later
+    configData = {}
+    for entry in config:
+        configData[entry[0]] = entry[1]
+        
+    return JobProperties(**configData)
+
+def makeDatasetsDictionary(rcmedConfig):
+    """
+    Helper function to decouple the argument parsing from the RCMEDDataset object creation
+
+    Input::  
+        rcmedConfig - list of ('key', 'value') tuples.
+            obsDatasetId=3,10
+            obsParamId=36,32
+            obsTimeStep=monthly,monthly
+
+    Output::
+        datasetDict - Dictionary with dataset metadata
+    # Setup the config Data Dictionary to make parsing easier later
+    """
+    delimiter = ','
+    configData = {}
+    for entry in rcmedConfig:
+        if delimiter in entry[1]:
+            # print 'delim found - %s' % entry[1]
+            valueList = entry[1].split(delimiter)
+            configData[entry[0]] = valueList
+        else:
+            configData[entry[0]] = entry[1:]
+
+    return configData
+
+def tempGetYears():
+    startYear = int(raw_input('Enter start year YYYY \n'))
+    endYear = int(raw_input('Enter end year YYYY \n'))
+    # CGOODALE - Updating the Static endTime to be 31-DEC
+    startTime = datetime.datetime(startYear, 1, 1, 0, 0)
+    endTime = datetime.datetime(endYear, 12, 31, 0, 0)
+    return (startTime, endTime)
+
+
+def runUsingConfig(argsConfig):
+    """
+    This function is called when a user provides a configuration file to specify an evaluation job.
+
+    Input::
+        argsConfig - Path to a ConfigParser compliant file
+
+    Output::
+        Plots that visualize the evaluation job. These will be output to SETTINGS.workDir from the config file
+    """
+    
+    print 'Running using config file: %s' % argsConfig
+    # Parse the Config file
+    userConfig = ConfigParser.SafeConfigParser()
+    userConfig.optionxform = str # This is so the case is preserved on the items in the config file
+    userConfig.read(argsConfig)
+
+    try:
+        checkConfigSettings(userConfig)
+    except:
+        raise
+
+    jobProperties = generateSettings(userConfig.items('SETTINGS'))
+    workdir = jobProperties.workDir
+    
+    try:
+        gridBox = GridBox(jobProperties.latMin, jobProperties.lonMin, jobProperties.latMax,
+                          jobProperties.lonMax, jobProperties.gridLonStep, jobProperties.gridLatStep)
+    except:
+        gridBox = None
+
+    models = generateModels(userConfig.items('MODEL'))
+    
+    # 5/28/2013, JK: The RCMED block has been modified to accommodate ref data input from users' local disk
+
+    datasetDict = makeDatasetsDictionary(userConfig.items('RCMED'))
+
+
+    # Go get the parameter listing from the database
+    try:
+        params = db.get_parameters_metadata()
+    except:
+        raise
+
+    obsDatasetList = []
+    obsList = []
+    obsVarName = datasetDict['obsVarName'][0]
+    obsTimeName = datasetDict['obsTimeVar'][0]
+    obsLonName = datasetDict['obsLonVar'][0]
+    obsLatName = datasetDict['obsLatVar'][0]
+    obsTimestep = []
+    obsSource = int(datasetDict['obsSource'][0])
+    #print 'Obs datasetDict'
+    #print datasetDict
+
+    if obsSource < 0:                             # no obs data to be processed
+        obsVarName = []
+        obsTimeName = []
+        obsLonName = []
+        obsLatName = []
+    elif obsSource == 0:                          # input from RCMED
+        for param_id in datasetDict['obsParamId']:
+            for param in params:
+                if int(param['parameter_id']) == int(param_id):
+                    obsDatasetList.append(param)
+                else:
+                    pass
+    elif obsSource == 1:                        # input from local disk
+        for param in datasetDict['obsInputFile']:
+            obsDatasetList.append(param)
+        for param in datasetDict['obsFileName']:
+            obsList.append(param)
+        for param in datasetDict['obsDltaTime']:
+            obsTimestep.append(param)
+    #print obsSource,obsDatasetList,obsList,obsTimeName,obsTimestep
+
+    #TODO: Unhardcode this when we decided where this belongs in the Config File
+    jobProperties.maskOption = True
+    # User must provide startTime and endTime if not defined
+    if jobProperties.startDate == None or jobProperties.endDate == None:
+        jobProperties.startDate,jobProperties.endDate = misc.userDefinedStartEndTimes(obsSource,obsList,obsTimeName,obsDatasetList,models)
+
+    numOBS,numMDL,nT,ngrdY,ngrdX,Times,lons,lats,obsData,mdlData,obsName,mdlName,varType = do_data_prep.prep_data   \
+          (jobProperties,obsSource,obsDatasetList,obsList,obsVarName,obsLonName,obsLatName,obsTimeName,obsTimestep,gridBox,models)
+
+    # 6/3/2013: Combine the regridded reference and model datasets. The packing order is: 
+    #               First pack all ref (obs) data with the ref enseble in the end (if exists).
+    #               Then pack all model data with the model ensemble in the end (if exists)
+    #           Release 'obsData' and 'mdlData' after their values are transferred to 'allData'
+    print 'Input and regridding of both obs and model data are completed. Combine the obs and model data'
+    numDatasets = numOBS + numMDL
+    allData = ma.zeros((numDatasets, nT, ngrdY, ngrdX))
+    if (numOBS>0) & (numMDL>0):
+        dataName = obsName + mdlName
+        allData[0:numOBS, :, :, :] = obsData[0:numOBS, :, :, :]
+        allData[numOBS:numDatasets, :, :, :] = mdlData[0:numMDL, :, :, :]
+        obsData = 0.
+        mdlData = 0.
+    elif numOBS==0:
+        dataName = mdlName
+        allData = mdlData
+        mdlData = 0.
+    else:
+        dataName = obsName
+        allData = obsData
+        obsData = 0
+    print ''
+    print 'dataName: ',dataName,' shape of all data= ',allData.shape
+
+    ##################################################################################
+    # calculate metrics and make plots using the regridded reference and model data. #
+    ##################################################################################
+    print 'Data preparation is completed; now move to metrics calculations'
+    
+    try:
+        subRegionConfig = misc.configToDict(userConfig.items('SUB_REGION'))
+        subRegions = misc.parseSubRegions(subRegionConfig)
+        # REORDER SUBREGION OBJECTS until we standardize on Python 2.7
+        # TODO Remove once Python 2.7 support is finalized
+        if subRegions:
+            subRegions.sort(key=lambda x:x.name)
+        
+    except ConfigParser.NoSectionError:
+        
+        counts = {'observations': numOBS,
+                  'models'      : numMDL,
+                  'times'       : nT}
+        subRegions = misc.getSubRegionsInteractively(counts, workdir)
+        
+        if len(subRegions) == 0:
+            print 'Processing without SubRegion support'
+        
+
+    # TODO: New function Call
+    timeRegridOption = jobProperties.temporalGrid
+    fileOutputOption = jobProperties.writeOutFile
+    modelVarName = models[0].varName
+    metrics.metrics_plots(modelVarName, numOBS, numMDL, nT, ngrdY, ngrdX, Times, lons, lats, allData, dataName, workdir, subRegions, \
+                          timeRegridOption, fileOutputOption, varType)
+
+
+if __name__ == "__main__":
+    
+    if args.CONFIG:
+        
+        runUsingConfig(args.CONFIG)
+
+    else:
+        print 'Interactive mode has been enabled'
+        ui.rcmetUI()
+
+    #rcmet_cordexAF()

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/rcmes/resources/.svn/all-wcprops
----------------------------------------------------------------------
diff --git a/src/main/python/rcmes/resources/.svn/all-wcprops b/src/main/python/rcmes/resources/.svn/all-wcprops
new file mode 100755
index 0000000..b1b775d
--- /dev/null
+++ b/src/main/python/rcmes/resources/.svn/all-wcprops
@@ -0,0 +1,17 @@
+K 25
+svn:wc:ra_dav:version-url
+V 89
+/repos/asf/!svn/ver/1479720/incubator/climate/trunk/rcmet/src/main/python/rcmes/resources
+END
+cordexSubRegions.txt
+K 25
+svn:wc:ra_dav:version-url
+V 110
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/python/rcmes/resources/cordexSubRegions.txt
+END
+cordexAF.cfg
+K 25
+svn:wc:ra_dav:version-url
+V 102
+/repos/asf/!svn/ver/1479720/incubator/climate/trunk/rcmet/src/main/python/rcmes/resources/cordexAF.cfg
+END

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/rcmes/resources/.svn/entries
----------------------------------------------------------------------
diff --git a/src/main/python/rcmes/resources/.svn/entries b/src/main/python/rcmes/resources/.svn/entries
new file mode 100755
index 0000000..71a5233
--- /dev/null
+++ b/src/main/python/rcmes/resources/.svn/entries
@@ -0,0 +1,99 @@
+10
+
+dir
+1485921
+https://svn.apache.org/repos/asf/incubator/climate/trunk/rcmet/src/main/python/rcmes/resources
+https://svn.apache.org/repos/asf
+
+
+
+2013-05-06T23:24:37.933090Z
+1479720
+huikyole
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+13f79535-47bb-0310-9956-ffa450edef68
+
+cordexSubRegions.txt
+file
+
+
+
+
+2013-05-24T10:13:50.000000Z
+b2e732c6fd18365a4a2ffdff8cde539c
+2013-01-25T19:56:01.681818Z
+1474794
+mjjoyce
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+928
+
+watersheds
+dir
+
+cordexAF.cfg
+file
+
+
+
+
+2013-05-24T10:13:50.000000Z
+914367b5c8e85cb405f1c5c548110445
+2013-05-06T23:24:37.933090Z
+1479720
+huikyole
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+956
+

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/rcmes/resources/.svn/text-base/cordexAF.cfg.svn-base
----------------------------------------------------------------------
diff --git a/src/main/python/rcmes/resources/.svn/text-base/cordexAF.cfg.svn-base b/src/main/python/rcmes/resources/.svn/text-base/cordexAF.cfg.svn-base
new file mode 100755
index 0000000..77ee0d5
--- /dev/null
+++ b/src/main/python/rcmes/resources/.svn/text-base/cordexAF.cfg.svn-base
@@ -0,0 +1,30 @@
+[SETTINGS]
+workDir=/home/huikyole/work/RCMES/cases/cordex-af
+cacheDir=/nas/share4-cf/huikyole/RCMES_cache
+# Choices: full, annual, monthly, daily
+temporalGrid=monthly
+# Choices, obs, model, user
+spatialGrid=model
+gridLonStep=0.44 ; only use with user spatialGrid
+gridLatStep=0.44 ; only use with user spatialGrid
+latMin=-45.76 ; only use with user spatialGrid
+latMax=42.24 ; only use with user spatialGrid
+lonMin=-24.64 ; only use with user spatialGrid
+lonMax=60.28 ; only use with user spatialGrid
+# Choices: False, NetCDF
+outputFile=NetCDF
+[MODEL]
+filenamePattern=/nas/share4-cf/jinwonki/data/cordex-af/*pr.nc
+latVariable=lat
+lonVariable=lon
+timeVariable=time
+varName=pr
+precipFlag=True ; This is just used to support an unknown UNITS in precip data
+
+[RCMED]
+obsParamId=36  ; pcp  and pr
+obsTimeStep=monthly ; WITH THE PARAMETER SERVICE THIS WILL GO AWAY
+
+[SUB_REGION]
+# Sub Region(s) Full File Path
+subRegionFile=../rcmes/resources/cordexSubRegions.txt

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/rcmes/resources/.svn/text-base/cordexSubRegions.txt.svn-base
----------------------------------------------------------------------
diff --git a/src/main/python/rcmes/resources/.svn/text-base/cordexSubRegions.txt.svn-base b/src/main/python/rcmes/resources/.svn/text-base/cordexSubRegions.txt.svn-base
new file mode 100755
index 0000000..c4dc220
--- /dev/null
+++ b/src/main/python/rcmes/resources/.svn/text-base/cordexSubRegions.txt.svn-base
@@ -0,0 +1,25 @@
+[REGIONS]
+# RegionXX:["region Label", north, south, east, west] >>> Region00:["Region Zero", 30.1, 10.54, 92.1332, -10.7 ]
+#TestRegion:["TEST", 27, 25, 15, 12]
+Region01:["R01", 36.5, 29, 0.0, -10]
+Region02:["R02", 37.5, 29, 10, 0]
+Region03:["R03", 32.5, 25, 20, 10]
+Region04:["R04", 32.5, 25, 33, 20]
+Region05:["R05", 20.0, 12, -10.2, -19.3]
+Region06:["R06", 25.0, 15.0, 30, 15]
+Region07:["R07", 15,   7.3, 10, -10]
+Region08:["R08", 7.3,  5.0, 10, -10]
+Region09:["R09", 15, 6.9, 40, 33.9]
+Region10:["R10", 11.8, 2.2, 51.8, 44.2]
+Region11:["R11", 10, 0, 25, 10]
+Region12:["R12", 0, -10, 25, 10]
+Region13:["R13", 0, -15, 40, 30]
+Region14:["R14", -21.4, -27.9, 20, 13.6]
+Region15:["R15", -27.9, -35, 20, 13.6]
+Region16:["R16", -21.4, -35, 35.7, 20]
+Region17:["R17", -11.7, -25.8, 50.3, 43.2]
+Region18:["R18", 35.0, 25, 40, 33]
+Region19:["R19", 35, 28, 50, 45]
+Region20:["R20", 20.0, 13, 50, 43]
+Region21:["R21", 27.5, 20, 58, 50]
+

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/rcmes/resources/cordexAF.cfg
----------------------------------------------------------------------
diff --git a/src/main/python/rcmes/resources/cordexAF.cfg b/src/main/python/rcmes/resources/cordexAF.cfg
new file mode 100755
index 0000000..b26d279
--- /dev/null
+++ b/src/main/python/rcmes/resources/cordexAF.cfg
@@ -0,0 +1,55 @@
+# The configure file for the Indian subdomain of the CORDEX-Asia domain
+[SETTINGS]
+workDir=/Volumes/rcmes2t/rcmet/cases/cordex-af/work
+cacheDir=/Volumes/rcmes2t/rcmet/cases/cordex-af/cache
+# temporalGrid assigns the data time step to be temporally regridded: Choices = full (entire period), annual, monthly, daily
+temporalGrid=monthly
+# Choices, obs, model, user
+# gridLonStep, gridLatStep, latMin, latMax, lonMin, lonMax are used only with 'user' spatial grid option
+spatialGrid=user
+gridLonStep=0.44
+gridLatStep=0.44
+latMin=-45.76
+latMax=42.24
+lonMin=-24.64
+lonMax=60.28
+# Choices: False, NetCDF
+outputFile=False
+# variableType (reference units): 'precipitation' (mm/day); 'temperature' (K); 'cloudiness' (%), 'radiation' (W/m^2);
+#                                 'evaporation' (mm/day); 'runoff' (mm/day); 'SMC' (fraction)'; 'SWE' (mm); 'heatFlux' (W/m2)
+variableType=precipitation
+
+[MODEL]
+# The model data file(s) to be evaluated is(are) assinged here. Note that the current convention is for easy handling of
+#   multiple model datasets from coordinated experiments such as CORDEX that tend to assign a data file with a name that
+#   follows pre-determined convention (a combination of model name, institution, variable name, experiment name, etc.).
+#   In case only one model is evaluated, a user can specify the full file name for 'filenamePattern'
+#filenamePattern = none           # option currently not working; 2b added for obs-only processing
+filenamePattern=/Volumes/rcmes2t/rcmet/cases/cordex-af/mdlData/mon/*pr.nc
+latVariable=lat
+lonVariable=lon
+timeVariable=time
+varName=pr
+
+[RCMED]
+# obsParamId designates the reference data file. see http://rcmes.jpl.nasa.gov/rcmed/parameters
+# for multiple ref datasets, provide the id separated by ',' (e.g., 36,37 for TRMM and CRU3.1).
+# obsSource specifies the source of the reference data: 0 = RCMED, 1 = user's local disk, -9 = no obs data
+#   For obsSource == 1, obsInputFile, the file that provides the list of users' own reference data
+#                       also a user have to provide obsVarName, obsTimeVar, obsLonVar, and obsLatVar as specified in the data files
+obsSource = 0
+obsInputFile = /nas/share1-hp/jinwonki/data/rean/narr/day_narccap_domain/NARR_prec.nc,/nas/share1-hp/jinwonki/data/obs/cpc/netcdf/cpc_1979_present.nc
+obsVarName = pr,pr
+obsFileName = NARR,CPC
+obsDltaTime = daily,daily
+obsTimeVar = time,time
+obsLonVar = lon,longitude
+obsLatVar = lat,latitude
+# if obsSource = 0, the lines from 'obsSource' to 'obsLatVar' above are inactive
+# 36= TRMM monthly, 37= CRU3.1 monthly, 72= UDEL monthly; 74= GPCP2.2 monthly; 81=GPCC
+obsParamId=37,72,81,36,74
+obsTimeStep=monthly,monthly,monthly,monthly,monthly ; WITH THE PARAMETER SERVICE THIS WILL GO AWAY
+
+[SUB_REGION]
+# Sub Region(s) Full File Path
+subRegionFile=/Volumes/rcmes2t/rcmet/cases/cordex-af/work/inputs/subRgns.AF

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/rcmes/resources/cordexIndia.cfg
----------------------------------------------------------------------
diff --git a/src/main/python/rcmes/resources/cordexIndia.cfg b/src/main/python/rcmes/resources/cordexIndia.cfg
new file mode 100755
index 0000000..d63beaf
--- /dev/null
+++ b/src/main/python/rcmes/resources/cordexIndia.cfg
@@ -0,0 +1,56 @@
+# The configure file for the Indian subdomain of the CORDEX-Asia domain
+[SETTINGS]
+workDir=/Volumes/rcmes2t/rcmet/cases/cordex-sa/work
+cacheDir=/Volumes/rcmes2t/rcmet/cases/cordex-sa/cache
+# temporalGrid assigns the data time step to be temporally regridded: Choices = full (entire period), annual, monthly, daily
+temporalGrid=monthly
+# Choices, obs, model, user
+# gridLonStep, gridLatStep, latMin, latMax, lonMin, lonMax are used only with 'user' spatial grid option
+spatialGrid=user
+gridLonStep=0.5
+gridLatStep=0.5
+latMin=5.
+latMax=40.
+lonMin=60.
+lonMax=100.
+# Choices: False, NetCDF
+outputFile=False
+# variableType (reference units): 'precipitation' (mm/day); 'temperature' (K); 'cloudiness' (%), 'radiation' (W/m^2);
+#                                 'evaporation' (mm/day); 'runoff' (mm/day); 'SMC' (fraction)'; 'SWE' (mm); 'heatFlux' (W/m2)
+variableType=precipitation
+
+[MODEL]
+# The model data file(s) to be evaluated is(are) assinged here. Note that the current convention is for easy handling of
+#   multiple model datasets from coordinated experiments such as CORDEX that tend to assign a data file with a name that
+#   follows pre-determined convention (a combination of model name, institution, variable name, experiment name, etc.).
+#   In case only one model is evaluated, a user can specify the full file name for 'filenamePattern'
+#filenamePattern = none           # option currently not working; 2b added for obs-only processing
+filenamePattern=/Volumes/rcmes2t/rcmet/cases/cordex-sa/mdlData/mon/pr*.nc
+latVariable=lat
+lonVariable=lon
+timeVariable=time
+varName=pr
+
+[RCMED]
+# obsParamId designates the reference data file. see http://rcmes.jpl.nasa.gov/rcmed/parameters
+# for multiple ref datasets, provide the id separated by ',' (e.g., 36,37 for TRMM and CRU3.1).
+# obsSource specifies the source of the reference data: 0 = RCMED, 1 = user's local disk, -9 = no obs data
+#   For obsSource == 1, obsInputFile, the file that provides the list of users' own reference data
+#                       also a user have to provide obsVarName, obsTimeVar, obsLonVar, and obsLatVar as specified in the data files
+obsSource = 0
+obsInputFile = /nas/share1-hp/jinwonki/data/rean/narr/day_narccap_domain/NARR_prec.nc,/nas/share1-hp/jinwonki/data/obs/cpc/netcdf/cpc_1979_present.nc
+obsVarName = pr,pr
+obsFileName = NARR,CPC
+obsDltaTime = daily,daily
+obsTimeVar = time,time
+obsLonVar = lon,longitude
+obsLatVar = lat,latitude
+# if obsSource = 0, the lines from 'obsSource' to 'obsLatVar' above are inactive
+# 36= TRMM monthly, 37= CRU3.1 monthly, 72= UDEL monthly; 74= GPCP2.2 monthly; 80= aphr1101
+obsParamId=37,80,81,36,74
+obsTimeStep=monthly,monthly,monthly,monthly ; WITH THE PARAMETER SERVICE THIS WILL GO AWAY
+
+[SUB_REGION]
+# Sub Region(s) Full File Path
+#subRegionFile=/nas/share3-wf/jinwonki/rcmet/cases/cordex-sa/work/inputs/subRgnsSA.India
+subRegionFile=/Volumes/rcmes2t/rcmet/cases/cordex-sa/work/inputs/subRgnsSA.India

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/rcmes/resources/narccap.cfg
----------------------------------------------------------------------
diff --git a/src/main/python/rcmes/resources/narccap.cfg b/src/main/python/rcmes/resources/narccap.cfg
new file mode 100755
index 0000000..f0f3b50
--- /dev/null
+++ b/src/main/python/rcmes/resources/narccap.cfg
@@ -0,0 +1,55 @@
+[SETTINGS]
+workDir=/Volumes/rcmes2t/rcmet/cases/narccap/work
+cacheDir=/Volumes/rcmes2t/rcmet/cases/narccap/cache
+# temporalGrid assigns the data time step to be temporally regridded: Choices = full (entire period), annual, monthly, daily
+temporalGrid=monthly
+# Choices, obs, model, user
+# gridLonStep, gridLatStep, latMin, latMax, lonMin, lonMax are used only with 'user' spatial grid option
+spatialGrid=user
+gridLonStep=0.5
+gridLatStep=0.5
+latMin=23.75            ; for NARCCAP-ConterminousUS / WUS
+latMax=49.75            ; for NARCCAP-ConterminousUS / WUS
+lonMin=-125.75          ; for NARCCAP-ConterminousUS / WUS
+lonMax=-66.75           ; for NARCCAP-Conterminous US
+#lonMax=-100.75          ; for NARCCAP-WUS.
+# Choices: False, NetCDF
+outputFile=NetCDF
+# variableType (reference units): 'precipitation' (mm/day); 'temperature' (K); 'cloudiness' (%), 'radiation' (W/m^2);
+#                                 'evaporation' (mm/day); 'runoff' (mm/day); 'SMC' (fraction)'; 'SWE' (mm); 'heatFlux' (W/m2)
+variableType=precipitation
+
+[MODEL]
+# The model data file(s) to be evaluated is(are) assinged here. Note that the current convention is for easy handling of
+#   multiple model datasets from coordinated experiments such as CORDEX that tend to assign a data file with a name that
+#   follows pre-determined convention (a combination of model name, institution, variable name, experiment name, etc.).
+#   In case only one model is evaluated, a user can specify the full file name for 'filenamePattern'
+#filenamePattern = none           # option currently not working; 2b added for obs-only processing
+filenamePattern=/Volumes/rcmes2t/rcmet/cases/narccap/mdlData/mon/prec*.nc
+latVariable=lat
+lonVariable=lon
+timeVariable=time
+varName=prec
+#variableType=precipitation
+
+[RCMED]
+# obsParamId designates the reference data file. see http://rcmes.jpl.nasa.gov/rcmed/parameters
+# for multiple ref datasets, provide the id separated by ',' (e.g., 36,37 for TRMM and CRU3.1).
+# obsSource specifies the source of the reference data: 0 = RCMED, 1 = user's local disk, -9 = no obs data
+#   For obsSource == 1, obsInputFile, the file that provides the list of users' own reference data
+obsSource = 0
+obsInputFile = /nas/share1-hp/jinwonki/data/rean/narr/day_narccap_domain/NARR_prec.nc,/nas/share1-hp/jinwonki/data/obs/cpc/netcdf/cpc_1979_present.nc
+obsVarName = pr,pr
+obsFileName = NARR,CPC
+obsDltaTime = daily,daily
+obsTimeVar = time,time
+obsLonVar = lon,longitude
+obsLatVar = lat,latitude
+# if obsSource = 0, the lines from 'obsSource' to 'obsLatVar' above are inactive
+#obsParamId=37,72,81,36,74
+obsParamId=37,36
+obsTimeStep=monthly,monthly,monthly,monthly,monthly ; WITH THE PARAMETER SERVICE THIS WILL GO AWAY
+
+[SUB_REGION]
+# Sub Region(s) Full File Path
+subRegionFile=/Volumes/rcmes2t/rcmet/cases/narccap/work/inputs/subRgnsNARCCAP.US

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/rcmes/services/.svn/all-wcprops
----------------------------------------------------------------------
diff --git a/src/main/python/rcmes/services/.svn/all-wcprops b/src/main/python/rcmes/services/.svn/all-wcprops
new file mode 100755
index 0000000..3cd9eb6
--- /dev/null
+++ b/src/main/python/rcmes/services/.svn/all-wcprops
@@ -0,0 +1,71 @@
+K 25
+svn:wc:ra_dav:version-url
+V 88
+/repos/asf/!svn/ver/1482547/incubator/climate/trunk/rcmet/src/main/python/rcmes/services
+END
+run_rcmes_processing.py
+K 25
+svn:wc:ra_dav:version-url
+V 112
+/repos/asf/!svn/ver/1480068/incubator/climate/trunk/rcmet/src/main/python/rcmes/services/run_rcmes_processing.py
+END
+list_vars_in_file.py
+K 25
+svn:wc:ra_dav:version-url
+V 109
+/repos/asf/!svn/ver/1480068/incubator/climate/trunk/rcmet/src/main/python/rcmes/services/list_vars_in_file.py
+END
+main_ws.py
+K 25
+svn:wc:ra_dav:version-url
+V 99
+/repos/asf/!svn/ver/1480068/incubator/climate/trunk/rcmet/src/main/python/rcmes/services/main_ws.py
+END
+__init__.py
+K 25
+svn:wc:ra_dav:version-url
+V 100
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/python/rcmes/services/__init__.py
+END
+bottlemet.py
+K 25
+svn:wc:ra_dav:version-url
+V 101
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/python/rcmes/services/bottlemet.py
+END
+find_latlon_var.py
+K 25
+svn:wc:ra_dav:version-url
+V 107
+/repos/asf/!svn/ver/1480068/incubator/climate/trunk/rcmet/src/main/python/rcmes/services/find_latlon_var.py
+END
+README.txt
+K 25
+svn:wc:ra_dav:version-url
+V 99
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/python/rcmes/services/README.txt
+END
+decode_model_times.py
+K 25
+svn:wc:ra_dav:version-url
+V 110
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/python/rcmes/services/decode_model_times.py
+END
+directory_helpers.py
+K 25
+svn:wc:ra_dav:version-url
+V 109
+/repos/asf/!svn/ver/1482547/incubator/climate/trunk/rcmet/src/main/python/rcmes/services/directory_helpers.py
+END
+find_time_var.py
+K 25
+svn:wc:ra_dav:version-url
+V 105
+/repos/asf/!svn/ver/1480068/incubator/climate/trunk/rcmet/src/main/python/rcmes/services/find_time_var.py
+END
+dataset_helpers.py
+K 25
+svn:wc:ra_dav:version-url
+V 107
+/repos/asf/!svn/ver/1480068/incubator/climate/trunk/rcmet/src/main/python/rcmes/services/dataset_helpers.py
+END

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/rcmes/services/.svn/entries
----------------------------------------------------------------------
diff --git a/src/main/python/rcmes/services/.svn/entries b/src/main/python/rcmes/services/.svn/entries
new file mode 100755
index 0000000..b34041c
--- /dev/null
+++ b/src/main/python/rcmes/services/.svn/entries
@@ -0,0 +1,402 @@
+10
+
+dir
+1485921
+https://svn.apache.org/repos/asf/incubator/climate/trunk/rcmet/src/main/python/rcmes/services
+https://svn.apache.org/repos/asf
+
+
+
+2013-05-14T20:07:57.184268Z
+1482547
+joyce
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+13f79535-47bb-0310-9956-ffa450edef68
+
+run_rcmes_processing.py
+file
+
+
+
+
+2013-05-24T10:13:49.000000Z
+b72b173d9a8423c2ecc3ff915009717f
+2013-05-07T20:50:17.582309Z
+1480068
+joyce
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+4914
+
+list_vars_in_file.py
+file
+
+
+
+
+2013-05-24T10:13:49.000000Z
+2a2cd6269710cf6136c3b026713a63fb
+2013-05-07T20:50:17.582309Z
+1480068
+joyce
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+1548
+
+main_ws.py
+file
+
+
+
+
+2013-05-24T10:13:49.000000Z
+f6aaf93ae28329a6a6c75d074ce69bf5
+2013-05-07T20:50:17.582309Z
+1480068
+joyce
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+889
+
+__init__.py
+file
+
+
+
+
+2013-05-24T10:13:49.000000Z
+5c7b875cde03a6b682cc84a7858fd5dc
+2012-08-16T14:19:38.500472Z
+1473885
+cgoodale
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+132
+
+bottlemet.py
+file
+
+
+
+
+2013-05-24T10:13:49.000000Z
+6f5737a819d82d8c0cd574d6195acdbf
+2013-02-20T17:07:53.256865Z
+1474978
+cgoodale
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+21280
+
+find_latlon_var.py
+file
+
+
+
+
+2013-05-24T10:13:49.000000Z
+aa30bfb54cacbfb99ac263ae42ab32da
+2013-05-07T20:50:17.582309Z
+1480068
+joyce
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+4154
+
+README.txt
+file
+
+
+
+
+2013-05-24T10:13:49.000000Z
+dcf5694caba89c7989ff1e86fd9ea14b
+2012-08-14T20:33:03.986567Z
+1473860
+pramirez
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+1854
+
+decode_model_times.py
+file
+
+
+
+
+2013-05-24T10:13:49.000000Z
+52b776bfd8845a4830659cb09779af9b
+2013-03-05T16:19:20.432667Z
+1475039
+mjjoyce
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+4817
+
+directory_helpers.py
+file
+
+
+
+
+2013-05-24T10:13:49.000000Z
+22a41a483c4a806e3ef7dd8c17364e2e
+2013-05-14T20:07:57.184268Z
+1482547
+joyce
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+1260
+
+find_time_var.py
+file
+
+
+
+
+2013-05-24T10:13:49.000000Z
+addf1ca2427854ece4e5cbdaf1920e3b
+2013-05-07T20:50:17.582309Z
+1480068
+joyce
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+2882
+
+dataset_helpers.py
+file
+
+
+
+
+2013-05-24T10:13:49.000000Z
+69f9dd2f04b3b8e171e9b5593c076203
+2013-05-07T20:50:17.582309Z
+1480068
+joyce
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+834
+

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/rcmes/services/.svn/prop-base/__init__.py.svn-base
----------------------------------------------------------------------
diff --git a/src/main/python/rcmes/services/.svn/prop-base/__init__.py.svn-base b/src/main/python/rcmes/services/.svn/prop-base/__init__.py.svn-base
new file mode 100755
index 0000000..614166f
--- /dev/null
+++ b/src/main/python/rcmes/services/.svn/prop-base/__init__.py.svn-base
@@ -0,0 +1,5 @@
+K 12
+svn:keywords
+V 11
+Id Revision
+END

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/rcmes/services/.svn/prop-base/decode_model_times.py.svn-base
----------------------------------------------------------------------
diff --git a/src/main/python/rcmes/services/.svn/prop-base/decode_model_times.py.svn-base b/src/main/python/rcmes/services/.svn/prop-base/decode_model_times.py.svn-base
new file mode 100755
index 0000000..869ac71
--- /dev/null
+++ b/src/main/python/rcmes/services/.svn/prop-base/decode_model_times.py.svn-base
@@ -0,0 +1,5 @@
+K 14
+svn:executable
+V 1
+*
+END

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/rcmes/services/.svn/prop-base/find_latlon_var.py.svn-base
----------------------------------------------------------------------
diff --git a/src/main/python/rcmes/services/.svn/prop-base/find_latlon_var.py.svn-base b/src/main/python/rcmes/services/.svn/prop-base/find_latlon_var.py.svn-base
new file mode 100755
index 0000000..869ac71
--- /dev/null
+++ b/src/main/python/rcmes/services/.svn/prop-base/find_latlon_var.py.svn-base
@@ -0,0 +1,5 @@
+K 14
+svn:executable
+V 1
+*
+END

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/rcmes/services/.svn/prop-base/find_time_var.py.svn-base
----------------------------------------------------------------------
diff --git a/src/main/python/rcmes/services/.svn/prop-base/find_time_var.py.svn-base b/src/main/python/rcmes/services/.svn/prop-base/find_time_var.py.svn-base
new file mode 100755
index 0000000..869ac71
--- /dev/null
+++ b/src/main/python/rcmes/services/.svn/prop-base/find_time_var.py.svn-base
@@ -0,0 +1,5 @@
+K 14
+svn:executable
+V 1
+*
+END

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/rcmes/services/.svn/prop-base/list_vars_in_file.py.svn-base
----------------------------------------------------------------------
diff --git a/src/main/python/rcmes/services/.svn/prop-base/list_vars_in_file.py.svn-base b/src/main/python/rcmes/services/.svn/prop-base/list_vars_in_file.py.svn-base
new file mode 100755
index 0000000..869ac71
--- /dev/null
+++ b/src/main/python/rcmes/services/.svn/prop-base/list_vars_in_file.py.svn-base
@@ -0,0 +1,5 @@
+K 14
+svn:executable
+V 1
+*
+END

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/rcmes/services/.svn/text-base/README.txt.svn-base
----------------------------------------------------------------------
diff --git a/src/main/python/rcmes/services/.svn/text-base/README.txt.svn-base b/src/main/python/rcmes/services/.svn/text-base/README.txt.svn-base
new file mode 100755
index 0000000..27622ab
--- /dev/null
+++ b/src/main/python/rcmes/services/.svn/text-base/README.txt.svn-base
@@ -0,0 +1,68 @@
+RCMET Client API Web Service README
+===========================================================
+
+Prerequisites:
+
+ * Python 2.6+ with easy_install
+ * Bottle (http://bottlepy.org) Web Framework 
+
+Usage:
+
+ ./python main_ws.py
+
+
+Hints:
+
+  Changing the port Bottle runs on
+  --------------------------------
+  The port Bottle starts up on can be changed by editing
+  the last line in the ./main_ws.py file as follows:
+
+  if __name__ == "__main__":
+    run(host='localhost', port=*NEWPORT*)
+
+
+API Documentation:
+=================================================================
+
+Extract Model File Variables
+--------------------------------
+http://<webserviceUrl>/list/vars/"<PATH>"
+
+  INPUTS: 
+    PATH: the fully qualified path to the model file to use. Note 
+          that the path must be enclosed in double quotes.
+
+  RETURN:
+    SUCCESS: {"variables": ["tas", "level", "lon", "time", "lat"]}
+    FAILURE: []   <-- should probably be {}
+
+
+Extract Model Latitude and Longitude Variables and Bounds
+---------------------------------------------------------
+http://<webserviceUrl>/list/latlon/"<PATH>"
+
+  INPUTS: 
+    PATH: the fully qualified path to the model file to use. Note 
+    	  that the path must be enclosed in double quotes.
+
+  RETURN:
+    SUCCESS: {"latMax": "42.24", "success": 1, "latname": "lat", 
+              "lonMax": "60.28", "lonMin": "-24.64", 
+	      "lonname": "lon", "latMin": "-45.76"}
+    FAILURE: ?
+
+
+Extract Model Time Variable and Bounds
+--------------------------------------
+http://<webserviceUrl>/list/time/"<PATH>"
+
+  INPUTS: 
+    PATH: the fully qualified path to the model file to use. Note 
+          that the path must be enclosed in double quotes.
+
+  RETURN:
+    SUCCESS:  {"start_time": "1989-01-15 00:00:00", 
+    	       "timename": "time", "success": 1, 
+	       "end_time": "2008-12-15 00:00:00"}
+    FAILURE: ?

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/rcmes/services/.svn/text-base/__init__.py.svn-base
----------------------------------------------------------------------
diff --git a/src/main/python/rcmes/services/.svn/text-base/__init__.py.svn-base b/src/main/python/rcmes/services/.svn/text-base/__init__.py.svn-base
new file mode 100755
index 0000000..9a00597
--- /dev/null
+++ b/src/main/python/rcmes/services/.svn/text-base/__init__.py.svn-base
@@ -0,0 +1,2 @@
+"""The Services Package is a collection of RESTful Web Service modules that can
+be used to create custom User Interfaces to RCMES"""
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/rcmes/services/.svn/text-base/bottlemet.py.svn-base
----------------------------------------------------------------------
diff --git a/src/main/python/rcmes/services/.svn/text-base/bottlemet.py.svn-base b/src/main/python/rcmes/services/.svn/text-base/bottlemet.py.svn-base
new file mode 100755
index 0000000..0bcefb8
--- /dev/null
+++ b/src/main/python/rcmes/services/.svn/text-base/bottlemet.py.svn-base
@@ -0,0 +1,599 @@
+'''
+ Module to create a web service for RCMET statistical metrics
+'''
+
+
+
+
+##########################################################################################
+#setting up bottle and importing metrics
+##########################################################################################
+
+#sets up bottle and necessary methods.
+from bottle import route, run, post, request, redirect, debug 
+
+#temporary quick-fix to track errors, not for publication 
+debug(True)
+
+#imports pickle
+import pickle
+
+#imports metrics from RCMET
+import rcmes.metrics as mtx
+
+
+
+
+##########################################################################################
+#error-catching dictionaries 
+##########################################################################################
+
+#dictionary of MetricNames and their number of variables. Useful later on
+HowManyVariables={
+	"calc_stdev" :1,
+	"calc_annual_cycle_means" : 2,
+	"calc_annual_cycle_std" : 2,
+	"calc_annual_cycle_domain_means" : 2,
+	"calc_annual_cycle_domain_std" : 2,
+	"calc_bias" : 2,
+	"calc_bias_dom" : 2,
+	"calc_difference" : 2,
+	"calc_mae" : 2,
+	"calc_mae_dom" :2,
+	"calc_rms" : 2,
+	"calc_rms_dom" : 2,
+	"calc_temporal_pat_cor" : 2,
+	"calc_pat_cor" : 2,
+	"calc_nash_sutcliff" : 2,
+	"calc_pdf" : 2,
+	"calc_anom_corn" : 3
+}		
+	
+#dictionary of metric names and the names of their variables.
+NameOfVariables={
+	"calc_stdev":['t1'],
+	"calc_annual_cycle_means" :['data','time'],
+	"calc_annual_cycle_std" :['data','time'],
+	"calc_annual_cycle_domain_means" :['data','time'],
+	"calc_annual_cycle_domain_std" :['data','time'],
+	"calc_bias" :['t1','t2'],
+	"calc_bias_dom" :['t1','t2'],
+	"calc_difference" :['t1','t2'], 
+	"calc_mae" :['t1','t2'],
+	"calc_mae_dom" : ['t1','t2'],
+	"calc_rms" :['t1','t2'],
+	"calc_rms_dom" :['t1','t2'],
+	"calc_temporal_pat_cor" :['t1','t2'],
+	"calc_pat_cor" :['t1','t2'],
+	"calc_nash_sutcliff" :['t1','t2'],
+	"calc_pdf" :['t1','t2'],
+	"calc_anom_corn" :['t1','t2','t4']
+}				
+
+#two lists that will help with user explanation later
+
+ArrayNames=[]	   
+
+ListOfArrays=[]
+	
+	
+	
+##########################################################################################
+
+#Running the metrics through interactive web pages
+
+##########################################################################################
+
+
+
+##########################################################################################
+#First parts: introduction and identification of user's needs
+##########################################################################################
+
+#basic first page. Explanation could be more comprehensive
+@route('/rcmet/metrics/online')	
+def ShowPossibleMetrics():
+	'''
+	Returns a page in html that allows the user to select a metric through links
+	'''
+	return '''<html>
+		<head> RCMET Metrics through Bottle </head>
+		<body>
+		<p>Please select the metric you will use.</p>
+		
+		<p> Metrics with one variable: 
+		<a href='/rcmet/metrics/online/calc_stdev'>"calc_stdev" to return standard deviation</a>
+		</p>
+	
+		<p> Metrics with two variables: 
+		<a href='/rcmet/metrics/online/calc_annual_cycle_means'>"calc_annual_cycle_means" to return monthly means</a>
+		<a href='/rcmet/metrics/online/calc_annual_cycle_std'>""calc_annual_cycle_std" to return monthly standard deviation</a>  
+		<a href='/rcmet/metrics/online/calc_annual_cycle_domain_means'>"calc_annual_cycle_domain_ means" to return monthly 
+		domain means</a>   
+		<a href='/rcmet/metrics/online/calc_annual_cycle_domain_std'>"calc_annual_cycle_domain_std" to return monthly standard 
+		deviation</a>	
+		<a href='/rcmet/metrics/online/calc_bias'>"calc_bias" to return mean difference</a>	
+		<a href='/rcmet/metrics/online/calc_bias_dom'>"calc_bias_dom" to return domain mean difference</a>	 
+		<a href='/rcmet/metrics/online/calc_difference'>"calc_difference" to return difference</a>
+		<a href='/rcmet/metrics/online/calc_mae'>"calc_mae" to return mean absolute error</a>	
+		<a href='/rcmet/metrics/online/calc_mae_dom'>"calc_mae_dom" to return domain mean difference over time</a>
+		<a href='/rcmet/metrics/online/calc_rms'>"calc_rms" to return root mean square error
+		</a>	
+		<a href='/rcmet/metrics/online/calc_rms_dom'>"calc_rms_dom" to return domain root mean square error</a>	
+		<a href='/rcmet/metrics/online/calc_temporal_pat_cor'>"calc_temporal_pat_cor" to return temporal pattern correlation</a>
+		<a href='/rcmet/metrics/online/calc_pat_cor'>"calc_pat_cor" to return pattern correlation</a>
+		<a href='/rcmet/metrics/online/calc_nash_sutcliff'>"calc_nash_sutcliff" to return Nash-Sutcliff coefficient of 
+		efficiency</a>
+		<a href='/rcmet/metrics/online/calc_pdf'>"calc_pdf" to return probability distribution function</a>
+		
+		<p> Metrics with three variables:
+		<a href='/rcmet/metrics/online/calc_anom_corn'>"calc_anom_corn" to return anomaly correlation</a> </p>
+		</body>
+		<html>'''
+
+#creates introductory page to explain how to use bottle
+@route('/rcmet/metrics/online/<MetricNameHere>')
+def VariableSubmission(MetricNameHere):
+	'''
+	Returns a page in html that allows the user to choose between submitting variables on the command line or searching 
+	RCMED
+	'''	  
+	
+	global MetricName
+	
+	MetricName=MetricNameHere
+	
+	if MetricName in HowManyVariables:
+		return "For metric %s , you need %d variable(s), which will represent: %s" %(MetricName, 
+			HowManyVariables[MetricName], NameOfVariables[MetricName][:]), '''<html>
+			<body>
+			<p>Will you enter variables (which are arrays) through the command line or 
+			will you search the RCMES Database?</p>
+			<a href="/rcmet/metrics/online/commandline">command line</a>
+			<a href="/rcmet/metrics/online/rcmed">RCMED</a>
+			</body>
+			</html>''',
+			'''<a href='/rcmet/metrics/online/methods'>Run Methods</a>'''
+	
+	else:
+		return "The metric you entered doesn't exist."
+
+
+##########################################################################################
+#getting arrays through the command line
+##########################################################################################
+
+#Tells the user how to send variables from the command line
+@route('/rcmet/metrics/online/commandline')
+def ArraysFromCommandLine():
+	'''
+	Explains to the user how to submit a variable through POST on the command line
+	'''
+	if HowManyVariables[MetricName]-count<=0:
+		print "You have already submitted all the needed variables for this metric."
+		redirect('/rcmet/metrics/online/calculate')
+	else:
+		return "Please use your command line to POST a form with the array. Send either a pickled file or serialized ",
+		"string. Name the form: array. Include also, a form that describes/names the array. Call this form: name. A ",
+		"sample would be array=array_here and name=array_name_here. Send the form to: ",
+		"http://.../rcmet/metrics/<metric_name>/commandline. Once the computer receives all variables, you may ", 
+		"move on to the metrics portion of the website. Currently, you have submitted %d variable(s) and need %d ",
+		"more. The next variable you submit will represent the variable %s in %s" %(count, 
+		(HowManyVariables[MetricName]-count),NameOfVariables[MetricName][count], MetricName)
+	
+#this function	gets the array from the command line
+@route('/rcmet/metrics/online/commandline', method='POST') 
+def ReceivingArrays():
+	'''
+	Uses the POST method to retrieve any arrays sent by the user, and proceed to deserialize them. Also adds each
+	variable to the appropriate list, and proceeds to offer the user the option to add more variables or else move
+	on to calculating the value of the metric;
+	'''
+		
+	try:
+		BottleMetrics.GetVariablesFromCommandLine()
+			
+		return "Variable received as %s. Will represent %s" % (ArrayNames[count-1], 
+		NameOfVariables[MetricName][count-1]), "Submit more variables?",
+		'''<a href='/rcmet/metrics/online/rcmed'>Online</a>''',
+		'''<a href='/rcmet/metrics/online/commandline'>Command Line</a>''',
+		'''<a href='/rcmet/metrics/online/calculate'>No More Variables</a>''',
+		'''<a href='/rcmet/metrics/online/methods'>Run Methods</a>'''
+	
+	except pickle.UnpicklingError:
+		return "This object cannot be unpickled. Send only a file or serialized string.",
+		'''<a href='/rcmet/metrics/online/commandline'>Re-submit Variable</a>''',
+		'''<a href='/rcmet/metrics/online/methods'>Run Methods</a>'''
+		
+
+##########################################################################################
+#getting variables through RCMED
+##########################################################################################
+
+#explains how to enter information into a dynamic link
+@route('/rcmet/metrics/online/rcmed')
+def QueryRcmed():
+	'''
+	Returns a page in html that explains to the user how to search RCMED for the desired arrays, and offers the
+	user multiple forms in which to enter search parameters
+	'''
+	
+	#I was unclear what type the dataset ID and paramID were supposed to be. This may need to change
+	
+	return "Currently, you have submitted %d variable(s) and need %d more. The next"\
+	" variable you submit will represent the variable %s in %s" %(count, 
+	(HowManyVariables[MetricName]-count),NameOfVariables[MetricName][count], MetricName),'''<html>
+	<head> Query RCMED for Array Data </head>
+	<body>
+	<p>Enter the parameters into the appropriate boxes.</p>
+	<form method="POST">
+		<p>Dataset ID</p>
+		<input name="datasetID"	 type="string" />
+		<p>Parameter ID</p>
+		<input name="paramID"	 type="string" />
+		<p>latMin, float</p>
+		<input name="latMin"	 type="float" />
+		<p>latMax, float</p>
+		<input name="latMax"	 type="float" />
+		<p>lonMin, float</p>
+		<input name="lonMin"	 type="float" />
+		<p>lonMax, float</p>
+		<input name="lonMax"	 type="float" />
+		<p>startTime, datetime object</p>
+		<input name="startTime"	 type="datetime" />
+		<p>endTime, datetime object</p>
+		<input name="endTime"	 type="datetime" />
+		<p>cachedir, string</p>
+		<input name="cachedir"	 type="string" />
+		<p>Array Name, string</p>
+		<input name="ArrayName"	 type="string" />
+		<input type="Submit" /> </form>
+	</body>
+	</html>''' 
+	
+	
+@route('/rcmet/metrics/online/rcmed', method='POST')
+def GetVariablesFromDatabase():
+	'''
+	Gets data from forms, searches the database, processes the variables, and prompts the user to submit more.
+	'''
+	BottleMetrics.GetVariablesFromRcmed()	 
+
+
+	return "Submit more variables?",'''<a href='/rcmet/metrics/online/rcmed'>Online</a>''',
+	'''<a href='/rcmet/metrics/online/commandline'>Command Line</a>''',
+	'''<a href='/rcmet/metrics/online/calculate'>No More Variables</a>''',
+	'''<a href='/rcmet/metrics/online/methods'>Run Methods</a>'''
+
+
+##########################################################################################
+#running the metrics online
+##########################################################################################
+
+#this function actually runs the metrics
+@route('/rcmet/metrics/online/calculate')
+def Calculate(MetricName):
+	'''
+	Uses variables from the lists to return the answer for the metric. Also returns a brief description of the metric performed. 
+	'''
+		
+	if HowManyVariables[MetricName]<count:
+		return "You have too few variables to run this metric.",'''<a href='/rcmet/metrics/online/commandline'>Command Line</a>,
+		<a href='/rcmet/metrics/online/rcmed'>Online</a>''','''<a href='/rcmet/metrics/online/methods'>Run Methods</a>'''
+	
+	else:
+		return BottleMetrics.ExplainMetric(), str(result), '''<a href='/rcmet/metrics/online/methods'>Run Methods</a>''',
+		'''<a href='/rcmet/metrics/online'>Start Over</a>'''
+			
+	
+	'''<a href='/rcmet/metrics/online/methods'>Run Methods</a>'''
+	
+@route('/rcmet/metrics/online/methods')
+def ChooseMethodOnline():
+	'''
+	Allows an online user to access any method in the class
+	'''
+	
+	return "Which method?", '''<html>
+	<a href='/rcmet/metrics/online/methods/Status'>Status</a>
+	<a href='/rcmet/metrics/online/methods/ExplainMetric'>ExplainMetric</a>
+	<a href='/rcmet/metrics/online/methods/VariableCount'>VariableCount</a>
+	<a href='/rcmet/metrics/online/methods/ReturnResult'>ReturnResult</a>
+	<a href='/rcmet/metrics/online/methods/CleanUp'>CleanUp</a>'''
+	
+@route('/rcmet/metrics/online/methods/<MethodName>)
+def RunMethodOnline(MethodName):
+	'''
+	Runs any method in class MetricWebService() chosen by an online user
+	'''
+		
+	MetricWebServiceMethod=getattr(BottleMetrics, MethodName)
+	
+	return BottleMetrics.MetricWebServiceMethod(), '''<a href='/rcmet/metrics/online'>Back to Beginning</a>'''
+	
+
+##########################################################################################	
+##########################################################################################
+
+#creating a class for the Web Service 
+
+##########################################################################################
+##########################################################################################
+
+class MetricWebService(object):
+	'''
+	Class containing all of the necessary functions to find, process, and use the variables to run metrics. Also allows
+	the user to see the state of the metric, i.e. how many variables have been entered. 
+	'''
+		
+	def __init__(self):
+
+		global count
+		count=0
+
+##########################################################################################
+
+	def Status(self):
+		'''
+		Provides a standardized system for showing how many variables are submitted, allowing the user to 
+		check their progress 
+		'''
+		print "For metric %s , you need %d variable(s): %s. Currently, you have submitted "\
+		"%d variable(s) and need %d more. The values you have submitted, %s, will represent %s respectively." 
+		%(MetricName, HowManyVariables[MetricName], NameOfVariables[MetricName][:], count, 
+		(HowManyVariables[MetricName]-count),ArrayNames[:],NameOfVariables[MetricName][:])
+		
+		return "For metric %s , you need %d variable(s): %s. Currently, you have submitted "\
+		"%d variable(s) and need %d more. The values you have submitted, %s, will represent %s respectively." 
+		%(MetricName, HowManyVariables[MetricName], NameOfVariables[MetricName][:], count, 
+		(HowManyVariables[MetricName]-count),ArrayNames[:],NameOfVariables[MetricName][:])
+		
+##########################################################################################
+
+	def ExplainMetric(self):
+		'''
+		Provides a standardized means of returning a metric's docstring and thus describing the metric
+		'''
+		method=getattr(mt, MetricName)
+
+		print method.__doc__
+
+		return method.__doc__
+##########################################################################################
+
+	def VariableCount(self):
+		'''
+		Determines how many variables have been submitted, and if the right number has, this function runs the RunMetrics() method
+		'''
+			
+		if HowManyVariables[MetricName]-count>0:
+		
+			print "Please add more variables"
+			
+			return "Please add more variables"
+					
+		if HowManyVariables[MetricName]-count<0:
+			print "You have added too many variables"
+			
+			return "Please add more variabels"
+			
+		else:
+			print "You have added all necessary metrics. The program will now run your metric."
+			
+			self.RunMetrics()
+			
+
+##########################################################################################
+	
+	def ProcessVariables(self, array, ArrayName):	
+		'''
+		adds the variables posted by the user to the appropriate lists, raises count to indicate this addition, and
+		starts VariableCount()
+		'''			
+		ListOfArrays.append(array)
+		ArrayNames.append(ArrayName)
+			
+		global count
+		count=count+1
+			
+		print "Variable received as %s. Will represent %s" % (ArrayName, 
+		NameOfVariables[MetricName][count-1])
+			
+		self.VariableCount()
+		
+##########################################################################################
+
+	def GetVariablesFromCommandLine(self):	
+		'''
+		Gets array and array name from forms, deserializes them with unpickle, and runs ProcessVariables()
+		'''	
+		
+		if HowManyVariables[MetricName]-count>0:
+			array=request.forms.get('array')
+			ArrayName=request.forms.get('name')
+			
+			if type(array)==str:
+				array=pickle.loads(array)	   
+			
+			else:
+				array=pickle.load(array)
+		
+			self.ProcessVariables(array, ArrayName)
+		
+		else:
+			self.VariableCount()
+	
+##########################################################################################
+	
+	def GetVariablesFromRcmed(self):	
+		'''
+		Gets search parameters from forms, runs a search of RCMED, and returns the array mdata
+		'''
+		
+		if HowManyVariables[MetricName]-count>0:
+		
+			import rcmes.db as db
+	
+			datasetID=request.forms.get('datasetID')
+			paramID=request.forms.get('paramID')
+			latMin=request.forms.get('latMin')
+			latMax=request.forms.get('latMax')
+			lonMin=request.forms.get('lonMin')
+			lonMax=request.forms.get('lonMax')
+			startTime=request.forms.get('startTime')
+			endTime=request.forms.get('endTime')
+			cachedir=request.forms.get('cachedir')
+	
+			ArrayName=request.forms.get('name')				
+					
+			try:
+			
+				db.extract_data_from_db(datasetID, paramID, latMin, latMax, lonMin, lonMax, startTime, endTime, cachedir)
+				
+				#I don't think this will work
+				array=mdata
+				
+				self.ProcessVariables(array,ArrayName)
+										
+			except TypeError:
+				print "One of your variables was not entered in the correct format or was not entered at all"
+			
+		else:
+			self.VariableCount()	
+			
+##########################################################################################
+	
+	def GetVariables(self):
+		'''
+		Runs two links that connect with functions meant to handle the variables posted to the links
+		'''
+####################
+		
+		@route('/rcmet/metrics/get/variables/commandline', method='POST') 
+		def VariablesPostedToCommandline():
+			'''
+			runs the method GetVariablesFromCommandLine() at the URL, allowing the user to post their forms to this url and have
+			them handled by GetVariablesFromCommandLine().
+			'''
+			
+			try:
+				self.GetVariablesFromCommandLine()
+					
+			except pickle.UnpicklingError:
+				print "This object cannot be unpickled. Send only a file or serialized string."
+	
+
+####################
+
+		@route('/rcmet/metrics/get/variables/rcmed', method='POST')
+		def GetVariablesFromRCMED(self):
+			'''
+			runs the method GetVariablesFromRcmed() at the URL, allowing the user to post their forms to this url and have
+			them handled by GetVariablesFromRcmed().
+			'''
+			
+			self.GetVariablesFromRcmed()	 
+				
+##########################################################################################
+				
+	def RunMetrics(self):
+		'''
+		Calls to metrics.py and runs the desired metric using variables submitted by the user. Returns a string of the 
+		value returned by the metric
+		'''
+		
+		print "Running metric"	
+		  
+		method=getattr(mtx, MetricName)
+	
+		global result
+	
+		if HowManyVariables[MetricName]==1:
+			result=method(ListOfArrays[0])
+			
+		if HowManyVariables[MetricName]==2:
+			result=method(ListOfArrays[0], ListOfArrays[1])
+				
+		if HowManyVariables[MetricName]==3:
+			result=method(ListOfArrays[0], ListOfArrays[1], ListOfArrays[2])
+		
+##########################################################################################
+		
+	@route('/rcmet/metrics/commandline/return/result')
+	def ReturnResult():
+		'''
+		links the result to a uri from which the user can easily fetch it. Note, the result is returned as a string
+		'''	
+	#If the result of the metrics is an array, I would recommend including a provision in 
+	#ReturnResult() that pickles or somehow serializes the result, and then, upon getting 
+	#the pickled string from the URL, the user could unpickle it and use it as an array. 	
+	
+		return str(result)
+		
+##########################################################################################
+
+	def CleanUp(self, name):
+		'''
+		resets the lists, the count, and the variable MetricName back to zero, enabling a user to in effect start over, without
+		re-creating the instance of the class. 
+		'''
+		
+		global ArrayNames
+		ArrayNames=[]
+		
+		global ListOfArrays
+		ListOfArrays=[]
+		
+		global count
+		count=0	
+		
+		global MetricName
+		name=MetricName
+
+##########################################################################################
+#final commands to tie everything together 
+##########################################################################################
+
+#allows the command line user to remotely create an instance of the class
+@route('/rcmet/metrics/commandline', method='POST')
+def CreateAnInstance():
+	'''
+	Sets up a POST page that creates an instance of the class for a user on the command line. The user does not need
+	to open this page for it to function; they need only post the name of the metric they want. 
+	'''
+	
+	NameOfMetric=request.forms.get('NameOfMetric')
+	
+	global MetricName
+	
+	MetricName=NameOfMetric
+
+	if name in HowManyVariables:
+		BottleMetrics.GetVariables()
+	
+	else:
+		print "The metric you entered, %s, does not exist" %name	
+
+
+
+@route('/rcmet/metrics/commandline/methods', method='POST')
+def RunAMethod():
+	'''
+	Allows a command line user to access any method in class MetricWebService() by sending a form
+	'''
+	MethodName=request.forms.get('MethodName')
+	
+	MetricWebServiceMethod=getattr(BottleMetrics, MethodName)
+	
+	BottleMetrics.MetricWebServiceMethod()
+	 
+
+BottleMetrics=MetricWebService()
+
+#final function starts up bottle at http://localhost:8080
+#note: localhost:8080 may need to be changed eventually 
+run(host='localhost', port=8080)
+
+
+
+

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/rcmes/services/.svn/text-base/dataset_helpers.py.svn-base
----------------------------------------------------------------------
diff --git a/src/main/python/rcmes/services/.svn/text-base/dataset_helpers.py.svn-base b/src/main/python/rcmes/services/.svn/text-base/dataset_helpers.py.svn-base
new file mode 100755
index 0000000..2031caf
--- /dev/null
+++ b/src/main/python/rcmes/services/.svn/text-base/dataset_helpers.py.svn-base
@@ -0,0 +1,32 @@
+#!/usr/bin/env python
+"""
+    Provides Bottle services for interacting with RCMED
+"""
+
+from bottle import request, route
+
+import requests
+import Nio
+
+@route('/getObsDatasets')
+def getObservationDatasetData():
+    r = requests.get('http://rcmes.jpl.nasa.gov/query-api/datasets.php')
+
+    # Handle JSONP requests
+    if (request.query.callback):
+        return "%s(%s)" % (request.query.callback, r.text)
+    # Otherwise, just return JSON
+    else:
+        return r.text
+
+@route('/getDatasetParam')
+def getDatasetParameters():
+    url = 'http://rcmes.jpl.nasa.gov/query-api/parameters.php?dataset=' + request.query.dataset
+    r = requests.get(url)
+
+    # Handle JSONP requests
+    if (request.query.callback):
+        return "%s(%s)" % (request.query.callback, r.text)
+    # Otherwise, just return JSON
+    else:
+        return r.text

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/rcmes/services/.svn/text-base/decode_model_times.py.svn-base
----------------------------------------------------------------------
diff --git a/src/main/python/rcmes/services/.svn/text-base/decode_model_times.py.svn-base b/src/main/python/rcmes/services/.svn/text-base/decode_model_times.py.svn-base
new file mode 100755
index 0000000..ae7974d
--- /dev/null
+++ b/src/main/python/rcmes/services/.svn/text-base/decode_model_times.py.svn-base
@@ -0,0 +1,185 @@
+#!/usr/local/bin/python
+"""Module to simplify handling of model times """
+def decodeTimeFromString(time_string):
+    '''
+    # Decodes string into a python datetime object
+    # Method: tries a bunch of different time format possibilities and hopefully one of them will hit.
+    # 
+    #   Input:  time_string - a string that represents a date/time
+    #   Output: mytime - a python datetime object
+    #
+    #   Peter Lean   February 2011
+    '''
+    import time
+    import datetime
+
+    try:
+        mytime = time.strptime(time_string, '%Y-%m-%d %H:%M:%S')
+        mytime = datetime.datetime(*mytime[0:6])
+        return mytime
+
+    except ValueError:
+        pass
+
+    try:
+        mytime = time.strptime(time_string, '%Y/%m/%d %H:%M:%S')
+        mytime = datetime.datetime(*mytime[0:6])
+        return mytime
+
+    except ValueError:
+        pass
+
+    try:
+        mytime = time.strptime(time_string, '%Y%m%d %H:%M:%S')
+        mytime = datetime.datetime(*mytime[0:6])
+        return mytime
+
+    except ValueError:
+        pass
+
+    try:
+        mytime = time.strptime(time_string, '%Y:%m:%d %H:%M:%S')
+        mytime = datetime.datetime(*mytime[0:6])
+        return mytime
+
+    except ValueError:
+        pass
+
+    try:
+        mytime = time.strptime(time_string, '%Y%m%d%H%M%S')
+        mytime = datetime.datetime(*mytime[0:6])
+        return mytime
+
+    except ValueError:
+        pass
+
+    try:
+        mytime = time.strptime(time_string, '%Y-%m-%d %H:%M')
+        mytime = datetime.datetime(*mytime[0:6])
+        return mytime
+
+    except ValueError:
+        pass
+
+
+    print 'Error decoding time string: string does not match a predefined time format'
+    return 0
+
+
+
+def decode_model_times(filelist,timeVarName):
+   '''
+   #  Routine to convert from model times ('hours since 1900...', 'days since ...') 
+   #  into a python datetime structure
+   #
+   #  Input:
+   #      filelist - list of model files
+   #      timeVarName - name of the time variable in the model files
+   #
+   #  Output:
+   #      times  - list of python datetime objects describing model data times
+   #
+   #
+   #     Peter Lean February 2011
+   #
+   '''
+   import datetime
+   import re
+   import string
+   import math
+   import numpy
+   import Nio
+
+   f = Nio.open_file(filelist[0])
+   xtimes = f.variables[timeVarName]
+   timeFormat = xtimes.units
+
+   # search to check if 'since' appears in units
+   try:
+     sinceLoc = re.search('since',timeFormat).end()
+
+   except:
+     print 'Error decoding model times: time variable attributes do not contain "since"'
+     return 0
+
+   # search for 'seconds','minutes','hours', 'days', 'months', 'years' so know units
+   units = ''
+   try:
+     mysearch = re.search('minutes',timeFormat).end()
+     units = 'minutes'
+   except:
+     pass
+   try:
+     mysearch = re.search('hours',timeFormat).end()
+     units = 'hours'
+   except:
+     pass
+   try:
+     mysearch = re.search('days',timeFormat).end()
+     units = 'days'
+   except:
+     pass
+   try:
+     mysearch = re.search('months',timeFormat).end()
+     units = 'months'
+   except:
+     pass
+   try:
+     mysearch = re.search('years',timeFormat).end()
+     units = 'years'
+   except:
+     pass
+   
+   # cut out base time (the bit following 'since')
+   base_time_string = string.lstrip(timeFormat[sinceLoc:])
+
+   # decode base time
+   base_time = decodeTimeFromString(base_time_string)
+
+
+   times=[]
+   for xtime in xtimes[:]:
+      if(units=='minutes'):  
+         dt = datetime.timedelta(minutes=xtime)
+         new_time = base_time + dt
+
+      if(units=='hours'):  
+         dt = datetime.timedelta(hours=xtime)
+         new_time = base_time + dt
+
+      if(units=='days'):  
+         dt = datetime.timedelta(days=xtime)
+         new_time = base_time + dt
+
+      if(units=='months'):   # NB. adding months in python is complicated as month length varies and hence ambigous.
+         # Perform date arithmatic manually
+         #  Assumption: the base_date will usually be the first of the month
+         #              NB. this method will fail if the base time is on the 29th or higher day of month
+         #                      -as can't have, e.g. Feb 31st.
+         new_month = int(base_time.month + xtime % 12)
+         new_year = int(math.floor(base_time.year + xtime / 12.))
+         new_time = datetime.datetime(new_year,new_month,base_time.day,base_time.hour,base_time.second,0)
+
+      if(units=='years'):
+         dt = datetime.timedelta(years=xtime)
+         new_time = base_time + dt
+         
+      times.append(new_time)
+
+   return times
+
+
+''' NOT USED BY BOTTLE WS CALLS
+import sys
+import datetime 
+filename = [sys.argv[1]]
+time_var_name = sys.argv[2]
+
+print filename, type(filename)
+print time_var_name
+
+times = decode_model_times(filename,time_var_name)
+
+for time in times:
+  print time.strftime('%Y-%m-%d %H:%M:%S')
+'''

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/rcmes/services/.svn/text-base/directory_helpers.py.svn-base
----------------------------------------------------------------------
diff --git a/src/main/python/rcmes/services/.svn/text-base/directory_helpers.py.svn-base b/src/main/python/rcmes/services/.svn/text-base/directory_helpers.py.svn-base
new file mode 100755
index 0000000..70147c4
--- /dev/null
+++ b/src/main/python/rcmes/services/.svn/text-base/directory_helpers.py.svn-base
@@ -0,0 +1,42 @@
+#!/usr/bin/env python
+"""
+    Provides helpers for listing retrieving directory information from the server.
+"""
+
+from bottle import request, route
+import os
+import json
+
+PATH_LEADER = "/usr/local/rcmes"
+
+@route('/getDirInfo/<dirPath:path>')
+def getDirectoryInfo(dirPath):
+    dirPath = PATH_LEADER + dirPath
+    dirPath = dirPath.replace('/../', '/')
+    dirPath = dirPath.replace('/./', '/')
+
+    if os.path.isdir(dirPath):
+        listing = os.listdir(dirPath)
+        listingNoHidden = [f for f in listing if f[0] != '.']
+        joinedPaths = [os.path.join(dirPath, f) for f in listingNoHidden]
+        joinedPaths = [f + "/" if os.path.isdir(f) else f for f in joinedPaths]
+        finalPaths = [p.replace(PATH_LEADER, '') for p in joinedPaths]
+        sorted(finalPaths, key=lambda s: s.lower())
+        returnJSON = finalPaths
+    else:
+        returnJSON = []
+
+    returnJSON = json.dumps(returnJSON)
+    if request.query.callback:
+        return "%s(%s)" % (request.query.callback, returnJSON)
+    else:
+        return returnJSON
+
+@route('/getPathLeader/')
+def getPathLeader():
+    returnJSON = {"leader": PATH_LEADER}
+
+    if request.query.callback:
+        return "%s(%s)" % (request.query.callback, returnJSON)
+    else:
+        return returnJSON

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/rcmes/services/.svn/text-base/find_latlon_var.py.svn-base
----------------------------------------------------------------------
diff --git a/src/main/python/rcmes/services/.svn/text-base/find_latlon_var.py.svn-base b/src/main/python/rcmes/services/.svn/text-base/find_latlon_var.py.svn-base
new file mode 100755
index 0000000..f46e8d4
--- /dev/null
+++ b/src/main/python/rcmes/services/.svn/text-base/find_latlon_var.py.svn-base
@@ -0,0 +1,136 @@
+#!/usr/local/bin/python
+"""
+    Small command line utility to find what the latitude and longitude variables are called in a model file.
+
+    Background::  
+        Model output files tend not to follow any defined standard in terms of 
+        variable naming conventions.  One model may call the latitude "lat", 
+        another one may call it "Latitudes".  This script looks for the 
+        existence of any of a predefined list of synonyms for lat and long.
+
+    This script should be run from the command line (i.e. not called from 
+    within python)
+
+    Input::
+        -filename
+    
+    Output::
+        -success flag (1 or 0): were both latitude and longitude variable names found in the file?
+    
+    if successful::
+        -name of latitude variable
+        -name of longitude variable
+        -latMin -descriptions of lat/lon ranges in data files
+        -latMax
+        -lonMin
+        -lonMax
+    
+    if unsuccessful:
+        -list of variable names in file
+    
+    (NB. all printed to standar output)
+    
+"""
+
+import sys
+import Nio
+import bottle
+from bottle import request
+import json
+
+#filename = sys.argv[1]
+
+@bottle.route('/list/latlon/:filename#".*"#')
+def find_latlon(filename):
+  success = 0
+  filename = filename.strip('"')
+  f = Nio.open_file(filename)
+  var_name_list = f.variables.keys()
+
+  # convert all variable names into lower case
+  var_name_list_lower = [x.lower() for x in var_name_list]
+
+  # create a "set" from this list of names
+  varset = set(var_name_list_lower)
+
+  # Use "set" types for finding common variable name from in the file and from the list of possibilities
+  lat_possible_names = set(['latitude','lat','lats','latitudes'])
+  lon_possible_names = set(['longitude','lon','lons','longitudes'])
+
+  # Search for common latitude name variants:
+  # Find the intersection of two sets, i.e. find what latitude is called in this file.
+  
+  try:
+    print 'hello from inside try block'
+    lat_var_name = list(varset & lat_possible_names)[0]
+    successlat = 1
+    index = 0
+    for i in var_name_list_lower: 
+     if i==lat_var_name:
+          whlat = index
+     index += 1
+    latname = var_name_list[whlat]
+
+    lats = f.variables[latname][:]
+    latMin = lats.min()
+    latMax = lats.max()
+
+  except:
+    print 'exception happens'
+    latname = 'not_found'
+    successlat = 0
+
+  # Search for common longitude name variants:
+  # Find the intersection of two sets, i.e. find what longitude
+  # is called in this file.
+  try:
+    lon_var_name = list(varset & lon_possible_names)[0]
+    successlon = 1
+    index = 0
+    for i in var_name_list_lower:
+     if i==lon_var_name:
+          whlon = index
+     index += 1
+    lonname = var_name_list[whlon]
+
+    lons = f.variables[lonname][:]
+    #this will correct all lons to -180 , 180
+    lons[lons>180]=lons[lons>180]-360
+    
+    lonMin = lons.min()
+    lonMax = lons.max()
+
+  except:
+    lonname = 'not_found'
+    successlon = 0
+
+  
+  if(successlat & successlon): 
+     success = 1
+  
+  
+  if success:
+    print success, latname, lonname, latMin, latMax, lonMin, lonMax
+    val_types= [int,str,str,str,str,str,str]
+    success_values = [success, latname, lonname, latMin, latMax, lonMin, lonMax]
+    value_names = ['success','latname','lonname','latMin','latMax','lonMin','lonMax']
+    values = [vtypes(svalues) for vtypes,svalues in zip(val_types,success_values)]
+    print values
+    output = dict(zip(value_names,values))
+    #json_output = json.dumps({'success':success,'latname':latname, \
+    #                          'lonname':lonname,'latMin':latMin, \
+    #                           'latMax':latMax,'lonMin':lonMin, \
+    #                           'lonMax':lonMax }, sort_keys=True, indent=4)
+    if (request.query.callback):
+      return "%s(%s)" % (request.query.callback, output)
+    return output
+
+  if success==0:
+    json_output = json.dumps({'success':success,
+                                 'variables':var_name_list }, \
+                                sort_keys=True, indent=4)
+    if (request.query.callback):
+      return "%s(%s)" % (request.query.callback, json_output)
+    return json_output
+    #print success, var_name_list
+

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/rcmes/services/.svn/text-base/find_time_var.py.svn-base
----------------------------------------------------------------------
diff --git a/src/main/python/rcmes/services/.svn/text-base/find_time_var.py.svn-base b/src/main/python/rcmes/services/.svn/text-base/find_time_var.py.svn-base
new file mode 100755
index 0000000..b099553
--- /dev/null
+++ b/src/main/python/rcmes/services/.svn/text-base/find_time_var.py.svn-base
@@ -0,0 +1,87 @@
+#!/usr/local/bin/python
+"""
+    Small command line utility to find what the time variable is called in a model file.
+    
+    Background::  
+        Model output files tend not to follow any defined standard in terms of 
+        variable naming conventions.  One model may call the time "time", 
+        another one may call it "t".  This script looks for the existence of 
+        any of a predefined list of synonyms for time.
+    
+    This script should be run from the command line (i.e. not called from within python)
+    
+    Input::
+        -filename
+    
+    Output::
+        -success flag (1 or 0): were both latitude and longitude variable names found in the file?
+        
+        if successful:
+            -name of time variable
+            -(TODO) modelStartTime -descriptions of time ranges in data files
+            -(TODO) modelEndTime
+        if unsuccessful:
+            -list of variable names in file
+    
+    (NB. all printed to standar output)
+"""
+
+import sys
+import bottle
+from bottle import request
+import Nio
+import json
+import decode_model_times as dmt
+
+
+#filename = sys.argv[1]
+
+
+@bottle.route('/list/time/:filename#".*"#')
+def list_time(filename):
+    filename = filename.strip('"')
+    success = 0
+    f = Nio.open_file(filename)
+    var_name_list = f.variables.keys()
+    # convert all variable names into lower case
+    var_name_list_lower = [x.lower() for x in var_name_list]
+    # create a "set" from this list of names
+    varset = set(var_name_list_lower)
+    # Use "set" types for finding common variable name from in the file and from the list of possibilities
+    time_possible_names = set(['time','t','times','date','dates','julian'])
+    # Search for common latitude name variants:
+    # Find the intersection of two sets, i.e. find what latitude is called in this file.
+    try:
+      time_var_name = list(varset & time_possible_names)[0]
+      success = 1
+      index = 0
+      for i in var_name_list_lower:
+       if i==time_var_name:
+            wh = index
+       index += 1
+      timename = var_name_list[wh]
+      
+    except:
+      timename = 'not_found'
+      success = 0
+    
+    if success:
+        print 'timename is '+timename
+        times = dmt.decode_model_times([filename],timename)
+        start_time = str(min(times))
+        end_time = str(max(times))
+        time_var = json.dumps({'success':success,'timename':timename,
+                               'start_time':start_time,'end_time':end_time})
+        #return time_var
+        if (request.query.callback):
+            return "%s(%s)" % (request.query.callback, time_var)
+        return time_var
+        
+    if success==0:
+        json_output = json.dumps({'success':success,'variables':var_name_list })
+    if (request.query.callback):
+        return "%s(%s)" % (request.query.callback, json_output)
+    return json_output
+       
+    #print success, var_name_list
+

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/rcmes/services/.svn/text-base/list_vars_in_file.py.svn-base
----------------------------------------------------------------------
diff --git a/src/main/python/rcmes/services/.svn/text-base/list_vars_in_file.py.svn-base b/src/main/python/rcmes/services/.svn/text-base/list_vars_in_file.py.svn-base
new file mode 100755
index 0000000..43da7e6
--- /dev/null
+++ b/src/main/python/rcmes/services/.svn/text-base/list_vars_in_file.py.svn-base
@@ -0,0 +1,59 @@
+#!/usr/local/bin/python
+"""
+ Small command line utility to list the variables contained within a model file.
+
+  This script should be run from the command line (i.e. not called from within python)
+
+       Input: 
+               -filename
+
+       Output: 
+               -list of variable names in file
+
+       (NB. all printed to standar output)
+
+       Peter Lean   February 2011
+
+ WEBSERVICE PLAN
+
+    URL:  localhost:9999/list_vars/:filename    (full file path plus file name)
+    Example:  localhost:9999/list/vars/"/usr/local/wrm/modeldata/wrf.nc"
+
+    Return:  JSON Array of Variable Names
+    Example:  { "variables": [ "time_bnds", "tas", "level", "lon", "time", "lat" ] }
+"""
+
+import sys
+import Nio
+import bottle
+from bottle import request
+import json
+#filename = sys.argv[1]
+
+
+@bottle.route('/list/vars/:filename#".*"#')
+def list_vars(filename):
+    success = 0
+    filename = filename.strip('"')
+    print filename + ' is filename variable'
+    try:
+      f = Nio.open_file(filename)
+      success = 1
+    except:
+      print 'Error_reading_file '+filename
+    
+    if success:  #make some json
+      var_name_list = json.dumps({'variables':f.variables.keys() }, \
+                                 sort_keys=True, indent=2)
+      if (request.query.callback):
+          return "%s(%s)" % (request.query.callback, var_name_list)
+      return var_name_list
+  
+    else:
+      failRet = "{\"FAIL\": \""+filename+"\"}"
+      if (request.query.callback):
+          return "%s(%s)" % (request.query.callback, failRet)
+      return failRet
+  
+
+

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/rcmes/services/.svn/text-base/main_ws.py.svn-base
----------------------------------------------------------------------
diff --git a/src/main/python/rcmes/services/.svn/text-base/main_ws.py.svn-base b/src/main/python/rcmes/services/.svn/text-base/main_ws.py.svn-base
new file mode 100755
index 0000000..4d78f4d
--- /dev/null
+++ b/src/main/python/rcmes/services/.svn/text-base/main_ws.py.svn-base
@@ -0,0 +1,36 @@
+"""Module that demonstrates how to initialize the RESTful web services that 
+power the RCMET GUI"""
+
+from bottle import route, response, run, static_file, hook
+import list_vars_in_file
+import find_latlon_var
+import find_time_var
+import decode_model_times as dmt
+import run_rcmes_processing
+import dataset_helpers
+import directory_helpers
+
+@route('/')
+@route('/index.html')
+def index():
+    return "<a href='/hello'>Go to Hello World page</a>"
+
+@route('/hello')
+def hello():
+    return "Hello World!"
+
+@route('/api/status')
+def api_status():
+    return {'status':'online', 'key':'value'}
+
+@route('/static/evalResults/<filename>')
+def get_eval_result_image(filename):
+    return static_file(filename, root="/tmp/rcmet")
+
+@hook('after_request')
+def enable_cors():
+    response.headers['Access-Control-Allow-Origin'] = '*'
+
+if __name__ == "__main__":
+    run(host='localhost', port=8082)
+    


[37/51] [abbrv] [partial] Adding Jinwon's custom RCMET

Posted by jo...@apache.org.
http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/rcmes/utils/misc.py
----------------------------------------------------------------------
diff --git a/src/main/python/rcmes/utils/misc.py b/src/main/python/rcmes/utils/misc.py
new file mode 100755
index 0000000..ba16ac5
--- /dev/null
+++ b/src/main/python/rcmes/utils/misc.py
@@ -0,0 +1,1385 @@
+"""Module with a collection of helper functions"""
+
+
+import ConfigParser
+import datetime
+import glob
+import json
+import os
+import sys
+
+import numpy as np
+import numpy.ma as ma
+import netCDF4
+
+import classes
+
+from fortranfile import FortranFile
+from toolkit import process
+
+def configToDict(config):
+    """
+    Helper function to parse a configuration input and return a python dictionary
+    
+    Input::  
+        config - list of ('key', 'value') tuples from ConfigParser.
+            key01 - string i.e. 'value01'
+            key-2 - string i.e. 'value02'
+    Output::
+        configDict - Dictionary of Key/Value pairs
+    """
+    configDict = {}
+    for entry in config:
+        configDict[entry[0]] = entry[1]
+
+    return configDict
+
+
+def readSubRegionsFile(regionsFile):
+    """
+    Input::
+        regionsFile - Path to a subRegion configuration file
+        
+    Output::
+        Ordered List of SubRegion Objects decoded from regionsFile
+    """
+    if os.path.exists(regionsFile):
+        regionsConfig = ConfigParser.SafeConfigParser()
+        regionsConfig.optionxform = str
+        regionsConfig.read(regionsFile)
+        regions = generateSubRegions(regionsConfig.items('REGIONS'))
+
+        return regions
+    else:
+        raise IOError
+
+def getSubRegionsInteractively(counts, workdir):
+    """
+    Purpose::
+        This function provides a commandline Q&A session to help users define 
+        SubRegion Objects.
+    Input::
+        counts - dictionary with int counts of various metric inputs
+            i.e. {'observations': 3,
+                  'models'      : 1,
+                  'times'       : 120}
+        workdir - string of the current working directory where auxillary files
+        can be found.  In this case the directory will be used to locate an 
+        existing sub_regions.txt file.
+
+    Output:: 
+        subRegions = List of Parsed SubRegion Objects based on User inputs 
+    """
+    do_timeseries = None
+    yes_no_list = ['y', 'n', '']
+    
+    while do_timeseries not in yes_no_list:
+        do_timeseries = raw_input('Calculate area-mean timeseries for subregions? y/n: [n] \n>>>')
+        if do_timeseries not in yes_no_list:
+            print("'%s' is not a valid answer please try again" % do_timeseries)
+
+    if do_timeseries == 'y':
+        interactive_subregions = None
+        while interactive_subregions not in yes_no_list:
+            interactive_subregions = raw_input('Input Sub Region info interactively? y/n: [n] \n>>>')
+            if interactive_subregions not in yes_no_list:
+                print("'%s' is not a valid answer please try again" % interactive_subregions)
+            
+        if interactive_subregions == 'y':
+            while interactive_subregions == 'y':
+                regions = []
+                region = createSubRegionObjectInteractively()
+                regions.append(region)
+                anotherRegion = None
+                while anotherRegion == None:
+                    another = raw_input("Would you like to add another sub region? y/n [n] \n>>>")
+                    if another not in yes_no_list:
+                        print("'%s' is not a valid answer please try again" % another)
+                    elif another in ['', 'n']:
+                        anotherRegion = 'n'
+                        interactive_subregions = 'n'
+                    else:
+                        anotherRegion = 'y'
+
+        else:
+            subRegionFilename = None
+            while subRegionFilename == None:
+                readDefault = raw_input('Read from a default file (workdir + "/sub_regions.txt")? y/n: [y] \n>>>')
+
+                if readDefault == 'y' or readDefault == '':
+                    subRegionFilename = workdir + "/sub_regions.txt"
+                    print("Attempting to parse %s..." % subRegionFilename)
+                    regions = readSubRegionsFile(subRegionFilename)
+
+                elif readDefault == 'n':
+                    while subRegionFilename == None:
+                        # ask about using a non default filename
+                        subRegionFilename = raw_input('Enter the full path to the Sub Region file to read from:\n>>>')
+                        print("Attempting to parse %s..." % subRegionFilename)
+                        regions = readSubRegionsFile(subRegionFilename)
+
+                elif readDefault == 'NONE':
+                    subRegionFilename = 'NONE'
+                    regions = []
+            
+                else:
+                    print("'%'s is not a valid selection.  Please try again.  To proceed without Sub Regions defined enter NONE at the prompt" % readDefault)
+
+        return regions
+
+def generateSubRegions(regions):
+    """ Takes in a list of ConfigParser tuples and returns a list of SubRegion objects
+    
+    Input::
+        regions - Config Tuple: [('Region01', '["R01", 36.5, 29, 0.0, -10]'), ('Region02',....]
+
+    Output::
+        subRegions - list of SubRegion objects
+    """
+    subRegions = []
+    for region in regions:
+        name, latMax, latMin, lonMax, lonMin = json.loads(region[1])
+        subRegion = classes.SubRegion(name, latMin, lonMin, latMax, lonMax)
+        subRegions.append(subRegion)
+
+    return subRegions
+
+def parseSubRegions(subRegionConfig):
+    """
+    Input::
+        subRegionConfig - ConfigParser object
+    
+    Output::
+        subRegions - List of SubRegion Objects.  This could return an empty List if unable to parse subRegionConfig
+    """
+    subRegions = []
+    try:
+        if os.path.exists(subRegionConfig['subRegionFile']):
+            subRegions = readSubRegionsFile(subRegionConfig['subRegionFile'])
+            
+        else:
+            print "SubRegion Filepath: [%s] does not exist.  Check your configuration file, or comment out the SUB_REGION Section." % (subRegionConfig['subRegionFile'],)
+            print "Processing without SubRegion support"
+
+
+    except IOError:
+        print "Unable to open %s.  Running without SubRegions" % (subRegionConfig['subRegionFile'],)
+    except KeyError:
+        print "subRegionFile parameter was not provided.  Processing without SubRegion support"
+
+    return subRegions
+
+
+def decode_wrf_times(xtimes, base_time):
+    '''
+      Routine to convert from WRF time ('minutes since simulation start....') 
+      into a python datetime structure
+      Input:
+          xtimes - list of wrf 'XTIME' in units of 'minutes since simulation start'
+          base_time - a python datetime object describing simulation start date/time
+      Output:
+          times  - list of python datetime objects describing model data times
+         Peter Lean August 2010
+    '''
+    times = []
+    for xtime in xtimes:
+        dt = datetime.timedelta(minutes=xtime)
+        times.append(base_time + dt)
+    return times
+
+def calc_base_time_wrf(filename):
+    '''
+      Routine to calculate base_time (i.e. model initialization time)
+       for wrf files with timestamp in their filenames.
+        NB. Only works if includes a timestamp in format 'YYYY-MM-DD_HH:MM:SS'
+        TODO: work out a more general way of doing this...
+      Input:
+          filename - full path to WRF netCDF file.
+      Output:
+          base_time  - a python datetime object describing model start time
+         Peter Lean August 2010
+    '''
+    
+    # Extract time from netCDF file (in units of 'minutes since beginning of simulation')
+    f = netCDF4.Dataset(filename, mode='r')
+    timesraw = f.variables["XTIME"]
+    model_time = timesraw[0]
+    
+    dt = datetime.timedelta(minutes=int(model_time))
+           
+    # Extract and decode timestamp from filename
+    
+    filename = os.path.basename(filename)  # strip off the filepath
+    
+    timestamp_string = filename[11:30]   # cut out the date time stamp
+    DATE_FORMAT = '%Y-%m-%d_%H:%M:%S'  
+    
+    timestamp = datetime.datetime(*time.strptime(timestamp_string, DATE_FORMAT)[:6])
+    
+    # Base Time = timestamp - 'minutes since beginning of simulation'
+    base_time = timestamp - dt
+    
+    print 'Base Time calculated as: ', base_time
+    
+    return base_time
+
+def calc_period_precip_from_running_tot(running_precip):
+    '''
+     WRF precipitation accumulations are stored as running totals from the start of the model run
+     To find out values during each output time period, you must subtract the previous total
+    
+       e.g. running tot = 0,0,1,1,1,2,2,4,7,9,9,11 
+            period accu = 0,0,1,0,0,1,0,2,3,2,0,2
+    
+      Input: 
+         running_precip   - numpy array containing precipitation data at more than one time level
+                             NB. assumes time dimension is the first one precip[time, lat, lon, level] 
+    
+      Output:
+         acc_precip       - numpy array of same dimensions as input, 
+                            but with period accumulations instead of running total.
+    
+    
+        Peter Lean August 2010
+    
+    '''
+    
+    print 'Calculating period precip accumulations from running total'
+    shifted_running_precip = np.roll(running_precip, -1, axis=0)
+    nt = running_precip.shape[0]
+    # avoid wrapping from the end time to the start time by forcing the accumulation at final time=0
+    shifted_running_precip[nt - 1, :, :] = running_precip[nt - 1, :, :]
+    acc_precip = shifted_running_precip - running_precip 
+
+    # NB. sometimes rounding errors in the model lead to very small negative period accumulations
+    #     These are removed and set to zero here.
+    acc_precip = np.maximum(acc_precip, 0)
+
+    return acc_precip
+
+def decode_eraint_surf_times(xtimes):
+    '''
+      Routine to convert from ERA-Interim time ('hours since 1900...') 
+      into a python datetime structure
+    
+      Input:
+          xtimes - list of ERA-Interim times in units of 'hours since 1900'
+    
+      Output:
+          times  - list of python datetime objects describing model data times
+    
+    
+         Peter Lean August 2010
+    
+    '''
+    base_time = datetime.datetime(1900, 1, 1, 0, 0, 0, 0)
+    times = []
+    
+    for xtime in xtimes:
+        dt = datetime.timedelta(hours=xtime)
+        times.append(base_time + dt)
+    
+    return times
+
+def read_total_precip_from_filelist(myfilelist):
+    '''
+     WRF outputs precipitation data under several variables:
+     
+         **RAINC** =  convective total precip
+         
+         **RAINNC** = large scale total precip  ("no convective")
+         
+         **SNOWC** =  convective snow
+         
+         **SNOWNC** = large scale snow  ("no convective")
+     
+     Therefore: 
+         real rain = (rainc+rainnc)-(snowc+snownc)
+         total precip = rainc+rainnc+snowc+snownc
+         
+     Input:
+         myfilelist - a list of filename (including full path)
+           
+     Output:
+         precip - a numpy array of total precip values
+         lat, lon - 2D array of latitude and longitude values
+         times    - list of times
+     
+     NB. THIS ROUTINE IS NO LONGER NEEDED... I HAD MISUNDERSTOOD HOW PRECIP DATA WAS STORED IN WRF
+     TOTAL PRECIP  = RAINNC
+     **A SIMILAR ROUTINE MAY BE REQUIRED TO FIND THE INDIVIDUAL COMPONENTS THOUGH..**
+    
+    '''
+    myfilelist.sort()
+
+    print 'Calculating total precipitation from individual rain/snow, convective/ls components'
+    lat, lon, times, rainnc = read_data_from_file_list(myfilelist, 'RAINC')
+    lat, lon, times, rainc = read_data_from_file_list(myfilelist, 'RAINNC')
+    precip = rainnc + rainc
+    # reset negative values to zero
+    precip[precip < 0] = 0.0
+
+    return lat, lon, times, precip
+
+
+def isDirGood(directory):
+    """
+    Purpose::
+        This function will check if a directory exists and is writeable.  If the directory doesn't exist it is created.
+    Input::
+        directory - Path we need to check 
+    Output::
+        directoryStatus - Boolean
+    """
+    directoryStatus = False
+    
+    if os.path.exists(directory):
+        directoryStatus = os.access(directory, os.W_OK | os.X_OK)
+        if directoryStatus:
+            pass
+        else:
+            raise OSError("Unable to access the directory: %s.  Check that you have the proper permissions to read and write to that directory." % directory)
+            #directoryStatus = False
+    else:
+        try:
+            os.mkdir(directory)
+            directoryStatus = True
+        except OSError:
+            raise
+
+    return directoryStatus
+    
+
+def read_trmm_3b42_files(filelist, latMin, latMax, lonMin, lonMax):
+    '''
+     ** Alternate method of getting TRMM data from local repository if DB not available **
+     Reads TRMM gridded precipitation data from netCDF files in local repository.
+    
+     Input:
+        filelist - list of filenames (including path)
+        latMin,latMax,lonMin,lonMax - define region to extract (in degrees)
+     Output:
+        lat, lon   - 1D array of latitude and longitude values
+        timestore  - list of python datetime objects
+        mdata      - numpy masked array containing data from all files    
+    
+      NB. written specific for TRMM netCDF output files
+    
+       Peter Lean June 2010 
+    '''
+    filelist.sort()
+
+    # Crash nicely if 'filelist' is zero length
+    if len(filelist) == 0:
+        print 'Error: no files have been passed to read_data_from_file_list()'
+        sys.exit()
+    
+    # Open the first file in the list to:
+    #    i) read in lats, lons
+    #    ii) find out how many timesteps in the file 
+    #        (assume same ntimes in each file in list)
+    #     -allows you to create an empty array to store variable data for all times
+    tmp = netCDF4.Dataset(filelist[0], mode='r')
+    latsraw = tmp.variables["latitude"]
+    lonsraw = tmp.variables["longitude"]
+    lat = latsraw[:]
+    lon = lonsraw[:]
+    print 'Lats and lons read in for first file in filelist'
+
+    # Find out how many times there are in the file (should always be 1 for these TRMM files)
+    timesraw = tmp.variables["time"]
+    ntimes = len(timesraw)
+    
+    
+    # Convert specified longitudes into 0-360 format if required
+    if(lonMin < 0):
+        lonMin = lonMin + 360
+    if(lonMax < 0):
+        lonMax = lonMax + 360
+
+    # Create mask to extract required region only
+    #  NB. longitude is slightly more complicated as can wrap the prime meridion
+    print 'Extracting for :- lats:', latMin, latMax, ' lons: ', lonMin, lonMax
+    wh_lat = np.logical_and((lat > latMin), (lat < latMax))
+    if(lonMin <= lonMax):
+        wh_lon = np.logical_and((lon > lonMin), (lon < lonMax))
+    if(lonMin > lonMax):
+        wh_lon = np.logical_or((lon > lonMin), (lon < lonMax))
+    
+    sublat = lat[wh_lat]
+    sublon = lon[wh_lon]
+    
+    wh_true1, wh_true2 = np.meshgrid(wh_lon, wh_lat)
+    wh = np.logical_and(wh_true1, wh_true2)
+    
+    # Create empty array to store data
+    t2store = np.empty((ntimes * len(filelist), sublat.size, sublon.size))
+    timestore = []
+
+    # Now load in the data for real
+    #  NB. no need to reload in the latitudes and longitudes -assume invariant
+    i = 0
+    timesaccu = 0 # a counter for number of times stored so far in t2store 
+    #  NB. this method allows for missing times in data files 
+    #      as no assumption made that same number of times in each file...
+    for ifile in filelist:
+        print 'Loading data from file: ', filelist[i]
+        f = netCDF4.Dataset(ifile, mode = 'r')
+        t2raw = f.variables['hrf']
+        
+        # Read time from filename (NB. 'time' variable in netCDF always set to zero)
+        filename = os.path.basename(ifile)  # strip off the filepath
+        timestamp_string = filename[11:23]   # cut out the date time stamp
+        DATE_FORMAT = '%Y.%m.%d.%H'  
+        mytime = datetime.datetime(*time.strptime(timestamp_string, DATE_FORMAT)[:4])
+        ntimes = 1
+        t2tmp = t2raw[0, :, :]
+        sub = t2tmp[wh].reshape(sublat.size, sublon.size)
+        t2store[timesaccu, :, :] = sub
+        timestore.append(mytime)
+        timesaccu = timesaccu + ntimes
+        i += 1 
+    
+    print 'Data read in successfully with dimensions: ', t2store.shape
+    
+    # Create masked array using missing value flag from file
+    mdi = f.variables['hrf'].missing_value[0]
+    mdata = ma.masked_array(t2store, mask=(t2store == mdi))
+    
+    return sublat, sublon, timestore, mdata
+
+def read_airs_lev3_files(filelist, myvar, latMin, latMax, lonMin, lonMax):
+    '''
+     ** For testing work before database was ready. **
+     Reads AIRS level III gridded data from netCDF files.
+    
+     Input:
+        filelist - list of filenames (including path)
+        myvar    - name of variable to load
+        latMin,latMax,lonMin,lonMax - define region to extract (in degrees)
+     Output:
+        lat, lon   - 1D array of latitude and longitude values
+        timestore  - list of python datetime objects
+        mdata      - numpy masked array containing data from all files    
+    
+      NB. written specific for AIRS level III netCDF output files
+    
+      NB. Ascending passes have local time of 1:30pm
+      NB. Descending passes have local time of 1:30am
+    
+       Peter Lean June 2010 
+    '''
+    
+    filelist.sort()
+    
+    # Crash nicely if 'filelist' is zero length
+    if len(filelist) == 0:
+        print 'Error: no files have been passed to read_data_from_file_list()'
+        sys.exit()
+
+    # Open the first file in the list to:
+    #    i) read in lats, lons
+    #    ii) find out how many timesteps in the file 
+    #        (assume same ntimes in each file in list)
+    #     -allows you to create an empty array to store variable data for all times
+    tmp = netCDF4.Dataset(filelist[0], mode = 'r')
+    latsraw = tmp.variables["lat"]
+    lonsraw = tmp.variables["lon"]
+    lat = latsraw[:]
+    lon = lonsraw[:]
+    print 'Lats and lons read in for first file in filelist'
+
+    # Only one time per file in AIRS level III data
+    ntimes = 1
+    
+    # Create mask to extract required region only
+    #  NB. longitude is slightly more complicated as can wrap the prime meridion
+    print 'Extracting for :- lats:', latMin, latMax, ' lons: ', lonMin, lonMax
+    wh_lat = np.logical_and((lat >= latMin), (lat <= latMax))
+    if(lonMin < lonMax):
+        wh_lon = np.logical_and((lon >= lonMin), (lon <= lonMax))
+    if(lonMin > lonMax):
+        wh_lon = np.logical_or((lon >= lonMin), (lon <= lonMax))
+    
+    sublat = lat[wh_lat]
+    sublon = lon[wh_lon]
+    
+    wh_true1, wh_true2 = np.meshgrid(wh_lon, wh_lat)
+    wh = np.logical_and(wh_true1, wh_true2)
+    
+    # Create empty array to store data
+    t2store = np.empty((ntimes * len(filelist), sublat.size, sublon.size))
+    timestore = []
+
+    # Now load in the data for real
+    #  NB. no need to reload in the latitudes and longitudes -assume invariant
+    i = 0
+    timesaccu = 0 # a counter for number of times stored so far in t2store 
+    #  NB. this method allows for missing times in data files 
+    #      as no assumption made that same number of times in each file...
+    for ifile in filelist:
+        print 'Loading data from file: ', filelist[i]
+        f = netCDF4.Dataset(ifile, mode='r')
+        t2raw = f.variables[myvar]
+        
+        # Read time from filename (NB. 'time' variable in netCDF always set to zero)
+        filename = os.path.basename(ifile)  # strip off the filepath
+        timestamp_string = filename[5:15]   # cut out the date time stamp
+        DATE_FORMAT = '%Y.%m.%d'  
+        mytime = datetime.datetime(*time.strptime(timestamp_string, DATE_FORMAT)[:4])
+        print mytime
+        ntimes = 1
+        t2tmp = t2raw[:, :]
+        sub = t2tmp[wh].reshape(sublat.size, sublon.size)
+        t2store[timesaccu, :, :] = sub
+        timestore.append(mytime)
+        timesaccu = timesaccu + ntimes
+        i += 1 
+
+
+    print 'Data read in successfully with dimensions: ', t2store.shape
+
+    # Create masked array using missing value flag from file
+    mdi = f.variables[myvar]._FillValue[0]
+    mdata = ma.masked_array(t2store, mask=(t2store == mdi))
+    # Rearrange array so data match lat lon values
+    mdata = np.flipud(mdata[:, ::-1])
+
+    return sublat, sublon, timestore, mdata
+
+def read_urd_files(filelist, latMin, latMax, lonMin, lonMax):
+    '''
+     Routine to load in NCEP Unified Raingauge Database binary files
+    
+      Input:
+         filelist - a list of URD data files
+    
+    
+      Output:
+         sublats, sublons: 2d arrays of latitude and longitude values for user selected region.
+         times - a list of python datetime objects
+         subdata - precipitation data for user selected region
+    
+      Peter Lean  August 2010
+    '''
+    
+    repository_path = '/nas/share1-hp/jinwonki/data/obs/pr25urd/daily/'
+    
+    # NB. Domain: 140W - 60W; 20N - 60N; Resolution: 0.25x0.25 degrees.
+    #     The grids are arranged such that
+    #     longitude is from 140W eastward to 60W and latitude from 20N northward
+    #     to 60N, so that the first grid is (140W,20N), the second is 
+    #     (139.75W,20N)......
+    
+    # Parameters specific to the URD dataset
+    nlat = 161
+    nlon = 321
+    
+    # Calculate the latitude and longitude arrays
+    lat = np.arange(20, 60.25, 0.25)  # Hard wired lat,lon extent values for URD data files
+    lon = np.arange(-140, -59.75, 0.25)
+    
+    lons, lats = np.meshgrid(lon, lat)
+
+    # Define sub-region mask 
+    #  NB. longitude is slightly more complicated as can wrap the prime meridion
+    print 'Extracting for :- lats:', latMin, latMax, ' lons: ', lonMin, lonMax
+    wh_lat = np.logical_and((lats >= latMin), (lats <= latMax))
+    if(lonMin < lonMax):
+        wh_lon = np.logical_and((lons >= lonMin), (lons <= lonMax))
+    if(lonMin > lonMax):
+        wh_lon = np.logical_or((lons >= lonMin), (lons <= lonMax))
+    
+    # count number of latitude values in subselection (for redimensioning array)
+    wh_true = np.logical_and(wh_lat, wh_lon)
+    nsublat = np.where(np.logical_and((lat >= latMin), (lat <= latMax)))[0].size
+    
+    sublats = lats[wh_true].reshape(nsublat, -1)  # infers longitude dimension given latitude dimension
+    sublons = lons[wh_true].reshape(nsublat, -1)  # infers longitude dimension given latitude dimension
+    nsublon = sublats.shape[1]
+
+    # Load in the daily data
+    datastore = []
+    for myfile in filelist:
+        f = FortranFile(repository_path + myfile)
+    
+        # Extract month and year from filename
+        yearmonth = int(myfile[7:13])
+        year = int(str(yearmonth)[0:4])
+        month = int(str(yearmonth)[4:6])
+        
+        # Find out how many days there are in that month
+        nt = calendar.monthrange(year, month)[1]
+        
+        data = np.zeros((nt, nsublat, nsublon))
+        for t in np.arange(nt):
+            precip = f.readReals()
+            precip.shape = [nlat, nlon]
+            data[t, :, :] = precip[wh_true].reshape(nsublat, nsublon) 
+        
+        datastore.append(data)
+
+    # Make a single 3d numpy array out of my list of numpy arrays
+    nt = 0
+    for i in range(len(datastore)):
+        nt = nt + datastore[i].shape[0]
+    
+    final_data = np.zeros((nt, nsublat, nsublon))
+    t = 0
+    for i in range(len(datastore)):
+        nt = datastore[i].shape[0]
+        final_data[t:t + nt, :, :] = datastore[i]
+        t = t + nt
+
+    # Load in land/sea mask
+    ls = np.fromfile("/nas/share1-hp/jinwonki/data/obs/pr25urd/s/d/lsm25.usa", sep=" ")
+    ls.shape = [nlat, nlon]
+    # Extract subregion from land/sea mask
+    subls = np.ones(final_data.shape)
+    for t in np.arange(final_data.shape[0]):
+        subls[t, :, :] = ls[wh_true].reshape(nsublat, nsublon) 
+    
+    # Construct a masked array of data i.e. only using data from land points
+    mdi = -1
+    mdata = ma.masked_array(final_data, mask=(subls == mdi))
+
+    # Construct datetime list from dates in filenames.
+    yearmonth = np.zeros(len(filelist))
+    i = 0
+    for filename in filelist:
+        # Extract month and year from filename
+        yearmonth[i] = int(filename[7:13])
+        i += 1
+    
+    # Construct a list of datetimes between the earliest and latest yearmonth
+    firstyear = int(str(yearmonth.min())[0:4])
+    firstmonth = int(str(yearmonth.min())[4:6])
+    times = []
+
+    cur_time = datetime.datetime(firstyear, firstmonth, 1, 0, 0, 0, 0)
+    
+    for i in range(final_data.shape[0]):
+        times.append(cur_time)
+        dt = datetime.timedelta(days=1)
+        cur_time = cur_time + dt
+    
+    return sublats, sublons, times, mdata
+
+def read_tmp_watershed(myfile, dom_num):
+    '''
+     Routine to read watershed weighting file mapped onto WRF model grids.
+      NB.this will be superceded by proper routines to read shape files and regrid onto any model grid.
+    
+      Input:
+         myfile - file name of the watershed ascii file to load
+         dom_num - WRF domain number (specific to this experiment)
+    
+      Output:
+         mymask - boolean mask array saying where the watershed is
+    
+       Peter Lean    September 2010
+    '''
+    
+    # Parameters specific to WRF domain setup required for these files
+    if(dom_num == 1):
+        nx = 190
+        ny = 130
+    
+    if(dom_num == 2):
+        nx = 192
+        ny = 180
+      
+    # Create an empty array to store the weights
+    myweights = np.zeros((ny, nx))
+    
+    # Load in data from the mask file
+    i, j, w = np.loadtxt("/home/plean/demo/rcmes/watersheds/" + myfile, unpack=True)
+    
+    for q in np.arange(len(i)):
+        myweights[j[q], i[q]] = w[q]
+    
+    mymask = np.empty((ny, nx))
+    mymask[:] = True
+    mymask[(myweights > 0.5)] = False
+    
+    return mymask
+
+def read_eraint_surf_files(filelist, myvar, latMin, latMax, lonMin, lonMax):
+    '''
+     ** For testing work before database was ready. **
+     Reads ERA-Interim surface netCDF files.
+    
+     Input:
+        filelist - list of filenames (including path)
+        myvar    - name of variable to load
+        latMin,latMax,lonMin,lonMax - define region to extract (in degrees)
+     Output:
+        lat, lon   - 1D array of latitude and longitude values
+        timestore  - list of python datetime objects
+        mdata      - numpy masked array containing data from all files    
+    
+       Peter Lean September 2010 
+    '''
+    
+    
+    # Crash nicely if 'filelist' is zero length
+    if len(filelist) == 0:
+        print 'Error: no files have been passed to read_data_from_file_list()'
+        sys.exit()
+
+    # Open the first file in the list to:
+    #    i) read in lats, lons
+    #    ii) find out how many timesteps in the file 
+    #        (assume same ntimes in each file in list)
+    #     -allows you to create an empty array to store variable data for all times
+    tmp = netCDF4.Dataset(filelist[0], mode='r')
+    latsraw = tmp.variables["latitude"]
+    lonsraw = tmp.variables["longitude"]
+    lat = latsraw[:]
+    lon = lonsraw[:]
+    print 'Lats and lons read in for first file in filelist'
+    
+    # Create mask to extract required region only
+    #  NB. longitude is slightly more complicated as can wrap the prime meridion
+    print 'Extracting for :- lats:', latMin, latMax, ' lons: ', lonMin, lonMax
+    wh_lat = np.logical_and((lat >= latMin), (lat <= latMax))
+    if(lonMin < lonMax):
+        wh_lon = np.logical_and((lon >= lonMin), (lon <= lonMax))
+    if(lonMin > lonMax):
+        wh_lon = np.logical_or((lon >= lonMin), (lon <= lonMax))
+    
+    sublat = lat[wh_lat]
+    sublon = lon[wh_lon]
+    
+    wh_true1, wh_true2 = np.meshgrid(wh_lon, wh_lat)
+    wh = np.logical_and(wh_true1, wh_true2)
+    
+    # Create storage lists
+    datastore = []
+    timestore = []
+
+    # Now load in the data for real
+    #  NB. no need to reload in the latitudes and longitudes -assume invariant
+    i = 0
+    timesaccu = 0 # a counter for number of times stored so far in t2store 
+    #  NB. this method allows for missing times in data files 
+    #      as no assumption made that same number of times in each file...
+    for ifile in filelist:
+        print 'Loading data from file: ', filelist[i]
+        f = netCDF4.open_file(ifile, mode='r')
+        data = f.variables[myvar][:]
+        scale = f.variables[myvar].scale_factor
+        offset = f.variables[myvar].add_offset
+        data = data * scale + offset
+        times = f.variables["time"][:]
+        ntimes = times.size
+        # Decode times into python datetime object
+        sub = data[:, wh].reshape(ntimes, sublat.size, sublon.size)
+        datastore.append(sub)
+        timestore.append(times)
+        timesaccu = timesaccu + ntimes
+        i += 1 
+
+    # move data from lists into correctly dimensioned arrays
+    final_data = np.zeros((timesaccu, sublat.size, sublon.size))
+    t = 0
+    for i in range(len(datastore)):
+        nt = datastore[i].shape[0]
+        final_data[t:t + nt, :, :] = datastore[i]
+        t = t + nt
+    
+    times = np.zeros((timesaccu))
+    t = 0
+    for i in range(len(timestore)):
+        nt = timestore[i].shape[0]
+        times[t:t + nt] = timestore[i]
+        t = t + nt
+  
+    # Decode times into python datetime objects
+    times = rcmes.process.decode_eraint_surf_times(times)
+    
+    print 'Data read in successfully with dimensions: ', final_data.shape
+    
+    # Create masked array using missing value flag from file
+    mdi = f.variables[myvar]._FillValue[0]
+    mdata = ma.masked_array(final_data, mask=(final_data == mdi))
+
+    # Rearrange array so data match lat lon values
+    mdata = np.flipud(mdata[:, ::-1])
+    
+    return sublat, sublon, times, mdata
+
+def make_list_of_wrf_files(firstTime, lastTime, ident):
+    '''
+     Routine to make list of WRF filenames given time period.
+    
+      Input:
+          firstTime - datetime object specifying start time
+          lastTime  - datetime object specifying end time
+          ident     - identifier for model run, e.g. 'd01'
+    
+      Output:
+          filelist  - list of standard format WRF filenames
+    
+          Peter Lean
+    '''
+
+    dt = datetime.timedelta(hours=6)
+    filenamelist = []
+    curTime = firstTime
+
+    while curTime <= lastTime:
+        curTimeString = curTime.strftime("%Y-%m-%d_%H:%M:%S")
+        filenamelist.append('wrfout_' + ident + '_' + curTimeString)
+        curTime += dt
+    
+    return filenamelist
+
+def make_list_of_trmm_files(firstTime, lastTime):
+    '''
+     Routine to make list of TRMM filenames given time period.
+    
+      Input:
+          firstTime - datetime object specifying start time
+          lastTime  - datetime object specifying end time
+    
+      Output:
+          filelist  - list of standard format WRF filenames
+    
+          Peter Lean
+    '''
+    trmm_repository = '/nas/share4-cf/plean/TRMM/'
+    dt = datetime.timedelta(hours=24)
+    filenamelist = []
+    curTime = firstTime
+    while curTime <= lastTime:
+        curTimeString = curTime.strftime("%Y.%m.%d")
+        filenamelist.append(trmm_repository + '3B42_daily.' + curTimeString + '.6.nc')
+        
+        curTime += dt
+    
+    return filenamelist
+
+def make_list_of_airs_files(firstTime, lastTime):
+    '''
+     Routine to make list of AIRS filenames given time period.
+    
+      Input:
+          firstTime - datetime object specifying start time
+          lastTime  - datetime object specifying end time
+    
+      Output:
+          filelist  - list of standard format WRF filenames
+    
+          Peter Lean
+    '''
+
+
+    airs_repository = '/nas/share4-cf/plean/AIRX3STD/'
+    dt = datetime.timedelta(hours=24)
+    filenamelist = []
+    curTime = firstTime
+    while curTime <= lastTime:
+        curTimeString = curTime.strftime("%Y.%m.%d")
+        filenamelist.append(glob.glob(airs_repository + 'AIRS.' + curTimeString + '.L3.*.nc')[0])
+        
+        curTime += dt
+    
+    return filenamelist
+
+def make_list_of_urd_files(firstTime, lastTime):
+    '''
+     Routine to make list of URD filenames given time period.
+    
+      Input:
+          firstTime - datetime object specifying start time
+          lastTime  - datetime object specifying end time
+    
+      Output:
+          filelist  - list of standard format WRF filenames
+    
+          Peter Lean
+    '''
+    
+    dt = datetime.timedelta(days=30)
+    filenamelist = []
+    newfirstTime = datetime.datetime(firstTime.year, firstTime.month, 15, 0, 0, 0)
+    newlastTime = datetime.datetime(lastTime.year, lastTime.month, 15, 0, 0, 0)
+    
+    curTime = newfirstTime
+    while curTime <= newlastTime:
+        curTimeString = curTime.strftime("%Y%m")
+        filenamelist.append('pr_ncep' + curTimeString)
+        if(curTime.month == 1):
+            curTime = datetime.datetime(curTime.year, curTime.month, 15, 00, 00, 00, 00)
+        
+        curTime += dt
+    
+    return filenamelist
+
+def make_list_of_era_surf_files(firstTime, lastTime):
+    '''
+     Routine to make list of ERA-Interim surface filenames given time period.
+    
+      Input:
+          firstTime - datetime object specifying start time
+          lastTime  - datetime object specifying end time
+    
+      Output:
+          filelist  - list of standard format WRF filenames
+    
+          Peter Lean
+    '''
+
+    import datetime
+    eraint_repository = '/data/plean/era-int/surf/'
+    filenamelist = []
+    dt = datetime.timedelta(days=30)
+    newfirstTime = datetime.datetime(firstTime.year, firstTime.month, 15, 0, 0, 0)
+    newlastTime = datetime.datetime(lastTime.year, lastTime.month, 15, 0, 0, 0)
+    curTime = newfirstTime
+
+    while curTime <= newlastTime:
+        curTimeString = curTime.strftime("%b%Y")
+        filenamelist.append(eraint_repository + 'sfc.' + curTimeString.lower() + '.nc')
+        if(curTime.month == 1):
+            curTime = datetime.datetime(curTime.year, curTime.month, 15, 00, 00, 00, 00)
+        
+        curTime += dt
+    
+    return filenamelist
+
+
+#
+
+def assign_subRgns_from_a_text_file(infile):
+    # Read pre-fabricated sugregion information from a text file
+    # Note: python indexing includes the beginning point but excludes the ending point
+    f = open(infile, 'r')
+    for i in np.arange(8):
+        string = f.readline()
+        print 'Line ', i, ': Content ', string
+    string = f.readline()
+    numSubRgn = int(string[20:22])
+    print 'numSubRgn = ', numSubRgn
+    for i in np.arange(3):
+        string = f.readline()
+    # Read input string and extract subRegion info (name, longs, lats) from the string
+    subRgnName = []
+    subRgnLon0 = ma.zeros((numSubRgn))
+    subRgnLon1 = ma.zeros((numSubRgn))
+    subRgnLat0 = ma.zeros((numSubRgn))
+    subRgnLat1 = ma.zeros((numSubRgn))
+    for i in np.arange(numSubRgn):
+        string = f.readline()
+        subRgnName.append(string[0:19])
+        subRgnLon0[i] = float(string[30:37])
+        subRgnLon1[i] = float(string[40:47])
+        subRgnLat0[i] = float(string[50:55])
+        subRgnLat1[i] = float(string[60:65])
+    f.close()
+    print 'subRgnName: ', subRgnName
+    print 'subRgnLon0: ', subRgnLon0
+    print 'subRgnLon1: ', subRgnLon1
+    print 'subRgnLat0: ', subRgnLat0
+    print 'subRgnLat1: ', subRgnLat1
+    return numSubRgn, subRgnName, subRgnLon0, subRgnLon1, subRgnLat0, subRgnLat1
+
+def createSubRegionObjectInteractively():
+    """
+    Purpose::
+        Mini command line program to enable users to enter SubRegion Information
+    Input::
+        None
+    Output::
+        SubRegion Object
+    """
+    rawInput = None
+    while rawInput == None:
+        userMessage = ("Enter information for 1 Sub Region using the following "
+                       "pipe '|' separated format: \n"
+                       "RegionName | Degrees North | Degrees South | Degrees East | Degrees West \n>>>")
+        userInput = raw_input(userMessage)
+        inputList = userInput.split('|')
+        if len(inputList) != 5:
+            badLengthMessage = ("Unable to parse %s.  You should have 5 inputs "
+                                "separated by 4 pipe characters. \n"
+                                "Example:  Region Name | 85 | 80 | 10 | -30" % userInput)
+            print(badLengthMessage)
+        else:
+            name = str(inputList[0]).strip()
+            latMax = str(inputList[1]).strip()
+            latMin = str(inputList[2]).strip()
+            lonMax = str(inputList[3]).strip()
+            lonMin = str(inputList[4]).strip()
+            subRegion = classes.SubRegion(name, latMin, lonMin, latMax, lonMax)
+            rawInput = True
+
+    return subRegion
+
+def selectSubRegion(subRegions):
+    # interactively select the sub-region ID for area-mean time-series evaluation
+    print '-'*59
+    columnTemplate = "|{0:2}|{1:10}|{2:10}|{3:10}|{4:10}|{5:10}|"
+    print columnTemplate.format("ID", "Name", "LonMin", "LonMax", "LatMin", "LatMax")
+    counter = 0
+    for subRegion in subRegions:
+        print columnTemplate.format(counter, subRegion.name, subRegion.lonMin, subRegion.lonMax, subRegion.latMin, subRegion.latMax)
+        counter += 1
+
+    print '-'*59
+    ask = 'Enter the sub-region ID to be evaluated. -9 for all sub-regions: \n'
+    rgnSelect = int(raw_input(ask))
+    if rgnSelect >= len(subRegions):
+        print 'sub-region ID out of range. Max = %s' % len(subRegions)
+        sys.exit()
+    return rgnSelect
+
+def getStartEndTimes(status, startOverLapTime, endOverLapTime):
+    '''
+    This function will get the start and end time from user.
+    It also check whether or not user enters the proper time for both start and end.
+    If user leaves the start and end time empty, it will get the largest time range as default (overlap).
+    '''
+
+    if status == "start":
+        try:
+            time = raw_input("Please Enter a Start Date [%s]: " % startOverLapTime.strftime('%Y-%m-%d'))
+            if not time:
+                time = startOverLapTime
+                print "Your time starts from [%s] " % time.strftime('%Y-%m-%d')
+                return time
+            time = datetime.datetime.strptime(time, '%Y-%m-%d')
+            if time < startOverLapTime:
+                print "WARNING: The time you inputted [%s] " % time.strftime('%Y-%m-%d') + " is before the minimum start time [%s]."  % startOverLapTime.strftime('%Y-%m-%d')
+                time = getStartEndTimes("start", startOverLapTime, endOverLapTime)
+                return time
+            elif time > endOverLapTime:
+                print "WARNING: The time you inputted [%s] " % time.strftime('%Y-%m-%d') + " is after the maximum end time [%s]. " % endOverLapTime.strftime('%Y-%m-%d')
+                time = getStartEndTimes("start", startOverLapTime, endOverLapTime)
+                return time
+            else:
+                return time
+        except ValueError:
+            getStartEndTimes(status, startOverLapTime, endOverLapTime)
+    
+    if status == "end":
+        try:
+            time = raw_input("Please Enter an End Date [%s]: " % endOverLapTime.strftime('%Y-%m-%d'))
+            if not time:
+                time = endOverLapTime
+                print "Your time ends by [%s] " % time.strftime('%Y-%m-%d')
+                return time
+            time = datetime.datetime.strptime(time, '%Y-%m-%d')
+            if time > endOverLapTime:
+                print "WARNING: The time you inputted [%s] " % time.strftime('%Y-%m-%d') + " is after the maximum end time [%s]. " % endOverLapTime.strftime('%Y-%m-%d')
+                time = getStartEndTimes("end", startOverLapTime, endOverLapTime)
+                return time
+            elif time < startOverLapTime:
+                print "WARNING: The time you inputted [%s] " % time.strftime('%Y-%m-%d') + " is before the minimum start time [%s]."  % startOverLapTime.strftime('%Y-%m-%d')
+                time = getStartEndTimes("end", startOverLapTime, endOverLapTime)
+                return time
+            else:
+                return time
+        except ValueError:
+            getStartEndTimes(status, startOverLapTime, endOverLapTime)
+
+
+def getDirSettings():
+    """
+    This function will collect 2 parameters from the user about the RCMET run they have started.
+    
+    Output::
+        dirs - Tuple of strings i.e. ('workDirPath', 'cacheDirPath')
+    """
+    workDir = os.path.abspath(raw_input('Please enter workDir:\n> '))
+    if os.path.isdir(workDir):
+        pass
+    else:
+        makeDirectory(workDir)
+    
+    cacheDir= os.path.abspath(raw_input('Please enter cacheDir:\n> '))
+    if os.path.isdir(cacheDir):
+        pass
+    else:
+        makeDirectory(cacheDir)
+    
+    return (workDir, cacheDir)
+
+def getModelFiles():
+    modelList = []
+    while len(modelList) < 1:
+        userInput = raw_input('Please enter model file (or specify multiple files using wildcard):\n> ')
+        modelList = glob.glob(userInput)
+        if len(modelList) == 0:
+            print("Sorry we were unable to find any files at - %s" % userInput)
+            print("Please try again, and use the asterisk * for the wildcard")
+        
+    return modelList
+
+def getTemporalGrid():
+    options = ['annual', 'monthly', 'daily']
+    print("Please select one of the following Temporal Grid Options:\n")
+    for key, option in enumerate(options):
+        print("[%s] - %s" % (key, option))
+    choice = int(raw_input(">>>"))
+    try:
+        temporalGrid = options[choice]
+    except IndexError:
+        getTemporalGrid()
+    else:
+        return temporalGrid
+
+def getSpatialGrid():
+    options = ['obs', 'model', 'user']
+    print("Please select one of the following Spatial Grid Options:\n")
+    for key, option in enumerate(options):
+        print("[%s] - %s" % (key, option))
+
+    choice = int(raw_input(">>>"))
+    try:
+        spatialGrid = options[choice]
+    except IndexError:
+        getSpatialGrid()
+
+    return spatialGrid
+
+def askUserForVariableName(variableNames, targetName):
+    if targetName == "analysis":
+        print("Select the variable you want to use for analysis/metrics:")
+    else:
+        print("Select the variable that corresponds to %s:" % targetName)
+
+    for idx, variable in enumerate(variableNames):
+        print("[%s] - %s" % (idx, variable))
+    userChoice = int(raw_input(">>>"))
+    try:
+        variableName = variableNames[userChoice]
+    except IndexError:
+        askUserForVariableName(variableNames, targetName)
+    
+    return variableName
+        
+        
+
+def getLatLonStep(settings):
+    pass
+
+def getSpatialBounds(settings):
+    pass
+
+
+def getUserSpatialSettings(settings):
+    getLatLonStep(settings)
+    getSpatialBounds(settings)
+
+def makeDirectory(directory):
+    print "%s doesn't exist.  Trying to create it now." % directory
+    try:
+        os.mkdir(directory)
+        print("Created %s successfully" % directory)
+    except OSError:
+        print "This program cannot create dir: %s due to permission issues." % directory
+        sys.exit()
+
+
+def userDefinedStartEndTimes(obsSource,obsName,obsTimeName,obsList,modelList):
+    """
+    The function will interactively ask the user to select a start and end time based on the start/end times
+    of the supplied observation and model objects
+     
+    Input::
+        obsList - List of Observation Objects
+        modelList - List of Model Objects
+    
+    Output::
+        startTime - Python datetime object from User Input
+        endTime - Python datetime object from User Input
+    """
+    startTimes = []
+    endTimes = []
+    print '='*94
+    template = "|{0:60}|{1:15}|{2:15}|"
+    print template.format('Dataset - NAME', 'START DATE', 'END DATE')
+    if obsSource == 0:                # observation from RCMED
+        for observation in obsList:
+            startTimes.append(datetime.datetime.strptime(observation['start_date'],'%Y-%m-%d'))
+            endTimes.append(datetime.datetime.strptime(observation['end_date'],'%Y-%m-%d'))
+            print template.format(observation['longname'], observation['start_date'], observation['end_date'])
+    elif obsSource == 1:              # observation from user
+        nn = 0
+        for observation in obsList:
+            times, timeStep = process.getModelTimes(observation,obsTimeName)
+            #print times, timeStep
+            startTimes.append(min(times))
+            endTimes.append(max(times))
+            print template.format(obsName[nn], min(times).strftime('%Y-%m-%d'), max(times).strftime('%Y-%m-%d'))
+            nn = +1
+    print '-'*94
+    for model in modelList:
+        startTimes.append(model.minTime)
+        endTimes.append(model.maxTime)
+        print template.format(model.name, model.minTime.strftime('%Y-%m-%d'), model.maxTime.strftime('%Y-%m-%d'))
+    print '='*94
+    
+    # Compute Overlap
+    maxstartTimes=max(startTimes)
+    minendTimes=min(endTimes)
+    # TODO:  Do we need to start on JAN and end on DEC?  Do we know someone is doing ANNUAL analysis at this point?
+#    if maxstartTimes.month != 1:
+#        maxstartTimes = datetime.datetime(maxstartTimes.year+1,1,maxstartTimes.day)
+#    if minendTimes.month != 12:
+#        minendTimes = datetime.datetime(minendTimes.year-1,12,minendTimes.day)
+    if minendTimes.year < maxstartTimes.year:
+        print 'Not enough data for overlapping years'
+        sys.exit()
+    overLap = (maxstartTimes.strftime('%Y-%m-%d'), minendTimes.strftime('%Y-%m-%d'))
+    # Present default overlap to user as default value
+    print 'Standard Overlap in the selected datasets are %s through %s' % (overLap)
+
+    startOverLapTime = datetime.datetime.strptime(overLap[0],'%Y-%m-%d')
+    endOverLapTime = datetime.datetime.strptime(overLap[1],'%Y-%m-%d')
+
+    # Enter Start Date
+    startTime = getStartEndTimes("start", startOverLapTime, endOverLapTime)    
+    # Enter End Date
+    endTime = getStartEndTimes("end", startOverLapTime, endOverLapTime)
+        
+    if startTime > endTime:
+        print "WARNING: The start time you entered [%s]" % startTime.strftime('%Y-%m-%d') + " is after the end time you entered [%s]." % endTime.strftime('%Y-%m-%d')
+        startTime = getStartEndTimes("start", startOverLapTime, endOverLapTime)
+        endTime = getStartEndTimes("end", startOverLapTime, endOverLapTime)
+
+    return startTime, endTime
+
+
+def reshapeMonthlyData(dataset1):
+    """
+    Purpose::
+       Returns a view of an array with shape (nMonth, ...)
+       reshaped to (nYR, 12, ...) in order to assist in monthly
+       calculations
+    Input::
+       dataset1 - an input array with the first dimension corresponding
+       to the number of months, which must be a multiple of 12
+    Output::
+       data - A view of dataset1 but with shape (nYR, 12, ...).
+    """
+
+    # Create a view of dataset1. This lets us change the shape
+    # without copying or modifying the original array.
+    data = dataset1[:]
+    ishape = data.shape
+    nMonth = ishape[0]
+    nshape = nMonth/12, 12
+
+    # Combine the number of years / months (nshape) with other dimensions
+    data.shape = tuple(list(nshape) + list(ishape[1:]))
+    return data
+
+
+def select_timOpt():
+    #---------------------------------------------
+    # Interacrively select the time scale to be evaluated
+    # e.g., the means over annual, seasonal, monthly, or a specified period (e.g., JJAS for Indian monsoon)
+    #------------------------------------------------------------------------------------
+    print 'Select the time-mean properties to be evaluated: Enter'
+    timeOption = \
+      int(raw_input('1=annual, 2=seasonal (define "season", e.g., JJAS for Indian monsoon), 3=monthly \n> '))
+    return timeOption
+
+def select_data(nDat, Times, List, sourceDat):
+    #---------------------------------------------
+    # Interacrively select a model or models for evaluation
+    #----------------------------------------------------------------------------
+    print '-----------------------------------------------'
+    if sourceDat == 'mdl':
+        print 'mdlID  mdlName numMOs  mdlStartTime mdlEndTime fileName'
+    elif sourceDat == 'obs':
+        print 'obsID  obsName obsMOs  obsStartTime obsEndTime fileName'
+    else:
+        print 'not valid data source: CRASH and restart'
+        sys.exit()
+    print '-----------------------------------------------'
+
+    for n in np.arange(len(List)):
+        print n, List[n], Times[0], Times[-1]
+        n += 1
+    print '-----------------------------------------------'
+    if sourceDat == 'mdl':
+        ask = 'Enter the model ID to be evaluated. -9 for all models (-9 is not active yet): \n'
+    elif sourceDat == 'obs':
+        ask = 'Enter the obs ID to be evaluated. -9 for all models (-9 is not active yet): \n'
+    datSelect = int(raw_input(ask))
+    if datSelect > nDat - 1:
+        print 'Data ID out of range: CRASH'
+        sys.exit()
+    return datSelect
+
+def select_data_combined(nDat, Times, List, datType):
+    '''
+    # Interacrively select a model or models for evaluation
+    '''
+    nT = len(Times)
+    print '-------------------------------------------------------'
+    print 'datID  datName numStp  datStartTime datEndTime dataName'
+    print '-------------------------------------------------------'
+    for n in np.arange(nDat):
+        print n, List[n], nT, Times[0], Times[nT-1], List[n]
+        n+=1
+    print '-----------------------------------------------'
+    if datType == 'ref':
+        ask = 'Enter the reference data ID.: \n'
+    elif datType == 'mdl':
+        ask = 'Enter the data ID to be evaluated. -1 for all models, -2 for all models + obs, -3 for all obs, -4 for any combinations: \n'
+    datSelect = int(raw_input(ask))
+    if datSelect > nDat-1:
+        print 'Data ID out of range: CRASH'
+        sys.exit()
+    return datSelect
+
+def select_metrics(mdlSelect):
+    #---------------------------------------------
+    # Interacrively select an evaluation metric
+    # Input : none
+    # Output: metricOption, the indicator for selecting the metric to be calculated
+    #------------------------------------------------------------------------------
+    print 'Metric options'
+    print '[0] Bias: mean bias over the full time range'
+    print '[1] Mean absolute error over the full time range'
+    print '[2] Temporal anomaly correlation: Eval local interannual variability'
+    print '[3] Temporal correlation: Eval localinterannual variability'
+    print '[5] Spatial correlation between the REF and model climatology: a single correlation coeff'
+    print '[6] RMSE in time over the entire time step values: Eval local interannual variability'
+    print '[7] RMSE between the REF and model climatology: a single correlation coeff'
+    print '[8] Taylor diagram for spatial variability'
+    if mdlSelect == -1 or mdlSelect == -3:
+        print '[10] Signal-2-Noise ratio'
+
+    choice = int(raw_input('Please make a selection from the options above\n> '))
+    # assign the evaluation metric to be calculated
+    if choice == 0:
+        metricOption = 'BIAS'
+    elif choice == 1:
+        metricOption = 'MAE'
+    elif choice == 2:
+        metricOption = 'ACt'
+    elif choice == 3:
+        metricOption = 'PCt'
+    elif choice == 4:
+        metricOption = 'ACs'
+    elif choice == 5:
+        metricOption = 'PCs'
+    elif choice == 6:
+        metricOption = 'RMSt'
+    elif choice == 7:
+        metricOption = 'RMSs'
+    elif choice == 8:
+        metricOption = 'Taylor_space'
+    elif choice == 9:
+        metricOption = 'CV'
+    elif choice ==10:
+        metricOption = 'S2N'
+    print 'in subroutine metricOption = ', metricOption
+    return metricOption
+

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/rcmes/utils/misc.pyc
----------------------------------------------------------------------
diff --git a/src/main/python/rcmes/utils/misc.pyc b/src/main/python/rcmes/utils/misc.pyc
new file mode 100644
index 0000000..567a153
Binary files /dev/null and b/src/main/python/rcmes/utils/misc.pyc differ

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/resources/.svn/all-wcprops
----------------------------------------------------------------------
diff --git a/src/main/resources/.svn/all-wcprops b/src/main/resources/.svn/all-wcprops
new file mode 100755
index 0000000..5eccd5a
--- /dev/null
+++ b/src/main/resources/.svn/all-wcprops
@@ -0,0 +1,23 @@
+K 25
+svn:wc:ra_dav:version-url
+V 76
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/resources
+END
+rcmet_use_case.txt
+K 25
+svn:wc:ra_dav:version-url
+V 95
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/resources/rcmet_use_case.txt
+END
+pyLintRcFile.txt
+K 25
+svn:wc:ra_dav:version-url
+V 93
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/resources/pyLintRcFile.txt
+END
+PyLintREADME.txt
+K 25
+svn:wc:ra_dav:version-url
+V 93
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/resources/PyLintREADME.txt
+END

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/resources/.svn/entries
----------------------------------------------------------------------
diff --git a/src/main/resources/.svn/entries b/src/main/resources/.svn/entries
new file mode 100755
index 0000000..44d8d73
--- /dev/null
+++ b/src/main/resources/.svn/entries
@@ -0,0 +1,130 @@
+10
+
+dir
+1485921
+https://svn.apache.org/repos/asf/incubator/climate/trunk/rcmet/src/main/resources
+https://svn.apache.org/repos/asf
+
+
+
+2012-08-20T14:54:20.638728Z
+1473898
+cgoodale
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+13f79535-47bb-0310-9956-ffa450edef68
+
+rcmet_use_case.txt
+file
+
+
+
+
+2013-05-24T10:13:55.000000Z
+5cf459bbc71cdb7f06171d213fe6614a
+2011-12-13T03:57:45.293099Z
+1471825
+mattmann
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+1938
+
+pyLintRcFile.txt
+file
+
+
+
+
+2013-05-24T10:13:55.000000Z
+257762042464ce3e986a053cc1071128
+2012-08-07T16:49:27.568534Z
+1473820
+cgoodale
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+7293
+
+PyLintREADME.txt
+file
+
+
+
+
+2013-05-24T10:13:55.000000Z
+5705ddf0db60fc83053b83316ea7b6fc
+2012-08-20T14:54:20.638728Z
+1473898
+cgoodale
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+1272
+

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/resources/.svn/text-base/PyLintREADME.txt.svn-base
----------------------------------------------------------------------
diff --git a/src/main/resources/.svn/text-base/PyLintREADME.txt.svn-base b/src/main/resources/.svn/text-base/PyLintREADME.txt.svn-base
new file mode 100755
index 0000000..3214791
--- /dev/null
+++ b/src/main/resources/.svn/text-base/PyLintREADME.txt.svn-base
@@ -0,0 +1,26 @@
+OVERVIEW:
+
+The code within RCMES has been linted using a project specific set of parameters.  We have blended Python's PEP-8
+while also including some Java formatting (namely camelCase instead of underscores).
+
+You don't really need to know all the particulars, but if you are curious you can look at the pyLintRcFile.txt in 
+this directory for full details.
+
+
+HOW TO LINT THE CODE:
+
+If you are contributing to this code base then you will need to comply with the code convention standards set forth
+by the project team.  We have used PyLint to check for code correctness, and the included pyLintRcFile.txt can be
+used with PyLint (http://pypi.python.org/pypi/pylint/).
+
+After you have installed pylint follow these directions.  Happy linting!
+
+Assuming you want to lint the metrics.py file within lib/rcmes, do the following
+
+$> cd rcmes/rcmet/src/main/python/rcmes
+$> pylint --rcfile=../../resources/pyLintRcFile.txt cli/rcmet_ui.py
+
+You will be presented with a Report of any Warnings, Conventions, Errors, or Refactoring opportunities as well as
+variable name conventions, etc..  For more about the meaning of the report look up the PyLint documentation online.
+
+This will help the team keep the codebase clean and consistent as multiple team members contribute code.

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/resources/.svn/text-base/pyLintRcFile.txt.svn-base
----------------------------------------------------------------------
diff --git a/src/main/resources/.svn/text-base/pyLintRcFile.txt.svn-base b/src/main/resources/.svn/text-base/pyLintRcFile.txt.svn-base
new file mode 100755
index 0000000..286dcfe
--- /dev/null
+++ b/src/main/resources/.svn/text-base/pyLintRcFile.txt.svn-base
@@ -0,0 +1,249 @@
+[MASTER]
+
+# Specify a configuration file.
+#rcfile=
+
+# Python code to execute, usually for sys.path manipulation such as
+# pygtk.require().
+#init-hook=
+
+# Profiled execution.
+profile=no
+
+# Add files or directories to the blacklist. They should be base names, not
+# paths.
+ignore=CVS
+
+# Pickle collected data for later comparisons.
+persistent=yes
+
+# List of plugins (as comma separated values of python modules names) to load,
+# usually to register additional checkers.
+load-plugins=
+
+
+[MESSAGES CONTROL]
+
+# Enable the message, report, category or checker with the given id(s). You can
+# either give multiple identifier separated by comma (,) or put this option
+# multiple time.
+#enable=
+
+# Disable the message, report, category or checker with the given id(s). You
+# can either give multiple identifier separated by comma (,) or put this option
+# multiple time (only on the command line, not in the configuration file where
+# it should appear only once).
+#disable=
+
+
+[REPORTS]
+
+# Set the output format. Available formats are text, parseable, colorized, msvs
+# (visual studio) and html
+output-format=text
+
+# Include message's id in output
+include-ids=no
+
+# Put messages in a separate file for each module / package specified on the
+# command line instead of printing them on stdout. Reports (if any) will be
+# written in a file name "pylint_global.[txt|html]".
+files-output=no
+
+# Tells whether to display a full report or only the messages
+reports=yes
+
+# Python expression which should return a note less than 10 (10 is the highest
+# note). You have access to the variables errors warning, statement which
+# respectively contain the number of errors / warnings messages and the total
+# number of statements analyzed. This is used by the global evaluation report
+# (RP0004).
+evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10)
+
+# Add a comment according to your evaluation note. This is used by the global
+# evaluation report (RP0004).
+comment=no
+
+
+[BASIC]
+
+# Required attributes for module, separated by a comma
+required-attributes=
+
+# List of builtins function names that should not be used, separated by a comma
+bad-functions=map,filter,apply,input
+
+# Regular expression which should only match correct module names
+module-rgx=(([a-z][a-z0-9]*)|([A-Z][a-zA-Z0-9]+))$
+
+# Regular expression which should only match correct module level names
+const-rgx=(([A-Z_][A-Z0-9_]*)|(__.*__))$
+
+# Regular expression which should only match correct class names
+class-rgx=[A-Z][a-zA-Z]+$
+
+# Regular expression which should only match correct function names
+function-rgx=[a-z]+[A-Za-z0-9]{2,30}$
+
+# Regular expression which should only match correct method names
+method-rgx=(([a-z]+[A-Za-z0-9]{2,30})|(__.*__))$
+
+# Regular expression which should only match correct instance attribute names
+attr-rgx=[a-z]+[A-Za-z0-9]{2,30}$
+
+# Regular expression which should only match correct argument names
+argument-rgx=[a-z][A-Za-z0-9]{2,30}$
+
+# Regular expression which should only match correct variable names
+variable-rgx=[a-z]+[A-Za-z0-9]{2,30}$
+
+# Regular expression which should only match correct list comprehension /
+# generator expression variable names
+inlinevar-rgx=[A-Za-z][A-Za-z0-9]*$
+
+# Good variable names which should always be accepted, separated by a comma
+good-names=i,j,k,ex,Run,_
+
+# Bad variable names which should always be refused, separated by a comma
+bad-names=foo,bar,baz,toto,tutu,tata
+
+# Regular expression which should only match functions or classes name which do
+# not require a docstring
+no-docstring-rgx=__.*__
+
+
+[FORMAT]
+
+# Maximum number of characters on a single line.
+max-line-length=120
+
+# Maximum number of lines in a module
+max-module-lines=1000
+
+# String used as indentation unit. This is usually " " (4 spaces) or "\t" (1
+# tab).
+indent-string='    '
+
+
+[MISCELLANEOUS]
+
+# List of note tags to take in consideration, separated by a comma.
+notes=FIXME,XXX,TODO
+
+
+[SIMILARITIES]
+
+# Minimum lines number of a similarity.
+min-similarity-lines=4
+
+# Ignore comments when computing similarities.
+ignore-comments=yes
+
+# Ignore docstrings when computing similarities.
+ignore-docstrings=yes
+
+
+[TYPECHECK]
+
+# Tells whether missing members accessed in mixin class should be ignored. A
+# mixin class is detected if its name ends with "mixin" (case insensitive).
+ignore-mixin-members=yes
+
+# List of classes names for which member attributes should not be checked
+# (useful for classes with attributes dynamically set).
+ignored-classes=SQLObject
+
+# When zope mode is activated, add a predefined set of Zope acquired attributes
+# to generated-members.
+zope=no
+
+# List of members which are set dynamically and missed by pylint inference
+# system, and so shouldn't trigger E0201 when accessed. Python regular
+# expressions are accepted.
+generated-members=REQUEST,acl_users,aq_parent
+
+
+[VARIABLES]
+
+# Tells whether we should check for unused import in __init__ files.
+init-import=no
+
+# A regular expression matching the beginning of the name of dummy variables
+# (i.e. not used).
+dummy-variables-rgx=_|dummy
+
+# List of additional names supposed to be defined in builtins. Remember that
+# you should avoid to define new builtins when possible.
+additional-builtins=
+
+
+[CLASSES]
+
+# List of interface methods to ignore, separated by a comma. This is used for
+# instance to not check methods defines in Zope's Interface base class.
+ignore-iface-methods=isImplementedBy,deferred,extends,names,namesAndDescriptions,queryDescriptionFor,getBases,getDescriptionFor,getDoc,getName,getTaggedValue,getTaggedValueTags,isEqualOrExtendedBy,setTaggedValue,isImplementedByInstancesOf,adaptWith,is_implemented_by
+
+# List of method names used to declare (i.e. assign) instance attributes.
+defining-attr-methods=__init__,__new__,setUp
+
+# List of valid names for the first argument in a class method.
+valid-classmethod-first-arg=cls
+
+
+[DESIGN]
+
+# Maximum number of arguments for function / method
+max-args=5
+
+# Argument names that match this expression will be ignored. Default to name
+# with leading underscore
+ignored-argument-names=_.*
+
+# Maximum number of locals for function / method body
+max-locals=15
+
+# Maximum number of return / yield for function / method body
+max-returns=6
+
+# Maximum number of branch for function / method body
+max-branchs=12
+
+# Maximum number of statements in function / method body
+max-statements=50
+
+# Maximum number of parents for a class (see R0901).
+max-parents=7
+
+# Maximum number of attributes for a class (see R0902).
+max-attributes=7
+
+# Minimum number of public methods for a class (see R0903).
+min-public-methods=2
+
+# Maximum number of public methods for a class (see R0904).
+max-public-methods=20
+
+
+[IMPORTS]
+
+# Deprecated modules which should not be used, separated by a comma
+deprecated-modules=regsub,string,TERMIOS,Bastion,rexec
+
+# Create a graph of every (i.e. internal and external) dependencies in the
+# given file (report RP0402 must not be disabled)
+import-graph=
+
+# Create a graph of external dependencies in the given file (report RP0402 must
+# not be disabled)
+ext-import-graph=
+
+# Create a graph of internal dependencies in the given file (report RP0402 must
+# not be disabled)
+int-import-graph=
+
+
+[EXCEPTIONS]
+
+# Exceptions that will emit a warning when being caught. Defaults to
+# "Exception"
+overgeneral-exceptions=Exception

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/resources/.svn/text-base/rcmet_use_case.txt.svn-base
----------------------------------------------------------------------
diff --git a/src/main/resources/.svn/text-base/rcmet_use_case.txt.svn-base b/src/main/resources/.svn/text-base/rcmet_use_case.txt.svn-base
new file mode 100755
index 0000000..41e8e90
--- /dev/null
+++ b/src/main/resources/.svn/text-base/rcmet_use_case.txt.svn-base
@@ -0,0 +1,57 @@
+Regional Climate Modeling Evaluation Toolkit Use Case
+
+User = Scientist
+System = RCMES
+
+Goal:  Compute Metrics on a Local Climate Model
+Main Success Scenario
+1.  User logs into System
+2.  User selects a model file
+3.  User selects model latitude, longitude, time and parameter
+4.  User selects observation datasets and parameters
+5.  System returns the time range information where Obs and Model
+parameters overlap.
+6.  User selects time range.
+7.  System returns VALID re-gridding options for Space and Time.  
+(VALID meaning smaller grid to a larger grid step)
+8.  User selects the re-gridding options
+9.  Optional Processing (SEE OPEN ISSUES SECTION)
+
+
+Extensions:
+1a:  User has no account setup
+	.1:  User will create an account
+	.2:  System will create an upload directory for the account
+	and email instructions about how to FTP the model files into
+	the new directory
+	Main Success Scenario Step 1
+
+2a:  User has no models in the System to choose
+	.1:  User will FTP their model file(s) into their upload directory
+	Main Success Scenario Step 2
+
+# This could be prevented if Step 4 ONLY returns Datasets with a proper
+#  temporal overlap.  This might be an enhancement in the future.
+5a:  The Model and Observational Datasets don't have a time overlap
+	.1:  System will return a message explaining the lack of overlap
+	Main Success Scenario Step 4
+
+
+OPEN QUESTIONS/ISSUES
+
+***Optional Processing***
+Masked Region:  Does this work today?
+Seasonal Cycles:  Does this option work?
+
+User will select the Metric they want to compute.  [Should we consider limiting
+this list based on what is being selected in the model and observations]
+Metrics:
+-Bias: mean bias across full time range
+-Mean Absolute Error: across full time range  
+-Difference: calculated at each time unit
+-Anomaly Correlation
+-Pattern Correlation
+*Probability Distribution Function similarity score
+-Root Mean Square Error
+
+Customize Plots:  Does this work today?  

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/resources/PyLintREADME.txt
----------------------------------------------------------------------
diff --git a/src/main/resources/PyLintREADME.txt b/src/main/resources/PyLintREADME.txt
new file mode 100755
index 0000000..3214791
--- /dev/null
+++ b/src/main/resources/PyLintREADME.txt
@@ -0,0 +1,26 @@
+OVERVIEW:
+
+The code within RCMES has been linted using a project specific set of parameters.  We have blended Python's PEP-8
+while also including some Java formatting (namely camelCase instead of underscores).
+
+You don't really need to know all the particulars, but if you are curious you can look at the pyLintRcFile.txt in 
+this directory for full details.
+
+
+HOW TO LINT THE CODE:
+
+If you are contributing to this code base then you will need to comply with the code convention standards set forth
+by the project team.  We have used PyLint to check for code correctness, and the included pyLintRcFile.txt can be
+used with PyLint (http://pypi.python.org/pypi/pylint/).
+
+After you have installed pylint follow these directions.  Happy linting!
+
+Assuming you want to lint the metrics.py file within lib/rcmes, do the following
+
+$> cd rcmes/rcmet/src/main/python/rcmes
+$> pylint --rcfile=../../resources/pyLintRcFile.txt cli/rcmet_ui.py
+
+You will be presented with a Report of any Warnings, Conventions, Errors, or Refactoring opportunities as well as
+variable name conventions, etc..  For more about the meaning of the report look up the PyLint documentation online.
+
+This will help the team keep the codebase clean and consistent as multiple team members contribute code.

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/resources/pyLintRcFile.txt
----------------------------------------------------------------------
diff --git a/src/main/resources/pyLintRcFile.txt b/src/main/resources/pyLintRcFile.txt
new file mode 100755
index 0000000..286dcfe
--- /dev/null
+++ b/src/main/resources/pyLintRcFile.txt
@@ -0,0 +1,249 @@
+[MASTER]
+
+# Specify a configuration file.
+#rcfile=
+
+# Python code to execute, usually for sys.path manipulation such as
+# pygtk.require().
+#init-hook=
+
+# Profiled execution.
+profile=no
+
+# Add files or directories to the blacklist. They should be base names, not
+# paths.
+ignore=CVS
+
+# Pickle collected data for later comparisons.
+persistent=yes
+
+# List of plugins (as comma separated values of python modules names) to load,
+# usually to register additional checkers.
+load-plugins=
+
+
+[MESSAGES CONTROL]
+
+# Enable the message, report, category or checker with the given id(s). You can
+# either give multiple identifier separated by comma (,) or put this option
+# multiple time.
+#enable=
+
+# Disable the message, report, category or checker with the given id(s). You
+# can either give multiple identifier separated by comma (,) or put this option
+# multiple time (only on the command line, not in the configuration file where
+# it should appear only once).
+#disable=
+
+
+[REPORTS]
+
+# Set the output format. Available formats are text, parseable, colorized, msvs
+# (visual studio) and html
+output-format=text
+
+# Include message's id in output
+include-ids=no
+
+# Put messages in a separate file for each module / package specified on the
+# command line instead of printing them on stdout. Reports (if any) will be
+# written in a file name "pylint_global.[txt|html]".
+files-output=no
+
+# Tells whether to display a full report or only the messages
+reports=yes
+
+# Python expression which should return a note less than 10 (10 is the highest
+# note). You have access to the variables errors warning, statement which
+# respectively contain the number of errors / warnings messages and the total
+# number of statements analyzed. This is used by the global evaluation report
+# (RP0004).
+evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10)
+
+# Add a comment according to your evaluation note. This is used by the global
+# evaluation report (RP0004).
+comment=no
+
+
+[BASIC]
+
+# Required attributes for module, separated by a comma
+required-attributes=
+
+# List of builtins function names that should not be used, separated by a comma
+bad-functions=map,filter,apply,input
+
+# Regular expression which should only match correct module names
+module-rgx=(([a-z][a-z0-9]*)|([A-Z][a-zA-Z0-9]+))$
+
+# Regular expression which should only match correct module level names
+const-rgx=(([A-Z_][A-Z0-9_]*)|(__.*__))$
+
+# Regular expression which should only match correct class names
+class-rgx=[A-Z][a-zA-Z]+$
+
+# Regular expression which should only match correct function names
+function-rgx=[a-z]+[A-Za-z0-9]{2,30}$
+
+# Regular expression which should only match correct method names
+method-rgx=(([a-z]+[A-Za-z0-9]{2,30})|(__.*__))$
+
+# Regular expression which should only match correct instance attribute names
+attr-rgx=[a-z]+[A-Za-z0-9]{2,30}$
+
+# Regular expression which should only match correct argument names
+argument-rgx=[a-z][A-Za-z0-9]{2,30}$
+
+# Regular expression which should only match correct variable names
+variable-rgx=[a-z]+[A-Za-z0-9]{2,30}$
+
+# Regular expression which should only match correct list comprehension /
+# generator expression variable names
+inlinevar-rgx=[A-Za-z][A-Za-z0-9]*$
+
+# Good variable names which should always be accepted, separated by a comma
+good-names=i,j,k,ex,Run,_
+
+# Bad variable names which should always be refused, separated by a comma
+bad-names=foo,bar,baz,toto,tutu,tata
+
+# Regular expression which should only match functions or classes name which do
+# not require a docstring
+no-docstring-rgx=__.*__
+
+
+[FORMAT]
+
+# Maximum number of characters on a single line.
+max-line-length=120
+
+# Maximum number of lines in a module
+max-module-lines=1000
+
+# String used as indentation unit. This is usually " " (4 spaces) or "\t" (1
+# tab).
+indent-string='    '
+
+
+[MISCELLANEOUS]
+
+# List of note tags to take in consideration, separated by a comma.
+notes=FIXME,XXX,TODO
+
+
+[SIMILARITIES]
+
+# Minimum lines number of a similarity.
+min-similarity-lines=4
+
+# Ignore comments when computing similarities.
+ignore-comments=yes
+
+# Ignore docstrings when computing similarities.
+ignore-docstrings=yes
+
+
+[TYPECHECK]
+
+# Tells whether missing members accessed in mixin class should be ignored. A
+# mixin class is detected if its name ends with "mixin" (case insensitive).
+ignore-mixin-members=yes
+
+# List of classes names for which member attributes should not be checked
+# (useful for classes with attributes dynamically set).
+ignored-classes=SQLObject
+
+# When zope mode is activated, add a predefined set of Zope acquired attributes
+# to generated-members.
+zope=no
+
+# List of members which are set dynamically and missed by pylint inference
+# system, and so shouldn't trigger E0201 when accessed. Python regular
+# expressions are accepted.
+generated-members=REQUEST,acl_users,aq_parent
+
+
+[VARIABLES]
+
+# Tells whether we should check for unused import in __init__ files.
+init-import=no
+
+# A regular expression matching the beginning of the name of dummy variables
+# (i.e. not used).
+dummy-variables-rgx=_|dummy
+
+# List of additional names supposed to be defined in builtins. Remember that
+# you should avoid to define new builtins when possible.
+additional-builtins=
+
+
+[CLASSES]
+
+# List of interface methods to ignore, separated by a comma. This is used for
+# instance to not check methods defines in Zope's Interface base class.
+ignore-iface-methods=isImplementedBy,deferred,extends,names,namesAndDescriptions,queryDescriptionFor,getBases,getDescriptionFor,getDoc,getName,getTaggedValue,getTaggedValueTags,isEqualOrExtendedBy,setTaggedValue,isImplementedByInstancesOf,adaptWith,is_implemented_by
+
+# List of method names used to declare (i.e. assign) instance attributes.
+defining-attr-methods=__init__,__new__,setUp
+
+# List of valid names for the first argument in a class method.
+valid-classmethod-first-arg=cls
+
+
+[DESIGN]
+
+# Maximum number of arguments for function / method
+max-args=5
+
+# Argument names that match this expression will be ignored. Default to name
+# with leading underscore
+ignored-argument-names=_.*
+
+# Maximum number of locals for function / method body
+max-locals=15
+
+# Maximum number of return / yield for function / method body
+max-returns=6
+
+# Maximum number of branch for function / method body
+max-branchs=12
+
+# Maximum number of statements in function / method body
+max-statements=50
+
+# Maximum number of parents for a class (see R0901).
+max-parents=7
+
+# Maximum number of attributes for a class (see R0902).
+max-attributes=7
+
+# Minimum number of public methods for a class (see R0903).
+min-public-methods=2
+
+# Maximum number of public methods for a class (see R0904).
+max-public-methods=20
+
+
+[IMPORTS]
+
+# Deprecated modules which should not be used, separated by a comma
+deprecated-modules=regsub,string,TERMIOS,Bastion,rexec
+
+# Create a graph of every (i.e. internal and external) dependencies in the
+# given file (report RP0402 must not be disabled)
+import-graph=
+
+# Create a graph of external dependencies in the given file (report RP0402 must
+# not be disabled)
+ext-import-graph=
+
+# Create a graph of internal dependencies in the given file (report RP0402 must
+# not be disabled)
+int-import-graph=
+
+
+[EXCEPTIONS]
+
+# Exceptions that will emit a warning when being caught. Defaults to
+# "Exception"
+overgeneral-exceptions=Exception

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/resources/rcmet_use_case.txt
----------------------------------------------------------------------
diff --git a/src/main/resources/rcmet_use_case.txt b/src/main/resources/rcmet_use_case.txt
new file mode 100755
index 0000000..41e8e90
--- /dev/null
+++ b/src/main/resources/rcmet_use_case.txt
@@ -0,0 +1,57 @@
+Regional Climate Modeling Evaluation Toolkit Use Case
+
+User = Scientist
+System = RCMES
+
+Goal:  Compute Metrics on a Local Climate Model
+Main Success Scenario
+1.  User logs into System
+2.  User selects a model file
+3.  User selects model latitude, longitude, time and parameter
+4.  User selects observation datasets and parameters
+5.  System returns the time range information where Obs and Model
+parameters overlap.
+6.  User selects time range.
+7.  System returns VALID re-gridding options for Space and Time.  
+(VALID meaning smaller grid to a larger grid step)
+8.  User selects the re-gridding options
+9.  Optional Processing (SEE OPEN ISSUES SECTION)
+
+
+Extensions:
+1a:  User has no account setup
+	.1:  User will create an account
+	.2:  System will create an upload directory for the account
+	and email instructions about how to FTP the model files into
+	the new directory
+	Main Success Scenario Step 1
+
+2a:  User has no models in the System to choose
+	.1:  User will FTP their model file(s) into their upload directory
+	Main Success Scenario Step 2
+
+# This could be prevented if Step 4 ONLY returns Datasets with a proper
+#  temporal overlap.  This might be an enhancement in the future.
+5a:  The Model and Observational Datasets don't have a time overlap
+	.1:  System will return a message explaining the lack of overlap
+	Main Success Scenario Step 4
+
+
+OPEN QUESTIONS/ISSUES
+
+***Optional Processing***
+Masked Region:  Does this work today?
+Seasonal Cycles:  Does this option work?
+
+User will select the Metric they want to compute.  [Should we consider limiting
+this list based on what is being selected in the model and observations]
+Metrics:
+-Bias: mean bias across full time range
+-Mean Absolute Error: across full time range  
+-Difference: calculated at each time unit
+-Anomaly Correlation
+-Pattern Correlation
+*Probability Distribution Function similarity score
+-Root Mean Square Error
+
+Customize Plots:  Does this work today?  

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/.svn/all-wcprops
----------------------------------------------------------------------
diff --git a/src/main/ui/.svn/all-wcprops b/src/main/ui/.svn/all-wcprops
new file mode 100755
index 0000000..ce14d32
--- /dev/null
+++ b/src/main/ui/.svn/all-wcprops
@@ -0,0 +1,5 @@
+K 25
+svn:wc:ra_dav:version-url
+V 69
+/repos/asf/!svn/ver/1485460/incubator/climate/trunk/rcmet/src/main/ui
+END

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/.svn/entries
----------------------------------------------------------------------
diff --git a/src/main/ui/.svn/entries b/src/main/ui/.svn/entries
new file mode 100755
index 0000000..94f8e47
--- /dev/null
+++ b/src/main/ui/.svn/entries
@@ -0,0 +1,43 @@
+10
+
+dir
+1485921
+https://svn.apache.org/repos/asf/incubator/climate/trunk/rcmet/src/main/ui
+https://svn.apache.org/repos/asf
+
+
+
+2013-05-22T22:03:47.963281Z
+1485460
+joyce
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+13f79535-47bb-0310-9956-ffa450edef68
+
+test
+dir
+
+app
+dir
+
+logs
+dir
+
+config
+dir
+
+scripts
+dir
+

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/app/.svn/all-wcprops
----------------------------------------------------------------------
diff --git a/src/main/ui/app/.svn/all-wcprops b/src/main/ui/app/.svn/all-wcprops
new file mode 100755
index 0000000..078bda7
--- /dev/null
+++ b/src/main/ui/app/.svn/all-wcprops
@@ -0,0 +1,17 @@
+K 25
+svn:wc:ra_dav:version-url
+V 73
+/repos/asf/!svn/ver/1485460/incubator/climate/trunk/rcmet/src/main/ui/app
+END
+index-async.html
+K 25
+svn:wc:ra_dav:version-url
+V 90
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/ui/app/index-async.html
+END
+index.html
+K 25
+svn:wc:ra_dav:version-url
+V 84
+/repos/asf/!svn/ver/1485460/incubator/climate/trunk/rcmet/src/main/ui/app/index.html
+END

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/app/.svn/entries
----------------------------------------------------------------------
diff --git a/src/main/ui/app/.svn/entries b/src/main/ui/app/.svn/entries
new file mode 100755
index 0000000..e1aad1a
--- /dev/null
+++ b/src/main/ui/app/.svn/entries
@@ -0,0 +1,114 @@
+10
+
+dir
+1485921
+https://svn.apache.org/repos/asf/incubator/climate/trunk/rcmet/src/main/ui/app
+https://svn.apache.org/repos/asf
+
+
+
+2013-05-22T22:03:47.963281Z
+1485460
+joyce
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+13f79535-47bb-0310-9956-ffa450edef68
+
+partials
+dir
+
+index-async.html
+file
+
+
+
+
+2013-05-24T10:13:57.000000Z
+8565c9caf97406d346e86a8c454817d4
+2013-03-13T02:34:30.834306Z
+1475137
+mjjoyce
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+3325
+
+font
+dir
+
+lib
+dir
+
+css
+dir
+
+index.html
+file
+
+
+
+
+2013-05-24T10:13:57.000000Z
+5c1939c7b64d794f86d9ec7dc2f87c13
+2013-05-22T22:03:47.963281Z
+1485460
+joyce
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+7124
+
+img
+dir
+
+js
+dir
+

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/app/.svn/prop-base/index-async.html.svn-base
----------------------------------------------------------------------
diff --git a/src/main/ui/app/.svn/prop-base/index-async.html.svn-base b/src/main/ui/app/.svn/prop-base/index-async.html.svn-base
new file mode 100755
index 0000000..869ac71
--- /dev/null
+++ b/src/main/ui/app/.svn/prop-base/index-async.html.svn-base
@@ -0,0 +1,5 @@
+K 14
+svn:executable
+V 1
+*
+END

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/app/.svn/prop-base/index.html.svn-base
----------------------------------------------------------------------
diff --git a/src/main/ui/app/.svn/prop-base/index.html.svn-base b/src/main/ui/app/.svn/prop-base/index.html.svn-base
new file mode 100755
index 0000000..869ac71
--- /dev/null
+++ b/src/main/ui/app/.svn/prop-base/index.html.svn-base
@@ -0,0 +1,5 @@
+K 14
+svn:executable
+V 1
+*
+END

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/app/.svn/text-base/index-async.html.svn-base
----------------------------------------------------------------------
diff --git a/src/main/ui/app/.svn/text-base/index-async.html.svn-base b/src/main/ui/app/.svn/text-base/index-async.html.svn-base
new file mode 100755
index 0000000..b530660
--- /dev/null
+++ b/src/main/ui/app/.svn/text-base/index-async.html.svn-base
@@ -0,0 +1,57 @@
+<!doctype html>
+<html lang="en">
+<head>
+  <meta charset="utf-8">
+  <style>
+    [ng-cloak] {
+      display: none;
+    }
+  </style>
+  <script>
+    // include angular loader, which allows the files to load in any order
+    /*
+     AngularJS v1.0.0rc1
+     (c) 2010-2012 AngularJS http://angularjs.org
+     License: MIT
+    */
+    'use strict';(function(i){function d(c,a,e){return c[a]||(c[a]=e())}return d(d(i,"angular",Object),"module",function(){var c={};return function(a,e,f){e&&c.hasOwnProperty(a)&&(c[a]=null);return d(c,a,function(){function b(a,b,d){return function(){c[d||"push"]([a,b,arguments]);return g}}if(!e)throw Error("No module: "+a);var c=[],d=[],h=b("$injector","invoke"),g={_invokeQueue:c,_runBlocks:d,requires:e,name:a,provider:b("$provide","provider"),factory:b("$provide","factory"),service:b("$provide","service"),
+    value:b("$provide","value"),constant:b("$provide","constant","unshift"),filter:b("$filterProvider","register"),directive:b("$compileProvider","directive"),config:h,run:function(a){d.push(a);return this}};f&&h(f);return g})}})})(window);
+
+    // include a third-party async loader library
+    /*!
+     * $script.js v1.3
+     * https://github.com/ded/script.js
+     * Copyright: @ded & @fat - Dustin Diaz, Jacob Thornton 2011
+     * Follow our software http://twitter.com/dedfat
+     * License: MIT
+     */
+    !function(a,b,c){function t(a,c){var e=b.createElement("script"),f=j;e.onload=e.onerror=e[o]=function(){e[m]&&!/^c|loade/.test(e[m])||f||(e.onload=e[o]=null,f=1,c())},e.async=1,e.src=a,d.insertBefore(e,d.firstChild)}function q(a,b){p(a,function(a){return!b(a)})}var d=b.getElementsByTagName("head")[0],e={},f={},g={},h={},i="string",j=!1,k="push",l="DOMContentLoaded",m="readyState",n="addEventListener",o="onreadystatechange",p=function(a,b){for(var c=0,d=a.length;c<d;++c)if(!b(a[c]))return j;return 1};!b[m]&&b[n]&&(b[n](l,function r(){b.removeEventListener(l,r,j),b[m]="complete"},j),b[m]="loading");var s=function(a,b,d){function o(){if(!--m){e[l]=1,j&&j();for(var a in g)p(a.split("|"),n)&&!q(g[a],n)&&(g[a]=[])}}function n(a){return a.call?a():e[a]}a=a[k]?a:[a];var i=b&&b.call,j=i?b:d,l=i?a.join(""):b,m=a.length;c(function(){q(a,function(a){h[a]?(l&&(f[l]=1),o()):(h[a]=1,l&&(f[l]=1),t(s.path?s.path+a+".js":a,o))})},0);return s};s.get=t,s.ready=function(a,b,c){a=a[k]?a:[a];var d=[];
 !q(a,function(a){e[a]||d[k](a)})&&p(a,function(a){return e[a]})?b():!function(a){g[a]=g[a]||[],g[a][k](b),c&&c(d)}(a.join("|"));return s};var u=a.$script;s.noConflict=function(){a.$script=u;return this},typeof module!="undefined"&&module.exports?module.exports=s:a.$script=s}(this,document,setTimeout)
+
+    // load all of the dependencies asynchronously.
+    $script([
+      'lib/angular/angular.js',
+      'js/app.js',
+      'js/services.js',
+      'js/controllers.js',
+      'js/filters.js',
+      'js/directives.js'
+    ], function() {
+      // when all is done, execute bootstrap angular application
+      angular.bootstrap(document, ['myApp']);
+    });
+  </script>
+  <title>My AngularJS App</title>
+  <link rel="stylesheet" href="css/app.css">
+</head>
+<body ng-cloak>
+  <ul class="menu">
+    <li><a href="#/view1">view1</a></li>
+    <li><a href="#/view2">view2</a></li>
+  </ul>
+
+  <div ng-view></div>
+
+  <div>Angular seed app: v<span app-version></span></div>
+
+</body>
+</html>


[41/51] [abbrv] [partial] Adding Jinwon's custom RCMET

Posted by jo...@apache.org.
http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/rcmes/toolkit/.svn/text-base/process.py.svn-base
----------------------------------------------------------------------
diff --git a/src/main/python/rcmes/toolkit/.svn/text-base/process.py.svn-base b/src/main/python/rcmes/toolkit/.svn/text-base/process.py.svn-base
new file mode 100755
index 0000000..b5dde08
--- /dev/null
+++ b/src/main/python/rcmes/toolkit/.svn/text-base/process.py.svn-base
@@ -0,0 +1,1263 @@
+"""Collection of functions that process numpy arrays of varying shapes.  
+Functions can range from subsetting to regridding"""
+
+# Python Standard Libary Imports
+import math
+import datetime
+import re
+import string
+import sys
+import time
+
+# 3rd Party Imports
+import Nio
+import numpy as np
+import numpy.ma as ma
+from scipy.ndimage import map_coordinates
+
+
+def extract_subregion_from_data_array(data, lats, lons, latmin, latmax, lonmin, lonmax):
+    '''
+     Extract a sub-region from a data array.
+     
+     Example::
+       **e.g.** the user may load a global model file, but only want to examine data over North America
+            This function extracts a sub-domain from the original data.
+            The defined sub-region must be a regular lat/lon bounding box,
+            but the model data may be on a non-regular grid (e.g. rotated, or Guassian grid layout).
+            Data are kept on the original model grid and a rectangular (in model-space) region 
+            is extracted which contains the rectangular (in lat/lon space) user supplied region.
+    
+     INPUT::
+       data - 3d masked data array
+       lats - 2d array of latitudes corresponding to data array
+       lons - 2d array of longitudes corresponding to data array
+       latmin, latmax, lonmin, lonmax - bounding box of required region to extract
+       
+     OUTPUT::
+       data2 - subset of original data array containing only data from required subregion
+       lats2 - subset of original latitude data array
+       lons2 - subset of original longitude data array
+
+    '''
+    
+    
+
+    # Mask model data array to find grid points inside the supplied bounding box
+    whlat = (lats > latmin) & (lats < latmax)
+    whlon = (lons > lonmin) & (lons < lonmax)
+    wh = whlat & whlon
+
+    # Find required matrix indices describing the limits of the regular lat/lon bounding box
+    jmax = np.where(wh == True)[0].max()
+    jmin = np.where(wh == True)[0].min()
+    imax = np.where(wh == True)[1].max()
+    imin = np.where(wh == True)[1].min()
+
+    # Cut out the sub-region from the data array
+    data2 = ma.zeros((data.shape[0], jmax - jmin, imax - imin))
+    data2 = data[:, jmin:jmax, imin:imax]
+
+    # Cut out sub-region from lats,lons arrays
+    lats2 = lats[jmin:jmax, imin:imax]
+    lons2 = lons[jmin:jmax, imin:imax]
+
+    return data2, lats2, lons2
+
+def calc_area_mean(data, lats, lons, mymask='not set'):
+    '''
+     Calculate Area Average of data in a masked array
+     
+     INPUT::
+         data:  a masked array of data (NB. only data from one time expected to be passed at once)
+         lats:  2d array of regularly gridded latitudes
+         lons:  2d array of regularly gridded longitudes
+         mymask:  (optional) defines spatial region to do averaging over
+     
+     OUTPUT::
+         area_mean: a value for the mean inside the area
+
+    '''
+    
+    
+
+    # If mask not passed in, then set maks to cover whole data domain
+    if(mymask == 'not set'):
+       mymask = np.empty(data.shape)
+       mymask[:] = False	# NB. mask means (don't show), so False everywhere means use everything.
+   
+    # Dimension check on lats, lons
+    #  Sometimes these arrays are 3d, sometimes 2d, sometimes 1d
+    #  This bit of code just converts to the required 2d array shape
+    if(len(lats.shape) == 3):
+       lats = lats[0, :, :]
+
+    if(len(lons.shape) == 3):
+       lons = lons[0, :, :]
+
+    if(np.logical_and(len(lats.shape) == 1, len(lons.shape) == 1)):
+       lons, lats = np.meshgrid(lons, lats)
+ 
+    # Calculate grid length (assuming regular lat/lon grid)
+    dlat = lats[1, 0] - lats[0, 0]
+    dlon = lons[0, 1] - lons[0, 0]
+
+    # Calculates weights for each grid box
+    myweights = calc_area_in_grid_box(lats, dlon, dlat)
+
+    # Create a new masked array covering just user selected area (defined in mymask)
+    #   NB. this preserves missing data points in the observations data
+    subdata = ma.masked_array(data, mask=mymask)
+ 
+    if(myweights.shape != subdata.shape):
+       myweights.resize(subdata.shape)
+       myweights[1:, :] = myweights[0, :]
+
+    # Calculate weighted mean using ma.average (which takes weights)
+    area_mean = ma.average(subdata, weights=myweights)
+ 
+    return area_mean
+
+def calc_area_in_grid_box(latitude, dlat, dlon):
+    '''
+     Calculate area of regular lat-lon grid box
+     
+     INPUT::
+        latitude: latitude of grid box (degrees)
+        dlat:     grid length in latitude direction (degrees)
+        dlon:     grid length in longitude direction (degrees)
+        
+     OUTPUT::
+        A:        area of the grid box
+      
+      '''
+
+    R = 6371000  # radius of Earth in metres
+    C = 2 * math.pi * R
+
+    latitude = np.radians(latitude)
+
+    A = (dlon * (C / 360.)) * (dlat * (C / 360.) * np.cos(latitude))
+
+    return A
+
+def do_regrid(q, lat, lon, lat2, lon2, order=1, mdi= -999999999):
+    '''
+     Perform regridding from one set of lat,lon values onto a new set (lat2,lon2)
+    
+     Input::
+         q          - the variable to be regridded
+         lat,lon    - original co-ordinates corresponding to q values
+         lat2,lon2  - new set of latitudes and longitudes that you want to regrid q onto 
+         order      - (optional) interpolation order 1=bi-linear, 3=cubic spline
+         mdi  	    - (optional) fill value for missing data (used in creation of masked array)
+      
+     Output::
+         q2  - q regridded onto the new set of lat2,lon2 
+    
+    '''
+
+    nlat = q.shape[0]
+    nlon = q.shape[1]
+
+    nlat2 = lat2.shape[0]
+    nlon2 = lon2.shape[1]
+
+    # To make our lives easier down the road, let's 
+    # turn these into arrays of x & y coords
+    loni = lon2.ravel()
+    lati = lat2.ravel()
+
+    loni = loni.copy() # NB. it won't run unless you do this...
+    lati = lati.copy()
+
+    # Now, we'll set points outside the boundaries to lie along an edge
+    loni[loni > lon.max()] = lon.max()
+    loni[loni < lon.min()] = lon.min()
+    
+    # To deal with the "hard" break, we'll have to treat y differently,
+    # so we're just setting the min here...
+    lati[lati > lat.max()] = lat.max()
+    lati[lati < lat.min()] = lat.min()
+    
+    
+    # We need to convert these to (float) indicies
+    #   (xi should range from 0 to (nx - 1), etc)
+    loni = (nlon - 1) * (loni - lon.min()) / (lon.max() - lon.min())
+    
+    # Deal with the "hard" break in the y-direction
+    lati = (nlat - 1) * (lati - lat.min()) / (lat.max() - lat.min())
+    
+    # Notes on dealing with MDI when regridding data.
+    #  Method adopted here:
+    #    Use bilinear interpolation of data by default (but user can specify other order using order=... in call)
+    #    Perform bilinear interpolation of data, and of mask.
+    #    To be conservative, new grid point which contained some missing data on the old grid is set to missing data.
+    #            -this is achieved by looking for any non-zero interpolated mask values.
+    #    To avoid issues with bilinear interpolation producing strong gradients leading into the MDI,
+    #     set values at MDI points to mean data value so little gradient visible = not ideal, but acceptable for now.
+    
+    # Set values in MDI so that similar to surroundings so don't produce large gradients when interpolating
+    # Preserve MDI mask, by only changing data part of masked array object.
+    for shift in (-1, 1):
+        for axis in (0, 1):
+            q_shifted = np.roll(q, shift=shift, axis=axis)
+            idx = ~q_shifted.mask * q.mask
+            q.data[idx] = q_shifted[idx]
+
+    # Now we actually interpolate
+    # map_coordinates does cubic interpolation by default, 
+    # use "order=1" to preform bilinear interpolation instead...
+    q2 = map_coordinates(q, [lati, loni], order=order)
+    q2 = q2.reshape([nlat2, nlon2])
+
+    # Set values to missing data outside of original domain
+    q2 = ma.masked_array(q2, mask=np.logical_or(np.logical_or(lat2 >= lat.max(), 
+                                                              lat2 <= lat.min()), 
+                                                np.logical_or(lon2 <= lon.min(), 
+                                                              lon2 >= lon.max())))
+    
+    # Make second map using nearest neighbour interpolation -use this to determine locations with MDI and mask these
+    qmdi = np.zeros_like(q)
+    qmdi[q.mask == True] = 1.
+    qmdi[q.mask == False] = 0.
+    qmdi_r = map_coordinates(qmdi, [lati, loni], order=order)
+    qmdi_r = qmdi_r.reshape([nlat2, nlon2])
+    mdimask = (qmdi_r != 0.0)
+    
+    # Combine missing data mask, with outside domain mask define above.
+    q2.mask = np.logical_or(mdimask, q2.mask)
+
+    return q2
+
+def create_mask_using_threshold(masked_array, threshold=0.5):
+   '''
+    Routine to create a mask, depending on the proportion of times with missing data.
+    For each pixel, calculate proportion of times that are missing data,
+    **if** the proportion is above a specified threshold value,
+    then mark the pixel as missing data.
+   
+    Input::
+        masked_array - a numpy masked array of data (assumes time on axis 0, and space on axes 1 and 2).
+        threshold    - (optional) threshold proportion above which a pixel is marked as 'missing data'. 
+        NB. default threshold = 50%
+   
+    Output::
+        mymask       - a numpy array describing the mask. NB. not a masked array, just the mask itself.
+
+   '''
+   
+
+   # try, except used as some model files don't have a full mask, but a single bool
+   #  the except catches this situation and deals with it appropriately.
+   try:
+       nT = masked_array.mask.shape[0]
+
+       # For each pixel, count how many times are masked.
+       nMasked = masked_array.mask[:, :, :].sum(axis=0)
+
+       # Define new mask as when a pixel has over a defined threshold ratio of masked data
+       #   e.g. if the threshold is 75%, and there are 10 times,
+       #        then a pixel will be masked if more than 5 times are masked.
+       mymask = nMasked > (nT * threshold)
+
+   except:
+       mymask = np.zeros_like(masked_array.data[0, :, :])
+
+   return mymask
+
+def calc_average_on_new_time_unit(data, dateList, unit='monthly'):
+   '''
+    Routine to calculate averages on longer time units than the data exists on.
+    
+    Example::
+        If the data is 6-hourly, calculate daily, or monthly means.
+   
+    Input::
+        data     - data values
+        dateList - list of python datetime structures corresponding to data values
+        unit     - string describing time unit to average onto. 
+        *Valid values are: 'monthly', 'daily', 'pentad','annual','decadal'*
+      
+     Output:
+        meanstorem - numpy masked array of data values meaned over required time period
+        newTimesList - a list of python datetime objects representing the data in the new averagin period
+        *NB.* currently set to beginning of averaging period, 
+        **i.e. mean Jan 1st - Jan 31st -> represented as Jan 1st, 00Z.**
+   '''
+
+   # First catch unknown values of time unit passed in by user
+   acceptable = (unit == 'full') | (unit == 'annual') | (unit == 'monthly') | (unit == 'daily') | (unit == 'pentad')
+
+   if not acceptable:
+      print 'Error: unknown unit type selected for time averaging'
+      print '       Please check your code.'
+      return
+
+   # Calculate arrays of years (2007,2007),
+   #                     yearsmonths (200701,200702),
+   #                     or yearmonthdays (20070101,20070102) 
+   #  -depending on user selected averaging period.
+
+   # Year list
+   if unit == 'annual':
+      print 'Calculating annual mean data'
+      timeunits = []
+
+      for i in np.arange(len(dateList)):
+         timeunits.append(str(dateList[i].year))
+
+      timeunits = np.array(timeunits, dtype=int)
+         
+   # YearMonth format list
+   if unit == 'monthly':
+      print 'Calculating monthly mean data'
+      timeunits = []
+
+      for i in np.arange(len(dateList)):
+         timeunits.append(str(dateList[i].year) + str("%02d" % dateList[i].month))
+
+      timeunits = np.array(timeunits, dtype=int)
+
+   # YearMonthDay format list
+   if unit == 'daily':
+      print 'Calculating daily mean data'
+      timeunits = []
+ 
+      for i in np.arange(len(dateList)):
+         timeunits.append(str(dateList[i].year) + str("%02d" % dateList[i].month) + \
+                          str("%02d" % dateList[i].day))
+
+      timeunits = np.array(timeunits, dtype=int)
+
+
+   # TODO: add pentad setting using Julian days?
+
+
+   # Full list: a special case
+   if unit == 'full':
+      print 'Calculating means data over full time range'
+      timeunits = []
+
+      for i in np.arange(len(dateList)):
+         timeunits.append(999)  # i.e. we just want the same value for all times.
+
+      timeunits = np.array(timeunits, dtype=int)
+
+
+
+   # empty list to store new times
+   newTimesList = []
+
+   # Decide whether or not you need to do any time averaging.
+   #   i.e. if data are already on required time unit then just pass data through and 
+   #        calculate and return representative datetimes.
+   processing_required = True
+   if len(timeunits) == (len(np.unique(timeunits))):
+        processing_required = False
+
+   # 1D data arrays, i.e. time series
+   if data.ndim == 1:
+     # Create array to store the resulting data
+     meanstore = np.zeros(len(np.unique(timeunits)))
+  
+     # Calculate the means across each unique time unit
+     i = 0
+     for myunit in np.unique(timeunits):
+       if processing_required:
+         datam = ma.masked_array(data, timeunits != myunit)
+         meanstore[i] = ma.average(datam)
+
+       # construct new times list
+       smyunit = str(myunit)
+       if len(smyunit) == 4:  # YYYY
+        yyyy = int(myunit[0:4])
+        mm = 1
+        dd = 1
+       if len(smyunit) == 6:  # YYYYMM
+        yyyy = int(smyunit[0:4])
+        mm = int(smyunit[4:6])
+        dd = 1
+       if len(smyunit) == 8:  # YYYYMMDD
+        yyyy = int(smyunit[0:4])
+        mm = int(smyunit[4:6])
+        dd = int(smyunit[6:8])
+       if len(smyunit) == 3:  # Full time range
+        # Need to set an appropriate time representing the mid-point of the entire time span
+        dt = dateList[-1] - dateList[0]
+        halfway = dateList[0] + (dt / 2)
+        yyyy = int(halfway.year)
+        mm = int(halfway.month)
+        dd = int(halfway.day)
+  
+       newTimesList.append(datetime.datetime(yyyy, mm, dd, 0, 0, 0, 0))
+       i = i + 1
+
+   # 3D data arrays
+   if data.ndim == 3:
+
+     #datamask = create_mask_using_threshold(data,threshold=0.75)
+
+     # Create array to store the resulting data
+     meanstore = np.zeros([len(np.unique(timeunits)), data.shape[1], data.shape[2]])
+  
+     # Calculate the means across each unique time unit
+     i = 0
+     datamask_store = []
+     for myunit in np.unique(timeunits):
+       if processing_required:
+
+         mask = np.zeros_like(data)
+         mask[timeunits != myunit, :, :] = 1.0
+
+         # Calculate missing data mask within each time unit...
+         datamask_at_this_timeunit = np.zeros_like(data)
+         datamask_at_this_timeunit[:] = create_mask_using_threshold(data[timeunits == myunit, :, :], threshold=0.75)
+         # Store results for masking later
+         datamask_store.append(datamask_at_this_timeunit[0])
+
+         # Calculate means for each pixel in this time unit, ignoring missing data (using masked array).
+         datam = ma.masked_array(data, np.logical_or(mask, datamask_at_this_timeunit))
+         meanstore[i, :, :] = ma.average(datam, axis=0)
+
+       # construct new times list
+       smyunit = str(myunit)
+       if len(smyunit) == 4:  # YYYY
+        yyyy = int(smyunit[0:4])
+        mm = 1
+        dd = 1
+       if len(smyunit) == 6:  # YYYYMM
+        yyyy = int(smyunit[0:4])
+        mm = int(smyunit[4:6])
+        dd = 1
+       if len(smyunit) == 8:  # YYYYMMDD
+        yyyy = int(smyunit[0:4])
+        mm = int(smyunit[4:6])
+        dd = int(smyunit[6:8])
+       if len(smyunit) == 3:  # Full time range
+        # Need to set an appropriate time representing the mid-point of the entire time span
+        dt = dateList[-1] - dateList[0]
+        halfway = dateList[0] + (dt / 2)
+        yyyy = int(halfway.year)
+        mm = int(halfway.month)
+        dd = int(halfway.day)
+
+       newTimesList.append(datetime.datetime(yyyy, mm, dd, 0, 0, 0, 0))
+
+       i += 1
+
+     if not processing_required:
+        meanstorem = data
+
+     if processing_required:
+        # Create masked array (using missing data mask defined above)
+        datamask_store = np.array(datamask_store)
+        meanstorem = ma.masked_array(meanstore, datamask_store)
+
+   return meanstorem, newTimesList
+
+def calc_running_accum_from_period_accum(data):
+    '''
+     Routine to calculate running total accumulations from individual period accumulations.
+     ::
+    
+         e.g.  0,0,1,0,0,2,2,1,0,0
+            -> 0,0,1,1,1,3,5,6,6,6
+    
+     Input::
+          data: numpy array with time in the first axis
+    
+     Output::
+          running_acc: running accumulations
+    
+    '''
+    
+    
+    running_acc = np.zeros_like(data)
+    
+    if(len(data.shape) == 1):
+        running_acc[0] = data[0]
+    
+    if(len(data.shape) > 1):
+        running_acc[0, :] = data[0, :]
+    
+    for i in np.arange(data.shape[0] - 1):
+        if(len(data.shape) == 1):
+            running_acc[i + 1] = running_acc[i] + data[i + 1]
+    
+        if(len(data.shape) > 1):
+            running_acc[i + 1, :] = running_acc[i, :] + data[i + 1, :]
+    
+    return running_acc
+
+def ignore_boundaries(data, rim=10):
+    '''
+     Routine to mask the lateral boundary regions of model data to ignore them from calculations.
+     
+     Input::
+         data - a masked array of model data
+         rim - (optional) number of grid points to ignore
+    
+     Output::
+         data - data array with boundary region masked
+    
+    '''
+    
+    nx = data.shape[1]
+    ny = data.shape[0]
+    
+    rimmask = np.zeros_like(data)
+    for j in np.arange(rim):
+        rimmask[j, 0:nx - 1] = 1.0
+    
+    for j in ny - 1 - np.arange(rim):
+        rimmask[j, 0:nx - 1] = 1.0
+    
+    for i in np.arange(rim):
+        rimmask[0:ny - 1, i] = 1.0
+    
+    for i in nx - 1 - np.arange(rim):
+        rimmask[0:ny - 1, i] = 1.0
+    
+    data = ma.masked_array(data, mask=rimmask)
+    
+    return data
+
+def normalizeDatetimes(datetimes, timestep):
+    """
+    Input::
+        datetimes - list of datetime objects that need to be normalized
+        timestep - string of value ('daily' | 'monthly')
+    Output::
+        normalDatetimes - list of datetime objects that have been normalized
+    
+    Normalization Rules::
+        Daily data will be forced to an hour value of 00:00:00
+        Monthly data will be forced to the first of the month at midnight 
+    """
+    normalDatetimes = []
+    if timestep.lower() == 'monthly':
+        for inputDatetime in datetimes:
+            if inputDatetime.day != 1:
+                # Clean the inputDatetime
+                inputDatetimeString = inputDatetime.strftime('%Y%m%d')
+                normalInputDatetimeString = inputDatetimeString[:6] + '01'
+                inputDatetime = datetime.datetime.strptime(normalInputDatetimeString, '%Y%m%d')
+
+            normalDatetimes.append(inputDatetime)
+
+    elif timestep.lower() == 'daily':
+        for inputDatetime in datetimes:
+            if inputDatetime.hour != 0 or inputDatetime.minute != 0 or inputDatetime.second != 0:
+                datetimeString = inputDatetime.strftime('%Y%m%d%H%M%S')
+                normalDatetimeString = datetimeString[:8] + '000000'
+                inputDatetime = datetime.datetime.strptime(normalDatetimeString, '%Y%m%d%H%M%S')
+            
+            normalDatetimes.append(inputDatetime)
+
+
+    return normalDatetimes
+
+def getModelTimes(modelFile, timeVarName):
+    '''
+    TODO:  Do a better job handling dates here
+    Routine to convert from model times ('hours since 1900...', 'days since ...')
+    into a python datetime structure
+
+    Input::
+        modelFile - path to the model tile you want to extract the times list and modelTimeStep from
+        timeVarName - name of the time variable in the model file
+
+    Output::
+        times  - list of python datetime objects describing model data times
+        modelTimeStep - 'hourly','daily','monthly','annual'
+    '''
+
+    f = Nio.open_file(modelFile)
+    xtimes = f.variables[timeVarName]
+    timeFormat = xtimes.attributes['units']
+
+    # search to check if 'since' appears in units
+    try:
+        sinceLoc = re.search('since', timeFormat).end()
+
+    except AttributeError:
+        print 'Error decoding model times: time variable attributes do not contain "since"'
+        raise
+    
+    units = None
+    TIME_UNITS = ('minutes', 'hours', 'days', 'months', 'years')
+    # search for 'seconds','minutes','hours', 'days', 'months', 'years' so know units
+    for unit in TIME_UNITS:
+        if re.search(unit, timeFormat):
+            units = unit
+            break
+
+    # cut out base time (the bit following 'since')
+    base_time_string = string.lstrip(timeFormat[sinceLoc:])
+    # decode base time
+    base_time = decodeTimeFromString(base_time_string)
+    times = []
+
+    for xtime in xtimes[:]:
+        
+        # Cast time as an int
+        xtime = int(xtime)
+
+        if units == 'minutes':
+            dt = datetime.timedelta(minutes=xtime)
+            new_time = base_time + dt
+        elif units == 'hours':
+            dt = datetime.timedelta(hours=xtime)
+            new_time = base_time + dt
+        elif units == 'days':
+            dt = datetime.timedelta(days=xtime)
+            new_time = base_time + dt
+        elif units == 'months':
+            # NB. adding months in python is complicated as month length varies and hence ambiguous.
+            # Perform date arithmatic manually
+            #  Assumption: the base_date will usually be the first of the month
+            #              NB. this method will fail if the base time is on the 29th or higher day of month
+            #                      -as can't have, e.g. Feb 31st.
+            new_month = int(base_time.month + xtime % 12)
+            new_year = int(math.floor(base_time.year + xtime / 12.))
+            new_time = datetime.datetime(new_year, new_month, base_time.day, base_time.hour, base_time.second, 0)
+        elif units == 'years':
+            dt = datetime.timedelta(years=xtime)
+            new_time = base_time + dt
+
+        times.append(new_time)
+    
+    try:
+        timeStepLength = int(xtimes[1] - xtimes[0] + 1.e-12)
+        modelTimeStep = getModelTimeStep(units, timeStepLength)
+    except:
+        raise
+    
+    times = normalizeDatetimes(times, modelTimeStep)
+    
+    return times, modelTimeStep
+
+def getModelTimeStep(units, stepSize):
+    # Time units are now determined. Determine the time intervals of input data (mdlTimeStep)
+
+    if units == 'minutes':
+        if stepSize == 60:
+            modelTimeStep = 'hourly'
+        elif stepSize == 1440:
+            modelTimeStep = 'daily'
+        # 28 days through 31 days
+        elif 40320 <= stepSize <= 44640:
+            modelTimeStep = 'monthly'
+        # 365 days through 366 days 
+        elif 525600 <= stepSize <= 527040:
+            modelTimeStep = 'annual' 
+        else:
+            raise Exception('model data time step interval exceeds the max time interval (annual)', units, stepSize)
+
+    elif units == 'hours':
+        if stepSize == 1:
+            modelTimeStep = 'hourly'
+        elif stepSize == 24:
+            modelTimeStep = 'daily'
+        elif 672 <= stepSize <= 744:
+            modelTimeStep = 'monthly' 
+        elif 8760 <= stepSize <= 8784:
+            modelTimeStep = 'annual' 
+        else:
+            raise Exception('model data time step interval exceeds the max time interval (annual)', units, stepSize)
+
+    elif units == 'days':
+        if stepSize == 1:
+            modelTimeStep = 'daily'
+        elif 28 <= stepSize <= 31:
+            modelTimeStep = 'monthly'
+        elif 365 <= stepSize <= 366:
+            modelTimeStep = 'annual'
+        else:
+            raise Exception('model data time step interval exceeds the max time interval (annual)', units, stepSize)
+
+    elif units == 'months':
+        if stepSize == 1:
+            modelTimeStep = 'monthly'
+        elif stepSize == 12:
+            modelTimeStep = 'annual'
+        else:
+            raise Exception('model data time step interval exceeds the max time interval (annual)', units, stepSize)
+
+    elif units == 'years':
+        if stepSize == 1:
+            modelTimeStep = 'annual'
+        else:
+            raise Exception('model data time step interval exceeds the max time interval (annual)', units, stepSize)
+
+    else:
+        errorMessage = 'the time unit ', units, ' is not currently handled in this version.'
+        raise Exception(errorMessage)
+
+    return modelTimeStep
+
+def decodeTimeFromString(time_string):
+    '''
+     Decodes string into a python datetime object
+     *Method:* tries a bunch of different time format possibilities and hopefully one of them will hit.
+     ::
+
+       **Input:**  time_string - a string that represents a date/time
+       
+       **Output:** mytime - a python datetime object
+    '''
+
+    # This will deal with times that use decimal seconds
+    if '.' in time_string:
+        time_string = time_string.split('.')[0] + '0'
+    else:
+        pass
+
+    try:
+        mytime = time.strptime(time_string, '%Y-%m-%d %H:%M:%S')
+        mytime = datetime.datetime(*mytime[0:6])
+        return mytime
+
+    except ValueError:
+        pass
+
+    try:
+        mytime = time.strptime(time_string, '%Y/%m/%d %H:%M:%S')
+        mytime = datetime.datetime(*mytime[0:6])
+        return mytime
+
+    except ValueError:
+        pass
+
+    try:
+        mytime = time.strptime(time_string, '%Y%m%d %H:%M:%S')
+        mytime = datetime.datetime(*mytime[0:6])
+        return mytime
+
+    except ValueError:
+        pass
+
+    try:
+        mytime = time.strptime(time_string, '%Y:%m:%d %H:%M:%S')
+        mytime = datetime.datetime(*mytime[0:6])
+        return mytime
+
+    except ValueError:
+        pass
+
+    try:
+        mytime = time.strptime(time_string, '%Y%m%d%H%M%S')
+        mytime = datetime.datetime(*mytime[0:6])
+        return mytime
+
+    except ValueError:
+        pass
+
+    try:
+        mytime = time.strptime(time_string, '%Y-%m-%d %H:%M')
+        mytime = datetime.datetime(*mytime[0:6])
+        return mytime
+
+    except ValueError:
+        pass
+
+    try:
+        mytime = time.strptime(time_string, '%Y-%m-%d')
+        mytime = datetime.datetime(*mytime[0:6])
+        return mytime
+
+    except ValueError:
+        pass
+
+
+    print 'Error decoding time string: string does not match a predefined time format'
+    return 0
+
+def regrid_wrapper(regrid_choice, obsdata, obslats, obslons, wrfdata, wrflats, wrflons):
+   '''
+    Wrapper routine for regridding.
+    
+    Either regrids model to obs grid, or obs to model grid, depending on user choice
+    
+        Inputs::
+            regrid_choice - [0] = Regrid obs data onto model grid or 
+                            [1] = Regrid model data onto obs grid
+
+            obsdata,wrfdata - data arrays
+            obslats,obslons - observation lat,lon arrays
+            wrflats,wrflons - model lat,lon arrays
+   
+        Output::
+            rdata,rdata2 - regridded data
+   	        lats,lons    - latitudes and longitudes of regridded data
+   
+   '''
+
+   # Regrid obs data onto model grid
+   if(regrid_choice == '0'):
+
+      ndims = len(obsdata.shape)
+      if(ndims == 3):
+         newshape = [obsdata.shape[0], wrfdata.shape[1], wrfdata.shape[2]]
+	 nT = obsdata.shape[0]
+
+      if(ndims == 2):
+         newshape = [wrfdata.shape[0], wrfdata.shape[1]]
+	 nT = 0
+
+      rdata = wrfdata
+      lats, lons = wrflats, wrflons
+
+      # Create a new masked array with the required dimensions
+      tmp = np.zeros(newshape)
+      rdata2 = ma.MaskedArray(tmp, mask=(tmp == 0))
+      tmp = 0 # free up some memory
+
+      rdata2[:] = 0.0
+
+      if(nT > 0):
+       for t in np.arange(nT):
+         rdata2[t, :, :] = do_regrid(obsdata[t, :, :], obslats[:, :], obslons[:, :], wrflats[:, :], wrflons[:, :])
+
+      if(nT == 0):
+         rdata2[:, :] = do_regrid(obsdata[:, :], obslats[:, :], obslons[:, :], wrflats[:, :], wrflons[:, :])
+
+
+   # Regrid model data onto obs grid
+   if(regrid_choice == '1'):
+      ndims = len(wrfdata.shape)
+      if(ndims == 3):
+         newshape = [wrfdata.shape[0], obsdata.shape[1], obsdata.shape[2]]
+	 nT = obsdata.shape[0]
+
+      if(ndims == 2):
+         newshape = [obsdata.shape[0], obsdata.shape[1]]
+	 nT = 0
+
+      rdata2 = obsdata
+      lats, lons = obslats, obslons
+
+      tmp = np.zeros(newshape)
+      rdata = ma.MaskedArray(tmp, mask=(tmp == 0))
+      tmp = 0 # free up some memory
+
+      rdata[:] = 0.0
+ 
+      if(nT > 0):
+        for t in np.arange(nT):
+	 rdata[t, :, :] = do_regrid(wrfdata[t, :, :], wrflats[:, :], wrflons[:, :], obslats[:, :], obslons[:, :])
+
+      if(nT == 0):
+	rdata[:, :] = do_regrid(wrfdata[:, :], wrflats[:, :], wrflons[:, :], obslats[:, :], obslons[:, :])
+
+  
+   return rdata, rdata2, lats, lons
+
+def extract_sub_time_selection(allTimes, subTimes, data):
+    '''
+     Routine to extract a sub-selection of times from a data array.
+
+     Example::
+           Suppose a data array has 30 time values for daily data for a whole month, 
+           but you only want the data from the 5th-15th of the month.
+    
+     Input::
+           allTimes - list of datetimes describing what times the data in the data array correspond to
+           subTimes - the times you want to extract data from
+           data     - the data array
+    
+     Output::
+           subdata     - subselection of data array
+    
+    '''
+    # Create new array to store the subselection
+    subdata = np.zeros([len(subTimes), data.shape[1], data.shape[2]])
+    
+    # Loop over all Times and when it is a member of the required subselection, copy the data across
+    i = 0     # counter for allTimes
+    subi = 0  # counter for subTimes
+    for t in allTimes:
+        if(np.setmember1d(allTimes, subTimes)):
+            subdata[subi, :, :] = data[i, :, :]
+            subi += 1
+        i += 1
+    
+    return subdata
+
+def calc_average_on_new_time_unit_K(data, dateList, unit):
+    '''
+    Routine to calculate averages on longer time units than the data exists on.
+    e.g. if the data is 6-hourly, calculate daily, or monthly means.
+     
+    Input:
+        data     - data values
+        dateList - list of python datetime structures corresponding to data values
+        unit     - string describing time unit to average onto 
+                      e.g. 'monthly', 'daily', 'pentad','annual','decadal'
+    Output:
+        meanstorem - numpy masked array of data values meaned over required time period
+        newTimesList - a list of python datetime objects representing the data in the new averagin period
+                           NB. currently set to beginning of averaging period, 
+                           i.e. mean Jan 1st - Jan 31st -> represented as Jan 1st, 00Z.
+    '''
+
+    # Check if the user-selected temporal grid is valid. If not, EXIT
+    acceptable = (unit=='full')|(unit=='annual')|(unit=='monthly')|(unit=='daily')|(unit=='pentad')
+    if not acceptable:
+        print 'Error: unknown unit type selected for time averaging: EXIT'
+        return -1,-1,-1,-1
+
+    # Calculate arrays of: annual timeseries: year (2007,2007),
+    #                      monthly time series: year-month (200701,200702),
+    #                      daily timeseries:  year-month-day (20070101,20070102) 
+    #  depending on user-selected averaging period.
+
+    # Year list
+    if unit=='annual':
+        timeunits = []
+        for i in np.arange(len(dateList)):
+            timeunits.append(str(dateList[i].year))
+        timeunits = np.array(timeunits, dtype=int)
+         
+    # YearMonth format list
+    if unit=='monthly':
+        timeunits = []
+        for i in np.arange(len(dateList)):
+            timeunits.append(str(dateList[i].year) + str("%02d" % dateList[i].month))
+        timeunits = np.array(timeunits,dtype=int)
+
+    # YearMonthDay format list
+    if unit=='daily':
+        timeunits = []
+        for i in np.arange(len(dateList)):
+            timeunits.append(str(dateList[i].year) + str("%02d" % dateList[i].month) + str("%02d" % dateList[i].day))
+        timeunits = np.array(timeunits,dtype=int)
+
+    # TODO: add pentad setting using Julian days?
+
+    # Full list: a special case
+    if unit == 'full':
+        comment='Calculating means data over the entire time range: i.e., annual-mean climatology'
+        timeunits = []
+        for i in np.arange(len(dateList)):
+            timeunits.append(999)  # i.e. we just want the same value for all times.
+        timeunits = np.array(timeunits, dtype=int)
+
+    # empty list to store new times
+    newTimesList = []
+
+    # Decide whether or not you need to do any time averaging.
+    #   i.e. if data are already on required time unit then just pass data through and 
+    #        calculate and return representative datetimes.
+    processing_required = True
+    if len(timeunits)==(len(np.unique(timeunits))):
+        processing_required = False
+
+    # 1D data arrays, i.e. time series
+    if data.ndim==1:
+        # Create array to store the resulting data
+        meanstore = np.zeros(len(np.unique(timeunits)))
+  
+        # Calculate the means across each unique time unit
+        i=0
+        for myunit in np.unique(timeunits):
+            if processing_required:
+                datam=ma.masked_array(data,timeunits!=myunit)
+                meanstore[i] = ma.average(datam)
+            
+            # construct new times list
+            smyunit = str(myunit)
+            if len(smyunit)==4:  # YYYY
+                yyyy = int(myunit[0:4])
+                mm = 1
+                dd = 1
+            if len(smyunit)==6:  # YYYYMM
+                yyyy = int(smyunit[0:4])
+                mm = int(smyunit[4:6])
+                dd = 1
+            if len(smyunit)==8:  # YYYYMMDD
+                yyyy = int(smyunit[0:4])
+                mm = int(smyunit[4:6])
+                dd = int(smyunit[6:8])
+            if len(smyunit)==3:  # Full time range
+                # Need to set an appropriate time representing the mid-point of the entire time span
+                dt = dateList[-1]-dateList[0]
+                halfway = dateList[0]+(dt/2)
+                yyyy = int(halfway.year)
+                mm = int(halfway.month)
+                dd = int(halfway.day)
+
+            newTimesList.append(datetime.datetime(yyyy,mm,dd,0,0,0,0))
+            i = i+1
+
+    # 3D data arrays
+    if data.ndim==3:
+        # datamask = create_mask_using_threshold(data,threshold=0.75)
+        # Create array to store the resulting data
+        meanstore = np.zeros([len(np.unique(timeunits)),data.shape[1],data.shape[2]])
+  
+        # Calculate the means across each unique time unit
+        i=0
+        datamask_store = []
+        for myunit in np.unique(timeunits):
+            if processing_required:
+                mask = np.zeros_like(data)
+                mask[timeunits!=myunit,:,:] = 1.0
+                # Calculate missing data mask within each time unit...
+                datamask_at_this_timeunit = np.zeros_like(data)
+                datamask_at_this_timeunit[:]= create_mask_using_threshold(data[timeunits==myunit,:,:],threshold=0.75)
+                # Store results for masking later
+                datamask_store.append(datamask_at_this_timeunit[0])
+                # Calculate means for each pixel in this time unit, ignoring missing data (using masked array).
+                datam = ma.masked_array(data,np.logical_or(mask,datamask_at_this_timeunit))
+                meanstore[i,:,:] = ma.average(datam,axis=0)
+            # construct new times list
+            smyunit = str(myunit)
+            if len(smyunit)==4:  # YYYY
+                yyyy = int(smyunit[0:4])
+                mm = 1
+                dd = 1
+            if len(smyunit)==6:  # YYYYMM
+                yyyy = int(smyunit[0:4])
+                mm = int(smyunit[4:6])
+                dd = 1
+            if len(smyunit)==8:  # YYYYMMDD
+                yyyy = int(smyunit[0:4])
+                mm = int(smyunit[4:6])
+                dd = int(smyunit[6:8])
+            if len(smyunit)==3:  # Full time range
+                # Need to set an appropriate time representing the mid-point of the entire time span
+                dt = dateList[-1]-dateList[0]
+                halfway = dateList[0]+(dt/2)
+                yyyy = int(halfway.year)
+                mm = int(halfway.month)
+                dd = int(halfway.day)
+            newTimesList.append(datetime.datetime(yyyy,mm,dd,0,0,0,0))
+            i += 1
+
+        if not processing_required:
+            meanstorem = data
+
+        if processing_required:
+            # Create masked array (using missing data mask defined above)
+            datamask_store = np.array(datamask_store)
+            meanstorem = ma.masked_array(meanstore, datamask_store)
+
+    return meanstorem,newTimesList
+
+def decode_model_timesK(ifile,timeVarName,file_type):
+    #################################################################################################
+    #  Convert model times ('hours since 1900...', 'days since ...') into a python datetime structure
+    #  Input:
+    #      filelist - list of model files
+    #      timeVarName - name of the time variable in the model files
+    #  Output:
+    #      times  - list of python datetime objects describing model data times
+    #     Peter Lean February 2011
+    #################################################################################################
+    f = Nio.open_file(ifile,mode='r',options=None,format=file_type)
+    xtimes = f.variables[timeVarName]
+    timeFormat = xtimes.attributes['units']
+    #timeFormat = "days since 1979-01-01 00:00:00"
+    # search to check if 'since' appears in units
+    try:
+        sinceLoc = re.search('since',timeFormat).end()
+    except:
+        print 'Error decoding model times: time var attributes do not contain "since": Exit'
+        sys.exit()
+    # search for 'seconds','minutes','hours', 'days', 'months', 'years' so know units
+    # TODO:  Swap out this section for a set of if...elseif statements
+    units = ''
+    try:
+        _ = re.search('minutes',timeFormat).end()
+        units = 'minutes'
+    except:
+        pass
+    try:
+        _ = re.search('hours',timeFormat).end()
+        units = 'hours'
+    except:
+        pass
+    try:
+        _ = re.search('days',timeFormat).end()
+        units = 'days'
+    except:
+        pass
+    try:
+        _ = re.search('months',timeFormat).end()
+        units = 'months'
+    except:
+        pass
+    try:
+        _ = re.search('years',timeFormat).end()
+        units = 'years'
+    except:
+        pass
+    # cut out base time (the bit following 'since')
+    base_time_string = string.lstrip(timeFormat[sinceLoc:])
+    # decode base time
+    # 9/25/2012: datetime.timedelta has problem with the argument because xtimes is NioVariable.
+    # Soln (J. Kim): use a temp variable ttmp in the for loop, then convert it into an integer xtime.
+    base_time = decodeTimeFromString(base_time_string)
+    times=[]
+    for ttmp in xtimes[:]:
+        xtime = int(ttmp)
+        if(units=='minutes'):  
+            dt = datetime.timedelta(minutes=xtime); new_time = base_time + dt
+        if(units=='hours'):  
+            dt = datetime.timedelta(hours=xtime); new_time = base_time + dt
+        if(units=='days'):  
+            dt = datetime.timedelta(days=xtime); new_time = base_time + dt
+        if(units=='months'):   # NB. adding months in python is complicated as month length varies and hence ambigous.
+            # Perform date arithmatic manually
+            #  Assumption: the base_date will usually be the first of the month
+            #              NB. this method will fail if the base time is on the 29th or higher day of month
+            #                      -as can't have, e.g. Feb 31st.
+            new_month = int(base_time.month + xtime % 12)
+            new_year = int(math.floor(base_time.year + xtime / 12.))
+            #print type(new_year),type(new_month),type(base_time.day),type(base_time.hour),type(base_time.second)
+            new_time = datetime.datetime(new_year,new_month,base_time.day,base_time.hour,base_time.second,0)
+        if(units=='years'):
+            dt = datetime.timedelta(years=xtime); new_time = base_time + dt
+        times.append(new_time)
+    return times
+
+
+def regrid_in_time(data,dateList,unit):
+   #################################################################################################
+   # Routine to calculate averages on longer time units than the data exists on.
+   #  e.g. if the data is 6-hourly, calculate daily, or monthly means.
+   #  Input:
+   #         data     - data values
+   #         dateList - list of python datetime structures corresponding to data values
+   #         unit     - string describing time unit to average onto 
+   #                       e.g. 'monthly', 'daily', 'pentad','annual','decadal'
+   #  Output:
+   #         meanstorem - numpy masked array of data values meaned over required time period
+   #         newTimesList - a list of python datetime objects representing the data in the new averagin period
+   #                            NB. currently set to beginning of averaging period, 
+   #                            i.e. mean Jan 1st - Jan 31st -> represented as Jan 1st, 00Z.
+   # ..............................
+   #   Jinwon Kim, Sept 30, 2012
+   #   Created from calc_average_on_new_time_unit_K, Peter's original, with the modification below:
+   #   Instead of masked array used by Peter, use wh to defined data within the averaging range.
+   #################################################################################################
+
+   print '***  Begin calc_average_on_new_time_unit_KK  ***'
+   # Check if the user-selected temporal grid is valid. If not, EXIT
+   acceptable = (unit=='full')|(unit=='annual')|(unit=='monthly')|(unit=='daily')|(unit=='pentad')
+   if not acceptable:
+     print 'Error: unknown unit type selected for time averaging: EXIT'; return -1,-1,-1,-1
+
+   # Calculate time arrays of: annual (yyyy, [2007]), monthly (yyyymm, [200701,200702]), daily (yyyymmdd, [20070101,20070102]) 
+   # "%02d" is similar to i2.2 in Fortran
+   if unit=='annual':                      # YYYY
+      timeunits = []
+      for i in np.arange(len(dateList)):
+         timeunits.append(str(dateList[i].year))
+   elif unit=='monthly':                   # YYYYMM
+      timeunits = []
+      for i in np.arange(len(dateList)):
+         timeunits.append(str(dateList[i].year) + str("%02d" % dateList[i].month))
+   elif unit=='daily':                     # YYYYMMDD
+      timeunits = []
+      for i in np.arange(len(dateList)):
+         timeunits.append(str(dateList[i].year) + str("%02d" % dateList[i].month) + str("%02d" % dateList[i].day))
+   elif unit=='full':                      # Full list: a special case
+      comment='Calculating means data over the entire time range: i.e., annual-mean climatology'
+      timeunits = []
+      for i in np.arange(len(dateList)):
+         timeunits.append(999)             # i.e. we just want the same value for all times.
+   timeunits = np.array(timeunits,dtype=int)
+   print 'timeRegridOption= ',unit#'; output timeunits= ',timeunits
+   #print 'timeRegridOption= ',unit,'; output timeunits= ',timeunits
+
+   # empty list to store time levels after temporal regridding
+   newTimesList = []
+
+   # Decide whether or not you need to do any time averaging.
+   #   i.e. if data are already on required time unit then just pass data through and calculate and return representative datetimes.
+   processing_required = True
+   if len(timeunits)==(len(np.unique(timeunits))):
+        processing_required = False
+   print 'processing_required= ',processing_required,': input time steps= ',len(timeunits),': regridded output time steps = ',len(np.unique(timeunits))
+   #print 'np.unique(timeunits): ',np.unique(timeunits)
+   print 'data.ndim= ',data.ndim
+
+   if data.ndim==1:                                           # 1D data arrays, i.e. 1D time series
+      # Create array to store the temporally regridded data
+     meanstore = np.zeros(len(np.unique(timeunits)))
+      # Calculate the means across each unique time unit
+     i=0
+     for myunit in np.unique(timeunits):
+       if processing_required:
+         wh = timeunits==myunit
+         datam = data[wh]
+         meanstore[i] = ma.average(datam)
+        # construct new times list
+       smyunit = str(myunit)
+       if len(smyunit)==4:  # YYYY
+        yyyy = int(myunit[0:4])
+        mm = 1
+        dd = 1
+       if len(smyunit)==6:  # YYYYMM
+        yyyy = int(smyunit[0:4])
+        mm = int(smyunit[4:6])
+        dd = 1
+       if len(smyunit)==8:  # YYYYMMDD
+        yyyy = int(smyunit[0:4])
+        mm = int(smyunit[4:6])
+        dd = int(smyunit[6:8])
+       if len(smyunit)==3:  # Full time range
+        # Need to set an appropriate time representing the mid-point of the entire time span
+        dt = dateList[-1]-dateList[0]
+        halfway = dateList[0]+(dt/2)
+        yyyy = int(halfway.year)
+        mm = int(halfway.month)
+        dd = int(halfway.day)
+       newTimesList.append(datetime.datetime(yyyy,mm,dd,0,0,0,0))
+       i = i+1
+
+   elif data.ndim==3:                                         # 3D data arrays, i.e. 2D time series
+      # Create array to store the resulting data
+     meanstore = np.zeros([len(np.unique(timeunits)),data.shape[1],data.shape[2]])
+     # Calculate the means across each unique time unit
+     i=0
+     datamask_store = []
+     for myunit in np.unique(timeunits):
+       if processing_required:
+         wh = timeunits==myunit
+         datam = data[wh,:,:]
+         meanstore[i,:,:] = ma.average(datam,axis=0)
+        # construct new times list
+       smyunit = str(myunit)
+       if len(smyunit)==4:  # YYYY
+        yyyy = int(smyunit[0:4])
+        mm = 1
+        dd = 1
+       if len(smyunit)==6:  # YYYYMM
+        yyyy = int(smyunit[0:4])
+        mm = int(smyunit[4:6])
+        dd = 1
+       if len(smyunit)==8:  # YYYYMMDD
+        yyyy = int(smyunit[0:4])
+        mm = int(smyunit[4:6])
+        dd = int(smyunit[6:8])
+       if len(smyunit)==3:  # Full time range
+        # Need to set an appropriate time representing the mid-point of the entire time span
+        dt = dateList[-1]-dateList[0]
+        halfway = dateList[0]+(dt/2)
+        yyyy = int(halfway.year)
+        mm = int(halfway.month)
+        dd = int(halfway.day)
+       newTimesList.append(datetime.datetime(yyyy,mm,dd,0,0,0,0))
+       i += 1
+
+     if not processing_required:
+        meanstorem = data
+     elif processing_required:
+        meanstorem = meanstore
+
+   print '***  End calc_average_on_new_time_unit_KK  ***'
+   return meanstorem,newTimesList

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/rcmes/toolkit/.svn/text-base/visualize.py.svn-base
----------------------------------------------------------------------
diff --git a/src/main/python/rcmes/toolkit/.svn/text-base/visualize.py.svn-base b/src/main/python/rcmes/toolkit/.svn/text-base/visualize.py.svn-base
new file mode 100755
index 0000000..20e4447
--- /dev/null
+++ b/src/main/python/rcmes/toolkit/.svn/text-base/visualize.py.svn-base
@@ -0,0 +1 @@
+"""Collection of functions to visualize the data analysis output artifacts"""
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/rcmes/toolkit/__init__.py
----------------------------------------------------------------------
diff --git a/src/main/python/rcmes/toolkit/__init__.py b/src/main/python/rcmes/toolkit/__init__.py
new file mode 100755
index 0000000..11548e6
--- /dev/null
+++ b/src/main/python/rcmes/toolkit/__init__.py
@@ -0,0 +1,2 @@
+"""The toolkit Package is a collection of modules that provide a set of tools
+that can be used to process, analyze and plot the analysis results."""
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/rcmes/toolkit/__init__.pyc
----------------------------------------------------------------------
diff --git a/src/main/python/rcmes/toolkit/__init__.pyc b/src/main/python/rcmes/toolkit/__init__.pyc
new file mode 100644
index 0000000..9b1707b
Binary files /dev/null and b/src/main/python/rcmes/toolkit/__init__.pyc differ

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/rcmes/toolkit/do_data_prep.py
----------------------------------------------------------------------
diff --git a/src/main/python/rcmes/toolkit/do_data_prep.py b/src/main/python/rcmes/toolkit/do_data_prep.py
new file mode 100755
index 0000000..db9ea39
--- /dev/null
+++ b/src/main/python/rcmes/toolkit/do_data_prep.py
@@ -0,0 +1,461 @@
+"""Prepare Datasets both model and observations for analysis using metrics"""
+
+
+import numpy as np
+import numpy.ma as ma
+import sys, os
+
+from storage import db, files
+import process
+from utils import misc
+import scipy.interpolate
+
+# TODO:  swap gridBox for Domain
+def prep_data(settings,obsSource,obsDatasetList,obsList,obsVarName,obsLonName,obsLatName,obsTimeName,obsTimestep,gridBox,modelList):
+    """
+    
+    returns numOBSs,numMDLs,nT,ngrdY,ngrdX,Times,lons,lats,obsData,modelData,obsList
+    
+        numOBSs - number of Observational Datasets.  Really need to look at using len(obsDatasetList) instead
+        numMDLs - number of Models used.  Again should use the len(modelList) instead
+        nT - Time value count after temporal regridding. Should use length of the time axis for a given dataset
+        ngrdY - size of the Y-Axis grid after spatial regridding
+        ngrdX - size of the X-Axis grid after spatial regridding
+        Times - list of python datetime objects the represent the list of time to be used in further calculations
+        lons - 
+        lats - 
+        obsData - 
+        modelData - 
+        obsList - 
+        
+    # 5/28/2013: Add 'obsSource' to indicate the source of the reference data file(s)
+    """
+    
+    # TODO:  Stop the object Deserialization and work on refactoring the core code here
+    cachedir = settings.cacheDir
+    workdir = settings.workDir
+    variableType = settings.variableType
+    variableType = variableType.lower()
+
+    # Use list comprehensions to deconstruct obsDatasetList
+    #  ['TRMM_pr_mon', 'CRU3.1_pr']    Basically a list of Dataset NAME +'_' + parameter name - THE 'CRU*' one triggers unit conversion issues later
+    # the plan here is to use the obsDatasetList which contains a longName key we can use.
+    if obsSource == 0:              # reference data from RCMED
+        obsList = [str(x['longname']) for x in obsDatasetList]
+        # Also using the obsDatasetList with a key of ['dataset_id']
+        obsDatasetId = [str(x['dataset_id']) for x in obsDatasetList]
+        # obsDatasetList ['paramter_id'] list
+        obsParameterId = [str(x['parameter_id']) for x in obsDatasetList]
+        obsTimestep = [str(x['timestep']) for x in obsDatasetList]
+    elif obsSource == 1:              # reference data from users' disk
+        # in this case, obsList and obsTimestep have been defined in the calling routine and passed into this routine
+        pass
+    elif obsSource < 0:               # no reference data are involved
+        pass
+
+    mdlList = [model.filename for model in modelList]
+
+    # Since all of the model objects in the modelList have the same "VarName" and "variableType", merely pull these from modelList[0]
+    modelTimeVarName = modelList[0].timeVariable
+    modelLatVarName = modelList[0].latVariable
+    modelLonVarName = modelList[0].lonVariable
+    modelVarName = modelList[0].varName
+    regridOption = settings.spatialGrid
+    timeRegridOption = settings.temporalGrid
+    print 'model parameter names ',modelVarName,modelTimeVarName,modelLatVarName,modelLonVarName
+    
+    """
+     Routine to read-in and re-grid both obs and mdl datasets.
+     Processes both single and multiple files of obs and mdl or combinations in a general way.
+           i)    retrieve observations from the database
+           ii)   load in model data
+           iii)  temporal regridding
+           iv)   spatial regridding
+           v)    area-averaging
+           Input:
+                   cachedir 	- string describing directory path
+                   workdir 	- string describing directory path
+                   obsList        - string describing the observation data files
+                   obsDatasetId 	- int, db dataset id
+                   obsParameterId	- int, db parameter id 
+                   latMin, latMax, lonMin, lonMax, dLat, dLon, naLats, naLons: define the evaluation/analysis domain/grid system
+    	         latMin		- float
+                   latMax		- float
+                   lonMin		- float
+                   lonMax		- float
+                   dLat  		- float
+                   dLon  		- float
+                   naLats		- integer
+                   naLons		- integer
+                   mdlList	- string describing model file name + path
+                   modelVarName	- string describing name of variable to evaluate (as written in model file)
+                 variableType   - string
+                   modelTimeVarName - string describing name of time variable in model file 	
+                   modelLatVarName  - string describing name of latitude variable in model file 
+                   modelLonVarName  - string describing name of longitude variable in model file 
+                   regridOption 	 - string: 'obs'|'model'|'user'
+                   timeRegridOption -string: 'full'|'annual'|'monthly'|'daily'
+                   maskOption - Boolean
+                   
+                   # TODO:  This isn't true in the current codebase.
+                   Instead the SubRegion's are being used.  You can see that these values are not
+                   being used in the code, at least they are not being passed in from the function
+                   
+                   maskLatMin - float (only used if maskOption=1)
+                   maskLatMax - float (only used if maskOption=1)
+    	         maskLonMin - float (only used if maskOption=1)
+                   maskLonMax - float (only used if maskOption=1)
+           Output: image files of plots + possibly data
+           Jinwon Kim, 7/11/2012
+    """
+
+
+    # check the number of obs & model data files
+    numOBSs = len(obsList)
+    numMDLs = len(mdlList)
+    
+    # assign parameters that must be preserved throughout the process
+    
+    print 'start & end time = ', settings.startDate, settings.endDate
+    yymm0 = settings.startDate.strftime("%Y%m")
+    yymm1 = settings.endDate.strftime("%Y%m")
+    print 'start & end eval period = ', yymm0, yymm1
+
+
+    #TODO: Wrap in try except blocks instead
+    # 2b expanded to encompass mdl-only or obs-only cases (post 2.1 item)
+    if numMDLs < 1: 
+        print 'No input model data file. EXIT'
+        sys.exit()
+    if numOBSs < 1: 
+        print 'No input observation data file. EXIT'
+        sys.exit()
+
+    ## Part 1: retrieve observation data from the database and regrid them
+    ##       NB. automatically uses local cache if already retrieved.
+
+    # preparation for spatial re-gridding: define the size of horizontal array of the target interpolation grid system (ngrdX and ngrdY)
+    print 'regridOption in prep_data= ', regridOption
+    if regridOption == 'model':
+        ifile = mdlList[0]
+        typeF = 'nc'
+        #lats, lons, mTimes = files.read_lolaT_from_file(ifile, modelLatVarName, modelLonVarName, modelTimeVarName, typeF)
+        lats, lons, mTimes = files.read_data_from_one_file(ifile, modelVarName,
+                                                           modelLatVarName,
+                                                           modelLonVarName,
+                                                           modelTimeVarName,
+                                                           typeF)[:3]
+        modelObject = modelList[0]
+        latMin = modelObject.latMin
+        latMax = modelObject.latMax
+        lonMin = modelObject.lonMin
+        lonMax = modelObject.lonMax
+    elif regridOption == 'user':
+        # Use the GridBox Object
+        latMin = gridBox.latMin
+        latMax = gridBox.latMax
+        lonMin = gridBox.lonMin
+        lonMax = gridBox.lonMax
+        naLats = gridBox.latCount
+        naLons = gridBox.lonCount
+        dLat = gridBox.latStep
+        dLon = gridBox.lonStep
+        lat = np.arange(naLats) * dLat + latMin
+        lon = np.arange(naLons) * dLon + lonMin
+        lons, lats = np.meshgrid(lon, lat)
+        lon = 0.
+        lat = 0.
+    else:
+        print "INVALID REGRID OPTION USED"
+        sys.exit()
+        
+    ngrdY = lats.shape[0]
+    ngrdX = lats.shape[1]
+
+    # All user-provided reference data are to be in netCDF format
+    if obsSource == 1:
+        typeF = 'nc'
+    regObsData = []
+    print ''
+    regularGrid = raw_input('OBS data are on regular grids? [y/n] \n>')
+    
+    for n in np.arange(numOBSs):
+
+        # read-in obs data and first do spatial regridding
+        if obsSource == 0:         # reference data from RCMED
+            oLats, oLons, _, oTimes, oData = db.extractData(obsDatasetId[n],
+                                                            obsParameterId[n],
+                                                            latMin, latMax,
+                                                            lonMin, lonMax,
+                                                            settings.startDate, settings.endDate,
+                                                            cachedir, obsTimestep[n])
+            # TODO: modify this if block with new metadata usage.
+            if (variableType == 'precipitation') and (obsList[n][0:3] == 'CRU'):
+                oData = 86400.0 * oData
+
+        elif obsSource == 1:      # reference data from users' own file
+            ifile = obsDatasetList[n]
+            oLats, oLons, oTimes, oData, ovUnit = files.read_data_from_one_file(ifile,
+                                                                                obsVarName,
+                                                                                obsLatName,
+                                                                                obsLonName,
+                                                                                obsTimeName,
+                                                                                typeF)
+            print 'ovUnit=',ovUnit
+            if (variableType == 'precipitation') or (variableType == 'evaporation') or (variableType == 'runoff'):
+                if ((ovUnit=='KG M-2 S-1') or (ovUnit=='kg m-2 s-1') or (ovUnit == 'MM S-1') or (ovUnit == 'mm s-1')):
+                    print 'convert model variable unit from mm/s to mm/day'
+                    oData=86400.*oData
+            # extract the reference data for the specified period
+            obsT = []
+            oStp = len(oTimes)
+            for i in np.arange(oStp):
+                obsT.append(oTimes[i].strftime("%Y%m"))
+            wh = (np.array(obsT) >= yymm0) & (np.array(obsT) <= yymm1)
+            oTimes = list(np.array(oTimes)[wh])
+            oData = oData[wh,:,:]
+
+        nstOBSs = oData.shape[0]         # note that the length of obs data can vary for different obs intervals (e.g., daily vs. monthly)
+        print 'Regrid OBS dataset onto the ', regridOption, ' grid system: ngrdY, ngrdX, nstOBSs= ', ngrdY, ngrdX, nstOBSs
+        print 'For dataset: %s' % obsList[n]
+        
+        tmpOBS = ma.zeros((nstOBSs, ngrdY, ngrdX))
+        print 'tmpOBS shape = ', tmpOBS.shape
+        if regularGrid == 'y':
+            for t in np.arange(nstOBSs):
+                tmpOBS[t, :, :] = process.do_regrid(oData[t, :, :], oLats, oLons, lats, lons)
+        else:
+            # new intetpolation scheme "scipy.interpolate.griddata" is used. note that masked values must be specified using "np.nan"
+            #     note that using "cubic" option causes problems in interpolation
+            for t in np.arange(nstOBSs):
+                inLats = oLats.flatten()
+                inLons = oLons.flatten()
+                length = len(inLats)
+                inPts = ma.zeros((length, 2))
+                inPts[:,0] = inLats
+                inPts[:,1] = inLons
+                inData = oData[t, :, :].flatten()
+                inData[inData < -999.] = np.nan
+                tmpOBS[t, :, :] = scipy.interpolate.griddata(inPts, inData, (lats, lons), method = 'linear')
+            inLats = 0.
+            inLons = 0.
+            inPts  = 0.
+            inData = 0.
+        print 'spatial regridding of the obs data ',n,' is completed'
+            
+        # TODO:  Not sure this is needed with Python Garbage Collector
+        # The used memory should be freed when the objects are no longer referenced.  If this continues to be an issue we may need to look
+        # at using generators where possible.
+        oLats = 0.0
+        oLons = 0.0       # release the memory occupied by the temporary variables oLats and oLons.
+        
+        # temporally regrid the spatially regridded obs data
+        oData, newObsTimes = process.calc_average_on_new_time_unit_K(tmpOBS, oTimes, unit=timeRegridOption)
+
+        tmpOBS = 0.0      # release temporary array after regridding
+        
+        # check the consistency of temporally regridded obs data
+        if n == 0:
+            oldObsTimes = newObsTimes
+        else:
+            if oldObsTimes != newObsTimes:
+                print 'temporally regridded obs data time levels do not match at ', n - 1, n
+                print '%s Time through Loop' % (n + 1)
+                print 'oldObsTimes Count: %s' % len(oldObsTimes)
+                print 'newObsTimes Count: %s' % len(newObsTimes)
+                # TODO:  We need to handle these cases using Try Except Blocks or insert a sys.exit if appropriate
+                sys.exit()
+            else:
+                oldObsTimes = newObsTimes
+        # if everything's fine, append the spatially and temporally regridded data in the obs data array (obsData)
+        regObsData.append(oData)
+
+
+    """ all obs datasets have been read-in and regridded. convert the regridded obs data from 'list' to 'array'
+    also finalize 'obsTimes', the time coordinate values of the regridded obs data.
+    NOTE: using 'list_to_array' assigns values to the missing points; this has become a problem in handling the CRU data.
+          this problem disappears by using 'ma.array'."""
+
+    obsData = ma.array(regObsData)
+    obsTimes = newObsTimes
+    regObsData = 0
+    oldObsTimes = 0
+    nT = len(obsTimes)
+
+    # TODO:  Refactor this into a function within the toolkit module
+    # compute the simple multi-obs ensemble if multiple obs are used
+    if numOBSs > 1:
+        print 'numOBSs = ', numOBSs
+        oData = obsData
+        print 'oData shape = ', oData.shape
+        obsData = ma.zeros((numOBSs + 1, nT, ngrdY, ngrdX))
+        print 'obsData shape = ', obsData.shape
+        avg = ma.zeros((nT, ngrdY, ngrdX))
+        
+        for i in np.arange(numOBSs):
+            obsData[i, :, :, :] = oData[i, :, :, :]
+            avg[:, :, :] = avg[:, :, :] + oData[i, :, :, :]
+
+        avg = avg / float(numOBSs)
+        obsData[numOBSs, :, :, :] = avg[:, :, :]     # store the obs-ensemble data
+        numOBSs = numOBSs + 1                        # update the number of obs data to include the obs ensemble
+        obsList.append('ensOBS')
+    print 'OBS regridded: ', obsData.shape
+
+    ## Part 2: load in and regrid model data from file(s)
+    ## NOTE: tthe wo parameters, numMDLs and numMOmx are defined to represent the number of models (w/ all 240 mos) &
+    ##       the total number of months, respectively, in later multi-model calculations.
+
+    typeF = 'nc'
+    regridMdlData = []
+    # extract the model names and store them in the list 'mdlList'
+    mdlName = []
+    mdlListReversed=[]
+    if len(mdlList) >1:
+       for element in mdlList:
+           mdlListReversed.append(element[::-1])
+       prefix=os.path.commonprefix(mdlList)
+       postfix=os.path.commonprefix(mdlListReversed)[::-1]
+       for element in mdlList:
+           mdlName.append(element.replace(prefix,'').replace(postfix,''))
+    else:
+        mdlName.append('model') 
+
+    print ''
+    regularGrid = raw_input('MDL data are on regular grids? [y/n] \n>')
+    
+    for n in np.arange(numMDLs):
+        # read model grid info, then model data
+        ifile = mdlList[n]
+        print 'ifile= ', ifile
+        #modelLats, modelLons, mTimes = files.read_lolaT_from_file(ifile, modelLatVarName, modelLonVarName, modelTimeVarName, typeF)
+        #mTime, mdlDat, mvUnit = files.read_data_from_one_file(ifile, modelVarName, modelTimeVarName, modelLats, typeF)
+        modelLats, modelLons, mTimes, mdlDat, mvUnit = files.read_data_from_one_file(ifile,
+                                                                                     modelVarName,
+                                                                                     modelLatVarName,
+                                                                                     modelLonVarName,
+                                                                                     modelTimeVarName,
+                                                                                     typeF)
+        mdlT = []
+        mStep = len(mTimes)
+
+        for i in np.arange(mStep):
+            mdlT.append(mTimes[i].strftime("%Y%m"))
+
+        wh = (np.array(mdlT) >= yymm0) & (np.array(mdlT) <= yymm1)
+        modelTimes = list(np.array(mTimes)[wh])
+        mData = mdlDat[wh, :, :]
+        # convert the units of model water flux variables (precipitation, evaporation, runoff) into "mm/day" as necessary
+        if (variableType == 'precipitation') or (variableType == 'evaporation') or (variableType == 'runoff'):
+            if (mvUnit=='KG M-2 S-1') or (mvUnit=='kg m-2 s-1') or (mvUnit == 'MM S-1') or (mvUnit == 'mm s-1'):
+                print 'convert model variable unit from mm/s to mm/day'
+                mData = 86400. * mData
+            else:
+                pass
+        elif (variableType == 'SWE') or (variableType == 'swe'):
+            if (mvUnit=='m') or (mvUnit=='M') or (mvUnit=='meter') or (mvUnit=='METER'):
+                print 'convert model SWE unit from meters to mm'
+                mData = 1.e3 * mData
+            else:
+                pass
+   
+        # determine the dimension size from the model time and latitude data.
+        nT = len(modelTimes)
+        
+        # UNUSED VARIABLES - WILL DELETE AFTER TESTING
+        # nmdlY=modelLats.shape[0]
+        # nmdlX=modelLats.shape[1]
+        #print 'nT, ngrdY, ngrdX = ',nT,ngrdY, ngrdX,min(modelTimes),max(modelTimes)
+        print '  The shape of model data to be processed= ', mData.shape, ' for the period ', min(modelTimes), max(modelTimes)
+        # spatial regridding of the modl data
+        tmpMDL = ma.zeros((nT, ngrdY, ngrdX))
+        
+        if regridOption != 'model':
+            if regularGrid == 'y':
+                for t in np.arange(nT):
+                    tmpMDL[t, :, :] = process.do_regrid(mData[t, :, :], modelLats, modelLons, lats, lons)
+            else:
+                # new intetpolation scheme "scipy.interpolate.griddata" is used. note that masked values must be specified using "np.nan"
+                #     note that using "cubic" option causes problems in interpolation
+                for t in np.arange(nstOBSs):
+                    inLats = modelLats.flatten()
+                    inLons = modelLons.flatten()
+                    length = len(inLats)
+                    inPts = ma.zeros((length, 2))
+                    inPts[:,0] = inLats
+                    inPts[:,1] = inLons
+                    inData = mData[t, :, :].flatten()
+                    inData[inData < -999.] = np.nan
+                    tmpMDL[t, :, :] = scipy.interpolate.griddata(inPts, inData, (lats, lons), method = 'linear')
+                inLats = 0.
+                inLons = 0.
+                inPts  = 0.
+                inData = 0.
+        else:
+            tmpMDL = mData
+
+        # temporally regrid the model data
+        mData, newMdlTimes = process.regrid_in_time(tmpMDL, modelTimes, unit=timeRegridOption)
+        tmpMDL = 0.0
+        
+        # check data consistency for all models 
+        if n == 0:
+            oldMdlTimes = newMdlTimes
+        else:
+            if oldMdlTimes != newMdlTimes:
+                print 'temporally regridded mdl data time levels do not match at ', n - 1, n
+                print len(oldMdlTimes), len(newMdlTimes)
+                sys.exit()
+            else:
+                oldMdlTimes = newMdlTimes
+
+        # if everything's fine, append the spatially and temporally regridded data in the obs data array (obsData)
+        regridMdlData.append(mData)
+
+    modelData = ma.array(regridMdlData)
+    modelTimes = newMdlTimes
+    regridMdlData = 0
+    oldMdlTimes = 0
+    newMdlTimes = 0
+    # check consistency between the time levels of the model and obs data
+    #   this is the final update of time levels: 'Times' and 'nT'
+    if obsTimes != modelTimes:
+        print 'time levels of the obs and model data are not consistent. EXIT'
+        print 'obsTimes'
+        print obsTimes
+        print 'modelTimes'
+        print modelTimes
+        sys.exit()
+    #  'Times = modelTimes = obsTimes' has been established and modelTimes and obsTimes will not be used hereafter. (de-allocated)
+    Times = modelTimes
+    nT = len(modelTimes)
+    modelTimes = 0
+    obsTimes = 0
+
+    print 'Reading and regridding model data are completed'
+    print 'numMDLs, modelData.shape= ', numMDLs, modelData.shape
+    
+    # TODO: Do we need to make this a user supplied flag, or do we just create an ensemble ALWAYS
+    # TODO: Add in Kyo's code here as well
+    # TODO:  Commented out until I can talk with Jinwon about this
+    # compute the simple multi-model ensemble if multiple models are evaluated
+    if numMDLs > 1:
+        mdlData=modelData
+        modelData=ma.zeros((numMDLs+1,nT,ngrdY,ngrdX))
+        avg=ma.zeros((nT,ngrdY,ngrdX))
+        for i in np.arange(numMDLs):
+            modelData[i,:,:,:]=mdlData[i,:,:,:]
+            avg[:,:,:]=avg[:,:,:]+mdlData[i,:,:,:]
+        avg=avg/float(numMDLs)
+        modelData[numMDLs,:,:,:]=avg[:,:,:]     # store the model-ensemble data
+        # THESE ARE NOT USED.  WILL DELETE AFTER TESTING
+        # i0mdl=0
+        # i1mdl=numMDLs
+        numMDLs=numMDLs+1
+        mdlName.append('ensMDL')
+        print 'Eval mdl-mean timeseries for the obs periods: modelData.shape= ',modelData.shape
+    # GOODALE:  This ensemble code should be refactored into process.py module since it's purpose is data processing
+
+    # Processing complete
+    print 'data_prep is completed: both obs and mdl data are re-gridded to a common analysis grid'
+    return numOBSs, numMDLs, nT, ngrdY, ngrdX, Times, lons, lats, obsData, modelData, obsList, mdlName, variableType

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/rcmes/toolkit/do_data_prep.pyc
----------------------------------------------------------------------
diff --git a/src/main/python/rcmes/toolkit/do_data_prep.pyc b/src/main/python/rcmes/toolkit/do_data_prep.pyc
new file mode 100644
index 0000000..d2b708c
Binary files /dev/null and b/src/main/python/rcmes/toolkit/do_data_prep.pyc differ


[24/51] [abbrv] [partial] Adding Jinwon's custom RCMET

Posted by jo...@apache.org.
http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/app/js/.svn/text-base/services.js.svn-base
----------------------------------------------------------------------
diff --git a/src/main/ui/app/js/.svn/text-base/services.js.svn-base b/src/main/ui/app/js/.svn/text-base/services.js.svn-base
new file mode 100755
index 0000000..334d543
--- /dev/null
+++ b/src/main/ui/app/js/.svn/text-base/services.js.svn-base
@@ -0,0 +1,9 @@
+'use strict';
+
+/* Services */
+
+
+// Demonstrate how to register services
+// In this case it is a simple value service.
+angular.module('myApp.services', []).
+  value('version', '0.1');

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/app/js/app.js
----------------------------------------------------------------------
diff --git a/src/main/ui/app/js/app.js b/src/main/ui/app/js/app.js
new file mode 100755
index 0000000..47b9e73
--- /dev/null
+++ b/src/main/ui/app/js/app.js
@@ -0,0 +1,53 @@
+'use strict';
+
+angular.module('rcmes', []).
+	config(['$routeProvider', function($routeProvider) {
+		$routeProvider.
+			when('/obs', {templateUrl: 'partials/selectObservation.html',   controller: ObservationSelectCtrl}).
+			when('/rcmed', {templateUrl: 'partials/selectRcmed.html', controller: RcmedSelectionCtrl}).
+			otherwise({redirectTo: '/obs'});
+	}]).
+	run(function($rootScope) {
+		$rootScope.evalResults = ""; 
+		$rootScope.fillColors = ['#ff0000', '#00c90d', '#cd0074', '#f3fd00'];
+		$rootScope.surroundColors = ['#a60000', '#008209', '#8f004b', '#93a400']
+		$rootScope.baseURL = 'http://localhost:8082';
+	}).
+	service('selectedDatasetInformation', function() {
+		var datasets = [];
+
+		return {
+			getDatasets: function() {
+				return datasets;
+			},
+			getDatasetCount: function() {
+				return datasets.length;
+			},
+			// TODO: Define the structure of the objects that are added with addDataset.
+			addDataset: function(dataset) {
+				datasets.push(dataset);
+			},
+			removeDataset: function(index) {
+				datasets.splice(index, 1);
+			},
+			clearDatasets: function() {
+				datasets.length = 0;
+			},
+		};
+	}).
+	service('regionSelectParams', function() {
+		var parameters = {
+			"latMin": "",
+			"latMax": "",
+			"lonMin": "",
+			"lonMax": "",
+			"start" : "",
+			"end"   : "",
+		};
+
+		return {
+			getParameters: function() {
+				return parameters;
+			},
+		};
+   });

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/app/js/bootstrap.js
----------------------------------------------------------------------
diff --git a/src/main/ui/app/js/bootstrap.js b/src/main/ui/app/js/bootstrap.js
new file mode 100755
index 0000000..c298ee4
--- /dev/null
+++ b/src/main/ui/app/js/bootstrap.js
@@ -0,0 +1,2276 @@
+/* ===================================================
+ * bootstrap-transition.js v2.3.1
+ * http://twitter.github.com/bootstrap/javascript.html#transitions
+ * ===================================================
+ * Copyright 2012 Twitter, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ========================================================== */
+
+
+!function ($) {
+
+  "use strict"; // jshint ;_;
+
+
+  /* CSS TRANSITION SUPPORT (http://www.modernizr.com/)
+   * ======================================================= */
+
+  $(function () {
+
+    $.support.transition = (function () {
+
+      var transitionEnd = (function () {
+
+        var el = document.createElement('bootstrap')
+          , transEndEventNames = {
+               'WebkitTransition' : 'webkitTransitionEnd'
+            ,  'MozTransition'    : 'transitionend'
+            ,  'OTransition'      : 'oTransitionEnd otransitionend'
+            ,  'transition'       : 'transitionend'
+            }
+          , name
+
+        for (name in transEndEventNames){
+          if (el.style[name] !== undefined) {
+            return transEndEventNames[name]
+          }
+        }
+
+      }())
+
+      return transitionEnd && {
+        end: transitionEnd
+      }
+
+    })()
+
+  })
+
+}(window.jQuery);/* ==========================================================
+ * bootstrap-alert.js v2.3.1
+ * http://twitter.github.com/bootstrap/javascript.html#alerts
+ * ==========================================================
+ * Copyright 2012 Twitter, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ========================================================== */
+
+
+!function ($) {
+
+  "use strict"; // jshint ;_;
+
+
+ /* ALERT CLASS DEFINITION
+  * ====================== */
+
+  var dismiss = '[data-dismiss="alert"]'
+    , Alert = function (el) {
+        $(el).on('click', dismiss, this.close)
+      }
+
+  Alert.prototype.close = function (e) {
+    var $this = $(this)
+      , selector = $this.attr('data-target')
+      , $parent
+
+    if (!selector) {
+      selector = $this.attr('href')
+      selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') //strip for ie7
+    }
+
+    $parent = $(selector)
+
+    e && e.preventDefault()
+
+    $parent.length || ($parent = $this.hasClass('alert') ? $this : $this.parent())
+
+    $parent.trigger(e = $.Event('close'))
+
+    if (e.isDefaultPrevented()) return
+
+    $parent.removeClass('in')
+
+    function removeElement() {
+      $parent
+        .trigger('closed')
+        .remove()
+    }
+
+    $.support.transition && $parent.hasClass('fade') ?
+      $parent.on($.support.transition.end, removeElement) :
+      removeElement()
+  }
+
+
+ /* ALERT PLUGIN DEFINITION
+  * ======================= */
+
+  var old = $.fn.alert
+
+  $.fn.alert = function (option) {
+    return this.each(function () {
+      var $this = $(this)
+        , data = $this.data('alert')
+      if (!data) $this.data('alert', (data = new Alert(this)))
+      if (typeof option == 'string') data[option].call($this)
+    })
+  }
+
+  $.fn.alert.Constructor = Alert
+
+
+ /* ALERT NO CONFLICT
+  * ================= */
+
+  $.fn.alert.noConflict = function () {
+    $.fn.alert = old
+    return this
+  }
+
+
+ /* ALERT DATA-API
+  * ============== */
+
+  $(document).on('click.alert.data-api', dismiss, Alert.prototype.close)
+
+}(window.jQuery);/* ============================================================
+ * bootstrap-button.js v2.3.1
+ * http://twitter.github.com/bootstrap/javascript.html#buttons
+ * ============================================================
+ * Copyright 2012 Twitter, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============================================================ */
+
+
+!function ($) {
+
+  "use strict"; // jshint ;_;
+
+
+ /* BUTTON PUBLIC CLASS DEFINITION
+  * ============================== */
+
+  var Button = function (element, options) {
+    this.$element = $(element)
+    this.options = $.extend({}, $.fn.button.defaults, options)
+  }
+
+  Button.prototype.setState = function (state) {
+    var d = 'disabled'
+      , $el = this.$element
+      , data = $el.data()
+      , val = $el.is('input') ? 'val' : 'html'
+
+    state = state + 'Text'
+    data.resetText || $el.data('resetText', $el[val]())
+
+    $el[val](data[state] || this.options[state])
+
+    // push to event loop to allow forms to submit
+    setTimeout(function () {
+      state == 'loadingText' ?
+        $el.addClass(d).attr(d, d) :
+        $el.removeClass(d).removeAttr(d)
+    }, 0)
+  }
+
+  Button.prototype.toggle = function () {
+    var $parent = this.$element.closest('[data-toggle="buttons-radio"]')
+
+    $parent && $parent
+      .find('.active')
+      .removeClass('active')
+
+    this.$element.toggleClass('active')
+  }
+
+
+ /* BUTTON PLUGIN DEFINITION
+  * ======================== */
+
+  var old = $.fn.button
+
+  $.fn.button = function (option) {
+    return this.each(function () {
+      var $this = $(this)
+        , data = $this.data('button')
+        , options = typeof option == 'object' && option
+      if (!data) $this.data('button', (data = new Button(this, options)))
+      if (option == 'toggle') data.toggle()
+      else if (option) data.setState(option)
+    })
+  }
+
+  $.fn.button.defaults = {
+    loadingText: 'loading...'
+  }
+
+  $.fn.button.Constructor = Button
+
+
+ /* BUTTON NO CONFLICT
+  * ================== */
+
+  $.fn.button.noConflict = function () {
+    $.fn.button = old
+    return this
+  }
+
+
+ /* BUTTON DATA-API
+  * =============== */
+
+  $(document).on('click.button.data-api', '[data-toggle^=button]', function (e) {
+    var $btn = $(e.target)
+    if (!$btn.hasClass('btn')) $btn = $btn.closest('.btn')
+    $btn.button('toggle')
+  })
+
+}(window.jQuery);/* ==========================================================
+ * bootstrap-carousel.js v2.3.1
+ * http://twitter.github.com/bootstrap/javascript.html#carousel
+ * ==========================================================
+ * Copyright 2012 Twitter, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ========================================================== */
+
+
+!function ($) {
+
+  "use strict"; // jshint ;_;
+
+
+ /* CAROUSEL CLASS DEFINITION
+  * ========================= */
+
+  var Carousel = function (element, options) {
+    this.$element = $(element)
+    this.$indicators = this.$element.find('.carousel-indicators')
+    this.options = options
+    this.options.pause == 'hover' && this.$element
+      .on('mouseenter', $.proxy(this.pause, this))
+      .on('mouseleave', $.proxy(this.cycle, this))
+  }
+
+  Carousel.prototype = {
+
+    cycle: function (e) {
+      if (!e) this.paused = false
+      if (this.interval) clearInterval(this.interval);
+      this.options.interval
+        && !this.paused
+        && (this.interval = setInterval($.proxy(this.next, this), this.options.interval))
+      return this
+    }
+
+  , getActiveIndex: function () {
+      this.$active = this.$element.find('.item.active')
+      this.$items = this.$active.parent().children()
+      return this.$items.index(this.$active)
+    }
+
+  , to: function (pos) {
+      var activeIndex = this.getActiveIndex()
+        , that = this
+
+      if (pos > (this.$items.length - 1) || pos < 0) return
+
+      if (this.sliding) {
+        return this.$element.one('slid', function () {
+          that.to(pos)
+        })
+      }
+
+      if (activeIndex == pos) {
+        return this.pause().cycle()
+      }
+
+      return this.slide(pos > activeIndex ? 'next' : 'prev', $(this.$items[pos]))
+    }
+
+  , pause: function (e) {
+      if (!e) this.paused = true
+      if (this.$element.find('.next, .prev').length && $.support.transition.end) {
+        this.$element.trigger($.support.transition.end)
+        this.cycle(true)
+      }
+      clearInterval(this.interval)
+      this.interval = null
+      return this
+    }
+
+  , next: function () {
+      if (this.sliding) return
+      return this.slide('next')
+    }
+
+  , prev: function () {
+      if (this.sliding) return
+      return this.slide('prev')
+    }
+
+  , slide: function (type, next) {
+      var $active = this.$element.find('.item.active')
+        , $next = next || $active[type]()
+        , isCycling = this.interval
+        , direction = type == 'next' ? 'left' : 'right'
+        , fallback  = type == 'next' ? 'first' : 'last'
+        , that = this
+        , e
+
+      this.sliding = true
+
+      isCycling && this.pause()
+
+      $next = $next.length ? $next : this.$element.find('.item')[fallback]()
+
+      e = $.Event('slide', {
+        relatedTarget: $next[0]
+      , direction: direction
+      })
+
+      if ($next.hasClass('active')) return
+
+      if (this.$indicators.length) {
+        this.$indicators.find('.active').removeClass('active')
+        this.$element.one('slid', function () {
+          var $nextIndicator = $(that.$indicators.children()[that.getActiveIndex()])
+          $nextIndicator && $nextIndicator.addClass('active')
+        })
+      }
+
+      if ($.support.transition && this.$element.hasClass('slide')) {
+        this.$element.trigger(e)
+        if (e.isDefaultPrevented()) return
+        $next.addClass(type)
+        $next[0].offsetWidth // force reflow
+        $active.addClass(direction)
+        $next.addClass(direction)
+        this.$element.one($.support.transition.end, function () {
+          $next.removeClass([type, direction].join(' ')).addClass('active')
+          $active.removeClass(['active', direction].join(' '))
+          that.sliding = false
+          setTimeout(function () { that.$element.trigger('slid') }, 0)
+        })
+      } else {
+        this.$element.trigger(e)
+        if (e.isDefaultPrevented()) return
+        $active.removeClass('active')
+        $next.addClass('active')
+        this.sliding = false
+        this.$element.trigger('slid')
+      }
+
+      isCycling && this.cycle()
+
+      return this
+    }
+
+  }
+
+
+ /* CAROUSEL PLUGIN DEFINITION
+  * ========================== */
+
+  var old = $.fn.carousel
+
+  $.fn.carousel = function (option) {
+    return this.each(function () {
+      var $this = $(this)
+        , data = $this.data('carousel')
+        , options = $.extend({}, $.fn.carousel.defaults, typeof option == 'object' && option)
+        , action = typeof option == 'string' ? option : options.slide
+      if (!data) $this.data('carousel', (data = new Carousel(this, options)))
+      if (typeof option == 'number') data.to(option)
+      else if (action) data[action]()
+      else if (options.interval) data.pause().cycle()
+    })
+  }
+
+  $.fn.carousel.defaults = {
+    interval: 5000
+  , pause: 'hover'
+  }
+
+  $.fn.carousel.Constructor = Carousel
+
+
+ /* CAROUSEL NO CONFLICT
+  * ==================== */
+
+  $.fn.carousel.noConflict = function () {
+    $.fn.carousel = old
+    return this
+  }
+
+ /* CAROUSEL DATA-API
+  * ================= */
+
+  $(document).on('click.carousel.data-api', '[data-slide], [data-slide-to]', function (e) {
+    var $this = $(this), href
+      , $target = $($this.attr('data-target') || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '')) //strip for ie7
+      , options = $.extend({}, $target.data(), $this.data())
+      , slideIndex
+
+    $target.carousel(options)
+
+    if (slideIndex = $this.attr('data-slide-to')) {
+      $target.data('carousel').pause().to(slideIndex).cycle()
+    }
+
+    e.preventDefault()
+  })
+
+}(window.jQuery);/* =============================================================
+ * bootstrap-collapse.js v2.3.1
+ * http://twitter.github.com/bootstrap/javascript.html#collapse
+ * =============================================================
+ * Copyright 2012 Twitter, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============================================================ */
+
+
+!function ($) {
+
+  "use strict"; // jshint ;_;
+
+
+ /* COLLAPSE PUBLIC CLASS DEFINITION
+  * ================================ */
+
+  var Collapse = function (element, options) {
+    this.$element = $(element)
+    this.options = $.extend({}, $.fn.collapse.defaults, options)
+
+    if (this.options.parent) {
+      this.$parent = $(this.options.parent)
+    }
+
+    this.options.toggle && this.toggle()
+  }
+
+  Collapse.prototype = {
+
+    constructor: Collapse
+
+  , dimension: function () {
+      var hasWidth = this.$element.hasClass('width')
+      return hasWidth ? 'width' : 'height'
+    }
+
+  , show: function () {
+      var dimension
+        , scroll
+        , actives
+        , hasData
+
+      if (this.transitioning || this.$element.hasClass('in')) return
+
+      dimension = this.dimension()
+      scroll = $.camelCase(['scroll', dimension].join('-'))
+      actives = this.$parent && this.$parent.find('> .accordion-group > .in')
+
+      if (actives && actives.length) {
+        hasData = actives.data('collapse')
+        if (hasData && hasData.transitioning) return
+        actives.collapse('hide')
+        hasData || actives.data('collapse', null)
+      }
+
+      this.$element[dimension](0)
+      this.transition('addClass', $.Event('show'), 'shown')
+      $.support.transition && this.$element[dimension](this.$element[0][scroll])
+    }
+
+  , hide: function () {
+      var dimension
+      if (this.transitioning || !this.$element.hasClass('in')) return
+      dimension = this.dimension()
+      this.reset(this.$element[dimension]())
+      this.transition('removeClass', $.Event('hide'), 'hidden')
+      this.$element[dimension](0)
+    }
+
+  , reset: function (size) {
+      var dimension = this.dimension()
+
+      this.$element
+        .removeClass('collapse')
+        [dimension](size || 'auto')
+        [0].offsetWidth
+
+      this.$element[size !== null ? 'addClass' : 'removeClass']('collapse')
+
+      return this
+    }
+
+  , transition: function (method, startEvent, completeEvent) {
+      var that = this
+        , complete = function () {
+            if (startEvent.type == 'show') that.reset()
+            that.transitioning = 0
+            that.$element.trigger(completeEvent)
+          }
+
+      this.$element.trigger(startEvent)
+
+      if (startEvent.isDefaultPrevented()) return
+
+      this.transitioning = 1
+
+      this.$element[method]('in')
+
+      $.support.transition && this.$element.hasClass('collapse') ?
+        this.$element.one($.support.transition.end, complete) :
+        complete()
+    }
+
+  , toggle: function () {
+      this[this.$element.hasClass('in') ? 'hide' : 'show']()
+    }
+
+  }
+
+
+ /* COLLAPSE PLUGIN DEFINITION
+  * ========================== */
+
+  var old = $.fn.collapse
+
+  $.fn.collapse = function (option) {
+    return this.each(function () {
+      var $this = $(this)
+        , data = $this.data('collapse')
+        , options = $.extend({}, $.fn.collapse.defaults, $this.data(), typeof option == 'object' && option)
+      if (!data) $this.data('collapse', (data = new Collapse(this, options)))
+      if (typeof option == 'string') data[option]()
+    })
+  }
+
+  $.fn.collapse.defaults = {
+    toggle: true
+  }
+
+  $.fn.collapse.Constructor = Collapse
+
+
+ /* COLLAPSE NO CONFLICT
+  * ==================== */
+
+  $.fn.collapse.noConflict = function () {
+    $.fn.collapse = old
+    return this
+  }
+
+
+ /* COLLAPSE DATA-API
+  * ================= */
+
+  $(document).on('click.collapse.data-api', '[data-toggle=collapse]', function (e) {
+    var $this = $(this), href
+      , target = $this.attr('data-target')
+        || e.preventDefault()
+        || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') //strip for ie7
+      , option = $(target).data('collapse') ? 'toggle' : $this.data()
+    $this[$(target).hasClass('in') ? 'addClass' : 'removeClass']('collapsed')
+    $(target).collapse(option)
+  })
+
+}(window.jQuery);/* ============================================================
+ * bootstrap-dropdown.js v2.3.1
+ * http://twitter.github.com/bootstrap/javascript.html#dropdowns
+ * ============================================================
+ * Copyright 2012 Twitter, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============================================================ */
+
+
+!function ($) {
+
+  "use strict"; // jshint ;_;
+
+
+ /* DROPDOWN CLASS DEFINITION
+  * ========================= */
+
+  var toggle = '[data-toggle=dropdown]'
+    , Dropdown = function (element) {
+        var $el = $(element).on('click.dropdown.data-api', this.toggle)
+        $('html').on('click.dropdown.data-api', function () {
+          $el.parent().removeClass('open')
+        })
+      }
+
+  Dropdown.prototype = {
+
+    constructor: Dropdown
+
+  , toggle: function (e) {
+      var $this = $(this)
+        , $parent
+        , isActive
+
+      if ($this.is('.disabled, :disabled')) return
+
+      $parent = getParent($this)
+
+      isActive = $parent.hasClass('open')
+
+      clearMenus()
+
+      if (!isActive) {
+        $parent.toggleClass('open')
+      }
+
+      $this.focus()
+
+      return false
+    }
+
+  , keydown: function (e) {
+      var $this
+        , $items
+        , $active
+        , $parent
+        , isActive
+        , index
+
+      if (!/(38|40|27)/.test(e.keyCode)) return
+
+      $this = $(this)
+
+      e.preventDefault()
+      e.stopPropagation()
+
+      if ($this.is('.disabled, :disabled')) return
+
+      $parent = getParent($this)
+
+      isActive = $parent.hasClass('open')
+
+      if (!isActive || (isActive && e.keyCode == 27)) {
+        if (e.which == 27) $parent.find(toggle).focus()
+        return $this.click()
+      }
+
+      $items = $('[role=menu] li:not(.divider):visible a', $parent)
+
+      if (!$items.length) return
+
+      index = $items.index($items.filter(':focus'))
+
+      if (e.keyCode == 38 && index > 0) index--                                        // up
+      if (e.keyCode == 40 && index < $items.length - 1) index++                        // down
+      if (!~index) index = 0
+
+      $items
+        .eq(index)
+        .focus()
+    }
+
+  }
+
+  function clearMenus() {
+    $(toggle).each(function () {
+      getParent($(this)).removeClass('open')
+    })
+  }
+
+  function getParent($this) {
+    var selector = $this.attr('data-target')
+      , $parent
+
+    if (!selector) {
+      selector = $this.attr('href')
+      selector = selector && /#/.test(selector) && selector.replace(/.*(?=#[^\s]*$)/, '') //strip for ie7
+    }
+
+    $parent = selector && $(selector)
+
+    if (!$parent || !$parent.length) $parent = $this.parent()
+
+    return $parent
+  }
+
+
+  /* DROPDOWN PLUGIN DEFINITION
+   * ========================== */
+
+  var old = $.fn.dropdown
+
+  $.fn.dropdown = function (option) {
+    return this.each(function () {
+      var $this = $(this)
+        , data = $this.data('dropdown')
+      if (!data) $this.data('dropdown', (data = new Dropdown(this)))
+      if (typeof option == 'string') data[option].call($this)
+    })
+  }
+
+  $.fn.dropdown.Constructor = Dropdown
+
+
+ /* DROPDOWN NO CONFLICT
+  * ==================== */
+
+  $.fn.dropdown.noConflict = function () {
+    $.fn.dropdown = old
+    return this
+  }
+
+
+  /* APPLY TO STANDARD DROPDOWN ELEMENTS
+   * =================================== */
+
+  $(document)
+    .on('click.dropdown.data-api', clearMenus)
+    .on('click.dropdown.data-api', '.dropdown form', function (e) { e.stopPropagation() })
+    .on('click.dropdown-menu', function (e) { e.stopPropagation() })
+    .on('click.dropdown.data-api'  , toggle, Dropdown.prototype.toggle)
+    .on('keydown.dropdown.data-api', toggle + ', [role=menu]' , Dropdown.prototype.keydown)
+
+}(window.jQuery);
+/* =========================================================
+ * bootstrap-modal.js v2.3.1
+ * http://twitter.github.com/bootstrap/javascript.html#modals
+ * =========================================================
+ * Copyright 2012 Twitter, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ========================================================= */
+
+
+!function ($) {
+
+  "use strict"; // jshint ;_;
+
+
+ /* MODAL CLASS DEFINITION
+  * ====================== */
+
+  var Modal = function (element, options) {
+    this.options = options
+    this.$element = $(element)
+      .delegate('[data-dismiss="modal"]', 'click.dismiss.modal', $.proxy(this.hide, this))
+    this.options.remote && this.$element.find('.modal-body').load(this.options.remote)
+  }
+
+  Modal.prototype = {
+
+      constructor: Modal
+
+    , toggle: function () {
+        return this[!this.isShown ? 'show' : 'hide']()
+      }
+
+    , show: function () {
+        var that = this
+          , e = $.Event('show')
+
+        this.$element.trigger(e)
+
+        if (this.isShown || e.isDefaultPrevented()) return
+
+        this.isShown = true
+
+        this.escape()
+
+        this.backdrop(function () {
+          var transition = $.support.transition && that.$element.hasClass('fade')
+
+          if (!that.$element.parent().length) {
+            that.$element.appendTo(document.body) //don't move modals dom position
+          }
+
+          that.$element.show()
+
+          if (transition) {
+            that.$element[0].offsetWidth // force reflow
+          }
+
+          that.$element
+            .addClass('in')
+            .attr('aria-hidden', false)
+
+          that.enforceFocus()
+
+          transition ?
+            that.$element.one($.support.transition.end, function () { that.$element.focus().trigger('shown') }) :
+            that.$element.focus().trigger('shown')
+
+        })
+      }
+
+    , hide: function (e) {
+        e && e.preventDefault()
+
+        var that = this
+
+        e = $.Event('hide')
+
+        this.$element.trigger(e)
+
+        if (!this.isShown || e.isDefaultPrevented()) return
+
+        this.isShown = false
+
+        this.escape()
+
+        $(document).off('focusin.modal')
+
+        this.$element
+          .removeClass('in')
+          .attr('aria-hidden', true)
+
+        $.support.transition && this.$element.hasClass('fade') ?
+          this.hideWithTransition() :
+          this.hideModal()
+      }
+
+    , enforceFocus: function () {
+        var that = this
+        $(document).on('focusin.modal', function (e) {
+          if (that.$element[0] !== e.target && !that.$element.has(e.target).length) {
+            that.$element.focus()
+          }
+        })
+      }
+
+    , escape: function () {
+        var that = this
+        if (this.isShown && this.options.keyboard) {
+          this.$element.on('keyup.dismiss.modal', function ( e ) {
+            e.which == 27 && that.hide()
+          })
+        } else if (!this.isShown) {
+          this.$element.off('keyup.dismiss.modal')
+        }
+      }
+
+    , hideWithTransition: function () {
+        var that = this
+          , timeout = setTimeout(function () {
+              that.$element.off($.support.transition.end)
+              that.hideModal()
+            }, 500)
+
+        this.$element.one($.support.transition.end, function () {
+          clearTimeout(timeout)
+          that.hideModal()
+        })
+      }
+
+    , hideModal: function () {
+        var that = this
+        this.$element.hide()
+        this.backdrop(function () {
+          that.removeBackdrop()
+          that.$element.trigger('hidden')
+        })
+      }
+
+    , removeBackdrop: function () {
+        this.$backdrop && this.$backdrop.remove()
+        this.$backdrop = null
+      }
+
+    , backdrop: function (callback) {
+        var that = this
+          , animate = this.$element.hasClass('fade') ? 'fade' : ''
+
+        if (this.isShown && this.options.backdrop) {
+          var doAnimate = $.support.transition && animate
+
+          this.$backdrop = $('<div class="modal-backdrop ' + animate + '" />')
+            .appendTo(document.body)
+
+          this.$backdrop.click(
+            this.options.backdrop == 'static' ?
+              $.proxy(this.$element[0].focus, this.$element[0])
+            : $.proxy(this.hide, this)
+          )
+
+          if (doAnimate) this.$backdrop[0].offsetWidth // force reflow
+
+          this.$backdrop.addClass('in')
+
+          if (!callback) return
+
+          doAnimate ?
+            this.$backdrop.one($.support.transition.end, callback) :
+            callback()
+
+        } else if (!this.isShown && this.$backdrop) {
+          this.$backdrop.removeClass('in')
+
+          $.support.transition && this.$element.hasClass('fade')?
+            this.$backdrop.one($.support.transition.end, callback) :
+            callback()
+
+        } else if (callback) {
+          callback()
+        }
+      }
+  }
+
+
+ /* MODAL PLUGIN DEFINITION
+  * ======================= */
+
+  var old = $.fn.modal
+
+  $.fn.modal = function (option) {
+    return this.each(function () {
+      var $this = $(this)
+        , data = $this.data('modal')
+        , options = $.extend({}, $.fn.modal.defaults, $this.data(), typeof option == 'object' && option)
+      if (!data) $this.data('modal', (data = new Modal(this, options)))
+      if (typeof option == 'string') data[option]()
+      else if (options.show) data.show()
+    })
+  }
+
+  $.fn.modal.defaults = {
+      backdrop: true
+    , keyboard: true
+    , show: true
+  }
+
+  $.fn.modal.Constructor = Modal
+
+
+ /* MODAL NO CONFLICT
+  * ================= */
+
+  $.fn.modal.noConflict = function () {
+    $.fn.modal = old
+    return this
+  }
+
+
+ /* MODAL DATA-API
+  * ============== */
+
+  $(document).on('click.modal.data-api', '[data-toggle="modal"]', function (e) {
+    var $this = $(this)
+      , href = $this.attr('href')
+      , $target = $($this.attr('data-target') || (href && href.replace(/.*(?=#[^\s]+$)/, ''))) //strip for ie7
+      , option = $target.data('modal') ? 'toggle' : $.extend({ remote:!/#/.test(href) && href }, $target.data(), $this.data())
+
+    e.preventDefault()
+
+    $target
+      .modal(option)
+      .one('hide', function () {
+        $this.focus()
+      })
+  })
+
+}(window.jQuery);
+/* ===========================================================
+ * bootstrap-tooltip.js v2.3.1
+ * http://twitter.github.com/bootstrap/javascript.html#tooltips
+ * Inspired by the original jQuery.tipsy by Jason Frame
+ * ===========================================================
+ * Copyright 2012 Twitter, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ========================================================== */
+
+
+!function ($) {
+
+  "use strict"; // jshint ;_;
+
+
+ /* TOOLTIP PUBLIC CLASS DEFINITION
+  * =============================== */
+
+  var Tooltip = function (element, options) {
+    this.init('tooltip', element, options)
+  }
+
+  Tooltip.prototype = {
+
+    constructor: Tooltip
+
+  , init: function (type, element, options) {
+      var eventIn
+        , eventOut
+        , triggers
+        , trigger
+        , i
+
+      this.type = type
+      this.$element = $(element)
+      this.options = this.getOptions(options)
+      this.enabled = true
+
+      triggers = this.options.trigger.split(' ')
+
+      for (i = triggers.length; i--;) {
+        trigger = triggers[i]
+        if (trigger == 'click') {
+          this.$element.on('click.' + this.type, this.options.selector, $.proxy(this.toggle, this))
+        } else if (trigger != 'manual') {
+          eventIn = trigger == 'hover' ? 'mouseenter' : 'focus'
+          eventOut = trigger == 'hover' ? 'mouseleave' : 'blur'
+          this.$element.on(eventIn + '.' + this.type, this.options.selector, $.proxy(this.enter, this))
+          this.$element.on(eventOut + '.' + this.type, this.options.selector, $.proxy(this.leave, this))
+        }
+      }
+
+      this.options.selector ?
+        (this._options = $.extend({}, this.options, { trigger: 'manual', selector: '' })) :
+        this.fixTitle()
+    }
+
+  , getOptions: function (options) {
+      options = $.extend({}, $.fn[this.type].defaults, this.$element.data(), options)
+
+      if (options.delay && typeof options.delay == 'number') {
+        options.delay = {
+          show: options.delay
+        , hide: options.delay
+        }
+      }
+
+      return options
+    }
+
+  , enter: function (e) {
+      var defaults = $.fn[this.type].defaults
+        , options = {}
+        , self
+
+      this._options && $.each(this._options, function (key, value) {
+        if (defaults[key] != value) options[key] = value
+      }, this)
+
+      self = $(e.currentTarget)[this.type](options).data(this.type)
+
+      if (!self.options.delay || !self.options.delay.show) return self.show()
+
+      clearTimeout(this.timeout)
+      self.hoverState = 'in'
+      this.timeout = setTimeout(function() {
+        if (self.hoverState == 'in') self.show()
+      }, self.options.delay.show)
+    }
+
+  , leave: function (e) {
+      var self = $(e.currentTarget)[this.type](this._options).data(this.type)
+
+      if (this.timeout) clearTimeout(this.timeout)
+      if (!self.options.delay || !self.options.delay.hide) return self.hide()
+
+      self.hoverState = 'out'
+      this.timeout = setTimeout(function() {
+        if (self.hoverState == 'out') self.hide()
+      }, self.options.delay.hide)
+    }
+
+  , show: function () {
+      var $tip
+        , pos
+        , actualWidth
+        , actualHeight
+        , placement
+        , tp
+        , e = $.Event('show')
+
+      if (this.hasContent() && this.enabled) {
+        this.$element.trigger(e)
+        if (e.isDefaultPrevented()) return
+        $tip = this.tip()
+        this.setContent()
+
+        if (this.options.animation) {
+          $tip.addClass('fade')
+        }
+
+        placement = typeof this.options.placement == 'function' ?
+          this.options.placement.call(this, $tip[0], this.$element[0]) :
+          this.options.placement
+
+        $tip
+          .detach()
+          .css({ top: 0, left: 0, display: 'block' })
+
+        this.options.container ? $tip.appendTo(this.options.container) : $tip.insertAfter(this.$element)
+
+        pos = this.getPosition()
+
+        actualWidth = $tip[0].offsetWidth
+        actualHeight = $tip[0].offsetHeight
+
+        switch (placement) {
+          case 'bottom':
+            tp = {top: pos.top + pos.height, left: pos.left + pos.width / 2 - actualWidth / 2}
+            break
+          case 'top':
+            tp = {top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2}
+            break
+          case 'left':
+            tp = {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth}
+            break
+          case 'right':
+            tp = {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width}
+            break
+        }
+
+        this.applyPlacement(tp, placement)
+        this.$element.trigger('shown')
+      }
+    }
+
+  , applyPlacement: function(offset, placement){
+      var $tip = this.tip()
+        , width = $tip[0].offsetWidth
+        , height = $tip[0].offsetHeight
+        , actualWidth
+        , actualHeight
+        , delta
+        , replace
+
+      $tip
+        .offset(offset)
+        .addClass(placement)
+        .addClass('in')
+
+      actualWidth = $tip[0].offsetWidth
+      actualHeight = $tip[0].offsetHeight
+
+      if (placement == 'top' && actualHeight != height) {
+        offset.top = offset.top + height - actualHeight
+        replace = true
+      }
+
+      if (placement == 'bottom' || placement == 'top') {
+        delta = 0
+
+        if (offset.left < 0){
+          delta = offset.left * -2
+          offset.left = 0
+          $tip.offset(offset)
+          actualWidth = $tip[0].offsetWidth
+          actualHeight = $tip[0].offsetHeight
+        }
+
+        this.replaceArrow(delta - width + actualWidth, actualWidth, 'left')
+      } else {
+        this.replaceArrow(actualHeight - height, actualHeight, 'top')
+      }
+
+      if (replace) $tip.offset(offset)
+    }
+
+  , replaceArrow: function(delta, dimension, position){
+      this
+        .arrow()
+        .css(position, delta ? (50 * (1 - delta / dimension) + "%") : '')
+    }
+
+  , setContent: function () {
+      var $tip = this.tip()
+        , title = this.getTitle()
+
+      $tip.find('.tooltip-inner')[this.options.html ? 'html' : 'text'](title)
+      $tip.removeClass('fade in top bottom left right')
+    }
+
+  , hide: function () {
+      var that = this
+        , $tip = this.tip()
+        , e = $.Event('hide')
+
+      this.$element.trigger(e)
+      if (e.isDefaultPrevented()) return
+
+      $tip.removeClass('in')
+
+      function removeWithAnimation() {
+        var timeout = setTimeout(function () {
+          $tip.off($.support.transition.end).detach()
+        }, 500)
+
+        $tip.one($.support.transition.end, function () {
+          clearTimeout(timeout)
+          $tip.detach()
+        })
+      }
+
+      $.support.transition && this.$tip.hasClass('fade') ?
+        removeWithAnimation() :
+        $tip.detach()
+
+      this.$element.trigger('hidden')
+
+      return this
+    }
+
+  , fixTitle: function () {
+      var $e = this.$element
+      if ($e.attr('title') || typeof($e.attr('data-original-title')) != 'string') {
+        $e.attr('data-original-title', $e.attr('title') || '').attr('title', '')
+      }
+    }
+
+  , hasContent: function () {
+      return this.getTitle()
+    }
+
+  , getPosition: function () {
+      var el = this.$element[0]
+      return $.extend({}, (typeof el.getBoundingClientRect == 'function') ? el.getBoundingClientRect() : {
+        width: el.offsetWidth
+      , height: el.offsetHeight
+      }, this.$element.offset())
+    }
+
+  , getTitle: function () {
+      var title
+        , $e = this.$element
+        , o = this.options
+
+      title = $e.attr('data-original-title')
+        || (typeof o.title == 'function' ? o.title.call($e[0]) :  o.title)
+
+      return title
+    }
+
+  , tip: function () {
+      return this.$tip = this.$tip || $(this.options.template)
+    }
+
+  , arrow: function(){
+      return this.$arrow = this.$arrow || this.tip().find(".tooltip-arrow")
+    }
+
+  , validate: function () {
+      if (!this.$element[0].parentNode) {
+        this.hide()
+        this.$element = null
+        this.options = null
+      }
+    }
+
+  , enable: function () {
+      this.enabled = true
+    }
+
+  , disable: function () {
+      this.enabled = false
+    }
+
+  , toggleEnabled: function () {
+      this.enabled = !this.enabled
+    }
+
+  , toggle: function (e) {
+      var self = e ? $(e.currentTarget)[this.type](this._options).data(this.type) : this
+      self.tip().hasClass('in') ? self.hide() : self.show()
+    }
+
+  , destroy: function () {
+      this.hide().$element.off('.' + this.type).removeData(this.type)
+    }
+
+  }
+
+
+ /* TOOLTIP PLUGIN DEFINITION
+  * ========================= */
+
+  var old = $.fn.tooltip
+
+  $.fn.tooltip = function ( option ) {
+    return this.each(function () {
+      var $this = $(this)
+        , data = $this.data('tooltip')
+        , options = typeof option == 'object' && option
+      if (!data) $this.data('tooltip', (data = new Tooltip(this, options)))
+      if (typeof option == 'string') data[option]()
+    })
+  }
+
+  $.fn.tooltip.Constructor = Tooltip
+
+  $.fn.tooltip.defaults = {
+    animation: true
+  , placement: 'top'
+  , selector: false
+  , template: '<div class="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>'
+  , trigger: 'hover focus'
+  , title: ''
+  , delay: 0
+  , html: false
+  , container: false
+  }
+
+
+ /* TOOLTIP NO CONFLICT
+  * =================== */
+
+  $.fn.tooltip.noConflict = function () {
+    $.fn.tooltip = old
+    return this
+  }
+
+}(window.jQuery);
+/* ===========================================================
+ * bootstrap-popover.js v2.3.1
+ * http://twitter.github.com/bootstrap/javascript.html#popovers
+ * ===========================================================
+ * Copyright 2012 Twitter, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =========================================================== */
+
+
+!function ($) {
+
+  "use strict"; // jshint ;_;
+
+
+ /* POPOVER PUBLIC CLASS DEFINITION
+  * =============================== */
+
+  var Popover = function (element, options) {
+    this.init('popover', element, options)
+  }
+
+
+  /* NOTE: POPOVER EXTENDS BOOTSTRAP-TOOLTIP.js
+     ========================================== */
+
+  Popover.prototype = $.extend({}, $.fn.tooltip.Constructor.prototype, {
+
+    constructor: Popover
+
+  , setContent: function () {
+      var $tip = this.tip()
+        , title = this.getTitle()
+        , content = this.getContent()
+
+      $tip.find('.popover-title')[this.options.html ? 'html' : 'text'](title)
+      $tip.find('.popover-content')[this.options.html ? 'html' : 'text'](content)
+
+      $tip.removeClass('fade top bottom left right in')
+    }
+
+  , hasContent: function () {
+      return this.getTitle() || this.getContent()
+    }
+
+  , getContent: function () {
+      var content
+        , $e = this.$element
+        , o = this.options
+
+      content = (typeof o.content == 'function' ? o.content.call($e[0]) :  o.content)
+        || $e.attr('data-content')
+
+      return content
+    }
+
+  , tip: function () {
+      if (!this.$tip) {
+        this.$tip = $(this.options.template)
+      }
+      return this.$tip
+    }
+
+  , destroy: function () {
+      this.hide().$element.off('.' + this.type).removeData(this.type)
+    }
+
+  })
+
+
+ /* POPOVER PLUGIN DEFINITION
+  * ======================= */
+
+  var old = $.fn.popover
+
+  $.fn.popover = function (option) {
+    return this.each(function () {
+      var $this = $(this)
+        , data = $this.data('popover')
+        , options = typeof option == 'object' && option
+      if (!data) $this.data('popover', (data = new Popover(this, options)))
+      if (typeof option == 'string') data[option]()
+    })
+  }
+
+  $.fn.popover.Constructor = Popover
+
+  $.fn.popover.defaults = $.extend({} , $.fn.tooltip.defaults, {
+    placement: 'right'
+  , trigger: 'click'
+  , content: ''
+  , template: '<div class="popover"><div class="arrow"></div><h3 class="popover-title"></h3><div class="popover-content"></div></div>'
+  })
+
+
+ /* POPOVER NO CONFLICT
+  * =================== */
+
+  $.fn.popover.noConflict = function () {
+    $.fn.popover = old
+    return this
+  }
+
+}(window.jQuery);
+/* =============================================================
+ * bootstrap-scrollspy.js v2.3.1
+ * http://twitter.github.com/bootstrap/javascript.html#scrollspy
+ * =============================================================
+ * Copyright 2012 Twitter, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============================================================== */
+
+
+!function ($) {
+
+  "use strict"; // jshint ;_;
+
+
+ /* SCROLLSPY CLASS DEFINITION
+  * ========================== */
+
+  function ScrollSpy(element, options) {
+    var process = $.proxy(this.process, this)
+      , $element = $(element).is('body') ? $(window) : $(element)
+      , href
+    this.options = $.extend({}, $.fn.scrollspy.defaults, options)
+    this.$scrollElement = $element.on('scroll.scroll-spy.data-api', process)
+    this.selector = (this.options.target
+      || ((href = $(element).attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '')) //strip for ie7
+      || '') + ' .nav li > a'
+    this.$body = $('body')
+    this.refresh()
+    this.process()
+  }
+
+  ScrollSpy.prototype = {
+
+      constructor: ScrollSpy
+
+    , refresh: function () {
+        var self = this
+          , $targets
+
+        this.offsets = $([])
+        this.targets = $([])
+
+        $targets = this.$body
+          .find(this.selector)
+          .map(function () {
+            var $el = $(this)
+              , href = $el.data('target') || $el.attr('href')
+              , $href = /^#\w/.test(href) && $(href)
+            return ( $href
+              && $href.length
+              && [[ $href.position().top + (!$.isWindow(self.$scrollElement.get(0)) && self.$scrollElement.scrollTop()), href ]] ) || null
+          })
+          .sort(function (a, b) { return a[0] - b[0] })
+          .each(function () {
+            self.offsets.push(this[0])
+            self.targets.push(this[1])
+          })
+      }
+
+    , process: function () {
+        var scrollTop = this.$scrollElement.scrollTop() + this.options.offset
+          , scrollHeight = this.$scrollElement[0].scrollHeight || this.$body[0].scrollHeight
+          , maxScroll = scrollHeight - this.$scrollElement.height()
+          , offsets = this.offsets
+          , targets = this.targets
+          , activeTarget = this.activeTarget
+          , i
+
+        if (scrollTop >= maxScroll) {
+          return activeTarget != (i = targets.last()[0])
+            && this.activate ( i )
+        }
+
+        for (i = offsets.length; i--;) {
+          activeTarget != targets[i]
+            && scrollTop >= offsets[i]
+            && (!offsets[i + 1] || scrollTop <= offsets[i + 1])
+            && this.activate( targets[i] )
+        }
+      }
+
+    , activate: function (target) {
+        var active
+          , selector
+
+        this.activeTarget = target
+
+        $(this.selector)
+          .parent('.active')
+          .removeClass('active')
+
+        selector = this.selector
+          + '[data-target="' + target + '"],'
+          + this.selector + '[href="' + target + '"]'
+
+        active = $(selector)
+          .parent('li')
+          .addClass('active')
+
+        if (active.parent('.dropdown-menu').length)  {
+          active = active.closest('li.dropdown').addClass('active')
+        }
+
+        active.trigger('activate')
+      }
+
+  }
+
+
+ /* SCROLLSPY PLUGIN DEFINITION
+  * =========================== */
+
+  var old = $.fn.scrollspy
+
+  $.fn.scrollspy = function (option) {
+    return this.each(function () {
+      var $this = $(this)
+        , data = $this.data('scrollspy')
+        , options = typeof option == 'object' && option
+      if (!data) $this.data('scrollspy', (data = new ScrollSpy(this, options)))
+      if (typeof option == 'string') data[option]()
+    })
+  }
+
+  $.fn.scrollspy.Constructor = ScrollSpy
+
+  $.fn.scrollspy.defaults = {
+    offset: 10
+  }
+
+
+ /* SCROLLSPY NO CONFLICT
+  * ===================== */
+
+  $.fn.scrollspy.noConflict = function () {
+    $.fn.scrollspy = old
+    return this
+  }
+
+
+ /* SCROLLSPY DATA-API
+  * ================== */
+
+  $(window).on('load', function () {
+    $('[data-spy="scroll"]').each(function () {
+      var $spy = $(this)
+      $spy.scrollspy($spy.data())
+    })
+  })
+
+}(window.jQuery);/* ========================================================
+ * bootstrap-tab.js v2.3.1
+ * http://twitter.github.com/bootstrap/javascript.html#tabs
+ * ========================================================
+ * Copyright 2012 Twitter, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ======================================================== */
+
+
+!function ($) {
+
+  "use strict"; // jshint ;_;
+
+
+ /* TAB CLASS DEFINITION
+  * ==================== */
+
+  var Tab = function (element) {
+    this.element = $(element)
+  }
+
+  Tab.prototype = {
+
+    constructor: Tab
+
+  , show: function () {
+      var $this = this.element
+        , $ul = $this.closest('ul:not(.dropdown-menu)')
+        , selector = $this.attr('data-target')
+        , previous
+        , $target
+        , e
+
+      if (!selector) {
+        selector = $this.attr('href')
+        selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') //strip for ie7
+      }
+
+      if ( $this.parent('li').hasClass('active') ) return
+
+      previous = $ul.find('.active:last a')[0]
+
+      e = $.Event('show', {
+        relatedTarget: previous
+      })
+
+      $this.trigger(e)
+
+      if (e.isDefaultPrevented()) return
+
+      $target = $(selector)
+
+      this.activate($this.parent('li'), $ul)
+      this.activate($target, $target.parent(), function () {
+        $this.trigger({
+          type: 'shown'
+        , relatedTarget: previous
+        })
+      })
+    }
+
+  , activate: function ( element, container, callback) {
+      var $active = container.find('> .active')
+        , transition = callback
+            && $.support.transition
+            && $active.hasClass('fade')
+
+      function next() {
+        $active
+          .removeClass('active')
+          .find('> .dropdown-menu > .active')
+          .removeClass('active')
+
+        element.addClass('active')
+
+        if (transition) {
+          element[0].offsetWidth // reflow for transition
+          element.addClass('in')
+        } else {
+          element.removeClass('fade')
+        }
+
+        if ( element.parent('.dropdown-menu') ) {
+          element.closest('li.dropdown').addClass('active')
+        }
+
+        callback && callback()
+      }
+
+      transition ?
+        $active.one($.support.transition.end, next) :
+        next()
+
+      $active.removeClass('in')
+    }
+  }
+
+
+ /* TAB PLUGIN DEFINITION
+  * ===================== */
+
+  var old = $.fn.tab
+
+  $.fn.tab = function ( option ) {
+    return this.each(function () {
+      var $this = $(this)
+        , data = $this.data('tab')
+      if (!data) $this.data('tab', (data = new Tab(this)))
+      if (typeof option == 'string') data[option]()
+    })
+  }
+
+  $.fn.tab.Constructor = Tab
+
+
+ /* TAB NO CONFLICT
+  * =============== */
+
+  $.fn.tab.noConflict = function () {
+    $.fn.tab = old
+    return this
+  }
+
+
+ /* TAB DATA-API
+  * ============ */
+
+  $(document).on('click.tab.data-api', '[data-toggle="tab"], [data-toggle="pill"]', function (e) {
+    e.preventDefault()
+    $(this).tab('show')
+  })
+
+}(window.jQuery);/* =============================================================
+ * bootstrap-typeahead.js v2.3.1
+ * http://twitter.github.com/bootstrap/javascript.html#typeahead
+ * =============================================================
+ * Copyright 2012 Twitter, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============================================================ */
+
+
+!function($){
+
+  "use strict"; // jshint ;_;
+
+
+ /* TYPEAHEAD PUBLIC CLASS DEFINITION
+  * ================================= */
+
+  var Typeahead = function (element, options) {
+    this.$element = $(element)
+    this.options = $.extend({}, $.fn.typeahead.defaults, options)
+    this.matcher = this.options.matcher || this.matcher
+    this.sorter = this.options.sorter || this.sorter
+    this.highlighter = this.options.highlighter || this.highlighter
+    this.updater = this.options.updater || this.updater
+    this.source = this.options.source
+    this.$menu = $(this.options.menu)
+    this.shown = false
+    this.listen()
+  }
+
+  Typeahead.prototype = {
+
+    constructor: Typeahead
+
+  , select: function () {
+      var val = this.$menu.find('.active').attr('data-value')
+      this.$element
+        .val(this.updater(val))
+        .change()
+      return this.hide()
+    }
+
+  , updater: function (item) {
+      return item
+    }
+
+  , show: function () {
+      var pos = $.extend({}, this.$element.position(), {
+        height: this.$element[0].offsetHeight
+      })
+
+      this.$menu
+        .insertAfter(this.$element)
+        .css({
+          top: pos.top + pos.height
+        , left: pos.left
+        })
+        .show()
+
+      this.shown = true
+      return this
+    }
+
+  , hide: function () {
+      this.$menu.hide()
+      this.shown = false
+      return this
+    }
+
+  , lookup: function (event) {
+      var items
+
+      this.query = this.$element.val()
+
+      if (!this.query || this.query.length < this.options.minLength) {
+        return this.shown ? this.hide() : this
+      }
+
+      items = $.isFunction(this.source) ? this.source(this.query, $.proxy(this.process, this)) : this.source
+
+      return items ? this.process(items) : this
+    }
+
+  , process: function (items) {
+      var that = this
+
+      items = $.grep(items, function (item) {
+        return that.matcher(item)
+      })
+
+      items = this.sorter(items)
+
+      if (!items.length) {
+        return this.shown ? this.hide() : this
+      }
+
+      return this.render(items.slice(0, this.options.items)).show()
+    }
+
+  , matcher: function (item) {
+      return ~item.toLowerCase().indexOf(this.query.toLowerCase())
+    }
+
+  , sorter: function (items) {
+      var beginswith = []
+        , caseSensitive = []
+        , caseInsensitive = []
+        , item
+
+      while (item = items.shift()) {
+        if (!item.toLowerCase().indexOf(this.query.toLowerCase())) beginswith.push(item)
+        else if (~item.indexOf(this.query)) caseSensitive.push(item)
+        else caseInsensitive.push(item)
+      }
+
+      return beginswith.concat(caseSensitive, caseInsensitive)
+    }
+
+  , highlighter: function (item) {
+      var query = this.query.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g, '\\$&')
+      return item.replace(new RegExp('(' + query + ')', 'ig'), function ($1, match) {
+        return '<strong>' + match + '</strong>'
+      })
+    }
+
+  , render: function (items) {
+      var that = this
+
+      items = $(items).map(function (i, item) {
+        i = $(that.options.item).attr('data-value', item)
+        i.find('a').html(that.highlighter(item))
+        return i[0]
+      })
+
+      items.first().addClass('active')
+      this.$menu.html(items)
+      return this
+    }
+
+  , next: function (event) {
+      var active = this.$menu.find('.active').removeClass('active')
+        , next = active.next()
+
+      if (!next.length) {
+        next = $(this.$menu.find('li')[0])
+      }
+
+      next.addClass('active')
+    }
+
+  , prev: function (event) {
+      var active = this.$menu.find('.active').removeClass('active')
+        , prev = active.prev()
+
+      if (!prev.length) {
+        prev = this.$menu.find('li').last()
+      }
+
+      prev.addClass('active')
+    }
+
+  , listen: function () {
+      this.$element
+        .on('focus',    $.proxy(this.focus, this))
+        .on('blur',     $.proxy(this.blur, this))
+        .on('keypress', $.proxy(this.keypress, this))
+        .on('keyup',    $.proxy(this.keyup, this))
+
+      if (this.eventSupported('keydown')) {
+        this.$element.on('keydown', $.proxy(this.keydown, this))
+      }
+
+      this.$menu
+        .on('click', $.proxy(this.click, this))
+        .on('mouseenter', 'li', $.proxy(this.mouseenter, this))
+        .on('mouseleave', 'li', $.proxy(this.mouseleave, this))
+    }
+
+  , eventSupported: function(eventName) {
+      var isSupported = eventName in this.$element
+      if (!isSupported) {
+        this.$element.setAttribute(eventName, 'return;')
+        isSupported = typeof this.$element[eventName] === 'function'
+      }
+      return isSupported
+    }
+
+  , move: function (e) {
+      if (!this.shown) return
+
+      switch(e.keyCode) {
+        case 9: // tab
+        case 13: // enter
+        case 27: // escape
+          e.preventDefault()
+          break
+
+        case 38: // up arrow
+          e.preventDefault()
+          this.prev()
+          break
+
+        case 40: // down arrow
+          e.preventDefault()
+          this.next()
+          break
+      }
+
+      e.stopPropagation()
+    }
+
+  , keydown: function (e) {
+      this.suppressKeyPressRepeat = ~$.inArray(e.keyCode, [40,38,9,13,27])
+      this.move(e)
+    }
+
+  , keypress: function (e) {
+      if (this.suppressKeyPressRepeat) return
+      this.move(e)
+    }
+
+  , keyup: function (e) {
+      switch(e.keyCode) {
+        case 40: // down arrow
+        case 38: // up arrow
+        case 16: // shift
+        case 17: // ctrl
+        case 18: // alt
+          break
+
+        case 9: // tab
+        case 13: // enter
+          if (!this.shown) return
+          this.select()
+          break
+
+        case 27: // escape
+          if (!this.shown) return
+          this.hide()
+          break
+
+        default:
+          this.lookup()
+      }
+
+      e.stopPropagation()
+      e.preventDefault()
+  }
+
+  , focus: function (e) {
+      this.focused = true
+    }
+
+  , blur: function (e) {
+      this.focused = false
+      if (!this.mousedover && this.shown) this.hide()
+    }
+
+  , click: function (e) {
+      e.stopPropagation()
+      e.preventDefault()
+      this.select()
+      this.$element.focus()
+    }
+
+  , mouseenter: function (e) {
+      this.mousedover = true
+      this.$menu.find('.active').removeClass('active')
+      $(e.currentTarget).addClass('active')
+    }
+
+  , mouseleave: function (e) {
+      this.mousedover = false
+      if (!this.focused && this.shown) this.hide()
+    }
+
+  }
+
+
+  /* TYPEAHEAD PLUGIN DEFINITION
+   * =========================== */
+
+  var old = $.fn.typeahead
+
+  $.fn.typeahead = function (option) {
+    return this.each(function () {
+      var $this = $(this)
+        , data = $this.data('typeahead')
+        , options = typeof option == 'object' && option
+      if (!data) $this.data('typeahead', (data = new Typeahead(this, options)))
+      if (typeof option == 'string') data[option]()
+    })
+  }
+
+  $.fn.typeahead.defaults = {
+    source: []
+  , items: 8
+  , menu: '<ul class="typeahead dropdown-menu"></ul>'
+  , item: '<li><a href="#"></a></li>'
+  , minLength: 1
+  }
+
+  $.fn.typeahead.Constructor = Typeahead
+
+
+ /* TYPEAHEAD NO CONFLICT
+  * =================== */
+
+  $.fn.typeahead.noConflict = function () {
+    $.fn.typeahead = old
+    return this
+  }
+
+
+ /* TYPEAHEAD DATA-API
+  * ================== */
+
+  $(document).on('focus.typeahead.data-api', '[data-provide="typeahead"]', function (e) {
+    var $this = $(this)
+    if ($this.data('typeahead')) return
+    $this.typeahead($this.data())
+  })
+
+}(window.jQuery);
+/* ==========================================================
+ * bootstrap-affix.js v2.3.1
+ * http://twitter.github.com/bootstrap/javascript.html#affix
+ * ==========================================================
+ * Copyright 2012 Twitter, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ========================================================== */
+
+
+!function ($) {
+
+  "use strict"; // jshint ;_;
+
+
+ /* AFFIX CLASS DEFINITION
+  * ====================== */
+
+  var Affix = function (element, options) {
+    this.options = $.extend({}, $.fn.affix.defaults, options)
+    this.$window = $(window)
+      .on('scroll.affix.data-api', $.proxy(this.checkPosition, this))
+      .on('click.affix.data-api',  $.proxy(function () { setTimeout($.proxy(this.checkPosition, this), 1) }, this))
+    this.$element = $(element)
+    this.checkPosition()
+  }
+
+  Affix.prototype.checkPosition = function () {
+    if (!this.$element.is(':visible')) return
+
+    var scrollHeight = $(document).height()
+      , scrollTop = this.$window.scrollTop()
+      , position = this.$element.offset()
+      , offset = this.options.offset
+      , offsetBottom = offset.bottom
+      , offsetTop = offset.top
+      , reset = 'affix affix-top affix-bottom'
+      , affix
+
+    if (typeof offset != 'object') offsetBottom = offsetTop = offset
+    if (typeof offsetTop == 'function') offsetTop = offset.top()
+    if (typeof offsetBottom == 'function') offsetBottom = offset.bottom()
+
+    affix = this.unpin != null && (scrollTop + this.unpin <= position.top) ?
+      false    : offsetBottom != null && (position.top + this.$element.height() >= scrollHeight - offsetBottom) ?
+      'bottom' : offsetTop != null && scrollTop <= offsetTop ?
+      'top'    : false
+
+    if (this.affixed === affix) return
+
+    this.affixed = affix
+    this.unpin = affix == 'bottom' ? position.top - scrollTop : null
+
+    this.$element.removeClass(reset).addClass('affix' + (affix ? '-' + affix : ''))
+  }
+
+
+ /* AFFIX PLUGIN DEFINITION
+  * ======================= */
+
+  var old = $.fn.affix
+
+  $.fn.affix = function (option) {
+    return this.each(function () {
+      var $this = $(this)
+        , data = $this.data('affix')
+        , options = typeof option == 'object' && option
+      if (!data) $this.data('affix', (data = new Affix(this, options)))
+      if (typeof option == 'string') data[option]()
+    })
+  }
+
+  $.fn.affix.Constructor = Affix
+
+  $.fn.affix.defaults = {
+    offset: 0
+  }
+
+
+ /* AFFIX NO CONFLICT
+  * ================= */
+
+  $.fn.affix.noConflict = function () {
+    $.fn.affix = old
+    return this
+  }
+
+
+ /* AFFIX DATA-API
+  * ============== */
+
+  $(window).on('load', function () {
+    $('[data-spy="affix"]').each(function () {
+      var $spy = $(this)
+        , data = $spy.data()
+
+      data.offset = data.offset || {}
+
+      data.offsetBottom && (data.offset.bottom = data.offsetBottom)
+      data.offsetTop && (data.offset.top = data.offsetTop)
+
+      $spy.affix(data)
+    })
+  })
+
+
+}(window.jQuery);
\ No newline at end of file


[03/51] [abbrv] [partial] Adding Jinwon's custom RCMET

Posted by jo...@apache.org.
http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/python/providers/.svn/text-base/pip.rb.svn-base
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/python/providers/.svn/text-base/pip.rb.svn-base b/src/main/vm/src/cookbooks/python/providers/.svn/text-base/pip.rb.svn-base
new file mode 100755
index 0000000..1c58e5e
--- /dev/null
+++ b/src/main/vm/src/cookbooks/python/providers/.svn/text-base/pip.rb.svn-base
@@ -0,0 +1,167 @@
+#
+# Author:: Seth Chisamore <sc...@opscode.com>
+# Cookbook Name:: python
+# Provider:: pip
+#
+# Copyright:: 2011, Opscode, Inc <le...@opscode.com>
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+require 'chef/mixin/shell_out'
+require 'chef/mixin/language'
+include Chef::Mixin::ShellOut
+
+# the logic in all action methods mirror that of
+# the Chef::Provider::Package which will make
+# refactoring into core chef easy
+
+action :install do
+  # If we specified a version, and it's not the current version, move to the specified version
+  if @new_resource.version != nil && @new_resource.version != @current_resource.version
+    install_version = @new_resource.version
+  # If it's not installed at all, install it
+  elsif @current_resource.version == nil
+    install_version = candidate_version
+  end
+
+  # Set the timeout (units in seconds)
+  timeout = 900
+  if @new_resource.timeout
+    timeout = @new_resource.timeout
+  end
+
+  if install_version
+    Chef::Log.info("Installing #{@new_resource} version #{install_version}")
+    status = install_package(@new_resource.package_name, install_version, timeout)
+    if status
+      @new_resource.updated_by_last_action(true)
+    end
+  end
+end
+
+action :upgrade do
+  # Set the timeout (units in seconds)
+  timeout = 900
+  if @new_resource.timeout
+    timeout = @new_resource.timeout
+  end
+
+  if @current_resource.version != candidate_version
+    orig_version = @current_resource.version || "uninstalled"
+    Chef::Log.info("Upgrading #{@new_resource} version from #{orig_version} to #{candidate_version}")
+    status = upgrade_package(@new_resource.package_name, candidate_version, timeout)
+    if status
+      @new_resource.updated_by_last_action(true)
+    end
+  end
+end
+
+action :remove do
+  # Set the timeout (units in seconds)
+  timeout = 900
+  if @new_resource.timeout
+    timeout = @new_resource.timeout
+  end
+
+  if removing_package?
+    Chef::Log.info("Removing #{@new_resource}")
+    remove_package(@current_resource.package_name, @new_resource.version, timeout)
+    @new_resource.updated_by_last_action(true)
+  else
+  end
+end
+
+def removing_package?
+  if @current_resource.version.nil?
+    false # nothing to remove
+  elsif @new_resource.version.nil?
+    true # remove any version of a package
+  elsif @new_resource.version == @current_resource.version
+    true # remove the version we have
+  else
+    false # we don't have the version we want to remove
+  end
+end
+
+def expand_options(options)
+  options ? " #{options}" : ""
+end
+
+# these methods are the required overrides of
+# a provider that extends from Chef::Provider::Package
+# so refactoring into core Chef should be easy
+
+def load_current_resource
+  @current_resource = Chef::Resource::PythonPip.new(@new_resource.name)
+  @current_resource.package_name(@new_resource.package_name)
+  @current_resource.version(nil)
+
+  unless current_installed_version.nil?
+    @current_resource.version(current_installed_version)
+  end
+
+  @current_resource
+end
+
+def current_installed_version
+  @current_installed_version ||= begin
+    delimeter = /==/
+
+    version_check_cmd = "#{pip_cmd(@new_resource)} freeze | grep -i '^#{@new_resource.package_name}=='"
+    # incase you upgrade pip with pip!
+    if @new_resource.package_name.eql?('pip')
+      delimeter = /\s/
+      version_check_cmd = "pip --version"
+    end
+    p = shell_out!(version_check_cmd)
+    p.stdout.split(delimeter)[1].strip
+  rescue Chef::Exceptions::ShellCommandFailed
+  rescue Mixlib::ShellOut::ShellCommandFailed
+  end
+end
+
+def candidate_version
+  @candidate_version ||= begin
+    # `pip search` doesn't return versions yet
+    # `pip list` may be coming soon:
+    # https://bitbucket.org/ianb/pip/issue/197/option-to-show-what-version-would-be
+    @new_resource.version||'latest'
+  end
+end
+
+def install_package(name, version, timeout)
+  v = "==#{version}" unless version.eql?('latest')
+  shell_out!("#{pip_cmd(@new_resource)} install#{expand_options(@new_resource.options)} #{name}#{v}", :timeout => timeout)
+end
+
+def upgrade_package(name, version, timeout)
+  v = "==#{version}" unless version.eql?('latest')
+  shell_out!("#{pip_cmd(@new_resource)} install --upgrade#{expand_options(@new_resource.options)} #{@new_resource.name}#{v}", :timeout => timeout)
+end
+
+def remove_package(name, version, timeout)
+  shell_out!("#{pip_cmd(@new_resource)} uninstall -y#{expand_options(@new_resource.options)} #{@new_resource.name}", :timeout => timeout)
+end
+
+# TODO remove when provider is moved into Chef core
+# this allows PythonPip to work with Chef::Resource::Package
+def pip_cmd(nr)
+  if (nr.respond_to?("virtualenv") && nr.virtualenv)
+    ::File.join(nr.virtualenv,'/bin/pip')
+  elsif "#{node['python']['install_method']}".eql?("source")
+    ::File.join("#{node['python']['prefix_dir']}","/bin/pip")
+  else
+    'pip'
+  end
+end

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/python/providers/.svn/text-base/virtualenv.rb.svn-base
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/python/providers/.svn/text-base/virtualenv.rb.svn-base b/src/main/vm/src/cookbooks/python/providers/.svn/text-base/virtualenv.rb.svn-base
new file mode 100755
index 0000000..d10f099
--- /dev/null
+++ b/src/main/vm/src/cookbooks/python/providers/.svn/text-base/virtualenv.rb.svn-base
@@ -0,0 +1,68 @@
+#
+# Author:: Seth Chisamore <sc...@opscode.com>
+# Cookbook Name:: python
+# Provider:: virtualenv
+#
+# Copyright:: 2011, Opscode, Inc <le...@opscode.com>
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+require 'chef/mixin/shell_out'
+require 'chef/mixin/language'
+include Chef::Mixin::ShellOut
+
+action :create do
+  unless exists?
+    Chef::Log.info("Creating virtualenv #{@new_resource} at #{@new_resource.path}")
+    execute "#{virtualenv_cmd} --python=#{@new_resource.interpreter} #{@new_resource.options} #{@new_resource.path}" do
+      user new_resource.owner if new_resource.owner
+      group new_resource.group if new_resource.group
+    end
+    new_resource.updated_by_last_action(true)
+  end
+end
+
+action :delete do
+  if exists?
+    Chef::Log.info("Deleting virtualenv #{@new_resource} at #{@new_resource.path}")
+    FileUtils.rm_rf(@new_resource.path)
+    new_resource.updated_by_last_action(true)
+  end
+end
+
+def load_current_resource
+  @current_resource = Chef::Resource::PythonVirtualenv.new(@new_resource.name)
+  @current_resource.path(@new_resource.path)
+
+  if exists?
+    cstats = ::File.stat(@current_resource.path)
+    @current_resource.owner(cstats.uid)
+    @current_resource.group(cstats.gid)
+  end
+  @current_resource
+end
+
+def virtualenv_cmd()
+  if "#{node['python']['install_method']}".eql?("source")
+    ::File.join("#{node['python']['prefix_dir']}","/bin/virtualenv")
+  else
+    "virtualenv"
+  end
+end
+
+private
+def exists?
+  ::File.exist?(@current_resource.path) && ::File.directory?(@current_resource.path) \
+    && ::File.exists?("#{@current_resource.path}/bin/activate")
+end

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/python/providers/pip.rb
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/python/providers/pip.rb b/src/main/vm/src/cookbooks/python/providers/pip.rb
new file mode 100755
index 0000000..1c58e5e
--- /dev/null
+++ b/src/main/vm/src/cookbooks/python/providers/pip.rb
@@ -0,0 +1,167 @@
+#
+# Author:: Seth Chisamore <sc...@opscode.com>
+# Cookbook Name:: python
+# Provider:: pip
+#
+# Copyright:: 2011, Opscode, Inc <le...@opscode.com>
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+require 'chef/mixin/shell_out'
+require 'chef/mixin/language'
+include Chef::Mixin::ShellOut
+
+# the logic in all action methods mirror that of
+# the Chef::Provider::Package which will make
+# refactoring into core chef easy
+
+action :install do
+  # If we specified a version, and it's not the current version, move to the specified version
+  if @new_resource.version != nil && @new_resource.version != @current_resource.version
+    install_version = @new_resource.version
+  # If it's not installed at all, install it
+  elsif @current_resource.version == nil
+    install_version = candidate_version
+  end
+
+  # Set the timeout (units in seconds)
+  timeout = 900
+  if @new_resource.timeout
+    timeout = @new_resource.timeout
+  end
+
+  if install_version
+    Chef::Log.info("Installing #{@new_resource} version #{install_version}")
+    status = install_package(@new_resource.package_name, install_version, timeout)
+    if status
+      @new_resource.updated_by_last_action(true)
+    end
+  end
+end
+
+action :upgrade do
+  # Set the timeout (units in seconds)
+  timeout = 900
+  if @new_resource.timeout
+    timeout = @new_resource.timeout
+  end
+
+  if @current_resource.version != candidate_version
+    orig_version = @current_resource.version || "uninstalled"
+    Chef::Log.info("Upgrading #{@new_resource} version from #{orig_version} to #{candidate_version}")
+    status = upgrade_package(@new_resource.package_name, candidate_version, timeout)
+    if status
+      @new_resource.updated_by_last_action(true)
+    end
+  end
+end
+
+action :remove do
+  # Set the timeout (units in seconds)
+  timeout = 900
+  if @new_resource.timeout
+    timeout = @new_resource.timeout
+  end
+
+  if removing_package?
+    Chef::Log.info("Removing #{@new_resource}")
+    remove_package(@current_resource.package_name, @new_resource.version, timeout)
+    @new_resource.updated_by_last_action(true)
+  else
+  end
+end
+
+def removing_package?
+  if @current_resource.version.nil?
+    false # nothing to remove
+  elsif @new_resource.version.nil?
+    true # remove any version of a package
+  elsif @new_resource.version == @current_resource.version
+    true # remove the version we have
+  else
+    false # we don't have the version we want to remove
+  end
+end
+
+def expand_options(options)
+  options ? " #{options}" : ""
+end
+
+# these methods are the required overrides of
+# a provider that extends from Chef::Provider::Package
+# so refactoring into core Chef should be easy
+
+def load_current_resource
+  @current_resource = Chef::Resource::PythonPip.new(@new_resource.name)
+  @current_resource.package_name(@new_resource.package_name)
+  @current_resource.version(nil)
+
+  unless current_installed_version.nil?
+    @current_resource.version(current_installed_version)
+  end
+
+  @current_resource
+end
+
+def current_installed_version
+  @current_installed_version ||= begin
+    delimeter = /==/
+
+    version_check_cmd = "#{pip_cmd(@new_resource)} freeze | grep -i '^#{@new_resource.package_name}=='"
+    # incase you upgrade pip with pip!
+    if @new_resource.package_name.eql?('pip')
+      delimeter = /\s/
+      version_check_cmd = "pip --version"
+    end
+    p = shell_out!(version_check_cmd)
+    p.stdout.split(delimeter)[1].strip
+  rescue Chef::Exceptions::ShellCommandFailed
+  rescue Mixlib::ShellOut::ShellCommandFailed
+  end
+end
+
+def candidate_version
+  @candidate_version ||= begin
+    # `pip search` doesn't return versions yet
+    # `pip list` may be coming soon:
+    # https://bitbucket.org/ianb/pip/issue/197/option-to-show-what-version-would-be
+    @new_resource.version||'latest'
+  end
+end
+
+def install_package(name, version, timeout)
+  v = "==#{version}" unless version.eql?('latest')
+  shell_out!("#{pip_cmd(@new_resource)} install#{expand_options(@new_resource.options)} #{name}#{v}", :timeout => timeout)
+end
+
+def upgrade_package(name, version, timeout)
+  v = "==#{version}" unless version.eql?('latest')
+  shell_out!("#{pip_cmd(@new_resource)} install --upgrade#{expand_options(@new_resource.options)} #{@new_resource.name}#{v}", :timeout => timeout)
+end
+
+def remove_package(name, version, timeout)
+  shell_out!("#{pip_cmd(@new_resource)} uninstall -y#{expand_options(@new_resource.options)} #{@new_resource.name}", :timeout => timeout)
+end
+
+# TODO remove when provider is moved into Chef core
+# this allows PythonPip to work with Chef::Resource::Package
+def pip_cmd(nr)
+  if (nr.respond_to?("virtualenv") && nr.virtualenv)
+    ::File.join(nr.virtualenv,'/bin/pip')
+  elsif "#{node['python']['install_method']}".eql?("source")
+    ::File.join("#{node['python']['prefix_dir']}","/bin/pip")
+  else
+    'pip'
+  end
+end

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/python/providers/virtualenv.rb
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/python/providers/virtualenv.rb b/src/main/vm/src/cookbooks/python/providers/virtualenv.rb
new file mode 100755
index 0000000..d10f099
--- /dev/null
+++ b/src/main/vm/src/cookbooks/python/providers/virtualenv.rb
@@ -0,0 +1,68 @@
+#
+# Author:: Seth Chisamore <sc...@opscode.com>
+# Cookbook Name:: python
+# Provider:: virtualenv
+#
+# Copyright:: 2011, Opscode, Inc <le...@opscode.com>
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+require 'chef/mixin/shell_out'
+require 'chef/mixin/language'
+include Chef::Mixin::ShellOut
+
+action :create do
+  unless exists?
+    Chef::Log.info("Creating virtualenv #{@new_resource} at #{@new_resource.path}")
+    execute "#{virtualenv_cmd} --python=#{@new_resource.interpreter} #{@new_resource.options} #{@new_resource.path}" do
+      user new_resource.owner if new_resource.owner
+      group new_resource.group if new_resource.group
+    end
+    new_resource.updated_by_last_action(true)
+  end
+end
+
+action :delete do
+  if exists?
+    Chef::Log.info("Deleting virtualenv #{@new_resource} at #{@new_resource.path}")
+    FileUtils.rm_rf(@new_resource.path)
+    new_resource.updated_by_last_action(true)
+  end
+end
+
+def load_current_resource
+  @current_resource = Chef::Resource::PythonVirtualenv.new(@new_resource.name)
+  @current_resource.path(@new_resource.path)
+
+  if exists?
+    cstats = ::File.stat(@current_resource.path)
+    @current_resource.owner(cstats.uid)
+    @current_resource.group(cstats.gid)
+  end
+  @current_resource
+end
+
+def virtualenv_cmd()
+  if "#{node['python']['install_method']}".eql?("source")
+    ::File.join("#{node['python']['prefix_dir']}","/bin/virtualenv")
+  else
+    "virtualenv"
+  end
+end
+
+private
+def exists?
+  ::File.exist?(@current_resource.path) && ::File.directory?(@current_resource.path) \
+    && ::File.exists?("#{@current_resource.path}/bin/activate")
+end

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/python/recipes/.svn/all-wcprops
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/python/recipes/.svn/all-wcprops b/src/main/vm/src/cookbooks/python/recipes/.svn/all-wcprops
new file mode 100755
index 0000000..6713bd9
--- /dev/null
+++ b/src/main/vm/src/cookbooks/python/recipes/.svn/all-wcprops
@@ -0,0 +1,35 @@
+K 25
+svn:wc:ra_dav:version-url
+V 98
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks/python/recipes
+END
+virtualenv.rb
+K 25
+svn:wc:ra_dav:version-url
+V 112
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks/python/recipes/virtualenv.rb
+END
+source.rb
+K 25
+svn:wc:ra_dav:version-url
+V 108
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks/python/recipes/source.rb
+END
+default.rb
+K 25
+svn:wc:ra_dav:version-url
+V 109
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks/python/recipes/default.rb
+END
+pip.rb
+K 25
+svn:wc:ra_dav:version-url
+V 105
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks/python/recipes/pip.rb
+END
+package.rb
+K 25
+svn:wc:ra_dav:version-url
+V 109
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks/python/recipes/package.rb
+END

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/python/recipes/.svn/entries
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/python/recipes/.svn/entries b/src/main/vm/src/cookbooks/python/recipes/.svn/entries
new file mode 100755
index 0000000..f5cd331
--- /dev/null
+++ b/src/main/vm/src/cookbooks/python/recipes/.svn/entries
@@ -0,0 +1,198 @@
+10
+
+dir
+1485921
+https://svn.apache.org/repos/asf/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks/python/recipes
+https://svn.apache.org/repos/asf
+
+
+
+2012-11-20T00:41:18.502817Z
+1474517
+ahart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+13f79535-47bb-0310-9956-ffa450edef68
+
+virtualenv.rb
+file
+
+
+
+
+2013-05-24T10:13:51.000000Z
+eee5c176494ba192feb11292423176b3
+2012-11-20T00:41:18.502817Z
+1474517
+ahart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+760
+
+source.rb
+file
+
+
+
+
+2013-05-24T10:13:51.000000Z
+67e2e63f0b923603fe1b153ca27beaf6
+2012-11-20T00:41:18.502817Z
+1474517
+ahart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+1846
+
+default.rb
+file
+
+
+
+
+2013-05-24T10:13:51.000000Z
+0c4ff14b44567012d42140a5ff93bd38
+2012-11-20T00:41:18.502817Z
+1474517
+ahart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+803
+
+pip.rb
+file
+
+
+
+
+2013-05-24T10:13:51.000000Z
+233b268931d78f52071b418873074861
+2012-11-20T00:41:18.502817Z
+1474517
+ahart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+1504
+
+package.rb
+file
+
+
+
+
+2013-05-24T10:13:51.000000Z
+04edbbca99a7ace2a715521224d286c8
+2012-11-20T00:41:18.502817Z
+1474517
+ahart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+2176
+

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/python/recipes/.svn/text-base/default.rb.svn-base
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/python/recipes/.svn/text-base/default.rb.svn-base b/src/main/vm/src/cookbooks/python/recipes/.svn/text-base/default.rb.svn-base
new file mode 100755
index 0000000..47e2a20
--- /dev/null
+++ b/src/main/vm/src/cookbooks/python/recipes/.svn/text-base/default.rb.svn-base
@@ -0,0 +1,23 @@
+#
+# Author:: Seth Chisamore <sc...@opscode.com>
+# Cookbook Name:: python
+# Recipe:: default
+#
+# Copyright 2011, Opscode, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+include_recipe "python::#{node['python']['install_method']}"
+include_recipe "python::pip"
+include_recipe "python::virtualenv"
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/python/recipes/.svn/text-base/package.rb.svn-base
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/python/recipes/.svn/text-base/package.rb.svn-base b/src/main/vm/src/cookbooks/python/recipes/.svn/text-base/package.rb.svn-base
new file mode 100755
index 0000000..95dcce0
--- /dev/null
+++ b/src/main/vm/src/cookbooks/python/recipes/.svn/text-base/package.rb.svn-base
@@ -0,0 +1,58 @@
+#
+# Author:: Seth Chisamore <sc...@opscode.com>
+# Cookbook Name:: python
+# Recipe:: package
+#
+# Copyright 2011, Opscode, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+# COOK-1016 Handle RHEL/CentOS namings of python packages, by installing EPEL repo & package
+# This implementation was determined a stopgap measure until CHEF-2410 is implemented and widespread.
+if node['platform'] == 'centos' || node['platform'] == 'redhat'
+  major_version = node['platform_version'].split('.').first.to_i
+  if major_version == 5
+    include_recipe 'yum::epel'
+  else
+    # Do nothing.
+  end
+end
+
+python_pkgs = if node['platform'] == 'centos' || node['platform'] == 'redhat'
+                major_version = node['platform_version'].split('.').first.to_i
+                if major_version == 6
+                  ["python", "python-devel"]
+                else
+                  ["python26", "python26-devel"]
+                end
+              else
+                value_for_platform(
+                                   ["debian","ubuntu"] => {
+                                     "default" => ["python","python-dev"]
+                                   },
+                                   ["fedora","amazon"] => {
+                                     "default" => ["python","python-devel"]
+                                   },
+                                   ["freebsd"] => {
+                                     "default" => ["python"]
+                                   },
+                                   "default" => ["python","python-dev"]
+                                   )
+              end
+
+python_pkgs.each do |pkg|
+  package pkg do
+    action :install
+  end
+end

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/python/recipes/.svn/text-base/pip.rb.svn-base
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/python/recipes/.svn/text-base/pip.rb.svn-base b/src/main/vm/src/cookbooks/python/recipes/.svn/text-base/pip.rb.svn-base
new file mode 100755
index 0000000..ecb97c2
--- /dev/null
+++ b/src/main/vm/src/cookbooks/python/recipes/.svn/text-base/pip.rb.svn-base
@@ -0,0 +1,41 @@
+#
+# Author:: Seth Chisamore <sc...@opscode.com>
+# Cookbook Name:: python
+# Recipe:: pip
+#
+# Copyright 2011, Opscode, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+python_bindir = "#{node['python']['prefix_dir']}/bin"
+pip_bindir    = "#{node['python']['pip']['prefix_dir']}/bin"
+
+# Ubuntu's python-setuptools, python-pip and python-virtualenv packages
+# are broken...this feels like Rubygems!
+# http://stackoverflow.com/questions/4324558/whats-the-proper-way-to-install-pip-virtualenv-and-distribute-for-python
+# https://bitbucket.org/ianb/pip/issue/104/pip-uninstall-on-ubuntu-linux
+remote_file "#{Chef::Config[:file_cache_path]}/distribute_setup.py" do
+  source "http://python-distribute.org/distribute_setup.py"
+  mode "0644"
+  not_if { ::File.exists?("#{pip_bindir}/pip") }
+end
+
+bash "install-pip" do
+  cwd Chef::Config[:file_cache_path]
+  code <<-EOF
+  #{python_bindir}/python distribute_setup.py
+  #{pip_bindir}/easy_install pip
+  EOF
+  not_if { ::File.exists?("#{pip_bindir}/pip") }
+end

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/python/recipes/.svn/text-base/source.rb.svn-base
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/python/recipes/.svn/text-base/source.rb.svn-base b/src/main/vm/src/cookbooks/python/recipes/.svn/text-base/source.rb.svn-base
new file mode 100755
index 0000000..b4e3dd6
--- /dev/null
+++ b/src/main/vm/src/cookbooks/python/recipes/.svn/text-base/source.rb.svn-base
@@ -0,0 +1,52 @@
+#
+# Author:: Seth Chisamore <sc...@opscode.com>
+# Cookbook Name:: python
+# Recipe:: source
+#
+# Copyright 2011, Opscode, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+configure_options = node['python']['configure_options'].join(" ")
+
+packages = value_for_platform(
+    ["centos","redhat","fedora"] => 
+        {"default" => ["openssl-devel","bzip2-devel","zlib-devel","expat-devel","db4-devel","sqlite-devel","ncurses-devel","readline-devel"]},
+    "default" => 
+        ["libssl-dev","libbz2-dev","zlib1g-dev","libexpat1-dev","libdb4.8-dev","libsqlite3-dev","libncursesw5-dev","libncurses5-dev","libreadline-dev"]
+  )
+
+packages.each do |dev_pkg|
+  package dev_pkg
+end
+
+version = node['python']['version']
+install_path = "#{node['python']['prefix_dir']}/lib/python#{version.split(/(^\d+\.\d+)/)[1]}"
+
+remote_file "#{Chef::Config[:file_cache_path]}/Python-#{version}.tar.bz2" do
+  source "#{node['python']['url']}/#{version}/Python-#{version}.tar.bz2"
+  checksum node['python']['checksum']
+  mode "0644"
+  not_if { ::File.exists?(install_path) }
+end
+
+bash "build-and-install-python" do
+  cwd Chef::Config[:file_cache_path]
+  code <<-EOF
+  tar -jxvf Python-#{version}.tar.bz2
+  (cd Python-#{version} && ./configure #{configure_options})
+  (cd Python-#{version} && make && make install)
+  EOF
+  not_if { ::File.exists?(install_path) }
+end

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/python/recipes/.svn/text-base/virtualenv.rb.svn-base
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/python/recipes/.svn/text-base/virtualenv.rb.svn-base b/src/main/vm/src/cookbooks/python/recipes/.svn/text-base/virtualenv.rb.svn-base
new file mode 100755
index 0000000..4c28f80
--- /dev/null
+++ b/src/main/vm/src/cookbooks/python/recipes/.svn/text-base/virtualenv.rb.svn-base
@@ -0,0 +1,25 @@
+#
+# Author:: Seth Chisamore <sc...@opscode.com>
+# Cookbook Name:: python
+# Recipe:: virtualenv
+#
+# Copyright 2011, Opscode, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+include_recipe "python::pip"
+
+python_pip "virtualenv" do
+  action :install
+end

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/python/recipes/default.rb
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/python/recipes/default.rb b/src/main/vm/src/cookbooks/python/recipes/default.rb
new file mode 100755
index 0000000..47e2a20
--- /dev/null
+++ b/src/main/vm/src/cookbooks/python/recipes/default.rb
@@ -0,0 +1,23 @@
+#
+# Author:: Seth Chisamore <sc...@opscode.com>
+# Cookbook Name:: python
+# Recipe:: default
+#
+# Copyright 2011, Opscode, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+include_recipe "python::#{node['python']['install_method']}"
+include_recipe "python::pip"
+include_recipe "python::virtualenv"
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/python/recipes/package.rb
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/python/recipes/package.rb b/src/main/vm/src/cookbooks/python/recipes/package.rb
new file mode 100755
index 0000000..95dcce0
--- /dev/null
+++ b/src/main/vm/src/cookbooks/python/recipes/package.rb
@@ -0,0 +1,58 @@
+#
+# Author:: Seth Chisamore <sc...@opscode.com>
+# Cookbook Name:: python
+# Recipe:: package
+#
+# Copyright 2011, Opscode, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+# COOK-1016 Handle RHEL/CentOS namings of python packages, by installing EPEL repo & package
+# This implementation was determined a stopgap measure until CHEF-2410 is implemented and widespread.
+if node['platform'] == 'centos' || node['platform'] == 'redhat'
+  major_version = node['platform_version'].split('.').first.to_i
+  if major_version == 5
+    include_recipe 'yum::epel'
+  else
+    # Do nothing.
+  end
+end
+
+python_pkgs = if node['platform'] == 'centos' || node['platform'] == 'redhat'
+                major_version = node['platform_version'].split('.').first.to_i
+                if major_version == 6
+                  ["python", "python-devel"]
+                else
+                  ["python26", "python26-devel"]
+                end
+              else
+                value_for_platform(
+                                   ["debian","ubuntu"] => {
+                                     "default" => ["python","python-dev"]
+                                   },
+                                   ["fedora","amazon"] => {
+                                     "default" => ["python","python-devel"]
+                                   },
+                                   ["freebsd"] => {
+                                     "default" => ["python"]
+                                   },
+                                   "default" => ["python","python-dev"]
+                                   )
+              end
+
+python_pkgs.each do |pkg|
+  package pkg do
+    action :install
+  end
+end

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/python/recipes/pip.rb
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/python/recipes/pip.rb b/src/main/vm/src/cookbooks/python/recipes/pip.rb
new file mode 100755
index 0000000..ecb97c2
--- /dev/null
+++ b/src/main/vm/src/cookbooks/python/recipes/pip.rb
@@ -0,0 +1,41 @@
+#
+# Author:: Seth Chisamore <sc...@opscode.com>
+# Cookbook Name:: python
+# Recipe:: pip
+#
+# Copyright 2011, Opscode, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+python_bindir = "#{node['python']['prefix_dir']}/bin"
+pip_bindir    = "#{node['python']['pip']['prefix_dir']}/bin"
+
+# Ubuntu's python-setuptools, python-pip and python-virtualenv packages
+# are broken...this feels like Rubygems!
+# http://stackoverflow.com/questions/4324558/whats-the-proper-way-to-install-pip-virtualenv-and-distribute-for-python
+# https://bitbucket.org/ianb/pip/issue/104/pip-uninstall-on-ubuntu-linux
+remote_file "#{Chef::Config[:file_cache_path]}/distribute_setup.py" do
+  source "http://python-distribute.org/distribute_setup.py"
+  mode "0644"
+  not_if { ::File.exists?("#{pip_bindir}/pip") }
+end
+
+bash "install-pip" do
+  cwd Chef::Config[:file_cache_path]
+  code <<-EOF
+  #{python_bindir}/python distribute_setup.py
+  #{pip_bindir}/easy_install pip
+  EOF
+  not_if { ::File.exists?("#{pip_bindir}/pip") }
+end

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/python/recipes/source.rb
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/python/recipes/source.rb b/src/main/vm/src/cookbooks/python/recipes/source.rb
new file mode 100755
index 0000000..b4e3dd6
--- /dev/null
+++ b/src/main/vm/src/cookbooks/python/recipes/source.rb
@@ -0,0 +1,52 @@
+#
+# Author:: Seth Chisamore <sc...@opscode.com>
+# Cookbook Name:: python
+# Recipe:: source
+#
+# Copyright 2011, Opscode, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+configure_options = node['python']['configure_options'].join(" ")
+
+packages = value_for_platform(
+    ["centos","redhat","fedora"] => 
+        {"default" => ["openssl-devel","bzip2-devel","zlib-devel","expat-devel","db4-devel","sqlite-devel","ncurses-devel","readline-devel"]},
+    "default" => 
+        ["libssl-dev","libbz2-dev","zlib1g-dev","libexpat1-dev","libdb4.8-dev","libsqlite3-dev","libncursesw5-dev","libncurses5-dev","libreadline-dev"]
+  )
+
+packages.each do |dev_pkg|
+  package dev_pkg
+end
+
+version = node['python']['version']
+install_path = "#{node['python']['prefix_dir']}/lib/python#{version.split(/(^\d+\.\d+)/)[1]}"
+
+remote_file "#{Chef::Config[:file_cache_path]}/Python-#{version}.tar.bz2" do
+  source "#{node['python']['url']}/#{version}/Python-#{version}.tar.bz2"
+  checksum node['python']['checksum']
+  mode "0644"
+  not_if { ::File.exists?(install_path) }
+end
+
+bash "build-and-install-python" do
+  cwd Chef::Config[:file_cache_path]
+  code <<-EOF
+  tar -jxvf Python-#{version}.tar.bz2
+  (cd Python-#{version} && ./configure #{configure_options})
+  (cd Python-#{version} && make && make install)
+  EOF
+  not_if { ::File.exists?(install_path) }
+end

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/python/recipes/virtualenv.rb
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/python/recipes/virtualenv.rb b/src/main/vm/src/cookbooks/python/recipes/virtualenv.rb
new file mode 100755
index 0000000..4c28f80
--- /dev/null
+++ b/src/main/vm/src/cookbooks/python/recipes/virtualenv.rb
@@ -0,0 +1,25 @@
+#
+# Author:: Seth Chisamore <sc...@opscode.com>
+# Cookbook Name:: python
+# Recipe:: virtualenv
+#
+# Copyright 2011, Opscode, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+include_recipe "python::pip"
+
+python_pip "virtualenv" do
+  action :install
+end

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/python/resources/.svn/all-wcprops
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/python/resources/.svn/all-wcprops b/src/main/vm/src/cookbooks/python/resources/.svn/all-wcprops
new file mode 100755
index 0000000..af97be4
--- /dev/null
+++ b/src/main/vm/src/cookbooks/python/resources/.svn/all-wcprops
@@ -0,0 +1,17 @@
+K 25
+svn:wc:ra_dav:version-url
+V 100
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks/python/resources
+END
+virtualenv.rb
+K 25
+svn:wc:ra_dav:version-url
+V 114
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks/python/resources/virtualenv.rb
+END
+pip.rb
+K 25
+svn:wc:ra_dav:version-url
+V 107
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks/python/resources/pip.rb
+END

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/python/resources/.svn/entries
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/python/resources/.svn/entries b/src/main/vm/src/cookbooks/python/resources/.svn/entries
new file mode 100755
index 0000000..aba5cfa
--- /dev/null
+++ b/src/main/vm/src/cookbooks/python/resources/.svn/entries
@@ -0,0 +1,96 @@
+10
+
+dir
+1485921
+https://svn.apache.org/repos/asf/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks/python/resources
+https://svn.apache.org/repos/asf
+
+
+
+2012-11-20T00:41:18.502817Z
+1474517
+ahart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+13f79535-47bb-0310-9956-ffa450edef68
+
+virtualenv.rb
+file
+
+
+
+
+2013-05-24T10:13:51.000000Z
+7b3a77f1725755dd12263fa9c6ff8092
+2012-11-20T00:41:18.502817Z
+1474517
+ahart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+996
+
+pip.rb
+file
+
+
+
+
+2013-05-24T10:13:51.000000Z
+fa753c07988d3faea2dfa3c87e0b7661
+2012-11-20T00:41:18.502817Z
+1474517
+ahart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+964
+

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/python/resources/.svn/text-base/pip.rb.svn-base
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/python/resources/.svn/text-base/pip.rb.svn-base b/src/main/vm/src/cookbooks/python/resources/.svn/text-base/pip.rb.svn-base
new file mode 100755
index 0000000..6b1780c
--- /dev/null
+++ b/src/main/vm/src/cookbooks/python/resources/.svn/text-base/pip.rb.svn-base
@@ -0,0 +1,27 @@
+#
+# Author:: Seth Chisamore <sc...@opscode.com>
+# Cookbook Name:: python
+# Resource:: pip
+#
+# Copyright:: 2011, Opscode, Inc <le...@opscode.com>
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+actions :install, :upgrade, :remove, :purge
+
+attribute :package_name, :kind_of => String, :name_attribute => true
+attribute :version, :default => nil
+attribute :timeout, :default => nil
+attribute :virtualenv, :kind_of => String
+attribute :options, :kind_of => String

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/python/resources/.svn/text-base/virtualenv.rb.svn-base
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/python/resources/.svn/text-base/virtualenv.rb.svn-base b/src/main/vm/src/cookbooks/python/resources/.svn/text-base/virtualenv.rb.svn-base
new file mode 100755
index 0000000..6f14820
--- /dev/null
+++ b/src/main/vm/src/cookbooks/python/resources/.svn/text-base/virtualenv.rb.svn-base
@@ -0,0 +1,27 @@
+#
+# Author:: Seth Chisamore <sc...@opscode.com>
+# Cookbook Name:: python
+# Resource:: virtualenv
+#
+# Copyright:: 2011, Opscode, Inc <le...@opscode.com>
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+actions :create, :delete
+
+attribute :path, :kind_of => String, :name_attribute => true
+attribute :interpreter, :default => 'python'
+attribute :owner, :regex => Chef::Config[:user_valid_regex]
+attribute :group, :regex => Chef::Config[:group_valid_regex]
+attribute :options, :kind_of => String

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/python/resources/pip.rb
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/python/resources/pip.rb b/src/main/vm/src/cookbooks/python/resources/pip.rb
new file mode 100755
index 0000000..6b1780c
--- /dev/null
+++ b/src/main/vm/src/cookbooks/python/resources/pip.rb
@@ -0,0 +1,27 @@
+#
+# Author:: Seth Chisamore <sc...@opscode.com>
+# Cookbook Name:: python
+# Resource:: pip
+#
+# Copyright:: 2011, Opscode, Inc <le...@opscode.com>
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+actions :install, :upgrade, :remove, :purge
+
+attribute :package_name, :kind_of => String, :name_attribute => true
+attribute :version, :default => nil
+attribute :timeout, :default => nil
+attribute :virtualenv, :kind_of => String
+attribute :options, :kind_of => String

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/python/resources/virtualenv.rb
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/python/resources/virtualenv.rb b/src/main/vm/src/cookbooks/python/resources/virtualenv.rb
new file mode 100755
index 0000000..6f14820
--- /dev/null
+++ b/src/main/vm/src/cookbooks/python/resources/virtualenv.rb
@@ -0,0 +1,27 @@
+#
+# Author:: Seth Chisamore <sc...@opscode.com>
+# Cookbook Name:: python
+# Resource:: virtualenv
+#
+# Copyright:: 2011, Opscode, Inc <le...@opscode.com>
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+actions :create, :delete
+
+attribute :path, :kind_of => String, :name_attribute => true
+attribute :interpreter, :default => 'python'
+attribute :owner, :regex => Chef::Config[:user_valid_regex]
+attribute :group, :regex => Chef::Config[:group_valid_regex]
+attribute :options, :kind_of => String

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/vagrant_main/.svn/all-wcprops
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/vagrant_main/.svn/all-wcprops b/src/main/vm/src/cookbooks/vagrant_main/.svn/all-wcprops
new file mode 100755
index 0000000..dc8d918
--- /dev/null
+++ b/src/main/vm/src/cookbooks/vagrant_main/.svn/all-wcprops
@@ -0,0 +1,5 @@
+K 25
+svn:wc:ra_dav:version-url
+V 96
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks/vagrant_main
+END

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/vagrant_main/.svn/entries
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/vagrant_main/.svn/entries b/src/main/vm/src/cookbooks/vagrant_main/.svn/entries
new file mode 100755
index 0000000..bd87d9e
--- /dev/null
+++ b/src/main/vm/src/cookbooks/vagrant_main/.svn/entries
@@ -0,0 +1,34 @@
+10
+
+dir
+1485921
+https://svn.apache.org/repos/asf/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks/vagrant_main
+https://svn.apache.org/repos/asf
+
+
+
+2012-12-07T19:15:28.460275Z
+1474605
+ahart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+13f79535-47bb-0310-9956-ffa450edef68
+
+recipes
+dir
+
+templates
+dir
+

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/vagrant_main/recipes/.svn/all-wcprops
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/vagrant_main/recipes/.svn/all-wcprops b/src/main/vm/src/cookbooks/vagrant_main/recipes/.svn/all-wcprops
new file mode 100755
index 0000000..80cb539
--- /dev/null
+++ b/src/main/vm/src/cookbooks/vagrant_main/recipes/.svn/all-wcprops
@@ -0,0 +1,11 @@
+K 25
+svn:wc:ra_dav:version-url
+V 104
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks/vagrant_main/recipes
+END
+default.rb
+K 25
+svn:wc:ra_dav:version-url
+V 115
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks/vagrant_main/recipes/default.rb
+END

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/vagrant_main/recipes/.svn/entries
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/vagrant_main/recipes/.svn/entries b/src/main/vm/src/cookbooks/vagrant_main/recipes/.svn/entries
new file mode 100755
index 0000000..abbc399
--- /dev/null
+++ b/src/main/vm/src/cookbooks/vagrant_main/recipes/.svn/entries
@@ -0,0 +1,62 @@
+10
+
+dir
+1485921
+https://svn.apache.org/repos/asf/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks/vagrant_main/recipes
+https://svn.apache.org/repos/asf
+
+
+
+2012-12-07T19:15:28.460275Z
+1474605
+ahart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+13f79535-47bb-0310-9956-ffa450edef68
+
+default.rb
+file
+
+
+
+
+2013-05-24T10:13:55.000000Z
+f9e170538631d8b1b7a7684951890d9b
+2012-12-07T19:15:28.460275Z
+1474605
+ahart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+1485
+

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/vagrant_main/recipes/.svn/text-base/default.rb.svn-base
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/vagrant_main/recipes/.svn/text-base/default.rb.svn-base b/src/main/vm/src/cookbooks/vagrant_main/recipes/.svn/text-base/default.rb.svn-base
new file mode 100755
index 0000000..7eed825
--- /dev/null
+++ b/src/main/vm/src/cookbooks/vagrant_main/recipes/.svn/text-base/default.rb.svn-base
@@ -0,0 +1,56 @@
+# APT Package Management --------------------------------------------
+# Install the APT package management tool, and then install any
+# packages that we will need to have to complete the buildout.
+#
+include_recipe "apt"
+include_recipe "build-essential"
+gem_package "ruby-shadow" do
+  action :install
+end
+
+# User Creation -----------------------------------------------------
+# Create a user account for the 'rcmet' user
+#
+user "rcmet" do
+  comment "RCMET user"
+  uid 1001
+  #gid "users"
+  home "/usr/local/rcmet"
+  shell "/bin/bash"
+  #password "1bob1bob"
+end
+
+directory "/usr/local/rcmet" do
+  mode "0777"
+end
+
+
+# Python Environment Setup ------------------------------------------
+# Install Python and package management tools 'pip' and 'virtualenv'.
+# Then create a virtual environment in  the 'rcmet' user's home 
+# directory, into which all RCMET python code and dependencies can be 
+# installed.
+#
+include_recipe "python"
+
+python_virtualenv "/usr/local/rcmet/python-env" do
+  owner "rcmet"
+  group "rcmet"
+  action :create
+end
+
+# Apache Web Server Configuration -----------------------------------
+# Install the Apache2 HTTPD Web Server, and configure a virtual host
+# for the RCMET web application.
+#
+include_recipe "apache2"
+
+execute "disable-default-site" do
+  command "sudo a2dissite default"
+  notifies :reload, resources(:service => "apache2"), :delayed
+end
+
+web_app "rcmet" do
+  template "rcmet.conf.erb"
+  notifies :reload, resources(:service => "apache2"), :delayed
+end

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/vagrant_main/recipes/default.rb
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/vagrant_main/recipes/default.rb b/src/main/vm/src/cookbooks/vagrant_main/recipes/default.rb
new file mode 100755
index 0000000..7eed825
--- /dev/null
+++ b/src/main/vm/src/cookbooks/vagrant_main/recipes/default.rb
@@ -0,0 +1,56 @@
+# APT Package Management --------------------------------------------
+# Install the APT package management tool, and then install any
+# packages that we will need to have to complete the buildout.
+#
+include_recipe "apt"
+include_recipe "build-essential"
+gem_package "ruby-shadow" do
+  action :install
+end
+
+# User Creation -----------------------------------------------------
+# Create a user account for the 'rcmet' user
+#
+user "rcmet" do
+  comment "RCMET user"
+  uid 1001
+  #gid "users"
+  home "/usr/local/rcmet"
+  shell "/bin/bash"
+  #password "1bob1bob"
+end
+
+directory "/usr/local/rcmet" do
+  mode "0777"
+end
+
+
+# Python Environment Setup ------------------------------------------
+# Install Python and package management tools 'pip' and 'virtualenv'.
+# Then create a virtual environment in  the 'rcmet' user's home 
+# directory, into which all RCMET python code and dependencies can be 
+# installed.
+#
+include_recipe "python"
+
+python_virtualenv "/usr/local/rcmet/python-env" do
+  owner "rcmet"
+  group "rcmet"
+  action :create
+end
+
+# Apache Web Server Configuration -----------------------------------
+# Install the Apache2 HTTPD Web Server, and configure a virtual host
+# for the RCMET web application.
+#
+include_recipe "apache2"
+
+execute "disable-default-site" do
+  command "sudo a2dissite default"
+  notifies :reload, resources(:service => "apache2"), :delayed
+end
+
+web_app "rcmet" do
+  template "rcmet.conf.erb"
+  notifies :reload, resources(:service => "apache2"), :delayed
+end

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/vagrant_main/templates/.svn/all-wcprops
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/vagrant_main/templates/.svn/all-wcprops b/src/main/vm/src/cookbooks/vagrant_main/templates/.svn/all-wcprops
new file mode 100755
index 0000000..3bcba23
--- /dev/null
+++ b/src/main/vm/src/cookbooks/vagrant_main/templates/.svn/all-wcprops
@@ -0,0 +1,5 @@
+K 25
+svn:wc:ra_dav:version-url
+V 106
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks/vagrant_main/templates
+END

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/vagrant_main/templates/.svn/entries
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/vagrant_main/templates/.svn/entries b/src/main/vm/src/cookbooks/vagrant_main/templates/.svn/entries
new file mode 100755
index 0000000..f2f38e2
--- /dev/null
+++ b/src/main/vm/src/cookbooks/vagrant_main/templates/.svn/entries
@@ -0,0 +1,31 @@
+10
+
+dir
+1485921
+https://svn.apache.org/repos/asf/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks/vagrant_main/templates
+https://svn.apache.org/repos/asf
+
+
+
+2012-10-10T00:54:31.813219Z
+1474265
+ahart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+13f79535-47bb-0310-9956-ffa450edef68
+
+default
+dir
+

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/vagrant_main/templates/default/.svn/all-wcprops
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/vagrant_main/templates/default/.svn/all-wcprops b/src/main/vm/src/cookbooks/vagrant_main/templates/default/.svn/all-wcprops
new file mode 100755
index 0000000..5031d4e
--- /dev/null
+++ b/src/main/vm/src/cookbooks/vagrant_main/templates/default/.svn/all-wcprops
@@ -0,0 +1,17 @@
+K 25
+svn:wc:ra_dav:version-url
+V 114
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks/vagrant_main/templates/default
+END
+project.conf.erb
+K 25
+svn:wc:ra_dav:version-url
+V 131
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks/vagrant_main/templates/default/project.conf.erb
+END
+rcmet.conf.erb
+K 25
+svn:wc:ra_dav:version-url
+V 129
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks/vagrant_main/templates/default/rcmet.conf.erb
+END

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/vagrant_main/templates/default/.svn/entries
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/vagrant_main/templates/default/.svn/entries b/src/main/vm/src/cookbooks/vagrant_main/templates/default/.svn/entries
new file mode 100755
index 0000000..14b1805
--- /dev/null
+++ b/src/main/vm/src/cookbooks/vagrant_main/templates/default/.svn/entries
@@ -0,0 +1,96 @@
+10
+
+dir
+1485921
+https://svn.apache.org/repos/asf/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks/vagrant_main/templates/default
+https://svn.apache.org/repos/asf
+
+
+
+2012-10-10T00:54:31.813219Z
+1474265
+ahart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+13f79535-47bb-0310-9956-ffa450edef68
+
+project.conf.erb
+file
+
+
+
+
+2013-05-24T10:13:55.000000Z
+2eddd2fd3bfde3e4d3af630302aeb179
+2012-10-10T00:49:17.045897Z
+1474264
+ahart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+85
+
+rcmet.conf.erb
+file
+
+
+
+
+2013-05-24T10:13:55.000000Z
+77767ced087eac1a32b3b4f35d4163b6
+2012-10-10T00:54:31.813219Z
+1474265
+ahart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+93
+

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/vagrant_main/templates/default/.svn/text-base/project.conf.erb.svn-base
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/vagrant_main/templates/default/.svn/text-base/project.conf.erb.svn-base b/src/main/vm/src/cookbooks/vagrant_main/templates/default/.svn/text-base/project.conf.erb.svn-base
new file mode 100755
index 0000000..16176b4
--- /dev/null
+++ b/src/main/vm/src/cookbooks/vagrant_main/templates/default/.svn/text-base/project.conf.erb.svn-base
@@ -0,0 +1,3 @@
+<VirtualHost *:80>
+    DocumentRoot <%= @node[:vagrant][:directory] %>
+</VirtualHost>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/vagrant_main/templates/default/.svn/text-base/rcmet.conf.erb.svn-base
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/vagrant_main/templates/default/.svn/text-base/rcmet.conf.erb.svn-base b/src/main/vm/src/cookbooks/vagrant_main/templates/default/.svn/text-base/rcmet.conf.erb.svn-base
new file mode 100755
index 0000000..9283347
--- /dev/null
+++ b/src/main/vm/src/cookbooks/vagrant_main/templates/default/.svn/text-base/rcmet.conf.erb.svn-base
@@ -0,0 +1,3 @@
+<VirtualHost *:80>
+    DocumentRoot <%= @node[:vagrant][:directory] %>/env/www
+</VirtualHost>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/vagrant_main/templates/default/project.conf.erb
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/vagrant_main/templates/default/project.conf.erb b/src/main/vm/src/cookbooks/vagrant_main/templates/default/project.conf.erb
new file mode 100755
index 0000000..16176b4
--- /dev/null
+++ b/src/main/vm/src/cookbooks/vagrant_main/templates/default/project.conf.erb
@@ -0,0 +1,3 @@
+<VirtualHost *:80>
+    DocumentRoot <%= @node[:vagrant][:directory] %>
+</VirtualHost>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/vagrant_main/templates/default/rcmet.conf.erb
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/vagrant_main/templates/default/rcmet.conf.erb b/src/main/vm/src/cookbooks/vagrant_main/templates/default/rcmet.conf.erb
new file mode 100755
index 0000000..9283347
--- /dev/null
+++ b/src/main/vm/src/cookbooks/vagrant_main/templates/default/rcmet.conf.erb
@@ -0,0 +1,3 @@
+<VirtualHost *:80>
+    DocumentRoot <%= @node[:vagrant][:directory] %>/env/www
+</VirtualHost>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/scripts/.svn/all-wcprops
----------------------------------------------------------------------
diff --git a/src/main/vm/src/scripts/.svn/all-wcprops b/src/main/vm/src/scripts/.svn/all-wcprops
new file mode 100755
index 0000000..8697f6f
--- /dev/null
+++ b/src/main/vm/src/scripts/.svn/all-wcprops
@@ -0,0 +1,5 @@
+K 25
+svn:wc:ra_dav:version-url
+V 81
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/vm/src/scripts
+END

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/scripts/.svn/entries
----------------------------------------------------------------------
diff --git a/src/main/vm/src/scripts/.svn/entries b/src/main/vm/src/scripts/.svn/entries
new file mode 100755
index 0000000..b5d0e37
--- /dev/null
+++ b/src/main/vm/src/scripts/.svn/entries
@@ -0,0 +1,31 @@
+10
+
+dir
+1485921
+https://svn.apache.org/repos/asf/incubator/climate/trunk/rcmet/src/main/vm/src/scripts
+https://svn.apache.org/repos/asf
+
+
+
+2012-12-07T19:44:54.983182Z
+1474607
+ahart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+13f79535-47bb-0310-9956-ffa450edef68
+
+ncl
+dir
+

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/scripts/ncl/.svn/all-wcprops
----------------------------------------------------------------------
diff --git a/src/main/vm/src/scripts/ncl/.svn/all-wcprops b/src/main/vm/src/scripts/ncl/.svn/all-wcprops
new file mode 100755
index 0000000..ab6be5e
--- /dev/null
+++ b/src/main/vm/src/scripts/ncl/.svn/all-wcprops
@@ -0,0 +1,11 @@
+K 25
+svn:wc:ra_dav:version-url
+V 85
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/vm/src/scripts/ncl
+END
+wget-download.sh
+K 25
+svn:wc:ra_dav:version-url
+V 102
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/vm/src/scripts/ncl/wget-download.sh
+END

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/scripts/ncl/.svn/entries
----------------------------------------------------------------------
diff --git a/src/main/vm/src/scripts/ncl/.svn/entries b/src/main/vm/src/scripts/ncl/.svn/entries
new file mode 100755
index 0000000..5b634eb
--- /dev/null
+++ b/src/main/vm/src/scripts/ncl/.svn/entries
@@ -0,0 +1,62 @@
+10
+
+dir
+1485921
+https://svn.apache.org/repos/asf/incubator/climate/trunk/rcmet/src/main/vm/src/scripts/ncl
+https://svn.apache.org/repos/asf
+
+
+
+2012-12-07T19:44:54.983182Z
+1474607
+ahart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+13f79535-47bb-0310-9956-ffa450edef68
+
+wget-download.sh
+file
+
+
+
+
+2013-05-24T10:13:50.000000Z
+6850ecc31327edf0dff68342cb64992d
+2012-12-07T19:44:54.983182Z
+1474607
+ahart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+9082
+

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/scripts/ncl/.svn/text-base/wget-download.sh.svn-base
----------------------------------------------------------------------
diff --git a/src/main/vm/src/scripts/ncl/.svn/text-base/wget-download.sh.svn-base b/src/main/vm/src/scripts/ncl/.svn/text-base/wget-download.sh.svn-base
new file mode 100755
index 0000000..5444fab
--- /dev/null
+++ b/src/main/vm/src/scripts/ncl/.svn/text-base/wget-download.sh.svn-base
@@ -0,0 +1,263 @@
+#!/bin/bash
+#
+# ESG Federation download script
+#
+# Template version
+version=0.4.3
+# Generated by Gateway: ESG-NCAR
+#
+# Script generated user OpenID: https://www.earthsystemgrid.org/myopenid/ahart
+#
+
+CACHE_FILE=.md5_results
+
+##############################################################################
+#
+# Your download selection includes data secured using ESG
+# certificate-based security.  In order to access the download URLs
+# you must first obtain a credentials file from your home Gateway's
+# MyProxy server.
+#
+# If you don't already have a myproxy client you can download the
+# MyProxyLogon Java client from
+#   http://www.earthsystemgrid.org//webstart/myProxyLogon/MyProxyLogon-ESG.jar
+#
+# Then execute it as follows:
+#  $ java -jar MyProxyLogon-ESG.jar -h vetswebprod.ucar.edu -p 7512 -u <username>
+#
+# Further information is available at
+#   http://www.earthsystemgrid.org//help/download-help.htm
+#
+##############################################################################
+
+##############################################################################
+#
+# Script defaults
+#
+
+# ESG_HOME should point to the directory containing ESG credentials.
+#   Default is $HOME/.esg.
+ESG_HOME=${ESG_HOME:-$HOME/.esg}
+ESG_CREDENTIALS=${X509_USER_PROXY:-$ESG_HOME/credentials.pem}
+ESG_CERT_DIR=${X509_CERT_DIR:-$ESG_HOME/certificates}
+COOKIE_JAR=$ESG_HOME/cookies
+CERT_EXPIRATION_WARNING=$((60 * 60 * 1))	#One hour (in seconds)
+
+# Configure checking of server SSL certificates.
+#   Disabling server certificate checking can resolve problems with myproxy
+#   servers being out of sync with datanodes.
+CHECK_SERVER_CERT=${CHECK_SERVER_CERT:-Yes}
+
+
+
+usage() {
+    echo "Usage: $(basename $0) [flags]"
+    echo "Flags is one of:"
+    sed -n '/^while getopts/,/^done/  s/^\([^)]*\)[^#]*#\(.*$\)/\1 \2/p' $0
+}
+#defaults
+debug=0
+clean_work=1
+
+#parse flags
+while getopts ':c:pdvqo:' OPT; do
+    case $OPT in
+    	c) ESG_CREDENTIALS="$OPTARG";;	#<cert> : use this certificate for authentication.
+        p) clean_work=0;;       #	: preserve data that failed checksum
+        o) output="$OPTARG";;   #<file>	: Write output for DML in the given file
+        d) debug=1;;            #	: display debug information
+        v) verbose=1;;          #       : be more verbose
+        q) quiet=1;;            #	: be less verbose
+        \?) echo "Unknown option '$OPTARG'" >&2 && usage && exit 1;;
+        \:) echo "Missing parameter for flag '$OPTARG'" >&2 && usage && exit 1;;
+    esac
+done
+shift $(($OPTIND - 1))
+
+if [[ "$output" ]]; then
+    #check and prepare the file
+    if [[ -f "$output" ]]; then
+        read -p "Overwrite existing file $output? (y/N) " answ
+        case $answ in y|Y|yes|Yes);; *) echo "Aborting then..."; exit 0;; esac
+    fi
+    : > "$output" || { echo "Can't write file $output"; break; }
+fi
+
+##############################################################################
+
+# Retrieve ESG credentials (not done yet)
+get_credentials() {
+    cat <<EOF
+Your download selection includes data secured using ESG
+certificate-based security.  In order to access the download URLs
+you must first obtain a credentials file from your home Gateway's
+MyProxy server at vetswebprod.ucar.edu:7512
+
+If you don't already have a myproxy client you can download the
+MyProxyLogon Java client from
+  http://www.earthsystemgrid.org//webstart/myProxyLogon/MyProxyLogon-ESG.jar
+
+Then execute it as follows:
+ $ java -jar MyProxyLogon-ESG.jar -u <username> -h vetswebprod.ucar.edu -p 7512
+Further information is available at
+  http://www.earthsystemgrid.org//help/download-help.htm
+
+EOF
+	exit 1
+}
+
+# check the certificate validity
+check_cert() {
+    #chek openssl and certificate
+    if (which openssl &>/dev/null); then
+        if ! openssl x509 -checkend 0 -noout -in $ESG_CERT; then
+            echo "The Certificate has expired, please renew."
+            return 1
+        else
+            if ! openssl x509 -checkend $CERT_EXPIRATION_WARNING -noout -in $ESG_CERT; then
+                echo "The certificate expires in less than $((CERT_EXPIRATION_WARNING / 60 / 60)) hour(s), please renew."
+                return 2
+            fi
+        fi
+    fi
+}
+
+#
+# Detect ESG credentials
+#
+find_credentials() {
+
+    if [[ -f "$ESG_CREDENTIALS" ]]; then
+    	# file found, proceed.
+    	ESG_CERT="$ESG_CREDENTIALS"
+    	ESG_KEY="$ESG_CREDENTIALS"
+    elif [[ -f "$X509_USER_CERT" && -f "$X509_USER_KEY" ]]; then
+    	# second try, use these certificates.
+        ESG_CERT="$X509_USER_CERT"
+        ESG_KEY="$X509_USER_KEY"
+    else
+	    # If credentials are not present exit
+    	echo "No ESG Credentials found in $ESG_CREDENTIALS" >&2
+    	    get_credentials
+	fi
+
+
+    #chek openssl and certificate
+    if (which openssl &>/dev/null); then
+    	if ( openssl version | grep 'OpenSSL 1\.0' ); then
+        	echo '** WARNING: ESGF Host certificate checking might not be compatible with OpenSSL 1.0+'
+    	fi
+        check_cert || { (($?==1)); exit 1; }
+    fi
+    
+    if [[ $CHECK_SERVER_CERT == "Yes" ]]; then
+    	[[ -d "$ESG_CERT_DIR" ]] || { echo "CA certs not found. Aborting."; exit 1; }
+    	PKI_WGET_OPTS="--ca-directory=$ESG_CERT_DIR"
+    fi
+
+    #some wget version complain if there's no file present
+    [[ -f $COOKIE_JAR ]] || touch $COOKIE_JAR
+
+    PKI_WGET_OPTS="$PKI_WGET_OPTS --certificate=$ESG_CERT --private-key=$ESG_KEY --save-cookies=$COOKIE_JAR --load-cookies=$COOKIE_JAR"
+
+}
+
+check_chksum() {
+    local file="$1"
+    local chk_type=$2
+    local chk_value=$3
+    local local_chksum
+
+    case $chk_type in
+        md5) local_chksum=$(md5sum $file | cut -f1 -d" ");;
+        *) echo "Can't verify checksum." && return 0;;
+    esac
+
+    #verify
+    ((debug)) && echo "local:$local_chksum vs remote:$chk_value"
+    diff -q <(echo $local_chksum) <(echo $chk_value) >/dev/null
+}
+
+download() {
+    wget="wget -c $PKI_WGET_OPTS"
+    ((quiet)) && wget="$wget -q" || { ((!verbose)) && wget="$wget -nv"; }
+    
+    while read line
+    do
+        # read csv here document into proper variables
+        eval $(awk -F "' '" '{$0=substr($0,2,length($0)-2); $3=tolower($3); print "file=\""$1"\";url=\""$2"\";chksum_type=\""$3"\";chksum=\""$4"\""}' <(echo $line) )
+
+        #Process the file
+        echo -n "$file ..."
+
+        #are we just writing a file?
+        if [ "$output" ]; then
+            echo "$file - $url" >> $output
+            echo ""
+            continue
+        fi
+
+        while : ; do
+                #if we have the file, check if it's already processed.
+                [ -f $file ] && cached="$(grep $file $CACHE_FILE)" || unset cached
+
+                #check it wasn't modified
+                if [[ -n "$cached" && "$(stat -c %Y $file)" == $(echo "$cached" | cut -d ' ' -f2) ]]; then
+                    echo "Already downloaded and verified"
+                    break
+                fi
+
+                # (if we had the file size, we could check before trying to complete)
+                echo "Downloading"
+                $wget -O "$file" $url || { failed=1; break; }
+
+                #check if file is there
+                if [[ -f $file ]]; then
+                        ((debug)) && echo file found
+                        if ! check_chksum "$file" $chksum_type $chksum; then
+                                echo "  $chksum_type failed!"
+                                if ((clean_work)); then
+                                        rm $file
+                                        #try again
+                                        echo -n "  re-downloading..."
+                                        continue
+                                else
+                                        echo "  don't use -p or remove manually."
+                                fi
+                        else
+                                echo "  $chksum_type ok. done!"
+                                echo $file $(stat -c %Y $file) $chksum >> $CACHE_FILE
+                        fi
+                fi
+                #done!
+                break
+        done
+        
+        if ((failed)); then
+            echo "download failed"
+            # most common failure is certificate expiration, so check this
+            check_cert
+            unset failed
+        fi
+        
+    done <<EOF--dataset.file.url.chksum_type.chksum
+'ncl_ncarg-6.1.0.Linux_Debian_x86_64_gcc432.tar.gz' 'http://www.earthsystemgrid.org//download/fileTokenDownload.htm?fileAccessPointId=425ef002-12f9-4087-8df0-dfd60304469a&authzToken=3648d4cf-d81c-474d-9779-bd0d6f91b832&gateway=ESG-NCAR' '' ''
+'ncl_ncarg-6.1.0.Linux_Debian_x86_64_gcc445.tar.gz' 'http://www.earthsystemgrid.org//download/fileTokenDownload.htm?fileAccessPointId=afb26ae5-6a93-4801-b0fb-7bad630e922f&authzToken=c866c5c8-ea30-4682-b1ce-1040e2fa377c&gateway=ESG-NCAR' '' ''
+EOF--dataset.file.url.chksum_type.chksum
+
+}
+
+
+#
+# MAIN
+#
+echo "Running $(basename $0) version: $version"
+
+find_credentials
+#do we have old results? Create the file if not
+[ ! -f $CACHE_FILE ] && echo "#filename mtime checksum" > $CACHE_FILE
+
+download
+
+#remove duplicates (if any)
+{ rm $CACHE_FILE && tac | awk '!x[$1]++' | tac > $CACHE_FILE; } < $CACHE_FILE

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/scripts/ncl/wget-download.sh
----------------------------------------------------------------------
diff --git a/src/main/vm/src/scripts/ncl/wget-download.sh b/src/main/vm/src/scripts/ncl/wget-download.sh
new file mode 100755
index 0000000..5444fab
--- /dev/null
+++ b/src/main/vm/src/scripts/ncl/wget-download.sh
@@ -0,0 +1,263 @@
+#!/bin/bash
+#
+# ESG Federation download script
+#
+# Template version
+version=0.4.3
+# Generated by Gateway: ESG-NCAR
+#
+# Script generated user OpenID: https://www.earthsystemgrid.org/myopenid/ahart
+#
+
+CACHE_FILE=.md5_results
+
+##############################################################################
+#
+# Your download selection includes data secured using ESG
+# certificate-based security.  In order to access the download URLs
+# you must first obtain a credentials file from your home Gateway's
+# MyProxy server.
+#
+# If you don't already have a myproxy client you can download the
+# MyProxyLogon Java client from
+#   http://www.earthsystemgrid.org//webstart/myProxyLogon/MyProxyLogon-ESG.jar
+#
+# Then execute it as follows:
+#  $ java -jar MyProxyLogon-ESG.jar -h vetswebprod.ucar.edu -p 7512 -u <username>
+#
+# Further information is available at
+#   http://www.earthsystemgrid.org//help/download-help.htm
+#
+##############################################################################
+
+##############################################################################
+#
+# Script defaults
+#
+
+# ESG_HOME should point to the directory containing ESG credentials.
+#   Default is $HOME/.esg.
+ESG_HOME=${ESG_HOME:-$HOME/.esg}
+ESG_CREDENTIALS=${X509_USER_PROXY:-$ESG_HOME/credentials.pem}
+ESG_CERT_DIR=${X509_CERT_DIR:-$ESG_HOME/certificates}
+COOKIE_JAR=$ESG_HOME/cookies
+CERT_EXPIRATION_WARNING=$((60 * 60 * 1))	#One hour (in seconds)
+
+# Configure checking of server SSL certificates.
+#   Disabling server certificate checking can resolve problems with myproxy
+#   servers being out of sync with datanodes.
+CHECK_SERVER_CERT=${CHECK_SERVER_CERT:-Yes}
+
+
+
+usage() {
+    echo "Usage: $(basename $0) [flags]"
+    echo "Flags is one of:"
+    sed -n '/^while getopts/,/^done/  s/^\([^)]*\)[^#]*#\(.*$\)/\1 \2/p' $0
+}
+#defaults
+debug=0
+clean_work=1
+
+#parse flags
+while getopts ':c:pdvqo:' OPT; do
+    case $OPT in
+    	c) ESG_CREDENTIALS="$OPTARG";;	#<cert> : use this certificate for authentication.
+        p) clean_work=0;;       #	: preserve data that failed checksum
+        o) output="$OPTARG";;   #<file>	: Write output for DML in the given file
+        d) debug=1;;            #	: display debug information
+        v) verbose=1;;          #       : be more verbose
+        q) quiet=1;;            #	: be less verbose
+        \?) echo "Unknown option '$OPTARG'" >&2 && usage && exit 1;;
+        \:) echo "Missing parameter for flag '$OPTARG'" >&2 && usage && exit 1;;
+    esac
+done
+shift $(($OPTIND - 1))
+
+if [[ "$output" ]]; then
+    #check and prepare the file
+    if [[ -f "$output" ]]; then
+        read -p "Overwrite existing file $output? (y/N) " answ
+        case $answ in y|Y|yes|Yes);; *) echo "Aborting then..."; exit 0;; esac
+    fi
+    : > "$output" || { echo "Can't write file $output"; break; }
+fi
+
+##############################################################################
+
+# Retrieve ESG credentials (not done yet)
+get_credentials() {
+    cat <<EOF
+Your download selection includes data secured using ESG
+certificate-based security.  In order to access the download URLs
+you must first obtain a credentials file from your home Gateway's
+MyProxy server at vetswebprod.ucar.edu:7512
+
+If you don't already have a myproxy client you can download the
+MyProxyLogon Java client from
+  http://www.earthsystemgrid.org//webstart/myProxyLogon/MyProxyLogon-ESG.jar
+
+Then execute it as follows:
+ $ java -jar MyProxyLogon-ESG.jar -u <username> -h vetswebprod.ucar.edu -p 7512
+Further information is available at
+  http://www.earthsystemgrid.org//help/download-help.htm
+
+EOF
+	exit 1
+}
+
+# check the certificate validity
+check_cert() {
+    #chek openssl and certificate
+    if (which openssl &>/dev/null); then
+        if ! openssl x509 -checkend 0 -noout -in $ESG_CERT; then
+            echo "The Certificate has expired, please renew."
+            return 1
+        else
+            if ! openssl x509 -checkend $CERT_EXPIRATION_WARNING -noout -in $ESG_CERT; then
+                echo "The certificate expires in less than $((CERT_EXPIRATION_WARNING / 60 / 60)) hour(s), please renew."
+                return 2
+            fi
+        fi
+    fi
+}
+
+#
+# Detect ESG credentials
+#
+find_credentials() {
+
+    if [[ -f "$ESG_CREDENTIALS" ]]; then
+    	# file found, proceed.
+    	ESG_CERT="$ESG_CREDENTIALS"
+    	ESG_KEY="$ESG_CREDENTIALS"
+    elif [[ -f "$X509_USER_CERT" && -f "$X509_USER_KEY" ]]; then
+    	# second try, use these certificates.
+        ESG_CERT="$X509_USER_CERT"
+        ESG_KEY="$X509_USER_KEY"
+    else
+	    # If credentials are not present exit
+    	echo "No ESG Credentials found in $ESG_CREDENTIALS" >&2
+    	    get_credentials
+	fi
+
+
+    #chek openssl and certificate
+    if (which openssl &>/dev/null); then
+    	if ( openssl version | grep 'OpenSSL 1\.0' ); then
+        	echo '** WARNING: ESGF Host certificate checking might not be compatible with OpenSSL 1.0+'
+    	fi
+        check_cert || { (($?==1)); exit 1; }
+    fi
+    
+    if [[ $CHECK_SERVER_CERT == "Yes" ]]; then
+    	[[ -d "$ESG_CERT_DIR" ]] || { echo "CA certs not found. Aborting."; exit 1; }
+    	PKI_WGET_OPTS="--ca-directory=$ESG_CERT_DIR"
+    fi
+
+    #some wget version complain if there's no file present
+    [[ -f $COOKIE_JAR ]] || touch $COOKIE_JAR
+
+    PKI_WGET_OPTS="$PKI_WGET_OPTS --certificate=$ESG_CERT --private-key=$ESG_KEY --save-cookies=$COOKIE_JAR --load-cookies=$COOKIE_JAR"
+
+}
+
+check_chksum() {
+    local file="$1"
+    local chk_type=$2
+    local chk_value=$3
+    local local_chksum
+
+    case $chk_type in
+        md5) local_chksum=$(md5sum $file | cut -f1 -d" ");;
+        *) echo "Can't verify checksum." && return 0;;
+    esac
+
+    #verify
+    ((debug)) && echo "local:$local_chksum vs remote:$chk_value"
+    diff -q <(echo $local_chksum) <(echo $chk_value) >/dev/null
+}
+
+download() {
+    wget="wget -c $PKI_WGET_OPTS"
+    ((quiet)) && wget="$wget -q" || { ((!verbose)) && wget="$wget -nv"; }
+    
+    while read line
+    do
+        # read csv here document into proper variables
+        eval $(awk -F "' '" '{$0=substr($0,2,length($0)-2); $3=tolower($3); print "file=\""$1"\";url=\""$2"\";chksum_type=\""$3"\";chksum=\""$4"\""}' <(echo $line) )
+
+        #Process the file
+        echo -n "$file ..."
+
+        #are we just writing a file?
+        if [ "$output" ]; then
+            echo "$file - $url" >> $output
+            echo ""
+            continue
+        fi
+
+        while : ; do
+                #if we have the file, check if it's already processed.
+                [ -f $file ] && cached="$(grep $file $CACHE_FILE)" || unset cached
+
+                #check it wasn't modified
+                if [[ -n "$cached" && "$(stat -c %Y $file)" == $(echo "$cached" | cut -d ' ' -f2) ]]; then
+                    echo "Already downloaded and verified"
+                    break
+                fi
+
+                # (if we had the file size, we could check before trying to complete)
+                echo "Downloading"
+                $wget -O "$file" $url || { failed=1; break; }
+
+                #check if file is there
+                if [[ -f $file ]]; then
+                        ((debug)) && echo file found
+                        if ! check_chksum "$file" $chksum_type $chksum; then
+                                echo "  $chksum_type failed!"
+                                if ((clean_work)); then
+                                        rm $file
+                                        #try again
+                                        echo -n "  re-downloading..."
+                                        continue
+                                else
+                                        echo "  don't use -p or remove manually."
+                                fi
+                        else
+                                echo "  $chksum_type ok. done!"
+                                echo $file $(stat -c %Y $file) $chksum >> $CACHE_FILE
+                        fi
+                fi
+                #done!
+                break
+        done
+        
+        if ((failed)); then
+            echo "download failed"
+            # most common failure is certificate expiration, so check this
+            check_cert
+            unset failed
+        fi
+        
+    done <<EOF--dataset.file.url.chksum_type.chksum
+'ncl_ncarg-6.1.0.Linux_Debian_x86_64_gcc432.tar.gz' 'http://www.earthsystemgrid.org//download/fileTokenDownload.htm?fileAccessPointId=425ef002-12f9-4087-8df0-dfd60304469a&authzToken=3648d4cf-d81c-474d-9779-bd0d6f91b832&gateway=ESG-NCAR' '' ''
+'ncl_ncarg-6.1.0.Linux_Debian_x86_64_gcc445.tar.gz' 'http://www.earthsystemgrid.org//download/fileTokenDownload.htm?fileAccessPointId=afb26ae5-6a93-4801-b0fb-7bad630e922f&authzToken=c866c5c8-ea30-4682-b1ce-1040e2fa377c&gateway=ESG-NCAR' '' ''
+EOF--dataset.file.url.chksum_type.chksum
+
+}
+
+
+#
+# MAIN
+#
+echo "Running $(basename $0) version: $version"
+
+find_credentials
+#do we have old results? Create the file if not
+[ ! -f $CACHE_FILE ] && echo "#filename mtime checksum" > $CACHE_FILE
+
+download
+
+#remove duplicates (if any)
+{ rm $CACHE_FILE && tac | awk '!x[$1]++' | tac > $CACHE_FILE; } < $CACHE_FILE

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/webapp/.htaccess
----------------------------------------------------------------------
diff --git a/src/main/webapp/.htaccess b/src/main/webapp/.htaccess
new file mode 100755
index 0000000..e3a557a
--- /dev/null
+++ b/src/main/webapp/.htaccess
@@ -0,0 +1,45 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+# Rewrite rules for OODT Balance web applications. 
+#
+# Enable the rewrite engine
+RewriteEngine On
+
+# Make sure that the value for RewriteBase exactly matches the 
+# value for site_root in config.ini. This value should point to the 
+# location (relative to the server's document root) of the 
+# Balance webapp directory (the directory containing config.ini). For
+# example, if the application lives at the server's document root, then
+# RewriteBase should be set to '/'. If, on the other hand, the application
+# has been installed into a subdirectory 'foo' underneath the server's 
+# document root, RewriteBase (and site_root in config.ini) should be set
+# to '/foo/'
+RewriteBase /
+
+# This section forwards all requests to the Balance application's front
+# controller. Unless you are modifying the low-level behavior of the 
+# Balance application framework, there should be no need to make any
+# modifications below this line. -----------------------------------------
+#
+# Send all other non-static requests to the main controller
+RewriteCond %{REQUEST_URI} !/static/(.*)$
+RewriteCond %{REQUEST_URI} !/scripts/(.*)$
+RewriteCond %{REQUEST_URI} !/global/(.*)$
+RewriteCond %{REQUEST_URI} !index\.php/.+$
+RewriteRule ^(.+)$ ./index\.php/$1 [L,NC]
+

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/webapp/.svn/all-wcprops
----------------------------------------------------------------------
diff --git a/src/main/webapp/.svn/all-wcprops b/src/main/webapp/.svn/all-wcprops
new file mode 100755
index 0000000..e4f2a3f
--- /dev/null
+++ b/src/main/webapp/.svn/all-wcprops
@@ -0,0 +1,29 @@
+K 25
+svn:wc:ra_dav:version-url
+V 73
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/webapp
+END
+config.ini
+K 25
+svn:wc:ra_dav:version-url
+V 84
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/webapp/config.ini
+END
+hooks.php
+K 25
+svn:wc:ra_dav:version-url
+V 83
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/webapp/hooks.php
+END
+.htaccess
+K 25
+svn:wc:ra_dav:version-url
+V 83
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/webapp/.htaccess
+END
+index.php
+K 25
+svn:wc:ra_dav:version-url
+V 83
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/webapp/index.php
+END

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/webapp/.svn/entries
----------------------------------------------------------------------
diff --git a/src/main/webapp/.svn/entries b/src/main/webapp/.svn/entries
new file mode 100755
index 0000000..7bc877c
--- /dev/null
+++ b/src/main/webapp/.svn/entries
@@ -0,0 +1,179 @@
+10
+
+dir
+1485921
+https://svn.apache.org/repos/asf/incubator/climate/trunk/rcmet/src/main/webapp
+https://svn.apache.org/repos/asf
+
+
+
+2012-11-20T16:20:28.221964Z
+1474523
+ahart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+13f79535-47bb-0310-9956-ffa450edef68
+
+config.ini
+file
+
+
+
+
+2013-05-24T10:14:00.000000Z
+e49532fda7eb6df157d387d9ea350851
+2012-11-20T16:20:28.221964Z
+1474523
+ahart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+2517
+
+scripts
+dir
+
+static
+dir
+
+modules
+dir
+
+hooks.php
+file
+
+
+
+
+2013-05-24T10:14:00.000000Z
+c31a5fa4bf9795a92d66b219d41c469f
+2011-12-13T03:57:45.293099Z
+1471825
+mattmann
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+2541
+
+.htaccess
+file
+
+
+
+
+2013-05-24T10:14:00.000000Z
+e90d0903d188427e6503322c57c57f03
+2012-08-30T16:31:25.045467Z
+1473966
+ahart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+2030
+
+classes
+dir
+
+views
+dir
+
+index.php
+file
+
+
+
+
+2013-05-24T10:14:00.000000Z
+72fa0dc92daed41b3cc30c7515daa7c3
+2012-08-30T16:30:39.702082Z
+1473965
+ahart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+1855
+


[11/51] [abbrv] [partial] Adding Jinwon's custom RCMET

Posted by jo...@apache.org.
http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/test/lib/angular/angular-mocks.js
----------------------------------------------------------------------
diff --git a/src/main/ui/test/lib/angular/angular-mocks.js b/src/main/ui/test/lib/angular/angular-mocks.js
new file mode 100755
index 0000000..b6ecc79
--- /dev/null
+++ b/src/main/ui/test/lib/angular/angular-mocks.js
@@ -0,0 +1,1764 @@
+/**
+ * @license AngularJS v1.0.5
+ * (c) 2010-2012 Google, Inc. http://angularjs.org
+ * License: MIT
+ *
+ * TODO(vojta): wrap whole file into closure during build
+ */
+
+/**
+ * @ngdoc overview
+ * @name angular.mock
+ * @description
+ *
+ * Namespace from 'angular-mocks.js' which contains testing related code.
+ */
+angular.mock = {};
+
+/**
+ * ! This is a private undocumented service !
+ *
+ * @name ngMock.$browser
+ *
+ * @description
+ * This service is a mock implementation of {@link ng.$browser}. It provides fake
+ * implementation for commonly used browser apis that are hard to test, e.g. setTimeout, xhr,
+ * cookies, etc...
+ *
+ * The api of this service is the same as that of the real {@link ng.$browser $browser}, except
+ * that there are several helper methods available which can be used in tests.
+ */
+angular.mock.$BrowserProvider = function() {
+  this.$get = function(){
+    return new angular.mock.$Browser();
+  };
+};
+
+angular.mock.$Browser = function() {
+  var self = this;
+
+  this.isMock = true;
+  self.$$url = "http://server/";
+  self.$$lastUrl = self.$$url; // used by url polling fn
+  self.pollFns = [];
+
+  // TODO(vojta): remove this temporary api
+  self.$$completeOutstandingRequest = angular.noop;
+  self.$$incOutstandingRequestCount = angular.noop;
+
+
+  // register url polling fn
+
+  self.onUrlChange = function(listener) {
+    self.pollFns.push(
+      function() {
+        if (self.$$lastUrl != self.$$url) {
+          self.$$lastUrl = self.$$url;
+          listener(self.$$url);
+        }
+      }
+    );
+
+    return listener;
+  };
+
+  self.cookieHash = {};
+  self.lastCookieHash = {};
+  self.deferredFns = [];
+  self.deferredNextId = 0;
+
+  self.defer = function(fn, delay) {
+    delay = delay || 0;
+    self.deferredFns.push({time:(self.defer.now + delay), fn:fn, id: self.deferredNextId});
+    self.deferredFns.sort(function(a,b){ return a.time - b.time;});
+    return self.deferredNextId++;
+  };
+
+
+  self.defer.now = 0;
+
+
+  self.defer.cancel = function(deferId) {
+    var fnIndex;
+
+    angular.forEach(self.deferredFns, function(fn, index) {
+      if (fn.id === deferId) fnIndex = index;
+    });
+
+    if (fnIndex !== undefined) {
+      self.deferredFns.splice(fnIndex, 1);
+      return true;
+    }
+
+    return false;
+  };
+
+
+  /**
+   * @name ngMock.$browser#defer.flush
+   * @methodOf ngMock.$browser
+   *
+   * @description
+   * Flushes all pending requests and executes the defer callbacks.
+   *
+   * @param {number=} number of milliseconds to flush. See {@link #defer.now}
+   */
+  self.defer.flush = function(delay) {
+    if (angular.isDefined(delay)) {
+      self.defer.now += delay;
+    } else {
+      if (self.deferredFns.length) {
+        self.defer.now = self.deferredFns[self.deferredFns.length-1].time;
+      } else {
+        throw Error('No deferred tasks to be flushed');
+      }
+    }
+
+    while (self.deferredFns.length && self.deferredFns[0].time <= self.defer.now) {
+      self.deferredFns.shift().fn();
+    }
+  };
+  /**
+   * @name ngMock.$browser#defer.now
+   * @propertyOf ngMock.$browser
+   *
+   * @description
+   * Current milliseconds mock time.
+   */
+
+  self.$$baseHref = '';
+  self.baseHref = function() {
+    return this.$$baseHref;
+  };
+};
+angular.mock.$Browser.prototype = {
+
+/**
+  * @name ngMock.$browser#poll
+  * @methodOf ngMock.$browser
+  *
+  * @description
+  * run all fns in pollFns
+  */
+  poll: function poll() {
+    angular.forEach(this.pollFns, function(pollFn){
+      pollFn();
+    });
+  },
+
+  addPollFn: function(pollFn) {
+    this.pollFns.push(pollFn);
+    return pollFn;
+  },
+
+  url: function(url, replace) {
+    if (url) {
+      this.$$url = url;
+      return this;
+    }
+
+    return this.$$url;
+  },
+
+  cookies:  function(name, value) {
+    if (name) {
+      if (value == undefined) {
+        delete this.cookieHash[name];
+      } else {
+        if (angular.isString(value) &&       //strings only
+            value.length <= 4096) {          //strict cookie storage limits
+          this.cookieHash[name] = value;
+        }
+      }
+    } else {
+      if (!angular.equals(this.cookieHash, this.lastCookieHash)) {
+        this.lastCookieHash = angular.copy(this.cookieHash);
+        this.cookieHash = angular.copy(this.cookieHash);
+      }
+      return this.cookieHash;
+    }
+  },
+
+  notifyWhenNoOutstandingRequests: function(fn) {
+    fn();
+  }
+};
+
+
+/**
+ * @ngdoc object
+ * @name ngMock.$exceptionHandlerProvider
+ *
+ * @description
+ * Configures the mock implementation of {@link ng.$exceptionHandler} to rethrow or to log errors passed
+ * into the `$exceptionHandler`.
+ */
+
+/**
+ * @ngdoc object
+ * @name ngMock.$exceptionHandler
+ *
+ * @description
+ * Mock implementation of {@link ng.$exceptionHandler} that rethrows or logs errors passed
+ * into it. See {@link ngMock.$exceptionHandlerProvider $exceptionHandlerProvider} for configuration
+ * information.
+ *
+ *
+ * <pre>
+ *   describe('$exceptionHandlerProvider', function() {
+ *
+ *     it('should capture log messages and exceptions', function() {
+ *
+ *       module(function($exceptionHandlerProvider) {
+ *         $exceptionHandlerProvider.mode('log');
+ *       });
+ *
+ *       inject(function($log, $exceptionHandler, $timeout) {
+ *         $timeout(function() { $log.log(1); });
+ *         $timeout(function() { $log.log(2); throw 'banana peel'; });
+ *         $timeout(function() { $log.log(3); });
+ *         expect($exceptionHandler.errors).toEqual([]);
+ *         expect($log.assertEmpty());
+ *         $timeout.flush();
+ *         expect($exceptionHandler.errors).toEqual(['banana peel']);
+ *         expect($log.log.logs).toEqual([[1], [2], [3]]);
+ *       });
+ *     });
+ *   });
+ * </pre>
+ */
+
+angular.mock.$ExceptionHandlerProvider = function() {
+  var handler;
+
+  /**
+   * @ngdoc method
+   * @name ngMock.$exceptionHandlerProvider#mode
+   * @methodOf ngMock.$exceptionHandlerProvider
+   *
+   * @description
+   * Sets the logging mode.
+   *
+   * @param {string} mode Mode of operation, defaults to `rethrow`.
+   *
+   *   - `rethrow`: If any errors are are passed into the handler in tests, it typically
+   *                means that there is a bug in the application or test, so this mock will
+   *                make these tests fail.
+   *   - `log`: Sometimes it is desirable to test that an error is throw, for this case the `log` mode stores an
+   *            array of errors in `$exceptionHandler.errors`, to allow later assertion of them.
+   *            See {@link ngMock.$log#assertEmpty assertEmpty()} and
+   *             {@link ngMock.$log#reset reset()}
+   */
+  this.mode = function(mode) {
+    switch(mode) {
+      case 'rethrow':
+        handler = function(e) {
+          throw e;
+        };
+        break;
+      case 'log':
+        var errors = [];
+
+        handler = function(e) {
+          if (arguments.length == 1) {
+            errors.push(e);
+          } else {
+            errors.push([].slice.call(arguments, 0));
+          }
+        };
+
+        handler.errors = errors;
+        break;
+      default:
+        throw Error("Unknown mode '" + mode + "', only 'log'/'rethrow' modes are allowed!");
+    }
+  };
+
+  this.$get = function() {
+    return handler;
+  };
+
+  this.mode('rethrow');
+};
+
+
+/**
+ * @ngdoc service
+ * @name ngMock.$log
+ *
+ * @description
+ * Mock implementation of {@link ng.$log} that gathers all logged messages in arrays
+ * (one array per logging level). These arrays are exposed as `logs` property of each of the
+ * level-specific log function, e.g. for level `error` the array is exposed as `$log.error.logs`.
+ *
+ */
+angular.mock.$LogProvider = function() {
+
+  function concat(array1, array2, index) {
+    return array1.concat(Array.prototype.slice.call(array2, index));
+  }
+
+
+  this.$get = function () {
+    var $log = {
+      log: function() { $log.log.logs.push(concat([], arguments, 0)); },
+      warn: function() { $log.warn.logs.push(concat([], arguments, 0)); },
+      info: function() { $log.info.logs.push(concat([], arguments, 0)); },
+      error: function() { $log.error.logs.push(concat([], arguments, 0)); }
+    };
+
+    /**
+     * @ngdoc method
+     * @name ngMock.$log#reset
+     * @methodOf ngMock.$log
+     *
+     * @description
+     * Reset all of the logging arrays to empty.
+     */
+    $log.reset = function () {
+      /**
+       * @ngdoc property
+       * @name ngMock.$log#log.logs
+       * @propertyOf ngMock.$log
+       *
+       * @description
+       * Array of logged messages.
+       */
+      $log.log.logs = [];
+      /**
+       * @ngdoc property
+       * @name ngMock.$log#warn.logs
+       * @propertyOf ngMock.$log
+       *
+       * @description
+       * Array of logged messages.
+       */
+      $log.warn.logs = [];
+      /**
+       * @ngdoc property
+       * @name ngMock.$log#info.logs
+       * @propertyOf ngMock.$log
+       *
+       * @description
+       * Array of logged messages.
+       */
+      $log.info.logs = [];
+      /**
+       * @ngdoc property
+       * @name ngMock.$log#error.logs
+       * @propertyOf ngMock.$log
+       *
+       * @description
+       * Array of logged messages.
+       */
+      $log.error.logs = [];
+    };
+
+    /**
+     * @ngdoc method
+     * @name ngMock.$log#assertEmpty
+     * @methodOf ngMock.$log
+     *
+     * @description
+     * Assert that the all of the logging methods have no logged messages. If messages present, an exception is thrown.
+     */
+    $log.assertEmpty = function() {
+      var errors = [];
+      angular.forEach(['error', 'warn', 'info', 'log'], function(logLevel) {
+        angular.forEach($log[logLevel].logs, function(log) {
+          angular.forEach(log, function (logItem) {
+            errors.push('MOCK $log (' + logLevel + '): ' + String(logItem) + '\n' + (logItem.stack || ''));
+          });
+        });
+      });
+      if (errors.length) {
+        errors.unshift("Expected $log to be empty! Either a message was logged unexpectedly, or an expected " +
+          "log message was not checked and removed:");
+        errors.push('');
+        throw new Error(errors.join('\n---------\n'));
+      }
+    };
+
+    $log.reset();
+    return $log;
+  };
+};
+
+
+(function() {
+  var R_ISO8061_STR = /^(\d{4})-?(\d\d)-?(\d\d)(?:T(\d\d)(?:\:?(\d\d)(?:\:?(\d\d)(?:\.(\d{3}))?)?)?(Z|([+-])(\d\d):?(\d\d)))?$/;
+
+  function jsonStringToDate(string){
+    var match;
+    if (match = string.match(R_ISO8061_STR)) {
+      var date = new Date(0),
+          tzHour = 0,
+          tzMin  = 0;
+      if (match[9]) {
+        tzHour = int(match[9] + match[10]);
+        tzMin = int(match[9] + match[11]);
+      }
+      date.setUTCFullYear(int(match[1]), int(match[2]) - 1, int(match[3]));
+      date.setUTCHours(int(match[4]||0) - tzHour, int(match[5]||0) - tzMin, int(match[6]||0), int(match[7]||0));
+      return date;
+    }
+    return string;
+  }
+
+  function int(str) {
+    return parseInt(str, 10);
+  }
+
+  function padNumber(num, digits, trim) {
+    var neg = '';
+    if (num < 0) {
+      neg =  '-';
+      num = -num;
+    }
+    num = '' + num;
+    while(num.length < digits) num = '0' + num;
+    if (trim)
+      num = num.substr(num.length - digits);
+    return neg + num;
+  }
+
+
+  /**
+   * @ngdoc object
+   * @name angular.mock.TzDate
+   * @description
+   *
+   * *NOTE*: this is not an injectable instance, just a globally available mock class of `Date`.
+   *
+   * Mock of the Date type which has its timezone specified via constroctor arg.
+   *
+   * The main purpose is to create Date-like instances with timezone fixed to the specified timezone
+   * offset, so that we can test code that depends on local timezone settings without dependency on
+   * the time zone settings of the machine where the code is running.
+   *
+   * @param {number} offset Offset of the *desired* timezone in hours (fractions will be honored)
+   * @param {(number|string)} timestamp Timestamp representing the desired time in *UTC*
+   *
+   * @example
+   * !!!! WARNING !!!!!
+   * This is not a complete Date object so only methods that were implemented can be called safely.
+   * To make matters worse, TzDate instances inherit stuff from Date via a prototype.
+   *
+   * We do our best to intercept calls to "unimplemented" methods, but since the list of methods is
+   * incomplete we might be missing some non-standard methods. This can result in errors like:
+   * "Date.prototype.foo called on incompatible Object".
+   *
+   * <pre>
+   * var newYearInBratislava = new TzDate(-1, '2009-12-31T23:00:00Z');
+   * newYearInBratislava.getTimezoneOffset() => -60;
+   * newYearInBratislava.getFullYear() => 2010;
+   * newYearInBratislava.getMonth() => 0;
+   * newYearInBratislava.getDate() => 1;
+   * newYearInBratislava.getHours() => 0;
+   * newYearInBratislava.getMinutes() => 0;
+   * </pre>
+   *
+   */
+  angular.mock.TzDate = function (offset, timestamp) {
+    var self = new Date(0);
+    if (angular.isString(timestamp)) {
+      var tsStr = timestamp;
+
+      self.origDate = jsonStringToDate(timestamp);
+
+      timestamp = self.origDate.getTime();
+      if (isNaN(timestamp))
+        throw {
+          name: "Illegal Argument",
+          message: "Arg '" + tsStr + "' passed into TzDate constructor is not a valid date string"
+        };
+    } else {
+      self.origDate = new Date(timestamp);
+    }
+
+    var localOffset = new Date(timestamp).getTimezoneOffset();
+    self.offsetDiff = localOffset*60*1000 - offset*1000*60*60;
+    self.date = new Date(timestamp + self.offsetDiff);
+
+    self.getTime = function() {
+      return self.date.getTime() - self.offsetDiff;
+    };
+
+    self.toLocaleDateString = function() {
+      return self.date.toLocaleDateString();
+    };
+
+    self.getFullYear = function() {
+      return self.date.getFullYear();
+    };
+
+    self.getMonth = function() {
+      return self.date.getMonth();
+    };
+
+    self.getDate = function() {
+      return self.date.getDate();
+    };
+
+    self.getHours = function() {
+      return self.date.getHours();
+    };
+
+    self.getMinutes = function() {
+      return self.date.getMinutes();
+    };
+
+    self.getSeconds = function() {
+      return self.date.getSeconds();
+    };
+
+    self.getTimezoneOffset = function() {
+      return offset * 60;
+    };
+
+    self.getUTCFullYear = function() {
+      return self.origDate.getUTCFullYear();
+    };
+
+    self.getUTCMonth = function() {
+      return self.origDate.getUTCMonth();
+    };
+
+    self.getUTCDate = function() {
+      return self.origDate.getUTCDate();
+    };
+
+    self.getUTCHours = function() {
+      return self.origDate.getUTCHours();
+    };
+
+    self.getUTCMinutes = function() {
+      return self.origDate.getUTCMinutes();
+    };
+
+    self.getUTCSeconds = function() {
+      return self.origDate.getUTCSeconds();
+    };
+
+    self.getUTCMilliseconds = function() {
+      return self.origDate.getUTCMilliseconds();
+    };
+
+    self.getDay = function() {
+      return self.date.getDay();
+    };
+
+    // provide this method only on browsers that already have it
+    if (self.toISOString) {
+      self.toISOString = function() {
+        return padNumber(self.origDate.getUTCFullYear(), 4) + '-' +
+              padNumber(self.origDate.getUTCMonth() + 1, 2) + '-' +
+              padNumber(self.origDate.getUTCDate(), 2) + 'T' +
+              padNumber(self.origDate.getUTCHours(), 2) + ':' +
+              padNumber(self.origDate.getUTCMinutes(), 2) + ':' +
+              padNumber(self.origDate.getUTCSeconds(), 2) + '.' +
+              padNumber(self.origDate.getUTCMilliseconds(), 3) + 'Z'
+      }
+    }
+
+    //hide all methods not implemented in this mock that the Date prototype exposes
+    var unimplementedMethods = ['getMilliseconds', 'getUTCDay',
+        'getYear', 'setDate', 'setFullYear', 'setHours', 'setMilliseconds',
+        'setMinutes', 'setMonth', 'setSeconds', 'setTime', 'setUTCDate', 'setUTCFullYear',
+        'setUTCHours', 'setUTCMilliseconds', 'setUTCMinutes', 'setUTCMonth', 'setUTCSeconds',
+        'setYear', 'toDateString', 'toGMTString', 'toJSON', 'toLocaleFormat', 'toLocaleString',
+        'toLocaleTimeString', 'toSource', 'toString', 'toTimeString', 'toUTCString', 'valueOf'];
+
+    angular.forEach(unimplementedMethods, function(methodName) {
+      self[methodName] = function() {
+        throw Error("Method '" + methodName + "' is not implemented in the TzDate mock");
+      };
+    });
+
+    return self;
+  };
+
+  //make "tzDateInstance instanceof Date" return true
+  angular.mock.TzDate.prototype = Date.prototype;
+})();
+
+
+/**
+ * @ngdoc function
+ * @name angular.mock.dump
+ * @description
+ *
+ * *NOTE*: this is not an injectable instance, just a globally available function.
+ *
+ * Method for serializing common angular objects (scope, elements, etc..) into strings, useful for debugging.
+ *
+ * This method is also available on window, where it can be used to display objects on debug console.
+ *
+ * @param {*} object - any object to turn into string.
+ * @return {string} a serialized string of the argument
+ */
+angular.mock.dump = function(object) {
+  return serialize(object);
+
+  function serialize(object) {
+    var out;
+
+    if (angular.isElement(object)) {
+      object = angular.element(object);
+      out = angular.element('<div></div>');
+      angular.forEach(object, function(element) {
+        out.append(angular.element(element).clone());
+      });
+      out = out.html();
+    } else if (angular.isArray(object)) {
+      out = [];
+      angular.forEach(object, function(o) {
+        out.push(serialize(o));
+      });
+      out = '[ ' + out.join(', ') + ' ]';
+    } else if (angular.isObject(object)) {
+      if (angular.isFunction(object.$eval) && angular.isFunction(object.$apply)) {
+        out = serializeScope(object);
+      } else if (object instanceof Error) {
+        out = object.stack || ('' + object.name + ': ' + object.message);
+      } else {
+        out = angular.toJson(object, true);
+      }
+    } else {
+      out = String(object);
+    }
+
+    return out;
+  }
+
+  function serializeScope(scope, offset) {
+    offset = offset ||  '  ';
+    var log = [offset + 'Scope(' + scope.$id + '): {'];
+    for ( var key in scope ) {
+      if (scope.hasOwnProperty(key) && !key.match(/^(\$|this)/)) {
+        log.push('  ' + key + ': ' + angular.toJson(scope[key]));
+      }
+    }
+    var child = scope.$$childHead;
+    while(child) {
+      log.push(serializeScope(child, offset + '  '));
+      child = child.$$nextSibling;
+    }
+    log.push('}');
+    return log.join('\n' + offset);
+  }
+};
+
+/**
+ * @ngdoc object
+ * @name ngMock.$httpBackend
+ * @description
+ * Fake HTTP backend implementation suitable for unit testing application that use the
+ * {@link ng.$http $http service}.
+ *
+ * *Note*: For fake http backend implementation suitable for end-to-end testing or backend-less
+ * development please see {@link ngMockE2E.$httpBackend e2e $httpBackend mock}.
+ *
+ * During unit testing, we want our unit tests to run quickly and have no external dependencies so
+ * we don’t want to send {@link https://developer.mozilla.org/en/xmlhttprequest XHR} or
+ * {@link http://en.wikipedia.org/wiki/JSONP JSONP} requests to a real server. All we really need is
+ * to verify whether a certain request has been sent or not, or alternatively just let the
+ * application make requests, respond with pre-trained responses and assert that the end result is
+ * what we expect it to be.
+ *
+ * This mock implementation can be used to respond with static or dynamic responses via the
+ * `expect` and `when` apis and their shortcuts (`expectGET`, `whenPOST`, etc).
+ *
+ * When an Angular application needs some data from a server, it calls the $http service, which
+ * sends the request to a real server using $httpBackend service. With dependency injection, it is
+ * easy to inject $httpBackend mock (which has the same API as $httpBackend) and use it to verify
+ * the requests and respond with some testing data without sending a request to real server.
+ *
+ * There are two ways to specify what test data should be returned as http responses by the mock
+ * backend when the code under test makes http requests:
+ *
+ * - `$httpBackend.expect` - specifies a request expectation
+ * - `$httpBackend.when` - specifies a backend definition
+ *
+ *
+ * # Request Expectations vs Backend Definitions
+ *
+ * Request expectations provide a way to make assertions about requests made by the application and
+ * to define responses for those requests. The test will fail if the expected requests are not made
+ * or they are made in the wrong order.
+ *
+ * Backend definitions allow you to define a fake backend for your application which doesn't assert
+ * if a particular request was made or not, it just returns a trained response if a request is made.
+ * The test will pass whether or not the request gets made during testing.
+ *
+ *
+ * <table class="table">
+ *   <tr><th width="220px"></th><th>Request expectations</th><th>Backend definitions</th></tr>
+ *   <tr>
+ *     <th>Syntax</th>
+ *     <td>.expect(...).respond(...)</td>
+ *     <td>.when(...).respond(...)</td>
+ *   </tr>
+ *   <tr>
+ *     <th>Typical usage</th>
+ *     <td>strict unit tests</td>
+ *     <td>loose (black-box) unit testing</td>
+ *   </tr>
+ *   <tr>
+ *     <th>Fulfills multiple requests</th>
+ *     <td>NO</td>
+ *     <td>YES</td>
+ *   </tr>
+ *   <tr>
+ *     <th>Order of requests matters</th>
+ *     <td>YES</td>
+ *     <td>NO</td>
+ *   </tr>
+ *   <tr>
+ *     <th>Request required</th>
+ *     <td>YES</td>
+ *     <td>NO</td>
+ *   </tr>
+ *   <tr>
+ *     <th>Response required</th>
+ *     <td>optional (see below)</td>
+ *     <td>YES</td>
+ *   </tr>
+ * </table>
+ *
+ * In cases where both backend definitions and request expectations are specified during unit
+ * testing, the request expectations are evaluated first.
+ *
+ * If a request expectation has no response specified, the algorithm will search your backend
+ * definitions for an appropriate response.
+ *
+ * If a request didn't match any expectation or if the expectation doesn't have the response
+ * defined, the backend definitions are evaluated in sequential order to see if any of them match
+ * the request. The response from the first matched definition is returned.
+ *
+ *
+ * # Flushing HTTP requests
+ *
+ * The $httpBackend used in production, always responds to requests with responses asynchronously.
+ * If we preserved this behavior in unit testing, we'd have to create async unit tests, which are
+ * hard to write, follow and maintain. At the same time the testing mock, can't respond
+ * synchronously because that would change the execution of the code under test. For this reason the
+ * mock $httpBackend has a `flush()` method, which allows the test to explicitly flush pending
+ * requests and thus preserving the async api of the backend, while allowing the test to execute
+ * synchronously.
+ *
+ *
+ * # Unit testing with mock $httpBackend
+ *
+ * <pre>
+   // controller
+   function MyController($scope, $http) {
+     $http.get('/auth.py').success(function(data) {
+       $scope.user = data;
+     });
+
+     this.saveMessage = function(message) {
+       $scope.status = 'Saving...';
+       $http.post('/add-msg.py', message).success(function(response) {
+         $scope.status = '';
+       }).error(function() {
+         $scope.status = 'ERROR!';
+       });
+     };
+   }
+
+   // testing controller
+   var $httpBackend;
+
+   beforeEach(inject(function($injector) {
+     $httpBackend = $injector.get('$httpBackend');
+
+     // backend definition common for all tests
+     $httpBackend.when('GET', '/auth.py').respond({userId: 'userX'}, {'A-Token': 'xxx'});
+   }));
+
+
+   afterEach(function() {
+     $httpBackend.verifyNoOutstandingExpectation();
+     $httpBackend.verifyNoOutstandingRequest();
+   });
+
+
+   it('should fetch authentication token', function() {
+     $httpBackend.expectGET('/auth.py');
+     var controller = scope.$new(MyController);
+     $httpBackend.flush();
+   });
+
+
+   it('should send msg to server', function() {
+     // now you don’t care about the authentication, but
+     // the controller will still send the request and
+     // $httpBackend will respond without you having to
+     // specify the expectation and response for this request
+     $httpBackend.expectPOST('/add-msg.py', 'message content').respond(201, '');
+
+     var controller = scope.$new(MyController);
+     $httpBackend.flush();
+     controller.saveMessage('message content');
+     expect(controller.status).toBe('Saving...');
+     $httpBackend.flush();
+     expect(controller.status).toBe('');
+   });
+
+
+   it('should send auth header', function() {
+     $httpBackend.expectPOST('/add-msg.py', undefined, function(headers) {
+       // check if the header was send, if it wasn't the expectation won't
+       // match the request and the test will fail
+       return headers['Authorization'] == 'xxx';
+     }).respond(201, '');
+
+     var controller = scope.$new(MyController);
+     controller.saveMessage('whatever');
+     $httpBackend.flush();
+   });
+   </pre>
+ */
+angular.mock.$HttpBackendProvider = function() {
+  this.$get = [createHttpBackendMock];
+};
+
+/**
+ * General factory function for $httpBackend mock.
+ * Returns instance for unit testing (when no arguments specified):
+ *   - passing through is disabled
+ *   - auto flushing is disabled
+ *
+ * Returns instance for e2e testing (when `$delegate` and `$browser` specified):
+ *   - passing through (delegating request to real backend) is enabled
+ *   - auto flushing is enabled
+ *
+ * @param {Object=} $delegate Real $httpBackend instance (allow passing through if specified)
+ * @param {Object=} $browser Auto-flushing enabled if specified
+ * @return {Object} Instance of $httpBackend mock
+ */
+function createHttpBackendMock($delegate, $browser) {
+  var definitions = [],
+      expectations = [],
+      responses = [],
+      responsesPush = angular.bind(responses, responses.push);
+
+  function createResponse(status, data, headers) {
+    if (angular.isFunction(status)) return status;
+
+    return function() {
+      return angular.isNumber(status)
+          ? [status, data, headers]
+          : [200, status, data];
+    };
+  }
+
+  // TODO(vojta): change params to: method, url, data, headers, callback
+  function $httpBackend(method, url, data, callback, headers) {
+    var xhr = new MockXhr(),
+        expectation = expectations[0],
+        wasExpected = false;
+
+    function prettyPrint(data) {
+      return (angular.isString(data) || angular.isFunction(data) || data instanceof RegExp)
+          ? data
+          : angular.toJson(data);
+    }
+
+    if (expectation && expectation.match(method, url)) {
+      if (!expectation.matchData(data))
+        throw Error('Expected ' + expectation + ' with different data\n' +
+            'EXPECTED: ' + prettyPrint(expectation.data) + '\nGOT:      ' + data);
+
+      if (!expectation.matchHeaders(headers))
+        throw Error('Expected ' + expectation + ' with different headers\n' +
+            'EXPECTED: ' + prettyPrint(expectation.headers) + '\nGOT:      ' +
+            prettyPrint(headers));
+
+      expectations.shift();
+
+      if (expectation.response) {
+        responses.push(function() {
+          var response = expectation.response(method, url, data, headers);
+          xhr.$$respHeaders = response[2];
+          callback(response[0], response[1], xhr.getAllResponseHeaders());
+        });
+        return;
+      }
+      wasExpected = true;
+    }
+
+    var i = -1, definition;
+    while ((definition = definitions[++i])) {
+      if (definition.match(method, url, data, headers || {})) {
+        if (definition.response) {
+          // if $browser specified, we do auto flush all requests
+          ($browser ? $browser.defer : responsesPush)(function() {
+            var response = definition.response(method, url, data, headers);
+            xhr.$$respHeaders = response[2];
+            callback(response[0], response[1], xhr.getAllResponseHeaders());
+          });
+        } else if (definition.passThrough) {
+          $delegate(method, url, data, callback, headers);
+        } else throw Error('No response defined !');
+        return;
+      }
+    }
+    throw wasExpected ?
+        Error('No response defined !') :
+        Error('Unexpected request: ' + method + ' ' + url + '\n' +
+              (expectation ? 'Expected ' + expectation : 'No more request expected'));
+  }
+
+  /**
+   * @ngdoc method
+   * @name ngMock.$httpBackend#when
+   * @methodOf ngMock.$httpBackend
+   * @description
+   * Creates a new backend definition.
+   *
+   * @param {string} method HTTP method.
+   * @param {string|RegExp} url HTTP url.
+   * @param {(string|RegExp)=} data HTTP request body.
+   * @param {(Object|function(Object))=} headers HTTP headers or function that receives http header
+   *   object and returns true if the headers match the current definition.
+   * @returns {requestHandler} Returns an object with `respond` method that control how a matched
+   *   request is handled.
+   *
+   *  - respond – `{function([status,] data[, headers])|function(function(method, url, data, headers)}`
+   *    – The respond method takes a set of static data to be returned or a function that can return
+   *    an array containing response status (number), response data (string) and response headers
+   *    (Object).
+   */
+  $httpBackend.when = function(method, url, data, headers) {
+    var definition = new MockHttpExpectation(method, url, data, headers),
+        chain = {
+          respond: function(status, data, headers) {
+            definition.response = createResponse(status, data, headers);
+          }
+        };
+
+    if ($browser) {
+      chain.passThrough = function() {
+        definition.passThrough = true;
+      };
+    }
+
+    definitions.push(definition);
+    return chain;
+  };
+
+  /**
+   * @ngdoc method
+   * @name ngMock.$httpBackend#whenGET
+   * @methodOf ngMock.$httpBackend
+   * @description
+   * Creates a new backend definition for GET requests. For more info see `when()`.
+   *
+   * @param {string|RegExp} url HTTP url.
+   * @param {(Object|function(Object))=} headers HTTP headers.
+   * @returns {requestHandler} Returns an object with `respond` method that control how a matched
+   * request is handled.
+   */
+
+  /**
+   * @ngdoc method
+   * @name ngMock.$httpBackend#whenHEAD
+   * @methodOf ngMock.$httpBackend
+   * @description
+   * Creates a new backend definition for HEAD requests. For more info see `when()`.
+   *
+   * @param {string|RegExp} url HTTP url.
+   * @param {(Object|function(Object))=} headers HTTP headers.
+   * @returns {requestHandler} Returns an object with `respond` method that control how a matched
+   * request is handled.
+   */
+
+  /**
+   * @ngdoc method
+   * @name ngMock.$httpBackend#whenDELETE
+   * @methodOf ngMock.$httpBackend
+   * @description
+   * Creates a new backend definition for DELETE requests. For more info see `when()`.
+   *
+   * @param {string|RegExp} url HTTP url.
+   * @param {(Object|function(Object))=} headers HTTP headers.
+   * @returns {requestHandler} Returns an object with `respond` method that control how a matched
+   * request is handled.
+   */
+
+  /**
+   * @ngdoc method
+   * @name ngMock.$httpBackend#whenPOST
+   * @methodOf ngMock.$httpBackend
+   * @description
+   * Creates a new backend definition for POST requests. For more info see `when()`.
+   *
+   * @param {string|RegExp} url HTTP url.
+   * @param {(string|RegExp)=} data HTTP request body.
+   * @param {(Object|function(Object))=} headers HTTP headers.
+   * @returns {requestHandler} Returns an object with `respond` method that control how a matched
+   * request is handled.
+   */
+
+  /**
+   * @ngdoc method
+   * @name ngMock.$httpBackend#whenPUT
+   * @methodOf ngMock.$httpBackend
+   * @description
+   * Creates a new backend definition for PUT requests.  For more info see `when()`.
+   *
+   * @param {string|RegExp} url HTTP url.
+   * @param {(string|RegExp)=} data HTTP request body.
+   * @param {(Object|function(Object))=} headers HTTP headers.
+   * @returns {requestHandler} Returns an object with `respond` method that control how a matched
+   * request is handled.
+   */
+
+  /**
+   * @ngdoc method
+   * @name ngMock.$httpBackend#whenJSONP
+   * @methodOf ngMock.$httpBackend
+   * @description
+   * Creates a new backend definition for JSONP requests. For more info see `when()`.
+   *
+   * @param {string|RegExp} url HTTP url.
+   * @returns {requestHandler} Returns an object with `respond` method that control how a matched
+   * request is handled.
+   */
+  createShortMethods('when');
+
+
+  /**
+   * @ngdoc method
+   * @name ngMock.$httpBackend#expect
+   * @methodOf ngMock.$httpBackend
+   * @description
+   * Creates a new request expectation.
+   *
+   * @param {string} method HTTP method.
+   * @param {string|RegExp} url HTTP url.
+   * @param {(string|RegExp)=} data HTTP request body.
+   * @param {(Object|function(Object))=} headers HTTP headers or function that receives http header
+   *   object and returns true if the headers match the current expectation.
+   * @returns {requestHandler} Returns an object with `respond` method that control how a matched
+   *  request is handled.
+   *
+   *  - respond – `{function([status,] data[, headers])|function(function(method, url, data, headers)}`
+   *    – The respond method takes a set of static data to be returned or a function that can return
+   *    an array containing response status (number), response data (string) and response headers
+   *    (Object).
+   */
+  $httpBackend.expect = function(method, url, data, headers) {
+    var expectation = new MockHttpExpectation(method, url, data, headers);
+    expectations.push(expectation);
+    return {
+      respond: function(status, data, headers) {
+        expectation.response = createResponse(status, data, headers);
+      }
+    };
+  };
+
+
+  /**
+   * @ngdoc method
+   * @name ngMock.$httpBackend#expectGET
+   * @methodOf ngMock.$httpBackend
+   * @description
+   * Creates a new request expectation for GET requests. For more info see `expect()`.
+   *
+   * @param {string|RegExp} url HTTP url.
+   * @param {Object=} headers HTTP headers.
+   * @returns {requestHandler} Returns an object with `respond` method that control how a matched
+   * request is handled. See #expect for more info.
+   */
+
+  /**
+   * @ngdoc method
+   * @name ngMock.$httpBackend#expectHEAD
+   * @methodOf ngMock.$httpBackend
+   * @description
+   * Creates a new request expectation for HEAD requests. For more info see `expect()`.
+   *
+   * @param {string|RegExp} url HTTP url.
+   * @param {Object=} headers HTTP headers.
+   * @returns {requestHandler} Returns an object with `respond` method that control how a matched
+   *   request is handled.
+   */
+
+  /**
+   * @ngdoc method
+   * @name ngMock.$httpBackend#expectDELETE
+   * @methodOf ngMock.$httpBackend
+   * @description
+   * Creates a new request expectation for DELETE requests. For more info see `expect()`.
+   *
+   * @param {string|RegExp} url HTTP url.
+   * @param {Object=} headers HTTP headers.
+   * @returns {requestHandler} Returns an object with `respond` method that control how a matched
+   *   request is handled.
+   */
+
+  /**
+   * @ngdoc method
+   * @name ngMock.$httpBackend#expectPOST
+   * @methodOf ngMock.$httpBackend
+   * @description
+   * Creates a new request expectation for POST requests. For more info see `expect()`.
+   *
+   * @param {string|RegExp} url HTTP url.
+   * @param {(string|RegExp)=} data HTTP request body.
+   * @param {Object=} headers HTTP headers.
+   * @returns {requestHandler} Returns an object with `respond` method that control how a matched
+   *   request is handled.
+   */
+
+  /**
+   * @ngdoc method
+   * @name ngMock.$httpBackend#expectPUT
+   * @methodOf ngMock.$httpBackend
+   * @description
+   * Creates a new request expectation for PUT requests. For more info see `expect()`.
+   *
+   * @param {string|RegExp} url HTTP url.
+   * @param {(string|RegExp)=} data HTTP request body.
+   * @param {Object=} headers HTTP headers.
+   * @returns {requestHandler} Returns an object with `respond` method that control how a matched
+   *   request is handled.
+   */
+
+  /**
+   * @ngdoc method
+   * @name ngMock.$httpBackend#expectPATCH
+   * @methodOf ngMock.$httpBackend
+   * @description
+   * Creates a new request expectation for PATCH requests. For more info see `expect()`.
+   *
+   * @param {string|RegExp} url HTTP url.
+   * @param {(string|RegExp)=} data HTTP request body.
+   * @param {Object=} headers HTTP headers.
+   * @returns {requestHandler} Returns an object with `respond` method that control how a matched
+   *   request is handled.
+   */
+
+  /**
+   * @ngdoc method
+   * @name ngMock.$httpBackend#expectJSONP
+   * @methodOf ngMock.$httpBackend
+   * @description
+   * Creates a new request expectation for JSONP requests. For more info see `expect()`.
+   *
+   * @param {string|RegExp} url HTTP url.
+   * @returns {requestHandler} Returns an object with `respond` method that control how a matched
+   *   request is handled.
+   */
+  createShortMethods('expect');
+
+
+  /**
+   * @ngdoc method
+   * @name ngMock.$httpBackend#flush
+   * @methodOf ngMock.$httpBackend
+   * @description
+   * Flushes all pending requests using the trained responses.
+   *
+   * @param {number=} count Number of responses to flush (in the order they arrived). If undefined,
+   *   all pending requests will be flushed. If there are no pending requests when the flush method
+   *   is called an exception is thrown (as this typically a sign of programming error).
+   */
+  $httpBackend.flush = function(count) {
+    if (!responses.length) throw Error('No pending request to flush !');
+
+    if (angular.isDefined(count)) {
+      while (count--) {
+        if (!responses.length) throw Error('No more pending request to flush !');
+        responses.shift()();
+      }
+    } else {
+      while (responses.length) {
+        responses.shift()();
+      }
+    }
+    $httpBackend.verifyNoOutstandingExpectation();
+  };
+
+
+  /**
+   * @ngdoc method
+   * @name ngMock.$httpBackend#verifyNoOutstandingExpectation
+   * @methodOf ngMock.$httpBackend
+   * @description
+   * Verifies that all of the requests defined via the `expect` api were made. If any of the
+   * requests were not made, verifyNoOutstandingExpectation throws an exception.
+   *
+   * Typically, you would call this method following each test case that asserts requests using an
+   * "afterEach" clause.
+   *
+   * <pre>
+   *   afterEach($httpBackend.verifyExpectations);
+   * </pre>
+   */
+  $httpBackend.verifyNoOutstandingExpectation = function() {
+    if (expectations.length) {
+      throw Error('Unsatisfied requests: ' + expectations.join(', '));
+    }
+  };
+
+
+  /**
+   * @ngdoc method
+   * @name ngMock.$httpBackend#verifyNoOutstandingRequest
+   * @methodOf ngMock.$httpBackend
+   * @description
+   * Verifies that there are no outstanding requests that need to be flushed.
+   *
+   * Typically, you would call this method following each test case that asserts requests using an
+   * "afterEach" clause.
+   *
+   * <pre>
+   *   afterEach($httpBackend.verifyNoOutstandingRequest);
+   * </pre>
+   */
+  $httpBackend.verifyNoOutstandingRequest = function() {
+    if (responses.length) {
+      throw Error('Unflushed requests: ' + responses.length);
+    }
+  };
+
+
+  /**
+   * @ngdoc method
+   * @name ngMock.$httpBackend#resetExpectations
+   * @methodOf ngMock.$httpBackend
+   * @description
+   * Resets all request expectations, but preserves all backend definitions. Typically, you would
+   * call resetExpectations during a multiple-phase test when you want to reuse the same instance of
+   * $httpBackend mock.
+   */
+  $httpBackend.resetExpectations = function() {
+    expectations.length = 0;
+    responses.length = 0;
+  };
+
+  return $httpBackend;
+
+
+  function createShortMethods(prefix) {
+    angular.forEach(['GET', 'DELETE', 'JSONP'], function(method) {
+     $httpBackend[prefix + method] = function(url, headers) {
+       return $httpBackend[prefix](method, url, undefined, headers)
+     }
+    });
+
+    angular.forEach(['PUT', 'POST', 'PATCH'], function(method) {
+      $httpBackend[prefix + method] = function(url, data, headers) {
+        return $httpBackend[prefix](method, url, data, headers)
+      }
+    });
+  }
+}
+
+function MockHttpExpectation(method, url, data, headers) {
+
+  this.data = data;
+  this.headers = headers;
+
+  this.match = function(m, u, d, h) {
+    if (method != m) return false;
+    if (!this.matchUrl(u)) return false;
+    if (angular.isDefined(d) && !this.matchData(d)) return false;
+    if (angular.isDefined(h) && !this.matchHeaders(h)) return false;
+    return true;
+  };
+
+  this.matchUrl = function(u) {
+    if (!url) return true;
+    if (angular.isFunction(url.test)) return url.test(u);
+    return url == u;
+  };
+
+  this.matchHeaders = function(h) {
+    if (angular.isUndefined(headers)) return true;
+    if (angular.isFunction(headers)) return headers(h);
+    return angular.equals(headers, h);
+  };
+
+  this.matchData = function(d) {
+    if (angular.isUndefined(data)) return true;
+    if (data && angular.isFunction(data.test)) return data.test(d);
+    if (data && !angular.isString(data)) return angular.toJson(data) == d;
+    return data == d;
+  };
+
+  this.toString = function() {
+    return method + ' ' + url;
+  };
+}
+
+function MockXhr() {
+
+  // hack for testing $http, $httpBackend
+  MockXhr.$$lastInstance = this;
+
+  this.open = function(method, url, async) {
+    this.$$method = method;
+    this.$$url = url;
+    this.$$async = async;
+    this.$$reqHeaders = {};
+    this.$$respHeaders = {};
+  };
+
+  this.send = function(data) {
+    this.$$data = data;
+  };
+
+  this.setRequestHeader = function(key, value) {
+    this.$$reqHeaders[key] = value;
+  };
+
+  this.getResponseHeader = function(name) {
+    // the lookup must be case insensitive, that's why we try two quick lookups and full scan at last
+    var header = this.$$respHeaders[name];
+    if (header) return header;
+
+    name = angular.lowercase(name);
+    header = this.$$respHeaders[name];
+    if (header) return header;
+
+    header = undefined;
+    angular.forEach(this.$$respHeaders, function(headerVal, headerName) {
+      if (!header && angular.lowercase(headerName) == name) header = headerVal;
+    });
+    return header;
+  };
+
+  this.getAllResponseHeaders = function() {
+    var lines = [];
+
+    angular.forEach(this.$$respHeaders, function(value, key) {
+      lines.push(key + ': ' + value);
+    });
+    return lines.join('\n');
+  };
+
+  this.abort = angular.noop;
+}
+
+
+/**
+ * @ngdoc function
+ * @name ngMock.$timeout
+ * @description
+ *
+ * This service is just a simple decorator for {@link ng.$timeout $timeout} service
+ * that adds a "flush" method.
+ */
+
+/**
+ * @ngdoc method
+ * @name ngMock.$timeout#flush
+ * @methodOf ngMock.$timeout
+ * @description
+ *
+ * Flushes the queue of pending tasks.
+ */
+
+/**
+ *
+ */
+angular.mock.$RootElementProvider = function() {
+  this.$get = function() {
+    return angular.element('<div ng-app></div>');
+  }
+};
+
+/**
+ * @ngdoc overview
+ * @name ngMock
+ * @description
+ *
+ * The `ngMock` is an angular module which is used with `ng` module and adds unit-test configuration as well as useful
+ * mocks to the {@link AUTO.$injector $injector}.
+ */
+angular.module('ngMock', ['ng']).provider({
+  $browser: angular.mock.$BrowserProvider,
+  $exceptionHandler: angular.mock.$ExceptionHandlerProvider,
+  $log: angular.mock.$LogProvider,
+  $httpBackend: angular.mock.$HttpBackendProvider,
+  $rootElement: angular.mock.$RootElementProvider
+}).config(function($provide) {
+  $provide.decorator('$timeout', function($delegate, $browser) {
+    $delegate.flush = function() {
+      $browser.defer.flush();
+    };
+    return $delegate;
+  });
+});
+
+
+/**
+ * @ngdoc overview
+ * @name ngMockE2E
+ * @description
+ *
+ * The `ngMockE2E` is an angular module which contains mocks suitable for end-to-end testing.
+ * Currently there is only one mock present in this module -
+ * the {@link ngMockE2E.$httpBackend e2e $httpBackend} mock.
+ */
+angular.module('ngMockE2E', ['ng']).config(function($provide) {
+  $provide.decorator('$httpBackend', angular.mock.e2e.$httpBackendDecorator);
+});
+
+/**
+ * @ngdoc object
+ * @name ngMockE2E.$httpBackend
+ * @description
+ * Fake HTTP backend implementation suitable for end-to-end testing or backend-less development of
+ * applications that use the {@link ng.$http $http service}.
+ *
+ * *Note*: For fake http backend implementation suitable for unit testing please see
+ * {@link ngMock.$httpBackend unit-testing $httpBackend mock}.
+ *
+ * This implementation can be used to respond with static or dynamic responses via the `when` api
+ * and its shortcuts (`whenGET`, `whenPOST`, etc) and optionally pass through requests to the
+ * real $httpBackend for specific requests (e.g. to interact with certain remote apis or to fetch
+ * templates from a webserver).
+ *
+ * As opposed to unit-testing, in an end-to-end testing scenario or in scenario when an application
+ * is being developed with the real backend api replaced with a mock, it is often desirable for
+ * certain category of requests to bypass the mock and issue a real http request (e.g. to fetch
+ * templates or static files from the webserver). To configure the backend with this behavior
+ * use the `passThrough` request handler of `when` instead of `respond`.
+ *
+ * Additionally, we don't want to manually have to flush mocked out requests like we do during unit
+ * testing. For this reason the e2e $httpBackend automatically flushes mocked out requests
+ * automatically, closely simulating the behavior of the XMLHttpRequest object.
+ *
+ * To setup the application to run with this http backend, you have to create a module that depends
+ * on the `ngMockE2E` and your application modules and defines the fake backend:
+ *
+ * <pre>
+ *   myAppDev = angular.module('myAppDev', ['myApp', 'ngMockE2E']);
+ *   myAppDev.run(function($httpBackend) {
+ *     phones = [{name: 'phone1'}, {name: 'phone2'}];
+ *
+ *     // returns the current list of phones
+ *     $httpBackend.whenGET('/phones').respond(phones);
+ *
+ *     // adds a new phone to the phones array
+ *     $httpBackend.whenPOST('/phones').respond(function(method, url, data) {
+ *       phones.push(angular.fromJSON(data));
+ *     });
+ *     $httpBackend.whenGET(/^\/templates\//).passThrough();
+ *     //...
+ *   });
+ * </pre>
+ *
+ * Afterwards, bootstrap your app with this new module.
+ */
+
+/**
+ * @ngdoc method
+ * @name ngMockE2E.$httpBackend#when
+ * @methodOf ngMockE2E.$httpBackend
+ * @description
+ * Creates a new backend definition.
+ *
+ * @param {string} method HTTP method.
+ * @param {string|RegExp} url HTTP url.
+ * @param {(string|RegExp)=} data HTTP request body.
+ * @param {(Object|function(Object))=} headers HTTP headers or function that receives http header
+ *   object and returns true if the headers match the current definition.
+ * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that
+ *   control how a matched request is handled.
+ *
+ *  - respond – `{function([status,] data[, headers])|function(function(method, url, data, headers)}`
+ *    – The respond method takes a set of static data to be returned or a function that can return
+ *    an array containing response status (number), response data (string) and response headers
+ *    (Object).
+ *  - passThrough – `{function()}` – Any request matching a backend definition with `passThrough`
+ *    handler, will be pass through to the real backend (an XHR request will be made to the
+ *    server.
+ */
+
+/**
+ * @ngdoc method
+ * @name ngMockE2E.$httpBackend#whenGET
+ * @methodOf ngMockE2E.$httpBackend
+ * @description
+ * Creates a new backend definition for GET requests. For more info see `when()`.
+ *
+ * @param {string|RegExp} url HTTP url.
+ * @param {(Object|function(Object))=} headers HTTP headers.
+ * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that
+ *   control how a matched request is handled.
+ */
+
+/**
+ * @ngdoc method
+ * @name ngMockE2E.$httpBackend#whenHEAD
+ * @methodOf ngMockE2E.$httpBackend
+ * @description
+ * Creates a new backend definition for HEAD requests. For more info see `when()`.
+ *
+ * @param {string|RegExp} url HTTP url.
+ * @param {(Object|function(Object))=} headers HTTP headers.
+ * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that
+ *   control how a matched request is handled.
+ */
+
+/**
+ * @ngdoc method
+ * @name ngMockE2E.$httpBackend#whenDELETE
+ * @methodOf ngMockE2E.$httpBackend
+ * @description
+ * Creates a new backend definition for DELETE requests. For more info see `when()`.
+ *
+ * @param {string|RegExp} url HTTP url.
+ * @param {(Object|function(Object))=} headers HTTP headers.
+ * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that
+ *   control how a matched request is handled.
+ */
+
+/**
+ * @ngdoc method
+ * @name ngMockE2E.$httpBackend#whenPOST
+ * @methodOf ngMockE2E.$httpBackend
+ * @description
+ * Creates a new backend definition for POST requests. For more info see `when()`.
+ *
+ * @param {string|RegExp} url HTTP url.
+ * @param {(string|RegExp)=} data HTTP request body.
+ * @param {(Object|function(Object))=} headers HTTP headers.
+ * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that
+ *   control how a matched request is handled.
+ */
+
+/**
+ * @ngdoc method
+ * @name ngMockE2E.$httpBackend#whenPUT
+ * @methodOf ngMockE2E.$httpBackend
+ * @description
+ * Creates a new backend definition for PUT requests.  For more info see `when()`.
+ *
+ * @param {string|RegExp} url HTTP url.
+ * @param {(string|RegExp)=} data HTTP request body.
+ * @param {(Object|function(Object))=} headers HTTP headers.
+ * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that
+ *   control how a matched request is handled.
+ */
+
+/**
+ * @ngdoc method
+ * @name ngMockE2E.$httpBackend#whenPATCH
+ * @methodOf ngMockE2E.$httpBackend
+ * @description
+ * Creates a new backend definition for PATCH requests.  For more info see `when()`.
+ *
+ * @param {string|RegExp} url HTTP url.
+ * @param {(string|RegExp)=} data HTTP request body.
+ * @param {(Object|function(Object))=} headers HTTP headers.
+ * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that
+ *   control how a matched request is handled.
+ */
+
+/**
+ * @ngdoc method
+ * @name ngMockE2E.$httpBackend#whenJSONP
+ * @methodOf ngMockE2E.$httpBackend
+ * @description
+ * Creates a new backend definition for JSONP requests. For more info see `when()`.
+ *
+ * @param {string|RegExp} url HTTP url.
+ * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that
+ *   control how a matched request is handled.
+ */
+angular.mock.e2e = {};
+angular.mock.e2e.$httpBackendDecorator = ['$delegate', '$browser', createHttpBackendMock];
+
+
+angular.mock.clearDataCache = function() {
+  var key,
+      cache = angular.element.cache;
+
+  for(key in cache) {
+    if (cache.hasOwnProperty(key)) {
+      var handle = cache[key].handle;
+
+      handle && angular.element(handle.elem).unbind();
+      delete cache[key];
+    }
+  }
+};
+
+
+window.jstestdriver && (function(window) {
+  /**
+   * Global method to output any number of objects into JSTD console. Useful for debugging.
+   */
+  window.dump = function() {
+    var args = [];
+    angular.forEach(arguments, function(arg) {
+      args.push(angular.mock.dump(arg));
+    });
+    jstestdriver.console.log.apply(jstestdriver.console, args);
+    if (window.console) {
+      window.console.log.apply(window.console, args);
+    }
+  };
+})(window);
+
+
+window.jasmine && (function(window) {
+
+  afterEach(function() {
+    var spec = getCurrentSpec();
+    var injector = spec.$injector;
+
+    spec.$injector = null;
+    spec.$modules = null;
+
+    if (injector) {
+      injector.get('$rootElement').unbind();
+      injector.get('$browser').pollFns.length = 0;
+    }
+
+    angular.mock.clearDataCache();
+
+    // clean up jquery's fragment cache
+    angular.forEach(angular.element.fragments, function(val, key) {
+      delete angular.element.fragments[key];
+    });
+
+    MockXhr.$$lastInstance = null;
+
+    angular.forEach(angular.callbacks, function(val, key) {
+      delete angular.callbacks[key];
+    });
+    angular.callbacks.counter = 0;
+  });
+
+  function getCurrentSpec() {
+    return jasmine.getEnv().currentSpec;
+  }
+
+  function isSpecRunning() {
+    var spec = getCurrentSpec();
+    return spec && spec.queue.running;
+  }
+
+  /**
+   * @ngdoc function
+   * @name angular.mock.module
+   * @description
+   *
+   * *NOTE*: This is function is also published on window for easy access.<br>
+   * *NOTE*: Only available with {@link http://pivotal.github.com/jasmine/ jasmine}.
+   *
+   * This function registers a module configuration code. It collects the configuration information
+   * which will be used when the injector is created by {@link angular.mock.inject inject}.
+   *
+   * See {@link angular.mock.inject inject} for usage example
+   *
+   * @param {...(string|Function)} fns any number of modules which are represented as string
+   *        aliases or as anonymous module initialization functions. The modules are used to
+   *        configure the injector. The 'ng' and 'ngMock' modules are automatically loaded.
+   */
+  window.module = angular.mock.module = function() {
+    var moduleFns = Array.prototype.slice.call(arguments, 0);
+    return isSpecRunning() ? workFn() : workFn;
+    /////////////////////
+    function workFn() {
+      var spec = getCurrentSpec();
+      if (spec.$injector) {
+        throw Error('Injector already created, can not register a module!');
+      } else {
+        var modules = spec.$modules || (spec.$modules = []);
+        angular.forEach(moduleFns, function(module) {
+          modules.push(module);
+        });
+      }
+    }
+  };
+
+  /**
+   * @ngdoc function
+   * @name angular.mock.inject
+   * @description
+   *
+   * *NOTE*: This is function is also published on window for easy access.<br>
+   * *NOTE*: Only available with {@link http://pivotal.github.com/jasmine/ jasmine}.
+   *
+   * The inject function wraps a function into an injectable function. The inject() creates new
+   * instance of {@link AUTO.$injector $injector} per test, which is then used for
+   * resolving references.
+   *
+   * See also {@link angular.mock.module module}
+   *
+   * Example of what a typical jasmine tests looks like with the inject method.
+   * <pre>
+   *
+   *   angular.module('myApplicationModule', [])
+   *       .value('mode', 'app')
+   *       .value('version', 'v1.0.1');
+   *
+   *
+   *   describe('MyApp', function() {
+   *
+   *     // You need to load modules that you want to test,
+   *     // it loads only the "ng" module by default.
+   *     beforeEach(module('myApplicationModule'));
+   *
+   *
+   *     // inject() is used to inject arguments of all given functions
+   *     it('should provide a version', inject(function(mode, version) {
+   *       expect(version).toEqual('v1.0.1');
+   *       expect(mode).toEqual('app');
+   *     }));
+   *
+   *
+   *     // The inject and module method can also be used inside of the it or beforeEach
+   *     it('should override a version and test the new version is injected', function() {
+   *       // module() takes functions or strings (module aliases)
+   *       module(function($provide) {
+   *         $provide.value('version', 'overridden'); // override version here
+   *       });
+   *
+   *       inject(function(version) {
+   *         expect(version).toEqual('overridden');
+   *       });
+   *     ));
+   *   });
+   *
+   * </pre>
+   *
+   * @param {...Function} fns any number of functions which will be injected using the injector.
+   */
+  window.inject = angular.mock.inject = function() {
+    var blockFns = Array.prototype.slice.call(arguments, 0);
+    var errorForStack = new Error('Declaration Location');
+    return isSpecRunning() ? workFn() : workFn;
+    /////////////////////
+    function workFn() {
+      var spec = getCurrentSpec();
+      var modules = spec.$modules || [];
+      modules.unshift('ngMock');
+      modules.unshift('ng');
+      var injector = spec.$injector;
+      if (!injector) {
+        injector = spec.$injector = angular.injector(modules);
+      }
+      for(var i = 0, ii = blockFns.length; i < ii; i++) {
+        try {
+          injector.invoke(blockFns[i] || angular.noop, this);
+        } catch (e) {
+          if(e.stack) e.stack +=  '\n' + errorForStack.stack;
+          throw e;
+        } finally {
+          errorForStack = null;
+        }
+      }
+    }
+  };
+})(window);


[39/51] [abbrv] [partial] Adding Jinwon's custom RCMET

Posted by jo...@apache.org.
http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/rcmes/toolkit/process.py
----------------------------------------------------------------------
diff --git a/src/main/python/rcmes/toolkit/process.py b/src/main/python/rcmes/toolkit/process.py
new file mode 100755
index 0000000..78f37f5
--- /dev/null
+++ b/src/main/python/rcmes/toolkit/process.py
@@ -0,0 +1,1270 @@
+"""Collection of functions that process numpy arrays of varying shapes.  
+Functions can range from subsetting to regridding"""
+
+# Python Standard Libary Imports
+import os, subprocess
+import math
+import datetime
+import re
+import string
+import sys
+import time
+
+# 3rd Party Imports
+import netCDF4
+import numpy as np
+import numpy.ma as ma
+from scipy.ndimage import map_coordinates
+
+
+def extract_subregion_from_data_array(data, lats, lons, latmin, latmax, lonmin, lonmax):
+    '''
+     Extract a sub-region from a data array.
+     
+     Example::
+       **e.g.** the user may load a global model file, but only want to examine data over North America
+            This function extracts a sub-domain from the original data.
+            The defined sub-region must be a regular lat/lon bounding box,
+            but the model data may be on a non-regular grid (e.g. rotated, or Guassian grid layout).
+            Data are kept on the original model grid and a rectangular (in model-space) region 
+            is extracted which contains the rectangular (in lat/lon space) user supplied region.
+    
+     INPUT::
+       data - 3d masked data array
+       lats - 2d array of latitudes corresponding to data array
+       lons - 2d array of longitudes corresponding to data array
+       latmin, latmax, lonmin, lonmax - bounding box of required region to extract
+       
+     OUTPUT::
+       data2 - subset of original data array containing only data from required subregion
+       lats2 - subset of original latitude data array
+       lons2 - subset of original longitude data array
+
+    '''
+    
+    
+
+    # Mask model data array to find grid points inside the supplied bounding box
+    whlat = (lats > latmin) & (lats < latmax)
+    whlon = (lons > lonmin) & (lons < lonmax)
+    wh = whlat & whlon
+
+    # Find required matrix indices describing the limits of the regular lat/lon bounding box
+    jmax = np.where(wh == True)[0].max()
+    jmin = np.where(wh == True)[0].min()
+    imax = np.where(wh == True)[1].max()
+    imin = np.where(wh == True)[1].min()
+
+    # Cut out the sub-region from the data array
+    data2 = ma.zeros((data.shape[0], jmax - jmin, imax - imin))
+    data2 = data[:, jmin:jmax, imin:imax]
+
+    # Cut out sub-region from lats,lons arrays
+    lats2 = lats[jmin:jmax, imin:imax]
+    lons2 = lons[jmin:jmax, imin:imax]
+
+    return data2, lats2, lons2
+
+def calc_area_mean(data, lats, lons, mymask='not set'):
+    '''
+     Calculate Area Average of data in a masked array
+     
+     INPUT::
+         data:  a masked array of data (NB. only data from one time expected to be passed at once)
+         lats:  2d array of regularly gridded latitudes
+         lons:  2d array of regularly gridded longitudes
+         mymask:  (optional) defines spatial region to do averaging over
+     
+     OUTPUT::
+         area_mean: a value for the mean inside the area
+
+    '''
+    
+    
+
+    # If mask not passed in, then set maks to cover whole data domain
+    if(mymask == 'not set'):
+       mymask = np.empty(data.shape)
+       mymask[:] = False	# NB. mask means (don't show), so False everywhere means use everything.
+   
+    # Dimension check on lats, lons
+    #  Sometimes these arrays are 3d, sometimes 2d, sometimes 1d
+    #  This bit of code just converts to the required 2d array shape
+    if(len(lats.shape) == 3):
+       lats = lats[0, :, :]
+
+    if(len(lons.shape) == 3):
+       lons = lons[0, :, :]
+
+    if(np.logical_and(len(lats.shape) == 1, len(lons.shape) == 1)):
+       lons, lats = np.meshgrid(lons, lats)
+ 
+    # Calculate grid length (assuming regular lat/lon grid)
+    dlat = lats[1, 0] - lats[0, 0]
+    dlon = lons[0, 1] - lons[0, 0]
+
+    # Calculates weights for each grid box
+    myweights = calc_area_in_grid_box(lats, dlon, dlat)
+
+    # Create a new masked array covering just user selected area (defined in mymask)
+    #   NB. this preserves missing data points in the observations data
+    subdata = ma.masked_array(data, mask=mymask)
+ 
+    if(myweights.shape != subdata.shape):
+       myweights.resize(subdata.shape)
+       myweights[1:, :] = myweights[0, :]
+
+    # Calculate weighted mean using ma.average (which takes weights)
+    area_mean = ma.average(subdata, weights=myweights)
+ 
+    return area_mean
+
+def calc_area_in_grid_box(latitude, dlat, dlon):
+    '''
+     Calculate area of regular lat-lon grid box
+     
+     INPUT::
+        latitude: latitude of grid box (degrees)
+        dlat:     grid length in latitude direction (degrees)
+        dlon:     grid length in longitude direction (degrees)
+        
+     OUTPUT::
+        A:        area of the grid box
+      
+      '''
+
+    R = 6371000  # radius of Earth in metres
+    C = 2 * math.pi * R
+
+    latitude = np.radians(latitude)
+
+    A = (dlon * (C / 360.)) * (dlat * (C / 360.) * np.cos(latitude))
+
+    return A
+
+def do_regrid(q, lat, lon, lat2, lon2, order=1, mdi= -999999999):
+    '''
+     Perform regridding from one set of lat,lon values onto a new set (lat2,lon2)
+    
+     Input::
+         q          - the variable to be regridded
+         lat,lon    - original co-ordinates corresponding to q values
+         lat2,lon2  - new set of latitudes and longitudes that you want to regrid q onto 
+         order      - (optional) interpolation order 1=bi-linear, 3=cubic spline
+         mdi  	    - (optional) fill value for missing data (used in creation of masked array)
+      
+     Output::
+         q2  - q regridded onto the new set of lat2,lon2 
+    
+    '''
+
+    nlat = q.shape[0]
+    nlon = q.shape[1]
+
+    nlat2 = lat2.shape[0]
+    nlon2 = lon2.shape[1]
+
+    # To make our lives easier down the road, let's 
+    # turn these into arrays of x & y coords
+    loni = lon2.ravel()
+    lati = lat2.ravel()
+
+    loni = loni.copy() # NB. it won't run unless you do this...
+    lati = lati.copy()
+
+    # Now, we'll set points outside the boundaries to lie along an edge
+    loni[loni > lon.max()] = lon.max()
+    loni[loni < lon.min()] = lon.min()
+    
+    # To deal with the "hard" break, we'll have to treat y differently,
+    # so we're just setting the min here...
+    lati[lati > lat.max()] = lat.max()
+    lati[lati < lat.min()] = lat.min()
+    
+    
+    # We need to convert these to (float) indicies
+    #   (xi should range from 0 to (nx - 1), etc)
+    loni = (nlon - 1) * (loni - lon.min()) / (lon.max() - lon.min())
+    
+    # Deal with the "hard" break in the y-direction
+    lati = (nlat - 1) * (lati - lat.min()) / (lat.max() - lat.min())
+    
+    # Notes on dealing with MDI when regridding data.
+    #  Method adopted here:
+    #    Use bilinear interpolation of data by default (but user can specify other order using order=... in call)
+    #    Perform bilinear interpolation of data, and of mask.
+    #    To be conservative, new grid point which contained some missing data on the old grid is set to missing data.
+    #            -this is achieved by looking for any non-zero interpolated mask values.
+    #    To avoid issues with bilinear interpolation producing strong gradients leading into the MDI,
+    #     set values at MDI points to mean data value so little gradient visible = not ideal, but acceptable for now.
+    
+    # Set values in MDI so that similar to surroundings so don't produce large gradients when interpolating
+    # Preserve MDI mask, by only changing data part of masked array object.
+    for shift in (-1, 1):
+        for axis in (0, 1):
+            q_shifted = np.roll(q, shift=shift, axis=axis)
+            idx = ~q_shifted.mask * q.mask
+            q.data[idx] = q_shifted[idx]
+
+    # Now we actually interpolate
+    # map_coordinates does cubic interpolation by default, 
+    # use "order=1" to preform bilinear interpolation instead...
+    q2 = map_coordinates(q, [lati, loni], order=order)
+    q2 = q2.reshape([nlat2, nlon2])
+
+    # Set values to missing data outside of original domain
+    q2 = ma.masked_array(q2, mask=np.logical_or(np.logical_or(lat2 >= lat.max(), 
+                                                              lat2 <= lat.min()), 
+                                                np.logical_or(lon2 <= lon.min(), 
+                                                              lon2 >= lon.max())))
+    
+    # Make second map using nearest neighbour interpolation -use this to determine locations with MDI and mask these
+    qmdi = np.zeros_like(q)
+    qmdi[q.mask == True] = 1.
+    qmdi[q.mask == False] = 0.
+    qmdi_r = map_coordinates(qmdi, [lati, loni], order=order)
+    qmdi_r = qmdi_r.reshape([nlat2, nlon2])
+    mdimask = (qmdi_r != 0.0)
+    
+    # Combine missing data mask, with outside domain mask define above.
+    q2.mask = np.logical_or(mdimask, q2.mask)
+
+    return q2
+
+def create_mask_using_threshold(masked_array, threshold=0.5):
+   '''
+    Routine to create a mask, depending on the proportion of times with missing data.
+    For each pixel, calculate proportion of times that are missing data,
+    **if** the proportion is above a specified threshold value,
+    then mark the pixel as missing data.
+   
+    Input::
+        masked_array - a numpy masked array of data (assumes time on axis 0, and space on axes 1 and 2).
+        threshold    - (optional) threshold proportion above which a pixel is marked as 'missing data'. 
+        NB. default threshold = 50%
+   
+    Output::
+        mymask       - a numpy array describing the mask. NB. not a masked array, just the mask itself.
+
+   '''
+   
+
+   # try, except used as some model files don't have a full mask, but a single bool
+   #  the except catches this situation and deals with it appropriately.
+   try:
+       nT = masked_array.mask.shape[0]
+
+       # For each pixel, count how many times are masked.
+       nMasked = masked_array.mask[:, :, :].sum(axis=0)
+
+       # Define new mask as when a pixel has over a defined threshold ratio of masked data
+       #   e.g. if the threshold is 75%, and there are 10 times,
+       #        then a pixel will be masked if more than 5 times are masked.
+       mymask = nMasked > (nT * threshold)
+
+   except:
+       mymask = np.zeros_like(masked_array.data[0, :, :])
+
+   return mymask
+
+def calc_average_on_new_time_unit(data, dateList, unit='monthly'):
+   '''
+    Routine to calculate averages on longer time units than the data exists on.
+    
+    Example::
+        If the data is 6-hourly, calculate daily, or monthly means.
+   
+    Input::
+        data     - data values
+        dateList - list of python datetime structures corresponding to data values
+        unit     - string describing time unit to average onto. 
+        *Valid values are: 'monthly', 'daily', 'pentad','annual','decadal'*
+      
+     Output:
+        meanstorem - numpy masked array of data values meaned over required time period
+        newTimesList - a list of python datetime objects representing the data in the new averagin period
+        *NB.* currently set to beginning of averaging period, 
+        **i.e. mean Jan 1st - Jan 31st -> represented as Jan 1st, 00Z.**
+   '''
+
+   # First catch unknown values of time unit passed in by user
+   acceptable = (unit == 'full') | (unit == 'annual') | (unit == 'monthly') | (unit == 'daily') | (unit == 'pentad')
+
+   if not acceptable:
+      print 'Error: unknown unit type selected for time averaging'
+      print '       Please check your code.'
+      return
+
+   # Calculate arrays of years (2007,2007),
+   #                     yearsmonths (200701,200702),
+   #                     or yearmonthdays (20070101,20070102) 
+   #  -depending on user selected averaging period.
+
+   # Year list
+   if unit == 'annual':
+      print 'Calculating annual mean data'
+      timeunits = []
+
+      for i in np.arange(len(dateList)):
+         timeunits.append(str(dateList[i].year))
+
+      timeunits = np.array(timeunits, dtype=int)
+         
+   # YearMonth format list
+   if unit == 'monthly':
+      print 'Calculating monthly mean data'
+      timeunits = []
+
+      for i in np.arange(len(dateList)):
+         timeunits.append(str(dateList[i].year) + str("%02d" % dateList[i].month))
+
+      timeunits = np.array(timeunits, dtype=int)
+
+   # YearMonthDay format list
+   if unit == 'daily':
+      print 'Calculating daily mean data'
+      timeunits = []
+ 
+      for i in np.arange(len(dateList)):
+         timeunits.append(str(dateList[i].year) + str("%02d" % dateList[i].month) + \
+                          str("%02d" % dateList[i].day))
+
+      timeunits = np.array(timeunits, dtype=int)
+
+
+   # TODO: add pentad setting using Julian days?
+
+
+   # Full list: a special case
+   if unit == 'full':
+      print 'Calculating means data over full time range'
+      timeunits = []
+
+      for i in np.arange(len(dateList)):
+         timeunits.append(999)  # i.e. we just want the same value for all times.
+
+      timeunits = np.array(timeunits, dtype=int)
+
+
+
+   # empty list to store new times
+   newTimesList = []
+
+   # Decide whether or not you need to do any time averaging.
+   #   i.e. if data are already on required time unit then just pass data through and 
+   #        calculate and return representative datetimes.
+   processing_required = True
+   if len(timeunits) == (len(np.unique(timeunits))):
+        processing_required = False
+
+   # 1D data arrays, i.e. time series
+   if data.ndim == 1:
+     # Create array to store the resulting data
+     meanstore = np.zeros(len(np.unique(timeunits)))
+  
+     # Calculate the means across each unique time unit
+     i = 0
+     for myunit in np.unique(timeunits):
+       if processing_required:
+         datam = ma.masked_array(data, timeunits != myunit)
+         meanstore[i] = ma.average(datam)
+
+       # construct new times list
+       smyunit = str(myunit)
+       if len(smyunit) == 4:  # YYYY
+        yyyy = int(myunit[0:4])
+        mm = 1
+        dd = 1
+       if len(smyunit) == 6:  # YYYYMM
+        yyyy = int(smyunit[0:4])
+        mm = int(smyunit[4:6])
+        dd = 1
+       if len(smyunit) == 8:  # YYYYMMDD
+        yyyy = int(smyunit[0:4])
+        mm = int(smyunit[4:6])
+        dd = int(smyunit[6:8])
+       if len(smyunit) == 3:  # Full time range
+        # Need to set an appropriate time representing the mid-point of the entire time span
+        dt = dateList[-1] - dateList[0]
+        halfway = dateList[0] + (dt / 2)
+        yyyy = int(halfway.year)
+        mm = int(halfway.month)
+        dd = int(halfway.day)
+  
+       newTimesList.append(datetime.datetime(yyyy, mm, dd, 0, 0, 0, 0))
+       i = i + 1
+
+   # 3D data arrays
+   if data.ndim == 3:
+
+     #datamask = create_mask_using_threshold(data,threshold=0.75)
+
+     # Create array to store the resulting data
+     meanstore = np.zeros([len(np.unique(timeunits)), data.shape[1], data.shape[2]])
+  
+     # Calculate the means across each unique time unit
+     i = 0
+     datamask_store = []
+     for myunit in np.unique(timeunits):
+       if processing_required:
+
+         mask = np.zeros_like(data)
+         mask[timeunits != myunit, :, :] = 1.0
+
+         # Calculate missing data mask within each time unit...
+         datamask_at_this_timeunit = np.zeros_like(data)
+         datamask_at_this_timeunit[:] = create_mask_using_threshold(data[timeunits == myunit, :, :], threshold=0.75)
+         # Store results for masking later
+         datamask_store.append(datamask_at_this_timeunit[0])
+
+         # Calculate means for each pixel in this time unit, ignoring missing data (using masked array).
+         datam = ma.masked_array(data, np.logical_or(mask, datamask_at_this_timeunit))
+         meanstore[i, :, :] = ma.average(datam, axis=0)
+
+       # construct new times list
+       smyunit = str(myunit)
+       if len(smyunit) == 4:  # YYYY
+        yyyy = int(smyunit[0:4])
+        mm = 1
+        dd = 1
+       if len(smyunit) == 6:  # YYYYMM
+        yyyy = int(smyunit[0:4])
+        mm = int(smyunit[4:6])
+        dd = 1
+       if len(smyunit) == 8:  # YYYYMMDD
+        yyyy = int(smyunit[0:4])
+        mm = int(smyunit[4:6])
+        dd = int(smyunit[6:8])
+       if len(smyunit) == 3:  # Full time range
+        # Need to set an appropriate time representing the mid-point of the entire time span
+        dt = dateList[-1] - dateList[0]
+        halfway = dateList[0] + (dt / 2)
+        yyyy = int(halfway.year)
+        mm = int(halfway.month)
+        dd = int(halfway.day)
+
+       newTimesList.append(datetime.datetime(yyyy, mm, dd, 0, 0, 0, 0))
+
+       i += 1
+
+     if not processing_required:
+        meanstorem = data
+
+     if processing_required:
+        # Create masked array (using missing data mask defined above)
+        datamask_store = np.array(datamask_store)
+        meanstorem = ma.masked_array(meanstore, datamask_store)
+
+   return meanstorem, newTimesList
+
+def calc_running_accum_from_period_accum(data):
+    '''
+     Routine to calculate running total accumulations from individual period accumulations.
+     ::
+    
+         e.g.  0,0,1,0,0,2,2,1,0,0
+            -> 0,0,1,1,1,3,5,6,6,6
+    
+     Input::
+          data: numpy array with time in the first axis
+    
+     Output::
+          running_acc: running accumulations
+    
+    '''
+    
+    
+    running_acc = np.zeros_like(data)
+    
+    if(len(data.shape) == 1):
+        running_acc[0] = data[0]
+    
+    if(len(data.shape) > 1):
+        running_acc[0, :] = data[0, :]
+    
+    for i in np.arange(data.shape[0] - 1):
+        if(len(data.shape) == 1):
+            running_acc[i + 1] = running_acc[i] + data[i + 1]
+    
+        if(len(data.shape) > 1):
+            running_acc[i + 1, :] = running_acc[i, :] + data[i + 1, :]
+    
+    return running_acc
+
+def ignore_boundaries(data, rim=10):
+    '''
+     Routine to mask the lateral boundary regions of model data to ignore them from calculations.
+     
+     Input::
+         data - a masked array of model data
+         rim - (optional) number of grid points to ignore
+    
+     Output::
+         data - data array with boundary region masked
+    
+    '''
+    
+    nx = data.shape[1]
+    ny = data.shape[0]
+    
+    rimmask = np.zeros_like(data)
+    for j in np.arange(rim):
+        rimmask[j, 0:nx - 1] = 1.0
+    
+    for j in ny - 1 - np.arange(rim):
+        rimmask[j, 0:nx - 1] = 1.0
+    
+    for i in np.arange(rim):
+        rimmask[0:ny - 1, i] = 1.0
+    
+    for i in nx - 1 - np.arange(rim):
+        rimmask[0:ny - 1, i] = 1.0
+    
+    data = ma.masked_array(data, mask=rimmask)
+    
+    return data
+
+def normalizeDatetimes(datetimes, timestep):
+    """
+    Input::
+        datetimes - list of datetime objects that need to be normalized
+        timestep - string of value ('daily' | 'monthly')
+    Output::
+        normalDatetimes - list of datetime objects that have been normalized
+    
+    Normalization Rules::
+        Daily data will be forced to an hour value of 00:00:00
+        Monthly data will be forced to the first of the month at midnight 
+    """
+    normalDatetimes = []
+    if timestep.lower() == 'monthly':
+        for inputDatetime in datetimes:
+            if inputDatetime.day != 1:
+                # Clean the inputDatetime
+                inputDatetimeString = inputDatetime.strftime('%Y%m%d')
+                normalInputDatetimeString = inputDatetimeString[:6] + '01'
+                inputDatetime = datetime.datetime.strptime(normalInputDatetimeString, '%Y%m%d')
+
+            normalDatetimes.append(inputDatetime)
+
+    elif timestep.lower() == 'daily':
+        for inputDatetime in datetimes:
+            if inputDatetime.hour != 0 or inputDatetime.minute != 0 or inputDatetime.second != 0:
+                datetimeString = inputDatetime.strftime('%Y%m%d%H%M%S')
+                normalDatetimeString = datetimeString[:8] + '000000'
+                inputDatetime = datetime.datetime.strptime(normalDatetimeString, '%Y%m%d%H%M%S')
+            
+            normalDatetimes.append(inputDatetime)
+
+
+    return normalDatetimes
+
+def getModelTimes(modelFile, timeVarName):
+    '''
+    TODO:  Do a better job handling dates here
+    Routine to convert from model times ('hours since 1900...', 'days since ...')
+    into a python datetime structure
+
+    Input::
+        modelFile - path to the model tile you want to extract the times list and modelTimeStep from
+        timeVarName - name of the time variable in the model file
+
+    Output::
+        times  - list of python datetime objects describing model data times
+        modelTimeStep - 'hourly','daily','monthly','annual'
+    '''
+
+    if os.path.exists(modelFile) == False:
+        print 'the designated file "', modelFile, '" does not exist in getModelTimes: EXIT'
+        cmnd = 'ls -l ' + modelFile
+        subprocess.call(cmnd, shell=True)
+        sys.exit()
+
+    f = netCDF4.Dataset(modelFile, mode='r')
+    xtimes = f.variables[timeVarName]
+    timeFormat = xtimes.units.encode()
+
+    # search to check if 'since' appears in units
+    try:
+        sinceLoc = re.search('since', timeFormat).end()
+
+    except AttributeError:
+        print 'Error decoding model times: time variable attributes do not contain "since"'
+        raise
+    
+    units = None
+    TIME_UNITS = ('minutes', 'hours', 'days', 'months', 'years')
+    # search for 'seconds','minutes','hours', 'days', 'months', 'years' so know units
+    for unit in TIME_UNITS:
+        if re.search(unit, timeFormat):
+            units = unit
+            break
+
+    # cut out base time (the bit following 'since')
+    base_time_string = string.lstrip(timeFormat[sinceLoc:])
+    # decode base time
+    base_time = decodeTimeFromString(base_time_string)
+    times = []
+
+    for xtime in xtimes[:]:
+        
+        # Cast time as an int
+        xtime = int(xtime)
+
+        if units == 'minutes':
+            dt = datetime.timedelta(minutes=xtime)
+            new_time = base_time + dt
+        elif units == 'hours':
+            dt = datetime.timedelta(hours=xtime)
+            new_time = base_time + dt
+        elif units == 'days':
+            dt = datetime.timedelta(days=xtime)
+            new_time = base_time + dt
+        elif units == 'months':
+            # NB. adding months in python is complicated as month length varies and hence ambiguous.
+            # Perform date arithmatic manually
+            #  Assumption: the base_date will usually be the first of the month
+            #              NB. this method will fail if the base time is on the 29th or higher day of month
+            #                      -as can't have, e.g. Feb 31st.
+            new_month = int(base_time.month + xtime % 12)
+            new_year = int(math.floor(base_time.year + xtime / 12.))
+            new_time = datetime.datetime(new_year, new_month, base_time.day, base_time.hour, base_time.second, 0)
+        elif units == 'years':
+            dt = datetime.timedelta(years=xtime)
+            new_time = base_time + dt
+
+        times.append(new_time)
+    
+    try:
+        timeStepLength = int(xtimes[1] - xtimes[0] + 1.e-12)
+        modelTimeStep = getModelTimeStep(units, timeStepLength)
+    except:
+        raise
+    
+    times = normalizeDatetimes(times, modelTimeStep)
+    
+    return times, modelTimeStep
+
+def getModelTimeStep(units, stepSize):
+    # Time units are now determined. Determine the time intervals of input data (mdlTimeStep)
+
+    if units == 'minutes':
+        if stepSize == 60:
+            modelTimeStep = 'hourly'
+        elif stepSize == 1440:
+            modelTimeStep = 'daily'
+        # 28 days through 31 days
+        elif 40320 <= stepSize <= 44640:
+            modelTimeStep = 'monthly'
+        # 365 days through 366 days 
+        elif 525600 <= stepSize <= 527040:
+            modelTimeStep = 'annual' 
+        else:
+            raise Exception('model data time step interval exceeds the max time interval (annual)', units, stepSize)
+
+    elif units == 'hours':
+        if stepSize == 1:
+            modelTimeStep = 'hourly'
+        elif stepSize == 24:
+            modelTimeStep = 'daily'
+        elif 672 <= stepSize <= 744:
+            modelTimeStep = 'monthly' 
+        elif 8760 <= stepSize <= 8784:
+            modelTimeStep = 'annual' 
+        else:
+            raise Exception('model data time step interval exceeds the max time interval (annual)', units, stepSize)
+
+    elif units == 'days':
+        if stepSize == 1:
+            modelTimeStep = 'daily'
+        elif 28 <= stepSize <= 31:
+            modelTimeStep = 'monthly'
+        elif 365 <= stepSize <= 366:
+            modelTimeStep = 'annual'
+        else:
+            raise Exception('model data time step interval exceeds the max time interval (annual)', units, stepSize)
+
+    elif units == 'months':
+        if stepSize == 1:
+            modelTimeStep = 'monthly'
+        elif stepSize == 12:
+            modelTimeStep = 'annual'
+        else:
+            raise Exception('model data time step interval exceeds the max time interval (annual)', units, stepSize)
+
+    elif units == 'years':
+        if stepSize == 1:
+            modelTimeStep = 'annual'
+        else:
+            raise Exception('model data time step interval exceeds the max time interval (annual)', units, stepSize)
+
+    else:
+        errorMessage = 'the time unit ', units, ' is not currently handled in this version.'
+        raise Exception(errorMessage)
+
+    return modelTimeStep
+
+def decodeTimeFromString(time_string):
+    '''
+     Decodes string into a python datetime object
+     *Method:* tries a bunch of different time format possibilities and hopefully one of them will hit.
+     ::
+
+       **Input:**  time_string - a string that represents a date/time
+       
+       **Output:** mytime - a python datetime object
+    '''
+
+    # This will deal with times that use decimal seconds
+    if '.' in time_string:
+        time_string = time_string.split('.')[0] + '0'
+    else:
+        pass
+
+    try:
+        mytime = time.strptime(time_string, '%Y-%m-%d %H:%M:%S')
+        mytime = datetime.datetime(*mytime[0:6])
+        return mytime
+
+    except ValueError:
+        pass
+
+    try:
+        mytime = time.strptime(time_string, '%Y/%m/%d %H:%M:%S')
+        mytime = datetime.datetime(*mytime[0:6])
+        return mytime
+
+    except ValueError:
+        pass
+
+    try:
+        mytime = time.strptime(time_string, '%Y%m%d %H:%M:%S')
+        mytime = datetime.datetime(*mytime[0:6])
+        return mytime
+
+    except ValueError:
+        pass
+
+    try:
+        mytime = time.strptime(time_string, '%Y:%m:%d %H:%M:%S')
+        mytime = datetime.datetime(*mytime[0:6])
+        return mytime
+
+    except ValueError:
+        pass
+
+    try:
+        mytime = time.strptime(time_string, '%Y%m%d%H%M%S')
+        mytime = datetime.datetime(*mytime[0:6])
+        return mytime
+
+    except ValueError:
+        pass
+
+    try:
+        mytime = time.strptime(time_string, '%Y-%m-%d %H:%M')
+        mytime = datetime.datetime(*mytime[0:6])
+        return mytime
+
+    except ValueError:
+        pass
+
+    try:
+        mytime = time.strptime(time_string, '%Y-%m-%d')
+        mytime = datetime.datetime(*mytime[0:6])
+        return mytime
+
+    except ValueError:
+        pass
+
+
+    print 'Error decoding time string: string does not match a predefined time format'
+    return 0
+
+def regrid_wrapper(regrid_choice, obsdata, obslats, obslons, wrfdata, wrflats, wrflons):
+   '''
+    Wrapper routine for regridding.
+    
+    Either regrids model to obs grid, or obs to model grid, depending on user choice
+    
+        Inputs::
+            regrid_choice - [0] = Regrid obs data onto model grid or 
+                            [1] = Regrid model data onto obs grid
+
+            obsdata,wrfdata - data arrays
+            obslats,obslons - observation lat,lon arrays
+            wrflats,wrflons - model lat,lon arrays
+   
+        Output::
+            rdata,rdata2 - regridded data
+   	        lats,lons    - latitudes and longitudes of regridded data
+   
+   '''
+
+   # Regrid obs data onto model grid
+   if(regrid_choice == '0'):
+
+      ndims = len(obsdata.shape)
+      if(ndims == 3):
+         newshape = [obsdata.shape[0], wrfdata.shape[1], wrfdata.shape[2]]
+	 nT = obsdata.shape[0]
+
+      if(ndims == 2):
+         newshape = [wrfdata.shape[0], wrfdata.shape[1]]
+	 nT = 0
+
+      rdata = wrfdata
+      lats, lons = wrflats, wrflons
+
+      # Create a new masked array with the required dimensions
+      tmp = np.zeros(newshape)
+      rdata2 = ma.MaskedArray(tmp, mask=(tmp == 0))
+      tmp = 0 # free up some memory
+
+      rdata2[:] = 0.0
+
+      if(nT > 0):
+       for t in np.arange(nT):
+         rdata2[t, :, :] = do_regrid(obsdata[t, :, :], obslats[:, :], obslons[:, :], wrflats[:, :], wrflons[:, :])
+
+      if(nT == 0):
+         rdata2[:, :] = do_regrid(obsdata[:, :], obslats[:, :], obslons[:, :], wrflats[:, :], wrflons[:, :])
+
+
+   # Regrid model data onto obs grid
+   if(regrid_choice == '1'):
+      ndims = len(wrfdata.shape)
+      if(ndims == 3):
+         newshape = [wrfdata.shape[0], obsdata.shape[1], obsdata.shape[2]]
+	 nT = obsdata.shape[0]
+
+      if(ndims == 2):
+         newshape = [obsdata.shape[0], obsdata.shape[1]]
+	 nT = 0
+
+      rdata2 = obsdata
+      lats, lons = obslats, obslons
+
+      tmp = np.zeros(newshape)
+      rdata = ma.MaskedArray(tmp, mask=(tmp == 0))
+      tmp = 0 # free up some memory
+
+      rdata[:] = 0.0
+ 
+      if(nT > 0):
+        for t in np.arange(nT):
+	 rdata[t, :, :] = do_regrid(wrfdata[t, :, :], wrflats[:, :], wrflons[:, :], obslats[:, :], obslons[:, :])
+
+      if(nT == 0):
+	rdata[:, :] = do_regrid(wrfdata[:, :], wrflats[:, :], wrflons[:, :], obslats[:, :], obslons[:, :])
+
+  
+   return rdata, rdata2, lats, lons
+
+def extract_sub_time_selection(allTimes, subTimes, data):
+    '''
+     Routine to extract a sub-selection of times from a data array.
+
+     Example::
+           Suppose a data array has 30 time values for daily data for a whole month, 
+           but you only want the data from the 5th-15th of the month.
+    
+     Input::
+           allTimes - list of datetimes describing what times the data in the data array correspond to
+           subTimes - the times you want to extract data from
+           data     - the data array
+    
+     Output::
+           subdata     - subselection of data array
+    
+    '''
+    # Create new array to store the subselection
+    subdata = np.zeros([len(subTimes), data.shape[1], data.shape[2]])
+    
+    # Loop over all Times and when it is a member of the required subselection, copy the data across
+    i = 0     # counter for allTimes
+    subi = 0  # counter for subTimes
+    for t in allTimes:
+        if(np.setmember1d(allTimes, subTimes)):
+            subdata[subi, :, :] = data[i, :, :]
+            subi += 1
+        i += 1
+    
+    return subdata
+
+def calc_average_on_new_time_unit_K(data, dateList, unit):
+    '''
+    Routine to calculate averages on longer time units than the data exists on.
+    e.g. if the data is 6-hourly, calculate daily, or monthly means.
+     
+    Input:
+        data     - data values
+        dateList - list of python datetime structures corresponding to data values
+        unit     - string describing time unit to average onto 
+                      e.g. 'monthly', 'daily', 'pentad','annual','decadal'
+    Output:
+        meanstorem - numpy masked array of data values meaned over required time period
+        newTimesList - a list of python datetime objects representing the data in the new averagin period
+                           NB. currently set to beginning of averaging period, 
+                           i.e. mean Jan 1st - Jan 31st -> represented as Jan 1st, 00Z.
+    '''
+
+    # Check if the user-selected temporal grid is valid. If not, EXIT
+    acceptable = (unit=='full')|(unit=='annual')|(unit=='monthly')|(unit=='daily')|(unit=='pentad')
+    if not acceptable:
+        print 'Error: unknown unit type selected for time averaging: EXIT'
+        return -1,-1,-1,-1
+
+    # Calculate arrays of: annual timeseries: year (2007,2007),
+    #                      monthly time series: year-month (200701,200702),
+    #                      daily timeseries:  year-month-day (20070101,20070102) 
+    #  depending on user-selected averaging period.
+
+    # Year list
+    if unit=='annual':
+        timeunits = []
+        for i in np.arange(len(dateList)):
+            timeunits.append(str(dateList[i].year))
+        timeunits = np.array(timeunits, dtype=int)
+         
+    # YearMonth format list
+    if unit=='monthly':
+        timeunits = []
+        for i in np.arange(len(dateList)):
+            timeunits.append(str(dateList[i].year) + str("%02d" % dateList[i].month))
+        timeunits = np.array(timeunits,dtype=int)
+
+    # YearMonthDay format list
+    if unit=='daily':
+        timeunits = []
+        for i in np.arange(len(dateList)):
+            timeunits.append(str(dateList[i].year) + str("%02d" % dateList[i].month) + str("%02d" % dateList[i].day))
+        timeunits = np.array(timeunits,dtype=int)
+
+    # TODO: add pentad setting using Julian days?
+
+    # Full list: a special case
+    if unit == 'full':
+        comment='Calculating means data over the entire time range: i.e., annual-mean climatology'
+        timeunits = []
+        for i in np.arange(len(dateList)):
+            timeunits.append(999)  # i.e. we just want the same value for all times.
+        timeunits = np.array(timeunits, dtype=int)
+
+    # empty list to store new times
+    newTimesList = []
+
+    # Decide whether or not you need to do any time averaging.
+    #   i.e. if data are already on required time unit then just pass data through and 
+    #        calculate and return representative datetimes.
+    processing_required = True
+    if len(timeunits)==(len(np.unique(timeunits))):
+        processing_required = False
+
+    # 1D data arrays, i.e. time series
+    if data.ndim==1:
+        # Create array to store the resulting data
+        meanstore = np.zeros(len(np.unique(timeunits)))
+  
+        # Calculate the means across each unique time unit
+        i=0
+        for myunit in np.unique(timeunits):
+            if processing_required:
+                datam=ma.masked_array(data,timeunits!=myunit)
+                meanstore[i] = ma.average(datam)
+            
+            # construct new times list
+            smyunit = str(myunit)
+            if len(smyunit)==4:  # YYYY
+                yyyy = int(myunit[0:4])
+                mm = 1
+                dd = 1
+            if len(smyunit)==6:  # YYYYMM
+                yyyy = int(smyunit[0:4])
+                mm = int(smyunit[4:6])
+                dd = 1
+            if len(smyunit)==8:  # YYYYMMDD
+                yyyy = int(smyunit[0:4])
+                mm = int(smyunit[4:6])
+                dd = int(smyunit[6:8])
+            if len(smyunit)==3:  # Full time range
+                # Need to set an appropriate time representing the mid-point of the entire time span
+                dt = dateList[-1]-dateList[0]
+                halfway = dateList[0]+(dt/2)
+                yyyy = int(halfway.year)
+                mm = int(halfway.month)
+                dd = int(halfway.day)
+
+            newTimesList.append(datetime.datetime(yyyy,mm,dd,0,0,0,0))
+            i = i+1
+
+    # 3D data arrays
+    if data.ndim==3:
+        # datamask = create_mask_using_threshold(data,threshold=0.75)
+        # Create array to store the resulting data
+        meanstore = np.zeros([len(np.unique(timeunits)),data.shape[1],data.shape[2]])
+  
+        # Calculate the means across each unique time unit
+        i=0
+        datamask_store = []
+        for myunit in np.unique(timeunits):
+            if processing_required:
+                mask = np.zeros_like(data)
+                mask[timeunits!=myunit,:,:] = 1.0
+                # Calculate missing data mask within each time unit...
+                datamask_at_this_timeunit = np.zeros_like(data)
+                datamask_at_this_timeunit[:]= create_mask_using_threshold(data[timeunits==myunit,:,:],threshold=0.75)
+                # Store results for masking later
+                datamask_store.append(datamask_at_this_timeunit[0])
+                # Calculate means for each pixel in this time unit, ignoring missing data (using masked array).
+                datam = ma.masked_array(data,np.logical_or(mask,datamask_at_this_timeunit))
+                meanstore[i,:,:] = ma.average(datam,axis=0)
+            # construct new times list
+            smyunit = str(myunit)
+            if len(smyunit)==4:  # YYYY
+                yyyy = int(smyunit[0:4])
+                mm = 1
+                dd = 1
+            if len(smyunit)==6:  # YYYYMM
+                yyyy = int(smyunit[0:4])
+                mm = int(smyunit[4:6])
+                dd = 1
+            if len(smyunit)==8:  # YYYYMMDD
+                yyyy = int(smyunit[0:4])
+                mm = int(smyunit[4:6])
+                dd = int(smyunit[6:8])
+            if len(smyunit)==3:  # Full time range
+                # Need to set an appropriate time representing the mid-point of the entire time span
+                dt = dateList[-1]-dateList[0]
+                halfway = dateList[0]+(dt/2)
+                yyyy = int(halfway.year)
+                mm = int(halfway.month)
+                dd = int(halfway.day)
+            newTimesList.append(datetime.datetime(yyyy,mm,dd,0,0,0,0))
+            i += 1
+
+        if not processing_required:
+            meanstorem = data
+
+        if processing_required:
+            # Create masked array (using missing data mask defined above)
+            datamask_store = np.array(datamask_store)
+            meanstorem = ma.masked_array(meanstore, datamask_store)
+
+    return meanstorem,newTimesList
+
+def decode_model_timesK(ifile,timeVarName,file_type):
+    #################################################################################################
+    #  Convert model times ('hours since 1900...', 'days since ...') into a python datetime structure
+    #  Input:
+    #      filelist - list of model files
+    #      timeVarName - name of the time variable in the model files
+    #  Output:
+    #      times  - list of python datetime objects describing model data times
+    #     Peter Lean February 2011
+    #################################################################################################
+    f = netCDF4.Dataset(ifile,mode='r',format=file_type)
+    xtimes = f.variables[timeVarName]
+    timeFormat = xtimes.units.encode()
+    #timeFormat = "days since 1979-01-01 00:00:00"
+    # search to check if 'since' appears in units
+    try:
+        sinceLoc = re.search('since',timeFormat).end()
+    except:
+        print 'Error decoding model times: time var attributes do not contain "since": Exit'
+        sys.exit()
+    # search for 'seconds','minutes','hours', 'days', 'months', 'years' so know units
+    # TODO:  Swap out this section for a set of if...elseif statements
+    units = ''
+    try:
+        _ = re.search('minutes',timeFormat).end()
+        units = 'minutes'
+    except:
+        pass
+    try:
+        _ = re.search('hours',timeFormat).end()
+        units = 'hours'
+    except:
+        pass
+    try:
+        _ = re.search('days',timeFormat).end()
+        units = 'days'
+    except:
+        pass
+    try:
+        _ = re.search('months',timeFormat).end()
+        units = 'months'
+    except:
+        pass
+    try:
+        _ = re.search('years',timeFormat).end()
+        units = 'years'
+    except:
+        pass
+    # cut out base time (the bit following 'since')
+    base_time_string = string.lstrip(timeFormat[sinceLoc:])
+    # decode base time
+    # 9/25/2012: datetime.timedelta has problem with the argument because xtimes is NioVariable.
+    # Soln (J. Kim): use a temp variable ttmp in the for loop, then convert it into an integer xtime.
+    base_time = decodeTimeFromString(base_time_string)
+    times=[]
+    for ttmp in xtimes[:]:
+        xtime = int(ttmp)
+        if(units=='minutes'):  
+            dt = datetime.timedelta(minutes=xtime); new_time = base_time + dt
+        if(units=='hours'):  
+            dt = datetime.timedelta(hours=xtime); new_time = base_time + dt
+        if(units=='days'):  
+            dt = datetime.timedelta(days=xtime); new_time = base_time + dt
+        if(units=='months'):   # NB. adding months in python is complicated as month length varies and hence ambigous.
+            # Perform date arithmatic manually
+            #  Assumption: the base_date will usually be the first of the month
+            #              NB. this method will fail if the base time is on the 29th or higher day of month
+            #                      -as can't have, e.g. Feb 31st.
+            new_month = int(base_time.month + xtime % 12)
+            new_year = int(math.floor(base_time.year + xtime / 12.))
+            #print type(new_year),type(new_month),type(base_time.day),type(base_time.hour),type(base_time.second)
+            new_time = datetime.datetime(new_year,new_month,base_time.day,base_time.hour,base_time.second,0)
+        if(units=='years'):
+            dt = datetime.timedelta(years=xtime); new_time = base_time + dt
+        times.append(new_time)
+    return times
+
+
+def regrid_in_time(data,dateList,unit):
+   #################################################################################################
+   # Routine to calculate averages on longer time units than the data exists on.
+   #  e.g. if the data is 6-hourly, calculate daily, or monthly means.
+   #  Input:
+   #         data     - data values
+   #         dateList - list of python datetime structures corresponding to data values
+   #         unit     - string describing time unit to average onto 
+   #                       e.g. 'monthly', 'daily', 'pentad','annual','decadal'
+   #  Output:
+   #         meanstorem - numpy masked array of data values meaned over required time period
+   #         newTimesList - a list of python datetime objects representing the data in the new averagin period
+   #                            NB. currently set to beginning of averaging period, 
+   #                            i.e. mean Jan 1st - Jan 31st -> represented as Jan 1st, 00Z.
+   # ..............................
+   #   Jinwon Kim, Sept 30, 2012
+   #   Created from calc_average_on_new_time_unit_K, Peter's original, with the modification below:
+   #   Instead of masked array used by Peter, use wh to defined data within the averaging range.
+   #################################################################################################
+
+   print '***  Begin calc_average_on_new_time_unit_KK  ***'
+   # Check if the user-selected temporal grid is valid. If not, EXIT
+   acceptable = (unit=='full')|(unit=='annual')|(unit=='monthly')|(unit=='daily')|(unit=='pentad')
+   if not acceptable:
+     print 'Error: unknown unit type selected for time averaging: EXIT'; return -1,-1,-1,-1
+
+   # Calculate time arrays of: annual (yyyy, [2007]), monthly (yyyymm, [200701,200702]), daily (yyyymmdd, [20070101,20070102]) 
+   # "%02d" is similar to i2.2 in Fortran
+   if unit=='annual':                      # YYYY
+      timeunits = []
+      for i in np.arange(len(dateList)):
+         timeunits.append(str(dateList[i].year))
+   elif unit=='monthly':                   # YYYYMM
+      timeunits = []
+      for i in np.arange(len(dateList)):
+         timeunits.append(str(dateList[i].year) + str("%02d" % dateList[i].month))
+   elif unit=='daily':                     # YYYYMMDD
+      timeunits = []
+      for i in np.arange(len(dateList)):
+         timeunits.append(str(dateList[i].year) + str("%02d" % dateList[i].month) + str("%02d" % dateList[i].day))
+   elif unit=='full':                      # Full list: a special case
+      comment='Calculating means data over the entire time range: i.e., annual-mean climatology'
+      timeunits = []
+      for i in np.arange(len(dateList)):
+         timeunits.append(999)             # i.e. we just want the same value for all times.
+   timeunits = np.array(timeunits,dtype=int)
+   print 'timeRegridOption= ',unit#'; output timeunits= ',timeunits
+   #print 'timeRegridOption= ',unit,'; output timeunits= ',timeunits
+
+   # empty list to store time levels after temporal regridding
+   newTimesList = []
+
+   # Decide whether or not you need to do any time averaging.
+   #   i.e. if data are already on required time unit then just pass data through and calculate and return representative datetimes.
+   processing_required = True
+   if len(timeunits)==(len(np.unique(timeunits))):
+        processing_required = False
+   print 'processing_required= ',processing_required,': input time steps= ',len(timeunits),': regridded output time steps = ',len(np.unique(timeunits))
+   #print 'np.unique(timeunits): ',np.unique(timeunits)
+   print 'data.ndim= ',data.ndim
+
+   if data.ndim==1:                                           # 1D data arrays, i.e. 1D time series
+      # Create array to store the temporally regridded data
+     meanstore = np.zeros(len(np.unique(timeunits)))
+      # Calculate the means across each unique time unit
+     i=0
+     for myunit in np.unique(timeunits):
+       if processing_required:
+         wh = timeunits==myunit
+         datam = data[wh]
+         meanstore[i] = ma.average(datam)
+        # construct new times list
+       smyunit = str(myunit)
+       if len(smyunit)==4:  # YYYY
+        yyyy = int(myunit[0:4])
+        mm = 1
+        dd = 1
+       if len(smyunit)==6:  # YYYYMM
+        yyyy = int(smyunit[0:4])
+        mm = int(smyunit[4:6])
+        dd = 1
+       if len(smyunit)==8:  # YYYYMMDD
+        yyyy = int(smyunit[0:4])
+        mm = int(smyunit[4:6])
+        dd = int(smyunit[6:8])
+       if len(smyunit)==3:  # Full time range
+        # Need to set an appropriate time representing the mid-point of the entire time span
+        dt = dateList[-1]-dateList[0]
+        halfway = dateList[0]+(dt/2)
+        yyyy = int(halfway.year)
+        mm = int(halfway.month)
+        dd = int(halfway.day)
+       newTimesList.append(datetime.datetime(yyyy,mm,dd,0,0,0,0))
+       i = i+1
+
+   elif data.ndim==3:                                         # 3D data arrays, i.e. 2D time series
+      # Create array to store the resulting data
+     meanstore = np.zeros([len(np.unique(timeunits)),data.shape[1],data.shape[2]])
+     # Calculate the means across each unique time unit
+     i=0
+     datamask_store = []
+     for myunit in np.unique(timeunits):
+       if processing_required:
+         wh = timeunits==myunit
+         datam = data[wh,:,:]
+         meanstore[i,:,:] = ma.average(datam,axis=0)
+        # construct new times list
+       smyunit = str(myunit)
+       if len(smyunit)==4:  # YYYY
+        yyyy = int(smyunit[0:4])
+        mm = 1
+        dd = 1
+       if len(smyunit)==6:  # YYYYMM
+        yyyy = int(smyunit[0:4])
+        mm = int(smyunit[4:6])
+        dd = 1
+       if len(smyunit)==8:  # YYYYMMDD
+        yyyy = int(smyunit[0:4])
+        mm = int(smyunit[4:6])
+        dd = int(smyunit[6:8])
+       if len(smyunit)==3:  # Full time range
+        # Need to set an appropriate time representing the mid-point of the entire time span
+        dt = dateList[-1]-dateList[0]
+        halfway = dateList[0]+(dt/2)
+        yyyy = int(halfway.year)
+        mm = int(halfway.month)
+        dd = int(halfway.day)
+       newTimesList.append(datetime.datetime(yyyy,mm,dd,0,0,0,0))
+       i += 1
+
+     if not processing_required:
+        meanstorem = data
+     elif processing_required:
+        meanstorem = meanstore
+
+   print '***  End calc_average_on_new_time_unit_KK  ***'
+   return meanstorem,newTimesList

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/rcmes/toolkit/process.pyc
----------------------------------------------------------------------
diff --git a/src/main/python/rcmes/toolkit/process.pyc b/src/main/python/rcmes/toolkit/process.pyc
new file mode 100644
index 0000000..598995f
Binary files /dev/null and b/src/main/python/rcmes/toolkit/process.pyc differ

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/rcmes/utils/.svn/all-wcprops
----------------------------------------------------------------------
diff --git a/src/main/python/rcmes/utils/.svn/all-wcprops b/src/main/python/rcmes/utils/.svn/all-wcprops
new file mode 100755
index 0000000..d1a5e75
--- /dev/null
+++ b/src/main/python/rcmes/utils/.svn/all-wcprops
@@ -0,0 +1,23 @@
+K 25
+svn:wc:ra_dav:version-url
+V 85
+/repos/asf/!svn/ver/1485875/incubator/climate/trunk/rcmet/src/main/python/rcmes/utils
+END
+fortranfile.py
+K 25
+svn:wc:ra_dav:version-url
+V 100
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/python/rcmes/utils/fortranfile.py
+END
+misc.py
+K 25
+svn:wc:ra_dav:version-url
+V 93
+/repos/asf/!svn/ver/1485875/incubator/climate/trunk/rcmet/src/main/python/rcmes/utils/misc.py
+END
+__init__.py
+K 25
+svn:wc:ra_dav:version-url
+V 97
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/python/rcmes/utils/__init__.py
+END

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/rcmes/utils/.svn/entries
----------------------------------------------------------------------
diff --git a/src/main/python/rcmes/utils/.svn/entries b/src/main/python/rcmes/utils/.svn/entries
new file mode 100755
index 0000000..4237e8b
--- /dev/null
+++ b/src/main/python/rcmes/utils/.svn/entries
@@ -0,0 +1,130 @@
+10
+
+dir
+1485921
+https://svn.apache.org/repos/asf/incubator/climate/trunk/rcmet/src/main/python/rcmes/utils
+https://svn.apache.org/repos/asf
+
+
+
+2013-05-23T22:20:38.670815Z
+1485875
+goodale
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+13f79535-47bb-0310-9956-ffa450edef68
+
+fortranfile.py
+file
+
+
+
+
+2013-05-24T10:13:49.000000Z
+441bc97dd6c9c1b1427f2d26551657b3
+2012-08-20T14:52:40.177916Z
+1473896
+cgoodale
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+9124
+
+misc.py
+file
+
+
+
+
+2013-05-24T10:13:49.000000Z
+46b5487ec6ea324f2510e6c455176907
+2013-05-23T22:20:38.670815Z
+1485875
+goodale
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+48435
+
+__init__.py
+file
+
+
+
+
+2013-05-24T10:13:49.000000Z
+4e1f33b6edbd359577a08d36213daaa1
+2012-08-16T14:44:27.851593Z
+1473888
+cgoodale
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+91
+

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/rcmes/utils/.svn/prop-base/__init__.py.svn-base
----------------------------------------------------------------------
diff --git a/src/main/python/rcmes/utils/.svn/prop-base/__init__.py.svn-base b/src/main/python/rcmes/utils/.svn/prop-base/__init__.py.svn-base
new file mode 100755
index 0000000..614166f
--- /dev/null
+++ b/src/main/python/rcmes/utils/.svn/prop-base/__init__.py.svn-base
@@ -0,0 +1,5 @@
+K 12
+svn:keywords
+V 11
+Id Revision
+END

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/rcmes/utils/.svn/text-base/__init__.py.svn-base
----------------------------------------------------------------------
diff --git a/src/main/python/rcmes/utils/.svn/text-base/__init__.py.svn-base b/src/main/python/rcmes/utils/.svn/text-base/__init__.py.svn-base
new file mode 100755
index 0000000..fbe6d4e
--- /dev/null
+++ b/src/main/python/rcmes/utils/.svn/text-base/__init__.py.svn-base
@@ -0,0 +1,2 @@
+"""Collection of modules that provide functionality across all of the RCMES
+sub-packages"""
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/rcmes/utils/.svn/text-base/fortranfile.py.svn-base
----------------------------------------------------------------------
diff --git a/src/main/python/rcmes/utils/.svn/text-base/fortranfile.py.svn-base b/src/main/python/rcmes/utils/.svn/text-base/fortranfile.py.svn-base
new file mode 100755
index 0000000..7ff7850
--- /dev/null
+++ b/src/main/python/rcmes/utils/.svn/text-base/fortranfile.py.svn-base
@@ -0,0 +1,274 @@
+# Copyright 2008, 2009 Neil Martinsen-Burrell
+
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+# THE SOFTWARE.
+
+
+"""
+Defines a file-derived class to read/write Fortran unformatted files.
+
+The assumption is that a Fortran unformatted file is being written by
+the Fortran runtime as a sequence of records.  Each record consists of
+an integer (of the default size [usually 32 or 64 bits]) giving the
+length of the following data in bytes, then the data itself, then the
+same integer as before.
+
+Examples
+--------
+
+To use the default endian and size settings, one can just do::
+
+    >>> f = FortranFile('filename')
+    >>> x = f.readReals()
+
+One can read arrays with varying precisions::
+
+    >>> f = FortranFile('filename')
+    >>> x = f.readInts('h')
+    >>> y = f.readInts('q')
+    >>> z = f.readReals('f')
+
+Where the format codes are those used by Python's struct module.
+
+One can change the default endian-ness and header precision::
+
+    >>> f = FortranFile('filename', endian='>', header_prec='l')
+    
+for a file with little-endian data whose record headers are long
+integers.
+"""
+
+__docformat__ = "restructuredtext en"
+
+import struct
+import numpy
+
+class FortranFile(file):
+
+    """File with methods for dealing with fortran unformatted data files"""
+
+    def _get_header_length(self):
+        return struct.calcsize(self._header_prec)
+    _header_length = property(fget=_get_header_length)
+
+    def _set_endian(self,c):
+        """
+        Set endian to big (c='>') or little (c='<') or native (c='@')
+
+        Parameters:
+          `c` : string
+            The endian-ness to use when reading from this file.
+        """
+        if c in '<>@=':
+            self._endian = c
+        else:
+            raise ValueError('Cannot set endian-ness')
+    def _get_endian(self):
+        return self._endian
+    ENDIAN = property(fset=_set_endian,
+                      fget=_get_endian,
+                      doc="Possible endian values are '<', '>', '@', '='"
+                     )
+
+    def _set_header_prec(self, prec):
+        if prec in 'hilq':
+            self._header_prec = prec
+        else:
+            raise ValueError('Cannot set header precision')
+    def _get_header_prec(self):
+        return self._header_prec
+    HEADER_PREC = property(fset=_set_header_prec,
+                           fget=_get_header_prec,
+                           doc="Possible header precisions are 'h', 'i', 'l', 'q'"
+                          )
+
+    def __init__(self, fname, endian='@', header_prec='i', *args, **kwargs):
+        """Open a Fortran unformatted file for writing.
+        
+        Parameters
+        ----------
+        endian : character, optional
+            Specify the endian-ness of the file.  Possible values are
+            '>', '<', '@' and '='.  See the documentation of Python's
+            struct module for their meanings.  The deafult is '@' (native
+            byte order)
+        header_prec : character, optional
+            Specify the precision used for the record headers.  Possible
+            values are 'h', 'i', 'l' and 'q' with their meanings from
+            Python's struct module.  The default is 'i' (the system's
+            default integer).
+
+        """
+        file.__init__(self, fname, *args, **kwargs)
+        self.ENDIAN = endian
+        self.HEADER_PREC = header_prec
+
+    def _read_exactly(self, num_bytes):
+        """Read in exactly num_bytes, raising an error if it can't be done."""
+        data = ''
+        while True:
+            l = len(data)
+            if l == num_bytes:
+                return data
+            else:
+                read_data = self.read(num_bytes - l)
+            if read_data == '':
+                raise IOError('Could not read enough data.'
+                              '  Wanted %d bytes, got %d.' % (num_bytes, l))
+            data += read_data
+
+    def _read_check(self):
+        return struct.unpack(self.ENDIAN+self.HEADER_PREC,
+                             self._read_exactly(self._header_length)
+                            )[0]
+
+    def _write_check(self, number_of_bytes):
+        """Write the header for the given number of bytes"""
+        self.write(struct.pack(self.ENDIAN+self.HEADER_PREC,
+                               number_of_bytes))
+
+    def readRecord(self):
+        """Read a single fortran record"""
+        l = self._read_check()
+        data_str = self._read_exactly(l)
+        check_size = self._read_check()
+        if check_size != l:
+            raise IOError('Error reading record from data file')
+        return data_str
+
+    def writeRecord(self,s):
+        """Write a record with the given bytes.
+
+        Parameters
+        
+            s : the string to write
+
+        """
+        length_bytes = len(s)
+        self._write_check(length_bytes)
+        self.write(s)
+        self._write_check(length_bytes)
+
+    def readString(self):
+        """Read a string."""
+        return self.readRecord()
+
+    def writeString(self,s):
+        """Write a string
+
+        Parameters
+        
+            s : the string to write
+        
+        """
+        self.writeRecord(s)
+
+    _real_precisions = 'df'
+
+    def readReals(self, prec='f'):
+        """
+        Read in an array of real numbers.
+        
+        Parameters
+        
+            prec : character, optional
+            
+            Specify the precision of the array using character codes from
+            Python's struct module.  Possible values are 'd' and 'f'.
+            
+        """
+        
+        _numpy_precisions = {'d': numpy.float64,
+                             'f': numpy.float32
+                            }
+
+        if prec not in self._real_precisions:
+            raise ValueError('Not an appropriate precision')
+            
+        data_str = self.readRecord()
+        num = len(data_str)/struct.calcsize(prec)
+        numbers =struct.unpack(self.ENDIAN+str(num)+prec,data_str) 
+        return numpy.array(numbers, dtype=_numpy_precisions[prec])
+
+    def writeReals(self, reals, prec='f'):
+        """
+        Write an array of floats in given precision
+
+        Parameters
+        
+        reals : array
+            Data to write
+        prec` : string
+            Character code for the precision to use in writing
+        
+        """
+        if prec not in self._real_precisions:
+            raise ValueError('Not an appropriate precision')
+        
+        # Don't use writeRecord to avoid having to form a
+        # string as large as the array of numbers
+        length_bytes = len(reals)*struct.calcsize(prec)
+        self._write_check(length_bytes)
+        _fmt = self.ENDIAN + prec
+        for r in reals:
+            self.write(struct.pack(_fmt,r))
+        self._write_check(length_bytes)
+    
+    _int_precisions = 'hilq'
+
+    def readInts(self, prec='i'):
+        """
+        Read an array of integers.
+        
+        Parameters
+        
+            prec : character, optional
+                Specify the precision of the data to be read using 
+                character codes from Python's struct module.  Possible
+                values are 'h', 'i', 'l' and 'q'
+            
+        """
+        if prec not in self._int_precisions:
+            raise ValueError('Not an appropriate precision')
+            
+        data_str = self.readRecord()
+        num = len(data_str)/struct.calcsize(prec)
+        return numpy.array(struct.unpack(self.ENDIAN+str(num)+prec,data_str))
+
+    def writeInts(self, ints, prec='i'):
+        """
+        Write an array of integers in given precision
+
+        Parameters
+        
+            reals : array
+                Data to write
+            prec : string
+                Character code for the precision to use in writing
+        """
+        if prec not in self._int_precisions:
+            raise ValueError('Not an appropriate precision')
+        
+        # Don't use writeRecord to avoid having to form a
+        # string as large as the array of numbers
+        length_bytes = len(ints)*struct.calcsize(prec)
+        self._write_check(length_bytes)
+        _fmt = self.ENDIAN + prec
+        for item in ints:
+            self.write(struct.pack(_fmt,item))
+        self._write_check(length_bytes)


[16/51] [abbrv] [partial] Adding Jinwon's custom RCMET

Posted by jo...@apache.org.
http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/app/lib/angular/angular.js
----------------------------------------------------------------------
diff --git a/src/main/ui/app/lib/angular/angular.js b/src/main/ui/app/lib/angular/angular.js
new file mode 100755
index 0000000..68b33c7
--- /dev/null
+++ b/src/main/ui/app/lib/angular/angular.js
@@ -0,0 +1,14733 @@
+/**
+ * @license AngularJS v1.0.5
+ * (c) 2010-2012 Google, Inc. http://angularjs.org
+ * License: MIT
+ */
+(function(window, document, undefined) {
+'use strict';
+
+////////////////////////////////////
+
+/**
+ * @ngdoc function
+ * @name angular.lowercase
+ * @function
+ *
+ * @description Converts the specified string to lowercase.
+ * @param {string} string String to be converted to lowercase.
+ * @returns {string} Lowercased string.
+ */
+var lowercase = function(string){return isString(string) ? string.toLowerCase() : string;};
+
+
+/**
+ * @ngdoc function
+ * @name angular.uppercase
+ * @function
+ *
+ * @description Converts the specified string to uppercase.
+ * @param {string} string String to be converted to uppercase.
+ * @returns {string} Uppercased string.
+ */
+var uppercase = function(string){return isString(string) ? string.toUpperCase() : string;};
+
+
+var manualLowercase = function(s) {
+  return isString(s)
+      ? s.replace(/[A-Z]/g, function(ch) {return fromCharCode(ch.charCodeAt(0) | 32);})
+      : s;
+};
+var manualUppercase = function(s) {
+  return isString(s)
+      ? s.replace(/[a-z]/g, function(ch) {return fromCharCode(ch.charCodeAt(0) & ~32);})
+      : s;
+};
+
+
+// String#toLowerCase and String#toUpperCase don't produce correct results in browsers with Turkish
+// locale, for this reason we need to detect this case and redefine lowercase/uppercase methods
+// with correct but slower alternatives.
+if ('i' !== 'I'.toLowerCase()) {
+  lowercase = manualLowercase;
+  uppercase = manualUppercase;
+}
+
+function fromCharCode(code) {return String.fromCharCode(code);}
+
+
+var /** holds major version number for IE or NaN for real browsers */
+    msie              = int((/msie (\d+)/.exec(lowercase(navigator.userAgent)) || [])[1]),
+    jqLite,           // delay binding since jQuery could be loaded after us.
+    jQuery,           // delay binding
+    slice             = [].slice,
+    push              = [].push,
+    toString          = Object.prototype.toString,
+
+    /** @name angular */
+    angular           = window.angular || (window.angular = {}),
+    angularModule,
+    nodeName_,
+    uid               = ['0', '0', '0'];
+
+/**
+ * @ngdoc function
+ * @name angular.forEach
+ * @function
+ *
+ * @description
+ * Invokes the `iterator` function once for each item in `obj` collection, which can be either an
+ * object or an array. The `iterator` function is invoked with `iterator(value, key)`, where `value`
+ * is the value of an object property or an array element and `key` is the object property key or
+ * array element index. Specifying a `context` for the function is optional.
+ *
+ * Note: this function was previously known as `angular.foreach`.
+ *
+   <pre>
+     var values = {name: 'misko', gender: 'male'};
+     var log = [];
+     angular.forEach(values, function(value, key){
+       this.push(key + ': ' + value);
+     }, log);
+     expect(log).toEqual(['name: misko', 'gender:male']);
+   </pre>
+ *
+ * @param {Object|Array} obj Object to iterate over.
+ * @param {Function} iterator Iterator function.
+ * @param {Object=} context Object to become context (`this`) for the iterator function.
+ * @returns {Object|Array} Reference to `obj`.
+ */
+
+
+/**
+ * @private
+ * @param {*} obj
+ * @return {boolean} Returns true if `obj` is an array or array-like object (NodeList, Arguments, ...)
+ */
+function isArrayLike(obj) {
+  if (!obj || (typeof obj.length !== 'number')) return false;
+
+  // We have on object which has length property. Should we treat it as array?
+  if (typeof obj.hasOwnProperty != 'function' &&
+      typeof obj.constructor != 'function') {
+    // This is here for IE8: it is a bogus object treat it as array;
+    return true;
+  } else  {
+    return obj instanceof JQLite ||                      // JQLite
+           (jQuery && obj instanceof jQuery) ||          // jQuery
+           toString.call(obj) !== '[object Object]' ||   // some browser native object
+           typeof obj.callee === 'function';              // arguments (on IE8 looks like regular obj)
+  }
+}
+
+
+function forEach(obj, iterator, context) {
+  var key;
+  if (obj) {
+    if (isFunction(obj)){
+      for (key in obj) {
+        if (key != 'prototype' && key != 'length' && key != 'name' && obj.hasOwnProperty(key)) {
+          iterator.call(context, obj[key], key);
+        }
+      }
+    } else if (obj.forEach && obj.forEach !== forEach) {
+      obj.forEach(iterator, context);
+    } else if (isArrayLike(obj)) {
+      for (key = 0; key < obj.length; key++)
+        iterator.call(context, obj[key], key);
+    } else {
+      for (key in obj) {
+        if (obj.hasOwnProperty(key)) {
+          iterator.call(context, obj[key], key);
+        }
+      }
+    }
+  }
+  return obj;
+}
+
+function sortedKeys(obj) {
+  var keys = [];
+  for (var key in obj) {
+    if (obj.hasOwnProperty(key)) {
+      keys.push(key);
+    }
+  }
+  return keys.sort();
+}
+
+function forEachSorted(obj, iterator, context) {
+  var keys = sortedKeys(obj);
+  for ( var i = 0; i < keys.length; i++) {
+    iterator.call(context, obj[keys[i]], keys[i]);
+  }
+  return keys;
+}
+
+
+/**
+ * when using forEach the params are value, key, but it is often useful to have key, value.
+ * @param {function(string, *)} iteratorFn
+ * @returns {function(*, string)}
+ */
+function reverseParams(iteratorFn) {
+  return function(value, key) { iteratorFn(key, value) };
+}
+
+/**
+ * A consistent way of creating unique IDs in angular. The ID is a sequence of alpha numeric
+ * characters such as '012ABC'. The reason why we are not using simply a number counter is that
+ * the number string gets longer over time, and it can also overflow, where as the nextId
+ * will grow much slower, it is a string, and it will never overflow.
+ *
+ * @returns an unique alpha-numeric string
+ */
+function nextUid() {
+  var index = uid.length;
+  var digit;
+
+  while(index) {
+    index--;
+    digit = uid[index].charCodeAt(0);
+    if (digit == 57 /*'9'*/) {
+      uid[index] = 'A';
+      return uid.join('');
+    }
+    if (digit == 90  /*'Z'*/) {
+      uid[index] = '0';
+    } else {
+      uid[index] = String.fromCharCode(digit + 1);
+      return uid.join('');
+    }
+  }
+  uid.unshift('0');
+  return uid.join('');
+}
+
+/**
+ * @ngdoc function
+ * @name angular.extend
+ * @function
+ *
+ * @description
+ * Extends the destination object `dst` by copying all of the properties from the `src` object(s)
+ * to `dst`. You can specify multiple `src` objects.
+ *
+ * @param {Object} dst Destination object.
+ * @param {...Object} src Source object(s).
+ */
+function extend(dst) {
+  forEach(arguments, function(obj){
+    if (obj !== dst) {
+      forEach(obj, function(value, key){
+        dst[key] = value;
+      });
+    }
+  });
+  return dst;
+}
+
+function int(str) {
+  return parseInt(str, 10);
+}
+
+
+function inherit(parent, extra) {
+  return extend(new (extend(function() {}, {prototype:parent}))(), extra);
+}
+
+
+/**
+ * @ngdoc function
+ * @name angular.noop
+ * @function
+ *
+ * @description
+ * A function that performs no operations. This function can be useful when writing code in the
+ * functional style.
+   <pre>
+     function foo(callback) {
+       var result = calculateResult();
+       (callback || angular.noop)(result);
+     }
+   </pre>
+ */
+function noop() {}
+noop.$inject = [];
+
+
+/**
+ * @ngdoc function
+ * @name angular.identity
+ * @function
+ *
+ * @description
+ * A function that returns its first argument. This function is useful when writing code in the
+ * functional style.
+ *
+   <pre>
+     function transformer(transformationFn, value) {
+       return (transformationFn || identity)(value);
+     };
+   </pre>
+ */
+function identity($) {return $;}
+identity.$inject = [];
+
+
+function valueFn(value) {return function() {return value;};}
+
+/**
+ * @ngdoc function
+ * @name angular.isUndefined
+ * @function
+ *
+ * @description
+ * Determines if a reference is undefined.
+ *
+ * @param {*} value Reference to check.
+ * @returns {boolean} True if `value` is undefined.
+ */
+function isUndefined(value){return typeof value == 'undefined';}
+
+
+/**
+ * @ngdoc function
+ * @name angular.isDefined
+ * @function
+ *
+ * @description
+ * Determines if a reference is defined.
+ *
+ * @param {*} value Reference to check.
+ * @returns {boolean} True if `value` is defined.
+ */
+function isDefined(value){return typeof value != 'undefined';}
+
+
+/**
+ * @ngdoc function
+ * @name angular.isObject
+ * @function
+ *
+ * @description
+ * Determines if a reference is an `Object`. Unlike `typeof` in JavaScript, `null`s are not
+ * considered to be objects.
+ *
+ * @param {*} value Reference to check.
+ * @returns {boolean} True if `value` is an `Object` but not `null`.
+ */
+function isObject(value){return value != null && typeof value == 'object';}
+
+
+/**
+ * @ngdoc function
+ * @name angular.isString
+ * @function
+ *
+ * @description
+ * Determines if a reference is a `String`.
+ *
+ * @param {*} value Reference to check.
+ * @returns {boolean} True if `value` is a `String`.
+ */
+function isString(value){return typeof value == 'string';}
+
+
+/**
+ * @ngdoc function
+ * @name angular.isNumber
+ * @function
+ *
+ * @description
+ * Determines if a reference is a `Number`.
+ *
+ * @param {*} value Reference to check.
+ * @returns {boolean} True if `value` is a `Number`.
+ */
+function isNumber(value){return typeof value == 'number';}
+
+
+/**
+ * @ngdoc function
+ * @name angular.isDate
+ * @function
+ *
+ * @description
+ * Determines if a value is a date.
+ *
+ * @param {*} value Reference to check.
+ * @returns {boolean} True if `value` is a `Date`.
+ */
+function isDate(value){
+  return toString.apply(value) == '[object Date]';
+}
+
+
+/**
+ * @ngdoc function
+ * @name angular.isArray
+ * @function
+ *
+ * @description
+ * Determines if a reference is an `Array`.
+ *
+ * @param {*} value Reference to check.
+ * @returns {boolean} True if `value` is an `Array`.
+ */
+function isArray(value) {
+  return toString.apply(value) == '[object Array]';
+}
+
+
+/**
+ * @ngdoc function
+ * @name angular.isFunction
+ * @function
+ *
+ * @description
+ * Determines if a reference is a `Function`.
+ *
+ * @param {*} value Reference to check.
+ * @returns {boolean} True if `value` is a `Function`.
+ */
+function isFunction(value){return typeof value == 'function';}
+
+
+/**
+ * Checks if `obj` is a window object.
+ *
+ * @private
+ * @param {*} obj Object to check
+ * @returns {boolean} True if `obj` is a window obj.
+ */
+function isWindow(obj) {
+  return obj && obj.document && obj.location && obj.alert && obj.setInterval;
+}
+
+
+function isScope(obj) {
+  return obj && obj.$evalAsync && obj.$watch;
+}
+
+
+function isFile(obj) {
+  return toString.apply(obj) === '[object File]';
+}
+
+
+function isBoolean(value) {
+  return typeof value == 'boolean';
+}
+
+
+function trim(value) {
+  return isString(value) ? value.replace(/^\s*/, '').replace(/\s*$/, '') : value;
+}
+
+/**
+ * @ngdoc function
+ * @name angular.isElement
+ * @function
+ *
+ * @description
+ * Determines if a reference is a DOM element (or wrapped jQuery element).
+ *
+ * @param {*} value Reference to check.
+ * @returns {boolean} True if `value` is a DOM element (or wrapped jQuery element).
+ */
+function isElement(node) {
+  return node &&
+    (node.nodeName  // we are a direct element
+    || (node.bind && node.find));  // we have a bind and find method part of jQuery API
+}
+
+/**
+ * @param str 'key1,key2,...'
+ * @returns {object} in the form of {key1:true, key2:true, ...}
+ */
+function makeMap(str){
+  var obj = {}, items = str.split(","), i;
+  for ( i = 0; i < items.length; i++ )
+    obj[ items[i] ] = true;
+  return obj;
+}
+
+
+if (msie < 9) {
+  nodeName_ = function(element) {
+    element = element.nodeName ? element : element[0];
+    return (element.scopeName && element.scopeName != 'HTML')
+      ? uppercase(element.scopeName + ':' + element.nodeName) : element.nodeName;
+  };
+} else {
+  nodeName_ = function(element) {
+    return element.nodeName ? element.nodeName : element[0].nodeName;
+  };
+}
+
+
+function map(obj, iterator, context) {
+  var results = [];
+  forEach(obj, function(value, index, list) {
+    results.push(iterator.call(context, value, index, list));
+  });
+  return results;
+}
+
+
+/**
+ * @description
+ * Determines the number of elements in an array, the number of properties an object has, or
+ * the length of a string.
+ *
+ * Note: This function is used to augment the Object type in Angular expressions. See
+ * {@link angular.Object} for more information about Angular arrays.
+ *
+ * @param {Object|Array|string} obj Object, array, or string to inspect.
+ * @param {boolean} [ownPropsOnly=false] Count only "own" properties in an object
+ * @returns {number} The size of `obj` or `0` if `obj` is neither an object nor an array.
+ */
+function size(obj, ownPropsOnly) {
+  var size = 0, key;
+
+  if (isArray(obj) || isString(obj)) {
+    return obj.length;
+  } else if (isObject(obj)){
+    for (key in obj)
+      if (!ownPropsOnly || obj.hasOwnProperty(key))
+        size++;
+  }
+
+  return size;
+}
+
+
+function includes(array, obj) {
+  return indexOf(array, obj) != -1;
+}
+
+function indexOf(array, obj) {
+  if (array.indexOf) return array.indexOf(obj);
+
+  for ( var i = 0; i < array.length; i++) {
+    if (obj === array[i]) return i;
+  }
+  return -1;
+}
+
+function arrayRemove(array, value) {
+  var index = indexOf(array, value);
+  if (index >=0)
+    array.splice(index, 1);
+  return value;
+}
+
+function isLeafNode (node) {
+  if (node) {
+    switch (node.nodeName) {
+    case "OPTION":
+    case "PRE":
+    case "TITLE":
+      return true;
+    }
+  }
+  return false;
+}
+
+/**
+ * @ngdoc function
+ * @name angular.copy
+ * @function
+ *
+ * @description
+ * Creates a deep copy of `source`, which should be an object or an array.
+ *
+ * * If no destination is supplied, a copy of the object or array is created.
+ * * If a destination is provided, all of its elements (for array) or properties (for objects)
+ *   are deleted and then all elements/properties from the source are copied to it.
+ * * If  `source` is not an object or array, `source` is returned.
+ *
+ * Note: this function is used to augment the Object type in Angular expressions. See
+ * {@link ng.$filter} for more information about Angular arrays.
+ *
+ * @param {*} source The source that will be used to make a copy.
+ *                   Can be any type, including primitives, `null`, and `undefined`.
+ * @param {(Object|Array)=} destination Destination into which the source is copied. If
+ *     provided, must be of the same type as `source`.
+ * @returns {*} The copy or updated `destination`, if `destination` was specified.
+ */
+function copy(source, destination){
+  if (isWindow(source) || isScope(source)) throw Error("Can't copy Window or Scope");
+  if (!destination) {
+    destination = source;
+    if (source) {
+      if (isArray(source)) {
+        destination = copy(source, []);
+      } else if (isDate(source)) {
+        destination = new Date(source.getTime());
+      } else if (isObject(source)) {
+        destination = copy(source, {});
+      }
+    }
+  } else {
+    if (source === destination) throw Error("Can't copy equivalent objects or arrays");
+    if (isArray(source)) {
+      destination.length = 0;
+      for ( var i = 0; i < source.length; i++) {
+        destination.push(copy(source[i]));
+      }
+    } else {
+      forEach(destination, function(value, key){
+        delete destination[key];
+      });
+      for ( var key in source) {
+        destination[key] = copy(source[key]);
+      }
+    }
+  }
+  return destination;
+}
+
+/**
+ * Create a shallow copy of an object
+ */
+function shallowCopy(src, dst) {
+  dst = dst || {};
+
+  for(var key in src) {
+    if (src.hasOwnProperty(key) && key.substr(0, 2) !== '$$') {
+      dst[key] = src[key];
+    }
+  }
+
+  return dst;
+}
+
+
+/**
+ * @ngdoc function
+ * @name angular.equals
+ * @function
+ *
+ * @description
+ * Determines if two objects or two values are equivalent. Supports value types, arrays and
+ * objects.
+ *
+ * Two objects or values are considered equivalent if at least one of the following is true:
+ *
+ * * Both objects or values pass `===` comparison.
+ * * Both objects or values are of the same type and all of their properties pass `===` comparison.
+ * * Both values are NaN. (In JavasScript, NaN == NaN => false. But we consider two NaN as equal)
+ *
+ * During a property comparision, properties of `function` type and properties with names
+ * that begin with `$` are ignored.
+ *
+ * Scope and DOMWindow objects are being compared only be identify (`===`).
+ *
+ * @param {*} o1 Object or value to compare.
+ * @param {*} o2 Object or value to compare.
+ * @returns {boolean} True if arguments are equal.
+ */
+function equals(o1, o2) {
+  if (o1 === o2) return true;
+  if (o1 === null || o2 === null) return false;
+  if (o1 !== o1 && o2 !== o2) return true; // NaN === NaN
+  var t1 = typeof o1, t2 = typeof o2, length, key, keySet;
+  if (t1 == t2) {
+    if (t1 == 'object') {
+      if (isArray(o1)) {
+        if ((length = o1.length) == o2.length) {
+          for(key=0; key<length; key++) {
+            if (!equals(o1[key], o2[key])) return false;
+          }
+          return true;
+        }
+      } else if (isDate(o1)) {
+        return isDate(o2) && o1.getTime() == o2.getTime();
+      } else {
+        if (isScope(o1) || isScope(o2) || isWindow(o1) || isWindow(o2)) return false;
+        keySet = {};
+        for(key in o1) {
+          if (key.charAt(0) === '$' || isFunction(o1[key])) continue;
+          if (!equals(o1[key], o2[key])) return false;
+          keySet[key] = true;
+        }
+        for(key in o2) {
+          if (!keySet[key] &&
+              key.charAt(0) !== '$' &&
+              o2[key] !== undefined &&
+              !isFunction(o2[key])) return false;
+        }
+        return true;
+      }
+    }
+  }
+  return false;
+}
+
+
+function concat(array1, array2, index) {
+  return array1.concat(slice.call(array2, index));
+}
+
+function sliceArgs(args, startIndex) {
+  return slice.call(args, startIndex || 0);
+}
+
+
+/**
+ * @ngdoc function
+ * @name angular.bind
+ * @function
+ *
+ * @description
+ * Returns a function which calls function `fn` bound to `self` (`self` becomes the `this` for
+ * `fn`). You can supply optional `args` that are are prebound to the function. This feature is also
+ * known as [function currying](http://en.wikipedia.org/wiki/Currying).
+ *
+ * @param {Object} self Context which `fn` should be evaluated in.
+ * @param {function()} fn Function to be bound.
+ * @param {...*} args Optional arguments to be prebound to the `fn` function call.
+ * @returns {function()} Function that wraps the `fn` with all the specified bindings.
+ */
+function bind(self, fn) {
+  var curryArgs = arguments.length > 2 ? sliceArgs(arguments, 2) : [];
+  if (isFunction(fn) && !(fn instanceof RegExp)) {
+    return curryArgs.length
+      ? function() {
+          return arguments.length
+            ? fn.apply(self, curryArgs.concat(slice.call(arguments, 0)))
+            : fn.apply(self, curryArgs);
+        }
+      : function() {
+          return arguments.length
+            ? fn.apply(self, arguments)
+            : fn.call(self);
+        };
+  } else {
+    // in IE, native methods are not functions so they cannot be bound (note: they don't need to be)
+    return fn;
+  }
+}
+
+
+function toJsonReplacer(key, value) {
+  var val = value;
+
+  if (/^\$+/.test(key)) {
+    val = undefined;
+  } else if (isWindow(value)) {
+    val = '$WINDOW';
+  } else if (value &&  document === value) {
+    val = '$DOCUMENT';
+  } else if (isScope(value)) {
+    val = '$SCOPE';
+  }
+
+  return val;
+}
+
+
+/**
+ * @ngdoc function
+ * @name angular.toJson
+ * @function
+ *
+ * @description
+ * Serializes input into a JSON-formatted string.
+ *
+ * @param {Object|Array|Date|string|number} obj Input to be serialized into JSON.
+ * @param {boolean=} pretty If set to true, the JSON output will contain newlines and whitespace.
+ * @returns {string} Jsonified string representing `obj`.
+ */
+function toJson(obj, pretty) {
+  return JSON.stringify(obj, toJsonReplacer, pretty ? '  ' : null);
+}
+
+
+/**
+ * @ngdoc function
+ * @name angular.fromJson
+ * @function
+ *
+ * @description
+ * Deserializes a JSON string.
+ *
+ * @param {string} json JSON string to deserialize.
+ * @returns {Object|Array|Date|string|number} Deserialized thingy.
+ */
+function fromJson(json) {
+  return isString(json)
+      ? JSON.parse(json)
+      : json;
+}
+
+
+function toBoolean(value) {
+  if (value && value.length !== 0) {
+    var v = lowercase("" + value);
+    value = !(v == 'f' || v == '0' || v == 'false' || v == 'no' || v == 'n' || v == '[]');
+  } else {
+    value = false;
+  }
+  return value;
+}
+
+/**
+ * @returns {string} Returns the string representation of the element.
+ */
+function startingTag(element) {
+  element = jqLite(element).clone();
+  try {
+    // turns out IE does not let you set .html() on elements which
+    // are not allowed to have children. So we just ignore it.
+    element.html('');
+  } catch(e) {}
+  // As Per DOM Standards
+  var TEXT_NODE = 3;
+  var elemHtml = jqLite('<div>').append(element).html();
+  try {
+    return element[0].nodeType === TEXT_NODE ? lowercase(elemHtml) :
+        elemHtml.
+          match(/^(<[^>]+>)/)[1].
+          replace(/^<([\w\-]+)/, function(match, nodeName) { return '<' + lowercase(nodeName); });
+  } catch(e) {
+    return lowercase(elemHtml);
+  }
+
+}
+
+
+/////////////////////////////////////////////////
+
+/**
+ * Parses an escaped url query string into key-value pairs.
+ * @returns Object.<(string|boolean)>
+ */
+function parseKeyValue(/**string*/keyValue) {
+  var obj = {}, key_value, key;
+  forEach((keyValue || "").split('&'), function(keyValue){
+    if (keyValue) {
+      key_value = keyValue.split('=');
+      key = decodeURIComponent(key_value[0]);
+      obj[key] = isDefined(key_value[1]) ? decodeURIComponent(key_value[1]) : true;
+    }
+  });
+  return obj;
+}
+
+function toKeyValue(obj) {
+  var parts = [];
+  forEach(obj, function(value, key) {
+    parts.push(encodeUriQuery(key, true) + (value === true ? '' : '=' + encodeUriQuery(value, true)));
+  });
+  return parts.length ? parts.join('&') : '';
+}
+
+
+/**
+ * We need our custom method because encodeURIComponent is too agressive and doesn't follow
+ * http://www.ietf.org/rfc/rfc3986.txt with regards to the character set (pchar) allowed in path
+ * segments:
+ *    segment       = *pchar
+ *    pchar         = unreserved / pct-encoded / sub-delims / ":" / "@"
+ *    pct-encoded   = "%" HEXDIG HEXDIG
+ *    unreserved    = ALPHA / DIGIT / "-" / "." / "_" / "~"
+ *    sub-delims    = "!" / "$" / "&" / "'" / "(" / ")"
+ *                     / "*" / "+" / "," / ";" / "="
+ */
+function encodeUriSegment(val) {
+  return encodeUriQuery(val, true).
+             replace(/%26/gi, '&').
+             replace(/%3D/gi, '=').
+             replace(/%2B/gi, '+');
+}
+
+
+/**
+ * This method is intended for encoding *key* or *value* parts of query component. We need a custom
+ * method becuase encodeURIComponent is too agressive and encodes stuff that doesn't have to be
+ * encoded per http://tools.ietf.org/html/rfc3986:
+ *    query       = *( pchar / "/" / "?" )
+ *    pchar         = unreserved / pct-encoded / sub-delims / ":" / "@"
+ *    unreserved    = ALPHA / DIGIT / "-" / "." / "_" / "~"
+ *    pct-encoded   = "%" HEXDIG HEXDIG
+ *    sub-delims    = "!" / "$" / "&" / "'" / "(" / ")"
+ *                     / "*" / "+" / "," / ";" / "="
+ */
+function encodeUriQuery(val, pctEncodeSpaces) {
+  return encodeURIComponent(val).
+             replace(/%40/gi, '@').
+             replace(/%3A/gi, ':').
+             replace(/%24/g, '$').
+             replace(/%2C/gi, ',').
+             replace((pctEncodeSpaces ? null : /%20/g), '+');
+}
+
+
+/**
+ * @ngdoc directive
+ * @name ng.directive:ngApp
+ *
+ * @element ANY
+ * @param {angular.Module} ngApp an optional application
+ *   {@link angular.module module} name to load.
+ *
+ * @description
+ *
+ * Use this directive to auto-bootstrap on application. Only
+ * one directive can be used per HTML document. The directive
+ * designates the root of the application and is typically placed
+ * at the root of the page.
+ *
+ * In the example below if the `ngApp` directive would not be placed
+ * on the `html` element then the document would not be compiled
+ * and the `{{ 1+2 }}` would not be resolved to `3`.
+ *
+ * `ngApp` is the easiest way to bootstrap an application.
+ *
+ <doc:example>
+   <doc:source>
+    I can add: 1 + 2 =  {{ 1+2 }}
+   </doc:source>
+ </doc:example>
+ *
+ */
+function angularInit(element, bootstrap) {
+  var elements = [element],
+      appElement,
+      module,
+      names = ['ng:app', 'ng-app', 'x-ng-app', 'data-ng-app'],
+      NG_APP_CLASS_REGEXP = /\sng[:\-]app(:\s*([\w\d_]+);?)?\s/;
+
+  function append(element) {
+    element && elements.push(element);
+  }
+
+  forEach(names, function(name) {
+    names[name] = true;
+    append(document.getElementById(name));
+    name = name.replace(':', '\\:');
+    if (element.querySelectorAll) {
+      forEach(element.querySelectorAll('.' + name), append);
+      forEach(element.querySelectorAll('.' + name + '\\:'), append);
+      forEach(element.querySelectorAll('[' + name + ']'), append);
+    }
+  });
+
+  forEach(elements, function(element) {
+    if (!appElement) {
+      var className = ' ' + element.className + ' ';
+      var match = NG_APP_CLASS_REGEXP.exec(className);
+      if (match) {
+        appElement = element;
+        module = (match[2] || '').replace(/\s+/g, ',');
+      } else {
+        forEach(element.attributes, function(attr) {
+          if (!appElement && names[attr.name]) {
+            appElement = element;
+            module = attr.value;
+          }
+        });
+      }
+    }
+  });
+  if (appElement) {
+    bootstrap(appElement, module ? [module] : []);
+  }
+}
+
+/**
+ * @ngdoc function
+ * @name angular.bootstrap
+ * @description
+ * Use this function to manually start up angular application.
+ *
+ * See: {@link guide/bootstrap Bootstrap}
+ *
+ * @param {Element} element DOM element which is the root of angular application.
+ * @param {Array<String|Function>=} modules an array of module declarations. See: {@link angular.module modules}
+ * @returns {AUTO.$injector} Returns the newly created injector for this app.
+ */
+function bootstrap(element, modules) {
+  element = jqLite(element);
+  modules = modules || [];
+  modules.unshift(['$provide', function($provide) {
+    $provide.value('$rootElement', element);
+  }]);
+  modules.unshift('ng');
+  var injector = createInjector(modules);
+  injector.invoke(
+    ['$rootScope', '$rootElement', '$compile', '$injector', function(scope, element, compile, injector){
+      scope.$apply(function() {
+        element.data('$injector', injector);
+        compile(element)(scope);
+      });
+    }]
+  );
+  return injector;
+}
+
+var SNAKE_CASE_REGEXP = /[A-Z]/g;
+function snake_case(name, separator){
+  separator = separator || '_';
+  return name.replace(SNAKE_CASE_REGEXP, function(letter, pos) {
+    return (pos ? separator : '') + letter.toLowerCase();
+  });
+}
+
+function bindJQuery() {
+  // bind to jQuery if present;
+  jQuery = window.jQuery;
+  // reset to jQuery or default to us.
+  if (jQuery) {
+    jqLite = jQuery;
+    extend(jQuery.fn, {
+      scope: JQLitePrototype.scope,
+      controller: JQLitePrototype.controller,
+      injector: JQLitePrototype.injector,
+      inheritedData: JQLitePrototype.inheritedData
+    });
+    JQLitePatchJQueryRemove('remove', true);
+    JQLitePatchJQueryRemove('empty');
+    JQLitePatchJQueryRemove('html');
+  } else {
+    jqLite = JQLite;
+  }
+  angular.element = jqLite;
+}
+
+/**
+ * throw error of the argument is falsy.
+ */
+function assertArg(arg, name, reason) {
+  if (!arg) {
+    throw new Error("Argument '" + (name || '?') + "' is " + (reason || "required"));
+  }
+  return arg;
+}
+
+function assertArgFn(arg, name, acceptArrayAnnotation) {
+  if (acceptArrayAnnotation && isArray(arg)) {
+      arg = arg[arg.length - 1];
+  }
+
+  assertArg(isFunction(arg), name, 'not a function, got ' +
+      (arg && typeof arg == 'object' ? arg.constructor.name || 'Object' : typeof arg));
+  return arg;
+}
+
+/**
+ * @ngdoc interface
+ * @name angular.Module
+ * @description
+ *
+ * Interface for configuring angular {@link angular.module modules}.
+ */
+
+function setupModuleLoader(window) {
+
+  function ensure(obj, name, factory) {
+    return obj[name] || (obj[name] = factory());
+  }
+
+  return ensure(ensure(window, 'angular', Object), 'module', function() {
+    /** @type {Object.<string, angular.Module>} */
+    var modules = {};
+
+    /**
+     * @ngdoc function
+     * @name angular.module
+     * @description
+     *
+     * The `angular.module` is a global place for creating and registering Angular modules. All
+     * modules (angular core or 3rd party) that should be available to an application must be
+     * registered using this mechanism.
+     *
+     *
+     * # Module
+     *
+     * A module is a collocation of services, directives, filters, and configuration information. Module
+     * is used to configure the {@link AUTO.$injector $injector}.
+     *
+     * <pre>
+     * // Create a new module
+     * var myModule = angular.module('myModule', []);
+     *
+     * // register a new service
+     * myModule.value('appName', 'MyCoolApp');
+     *
+     * // configure existing services inside initialization blocks.
+     * myModule.config(function($locationProvider) {
+     *   // Configure existing providers
+     *   $locationProvider.hashPrefix('!');
+     * });
+     * </pre>
+     *
+     * Then you can create an injector and load your modules like this:
+     *
+     * <pre>
+     * var injector = angular.injector(['ng', 'MyModule'])
+     * </pre>
+     *
+     * However it's more likely that you'll just use
+     * {@link ng.directive:ngApp ngApp} or
+     * {@link angular.bootstrap} to simplify this process for you.
+     *
+     * @param {!string} name The name of the module to create or retrieve.
+     * @param {Array.<string>=} requires If specified then new module is being created. If unspecified then the
+     *        the module is being retrieved for further configuration.
+     * @param {Function} configFn Optional configuration function for the module. Same as
+     *        {@link angular.Module#config Module#config()}.
+     * @returns {module} new module with the {@link angular.Module} api.
+     */
+    return function module(name, requires, configFn) {
+      if (requires && modules.hasOwnProperty(name)) {
+        modules[name] = null;
+      }
+      return ensure(modules, name, function() {
+        if (!requires) {
+          throw Error('No module: ' + name);
+        }
+
+        /** @type {!Array.<Array.<*>>} */
+        var invokeQueue = [];
+
+        /** @type {!Array.<Function>} */
+        var runBlocks = [];
+
+        var config = invokeLater('$injector', 'invoke');
+
+        /** @type {angular.Module} */
+        var moduleInstance = {
+          // Private state
+          _invokeQueue: invokeQueue,
+          _runBlocks: runBlocks,
+
+          /**
+           * @ngdoc property
+           * @name angular.Module#requires
+           * @propertyOf angular.Module
+           * @returns {Array.<string>} List of module names which must be loaded before this module.
+           * @description
+           * Holds the list of modules which the injector will load before the current module is loaded.
+           */
+          requires: requires,
+
+          /**
+           * @ngdoc property
+           * @name angular.Module#name
+           * @propertyOf angular.Module
+           * @returns {string} Name of the module.
+           * @description
+           */
+          name: name,
+
+
+          /**
+           * @ngdoc method
+           * @name angular.Module#provider
+           * @methodOf angular.Module
+           * @param {string} name service name
+           * @param {Function} providerType Construction function for creating new instance of the service.
+           * @description
+           * See {@link AUTO.$provide#provider $provide.provider()}.
+           */
+          provider: invokeLater('$provide', 'provider'),
+
+          /**
+           * @ngdoc method
+           * @name angular.Module#factory
+           * @methodOf angular.Module
+           * @param {string} name service name
+           * @param {Function} providerFunction Function for creating new instance of the service.
+           * @description
+           * See {@link AUTO.$provide#factory $provide.factory()}.
+           */
+          factory: invokeLater('$provide', 'factory'),
+
+          /**
+           * @ngdoc method
+           * @name angular.Module#service
+           * @methodOf angular.Module
+           * @param {string} name service name
+           * @param {Function} constructor A constructor function that will be instantiated.
+           * @description
+           * See {@link AUTO.$provide#service $provide.service()}.
+           */
+          service: invokeLater('$provide', 'service'),
+
+          /**
+           * @ngdoc method
+           * @name angular.Module#value
+           * @methodOf angular.Module
+           * @param {string} name service name
+           * @param {*} object Service instance object.
+           * @description
+           * See {@link AUTO.$provide#value $provide.value()}.
+           */
+          value: invokeLater('$provide', 'value'),
+
+          /**
+           * @ngdoc method
+           * @name angular.Module#constant
+           * @methodOf angular.Module
+           * @param {string} name constant name
+           * @param {*} object Constant value.
+           * @description
+           * Because the constant are fixed, they get applied before other provide methods.
+           * See {@link AUTO.$provide#constant $provide.constant()}.
+           */
+          constant: invokeLater('$provide', 'constant', 'unshift'),
+
+          /**
+           * @ngdoc method
+           * @name angular.Module#filter
+           * @methodOf angular.Module
+           * @param {string} name Filter name.
+           * @param {Function} filterFactory Factory function for creating new instance of filter.
+           * @description
+           * See {@link ng.$filterProvider#register $filterProvider.register()}.
+           */
+          filter: invokeLater('$filterProvider', 'register'),
+
+          /**
+           * @ngdoc method
+           * @name angular.Module#controller
+           * @methodOf angular.Module
+           * @param {string} name Controller name.
+           * @param {Function} constructor Controller constructor function.
+           * @description
+           * See {@link ng.$controllerProvider#register $controllerProvider.register()}.
+           */
+          controller: invokeLater('$controllerProvider', 'register'),
+
+          /**
+           * @ngdoc method
+           * @name angular.Module#directive
+           * @methodOf angular.Module
+           * @param {string} name directive name
+           * @param {Function} directiveFactory Factory function for creating new instance of
+           * directives.
+           * @description
+           * See {@link ng.$compileProvider#directive $compileProvider.directive()}.
+           */
+          directive: invokeLater('$compileProvider', 'directive'),
+
+          /**
+           * @ngdoc method
+           * @name angular.Module#config
+           * @methodOf angular.Module
+           * @param {Function} configFn Execute this function on module load. Useful for service
+           *    configuration.
+           * @description
+           * Use this method to register work which needs to be performed on module loading.
+           */
+          config: config,
+
+          /**
+           * @ngdoc method
+           * @name angular.Module#run
+           * @methodOf angular.Module
+           * @param {Function} initializationFn Execute this function after injector creation.
+           *    Useful for application initialization.
+           * @description
+           * Use this method to register work which should be performed when the injector is done
+           * loading all modules.
+           */
+          run: function(block) {
+            runBlocks.push(block);
+            return this;
+          }
+        };
+
+        if (configFn) {
+          config(configFn);
+        }
+
+        return  moduleInstance;
+
+        /**
+         * @param {string} provider
+         * @param {string} method
+         * @param {String=} insertMethod
+         * @returns {angular.Module}
+         */
+        function invokeLater(provider, method, insertMethod) {
+          return function() {
+            invokeQueue[insertMethod || 'push']([provider, method, arguments]);
+            return moduleInstance;
+          }
+        }
+      });
+    };
+  });
+
+}
+
+/**
+ * @ngdoc property
+ * @name angular.version
+ * @description
+ * An object that contains information about the current AngularJS version. This object has the
+ * following properties:
+ *
+ * - `full` – `{string}` – Full version string, such as "0.9.18".
+ * - `major` – `{number}` – Major version number, such as "0".
+ * - `minor` – `{number}` – Minor version number, such as "9".
+ * - `dot` – `{number}` – Dot version number, such as "18".
+ * - `codeName` – `{string}` – Code name of the release, such as "jiggling-armfat".
+ */
+var version = {
+  full: '1.0.5',    // all of these placeholder strings will be replaced by rake's
+  major: 1,    // compile task
+  minor: 0,
+  dot: 5,
+  codeName: 'flatulent-propulsion'
+};
+
+
+function publishExternalAPI(angular){
+  extend(angular, {
+    'bootstrap': bootstrap,
+    'copy': copy,
+    'extend': extend,
+    'equals': equals,
+    'element': jqLite,
+    'forEach': forEach,
+    'injector': createInjector,
+    'noop':noop,
+    'bind':bind,
+    'toJson': toJson,
+    'fromJson': fromJson,
+    'identity':identity,
+    'isUndefined': isUndefined,
+    'isDefined': isDefined,
+    'isString': isString,
+    'isFunction': isFunction,
+    'isObject': isObject,
+    'isNumber': isNumber,
+    'isElement': isElement,
+    'isArray': isArray,
+    'version': version,
+    'isDate': isDate,
+    'lowercase': lowercase,
+    'uppercase': uppercase,
+    'callbacks': {counter: 0}
+  });
+
+  angularModule = setupModuleLoader(window);
+  try {
+    angularModule('ngLocale');
+  } catch (e) {
+    angularModule('ngLocale', []).provider('$locale', $LocaleProvider);
+  }
+
+  angularModule('ng', ['ngLocale'], ['$provide',
+    function ngModule($provide) {
+      $provide.provider('$compile', $CompileProvider).
+        directive({
+            a: htmlAnchorDirective,
+            input: inputDirective,
+            textarea: inputDirective,
+            form: formDirective,
+            script: scriptDirective,
+            select: selectDirective,
+            style: styleDirective,
+            option: optionDirective,
+            ngBind: ngBindDirective,
+            ngBindHtmlUnsafe: ngBindHtmlUnsafeDirective,
+            ngBindTemplate: ngBindTemplateDirective,
+            ngClass: ngClassDirective,
+            ngClassEven: ngClassEvenDirective,
+            ngClassOdd: ngClassOddDirective,
+            ngCsp: ngCspDirective,
+            ngCloak: ngCloakDirective,
+            ngController: ngControllerDirective,
+            ngForm: ngFormDirective,
+            ngHide: ngHideDirective,
+            ngInclude: ngIncludeDirective,
+            ngInit: ngInitDirective,
+            ngNonBindable: ngNonBindableDirective,
+            ngPluralize: ngPluralizeDirective,
+            ngRepeat: ngRepeatDirective,
+            ngShow: ngShowDirective,
+            ngSubmit: ngSubmitDirective,
+            ngStyle: ngStyleDirective,
+            ngSwitch: ngSwitchDirective,
+            ngSwitchWhen: ngSwitchWhenDirective,
+            ngSwitchDefault: ngSwitchDefaultDirective,
+            ngOptions: ngOptionsDirective,
+            ngView: ngViewDirective,
+            ngTransclude: ngTranscludeDirective,
+            ngModel: ngModelDirective,
+            ngList: ngListDirective,
+            ngChange: ngChangeDirective,
+            required: requiredDirective,
+            ngRequired: requiredDirective,
+            ngValue: ngValueDirective
+        }).
+        directive(ngAttributeAliasDirectives).
+        directive(ngEventDirectives);
+      $provide.provider({
+        $anchorScroll: $AnchorScrollProvider,
+        $browser: $BrowserProvider,
+        $cacheFactory: $CacheFactoryProvider,
+        $controller: $ControllerProvider,
+        $document: $DocumentProvider,
+        $exceptionHandler: $ExceptionHandlerProvider,
+        $filter: $FilterProvider,
+        $interpolate: $InterpolateProvider,
+        $http: $HttpProvider,
+        $httpBackend: $HttpBackendProvider,
+        $location: $LocationProvider,
+        $log: $LogProvider,
+        $parse: $ParseProvider,
+        $route: $RouteProvider,
+        $routeParams: $RouteParamsProvider,
+        $rootScope: $RootScopeProvider,
+        $q: $QProvider,
+        $sniffer: $SnifferProvider,
+        $templateCache: $TemplateCacheProvider,
+        $timeout: $TimeoutProvider,
+        $window: $WindowProvider
+      });
+    }
+  ]);
+}
+
+//////////////////////////////////
+//JQLite
+//////////////////////////////////
+
+/**
+ * @ngdoc function
+ * @name angular.element
+ * @function
+ *
+ * @description
+ * Wraps a raw DOM element or HTML string as a [jQuery](http://jquery.com) element.
+ * `angular.element` can be either an alias for [jQuery](http://api.jquery.com/jQuery/) function, if
+ * jQuery is available, or a function that wraps the element or string in Angular's jQuery lite
+ * implementation (commonly referred to as jqLite).
+ *
+ * Real jQuery always takes precedence over jqLite, provided it was loaded before `DOMContentLoaded`
+ * event fired.
+ *
+ * jqLite is a tiny, API-compatible subset of jQuery that allows
+ * Angular to manipulate the DOM. jqLite implements only the most commonly needed functionality
+ * within a very small footprint, so only a subset of the jQuery API - methods, arguments and
+ * invocation styles - are supported.
+ *
+ * Note: All element references in Angular are always wrapped with jQuery or jqLite; they are never
+ * raw DOM references.
+ *
+ * ## Angular's jQuery lite provides the following methods:
+ *
+ * - [addClass()](http://api.jquery.com/addClass/)
+ * - [after()](http://api.jquery.com/after/)
+ * - [append()](http://api.jquery.com/append/)
+ * - [attr()](http://api.jquery.com/attr/)
+ * - [bind()](http://api.jquery.com/bind/)
+ * - [children()](http://api.jquery.com/children/)
+ * - [clone()](http://api.jquery.com/clone/)
+ * - [contents()](http://api.jquery.com/contents/)
+ * - [css()](http://api.jquery.com/css/)
+ * - [data()](http://api.jquery.com/data/)
+ * - [eq()](http://api.jquery.com/eq/)
+ * - [find()](http://api.jquery.com/find/) - Limited to lookups by tag name.
+ * - [hasClass()](http://api.jquery.com/hasClass/)
+ * - [html()](http://api.jquery.com/html/)
+ * - [next()](http://api.jquery.com/next/)
+ * - [parent()](http://api.jquery.com/parent/)
+ * - [prepend()](http://api.jquery.com/prepend/)
+ * - [prop()](http://api.jquery.com/prop/)
+ * - [ready()](http://api.jquery.com/ready/)
+ * - [remove()](http://api.jquery.com/remove/)
+ * - [removeAttr()](http://api.jquery.com/removeAttr/)
+ * - [removeClass()](http://api.jquery.com/removeClass/)
+ * - [removeData()](http://api.jquery.com/removeData/)
+ * - [replaceWith()](http://api.jquery.com/replaceWith/)
+ * - [text()](http://api.jquery.com/text/)
+ * - [toggleClass()](http://api.jquery.com/toggleClass/)
+ * - [triggerHandler()](http://api.jquery.com/triggerHandler/) - Doesn't pass native event objects to handlers.
+ * - [unbind()](http://api.jquery.com/unbind/)
+ * - [val()](http://api.jquery.com/val/)
+ * - [wrap()](http://api.jquery.com/wrap/)
+ *
+ * ## In addtion to the above, Angular provides additional methods to both jQuery and jQuery lite:
+ *
+ * - `controller(name)` - retrieves the controller of the current element or its parent. By default
+ *   retrieves controller associated with the `ngController` directive. If `name` is provided as
+ *   camelCase directive name, then the controller for this directive will be retrieved (e.g.
+ *   `'ngModel'`).
+ * - `injector()` - retrieves the injector of the current element or its parent.
+ * - `scope()` - retrieves the {@link api/ng.$rootScope.Scope scope} of the current
+ *   element or its parent.
+ * - `inheritedData()` - same as `data()`, but walks up the DOM until a value is found or the top
+ *   parent element is reached.
+ *
+ * @param {string|DOMElement} element HTML string or DOMElement to be wrapped into jQuery.
+ * @returns {Object} jQuery object.
+ */
+
+var jqCache = JQLite.cache = {},
+    jqName = JQLite.expando = 'ng-' + new Date().getTime(),
+    jqId = 1,
+    addEventListenerFn = (window.document.addEventListener
+      ? function(element, type, fn) {element.addEventListener(type, fn, false);}
+      : function(element, type, fn) {element.attachEvent('on' + type, fn);}),
+    removeEventListenerFn = (window.document.removeEventListener
+      ? function(element, type, fn) {element.removeEventListener(type, fn, false); }
+      : function(element, type, fn) {element.detachEvent('on' + type, fn); });
+
+function jqNextId() { return ++jqId; }
+
+
+var SPECIAL_CHARS_REGEXP = /([\:\-\_]+(.))/g;
+var MOZ_HACK_REGEXP = /^moz([A-Z])/;
+
+/**
+ * Converts snake_case to camelCase.
+ * Also there is special case for Moz prefix starting with upper case letter.
+ * @param name Name to normalize
+ */
+function camelCase(name) {
+  return name.
+    replace(SPECIAL_CHARS_REGEXP, function(_, separator, letter, offset) {
+      return offset ? letter.toUpperCase() : letter;
+    }).
+    replace(MOZ_HACK_REGEXP, 'Moz$1');
+}
+
+/////////////////////////////////////////////
+// jQuery mutation patch
+//
+//  In conjunction with bindJQuery intercepts all jQuery's DOM destruction apis and fires a
+// $destroy event on all DOM nodes being removed.
+//
+/////////////////////////////////////////////
+
+function JQLitePatchJQueryRemove(name, dispatchThis) {
+  var originalJqFn = jQuery.fn[name];
+  originalJqFn = originalJqFn.$original || originalJqFn;
+  removePatch.$original = originalJqFn;
+  jQuery.fn[name] = removePatch;
+
+  function removePatch() {
+    var list = [this],
+        fireEvent = dispatchThis,
+        set, setIndex, setLength,
+        element, childIndex, childLength, children,
+        fns, events;
+
+    while(list.length) {
+      set = list.shift();
+      for(setIndex = 0, setLength = set.length; setIndex < setLength; setIndex++) {
+        element = jqLite(set[setIndex]);
+        if (fireEvent) {
+          element.triggerHandler('$destroy');
+        } else {
+          fireEvent = !fireEvent;
+        }
+        for(childIndex = 0, childLength = (children = element.children()).length;
+            childIndex < childLength;
+            childIndex++) {
+          list.push(jQuery(children[childIndex]));
+        }
+      }
+    }
+    return originalJqFn.apply(this, arguments);
+  }
+}
+
+/////////////////////////////////////////////
+function JQLite(element) {
+  if (element instanceof JQLite) {
+    return element;
+  }
+  if (!(this instanceof JQLite)) {
+    if (isString(element) && element.charAt(0) != '<') {
+      throw Error('selectors not implemented');
+    }
+    return new JQLite(element);
+  }
+
+  if (isString(element)) {
+    var div = document.createElement('div');
+    // Read about the NoScope elements here:
+    // http://msdn.microsoft.com/en-us/library/ms533897(VS.85).aspx
+    div.innerHTML = '<div>&#160;</div>' + element; // IE insanity to make NoScope elements work!
+    div.removeChild(div.firstChild); // remove the superfluous div
+    JQLiteAddNodes(this, div.childNodes);
+    this.remove(); // detach the elements from the temporary DOM div.
+  } else {
+    JQLiteAddNodes(this, element);
+  }
+}
+
+function JQLiteClone(element) {
+  return element.cloneNode(true);
+}
+
+function JQLiteDealoc(element){
+  JQLiteRemoveData(element);
+  for ( var i = 0, children = element.childNodes || []; i < children.length; i++) {
+    JQLiteDealoc(children[i]);
+  }
+}
+
+function JQLiteUnbind(element, type, fn) {
+  var events = JQLiteExpandoStore(element, 'events'),
+      handle = JQLiteExpandoStore(element, 'handle');
+
+  if (!handle) return; //no listeners registered
+
+  if (isUndefined(type)) {
+    forEach(events, function(eventHandler, type) {
+      removeEventListenerFn(element, type, eventHandler);
+      delete events[type];
+    });
+  } else {
+    if (isUndefined(fn)) {
+      removeEventListenerFn(element, type, events[type]);
+      delete events[type];
+    } else {
+      arrayRemove(events[type], fn);
+    }
+  }
+}
+
+function JQLiteRemoveData(element) {
+  var expandoId = element[jqName],
+      expandoStore = jqCache[expandoId];
+
+  if (expandoStore) {
+    if (expandoStore.handle) {
+      expandoStore.events.$destroy && expandoStore.handle({}, '$destroy');
+      JQLiteUnbind(element);
+    }
+    delete jqCache[expandoId];
+    element[jqName] = undefined; // ie does not allow deletion of attributes on elements.
+  }
+}
+
+function JQLiteExpandoStore(element, key, value) {
+  var expandoId = element[jqName],
+      expandoStore = jqCache[expandoId || -1];
+
+  if (isDefined(value)) {
+    if (!expandoStore) {
+      element[jqName] = expandoId = jqNextId();
+      expandoStore = jqCache[expandoId] = {};
+    }
+    expandoStore[key] = value;
+  } else {
+    return expandoStore && expandoStore[key];
+  }
+}
+
+function JQLiteData(element, key, value) {
+  var data = JQLiteExpandoStore(element, 'data'),
+      isSetter = isDefined(value),
+      keyDefined = !isSetter && isDefined(key),
+      isSimpleGetter = keyDefined && !isObject(key);
+
+  if (!data && !isSimpleGetter) {
+    JQLiteExpandoStore(element, 'data', data = {});
+  }
+
+  if (isSetter) {
+    data[key] = value;
+  } else {
+    if (keyDefined) {
+      if (isSimpleGetter) {
+        // don't create data in this case.
+        return data && data[key];
+      } else {
+        extend(data, key);
+      }
+    } else {
+      return data;
+    }
+  }
+}
+
+function JQLiteHasClass(element, selector) {
+  return ((" " + element.className + " ").replace(/[\n\t]/g, " ").
+      indexOf( " " + selector + " " ) > -1);
+}
+
+function JQLiteRemoveClass(element, cssClasses) {
+  if (cssClasses) {
+    forEach(cssClasses.split(' '), function(cssClass) {
+      element.className = trim(
+          (" " + element.className + " ")
+          .replace(/[\n\t]/g, " ")
+          .replace(" " + trim(cssClass) + " ", " ")
+      );
+    });
+  }
+}
+
+function JQLiteAddClass(element, cssClasses) {
+  if (cssClasses) {
+    forEach(cssClasses.split(' '), function(cssClass) {
+      if (!JQLiteHasClass(element, cssClass)) {
+        element.className = trim(element.className + ' ' + trim(cssClass));
+      }
+    });
+  }
+}
+
+function JQLiteAddNodes(root, elements) {
+  if (elements) {
+    elements = (!elements.nodeName && isDefined(elements.length) && !isWindow(elements))
+      ? elements
+      : [ elements ];
+    for(var i=0; i < elements.length; i++) {
+      root.push(elements[i]);
+    }
+  }
+}
+
+function JQLiteController(element, name) {
+  return JQLiteInheritedData(element, '$' + (name || 'ngController' ) + 'Controller');
+}
+
+function JQLiteInheritedData(element, name, value) {
+  element = jqLite(element);
+
+  // if element is the document object work with the html element instead
+  // this makes $(document).scope() possible
+  if(element[0].nodeType == 9) {
+    element = element.find('html');
+  }
+
+  while (element.length) {
+    if (value = element.data(name)) return value;
+    element = element.parent();
+  }
+}
+
+//////////////////////////////////////////
+// Functions which are declared directly.
+//////////////////////////////////////////
+var JQLitePrototype = JQLite.prototype = {
+  ready: function(fn) {
+    var fired = false;
+
+    function trigger() {
+      if (fired) return;
+      fired = true;
+      fn();
+    }
+
+    this.bind('DOMContentLoaded', trigger); // works for modern browsers and IE9
+    // we can not use jqLite since we are not done loading and jQuery could be loaded later.
+    JQLite(window).bind('load', trigger); // fallback to window.onload for others
+  },
+  toString: function() {
+    var value = [];
+    forEach(this, function(e){ value.push('' + e);});
+    return '[' + value.join(', ') + ']';
+  },
+
+  eq: function(index) {
+      return (index >= 0) ? jqLite(this[index]) : jqLite(this[this.length + index]);
+  },
+
+  length: 0,
+  push: push,
+  sort: [].sort,
+  splice: [].splice
+};
+
+//////////////////////////////////////////
+// Functions iterating getter/setters.
+// these functions return self on setter and
+// value on get.
+//////////////////////////////////////////
+var BOOLEAN_ATTR = {};
+forEach('multiple,selected,checked,disabled,readOnly,required'.split(','), function(value) {
+  BOOLEAN_ATTR[lowercase(value)] = value;
+});
+var BOOLEAN_ELEMENTS = {};
+forEach('input,select,option,textarea,button,form'.split(','), function(value) {
+  BOOLEAN_ELEMENTS[uppercase(value)] = true;
+});
+
+function getBooleanAttrName(element, name) {
+  // check dom last since we will most likely fail on name
+  var booleanAttr = BOOLEAN_ATTR[name.toLowerCase()];
+
+  // booleanAttr is here twice to minimize DOM access
+  return booleanAttr && BOOLEAN_ELEMENTS[element.nodeName] && booleanAttr;
+}
+
+forEach({
+  data: JQLiteData,
+  inheritedData: JQLiteInheritedData,
+
+  scope: function(element) {
+    return JQLiteInheritedData(element, '$scope');
+  },
+
+  controller: JQLiteController ,
+
+  injector: function(element) {
+    return JQLiteInheritedData(element, '$injector');
+  },
+
+  removeAttr: function(element,name) {
+    element.removeAttribute(name);
+  },
+
+  hasClass: JQLiteHasClass,
+
+  css: function(element, name, value) {
+    name = camelCase(name);
+
+    if (isDefined(value)) {
+      element.style[name] = value;
+    } else {
+      var val;
+
+      if (msie <= 8) {
+        // this is some IE specific weirdness that jQuery 1.6.4 does not sure why
+        val = element.currentStyle && element.currentStyle[name];
+        if (val === '') val = 'auto';
+      }
+
+      val = val || element.style[name];
+
+      if (msie <= 8) {
+        // jquery weirdness :-/
+        val = (val === '') ? undefined : val;
+      }
+
+      return  val;
+    }
+  },
+
+  attr: function(element, name, value){
+    var lowercasedName = lowercase(name);
+    if (BOOLEAN_ATTR[lowercasedName]) {
+      if (isDefined(value)) {
+        if (!!value) {
+          element[name] = true;
+          element.setAttribute(name, lowercasedName);
+        } else {
+          element[name] = false;
+          element.removeAttribute(lowercasedName);
+        }
+      } else {
+        return (element[name] ||
+                 (element.attributes.getNamedItem(name)|| noop).specified)
+               ? lowercasedName
+               : undefined;
+      }
+    } else if (isDefined(value)) {
+      element.setAttribute(name, value);
+    } else if (element.getAttribute) {
+      // the extra argument "2" is to get the right thing for a.href in IE, see jQuery code
+      // some elements (e.g. Document) don't have get attribute, so return undefined
+      var ret = element.getAttribute(name, 2);
+      // normalize non-existing attributes to undefined (as jQuery)
+      return ret === null ? undefined : ret;
+    }
+  },
+
+  prop: function(element, name, value) {
+    if (isDefined(value)) {
+      element[name] = value;
+    } else {
+      return element[name];
+    }
+  },
+
+  text: extend((msie < 9)
+      ? function(element, value) {
+        if (element.nodeType == 1 /** Element */) {
+          if (isUndefined(value))
+            return element.innerText;
+          element.innerText = value;
+        } else {
+          if (isUndefined(value))
+            return element.nodeValue;
+          element.nodeValue = value;
+        }
+      }
+      : function(element, value) {
+        if (isUndefined(value)) {
+          return element.textContent;
+        }
+        element.textContent = value;
+      }, {$dv:''}),
+
+  val: function(element, value) {
+    if (isUndefined(value)) {
+      return element.value;
+    }
+    element.value = value;
+  },
+
+  html: function(element, value) {
+    if (isUndefined(value)) {
+      return element.innerHTML;
+    }
+    for (var i = 0, childNodes = element.childNodes; i < childNodes.length; i++) {
+      JQLiteDealoc(childNodes[i]);
+    }
+    element.innerHTML = value;
+  }
+}, function(fn, name){
+  /**
+   * Properties: writes return selection, reads return first value
+   */
+  JQLite.prototype[name] = function(arg1, arg2) {
+    var i, key;
+
+    // JQLiteHasClass has only two arguments, but is a getter-only fn, so we need to special-case it
+    // in a way that survives minification.
+    if (((fn.length == 2 && (fn !== JQLiteHasClass && fn !== JQLiteController)) ? arg1 : arg2) === undefined) {
+      if (isObject(arg1)) {
+
+        // we are a write, but the object properties are the key/values
+        for(i=0; i < this.length; i++) {
+          if (fn === JQLiteData) {
+            // data() takes the whole object in jQuery
+            fn(this[i], arg1);
+          } else {
+            for (key in arg1) {
+              fn(this[i], key, arg1[key]);
+            }
+          }
+        }
+        // return self for chaining
+        return this;
+      } else {
+        // we are a read, so read the first child.
+        if (this.length)
+          return fn(this[0], arg1, arg2);
+      }
+    } else {
+      // we are a write, so apply to all children
+      for(i=0; i < this.length; i++) {
+        fn(this[i], arg1, arg2);
+      }
+      // return self for chaining
+      return this;
+    }
+    return fn.$dv;
+  };
+});
+
+function createEventHandler(element, events) {
+  var eventHandler = function (event, type) {
+    if (!event.preventDefault) {
+      event.preventDefault = function() {
+        event.returnValue = false; //ie
+      };
+    }
+
+    if (!event.stopPropagation) {
+      event.stopPropagation = function() {
+        event.cancelBubble = true; //ie
+      };
+    }
+
+    if (!event.target) {
+      event.target = event.srcElement || document;
+    }
+
+    if (isUndefined(event.defaultPrevented)) {
+      var prevent = event.preventDefault;
+      event.preventDefault = function() {
+        event.defaultPrevented = true;
+        prevent.call(event);
+      };
+      event.defaultPrevented = false;
+    }
+
+    event.isDefaultPrevented = function() {
+      return event.defaultPrevented;
+    };
+
+    forEach(events[type || event.type], function(fn) {
+      fn.call(element, event);
+    });
+
+    // Remove monkey-patched methods (IE),
+    // as they would cause memory leaks in IE8.
+    if (msie <= 8) {
+      // IE7/8 does not allow to delete property on native object
+      event.preventDefault = null;
+      event.stopPropagation = null;
+      event.isDefaultPrevented = null;
+    } else {
+      // It shouldn't affect normal browsers (native methods are defined on prototype).
+      delete event.preventDefault;
+      delete event.stopPropagation;
+      delete event.isDefaultPrevented;
+    }
+  };
+  eventHandler.elem = element;
+  return eventHandler;
+}
+
+//////////////////////////////////////////
+// Functions iterating traversal.
+// These functions chain results into a single
+// selector.
+//////////////////////////////////////////
+forEach({
+  removeData: JQLiteRemoveData,
+
+  dealoc: JQLiteDealoc,
+
+  bind: function bindFn(element, type, fn){
+    var events = JQLiteExpandoStore(element, 'events'),
+        handle = JQLiteExpandoStore(element, 'handle');
+
+    if (!events) JQLiteExpandoStore(element, 'events', events = {});
+    if (!handle) JQLiteExpandoStore(element, 'handle', handle = createEventHandler(element, events));
+
+    forEach(type.split(' '), function(type){
+      var eventFns = events[type];
+
+      if (!eventFns) {
+        if (type == 'mouseenter' || type == 'mouseleave') {
+          var counter = 0;
+
+          events.mouseenter = [];
+          events.mouseleave = [];
+
+          bindFn(element, 'mouseover', function(event) {
+            counter++;
+            if (counter == 1) {
+              handle(event, 'mouseenter');
+            }
+          });
+          bindFn(element, 'mouseout', function(event) {
+            counter --;
+            if (counter == 0) {
+              handle(event, 'mouseleave');
+            }
+          });
+        } else {
+          addEventListenerFn(element, type, handle);
+          events[type] = [];
+        }
+        eventFns = events[type]
+      }
+      eventFns.push(fn);
+    });
+  },
+
+  unbind: JQLiteUnbind,
+
+  replaceWith: function(element, replaceNode) {
+    var index, parent = element.parentNode;
+    JQLiteDealoc(element);
+    forEach(new JQLite(replaceNode), function(node){
+      if (index) {
+        parent.insertBefore(node, index.nextSibling);
+      } else {
+        parent.replaceChild(node, element);
+      }
+      index = node;
+    });
+  },
+
+  children: function(element) {
+    var children = [];
+    forEach(element.childNodes, function(element){
+      if (element.nodeType === 1)
+        children.push(element);
+    });
+    return children;
+  },
+
+  contents: function(element) {
+    return element.childNodes || [];
+  },
+
+  append: function(element, node) {
+    forEach(new JQLite(node), function(child){
+      if (element.nodeType === 1)
+        element.appendChild(child);
+    });
+  },
+
+  prepend: function(element, node) {
+    if (element.nodeType === 1) {
+      var index = element.firstChild;
+      forEach(new JQLite(node), function(child){
+        if (index) {
+          element.insertBefore(child, index);
+        } else {
+          element.appendChild(child);
+          index = child;
+        }
+      });
+    }
+  },
+
+  wrap: function(element, wrapNode) {
+    wrapNode = jqLite(wrapNode)[0];
+    var parent = element.parentNode;
+    if (parent) {
+      parent.replaceChild(wrapNode, element);
+    }
+    wrapNode.appendChild(element);
+  },
+
+  remove: function(element) {
+    JQLiteDealoc(element);
+    var parent = element.parentNode;
+    if (parent) parent.removeChild(element);
+  },
+
+  after: function(element, newElement) {
+    var index = element, parent = element.parentNode;
+    forEach(new JQLite(newElement), function(node){
+      parent.insertBefore(node, index.nextSibling);
+      index = node;
+    });
+  },
+
+  addClass: JQLiteAddClass,
+  removeClass: JQLiteRemoveClass,
+
+  toggleClass: function(element, selector, condition) {
+    if (isUndefined(condition)) {
+      condition = !JQLiteHasClass(element, selector);
+    }
+    (condition ? JQLiteAddClass : JQLiteRemoveClass)(element, selector);
+  },
+
+  parent: function(element) {
+    var parent = element.parentNode;
+    return parent && parent.nodeType !== 11 ? parent : null;
+  },
+
+  next: function(element) {
+    if (element.nextElementSibling) {
+      return element.nextElementSibling;
+    }
+
+    // IE8 doesn't have nextElementSibling
+    var elm = element.nextSibling;
+    while (elm != null && elm.nodeType !== 1) {
+      elm = elm.nextSibling;
+    }
+    return elm;
+  },
+
+  find: function(element, selector) {
+    return element.getElementsByTagName(selector);
+  },
+
+  clone: JQLiteClone,
+
+  triggerHandler: function(element, eventName) {
+    var eventFns = (JQLiteExpandoStore(element, 'events') || {})[eventName];
+
+    forEach(eventFns, function(fn) {
+      fn.call(element, null);
+    });
+  }
+}, function(fn, name){
+  /**
+   * chaining functions
+   */
+  JQLite.prototype[name] = function(arg1, arg2) {
+    var value;
+    for(var i=0; i < this.length; i++) {
+      if (value == undefined) {
+        value = fn(this[i], arg1, arg2);
+        if (value !== undefined) {
+          // any function which returns a value needs to be wrapped
+          value = jqLite(value);
+        }
+      } else {
+        JQLiteAddNodes(value, fn(this[i], arg1, arg2));
+      }
+    }
+    return value == undefined ? this : value;
+  };
+});
+
+/**
+ * Computes a hash of an 'obj'.
+ * Hash of a:
+ *  string is string
+ *  number is number as string
+ *  object is either result of calling $$hashKey function on the object or uniquely generated id,
+ *         that is also assigned to the $$hashKey property of the object.
+ *
+ * @param obj
+ * @returns {string} hash string such that the same input will have the same hash string.
+ *         The resulting string key is in 'type:hashKey' format.
+ */
+function hashKey(obj) {
+  var objType = typeof obj,
+      key;
+
+  if (objType == 'object' && obj !== null) {
+    if (typeof (key = obj.$$hashKey) == 'function') {
+      // must invoke on object to keep the right this
+      key = obj.$$hashKey();
+    } else if (key === undefined) {
+      key = obj.$$hashKey = nextUid();
+    }
+  } else {
+    key = obj;
+  }
+
+  return objType + ':' + key;
+}
+
+/**
+ * HashMap which can use objects as keys
+ */
+function HashMap(array){
+  forEach(array, this.put, this);
+}
+HashMap.prototype = {
+  /**
+   * Store key value pair
+   * @param key key to store can be any type
+   * @param value value to store can be any type
+   */
+  put: function(key, value) {
+    this[hashKey(key)] = value;
+  },
+
+  /**
+   * @param key
+   * @returns the value for the key
+   */
+  get: function(key) {
+    return this[hashKey(key)];
+  },
+
+  /**
+   * Remove the key/value pair
+   * @param key
+   */
+  remove: function(key) {
+    var value = this[key = hashKey(key)];
+    delete this[key];
+    return value;
+  }
+};
+
+/**
+ * A map where multiple values can be added to the same key such that they form a queue.
+ * @returns {HashQueueMap}
+ */
+function HashQueueMap() {}
+HashQueueMap.prototype = {
+  /**
+   * Same as array push, but using an array as the value for the hash
+   */
+  push: function(key, value) {
+    var array = this[key = hashKey(key)];
+    if (!array) {
+      this[key] = [value];
+    } else {
+      array.push(value);
+    }
+  },
+
+  /**
+   * Same as array shift, but using an array as the value for the hash
+   */
+  shift: function(key) {
+    var array = this[key = hashKey(key)];
+    if (array) {
+      if (array.length == 1) {
+        delete this[key];
+        return array[0];
+      } else {
+        return array.shift();
+      }
+    }
+  },
+
+  /**
+   * return the first item without deleting it
+   */
+  peek: function(key) {
+    var array = this[hashKey(key)];
+    if (array) {
+    return array[0];
+    }
+  }
+};
+
+/**
+ * @ngdoc function
+ * @name angular.injector
+ * @function
+ *
+ * @description
+ * Creates an injector function that can be used for retrieving services as well as for
+ * dependency injection (see {@link guide/di dependency injection}).
+ *
+
+ * @param {Array.<string|Function>} modules A list of module functions or their aliases. See
+ *        {@link angular.module}. The `ng` module must be explicitly added.
+ * @returns {function()} Injector function. See {@link AUTO.$injector $injector}.
+ *
+ * @example
+ * Typical usage
+ * <pre>
+ *   // create an injector
+ *   var $injector = angular.injector(['ng']);
+ *
+ *   // use the injector to kick off your application
+ *   // use the type inference to auto inject arguments, or use implicit injection
+ *   $injector.invoke(function($rootScope, $compile, $document){
+ *     $compile($document)($rootScope);
+ *     $rootScope.$digest();
+ *   });
+ * </pre>
+ */
+
+
+/**
+ * @ngdoc overview
+ * @name AUTO
+ * @description
+ *
+ * Implicit module which gets automatically added to each {@link AUTO.$injector $injector}.
+ */
+
+var FN_ARGS = /^function\s*[^\(]*\(\s*([^\)]*)\)/m;
+var FN_ARG_SPLIT = /,/;
+var FN_ARG = /^\s*(_?)(\S+?)\1\s*$/;
+var STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg;
+function annotate(fn) {
+  var $inject,
+      fnText,
+      argDecl,
+      last;
+
+  if (typeof fn == 'function') {
+    if (!($inject = fn.$inject)) {
+      $inject = [];
+      fnText = fn.toString().replace(STRIP_COMMENTS, '');
+      argDecl = fnText.match(FN_ARGS);
+      forEach(argDecl[1].split(FN_ARG_SPLIT), function(arg){
+        arg.replace(FN_ARG, function(all, underscore, name){
+          $inject.push(name);
+        });
+      });
+      fn.$inject = $inject;
+    }
+  } else if (isArray(fn)) {
+    last = fn.length - 1;
+    assertArgFn(fn[last], 'fn')
+    $inject = fn.slice(0, last);
+  } else {
+    assertArgFn(fn, 'fn', true);
+  }
+  return $inject;
+}
+
+///////////////////////////////////////
+
+/**
+ * @ngdoc object
+ * @name AUTO.$injector
+ * @function
+ *
+ * @description
+ *
+ * `$injector` is used to retrieve object instances as defined by
+ * {@link AUTO.$provide provider}, instantiate types, invoke methods,
+ * and load modules.
+ *
+ * The following always holds true:
+ *
+ * <pre>
+ *   var $injector = angular.injector();
+ *   expect($injector.get('$injector')).toBe($injector);
+ *   expect($injector.invoke(function($injector){
+ *     return $injector;
+ *   }).toBe($injector);
+ * </pre>
+ *
+ * # Injection Function Annotation
+ *
+ * JavaScript does not have annotations, and annotations are needed for dependency injection. The
+ * following ways are all valid way of annotating function with injection arguments and are equivalent.
+ *
+ * <pre>
+ *   // inferred (only works if code not minified/obfuscated)
+ *   $inject.invoke(function(serviceA){});
+ *
+ *   // annotated
+ *   function explicit(serviceA) {};
+ *   explicit.$inject = ['serviceA'];
+ *   $inject.invoke(explicit);
+ *
+ *   // inline
+ *   $inject.invoke(['serviceA', function(serviceA){}]);
+ * </pre>
+ *
+ * ## Inference
+ *
+ * In JavaScript calling `toString()` on a function returns the function definition. The definition can then be
+ * parsed and the function arguments can be extracted. *NOTE:* This does not work with minification, and obfuscation
+ * tools since these tools change the argument names.
+ *
+ * ## `$inject` Annotation
+ * By adding a `$inject` property onto a function the injection parameters can be specified.
+ *
+ * ## Inline
+ * As an array of injection names, where the last item in the array is the function to call.
+ */
+
+/**
+ * @ngdoc method
+ * @name AUTO.$injector#get
+ * @methodOf AUTO.$injector
+ *
+ * @description
+ * Return an instance of the service.
+ *
+ * @param {string} name The name of the instance to retrieve.
+ * @return {*} The instance.
+ */
+
+/**
+ * @ngdoc method
+ * @name AUTO.$injector#invoke
+ * @methodOf AUTO.$injector
+ *
+ * @description
+ * Invoke the method and supply the method arguments from the `$injector`.
+ *
+ * @param {!function} fn The function to invoke. The function arguments come form the function annotation.
+ * @param {Object=} self The `this` for the invoked method.
+ * @param {Object=} locals Optional object. If preset then any argument names are read from this object first, before
+ *   the `$injector` is consulted.
+ * @returns {*} the value returned by the invoked `fn` function.
+ */
+
+/**
+ * @ngdoc method
+ * @name AUTO.$injector#instantiate
+ * @methodOf AUTO.$injector
+ * @description
+ * Create a new instance of JS type. The method takes a constructor function invokes the new operator and supplies
+ * all of the arguments to the constructor function as specified by the constructor annotation.
+ *
+ * @param {function} Type Annotated constructor function.
+ * @param {Object=} locals Optional object. If preset then any argument names are read from this object first, before
+ *   the `$injector` is consulted.
+ * @returns {Object} new instance of `Type`.
+ */
+
+/**
+ * @ngdoc method
+ * @name AUTO.$injector#annotate
+ * @methodOf AUTO.$injector
+ *
+ * @description
+ * Returns an array of service names which the function is requesting for injection. This API is used by the injector
+ * to determine which services need to be injected into the function when the function is invoked. There are three
+ * ways in which the function can be annotated with the needed dependencies.
+ *
+ * # Argument names
+ *
+ * The simplest form is to extract the dependencies from the arguments of the function. This is done by converting
+ * the function into a string using `toString()` method and extracting the argument names.
+ * <pre>
+ *   // Given
+ *   function MyController($scope, $route) {
+ *     // ...
+ *   }
+ *
+ *   // Then
+ *   expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);
+ * </pre>
+ *
+ * This method does not work with code minfication / obfuscation. For this reason the following annotation strategies
+ * are supported.
+ *
+ * # The `$inject` property
+ *
+ * If a function has an `$inject` property and its value is an array of strings, then the strings represent names of
+ * services to be injected into the function.
+ * <pre>
+ *   // Given
+ *   var MyController = function(obfuscatedScope, obfuscatedRoute) {
+ *     // ...
+ *   }
+ *   // Define function dependencies
+ *   MyController.$inject = ['$scope', '$route'];
+ *
+ *   // Then
+ *   expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);
+ * </pre>
+ *
+ * # The array notation
+ *
+ * It is often desirable to inline Injected functions and that's when setting the `$inject` property is very
+ * inconvenient. In these situations using the array notation to specify the dependencies in a way that survives
+ * minification is a better choice:
+ *
+ * <pre>
+ *   // We wish to write this (not minification / obfuscation safe)
+ *   injector.invoke(function($compile, $rootScope) {
+ *     // ...
+ *   });
+ *
+ *   // We are forced to write break inlining
+ *   var tmpFn = function(obfuscatedCompile, obfuscatedRootScope) {
+ *     // ...
+ *   };
+ *   tmpFn.$inject = ['$compile', '$rootScope'];
+ *   injector.invoke(tempFn);
+ *
+ *   // To better support inline function the inline annotation is supported
+ *   injector.invoke(['$compile', '$rootScope', function(obfCompile, obfRootScope) {
+ *     // ...
+ *   }]);
+ *
+ *   // Therefore
+ *   expect(injector.annotate(
+ *      ['$compile', '$rootScope', function(obfus_$compile, obfus_$rootScope) {}])
+ *    ).toEqual(['$compile', '$rootScope']);
+ * </pre>
+ *
+ * @param {function|Array.<string|Function>} fn Function for which dependent service names need to be retrieved as described
+ *   above.
+ *
+ * @returns {Array.<string>} The names of the services which the function requires.
+ */
+
+
+
+
+/**
+ * @ngdoc object
+ * @name AUTO.$provide
+ *
+ * @description
+ *
+ * Use `$provide` to register new providers with the `$injector`. The providers are the factories for the instance.
+ * The providers share the same name as the instance they create with the `Provider` suffixed to them.
+ *
+ * A provider is an object with a `$get()` method. The injector calls the `$get` method to create a new instance of
+ * a service. The Provider can have additional methods which would allow for configuration of the provider.
+ *
+ * <pre>
+ *   function GreetProvider() {
+ *     var salutation = 'Hello';
+ *
+ *     this.salutation = function(text) {
+ *       salutation = text;
+ *     };
+ *
+ *     this.$get = function() {
+ *       return function (name) {
+ *         return salutation + ' ' + name + '!';
+ *       };
+ *     };
+ *   }
+ *
+ *   describe('Greeter', function(){
+ *
+ *     beforeEach(module(function($provide) {
+ *       $provide.provider('greet', GreetProvider);
+ *     });
+ *
+ *     it('should greet', inject(function(greet) {
+ *       expect(greet('angular')).toEqual('Hello angular!');
+ *     }));
+ *
+ *     it('should allow configuration of salutation', function() {
+ *       module(function(greetProvider) {
+ *         greetProvider.salutation('Ahoj');
+ *       });
+ *       inject(function(greet) {
+ *         expect(greet('angular')).toEqual('Ahoj angular!');
+ *       });
+ *     )};
+ *
+ *   });
+ * </pre>
+ */
+
+/**
+ * @ngdoc method
+ * @name AUTO.$provide#provider
+ * @methodOf AUTO.$provide
+ * @description
+ *
+ * Register a provider for a service. The providers can be retrieved and can have additional configuration methods.
+ *
+ * @param {string} name The name of the instance. NOTE: the provider will be available under `name + 'Provider'` key.
+ * @param {(Object|function())} provider If the provider is:
+ *
+ *   - `Object`: then it should have a `$get` method. The `$get` method will be invoked using
+ *               {@link AUTO.$injector#invoke $injector.invoke()} when an instance needs to be created.
+ *   - `Constructor`: a new instance of the provider will be created using
+ *               {@link AUTO.$injector#instantiate $injector.instantiate()}, then treated as `object`.
+ *
+ * @returns {Object} registered provider instance
+ */
+
+/**
+ * @ngdoc method
+ * @name AUTO.$provide#factory
+ * @methodOf AUTO.$provide
+ * @description
+ *
+ * A short hand for configuring services if only `$get` method is required.
+ *
+ * @param {string} name The name of the instance.
+ * @param {function()} $getFn The $getFn for the instance creation. Internally this is a short hand for
+ * `$provide.provider(name, {$get: $getFn})`.
+ * @returns {Object} registered provider instance
+ */
+
+
+/**
+ * @ngdoc method
+ * @name AUTO.$provide#service
+ * @methodOf AUTO.$provide
+ * @description
+ *
+ * A short hand for registering service of given class.
+ *
+ * @param {string} name The name of the instance.
+ * @param {Function} constructor A class (constructor function) that will be instantiated.
+ * @returns {Object} registered provider instance
+ */
+
+
+/**
+ * @ngdoc method
+ * @name AUTO.$provide#value
+ * @methodOf AUTO.$provide
+ * @description
+ *
+ * A short hand for configuring services if the `$get` method is a constant.
+ *
+ * @param {string} name The name of the instance.
+ * @param {*} value The value.
+ * @returns {Object} registered provider instance
+ */
+
+
+/**
+ * @ngdoc method
+ * @name AUTO.$provide#constant
+ * @methodOf AUTO.$provide
+ * @description
+ *
+ * A constant value, but unlike {@link AUTO.$provide#value value} it can be injected
+ * into configuration function (other modules) and it is not interceptable by
+ * {@link AUTO.$provide#decorator decorator}.
+ *
+ * @param {string} name The name of the constant.
+ * @param {*} value The constant value.
+ * @returns {Object} registered instance
+ */
+
+
+/**
+ * @ngdoc method
+ * @name AUTO.$provide#decorator
+ * @methodOf AUTO.$provide
+ * @description
+ *
+ * Decoration of service, allows the decorator to intercept the service instance creation. The
+ * returned instance may be the original instance, or a new instance which delegates to the
+ * original instance.
+ *
+ * @param {string} name The name of the service to decorate.
+ * @param {function()} decorator This function will be invoked when the service needs to be
+ *    instanciated. The function is called using the {@link AUTO.$injector#invoke
+ *    injector.invoke} method and is therefore fully injectable. Local injection arguments:
+ *
+ *    * `$delegate` - The original service instance, which can be monkey patched, configured,
+ *      decorated or delegated to.
+ */
+
+
+function createInjector(modulesToLoad) {
+  var INSTANTIATING = {},
+      providerSuffix = 'Provider',
+      path = [],
+      loadedModules = new HashMap(),
+      providerCache = {
+        $provide: {
+            provider: supportObject(provider),
+            factory: supportObject(factory),
+            service: supportObject(service),
+            value: supportObject(value),
+            constant: supportObject(constant),
+            decorator: decorator
+          }
+      },
+      providerInjector = createInternalInjector(providerCache, function() {
+        throw Error("Unknown provider: " + path.join(' <- '));
+      }),
+      instanceCache = {},
+      instanceInjector = (instanceCache.$injector =
+          createInternalInjector(instanceCache, function(servicename) {
+            var provider = providerInjector.get(servicename + providerSuffix);
+            return instanceInjector.invoke(provider.$get, provider);
+          }));
+
+
+  forEach(loadModules(modulesToLoad), function(fn) { instanceInjector.invoke(fn || noop); });
+
+  return instanceInjector;
+
+  ////////////////////////////////////
+  // $provider
+  ////////////////////////////////////
+
+  function supportObject(delegate) {
+    return function(key, value) {
+      if (isObject(key)) {
+        forEach(key, reverseParams(delegate));
+      } else {
+        return delegate(key, value);
+      }
+    }
+  }
+
+  function provider(name, provider_) {
+    if (isFunction(provider_) || isArray(provider_)) {
+      provider_ = providerInjector.instantiate(provider_);
+    }
+    if (!provider_.$get) {
+      throw Error('Provider ' + name + ' must define $get factory method.');
+    }
+    return providerCache[name + providerSuffix] = provider_;
+  }
+
+  function factory(name, factoryFn) { return provider(name, { $get: factoryFn }); }
+
+  function service(name, constructor) {
+    return factory(name, ['$injector', function($injector) {
+      return $injector.instantiate(constructor);
+    }]);
+  }
+
+  function value(name, value) { return factory(name, valueFn(value)); }
+
+  function constant(name, value) {
+    providerCache[name] = value;
+    instanceCache[name] = value;
+  }
+
+  function decorator(serviceName, decorFn) {
+    var origProvider = providerInjector.get(serviceName + providerSuffix),
+        orig$get = origProvider.$get;
+
+    origProvider.$get = function() {
+      var origInstance = instanceInjector.invoke(orig$get, origProvider);
+      return instanceInjector.invoke(decorFn, null, {$delegate: origInstance});
+    };
+  }
+
+  ////////////////////////////////////
+  // Module Loading
+  ////////////////////////////////////
+  function loadModules(modulesToLoad){
+    var runBlocks = [];
+    forEach(modulesToLoad, function(module) {
+      if (loadedModules.get(module)) return;
+      loadedModules.put(module, true);
+      if (isString(module)) {
+        var moduleFn = angularModule(module);
+        runBlocks = runBlocks.concat(loadModules(moduleFn.requires)).concat(moduleFn._runBlocks);
+
+        try {
+          for(var invokeQueue = moduleFn._invokeQueue, i = 0, ii = invokeQueue.length; i < ii; i++) {
+            var invokeArgs = invokeQueue[i],
+                provider = invokeArgs[0] == '$injector'
+                    ? providerInjector
+                    : providerInjector.get(invokeArgs[0]);
+
+            provider[invokeArgs[1]].apply(provider, invokeArgs[2]);
+          }
+        } catch (e) {
+          if (e.message) e.message += ' from ' + module;
+          throw e;
+        }
+      } else if (isFunction(module)) {
+        try {
+          runBlocks.push(providerInjector.invoke(module));
+        } catch (e) {
+          if (e.message) e.message += ' from ' + module;
+          throw e;
+        }
+      } else if (isArray(module)) {
+        try {
+          runBlocks.push(providerInjector.invoke(module));
+        } catch (e) {
+          if (e.message) e.message += ' from ' + String(module[module.length - 1]);
+          throw e;
+        }
+      } else {
+        assertArgFn(module, 'module');
+      }
+    });
+    return runBlocks;
+  }
+
+  ////////////////////////////////////
+  // internal Injector
+  ////////////////////////////////////
+
+  function createInternalInjector(cache, factory) {
+
+    function getService(serviceName) {
+      if (typeof serviceName !== 'string') {
+        throw Error('Service name expected');
+      }
+      if (cache.hasOwnProperty(serviceName)) {
+        if (cache[serviceName] === INSTANTIATING) {
+          throw Error('Circular dependency: ' + path.join(' <- '));
+        }
+        return cache[serviceName];
+      } else {
+        try {
+          path.unshift(serviceName);
+          cache[serviceName] = INSTANTIATING;
+          return cache[serviceName] = factory(serviceName);
+        } finally {
+          path.shift();
+        }
+      }
+    }
+
+    function invoke(fn, self, locals){
+      var args = [],
+          $inject = annotate(fn),
+          length, i,
+          key;
+
+      for(i = 0, length = $inject.length; i < length; i++) {
+        key = $inject[i];
+        args.push(
+          locals && locals.hasOwnProperty(key)
+          ? locals[key]
+          : getService(key)
+        );
+      }
+      if (!fn.$inject) {
+        // this means that we must be an array.
+        fn = fn[length];
+      }
+
+
+      // Performance optimization: http://jsperf.com/apply-vs-call-vs-invoke
+      switch (self ? -1 : args.length) {
+        case  0: return fn();
+        case  1: return fn(args[0]);
+        case  2: return fn(args[0], args[1]);
+        case  3: return fn(args[0], args[1], args[2]);
+        case  4: return fn(args[0], args[1], args[2], args[3]);
+        case  5: return fn(args[0], args[1], args[2], args[3], args[4]);
+        case  6: return fn(args[0], args[1], args[2], args[3], args[4], args[5]);
+        case  7: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6]);
+        case  8: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7]);
+        case  9: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8]);
+        case 10: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9]);
+        default: return fn.apply(self, args);
+      }
+    }
+
+    function instantiate(Type, locals) {
+      var Constructor = function() {},
+          instance, returnedValue;
+
+      Constructor.prototype = (isArray(Type) ? Type[Type.length - 1] : Type).prototype;
+      instance = new Constructor();
+      returnedValue = invoke(Type, instance, locals);
+
+      return isObject(returnedValue) ? returnedValue : instance;
+    }
+
+    return {
+      invoke: invoke,
+      instantiate: instantiate,
+      get: getService,
+      annotate: annotate
+    };
+  }
+}
+/**
+ * @ngdoc function
+ * @name ng.$anchorScroll
+ * @requires $window
+ * @requires $location
+ * @requires $rootScope
+ *
+ * @description
+ * When called, it checks current value of `$location.hash()` and scroll to related element,
+ * according to rules specified in
+ * {@link http://dev.w3.org/html5/spec/Overview.html#the-indicated-part-of-the-document Html5 spec}.
+ *
+ * It also watches the `$location.hash()` and scroll whenever it changes to match any anchor.
+ * This can be disabled by calling `$anchorScrollProvider.disableAutoScrolling()`.
+ */
+function $AnchorScrollProvider() {
+
+  var autoScrollingEnabled = true;
+
+  this.disableAutoScrolling = function() {
+    autoScrollingEnabled = false;
+  };
+
+  this.$get = ['$window', '$location', '$rootScope', function($window, $location, $rootScope) {
+    var document = $window.document;
+
+    // helper function to get first anchor from a NodeList
+    // can't use filter.filter, as it accepts only instances of Array
+    // and IE can't convert NodeList to an array using [].slice
+    // TODO(vojta): use filter if we change it to accept lists as well
+    function getFirstAnchor(list) {
+      var result = null;
+      forEach(list, function(element) {
+        if (!result && lowercase(element.nodeName) === 'a') result = element;
+      });
+      return result;
+    }
+
+    function scroll() {
+      var hash = $location.hash(), elm;
+
+      // empty hash, scroll to the top of the page
+      if (!hash) $window.scrollTo(0, 0);
+
+      // element with given id
+      else if ((elm = document.getElementById(hash))) elm.scrollIntoView();
+
+      // first anchor with given name :-D
+      else if ((elm = getFirstAnchor(document.getElementsByName(hash)))) elm.scrollIntoView();
+
+      // 

<TRUNCATED>

[40/51] [abbrv] [partial] Adding Jinwon's custom RCMET

Posted by jo...@apache.org.
http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/rcmes/toolkit/metrics.py
----------------------------------------------------------------------
diff --git a/src/main/python/rcmes/toolkit/metrics.py b/src/main/python/rcmes/toolkit/metrics.py
new file mode 100755
index 0000000..f15be47
--- /dev/null
+++ b/src/main/python/rcmes/toolkit/metrics.py
@@ -0,0 +1,2550 @@
+#
+#  Licensed to the Apache Software Foundation (ASF) under one or more
+#  contributor license agreements.  See the NOTICE file distributed with
+#  this work for additional information regarding copyright ownership.
+#  The ASF licenses this file to You under the Apache License, Version 2.0
+#  (the "License"); you may not use this file except in compliance with
+#  the License.  You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+#  Unless required by applicable law or agreed to in writing, software
+#  distributed under the License is distributed on an "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#  See the License for the specific language governing permissions and
+#  limitations under the License.
+#
+
+'''
+Module storing functions to calculate statistical metrics from numpy arrays
+'''
+
+import datetime
+import subprocess
+import sys
+import os
+import numpy as np
+import numpy.ma as ma
+from math import floor, log
+from toolkit import process
+from utils import misc
+from storage import files 
+from pylab import *
+import scipy.stats.mstats as mstats
+import matplotlib as mpl
+import matplotlib.dates
+import matplotlib.pyplot as plt
+from mpl_toolkits.axes_grid1 import ImageGrid
+from matplotlib.font_manager import FontProperties
+from mpl_toolkits.basemap import Basemap
+from utils.Taylor import TaylorDiagram
+# 6/10/2012 JK: any Ngl dependence will be removed in later versions
+#import Ngl
+
+def calc_ann_mean(t2, time):
+    '''
+    Calculate annual cycle in terms of monthly means at every grid point.
+    '''
+    # Calculate annual cycle in terms of monthly means at every grid point including single point case (ndim=1)
+    # note: this routine is identical to 'calc_annual_cycle_means': must be converted to calculate the annual mean
+    # Extract months from time variable
+    months = np.empty(len(time))
+    for t in np.arange(len(time)):
+        months[t] = time[t].month
+    if t2.ndim == 3:
+        means = ma.empty((12, t2.shape[1], t2.shape[2])) # empty array to store means
+        # Calculate means month by month
+        for i in np.arange(12)+1:
+            means[i - 1, :, :] = t2[months == i, :, :].mean(0)
+    if t2.ndim == 1:
+        means = np.empty((12)) # empty array to store means
+        # Calculate means month by month
+        for i in np.arange(12)+1:
+            means[i - 1] = t2[months == i].mean(0)
+    return means
+
+
+def calc_clim_month(t2, time):
+    '''
+    Calculate monthly means at every grid point.
+    '''
+    # Calculate monthly means at every grid point including single point case (ndim=1)
+    # Extract months from time variable
+    months = np.empty(len(time))
+    for t in np.arange(len(time)):
+        months[t] = time[t].month
+    if t2.ndim == 3:
+        means = ma.empty((12, t2.shape[1], t2.shape[2])) # empty array to store means
+        # Calculate means month by month
+        for i in np.arange(12) + 1:
+            means[i - 1, :, :] = t2[months == i, :, :].mean(0)
+    if t2.ndim == 1:
+        means = np.empty((12)) # empty array to store means
+        # Calculate means month by month
+        for i in np.arange(12) + 1:
+            means[i - 1] = t2[months == i].mean(0)
+    return means
+
+
+def calc_clim_year(nYR, nT, ngrdY, ngrdX, t2, time):
+    '''
+    Calculate annual mean timeseries and climatology for both 2-D and point time series.
+    '''
+    # Extract months from time variable
+    yy = np.empty(nT)
+    mm = np.empty(nT)
+    for t in np.arange(nT):
+        yy[t] = time[t].year
+        mm[t] = time[t].month
+    if t2.ndim == 3:
+        tSeries = ma.zeros((nYR, ngrdY, ngrdX))
+        i = 0
+        for myunit in np.unique(yy):
+            wh = (yy == myunit)
+            data = t2[wh, :, :]
+            tSeries[i, :, :] = ma.average(data, axis = 0)
+            #print 'data.shape= ',data.shape,'  i= ',i,'  yy= ',yy
+            i += 1
+        means = ma.zeros((ngrdY, ngrdX))
+        means = ma.average(tSeries, axis = 0)
+    elif t2.ndim == 1:
+        tSeries = ma.zeros((nYR))
+        i = 0
+        for myunit in np.unique(yy):
+            wh = (yy == myunit)
+            data = t2[wh]
+            tSeries[i] = ma.average(data, axis = 0)
+            #print 'data.shape= ',data.shape,'  i= ',i,'  yy= ',yy
+            i += 1
+        means = ma.zeros((ngrdY, ngrdX))
+        means = ma.average(tSeries, axis = 0)
+    return tSeries, means
+
+
+def calc_clim_season(nYR, nT, mB, mE, ngrdY, ngrdX, t2, time):
+    '''
+    Calculate seasonal mean timeseries and climatology for both 2-D and point time series.
+    '''
+    #-------------------------------------------------------------------------------------
+    # Calculate seasonal mean timeseries and climatology for both 2-d and point time series
+    # The season to be calculated is defined by moB and moE; moE>=moB always
+    #-------------------------------------------------------------------------------------
+    # Extract months from time variable
+    yy = np.empty(nT)
+    mm = np.empty(nT)
+    for t in np.arange(nT):
+        yy[t] = time[t].year
+        mm[t] = time[t].month
+    if t2.ndim == 3:
+        tSeries = ma.zeros((nYR, ngrdY, ngrdX))
+        i = 0
+        for myunit in np.unique(yy):
+            wh = (yy == myunit) & (mm >= mB) & (mm <= mE)
+            data = t2[wh, :, :]
+            tSeries[i, :, :] = ma.average(data, axis = 0)
+            #print 'data.shape= ',data.shape,'  i= ',i,'  yy= ',yy
+            i += 1
+        means = ma.zeros((ngrdY, ngrdX))
+        means = ma.average(tSeries, axis = 0)
+    elif t2.ndim == 1:
+        tSeries = ma.zeros((nYR))
+        i = 0
+        for myunit in np.unique(yy):
+            wh = (yy == myunit) & (mm >= mB) & (mm <= mE)
+            data = t2[wh]
+            tSeries[i] = ma.average(data, axis = 0)
+            #print 'data.shape= ',data.shape,'  i= ',i,'  yy= ',yy
+            i += 1
+        means = ma.zeros((ngrdY, ngrdX))
+        means = ma.average(tSeries, axis = 0)
+    return tSeries, means
+
+
+def calc_clim_mo(nYR, nT, ngrdY, ngrdX, t2, time):
+    '''
+    Calculate monthly means at every grid points and the annual time series of single model including single point case (ndim=1).
+    JK20: This is modified from 'calc_clim_month'  with additional arguments & output, the annual time series of single model output (mData)
+    6/8/2013: bug fix: mm = months[t] --> mm = months[t] - 1, otherwise array overflow occurs
+    '''
+    # Extract months and monthly time series from the time and raw variable, respectively
+    months = np.empty(nT)
+    for t in np.arange(nT):
+        months[t] = time[t].month
+        if t == 0:
+            yy0 = time[t].year
+        # for a 2-D time series data
+    if t2.ndim == 3:
+        mData = ma.empty((nYR, 12, ngrdY, ngrdX))
+        for t in np.arange(nT):
+            yy = time[t].year
+            mm = months[t] - 1
+            yr = yy - yy0
+            mData[yr, mm, :, :] = t2[t, :, :]
+        # Calculate means month by month. means is an empty array to store means
+        means = ma.empty((12, ngrdY, ngrdX))
+        for i in np.arange(12) + 1:
+            means[i - 1, :, :] = t2[months == i, :, :].mean(0)
+        # for a point time series data
+    if t2.ndim == 1:
+        mData = ma.empty((nYR, 12))
+        for t in np.arange(nT):
+            yy = time[t].year
+            mm = months[t]
+            yr = yy - yy0
+            mData[yr, mm] = t2[t]
+        means = np.empty((12))
+        # Calculate means month by month. means is an empty array to store means
+        for i in np.arange(12) + 1:
+            means[i - 1] = t2[months == i].mean(0)
+    return mData, means
+
+
+def calc_clim_One_month(moID, nYR, nT, t2, time):
+    '''
+    Calculate the montly mean at every grid point for a specified month.
+    '''
+    #-------------------------------------------------------------------------------------
+    # Calculate monthly means at every grid point for a specified month
+    #-------------------------------------------------------------------------------------
+    # Extract months and the corresponding time series from time variable
+    months = np.empty(nT)
+    for t in np.arange(nT):
+        months[t] = time[t].month
+    if t2.ndim == 3:
+        mData = ma.empty((nYR, t2.shape[1], t2.shape[2])) # empty array to store time series
+        n = 0
+        if months[t] == moID:
+            mData[n, :, :] = t2[t, :, :]
+            n += 1
+        means = ma.empty((t2.shape[1], t2.shape[2])) # empty array to store means
+        # Calculate means for the month specified by moID
+        means[:, :] = t2[months == moID, :, :].mean(0)
+    return mData, means
+
+
+def calc_annual_cycle_means(data, time):
+    '''
+     Calculate monthly means for every grid point
+     
+     Inputs:: 
+     	data - masked 3d array of the model data (time, lon, lat)
+     	time - an array of python datetime objects
+    '''
+    # Extract months from time variable
+    months = np.empty(len(time))
+    
+    for t in np.arange(len(time)):
+        months[t] = time[t].month
+    
+    #if there is data varying in t and space
+    if data.ndim == 3:
+        # empty array to store means
+        means = ma.empty((12, data.shape[1], data.shape[2]))
+        
+        # Calculate means month by month
+        for i in np.arange(12) + 1:
+            means[i - 1, :, :] = data[months == i, :, :].mean(0)
+        
+    #if the data is a timeseries over area-averaged values
+    if data.ndim == 1:
+        # TODO - Investigate using ma per KDW
+        means = np.empty((12)) # empty array to store means??WHY NOT ma?
+        
+        # Calculate means month by month
+        for i in np.arange(12) + 1:
+            means[i - 1] = data[months == i].mean(0)
+    
+    return means
+
+
+def calc_annual_cycle_std(data, time):
+    '''
+     Calculate monthly standard deviations for every grid point
+    '''
+    # Extract months from time variable
+    months = np.empty(len(time))
+    
+    for t in np.arange(len(time)):
+        months[t] = time[t].month
+    
+    # empty array to store means
+    stds = np.empty((12, data.shape[1], data.shape[2]))
+    
+    # Calculate means month by month
+    for i in np.arange(12) + 1:
+        stds[i - 1, :, :] = data[months == i, :, :].std(axis = 0, ddof = 1)
+    
+    return stds
+
+
+def calc_annual_cycle_domain_means(data, time):
+    '''
+     Calculate domain means for each month of the year
+    '''
+    # Extract months from time variable
+    months = np.empty(len(time))
+    
+    for t in np.arange(len(time)):
+        months[t] = time[t].month
+       	
+    means = np.empty(12) # empty array to store means
+    
+    # Calculate means month by month
+    for i in np.arange(12) + 1:
+        means[i - 1] = data[months == i, :, :].mean()
+    
+    return means
+
+
+def calc_annual_cycle_domain_std(data, time):
+    '''
+     Calculate domain standard deviations for each month of the year
+    '''
+    # Extract months from time variable
+    months = np.empty(len(time))
+    
+    for t in np.arange(len(time)):
+        months[t] = time[t].month
+    
+    stds = np.empty(12) # empty array to store means
+    
+    # Calculate means month by month
+    for i in np.arange(12) + 1:
+        stds[i - 1] = data[months == i, :, :].std(ddof = 1)
+    
+    return stds
+
+
+def calc_bias_annual(t1, t2, optn):        # Mean Bias
+    '''
+    Calculate the mean difference between two fields over time for each grid point.
+    '''
+    # Calculate mean difference between two fields over time for each grid point
+    # Precrocessing of both obs and model data ensures the absence of missing values
+    diff = t1-t2
+    if(open == 'abs'): 
+        diff = abs(diff)
+    bias = diff.mean(axis = 0)
+    return bias
+
+
+def calc_bias(t1, t2):
+    '''
+    Calculate mean difference between two fields over time for each grid point
+    
+    Classify missing data resulting from multiple times (using threshold 
+    data requirement)
+    
+    i.e. if the working time unit is monthly data, and we are dealing with 
+    multiple months of data then when we show mean of several months, we need
+    to decide what threshold of missing data we tolerate before classifying a
+    data point as missing data.
+    '''
+    t1Mask = process.create_mask_using_threshold(t1, threshold = 0.75)
+    t2Mask = process.create_mask_using_threshold(t2, threshold = 0.75)
+    
+    diff = t1 - t2
+    bias = diff.mean(axis = 0)
+    
+    # Set mask for bias metric using missing data in obs or model data series
+    #   i.e. if obs contains more than threshold (e.g.50%) missing data 
+    #        then classify time average bias as missing data for that location. 
+    bias = ma.masked_array(bias.data, np.logical_or(t1Mask, t2Mask))
+    return bias
+
+
+def calc_bias_dom(t1, t2):
+    '''
+     Calculate domain mean difference between two fields over time
+    '''
+    diff = t1 - t2
+    bias = diff.mean()
+    return bias
+
+
+def calc_difference(t1, t2):
+    '''
+     Calculate mean difference between two fields over time for each grid point
+    '''
+    print 'Calculating difference'
+    diff = t1 - t2
+    return diff
+
+
+def calc_mae(t1, t2):
+    '''
+    Calculate mean difference between two fields over time for each grid point
+    
+    Classify missing data resulting from multiple times (using threshold 
+    data requirement) 
+    
+    i.e. if the working time unit is monthly data, and we are dealing with
+    multiple months of data then when we show mean of several months, we need
+    to decide what threshold of missing data we tolerate before classifying
+    a data point as missing data.
+    '''
+    t1Mask = process.create_mask_using_threshold(t1, threshold = 0.75)
+    t2Mask = process.create_mask_using_threshold(t2, threshold = 0.75)
+    
+    diff = t1 - t2
+    adiff = abs(diff)
+    
+    mae = adiff.mean(axis = 0)
+    
+    # Set mask for mae metric using missing data in obs or model data series
+    #   i.e. if obs contains more than threshold (e.g.50%) missing data 
+    #        then classify time average mae as missing data for that location. 
+    mae = ma.masked_array(mae.data, np.logical_or(t1Mask, t2Mask))
+    return mae
+
+
+def calc_mae_dom(t1, t2):
+    '''
+     Calculate domain mean difference between two fields over time
+    '''
+    diff = t1 - t2
+    adiff = abs(diff)
+    mae = adiff.mean()
+    return mae
+
+
+def calc_rms(t1, t2):
+    '''
+     Calculate mean difference between two fields over time for each grid point
+    '''
+    diff = t1 - t2
+    sqdiff = diff ** 2
+    msd = sqdiff.mean(axis = 0)
+    rms = np.sqrt(msd)
+    return rms
+
+
+def calc_rms_dom(t1, t2):
+    '''
+     Calculate RMS differences between two fields
+    '''
+    diff = t1 - t2
+    sqdiff = diff ** 2
+    msd = sqdiff.mean()
+    rms = np.sqrt(msd)
+    return rms
+
+
+def calc_temporal_stdv(t1):
+    '''
+    Calculate the temporal standard deviation.
+
+    Input:
+        t1 - data array of any shape
+
+    Output:
+        A 2-D array of temporal standard deviation
+    '''
+    # TODO Make sure the first dimension of t1 is teh time axis.
+    stdv = t1.std(axis = 0)
+    return stdv
+
+
+def calc_temporal_anom_cor(mD, oD):
+    '''
+    Calculate the temporal anomaly correlation.
+
+    Assumption(s);
+        The first dimension of mD and oD is the time axis.
+
+    Input:
+        mD - model data array of any shape
+        oD - observation data array of any shape
+
+    Output:
+        A 2-D array of time series pattern correlation coefficients at each grid point.
+
+    REF: 277-281 in Stat methods in atmos sci by Wilks, 1995, Academic Press, 467pp.
+    '''
+    mo = oD.mean(axis = 0)
+    nt = oD.shape[0]
+    deno1 = ((mD - mo) * (mD - mo)).sum(axis = 0)
+    deno2 = ((oD - mo) * (oD - mo)).sum(axis = 0)
+    patcor = ((mD - mo) * (oD - mo)).sum(axis = 0) / sqrt(deno1 * deno2)
+    return patcor
+
+
+def calc_spatial_anom_cor(mD, oD):
+    '''
+    Calculate anomaly correlation between two 2-D arrays.
+
+    Input:
+        mD - 2-D array of model data
+        oD - 2-D array of observation data
+
+    Output:
+        The anomaly correlation between the two input arrays.
+    '''
+    mo = oD.mean()
+    d1 = ((mD - mo)*(mD - mo)).sum()
+    d2 = ((oD - mo)*(oD - mo)).sum()
+    patcor = ((mD - mo) * (oD - mo)).sum() / sqrt(d1 * d2)
+    return patcor
+
+
+def calc_temporal_pat_cor(t1, t2):
+    '''
+     Calculate the Temporal Pattern Correlation
+    
+      Input::
+        t1 - 3d array of model data
+        t2 - 3d array of obs data
+         
+      Output::
+        2d array of time series pattern correlation coefficients at each grid point.
+        **Note:** std_dev is standardized on 1 degree of freedom
+    '''
+    mt1 = t1.mean(axis = 0)
+    mt2 = t2.mean(axis = 0)
+    nt = t1.shape[0]
+    sigma_t1 = t1.std(axis = 0, ddof = 1)
+    sigma_t2 = t2.std(axis = 0, ddof = 1)
+    patcor = ((((t1 - mt1) * (t2 - mt2)).sum(axis = 0)) / (nt)) / (sigma_t1 * sigma_t2)
+    
+    return patcor
+
+
+def calc_spatial_pat_cor(t1, t2):
+    '''
+    Calcualte pattern correlation between 2-D arrays.
+    6/10/2013: JK: Enforce both t1 & t2 have the identical mask before calculating std and corr
+
+    Input:
+        t1 - 2-D array of model data
+        t2 - 2-D array of observation data
+
+    Output:
+        Pattern correlation between two input arrays.
+    '''
+    import numpy as np
+    msk1 = ma.getmaskarray(t1)
+    msk2 = ma.getmaskarray(t2)
+    t1 = ma.masked_array(t1.data, np.logical_or(msk1, msk2))
+    t2 = ma.masked_array(t2.data, np.logical_or(msk1, msk2))
+    np = ma.count(t1)
+    mt1 = t1.mean()
+    mt2 = t2.mean()
+    st1 = t1.std()
+    st2 = t2.std()
+    patcor = ((t1 - mt1) * (t2 - mt2)).sum() / (np * st1 * st2)
+    return patcor
+
+
+def calc_pat_cor2D(t1, t2, nT):
+    '''
+    Calculate the pattern correlation between 3-D input arrays.
+
+    Input:
+        t1 - 3-D array of model data
+        t2 - 3-D array of observation data
+        nT
+
+    Output:
+        1-D array (time series) of pattern correlation coefficients.
+    '''
+    # TODO - Update docstring. What is nT?
+    nt = t1.shape[0]
+    if(nt != nT):
+        print 'input time levels do not match: Exit', nT, nt
+        return -1
+    # store results in list for convenience (then convert to numpy array at the end)
+    patcor = []
+    for t in xrange(nt):
+        mt1 = t1[t, :, :].mean()
+        mt2 = t2[t, :, :].mean()
+        sigma_t1 = t1[t, :, :].std()
+        sigma_t2 = t2[t, :, :].std()
+        # TODO: make means and standard deviations weighted by grid box area.
+        patcor.append((((((t1[t, :, :] - mt1) * (t2[t, :, :] - mt2)).sum()) / 
+                     (t1.shape[1] * t1.shape[2]) ) / (sigma_t1 * sigma_t2)))
+        print t, mt1.shape, mt2.shape, sigma_t1.shape, sigma_t2.shape, patcor[t]
+    # TODO: deal with missing data appropriately, i.e. mask out grid points with missing data above tolerence level
+    # convert from list into numpy array
+    patcor = numpy.array(patcor)
+    #print patcor.shape
+    return patcor
+
+def calc_pat_cor(dataset_1, dataset_2):
+    '''
+     Purpose: Calculate the Pattern Correlation Timeseries
+     Assumption(s)::  
+     	Both dataset_1 and dataset_2 are the same shape.
+        * lat, lon must match up
+        * time steps must align (i.e. months vs. months)
+     Input::
+        dataset_1 - 3d (time, lat, lon) array of data
+        dataset_2 - 3d (time, lat, lon) array of data
+     Output:
+        patcor - a 1d array (time series) of pattern correlation coefficients.
+     **Note:** Standard deviation is using 1 degree of freedom.  Debugging print 
+     statements to show the difference the n-1 makes. http://docs.scipy.org/doc/numpy/reference/generated/numpy.std.html
+     6/17/2013 JK: Add an option for a 1-d arrays
+    '''
+
+    # TODO:  Add in try block to ensure the shapes match
+
+    nDim1 = dataset_1.ndim
+    nDim2 = dataset_2.ndim
+    if nDim1 != nDim2:
+        print 'dimension mismatch in calc_pat_cor: exit', nDim1,nDim2
+        sys.exit()
+
+    if nDim1 == 1:
+        mt1 = dataset_1.mean()
+        mt2 = dataset_2.mean()
+        nt = dataset_1.shape[0]
+        sigma_t1 = dataset_1.std()
+        sigma_t2 = dataset_2.std()
+        patcor=((dataset_1 - mt1) * (dataset_2 - mt2)).sum() / (nt * sigma_t1 * sigma_t2)
+
+    elif nDim1 == 2:
+        # find mean and std_dev 
+        mt1 = dataset_1.mean()
+        mt2 = dataset_2.mean()
+        ny = dataset_1.shape[0]
+        nx = dataset_1.shape[1]
+        sigma_t1 = dataset_1.std()
+        sigma_t2 = dataset_2.std()
+        patcor=((dataset_1 - mt1) * (dataset_2 - mt2)).sum() / ((ny * nx) * (sigma_t1 * sigma_t2))
+
+    elif nDim1 == 3:
+        nt = dataset_1.shape[0]
+        ny = dataset_1.shape[1]
+        nx = dataset_1.shape[2]
+        # store results in list for convenience (then convert to numpy array)
+        patcor = []
+        for t in xrange(nt):
+            # find mean and std_dev 
+            mt1 = dataset_1[t, :, :].mean()
+            mt2 = dataset_2[t, :, :].mean()
+            sigma_t1 = dataset_1[t, :, :].std(ddof = 1)
+            sigma_t2 = dataset_2[t, :, :].std(ddof=1)
+            # TODO: make means and standard deviations weighted by grid box area.
+            # Equation from Santer_et_al 1995 
+            #     patcor = (1/(N*M_std*O_std))*sum((M_i-M_bar)*(O_i-O_bar))
+            patcor.append((((((dataset_1[t, :, :] - mt1) * (dataset_2[t, :, :] - mt2)).sum()) / (ny * nx)) / (sigma_t1 * sigma_t2)))
+            print t, mt1.shape, mt2.shape, sigma_t1.shape, sigma_t2.shape, patcor[t]
+            # TODO: deal with missing data appropriately, i.e. mask out grid points
+            # with missing data above tolerance level
+        # convert from list into numpy array
+        patcor = np.array(patcor)
+    
+    #print patcor.shape, patcor
+    return patcor
+
+
+def calc_anom_corn(dataset_1, dataset_2, climatology = None):
+    '''
+    Calculate the anomaly correlation.
+
+    Input:
+        dataset_1 - First input dataset
+        dataset_2 - Second input dataset
+        climatology - Optional climatology input array. Assumption is that it is for 
+            the same time period by default.
+
+    Output:
+        The anomaly correlation.
+    '''
+    # TODO: Update docstring with actual useful information
+
+    # store results in list for convenience (then convert to numpy array)
+    anomcor = []    
+    nt = dataset_1.shape[0]
+    #prompt for the third file, i.e. climo file...  
+    #include making sure the lat, lon and times are ok for comparision
+    # find the climo in here and then using for eg, if 100 yrs 
+    # is given for the climo file, but only looking at 10yrs
+    # ask if want to input climo dataset for use....if no, call previous 
+   
+    if climatology != None:
+        climoFileOption = raw_input('Would you like to use the full observation dataset as \
+                                     the climatology in this calculation? [y/n] \n>')
+        if climoFileOption == 'y':
+            base_dataset = climatology
+        else:
+            base_dataset = dataset_2
+    for t in xrange(nt):
+        mean_base = base_dataset[t, :, :].mean()
+        anomcor.append((((dataset_1[t, :, :] - mean_base) * (dataset_2[t, :, :] - mean_base)).sum()) / 
+                       np.sqrt(((dataset_1[t, :, :] - mean_base) ** 2).sum() * 
+                               ((dataset_2[t, :, :] - mean_base) ** 2).sum()))
+        print t, mean_base.shape, anomcor[t]
+
+    # TODO: deal with missing data appropriately, i.e. mask out grid points 
+    # with missing data above tolerence level
+    
+    # convert from list into numpy array
+    anomcor = np.array(anomcor)
+    print anomcor.shape, anomcor.ndim, anomcor
+    return anomcor
+
+
+def calc_anom_cor(t1, t2):
+    '''
+     Calculate the Anomaly Correlation (Deprecated)
+    '''
+    
+    nt = t1.shape[0]
+    
+    # store results in list for convenience (then convert to numpy 
+    # array at the end)
+    anomcor = []
+    for t in xrange(nt):
+        
+        mt2 = t2[t, :, :].mean()
+        
+        sigma_t1 = t1[t, :, :].std(ddof = 1)
+        sigma_t2 = t2[t, :, :].std(ddof = 1)
+        
+        # TODO: make means and standard deviations weighted by grid box area.
+        
+        anomcor.append(((((t1[t, :, :] - mt2) * (t2[t, :, :] - mt2)).sum()) / 
+                        (t1.shape[1] * t1.shape[2])) / (sigma_t1 * sigma_t2))
+        
+        print t, mt2.shape, sigma_t1.shape, sigma_t2.shape, anomcor[t]
+        
+        # TODO: deal with missing data appropriately, i.e. mask out grid points with 
+        #       missing data above tolerence level
+        
+    # convert from list into numpy array
+    anomcor = np.array(anomcor)
+    print anomcor.shape, anomcor.ndim, anomcor
+    return anomcor
+
+
+def calc_nash_sutcliff(dataset_1, dataset_2):
+    '''
+    Routine to calculate the Nash-Sutcliff coefficient of efficiency (E)
+    
+    Assumption(s)::  
+    	Both dataset_1 and dataset_2 are the same shape.
+        * lat, lon must match up
+        * time steps must align (i.e. months vs. months)
+    
+    Input::
+    	dataset_1 - 3d (time, lat, lon) array of data
+        dataset_2 - 3d (time, lat, lon) array of data
+    
+    Output:
+        nashcor - 1d array aligned along the time dimension of the input
+        datasets. Time Series of Nash-Sutcliff Coefficient of efficiency
+     
+     '''
+
+    nt = dataset_1.shape[0]
+    nashcor = []
+    for t in xrange(nt):
+        mean_dataset_2 = dataset_2[t, :, :].mean()
+        
+        nashcor.append(1 - ((((dataset_2[t, :, :] - dataset_1[t, :, :]) ** 2).sum()) / 
+                            ((dataset_2[t, :, :] - mean_dataset_2) ** 2).sum()))
+        
+        print t, mean_dataset_2.shape, nashcor[t]
+        
+    nashcor = np.array(nashcor)
+    print nashcor.shape, nashcor.ndim, nashcor
+    return nashcor
+
+
+def calc_pdf(dataset_1, dataset_2):
+    '''
+    Routine to calculate a normalized Probability Distribution Function with 
+    bins set according to data range.
+    Equation from Perkins et al. 2007
+
+        PS=sum(min(Z_O_i, Z_M_i)) where Z is the distribution (histogram of the data for either set)
+        called in do_rcmes_processing_sub.py
+         
+    Inputs::
+        2 arrays of data
+        t1 is the modelData and t2 is 3D obsdata - time,lat, lon NB, time here 
+        is the number of time values eg for time period 199001010000 - 199201010000 
+        
+        if annual means-opt 1, was chosen, then t2.shape = (2,lat,lon)
+        
+        if monthly means - opt 2, was choosen, then t2.shape = (24,lat,lon)
+        
+    User inputs: number of bins to use and edges (min and max)
+    Output:
+
+        one float which represents the PDF for the year
+
+    TODO:  Clean up this docstring so we have a single purpose statement
+     
+    Routine to calculate a normalised PDF with bins set according to data range.
+
+    Input::
+        2 data  arrays, modelData and obsData
+
+    Output::
+        PDF for the year
+
+    '''
+    #list to store PDFs of modelData and obsData
+    pdf_mod = []
+    pdf_obs = []
+    # float to store the final PDF similarity score
+    similarity_score = 0.0
+    d1_max = dataset_1.amax()
+    d1_min = dataset_1.amin()
+
+    print 'min modelData', dataset_1[:, :, :].min()
+    print 'max modelData', dataset_1[:, :, :].max()
+    print 'min obsData', dataset_2[:, :, :].min()
+    print 'max obsData', dataset_2[:, :, :].max()
+    # find a distribution for the entire dataset
+    #prompt the user to enter the min, max and number of bin values. 
+    # The max, min info above is to help guide the user with these choises
+    print '****PDF input values from user required **** \n'
+    nbins = int (raw_input('Please enter the number of bins to use. \n'))
+    minEdge = float(raw_input('Please enter the minimum value to use for the edge. \n'))
+    maxEdge = float(raw_input('Please enter the maximum value to use for the edge. \n'))
+    
+    mybins = np.linspace(minEdge, maxEdge, nbins)
+    print 'nbins is', nbins, 'mybins are', mybins
+    
+    
+    # TODO:  there is no 'new' kwargs for numpy.histogram 
+    # per: http://docs.scipy.org/doc/numpy/reference/generated/numpy.histogram.html
+    # PLAN: Replace new with density param.
+    pdf_mod, edges = np.histogram(dataset_1, bins = mybins, normed = True, new = True)  
+    print 'dataset_1 distribution and edges', pdf_mod, edges
+    pdf_obs, edges = np.histogram(dataset_2, bins = mybins, normed = True, new = True)           
+    print 'dataset_2 distribution and edges', pdf_obs, edges    
+    
+    # TODO: drop this
+    """
+    considering using pdf function from statistics package. It is not 
+     installed. Have to test on Mac.  
+     http://bonsai.hgc.jp/~mdehoon/software/python/Statistics/manual/index.xhtml#TOC31 
+    pdf_mod, edges = stats.pdf(dataset_1, bins=mybins)
+    print 'dataset_1 distribution and edges', pdf_mod, edges
+    pdf_obs,edges=stats.pdf(dataset_2,bins=mybins)           
+    print 'dataset_2 distribution and edges', pdf_obs, edges 
+    """
+
+    #find minimum at each bin between lists 
+    i = 0
+    for model_value in pdf_mod :
+        print 'model_value is', model_value, 'pdf_obs[', i, '] is', pdf_obs[i]
+        if model_value < pdf_obs[i]:
+            similarity_score += model_value
+        else:
+            similarity_score += pdf_obs[i] 
+        i += 1 
+    print 'similarity_score is', similarity_score
+    return similarity_score
+
+
+def calc_stdev(t1):
+    ''' 
+    Calculate the standard deviation for a given dataset.
+
+    Input:
+        t1 - Dataset to calculate the standard deviation on.
+
+    Output:
+        Array of the standard deviations for each month in the provided dataset.
+    '''
+    nt = t1.shape[0]
+    sigma_t1 = []
+    for t in xrange(nt):
+        sigma_t1.append(t1[t, :, :].std(ddof = 1))
+    sigma_t1 = np.array(sigma_t1)
+    print sigma_t1, sigma_t1.shape
+    return sigma_t1
+
+# 6/10/2013 JK: plotting routines are added below
+
+def pow_round(x):
+    '''
+     Function to round x to the nearest power of 10
+    '''
+    return 10 ** (floor(log(x, 10) - log(0.5, 10)))
+
+def calcNiceIntervals(data, nLevs):
+    '''
+    Purpose::
+        Calculates nice intervals between each color level for colorbars
+        and contour plots. The target minimum and maximum color levels are
+        calculated by taking the minimum and maximum of the distribution
+        after cutting off the tails to remove outliers.
+
+    Input::
+        data - an array of data to be plotted
+        nLevs - an int giving the target number of intervals
+
+    Output::
+        cLevs - A list of floats for the resultant colorbar levels
+    '''
+    # Find the min and max levels by cutting off the tails of the distribution
+    # This mitigates the influence of outliers
+    data = data.ravel()
+    mnLvl = mstats.scoreatpercentile(data, 5)
+    mxLvl = mstats.scoreatpercentile(data, 95)
+    locator = mpl.ticker.MaxNLocator(nLevs)
+    cLevs = locator.tick_values(mnLvl, mxLvl)
+
+    # Make sure the bounds of cLevs are reasonable since sometimes
+    # MaxNLocator gives values outside the domain of the input data
+    cLevs = cLevs[(cLevs >= mnLvl) & (cLevs <= mxLvl)]
+    return cLevs
+    
+def calcBestGridShape(nPlots, oldShape):
+    '''
+    Purpose::
+        Calculate a better grid shape in case the user enters more columns
+        and rows than needed to fit a given number of subplots.
+    
+    Input::
+        nPlots - an int giving the number of plots that will be made
+        oldShape - a tuple denoting the desired grid shape (nRows, nCols) for arranging
+                    the subplots originally requested by the user.
+   
+    Output::
+        newShape - the smallest possible subplot grid shape needed to fit nPlots
+    '''
+    nRows, nCols = oldShape
+    size = nRows * nCols
+    diff = size - nPlots
+    if diff < 0:
+        raise ValueError('gridShape=(%d, %d): Cannot fit enough subplots for data' %(nRows, nCols))
+    else:
+        # If the user enters an excessively large number of
+        # rows and columns for gridShape, automatically
+        # correct it so that it fits only as many plots
+        # as needed
+        while diff >= nCols:
+            nRows -= 1
+            size = nRows * nCols
+            diff = size - nPlots
+
+        # Don't forget to remove unnecessary columns too
+        if nRows == 1:
+            nCols = nPlots
+
+        newShape = nRows, nCols
+        return newShape
+
+def drawPortraitDiagramSingle(data, rowLabels, colLabels, cLevs, fName, fType = 'png',
+                              xLabel = '', yLabel = '', cLabel = '', pTitle = '', cMap = None):
+    '''
+    Purpose::
+        Makes a portrait diagram plot.
+        
+    Input::
+        data - 2d array of the field to be plotted
+        rowLabels - list of strings denoting labels for each row
+        colLabels - list of strings denoting labels for each column
+        cLevs - a list of integers or floats specifying the colorbar levels
+        xLabel - a string specifying the x-axis title
+        yLabel - a string specifying the y-axis title
+        cLabel - a string specifying the colorbar title
+        pTitle - a string specifying the plot title
+        fName  - a string specifying the filename of the plot
+        fType  - an optional string specifying the filetype, default is .png
+        cMap - an optional matplotlib.LinearSegmentedColormap object denoting the colormap,
+    '''
+    # Set up the colormap if not specified
+    if cMap is None:
+        cMap = plt.cm.RdBu_r
+
+    # Set up figure and axes
+    fig = plt.figure()
+    ax = fig.add_subplot(111)
+
+    # Make the portrait diagram
+    norm = mpl.colors.BoundaryNorm(cLevs, cMap.N)
+    cs = ax.matshow(data, cmap = cMap, aspect = 'auto', origin = 'lower', norm = norm)
+
+    # Add colorbar
+    cbar = fig.colorbar(cs, norm = norm, boundaries = cLevs, drawedges = True,
+                        pad = .05)
+    cbar.set_label(cLabel)
+    cbar.set_ticks(cLevs)
+    cbar.ax.xaxis.set_ticks_position("none")
+    cbar.ax.yaxis.set_ticks_position("none")
+
+    # Add grid lines
+    ax.xaxis.set_ticks(np.arange(data.shape[1] + 1))
+    ax.yaxis.set_ticks(np.arange(data.shape[0] + 1))
+    x = (ax.xaxis.get_majorticklocs() - .5)
+    y = (ax.yaxis.get_majorticklocs() - .5)
+    ax.vlines(x, y.min(), y.max())
+    ax.hlines(y, x.min(), x.max())
+
+    # Configure ticks
+    ax.xaxis.tick_bottom()
+    ax.xaxis.set_ticks_position('none')
+    ax.yaxis.set_ticks_position('none')
+    ax.set_xticklabels(rowLabels)
+    ax.set_yticklabels(colLabels)
+
+    # Add labels and title
+    ax.set_xlabel(xLabel)
+    ax.set_ylabel(yLabel)
+    ax.set_title(pTitle)
+
+    # Save the figure
+    fig.savefig('%s.%s' %(fName, fType))
+    plt.show()
+
+def drawPortraitDiagram(dataset, rowLabels, colLabels, fName, fType = 'png',
+                              gridShape = (1, 1), xLabel = '', yLabel = '', cLabel = '',
+                              pTitle = '', subTitles = None, cMap = None, cLevs = None,
+                              nLevs = 10, extend = 'neither'):
+    '''
+    Purpose::
+        Makes a portrait diagram plot.
+
+    Input::
+        dataset - 3d array of the field to be plotted (nT, nRows, nCols)
+        rowLabels - a list of strings denoting labels for each row
+        colLabels - a list of strings denoting labels for each column
+        fName - a string specifying the filename of the plot
+        fType - an optional string specifying the output filetype
+        xLabel - an optional string specifying the x-axis title
+        yLabel - an optional string specifying the y-axis title
+        cLabel - an optional string specifying the colorbar title
+        pTitle - a string specifying the plot title
+        subTitles - an optional list of strings specifying the title for each subplot
+        cMap - an optional matplotlib.LinearSegmentedColormap object denoting the colormap
+        cLevs - an optional list of ints or floats specifying colorbar levels
+        nLevs - an optional integer specifying the target number of contour levels if
+                cLevs is None
+        extend - an optional string to toggle whether to place arrows at the colorbar
+             boundaries. Default is 'neither', but can also be 'min', 'max', or
+             'both'. Will be automatically set to 'both' if cLevs is None.
+
+    '''
+    # Handle the single plot case.
+    if dataset.ndim == 2 or (dataset.ndim == 3 and dataset.shape[0] == 1):
+        dataset = dataset.reshape(1, *dataset.shape)
+
+    nPlots = dataset.shape[0]
+
+    # Make sure gridShape is compatible with input data
+    gridShape = calcBestGridShape(nPlots, gridShape)
+
+    # Row and Column labels must be consistent with the shape of
+    # the input data too
+    nRows, nCols = dataset.shape[1:]
+    if len(rowLabels) != nRows or len(colLabels) != nCols:
+        raise ValueError('rowLabels and colLabels must have %d and %d elements respectively' %(nRows, nCols))
+
+    # Set up the colormap if not specified
+    if cMap is None:
+        cMap = plt.cm.coolwarm
+
+    # Set up the figure
+    fig = plt.figure()
+    fig.set_size_inches((8.5, 11.))
+    fig.dpi = 300
+
+    # Make the subplot grid
+    grid = ImageGrid(fig, 111,
+                nrows_ncols = gridShape,
+                axes_pad = 0.4,
+                share_all = True,
+                aspect = False,
+                add_all = True,
+                ngrids = nPlots,
+                label_mode = "all",
+                cbar_mode = 'single',
+                cbar_location = 'bottom',
+                cbar_pad = '3%',
+                cbar_size = .15
+                )
+   
+    # Calculate colorbar levels if not given
+    if cLevs is None:
+        # Cut off the tails of the distribution
+        # for more representative colorbar levels
+        cLevs = calcNiceIntervals(dataset, nLevs)
+        extend = 'both'
+
+    norm = mpl.colors.BoundaryNorm(cLevs, cMap.N)
+
+    # Do the plotting
+    for i, ax in enumerate(grid):
+        data = dataset[i]
+        cs = ax.matshow(data, cmap = cMap, aspect = 'auto', origin = 'lower', norm = norm)
+
+        # Add grid lines
+        ax.xaxis.set_ticks(np.arange(data.shape[1] + 1))
+        ax.yaxis.set_ticks(np.arange(data.shape[0] + 1))
+        x = (ax.xaxis.get_majorticklocs() - .5)
+        y = (ax.yaxis.get_majorticklocs() - .5)
+        ax.vlines(x, y.min(), y.max())
+        ax.hlines(y, x.min(), x.max())
+
+        # Configure ticks
+        ax.xaxis.tick_bottom()
+        ax.xaxis.set_ticks_position('none')
+        ax.yaxis.set_ticks_position('none')
+        ax.set_xticklabels(colLabels, fontsize = 'xx-small')
+        ax.set_yticklabels(rowLabels, fontsize = 'xx-small')
+
+        # Add axes title
+        if subTitles is not None:
+            ax.text(0.5, 1.04, subTitles[i], va = 'center', ha = 'center',
+                    transform = ax.transAxes, fontsize = 'small')
+
+    # Add colorbar
+    cbar = fig.colorbar(cs, cax = ax.cax, norm = norm, boundaries = cLevs, drawedges = True,
+                        extend = extend, orientation = 'horizontal')
+    cbar.set_label(cLabel)
+    cbar.set_ticks(cLevs)
+    cbar.ax.xaxis.set_ticks_position("none")
+    cbar.ax.yaxis.set_ticks_position("none")
+
+    # This is an ugly hack to make the title show up at the correct height.
+    # Basically save the figure once to achieve tight layout and calculate
+    # the adjusted heights of the axes, then draw the title slightly above
+    # that height and save the figure again
+    fig.savefig('%s.%s' %(fName, fType), bbox_inches = 'tight', dpi = fig.dpi)
+    ymax = 0
+    for ax in grid:
+        bbox = ax.get_position()
+        ymax = max(ymax, bbox.ymax)
+
+    # Add figure title and axes labels
+    fig.text(.51, .14, yLabel, va = 'center', ha = 'center', rotation = 'horizontal')
+    fig.text(.08, .53, xLabel, va = 'center', ha = 'center', rotation = 'vertical')
+    fig.suptitle(pTitle, y = ymax + .04, fontsize = 16)
+    fig.savefig('%s.%s' %(fName, fType), bbox_inches = 'tight', dpi = fig.dpi)
+    plt.show()
+    fig.clf()
+
+def taylorDiagram(pltDat, pltTit, pltFileName, refName, legendPos, radMax):
+    '''
+    Draw a Taylor diagram
+    '''
+    stdref = 1.                     # Standard reference value 
+    rect = 111                      # Subplot setting and location
+    markerSize = 6
+    fig = plt.figure()
+    fig.suptitle(pltTit)            # PLot title
+    dia = TaylorDiagram (stdref, fig = fig, radMax = radMax, rect = rect, label = refName)
+    for i,(stddev,corrcoef,name) in enumerate(pltDat):
+        dia.add_sample (stddev, corrcoef, marker = '$%d$' % (i+1), ms = markerSize, label=name)
+    # Add ploylines to mark a range specified by input data - 2 be implemented
+    #circular_line = dia.add_stddev_contours(0.959, 1, 0.965)
+    #circular_line = dia.add_stddev_contours(1.1, 1, 0.973)
+    #straight_line = dia.add_contours(0.959, 1, 1.1, 1)
+    #straight_line = dia.add_contours(0.959, 0.965, 1.1, 0.973)
+    #l=fig.legend (dia.samplePoints, [p.get_label() for p in dia.samplePoints ], handlelength=0., prop={'size':10}, numpoints=1, loc=legendPos)
+    # loc: 1='upper right', 2='upper left' or specified in the calling program via "legendPos"
+    l = fig.legend (dia.samplePoints, [p.get_label() for p in dia.samplePoints ], handlelength=0., prop={'size':10}, numpoints=1, loc=legendPos)
+    l.draw_frame(False)
+    plt.savefig(pltFileName)
+    plt.show()
+    pltDat = 0.
+
+def drawTimeSeriesSingle(dataset, times, labels, fName, fType = 'png', xLabel = '', yLabel ='', pTitle ='',
+                   legendPos = 'upper center', legendFrameOn = False, yearLabels = True, yscale = 'linear'):
+    '''
+    Purpose::
+        Function to draw a time series plot
+
+    Input::
+        dataset - a list of arrays for each dataset as a time series
+        times - a list of python datetime objects
+        labels - a list of strings with the names of each dataset
+        fName - a string specifying the filename of the plot
+        fType - an optional string specifying the output filetype
+        xLabel - a string specifying the x-axis title
+        yLabel - a string specifying the y-axis title
+        pTitle - a string specifying the plot title
+        legendPos - an optional string or tuple of float for determining
+                    the position of the legend
+        legendFrameOn - optional bool to toggle drawing the frame around
+                        the legend
+        yearLabels - optional bool to toggle drawing year labels on the x-xaxis
+        yscale - optional string for setting the y-axis scale, 'linear' for linear
+                 and 'log' for log base 10.
+    '''
+    fig = plt.figure()
+    ax = fig.add_subplot(111)
+
+    if not yearLabels:
+        xfmt = mpl.dates.DateFormatter('%b')
+        ax.xaxis.set_major_formatter(xfmt)
+
+    ax.set_xlabel(xLabel)
+    ax.set_ylabel(yLabel)
+    ax.set_title(pTitle)
+
+    # Set up list of lines for legend
+    lines = []
+    ymin, ymax = 0, 0
+
+    # Plot each dataset
+    for data in dataset:
+        line = ax.plot_date(times, data, '', linewidth = 2)
+        lines.extend(line)
+        cmin, cmax = data.min(), data.max()
+        if ymin > cmin:
+            ymin = cmin
+        if ymax < cmax:
+            ymax = cmax
+
+    # Add a bit of padding so lines don't touch bottom and top of the plot
+    ymin = ymin - ((ymax - ymin) * 0.1)
+    ymax = ymax + ((ymax - ymin) * 0.1)
+    ax.set_ylim((ymin, ymax))
+
+    # Set the y-axis scale
+    ax.set_yscale(yscale)
+
+    # Create the legend
+    ax.legend((lines), labels, loc = legendPos, ncol = 10, fontsize='x-small',
+                       frameon=legendFrameOn)
+    fig.savefig('%s.%s' %(fName, fType), bbox_inches = 'tight')
+    plt.show()
+    fig.clf()
+
+
+def pltXY(x, y, lineLabel, lineTyp, pltTit, xLabel, yLabel, pltName, xmin, xmax, deltaX, ymin, ymax, deltaY, legendPos, xScale, yScale):
+    """
+    The default drawing order for axes is patches, lines, text.This order is determined by the zorder attribute. The following defaults are set:
+    Artist                      Z-order
+    Patch / PatchCollection      1
+    Line2D / LineCollection      2
+    Text                         3
+    You can change the order for individual artists by setting the zorder.  Any individual plot() call can set a value
+      for the zorder of that particular item.
+    In the fist subplot below, the lines are drawn above the patch collection from the scatter, which is the default.
+    In the subplot below, the order is reversed.
+    The second figure shows how to control the zorder of individual lines.
+    Arguments
+      x (nX)   : np array: the number of points in the x axis
+      y (nX,nY): np array: the number of y values to be plotted
+      lineLabel: list(nY): labels for individual y data
+      pltTit   : Text    : plot title
+      xLabel   : Text    : x-axis label
+      yLabel   : Text    : y-axis label
+      pltName  : Text    : name of the plot file
+    3/28/2013 Jinwon Kim: Modification of a routine in the matplotlib gallery
+    """
+    #lineColors = ['k', 'b', 'r', 'g', 'c', 'm', 'y', '0.5', '0.55', '0.6', '0.65', '0.7', '0.75', '0.8', '0.85', '0.9', '0.95', '1.0']
+    lineColors = ['k','r','y','g','b','c','m','k','r','y','g','b','c','m','k','r','y','g','b','c','m','0.35','0.5','0.65','0.8','.95']
+    nX = x.size
+    nY = len(lineLabel)
+    lineColors[nY - 1] = 'b'
+    fig = plt.figure()
+    ax = fig.add_subplot(1,1,1)
+    for n in np.arange(nY):
+        if n <= 6:
+            opacity=1.
+        elif n <= 13:
+            opacity = .75
+        elif n <= 20:
+            opacity = .40
+        plot(x,y[n, :], linewidth=1, alpha=opacity, color=lineColors[n], linestyle=lineTyp[n], label=lineLabel[n], zorder = 10)
+    xlabel(xLabel,fontsize=10); ylabel(yLabel,fontsize=10)
+    if xmax > xmin:
+        plt.xlim(xmin,xmax)
+        ticks = frange(xmin,xmax,npts=(xmax-xmin)/deltaX+1)
+        ax.xaxis.set_ticks(ticks,minor=False)
+    if ymax > ymin:
+        plt.ylim(ymin,ymax)
+        ticks = frange(ymin,ymax,npts=(ymax-ymin)/deltaY+1)
+        ax.yaxis.set_ticks(ticks,minor=False)
+    ax.set_title(pltTit)
+    ax.xaxis.tick_bottom(); ax.yaxis.tick_left()    # put tick marks only on the left (for y) and bottom (for x) axis
+    if xScale == 'log':
+        ax.set_xscale('log')
+    else:
+        ax.set_xscale('linear')
+    if yScale == 'log':
+        ax.set_yscale('log')
+    else:
+        ax.set_yscale('linear')
+    if(nY>1):
+        l = legend(prop={'size':10},loc='best')
+        l.set_zorder(20) # put the legend on top
+    plt.savefig(pltName)
+    show()
+    # release work arrays
+    x=0.; y=0.
+
+
+def pltSca1F(x, y, pltName, xLabel, yLabel, pmin, pmax, delP, pTit, pFname, xScale, yScale):
+    #*************************************#
+    # Plot a single-frame scatter diagram #
+    #*************************************#
+    fig = plt.figure(); ax = fig.add_subplot(1,1,1)
+    lTyp='o'
+    plot(x,y,lTyp,c='r')
+    if pmax > pmin:
+        ticks = frange(pmin,pmax,npts=(pmax-pmin)/delP+1)
+        plt.xlim(pmin,pmax); ax.xaxis.set_ticks(ticks,minor=False)
+        plt.ylim(pmin,pmax); ax.yaxis.set_ticks(ticks,minor=False)
+    ax.set_title(pTit)
+    if xScale == 'log':
+        ax.set_xscale('log')
+    else:
+        ax.set_xscale('linear')
+    if yScale == 'log':
+        ax.set_yscale('log')
+    else:
+        ax.set_yscale('linear')
+    xlabel(xLabel,fontsize=10); ylabel(yLabel,fontsize=10)
+    l = legend(prop={'size':8},loc='best')
+    l.set_zorder(20)
+    plt.savefig(pFname)
+    show()
+    x=0.; y=0.
+
+
+def pltSca6F(x, dName, pmin, pmax, delP, pTitle, pFname, xScale, yScale):
+    #****************************************************#
+    # Plot up to 6 frames (6 rows X 2 columns) on a page #
+    #****************************************************#
+    nPlt = x.shape[0]
+    if pmax > pmin:
+        ticks = frange(pmin,pmax,npts=(pmax-pmin)/delP+1)
+    if nPlt > 6:
+        print 'frames exceed 12: return'
+        return
+    nrows = 3; ncols = 2; npmax = nrows*ncols; lTyp='o'; xlabcol='black'; ylabcol='green'
+    fig = plt.figure()
+    plt.subplots_adjust(hspace=0.3, wspace=0.2)
+    for n in range(1,nPlt):
+        pid = n % npmax
+        if pid == 0:
+            pid = npmax
+        ax = fig.add_subplot(nrows,ncols,pid)
+        #ax.set_title(pTitle[n-1],fontsize=6)
+        if xScale == 'log':
+            ax.set_xscale('log')
+        else:
+            ax.set_xscale('linear')
+        if yScale == 'log':
+            ax.set_yscale('log')
+        else:
+            ax.set_yscale('linear')
+        plot(x[0,:],x[n,:],lTyp,label=pTitle[n-1],c='r')
+        plot(x[0,:],x[n,:],lTyp,c='r')
+        plot(frange(pmin,pmax),c='b')
+        l = legend(prop={'size':8},loc='best')
+        l.set_zorder(20)
+        xlabel(dName[0],fontsize=10); ylabel(dName[n],fontsize=10)
+        if pmax > pmin:
+            plt.xlim(pmin,pmax); ax.xaxis.set_ticks(ticks,minor=False)
+            plt.ylim(pmin,pmax); ax.yaxis.set_ticks(ticks,minor=False)
+        for label in ax.xaxis.get_ticklabels():
+            label.set_color(xlabcol)
+            label.set_rotation(0)
+            label.set_fontsize(8)
+        for label in ax.yaxis.get_ticklabels():
+            label.set_color(ylabcol)
+            label.set_rotation(0)
+            label.set_fontsize(8)
+    plt.savefig(pFname)
+    show()
+    x=0.
+
+def drawContourMapSingle(data, lats, lons, cLevs, fName, fType = 'png',
+                         cLabel = '', pTitle = '', cMap = None, nParallels = 5, nMeridians = 5):
+    '''
+    Purpose::
+        Plots a filled contour map.
+    Input::
+        data - 2d array of the field to be plotted with shape (nLon, nLat)
+        lats - array of latitudes 
+        lons - array of longitudes
+        cLevs - A list of ints or floats specifying contour levels
+        fName  - a string specifying the filename of the plot
+        fType  - an optional string specifying the filetype, default is .png
+        cLabel - an optional string specifying the colorbar title
+        pTitle - an optional string specifying plot title
+        cMap - an optional matplotlib.LinearSegmentedColormap object denoting the colormap
+        nParallels - an optional int for the number of parallels to draw
+        nMeridians - an optional int for the number of meridians to draw        
+    '''
+    # Set up the colormap if not specified
+    if cMap is None:
+        cMap = plt.cm.RdBu_r
+
+    # Set up the figure
+    fig = plt.figure()
+    ax = fig.add_subplot(111)
+
+    # Determine the map boundaries and construct a Basemap object
+    lonMin = lons.min()
+    lonMax = lons.max()
+    latMin = lats.min()
+    latMax = lats.max()
+    m = Basemap(projection = 'cyl', llcrnrlat = latMin, urcrnrlat = latMax,
+                llcrnrlon = lonMin, urcrnrlon = lonMax, resolution = 'l', ax = ax)
+
+    # Draw the borders for coastlines and countries
+    m.drawcoastlines(linewidth = 1)
+    m.drawcountries(linewidth = .75)
+
+    # Draw parallels / meridians.
+    m.drawmeridians(np.linspace(lonMin, lonMax, nMeridians), labels = [0, 0, 0, 1])
+    m.drawparallels(np.linspace(latMin, latMax, nMeridians), labels = [1, 0, 0, 1])
+
+    # Convert lats and lons to projection coordinates
+    if lats.ndim == 1 and lons.ndim == 1:
+        lons, lats = np.meshgrid(lons, lats)
+    x, y = m(lons, lats)
+
+    # Plot data with filled contours
+    cs = m.contourf(x, y, data, cmap = cMap, levels = cLevs)
+
+    # Add colorbar
+    cbar = m.colorbar(cs, drawedges = True, pad = '2%', size = '3%')
+    cbar.set_label(cLabel)
+    cbar.set_ticks(cLevs)
+    cbar.ax.xaxis.set_ticks_position("none")
+    cbar.ax.yaxis.set_ticks_position("none")
+
+    # Add title and save the figure
+    ax.set_title(pTitle)
+    fig.savefig('%s.%s' %(fName, fType))
+    show()
+
+def drawCntrMap(data,lon,lat,titles,ncols,pFname):
+    '''
+    This routine is based on PyNGL, i.e., NcarGraphics
+    data - a masked numpy array of data to plot (nT,nY,nX)
+    lon - longitude (nY,nX)
+    lat - latitude  (nY,nX)
+    titles - array of titles (nT)
+    nrows - number of rows of the paneled plots
+    ncols - number of columns of the paneled plots
+    nT = nrows * ncols
+    pFname - name of output postscript file
+    '''
+    wks_type = 'ps'
+    if data.ndim == 2:
+        nT = 1; nrows = 1; ncols = 1
+    elif data.ndim == 3:
+        nT=data.shape[0]
+        if nT % ncols == 0:
+            nrows = nT/ncols
+        else:
+            nrows = nT/ncols + 1
+    # set workstation type (X11, ps, png)
+    res = Ngl.Resources()
+    wks = Ngl.open_wks(wks_type,pFname,res)
+    # set plot resource paramters
+    resources = Ngl.Resources()
+    resources.mpLimitMode = "LatLon"    # Limit the map view.
+    resources.mpMinLonF   = lon.min()
+    resources.mpMaxLonF   = lon.max()
+    resources.mpMinLatF   = lat.min()
+    resources.mpMaxLatF   = lat.max()
+    resources.cnFillOn      = True
+    resources.cnLineLabelsOn        = False    # Turn off line labels.
+    resources.cnInfoLabelOn         = False    # Turn off info label.
+    resources.cnLinesOn             = False    # Turn off countour line (only filled colors)
+    resources.sfXArray              = lon[:,:]
+    resources.sfYArray              = lat[:,:]
+    resources.pmTickMarkDisplayMode = "Never"  # Turn off map tickmarks.
+    resources.mpOutlineBoundarySets = "GeophysicalAndUSStates"
+    resources.mpGeophysicalLineColor = "red"
+    resources.mpUSStateLineColor = "red"
+    resources.mpGeophysicalLineThicknessF = 0.75
+    resources.mpUSStateLineThicknessF = 0.75
+    resources.mpPerimOn             = True     # Turn on/off map perimeter
+    resources.mpGridAndLimbOn = True           # Turn off map grid.
+    resources.nglFrame = False    # Don't advance the frame
+    resources.nglDraw = False
+    plot=[]
+    for iT in np.arange(nT):
+        resources.tiMainString = titles[iT]
+        #resources.pmLabelBarDisplayMode = "Never" # Turn off individual label bars
+        resources.pmLabelBarDisplayMode = "Always" # Turn on individual label bars
+        if data.ndim == 3:
+            plot.append(Ngl.contour_map(wks,data[iT,:,:],resources))
+        elif data.ndim == 2:
+            plot.append(Ngl.contour_map(wks,data[:,:],resources))
+    panelres = Ngl.Resources()
+    panelres.nglPanelTop=0.95
+    panelres.nglPanelBottom=0.05
+    panelres.nglPanelLabelBar                 = False   # Turn on panel labelbar
+    panelres.nglPanelLabelBarLabelFontHeightF = 0.012  # Labelbar font height
+    panelres.nglPanelLabelBarHeightF          = 0.03   # Height of labelbar
+    panelres.nglPanelLabelBarWidthF           = 0.8    # Width of labelbar
+    panelres.lbLabelFont                      = "helvetica-bold" # Labelbar font
+    Ngl.panel(wks,plot[0:nT],[nrows,ncols],panelres)
+    Ngl.destroy(wks)
+    del plot
+    del resources
+    del wks
+    return
+
+def drawContourMap(dataset, lats, lons, fName, fType = 'png', gridShape = (1, 1),
+                      cLabel = '', pTitle = '', subTitles = None, cMap = None,
+                      cLevs = None, nLevs = 10, parallels = None, meridians = None,
+                      extend = 'neither'):
+    '''
+    Purpose::
+        Create a multiple panel contour map plot.
+    Input::
+        dataset -  3d array of the field to be plotted with shape (nT, nLon, nLat)
+        lats - array of latitudes
+        lons - array of longitudes
+        fName  - a string specifying the filename of the plot
+        fType  - an optional string specifying the filetype, default is .png
+        gridShape - optional tuple denoting the desired grid shape (nRows, nCols) for arranging
+                    the subplots.
+        cLabel - an optional string specifying the colorbar title
+        pTitle - an optional string specifying plot title
+        subTitles - an optional list of strings specifying the title for each subplot
+        cMap - an optional matplotlib.LinearSegmentedColormap object denoting the colormap
+        cLevs - an optional list of ints or floats specifying contour levels
+        nLevs - an optional integer specifying the target number of contour levels if
+                cLevs is None
+        parallels - an optional list of ints or floats for the parallels to be drawn
+        meridians - an optional list of ints or floats for the meridians to be drawn
+        extend - an optional string to toggle whether to place arrows at the colorbar
+                 boundaries. Default is 'neither', but can also be 'min', 'max', or
+                 'both'. Will be automatically set to 'both' if cLevs is None.
+    '''
+    # Handle the single plot case. Meridians and Parallels are not labeled for
+    # multiple plots to save space.
+    if dataset.ndim == 2 or (dataset.ndim == 3 and dataset.shape[0] == 1):
+        if dataset.ndim == 2:
+            dataset = dataset.reshape(1, *dataset.shape)
+        nPlots = 1
+        mLabels = [0, 0, 0, 1]
+        pLabels = [1, 0, 0, 1]
+    else:
+        nPlots = dataset.shape[0]
+        mLabels = [0, 0, 0, 0]
+        pLabels = [0, 0, 0, 0]
+
+    # Make sure gridShape is compatible with input data
+    gridShape = calcBestGridShape(nPlots, gridShape)
+
+    # Set up the colormap if not specified
+    if cMap is None:
+        cMap = plt.cm.coolwarm
+
+    # Set up the figure
+    fig = plt.figure()
+    #fig.set_size_inches((8.5, 11.))
+    #fig.dpi = 600
+
+    # Make the subplot grid
+    grid = ImageGrid(fig, 111,
+                nrows_ncols = gridShape,
+                axes_pad = 0.3,
+                share_all = True,
+                add_all = True,
+                ngrids = nPlots,
+                label_mode = "L",
+                cbar_mode = 'single',
+                cbar_location = 'bottom',
+                cbar_pad = '0%'
+                )
+
+    # Determine the map boundaries and construct a Basemap object
+    lonMin = lons.min()
+    lonMax = lons.max()
+    latMin = lats.min()
+    latMax = lats.max()
+    m = Basemap(projection = 'cyl', llcrnrlat = latMin, urcrnrlat = latMax,
+                llcrnrlon = lonMin, urcrnrlon = lonMax, resolution = 'l')
+
+    # Convert lats and lons to projection coordinates
+    if lats.ndim == 1 and lons.ndim == 1:
+        lons, lats = np.meshgrid(lons, lats)
+
+    # Calculate contour levels if not given
+    if cLevs is None:
+        # Cut off the tails of the distribution
+        # for more representative contour levels
+        cLevs = calcNiceIntervals(dataset, nLevs)
+    extend = 'both'
+
+    # Create default meridians and parallels
+    if meridians is None:
+        meridians = np.arange(-180, 181, 15)
+    if parallels is None:
+        parallels = np.arange(-90, 91, 15)
+
+    x, y = m(lons, lats)
+    for i, ax in enumerate(grid):
+        # Load the data to be plotted
+        data = dataset[i]
+        m.ax = ax
+
+        # Draw the borders for coastlines and countries
+        m.drawcoastlines(linewidth = 1)
+        m.drawcountries(linewidth = .75)
+
+        # Draw parallels / meridians
+        m.drawmeridians(meridians, labels = mLabels, linewidth = .75)
+        m.drawparallels(parallels, labels = pLabels, linewidth = .75)
+
+        # Draw filled contours
+        cs = m.contourf(x, y, data, cmap = cMap, levels = cLevs, extend = extend)
+
+        # Add title
+        if subTitles is not None:
+            ax.set_title(subTitles[i], fontsize = 'small')
+
+
+    # Add colorbar
+    cbar = fig.colorbar(cs, cax = ax.cax, drawedges = True, orientation = 'horizontal',
+                        extendfrac = 'auto')
+    cbar.set_label(cLabel)
+    cbar.set_ticks(cLevs)
+    cbar.ax.xaxis.set_ticks_position("none")
+    cbar.ax.yaxis.set_ticks_position("none")
+
+    # This is an ugly hack to make the title show up at the correct height.
+    # Basically save the figure once to achieve tight layout and calculate
+    # the adjusted heights of the axes, then draw the title slightly above
+    # that height and save the figure again
+    fig.savefig('%s.%s' %(fName, fType), bbox_inches = 'tight', dpi = fig.dpi)
+    ymax = 0
+    for ax in grid:
+        bbox = ax.get_position()
+        ymax = max(ymax, bbox.ymax)
+
+    # Add figure title
+    fig.suptitle(pTitle, y = ymax + .04, fontsize = 16)
+    fig.savefig('%s.%s' %(fName, fType), bbox_inches = 'tight', dpi = fig.dpi)
+    plt.show()
+    fig.clf()
+
+def drawSubRegions(subRegions, lats, lons, fName, fType = 'png', pTitle = '',
+                    parallels = None, meridians = None, subRegionMasks = None):
+    '''
+    Purpose::
+        Function to draw subregion domain(s) on a map
+    
+    Input::
+            subRegions - a list of subRegion objects
+        lats - array of latitudes
+        lons - array of longitudes
+        fName  - a string specifying the filename of the plot
+        fType  - an optional string specifying the filetype, default is .png
+        pTitle - an optional string specifying plot title
+        parallels - an optional list of ints or floats for the parallels to be drawn
+        meridians - an optional list of ints or floats for the meridians to be drawn
+        subRegionMasks - optional dictionary of boolean arrays for each subRegion
+                         for giving finer control of the domain to be drawn, by default
+                         the entire domain is drawn.
+    '''
+    # Set up the figure
+    fig = plt.figure()
+    fig.set_size_inches((8.5, 11.))
+    fig.dpi = 300
+    ax = fig.add_subplot(111)
+   
+    # Determine the map boundaries and construct a Basemap object
+    lonMin = lons.min()
+    lonMax = lons.max()
+    latMin = lats.min()
+    latMax = lats.max()
+    m = Basemap(projection = 'cyl', llcrnrlat = latMin, urcrnrlat = latMax,
+                llcrnrlon = lonMin, urcrnrlon = lonMax, resolution = 'l', ax = ax)
+   
+    # Draw the borders for coastlines and countries
+    m.drawcoastlines(linewidth = 1)
+    m.drawcountries(linewidth = .75)
+    m.drawstates()
+
+    # Create default meridians and parallels
+    if meridians is None:
+        meridians = np.arange(-180, 181, 15)
+    if parallels is None:
+        parallels = np.arange(-90, 91, 15)
+
+    # Draw parallels / meridians
+    m.drawmeridians(meridians, labels = [0, 0, 0, 1], linewidth = .75)
+    m.drawparallels(parallels, labels = [1, 0, 0, 1], linewidth = .75)
+
+    # Set up the color scaling
+    cMap = plt.cm.jet
+    norm = mpl.colors.BoundaryNorm(np.arange(1, len(subRegions) + 3), cMap.N)
+
+    # Process the subregions
+    for i, reg in enumerate(subRegions):
+        if subRegionMasks is not None and reg.name in subRegionMasks.keys():
+            domain = (i + 1) * subRegionMasks[reg.name]
+        else:
+            domain = (i + 1) * np.ones((2, 2))
+
+        nLats, nLons = domain.shape
+        domain = ma.masked_equal(domain, 0)
+        regLats = np.linspace(reg.latMin, reg.latMax, nLats)
+        regLons = np.linspace(reg.lonMin, reg.lonMax, nLons)
+        regLons, regLats = np.meshgrid(regLons, regLats)
+
+        # Convert to to projection coordinates. Not really necessary
+        # for cylindrical projections but keeping it here in case we need
+        # support for other projections.
+        x, y = m(regLons, regLats)
+
+        # Draw the subregion domain
+        m.pcolormesh(x, y, domain, cmap = cMap, norm = norm, alpha = .5)
+
+        # Label the subregion
+        xm, ym = x.mean(), y.mean()
+        m.plot(xm, ym, marker = '$%s$' %(reg.name), markersize = 12, color = 'k')
+
+    # Add the the title
+    ax.set_title(pTitle)
+
+    # Save the figure
+    fig.savefig('%s.%s' %(fName, fType), bbox_inches = 'tight', dpi = fig.dpi)
+    show()
+    fig.clf()
+
+def metrics_plots(varName, numOBS, numMDL, nT, ngrdY, ngrdX, Times, lons, lats, allData, dataList, workdir, subRegions, timeStep, fileOutputOption):
+    '''
+    Calculate evaluation metrics and generate plots.
+    '''
+    ##################################################################################################################
+    # Routine to compute evaluation metrics and generate plots
+    #    (1)  metric calculation
+    #    (2) plot production
+    #    Input: 
+    #        numOBS           - the number of obs data. either 1 or >2 as obs ensemble is added for multi-obs cases
+    #        numMDL           - the number of mdl data. either 1 or >2 as obs ensemble is added for multi-mdl cases
+    #        nT               - the length of the data in the time dimension
+    #        ngrdY            - the length of the data in Y dimension
+    #        ngrdX            - the length of the data in the X dimension
+    #        Times            - time stamps
+    #        lons,lats        - longitude & latitude values of the data domain (same for model & obs)
+    #        allData          - the sum of the observed and model data (combines obsData & mdlData in the old code)
+    #        dataList         - the list of data names (combines obsList and mdlList in the old code)
+    #        workdir        - string describing the directory path for storing results and plots
+    #        subRegions        - list of SubRegion Objects or False
+    #        fileOutputOption - option to write regridded data in a netCDF file or not
+    #    Output: image files of plots + possibly data
+    #******************************************************
+    # JK2.0: Only the data interpolated temporally and spatially onto the analysis grid 
+    #        are transferred into this routine. The rest of processing (e.g., area-averaging, etc.) 
+    #        are to be performed in this routine. Do not overwrite obsData[numOBs,nt,ngrdY,ngrdX] & 
+    #        mdlData[numMDL,nt,ngrdY,ngrdX]. These are the raw, re-gridded data to be used repeatedly 
+    #        for multiple evaluation steps as desired by an evaluator
+    # JK2.1: The observed and model data are unified in a single variable for ease of processing
+    ##################################################################################################################
+
+    print ''
+    print 'Start metrics.py'
+    print ''
+    # JK2.1: define the variable to represent the total number of combined (obs + model) datasets
+    numDatasets = numOBS + numMDL
+
+    #####################################################################################################
+    # JK2.0: Compute evaluation metrics and plots to visualize the results
+    #####################################################################################################
+    # (mp.001) Sub-regions for local timeseries analysis
+    #--------------------------------
+    # Enter the location of the subrgns via screen input of data; 
+    # modify this to add an option to read-in from data file(s)
+    #----------------------------------------------------------------------------------------------------
+    if subRegions:
+        numSubRgn = len(subRegions)
+        subRgnName = [ x.name   for x in subRegions ]
+        subRgnLon0 = [ x.lonMin for x in subRegions ]
+        subRgnLon1 = [ x.lonMax for x in subRegions ]
+        subRgnLat0 = [ x.latMin for x in subRegions ]
+        subRgnLat1 = [ x.latMax for x in subRegions ]
+    else:
+        print ''
+        ans = raw_input('Calculate area-mean timeseries for subregions? y/n: [n] \n')
+        print ''
+        if ans == 'y':
+            ans = raw_input('Input subregion info interactively? y/n: \n> ')
+            if ans == 'y':
+                numSubRgn, subRgnName, subRgnLon0, subRgnLon1, subRgnLat0, subRgnLat1 = misc.assign_subRgns_interactively()
+            else:
+                print 'Read subregion info from a pre-fabricated text file'
+                ans = raw_input('Read from a defaule file (workdir + "/sub_regions.txt")? y/n: \n> ')
+                if ans == 'y':
+                    subRgnFileName = workdir + "/sub_regions.txt"
+                else:
+                    subRgnFileName = raw_input('Enter the subRgnFileName to read from \n')
+                print 'subRgnFileName ', subRgnFileName
+                numSubRgn, subRgnName, subRgnLon0, subRgnLon1, subRgnLat0, subRgnLat1 = misc.assign_subRgns_from_a_text_file(subRgnFileName)
+            print subRgnName, subRgnLon0, subRgnLon1, subRgnLat0, subRgnLat1
+        else:
+            numSubRgn = 0
+    # compute the area-mean timeseries for all subregions if subregion(s) are defined.
+    #   the number of subregions is usually small and memory usage is usually not a concern
+    dataRgn = np.zeros((numDatasets, numSubRgn, nT))
+            
+    if subRegions:        
+        print 'Enter area-averaging: allData.shape ', allData.shape
+        print 'Using Latitude/Longitude Mask for Area Averaging'  
+        for n in np.arange(numSubRgn):
+            # Define mask using regular lat/lon box specified by users ('mask=True' defines the area to be excluded)
+            maskLonMin = subRegions[n].lonMin 
+            if maskLonMin > 180.:
+                maskLonMin = maskLonMin - 360.
+            maskLonMax = subRegions[n].lonMax
+            if maskLonMax > 180.:
+                maskLonMax = maskLonMax - 360.
+            maskLatMin = subRegions[n].latMin
+            maskLatMax = subRegions[n].latMax
+            mask = np.logical_or(np.logical_or(lats <= maskLatMin, lats >= maskLatMax), 
+                                 np.logical_or(lons <= maskLonMin, lons >= maskLonMax))
+            
+            # Calculate area-weighted averages within this region and store in a new list
+            for k in np.arange(numDatasets):           #JK2.1: area-average all data
+                Store = []
+                for t in np.arange(nT):
+                    Store.append(process.calc_area_mean(allData[k, t, :, :], lats, lons, mymask = mask))
+                dataRgn[k, n, :] = ma.array(Store[:])
+            Store = []                               # release the memory allocated by temporary vars
+
+    #-------------------------------------------------------------------------
+    # (mp.002) fileOutputOption: The option to create a binary or netCDF file of processed 
+    #                      (re-gridded and regionally-averaged) data for user-specific processing. 
+    #                      This option is useful for advanced users who need more than
+    #                      the metrics and vidualization provided in the basic package.
+    #----------------------------------------------------------------------------------------------------
+    print ''
+    if not fileOutputOption:
+        while fileOutputOption not in ['no', 'nc']:
+            fileOutputOption = raw_input('Option for output files of obs/model data: Enter no/nc \
+                                for no, netCDF file \n> ').lower()
+    print ''
+
+    # write a netCDF file for post-processing if desired. JK21: binary output option has been completely eliminated
+    if fileOutputOption == 'nc':
+        fileName = '%s/%s_Tseries.nc' % (workdir, varName)
+        tempName = fileName 
+        if(os.path.exists(tempName) == True):
+            print "removing %s from the local filesystem, so it can be replaced..." % (tempName,)
+            cmnd = 'rm -f ' + tempName
+            subprocess.call(cmnd, shell=True)
+        #files.writeNCfile1(fileName, numSubRgn, lons, lats, allData, dataRgn, dataList, subRegions)
+        files.writeNCfile1(fileName, numDatasets, numOBS, numMDL, numSubRgn, lons, lats, allData, dataRgn, dataList, subRegions)
+        print 'The regridded obs and model data are written in the netCDF file ', fileName
+
+    #####################################################################################################
+    ###################### Metrics calculation and plotting cycle starts from here ######################
+    #####################################################################################################
+    print ''
+    print 'OBS and MDL data have been prepared for the evaluation step'
+    print ''
+    doMetricsOption = raw_input('Want to calculate metrics and plot them? [y/n]\n> ').lower()
+    if doMetricsOption == 'y':
+        # Assign the variable name and unit to be used in plots
+        print 'The variable to be processed is ',timeStep,' ',varName
+        pltVarName = raw_input('Enter the variable name to appear in the plot\n> ')
+        pltVarUnit = raw_input('Enter the variable unit to appear in the plot\n> ')
+    print ''
+
+    ####################################################
+    # Terminate job if no metrics are to be calculated #
+    ####################################################
+
+    neval = 0
+
+    while doMetricsOption == 'y':
+        neval += 1
+        print ' '
+        print 'neval= ', neval
+        print ' '
+        #--------------------------------
+        # (mp.003) Preparation
+        #----------------------------------------------------------------------------------------------------
+        # Determine info on years (the years in the record [YR] and its number[numYR])
+        yy = ma.zeros(nT, 'i')
+        for n in np.arange(nT):
+            yy[n] = Times[n].strftime("%Y")
+        YR = np.unique(yy)
+        yy = 0
+        nYR = len(YR)
+        print 'nYR, YR = ', nYR, YR
+
+        # Select the eval domain: over the entire domain (spatial distrib) or regional time series
+        anlDomain = 'n'
+        anlRgn = 'n'
+        print ' '
+        analSelect = int(raw_input('Eval over domain (Enter 0) or time series of selected Sub Regions (Enter 1) \n> '))
+        print ' '
+        if analSelect == 0:
+            anlDomain = 'y'
+        elif analSelect == 1:
+            anlRgn = 'y'
+        else:
+            print 'analSelect= ', analSelect, ' is Not a valid option: CRASH'
+
+        #--------------------------------------------------------------------------------------------------------------------
+        # (mp.004) Select the model and data to be used in the evaluation step
+        # 6/7/2013: JK4 - unified handling of the ref & mdl datasets allows several diff types of evaluation (RCMES v2.1)
+        #                 such as ref vs. one model or ref; ref vs. all models; ref vs. all model + non-ref refs
+        #          refID: the ID of the reference data against which all data are to be evaluated
+        #          mdlID: the list of data ID's to be evaluated. if mdlSelect == -99, the list also includes non-ref obs data
+        #--------------------------------------------------------------------------------------------------------------------
+        refID = int(misc.select_data_combined(numDatasets, Times, dataList, 'ref'))
+        mdlSelect = int(misc.select_data_combined(numDatasets, Times, dataList, 'mdl'))
+        mdlID=[]
+        # Assign the data id to be evaluated. Note that a non-reference obs dataset is treated like a model dataset (mdlSelect == -99)
+        if mdlSelect >= 0:
+            mdlID.append(mdlSelect)
+        elif mdlSelect == -1:
+            for n in np.arange(numMDL):
+                mdlID.append(n+numOBS)
+        elif mdlSelect == -2:
+            for n in np.arange(refID):
+                mdlID.append(n)
+            for n in range(refID + 1, numDatasets):
+                mdlID.append(n)
+        elif mdlSelect == -3:
+            if numOBS == 1:
+                print 'There exist only one reference data: EXIT'
+                sys.exit()
+            for n in np.arange(refID):
+                mdlID.append(n)
+            for n in range(refID + 1, numOBS):
+                mdlID.append(n)
+        elif mdlSelect == -4:
+            id4eval = 0         # any number != -9
+            print 'Enter the data id to be evaluated: -9 to stop entering'
+            while id4eval != -9:
+                id4eval = int(raw_input('Enter the data id for evaluation. -9 to stop entry\n> '))
+                if id4eval != -9:
+                    mdlID.append(id4eval)
+        refName = dataList[refID]
+        mdlName = []
+        numMdl = len(mdlID)
+        for n in np.arange(numMdl):
+            tname = dataList[mdlID[n]]
+            m = min(len(tname), 8)
+            for k in np.arange(m):
+                if tname[k] == ' ':
+                    break
+                elif k == m-1:
+                    k = m
+            mdlName.append(tname[0:k])
+        print 'selected reference and model data for evaluation= ', refName, mdlName
+
+        #--------------------------------
+        # (mp.005) Spatial distribution analysis/Evaluation (anlDomain='y')
+        #          Obs/mdl climatology variables are 2-d/3d arrays (e.g., oClim = ma.zeros((ngrdY,ngrdX), mClim = ma.zeros((numMdl,ngrdY,ngrdX))
+        #----------------------------------------------------------------------------------------------------
+        if anlDomain == 'y':
+            # first determine the temporal properties to be evaluated
+            print ''
+            timeOption = misc.select_timOpt()
+            print ''
+            if timeOption == 1:
+                timeScale = 'annual'
+                # compute the annual-mean time series and climatology. 
+                oTser, oClim = calc_clim_year(nYR, nT, ngrdY, ngrdX, allData[refID, :, :, :], Times)
+                mTser = ma.zeros((numMdl, nYR, ngrdY, ngrdX))
+                mClim = ma.zeros((numMdl, ngrdY, ngrdX))
+                for n in np.arange(numMdl):
+                    id = mdlID[n]
+                    mTser[n, :, :, :], mClim[n, :, :] = calc_clim_year(nYR, nT, ngrdY, ngrdX, allData[id, :, :, :], Times)
+            elif timeOption == 2:
+                timeScale = 'seasonal'
+                # select the timeseries and climatology for a season specifiec by a user
+                mTser = ma.zeros((numMdl, nYR, ngrdY, ngrdX))
+                mClim = ma.zeros((numMdl, ngrdY, ngrdX))
+                print ' '
+                moBgn = int(raw_input('Enter the beginning month for your season. 1-12: \n> '))
+                moEnd = int(raw_input('Enter the ending month for your season. 1-12: \n> '))
+                print ' '
+                if moEnd >= moBgn:
+                    nMoPerSeason = moEnd - moBgn + 1
+                    oTser, oClim = calc_clim_season(nYR, nT, moBgn, moEnd, ngrdY, ngrdX, allData[refID, :, :, :], Times)
+                    for n in np.arange(numMdl):
+                        id = mdlID[n]
+                        mTser[n, :, :, :], mClim[n, :, :] = calc_clim_season(nYR, nT, moBgn, moEnd, ngrdY, ngrdX, allData[id, :, :, :], Times)
+                elif moEnd == moBgn:
+                    # Eval for a single month. mTser, oTser are the annual time series 
+                    # for the specified month (moEnd), and  mClim, oClim are the corresponding climatology
+                    oTser, oClim = calc_clim_One_month(moEnd, nYR, nT, allData[refID, :, :, :], Times)
+                    for n in np.arange(numMdl):
+                        id = mdlID[n]
+                        mTser[n, :, :, :], mClim[n, :, :] = calc_clim_One_month(moEnd, nYR, nT, allData[id, :, :, :], Times)
+                elif moEnd < moBgn:        # have to lose the ending year. redefine nYR=nYR-1, and drop the YR[nYR]
+                    nMoS1 = 12 - moBgn + 1
+                    nMoS2 = moEnd
+                    nMoPerSeason = nMoS1 + nMoS2
+                    mTser = ma.zeros((numMdl, nYR - 1, ngrdY, ngrdX))
+                    # calculate the seasonal timeseries and climatology for the model data
+                    for n in np.arange(numMdl):
+                        id = mdlID[n]
+                        mTser1, mClim1 = calc_clim_season(nYR, nT, moBgn, 12, ngrdY, ngrdX, allData[id, :, :, :], Times)
+                        mTser2, mClim2 = calc_clim_season(nYR, nT, 1, moEnd, ngrdY, ngrdX, allData[id, :, :, :], Times)
+                        for i in np.arange(nYR - 1):
+                            mTser[n, i, :, :] = (real(nMoS1) * mTser1[i, :, :] + real(nMoS2) * mTser2[i + 1, :, :]) / nMoPerSeason
+                    mClim = ma.average(mTser, axis=1)
+                    # repeat for the obs data
+                    mTser1, mClim1 = calc_clim_season(nYR, nT, moBgn, 12, ngrdY, ngrdX, allData[refID, :, :, :], Times)
+                    mTser2, mClim2 = calc_clim_season(nYR, nT, 1, moEnd, ngrdY, ngrdX, allData[refID, :, :, :], Times)
+                    oTser = ma.zeros((nYR - 1, ngrdY, ngrdX))
+                    for i in np.arange(nYR - 1):
+                        oTser[i, :, :] = (real(nMoS1) * mTser1[i, :, :] + real(nMoS2) * mTser2[i + 1, :, :]) / nMoPerSeason
+                    oClim = ma.zeros((ngrdY, ngrdX))
+                    oClim = ma.average(oTser, axis=0)
+                    nYR = nYR - 1
+                    yy = ma.empty(nYR)
+                    for i in np.arange(nYR):
+                        yy[i] = YR[i]
+                    mTser1 = 0.
+                    mTser2 = 0.
+                    mClim1 = 0.
+                    mClim2 = 0.
+            elif timeOption == 3:
+                timeScale = 'monthly'
+                # compute the monthly-mean time series and climatology
+                # Note that the shapes of the output vars are: 
+                #   mTser = ma.zeros((nYR,12,ngrdY,ngrdX)) & mClim = ma.zeros((12,ngrdY,ngrdX))
+                # Also same for oTser = ma.zeros((nYR,12,ngrdY,ngrdX)) &,oClim = ma.zeros((12,ngrdY,ngrdX))
+                oTser, oClim = calc_clim_mo(nYR, nT, ngrdY, ngrdX, allData[refID, :, :, :], Times)
+                mTser = ma.zeros((numMdl, nYR, 12, ngrdY, ngrdX))
+                mClim = ma.zeros((numMdl, 12, ngrdY, ngrdX))
+                for n in np.arange(numMdl):
+                    id = mdlID[n]
+                    mTser[n, :, :, :, :], mClim[n, :, :, :] = calc_clim_mo(nYR, nT, ngrdY, ngrdX, allData[id, :, :, :], Times)
+            else:
+                # undefined process options. exit
+                print 'The desired temporal scale is not available this time. END the job'
+                sys.exit()
+
+            # compute the interannual variability
+            if timeScale == 'monthly':
+                oTsig = ma.zeros((12, ngrdY, ngrdX))
+                mTsig = ma.zeros((numMdl, 12, ngrdY, ngrdX))
+            else:
+                oTsig = ma.zeros((ngrdY, ngrdX))
+                mTsig = ma.zeros((numMdl, ngrdY, ngrdX))
+            oTsig = oTser.std(axis = 0)
+            mTsig = mTser.std(axis = 1)
+
+            #--------------------------------
+            # (mp.006) Select metric to be calculated
+            # bias, mae, acct, accs, pcct, pccs, rmst, rmss, pdfSkillScore, taylor diagram
+            #----------------------------------------------------------------------------------------------------
+            print ' '
+            metricOption = misc.select_metrics(mdlSelect)
+            print ' '
+
+            # metrics calculation: the shape of metricDat varies according to the metric type & timescale opetions
+
+            if metricOption == 'BIAS':
+                iselect = int (raw_input('Enter to evaluate: 0 for the mean climatology; 1 for the interannual variability. \n'))
+            else:
+                iselect = 0
+
+            # metrics below yields a 2-d (annual or seasonal) or 3-d (monthly) array for each model
+            if metricOption == 'BIAS':
+                if timeScale == 'monthly':
+                    oStdv = np.zeros(12)
+                    metricDat = ma.zeros((numMdl, 12, ngrdY, ngrdX))
+                    for n in np.arange(numMdl):
+                        for m in np.arange(12):
+                            if iselect == 0:
+                                metricDat[n, m, :, :]  = calc_bias(mTser[n, :, m, :, :], oTser[m, :, :])
+                            elif iselect == 1:
+                                metricDat[n, m, :, :]  = mTsig[n, m, :, :] - oTsig[m, :, :]
+                            if n == 0:
+                                oStdv[m] = calc_temporal_stdv(oTser[m, :, :])
+                else:
+                    oStdv = calc_temporal_stdv(oTser)
+                    metricDat = ma.zeros((numMdl, ngrdY, ngrdX))
+                    for n in np.arange(numMdl):
+                        if iselect == 0:
+                            metricDat[n, :, :]  = calc_bias(mTser[n, :, :, :], oTser)
+                        elif iselect == 1:
+                            for n in np.arange(numMdl):
+                                metricDat[n, :, :]  = mTsig[n, :, :] - oTsig[:, :]
+
+            elif metricOption == 'MAE':
+                if timeScale == 'monthly':
+                    metricDat = ma.zeros((numMdl, 12, ngrdY, ngrdX))
+                    for n in np.arange(numMdl):
+                        for m in np.arange(12):
+                            metricDat[n, m, :, :]  = calc_mae(mTser[n, :, m, :, :], oTser[m, :, :])
+                else:
+                    metricDat = ma.zeros((numMdl, ngrdY, ngrdX))
+                    for n in np.arange(numMdl):
+                        metricDat[n, :, :]  = calc_mae(mTser[n, :, :, :], oTser)
+
+            elif metricOption == 'ACt':
+                if timeScale == 'monthly':
+                    metricDat = ma.zeros((numMdl, 12, ngrdY, ngrdX))
+                    for n in np.arange(numMdl):
+                        for m in np.arange(12):
+                            metricDat[n, m, :, :]  = calc_temporal_anom_cor(mTser[n, :, m, :, :], oTser[m, :, :])
+                else:
+                    metricDat = ma.zeros((numMdl, ngrdY, ngrdX))
+                    for n in np.arange(numMdl):
+                        metricDat[n, :, :]  = calc_temporal_anom_cor(mTser[n, :, :, :], oTser)
+
+            elif metricOption == 'PCt':
+                if timeScale == 'monthly':
+                    metricDat = ma.zeros((numMdl, 12, ngrdY, ngrdX))
+                    for n in np.arange(numMdl):
+                        for m in np.arange(12):
+                            metricDat[n, m, :, :]  = calc_temporal_pat_cor(mTser[n, :, m, :, :], oTser[m, :, :])
+                else:
+                    metricDat = ma.zeros((numMdl, ngrdY, ngrdX))
+                    for n in np.arange(numMdl):
+                        metricDat[n, :, :]  = calc_temporal_pat_cor(mTser[n, :, :, :], oTser)
+
+            elif metricOption == 'RMSt':
+                if timeScale == 'monthly':
+                    metricDat = ma.zeros((numMdl, 12, ngrdY, ngrdX))
+                    for n in np.arange(numMdl):
+                        for m in np.arange(12):
+                            metricDat[n, m, :, :]  = calc_rms(mTser[n, :, m, :, :], oTser[m, :, :])
+                else:
+                    metricDat = ma.zeros((numMdl, ngrdY, ngrdX))
+                    for n in np.arange(numMdl):
+                        metricDat[n, :, :]  = calc_rms(mTser[n, :, :, :], oTser)
+
+            # metrics below yields a scalar value for each model
+            elif metricOption == 'ACs':
+                if timeScale == 'monthly':
+                    metricDat = ma.zeros((numMdl, 12))
+                    for n in np.arange(numMdl):
+                        for m in np.arange(12):
+                            metricDat[n, m]  = calc_spatial_anom_cor(mClim[n, m, :, :], oClim[m, :, :])
+                else:
+                    metricDat = ma.zeros(numMdl)
+                    for n in np.arange(numMdl):
+                        metricDat[n]  = calc_spatial_anom_cor(mClim[n, :, :], oClim)
+                    print 'spatial anomaly correlation vs the reference data:', refName
+                    for n in np.arange(numMdl):
+                        print dataList[n+1][0:8],metricDat[n]
+
+            elif metricOption == 'PCs':
+                if timeScale == 'monthly':
+                    metricDat = ma.zeros((numMdl, 12))
+                    for n in np.arange(numMdl):
+                        for m in np.arange(12):
+                            metricDat[n, m]  = calc_spatial_pat_cor(mClim[n, m, :, :], oClim[m, :, :])
+                else:
+                    metricDat = ma.ze

<TRUNCATED>
http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/rcmes/toolkit/metrics.pyc
----------------------------------------------------------------------
diff --git a/src/main/python/rcmes/toolkit/metrics.pyc b/src/main/python/rcmes/toolkit/metrics.pyc
new file mode 100644
index 0000000..9f29207
Binary files /dev/null and b/src/main/python/rcmes/toolkit/metrics.pyc differ


[36/51] [abbrv] [partial] Adding Jinwon's custom RCMET

Posted by jo...@apache.org.
http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/app/.svn/text-base/index.html.svn-base
----------------------------------------------------------------------
diff --git a/src/main/ui/app/.svn/text-base/index.html.svn-base b/src/main/ui/app/.svn/text-base/index.html.svn-base
new file mode 100755
index 0000000..db85cf4
--- /dev/null
+++ b/src/main/ui/app/.svn/text-base/index.html.svn-base
@@ -0,0 +1,192 @@
+<!doctype html>
+<html lang="en" ng-app="rcmes">
+<head>
+  <meta charset="utf-8">
+  <meta name="viewport" content="width=device-width, initial-scale=1.0">
+  <title>RCMET UI</title>
+  <link rel="stylesheet" href="css/bootstrap.min.css"/>
+  <link rel="stylesheet" href="css/bootstrap-responsive.min.css"/>
+  <link rel="stylesheet" href="css/jasny-bootstrap.min.css"/>
+  <link rel="stylesheet" href="css/jasny-bootstrap-responsive.min.css"/>
+  <link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet-0.5/leaflet.css" />
+  <link rel="stylesheet" href="css/font-awesome.min.css"/>
+  <!--[if lte IE 8]>
+    <link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet-0.5/leaflet.ie.css" />
+  <![endif]-->
+  <link rel="stylesheet" href="css/app.css"/>
+</head>
+<body>
+  <bootstrap-modal modal-id="datasetSelect">
+	<div class="modal-header">
+		<button class="close">&times;</button>
+		<h3>Dataset Select</h3>
+	</div>
+	<div class="modal-body">
+		<div ng-view></div>
+	</div>
+	<div class="modal-footer">
+		<a href="#" class="btn btn-primary close">Close</a>
+	</div>
+  </bootstrap-modal>
+
+  <bootstrap-modal modal-id="evaluationResults">
+  <div class="modal-header">
+  	<button class="close">&times;</button>
+  	<h3>Evaluation Results</h3>
+  </div>
+  <div class="modal-body">
+	  <p>
+	  Comparison: <a href="{{baseURL}}/static/evalResults/{{evalResults.comparisonPath}}">
+		  {{evalResults.comparisonPath}}</a>
+	  </p>
+	  <p>
+	  Model: <a href="{{baseURL}}/static/evalResults/{{evalResults.modelPath}}">
+		  {{evalResults.modelPath}}</a>
+	  </p>
+	  <p>
+	  Observation: <a href="{{baseURL}}/static/evalResults/{{evalResults.obsPath}}">
+		  {{evalResults.obsPath}}</a>
+	  </p>
+	  <p><img src="{{baseURL}}/static/evalResults/{{evalResults.comparisonPath}}" alt="" /></p>
+	  <p><img src="{{baseURL}}/static/evalResults/{{evalResults.modelPath}}" alt="" /></p>
+	  <p><img src="{{baseURL}}/static/evalResults/{{evalResults.obsPath}}" alt="" /></p>
+  </div>
+  <div class="modal-footer">
+	  <a href="#" class="btn btn-primary close">Close</a>
+  </div>
+  </bootstrap-modal>
+
+  <h1 id="rcmetHeader">RCMET UI</h1>
+  <div ng-controller="WorldMapCtrl">
+    <sap id="map"></sap>
+  </div>
+
+  <div ng-controller="ParameterSelectCtrl">
+    <div class="row">
+      <div class="span1 offset2 text-center">Start Date:</div>
+      <div class="span2">
+        <form>
+      <input ng-model="displayParams.start" type="text" class="span2" />
+        </form>
+      </div>
+      <div class="span1 text-center">End Date:</div>
+      <div class="span2">
+        <form>
+		  <input ng-model="displayParams.end" type="text" class="span2" />
+        </form>
+      </div>
+      <div class="span1">
+		<button ng-click="runEvaluation()" ng-disabled="shouldDisableEvaluate()" class="btn btn-block btn-primary">
+		  <div ng-hide="runningEval">Evaluate</div>
+		  <div ng-show="runningEval"><i class="icon-spinner icon-spin"></i></div>
+		</button>
+      </div>
+      <div class="span2">
+        <button class="btn btn-block btn-success" bootstrap-modal-open="datasetSelect">Select a Dataset</button>
+      </div>
+	  <div class="span1">
+		  <button class="btn btn-block btn-primary" ng-disabled="shouldDisableResultsView()" bootstrap-modal-open="evaluationResults">Results</button>
+	  </div>
+    </div>
+    <div class="row">
+      <div class="span1 offset2 text-center">North:</div>
+      <div class="span2">
+        <form action="">
+		  <input ng-model="displayParams.latMax" type="text" class="span2" />
+        </form>
+      </div>
+      <div class="span1 text-center">East:</div>
+      <div class="span2">
+        <form>
+		  <input ng-model="displayParams.lonMax" type="text" class="span2" />
+        </form>
+      </div>
+      <div class="span1">
+        <button ng-click="updateParameters()" ng-disabled="shouldDisableControls()" class="btn btn-block btn-info">Update</button>
+      </div>
+	  <div class="span2">
+		<button ng-click="clearDatasets()" ng-disabled="shouldDisableClearButton()" class="btn btn-block btn-warning">Clear Datasets</button>
+	  </div>
+    </div>
+    <div class="row">
+      <div class="span1 offset2 text-center">South:</div>
+      <div class="span2">
+        <form action="">
+		  <input ng-model="displayParams.latMin" type="text" class="span2" />
+        </form>
+      </div>
+      <div class="span1 text-center">West:</div>
+      <div class="span2">
+        <form>
+		  <input ng-model="displayParams.lonMin" type="text" class="span2" />
+        </form>
+      </div>
+    </div>
+  </div>
+  <!--Dataset display-->
+  <div ng-controller="DatasetDisplayCtrl">
+    <div ng-repeat="dataset in datasets">
+	  <div class="row displayRow">
+  	    <div class="span10 offset2"><hr /></div>
+	  </div>
+	  <div class="row displayRow">
+		<div class="span4 offset2">
+		  <input class="span6 text-center" type="text" value="{{dataset.name}}" />
+		</div>
+	  </div>
+	  <!--Time Values!-->
+      <div class="row displayRow">
+        <div class="span1 offset2 text-center">Start Date:</div>
+		<div class="span2">
+		  <input class="span2 text-center" type="text" value="{{dataset.timeVals.start}}" readonly/>
+		</div>
+        <div class="span1 text-center">End Date:</div>
+		<div class="span2">
+		  <input class="span2 text-center" type="text" value="{{dataset.timeVals.end}}" readonly/>
+		</div>
+	  </div>
+	  <!--Lat/Long Values!-->
+      <div class="row displayRow">
+        <div class="span1 offset2 text-center">North:</div>
+		<div class="span2">
+		  <input class="span2 text-center" type="text" value="{{dataset.latlonVals.latMax}}" readonly/>
+		</div>
+        <div class="span1 text-center">East:</div>
+		<div class="span2">
+		  <input class="span2 text-center" type="text" value="{{dataset.latlonVals.lonMax}}" readonly/>
+		</div>
+		<div class="span2">
+		  <a class="btn btn-block" ng-click="removeDataset($index)">Remove Dataset</a>
+		</div>
+    <div class="span1" style="background-color: {{fillColors[$index]}}; height: 28px; width: 28px;"></div>
+	  </div>
+      <div class="row displayRow">
+        <div class="span1 offset2 text-center">South:</div>
+		<div class="span2">
+		  <input class="span2 text-center" type="text" value="{{dataset.latlonVals.latMin}}" readonly/>
+		</div>
+        <div class="span1 text-center">West:</div>
+		<div class="span2">
+		  <input class="span2 text-center" type="text" value="{{dataset.latlonVals.lonMin}}" readonly/>
+		</div>
+	  </div>
+    </div>
+  </div>
+
+  <!-- In production use:
+  <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.0.4/angular.min.js"></script>
+  -->
+  <!--<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>-->
+  <script src="http://code.jquery.com/jquery.js"></script>
+  <!--<script src="js/bootstrap.min.js"></script>-->
+  <script src="js/bootstrap.js"></script>
+  <script src="js/jasny-bootstrap.min.js"></script>
+  <script src="lib/angular/angular.js"></script>
+  <script src="http://cdn.leafletjs.com/leaflet-0.5/leaflet.js"></script>
+  <script src="js/app.js"></script>
+  <script src="js/services.js"></script>
+  <script src="js/controllers.js"></script>
+  <script src="js/filters.js"></script>
+  <script src="js/directives.js"></script>
+</body>
+</html>

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/app/css/.svn/all-wcprops
----------------------------------------------------------------------
diff --git a/src/main/ui/app/css/.svn/all-wcprops b/src/main/ui/app/css/.svn/all-wcprops
new file mode 100755
index 0000000..2a7c744
--- /dev/null
+++ b/src/main/ui/app/css/.svn/all-wcprops
@@ -0,0 +1,41 @@
+K 25
+svn:wc:ra_dav:version-url
+V 77
+/repos/asf/!svn/ver/1482549/incubator/climate/trunk/rcmet/src/main/ui/app/css
+END
+bootstrap-responsive.min.css
+K 25
+svn:wc:ra_dav:version-url
+V 106
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/ui/app/css/bootstrap-responsive.min.css
+END
+jasny-bootstrap-responsive.min.css
+K 25
+svn:wc:ra_dav:version-url
+V 112
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/ui/app/css/jasny-bootstrap-responsive.min.css
+END
+bootstrap.min.css
+K 25
+svn:wc:ra_dav:version-url
+V 95
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/ui/app/css/bootstrap.min.css
+END
+app.css
+K 25
+svn:wc:ra_dav:version-url
+V 85
+/repos/asf/!svn/ver/1482549/incubator/climate/trunk/rcmet/src/main/ui/app/css/app.css
+END
+jasny-bootstrap.min.css
+K 25
+svn:wc:ra_dav:version-url
+V 101
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/ui/app/css/jasny-bootstrap.min.css
+END
+font-awesome.min.css
+K 25
+svn:wc:ra_dav:version-url
+V 98
+/repos/asf/!svn/ver/1480068/incubator/climate/trunk/rcmet/src/main/ui/app/css/font-awesome.min.css
+END

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/app/css/.svn/entries
----------------------------------------------------------------------
diff --git a/src/main/ui/app/css/.svn/entries b/src/main/ui/app/css/.svn/entries
new file mode 100755
index 0000000..f947091
--- /dev/null
+++ b/src/main/ui/app/css/.svn/entries
@@ -0,0 +1,232 @@
+10
+
+dir
+1485921
+https://svn.apache.org/repos/asf/incubator/climate/trunk/rcmet/src/main/ui/app/css
+https://svn.apache.org/repos/asf
+
+
+
+2013-05-14T20:08:03.933527Z
+1482549
+joyce
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+13f79535-47bb-0310-9956-ffa450edef68
+
+bootstrap-responsive.min.css
+file
+
+
+
+
+2013-05-24T10:13:57.000000Z
+12d88b292711cd2af776fc3c8cf2649e
+2013-03-13T02:34:36.621563Z
+1475138
+mjjoyce
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+16849
+
+jasny-bootstrap-responsive.min.css
+file
+
+
+
+
+2013-05-24T10:13:57.000000Z
+84e46374a644857ba06dce1d9592dce8
+2013-03-25T17:12:04.245722Z
+1475246
+mjjoyce
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+2300
+
+bootstrap.min.css
+file
+
+
+
+
+2013-05-24T10:13:57.000000Z
+323f5dbc2c30537175dad260d75cf7ad
+2013-03-13T02:34:36.621563Z
+1475138
+mjjoyce
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+105939
+
+app.css
+file
+
+
+
+
+2013-05-24T10:13:57.000000Z
+569b1c30df1d5110d059bf87ab9816d3
+2013-05-14T20:08:03.933527Z
+1482549
+joyce
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+275
+
+jasny-bootstrap.min.css
+file
+
+
+
+
+2013-05-24T10:13:57.000000Z
+b6deae6bf670b855cddd341733097339
+2013-03-25T17:12:04.245722Z
+1475246
+mjjoyce
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+21189
+
+font-awesome.min.css
+file
+
+
+
+
+2013-05-24T10:13:57.000000Z
+c8595bd4b0ed08844f2cf3f730e7d4ca
+2013-05-07T20:50:17.582309Z
+1480068
+joyce
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+15725
+

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/app/css/.svn/prop-base/app.css.svn-base
----------------------------------------------------------------------
diff --git a/src/main/ui/app/css/.svn/prop-base/app.css.svn-base b/src/main/ui/app/css/.svn/prop-base/app.css.svn-base
new file mode 100755
index 0000000..869ac71
--- /dev/null
+++ b/src/main/ui/app/css/.svn/prop-base/app.css.svn-base
@@ -0,0 +1,5 @@
+K 14
+svn:executable
+V 1
+*
+END

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/app/css/.svn/prop-base/font-awesome.min.css.svn-base
----------------------------------------------------------------------
diff --git a/src/main/ui/app/css/.svn/prop-base/font-awesome.min.css.svn-base b/src/main/ui/app/css/.svn/prop-base/font-awesome.min.css.svn-base
new file mode 100755
index 0000000..869ac71
--- /dev/null
+++ b/src/main/ui/app/css/.svn/prop-base/font-awesome.min.css.svn-base
@@ -0,0 +1,5 @@
+K 14
+svn:executable
+V 1
+*
+END

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/app/css/.svn/text-base/app.css.svn-base
----------------------------------------------------------------------
diff --git a/src/main/ui/app/css/.svn/text-base/app.css.svn-base b/src/main/ui/app/css/.svn/text-base/app.css.svn-base
new file mode 100755
index 0000000..66ff15d
--- /dev/null
+++ b/src/main/ui/app/css/.svn/text-base/app.css.svn-base
@@ -0,0 +1,27 @@
+/* app css stylesheet */
+
+#map 
+{
+    height: 670px;
+    width: 80%;
+    margin-left: 10%;
+	margin-bottom: 20px;
+}
+
+#rcmetHeader
+{
+	margin-left: 10%;
+}
+
+.small-alert 
+{
+	font-size: 12px;
+	color: green;
+	margin-top: 4px;
+	margin-left: 10px;
+}
+
+ul 
+{
+	list-style-type: none;
+}

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/app/css/.svn/text-base/bootstrap-responsive.min.css.svn-base
----------------------------------------------------------------------
diff --git a/src/main/ui/app/css/.svn/text-base/bootstrap-responsive.min.css.svn-base b/src/main/ui/app/css/.svn/text-base/bootstrap-responsive.min.css.svn-base
new file mode 100755
index 0000000..d1b7f4b
--- /dev/null
+++ b/src/main/ui/app/css/.svn/text-base/bootstrap-responsive.min.css.svn-base
@@ -0,0 +1,9 @@
+/*!
+ * Bootstrap Responsive v2.3.1
+ *
+ * Copyright 2012 Twitter, Inc
+ * Licensed under the Apache License v2.0
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Designed and built with all the love in the world @twitter by @mdo and @fat.
+ */.clearfix{*zoom:1}.clearfix:before,.clearfix:after{display:table;line-height:0;content:""}.clearfix:after{clear:both}.hide-text{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.input-block-level{display:block;width:100%;min-height:30px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}@-ms-viewport{width:device-width}.hidden{display:none;visibility:hidden}.visible-phone{display:none!important}.visible-tablet{display:none!important}.hidden-desktop{display:none!important}.visible-desktop{display:inherit!important}@media(min-width:768px) and (max-width:979px){.hidden-desktop{display:inherit!important}.visible-desktop{display:none!important}.visible-tablet{display:inherit!important}.hidden-tablet{display:none!important}}@media(max-width:767px){.hidden-desktop{display:inherit!important}.visible-desktop{display:none!important}.visible-phone{display:inherit!important}.hidden-phone{display:none!important}}.visible-print{dis
 play:none!important}@media print{.visible-print{display:inherit!important}.hidden-print{display:none!important}}@media(min-width:1200px){.row{margin-left:-30px;*zoom:1}.row:before,.row:after{display:table;line-height:0;content:""}.row:after{clear:both}[class*="span"]{float:left;min-height:1px;margin-left:30px}.container,.navbar-static-top .container,.navbar-fixed-top .container,.navbar-fixed-bottom .container{width:1170px}.span12{width:1170px}.span11{width:1070px}.span10{width:970px}.span9{width:870px}.span8{width:770px}.span7{width:670px}.span6{width:570px}.span5{width:470px}.span4{width:370px}.span3{width:270px}.span2{width:170px}.span1{width:70px}.offset12{margin-left:1230px}.offset11{margin-left:1130px}.offset10{margin-left:1030px}.offset9{margin-left:930px}.offset8{margin-left:830px}.offset7{margin-left:730px}.offset6{margin-left:630px}.offset5{margin-left:530px}.offset4{margin-left:430px}.offset3{margin-left:330px}.offset2{margin-left:230px}.offset1{margin-left:130px}.row-flui
 d{width:100%;*zoom:1}.row-fluid:before,.row-fluid:after{display:table;line-height:0;content:""}.row-fluid:after{clear:both}.row-fluid [class*="span"]{display:block;float:left;width:100%;min-height:30px;margin-left:2.564102564102564%;*margin-left:2.5109110747408616%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.row-fluid [class*="span"]:first-child{margin-left:0}.row-fluid .controls-row [class*="span"]+[class*="span"]{margin-left:2.564102564102564%}.row-fluid .span12{width:100%;*width:99.94680851063829%}.row-fluid .span11{width:91.45299145299145%;*width:91.39979996362975%}.row-fluid .span10{width:82.90598290598291%;*width:82.8527914166212%}.row-fluid .span9{width:74.35897435897436%;*width:74.30578286961266%}.row-fluid .span8{width:65.81196581196582%;*width:65.75877432260411%}.row-fluid .span7{width:57.26495726495726%;*width:57.21176577559556%}.row-fluid .span6{width:48.717948717948715%;*width:48.664757228587014%}.row-fluid .span5{width:40.17094017094
 017%;*width:40.11774868157847%}.row-fluid .span4{width:31.623931623931625%;*width:31.570740134569924%}.row-fluid .span3{width:23.076923076923077%;*width:23.023731587561375%}.row-fluid .span2{width:14.52991452991453%;*width:14.476723040552828%}.row-fluid .span1{width:5.982905982905983%;*width:5.929714493544281%}.row-fluid .offset12{margin-left:105.12820512820512%;*margin-left:105.02182214948171%}.row-fluid .offset12:first-child{margin-left:102.56410256410257%;*margin-left:102.45771958537915%}.row-fluid .offset11{margin-left:96.58119658119658%;*margin-left:96.47481360247316%}.row-fluid .offset11:first-child{margin-left:94.01709401709402%;*margin-left:93.91071103837061%}.row-fluid .offset10{margin-left:88.03418803418803%;*margin-left:87.92780505546462%}.row-fluid .offset10:first-child{margin-left:85.47008547008548%;*margin-left:85.36370249136206%}.row-fluid .offset9{margin-left:79.48717948717949%;*margin-left:79.38079650845607%}.row-fluid .offset9:first-child{margin-left:76.92307692307
 693%;*margin-left:76.81669394435352%}.row-fluid .offset8{margin-left:70.94017094017094%;*margin-left:70.83378796144753%}.row-fluid .offset8:first-child{margin-left:68.37606837606839%;*margin-left:68.26968539734497%}.row-fluid .offset7{margin-left:62.393162393162385%;*margin-left:62.28677941443899%}.row-fluid .offset7:first-child{margin-left:59.82905982905982%;*margin-left:59.72267685033642%}.row-fluid .offset6{margin-left:53.84615384615384%;*margin-left:53.739770867430444%}.row-fluid .offset6:first-child{margin-left:51.28205128205128%;*margin-left:51.175668303327875%}.row-fluid .offset5{margin-left:45.299145299145295%;*margin-left:45.1927623204219%}.row-fluid .offset5:first-child{margin-left:42.73504273504273%;*margin-left:42.62865975631933%}.row-fluid .offset4{margin-left:36.75213675213675%;*margin-left:36.645753773413354%}.row-fluid .offset4:first-child{margin-left:34.18803418803419%;*margin-left:34.081651209310785%}.row-fluid .offset3{margin-left:28.205128205128204%;*margin-left:
 28.0987452264048%}.row-fluid .offset3:first-child{margin-left:25.641025641025642%;*margin-left:25.53464266230224%}.row-fluid .offset2{margin-left:19.65811965811966%;*margin-left:19.551736679396257%}.row-fluid .offset2:first-child{margin-left:17.094017094017094%;*margin-left:16.98763411529369%}.row-fluid .offset1{margin-left:11.11111111111111%;*margin-left:11.004728132387708%}.row-fluid .offset1:first-child{margin-left:8.547008547008547%;*margin-left:8.440625568285142%}input,textarea,.uneditable-input{margin-left:0}.controls-row [class*="span"]+[class*="span"]{margin-left:30px}input.span12,textarea.span12,.uneditable-input.span12{width:1156px}input.span11,textarea.span11,.uneditable-input.span11{width:1056px}input.span10,textarea.span10,.uneditable-input.span10{width:956px}input.span9,textarea.span9,.uneditable-input.span9{width:856px}input.span8,textarea.span8,.uneditable-input.span8{width:756px}input.span7,textarea.span7,.uneditable-input.span7{width:656px}input.span6,textarea.span
 6,.uneditable-input.span6{width:556px}input.span5,textarea.span5,.uneditable-input.span5{width:456px}input.span4,textarea.span4,.uneditable-input.span4{width:356px}input.span3,textarea.span3,.uneditable-input.span3{width:256px}input.span2,textarea.span2,.uneditable-input.span2{width:156px}input.span1,textarea.span1,.uneditable-input.span1{width:56px}.thumbnails{margin-left:-30px}.thumbnails>li{margin-left:30px}.row-fluid .thumbnails{margin-left:0}}@media(min-width:768px) and (max-width:979px){.row{margin-left:-20px;*zoom:1}.row:before,.row:after{display:table;line-height:0;content:""}.row:after{clear:both}[class*="span"]{float:left;min-height:1px;margin-left:20px}.container,.navbar-static-top .container,.navbar-fixed-top .container,.navbar-fixed-bottom .container{width:724px}.span12{width:724px}.span11{width:662px}.span10{width:600px}.span9{width:538px}.span8{width:476px}.span7{width:414px}.span6{width:352px}.span5{width:290px}.span4{width:228px}.span3{width:166px}.span2{width:104px
 }.span1{width:42px}.offset12{margin-left:764px}.offset11{margin-left:702px}.offset10{margin-left:640px}.offset9{margin-left:578px}.offset8{margin-left:516px}.offset7{margin-left:454px}.offset6{margin-left:392px}.offset5{margin-left:330px}.offset4{margin-left:268px}.offset3{margin-left:206px}.offset2{margin-left:144px}.offset1{margin-left:82px}.row-fluid{width:100%;*zoom:1}.row-fluid:before,.row-fluid:after{display:table;line-height:0;content:""}.row-fluid:after{clear:both}.row-fluid [class*="span"]{display:block;float:left;width:100%;min-height:30px;margin-left:2.7624309392265194%;*margin-left:2.709239449864817%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.row-fluid [class*="span"]:first-child{margin-left:0}.row-fluid .controls-row [class*="span"]+[class*="span"]{margin-left:2.7624309392265194%}.row-fluid .span12{width:100%;*width:99.94680851063829%}.row-fluid .span11{width:91.43646408839778%;*width:91.38327259903608%}.row-fluid .span10{width:82.87
 292817679558%;*width:82.81973668743387%}.row-fluid .span9{width:74.30939226519337%;*width:74.25620077583166%}.row-fluid .span8{width:65.74585635359117%;*width:65.69266486422946%}.row-fluid .span7{width:57.18232044198895%;*width:57.12912895262725%}.row-fluid .span6{width:48.61878453038674%;*width:48.56559304102504%}.row-fluid .span5{width:40.05524861878453%;*width:40.00205712942283%}.row-fluid .span4{width:31.491712707182323%;*width:31.43852121782062%}.row-fluid .span3{width:22.92817679558011%;*width:22.87498530621841%}.row-fluid .span2{width:14.3646408839779%;*width:14.311449394616199%}.row-fluid .span1{width:5.801104972375691%;*width:5.747913483013988%}.row-fluid .offset12{margin-left:105.52486187845304%;*margin-left:105.41847889972962%}.row-fluid .offset12:first-child{margin-left:102.76243093922652%;*margin-left:102.6560479605031%}.row-fluid .offset11{margin-left:96.96132596685082%;*margin-left:96.8549429881274%}.row-fluid .offset11:first-child{margin-left:94.1988950276243%;*margi
 n-left:94.09251204890089%}.row-fluid .offset10{margin-left:88.39779005524862%;*margin-left:88.2914070765252%}.row-fluid .offset10:first-child{margin-left:85.6353591160221%;*margin-left:85.52897613729868%}.row-fluid .offset9{margin-left:79.8342541436464%;*margin-left:79.72787116492299%}.row-fluid .offset9:first-child{margin-left:77.07182320441989%;*margin-left:76.96544022569647%}.row-fluid .offset8{margin-left:71.2707182320442%;*margin-left:71.16433525332079%}.row-fluid .offset8:first-child{margin-left:68.50828729281768%;*margin-left:68.40190431409427%}.row-fluid .offset7{margin-left:62.70718232044199%;*margin-left:62.600799341718584%}.row-fluid .offset7:first-child{margin-left:59.94475138121547%;*margin-left:59.838368402492065%}.row-fluid .offset6{margin-left:54.14364640883978%;*margin-left:54.037263430116376%}.row-fluid .offset6:first-child{margin-left:51.38121546961326%;*margin-left:51.27483249088986%}.row-fluid .offset5{margin-left:45.58011049723757%;*margin-left:45.4737275185141
 7%}.row-fluid .offset5:first-child{margin-left:42.81767955801105%;*margin-left:42.71129657928765%}.row-fluid .offset4{margin-left:37.01657458563536%;*margin-left:36.91019160691196%}.row-fluid .offset4:first-child{margin-left:34.25414364640884%;*margin-left:34.14776066768544%}.row-fluid .offset3{margin-left:28.45303867403315%;*margin-left:28.346655695309746%}.row-fluid .offset3:first-child{margin-left:25.69060773480663%;*margin-left:25.584224756083227%}.row-fluid .offset2{margin-left:19.88950276243094%;*margin-left:19.783119783707537%}.row-fluid .offset2:first-child{margin-left:17.12707182320442%;*margin-left:17.02068884448102%}.row-fluid .offset1{margin-left:11.32596685082873%;*margin-left:11.219583872105325%}.row-fluid .offset1:first-child{margin-left:8.56353591160221%;*margin-left:8.457152932878806%}input,textarea,.uneditable-input{margin-left:0}.controls-row [class*="span"]+[class*="span"]{margin-left:20px}input.span12,textarea.span12,.uneditable-input.span12{width:710px}input.sp
 an11,textarea.span11,.uneditable-input.span11{width:648px}input.span10,textarea.span10,.uneditable-input.span10{width:586px}input.span9,textarea.span9,.uneditable-input.span9{width:524px}input.span8,textarea.span8,.uneditable-input.span8{width:462px}input.span7,textarea.span7,.uneditable-input.span7{width:400px}input.span6,textarea.span6,.uneditable-input.span6{width:338px}input.span5,textarea.span5,.uneditable-input.span5{width:276px}input.span4,textarea.span4,.uneditable-input.span4{width:214px}input.span3,textarea.span3,.uneditable-input.span3{width:152px}input.span2,textarea.span2,.uneditable-input.span2{width:90px}input.span1,textarea.span1,.uneditable-input.span1{width:28px}}@media(max-width:767px){body{padding-right:20px;padding-left:20px}.navbar-fixed-top,.navbar-fixed-bottom,.navbar-static-top{margin-right:-20px;margin-left:-20px}.container-fluid{padding:0}.dl-horizontal dt{float:none;width:auto;clear:none;text-align:left}.dl-horizontal dd{margin-left:0}.container{width:aut
 o}.row-fluid{width:100%}.row,.thumbnails{margin-left:0}.thumbnails>li{float:none;margin-left:0}[class*="span"],.uneditable-input[class*="span"],.row-fluid [class*="span"]{display:block;float:none;width:100%;margin-left:0;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.span12,.row-fluid .span12{width:100%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.row-fluid [class*="offset"]:first-child{margin-left:0}.input-large,.input-xlarge,.input-xxlarge,input[class*="span"],select[class*="span"],textarea[class*="span"],.uneditable-input{display:block;width:100%;min-height:30px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.input-prepend input,.input-append input,.input-prepend input[class*="span"],.input-append input[class*="span"]{display:inline-block;width:auto}.controls-row [class*="span"]+[class*="span"]{margin-left:0}.modal{position:fixed;top:20px;right:20px;left:20px;width:auto;margin:0}.m
 odal.fade{top:-100px}.modal.fade.in{top:20px}}@media(max-width:480px){.nav-collapse{-webkit-transform:translate3d(0,0,0)}.page-header h1 small{display:block;line-height:20px}input[type="checkbox"],input[type="radio"]{border:1px solid #ccc}.form-horizontal .control-label{float:none;width:auto;padding-top:0;text-align:left}.form-horizontal .controls{margin-left:0}.form-horizontal .control-list{padding-top:0}.form-horizontal .form-actions{padding-right:10px;padding-left:10px}.media .pull-left,.media .pull-right{display:block;float:none;margin-bottom:10px}.media-object{margin-right:0;margin-left:0}.modal{top:10px;right:10px;left:10px}.modal-header .close{padding:10px;margin:-10px}.carousel-caption{position:static}}@media(max-width:979px){body{padding-top:0}.navbar-fixed-top,.navbar-fixed-bottom{position:static}.navbar-fixed-top{margin-bottom:20px}.navbar-fixed-bottom{margin-top:20px}.navbar-fixed-top .navbar-inner,.navbar-fixed-bottom .navbar-inner{padding:5px}.navbar .container{width:a
 uto;padding:0}.navbar .brand{padding-right:10px;padding-left:10px;margin:0 0 0 -5px}.nav-collapse{clear:both}.nav-collapse .nav{float:none;margin:0 0 10px}.nav-collapse .nav>li{float:none}.nav-collapse .nav>li>a{margin-bottom:2px}.nav-collapse .nav>.divider-vertical{display:none}.nav-collapse .nav .nav-header{color:#777;text-shadow:none}.nav-collapse .nav>li>a,.nav-collapse .dropdown-menu a{padding:9px 15px;font-weight:bold;color:#777;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}.nav-collapse .btn{padding:4px 10px 4px;font-weight:normal;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.nav-collapse .dropdown-menu li+li a{margin-bottom:2px}.nav-collapse .nav>li>a:hover,.nav-collapse .nav>li>a:focus,.nav-collapse .dropdown-menu a:hover,.nav-collapse .dropdown-menu a:focus{background-color:#f2f2f2}.navbar-inverse .nav-collapse .nav>li>a,.navbar-inverse .nav-collapse .dropdown-menu a{color:#999}.navbar-inverse .nav-collapse .nav>li>a:hover,.navbar
 -inverse .nav-collapse .nav>li>a:focus,.navbar-inverse .nav-collapse .dropdown-menu a:hover,.navbar-inverse .nav-collapse .dropdown-menu a:focus{background-color:#111}.nav-collapse.in .btn-group{padding:0;margin-top:5px}.nav-collapse .dropdown-menu{position:static;top:auto;left:auto;display:none;float:none;max-width:none;padding:0;margin:0 15px;background-color:transparent;border:0;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none}.nav-collapse .open>.dropdown-menu{display:block}.nav-collapse .dropdown-menu:before,.nav-collapse .dropdown-menu:after{display:none}.nav-collapse .dropdown-menu .divider{display:none}.nav-collapse .nav>li>.dropdown-menu:before,.nav-collapse .nav>li>.dropdown-menu:after{display:none}.nav-collapse .navbar-form,.nav-collapse .navbar-search{float:none;padding:10px 15px;margin:10px 0;border-top:1px solid #f2f2f2;border-bottom:1px solid #f2f2f2;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,
 255,0.1),0 1px 0 rgba(255,255,255,0.1);-moz-box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.1);box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.1)}.navbar-inverse .nav-collapse .navbar-form,.navbar-inverse .nav-collapse .navbar-search{border-top-color:#111;border-bottom-color:#111}.navbar .nav-collapse .nav.pull-right{float:none;margin-left:0}.nav-collapse,.nav-collapse.collapse{height:0;overflow:hidden}.navbar .btn-navbar{display:block}.navbar-static .navbar-inner{padding-right:10px;padding-left:10px}}@media(min-width:980px){.nav-collapse.collapse{height:auto!important;overflow:visible!important}}


[42/51] [abbrv] [partial] Adding Jinwon's custom RCMET

Posted by jo...@apache.org.
http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/rcmes/toolkit/.svn/text-base/metrics.py.svn-base
----------------------------------------------------------------------
diff --git a/src/main/python/rcmes/toolkit/.svn/text-base/metrics.py.svn-base b/src/main/python/rcmes/toolkit/.svn/text-base/metrics.py.svn-base
new file mode 100755
index 0000000..f52a8f2
--- /dev/null
+++ b/src/main/python/rcmes/toolkit/.svn/text-base/metrics.py.svn-base
@@ -0,0 +1,1345 @@
+#
+#  Licensed to the Apache Software Foundation (ASF) under one or more
+#  contributor license agreements.  See the NOTICE file distributed with
+#  this work for additional information regarding copyright ownership.
+#  The ASF licenses this file to You under the Apache License, Version 2.0
+#  (the "License"); you may not use this file except in compliance with
+#  the License.  You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+#  Unless required by applicable law or agreed to in writing, software
+#  distributed under the License is distributed on an "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#  See the License for the specific language governing permissions and
+#  limitations under the License.
+#
+
+'''
+Module storing functions to calculate statistical metrics from numpy arrays
+'''
+
+import datetime
+import subprocess
+import sys
+import os
+import numpy as np
+import numpy.ma as ma
+from toolkit import plots, process
+from utils import misc
+from storage import files 
+
+def calc_ann_mean(t2, time):
+    '''
+    Calculate annual cycle in terms of monthly means at every grid point.
+    '''
+    # Calculate annual cycle in terms of monthly means at every grid point including single point case (ndim=1)
+    # note: this routine is identical to 'calc_annual_cycle_means': must be converted to calculate the annual mean
+    # Extract months from time variable
+    months = np.empty(len(time))
+    for t in np.arange(len(time)):
+        months[t] = time[t].month
+    if t2.ndim == 3:
+        means = ma.empty((12, t2.shape[1], t2.shape[2])) # empty array to store means
+        # Calculate means month by month
+        for i in np.arange(12)+1:
+            means[i - 1, :, :] = t2[months == i, :, :].mean(0)
+    if t2.ndim == 1:
+        means = np.empty((12)) # empty array to store means
+        # Calculate means month by month
+        for i in np.arange(12)+1:
+            means[i - 1] = t2[months == i].mean(0)
+    return means
+
+
+def calc_clim_month(t2, time):
+    '''
+    Calculate monthly means at every grid point.
+    '''
+    # Calculate monthly means at every grid point including single point case (ndim=1)
+    # Extract months from time variable
+    months = np.empty(len(time))
+    for t in np.arange(len(time)):
+        months[t] = time[t].month
+    if t2.ndim == 3:
+        means = ma.empty((12, t2.shape[1], t2.shape[2])) # empty array to store means
+        # Calculate means month by month
+        for i in np.arange(12) + 1:
+            means[i - 1, :, :] = t2[months == i, :, :].mean(0)
+    if t2.ndim == 1:
+        means = np.empty((12)) # empty array to store means
+        # Calculate means month by month
+        for i in np.arange(12) + 1:
+            means[i - 1] = t2[months == i].mean(0)
+    return means
+
+
+def calc_clim_year(nYR, nT, ngrdY, ngrdX, t2, time):
+    '''
+    Calculate annual mean timeseries and climatology for both 2-D and point time series.
+    '''
+    # Extract months from time variable
+    yy = np.empty(nT)
+    mm = np.empty(nT)
+    for t in np.arange(nT):
+        yy[t] = time[t].year
+        mm[t] = time[t].month
+    if t2.ndim == 3:
+        tSeries = ma.zeros((nYR, ngrdY, ngrdX))
+        i = 0
+        for myunit in np.unique(yy):
+            wh = (yy == myunit)
+            data = t2[wh, :, :]
+            tSeries[i, :, :] = ma.average(data, axis = 0)
+            #print 'data.shape= ',data.shape,'  i= ',i,'  yy= ',yy
+            i += 1
+        means = ma.zeros((ngrdY, ngrdX))
+        means = ma.average(tSeries, axis = 0)
+    elif t2.ndim == 1:
+        tSeries = ma.zeros((nYR))
+        i = 0
+        for myunit in np.unique(yy):
+            wh = (yy == myunit)
+            data = t2[wh]
+            tSeries[i] = ma.average(data, axis = 0)
+            #print 'data.shape= ',data.shape,'  i= ',i,'  yy= ',yy
+            i += 1
+        means = ma.zeros((ngrdY, ngrdX))
+        means = ma.average(tSeries, axis = 0)
+    return tSeries, means
+
+
+def calc_clim_season(nYR, nT, mB, mE, ngrdY, ngrdX, t2, time):
+    '''
+    Calculate seasonal mean timeseries and climatology for both 2-D and point time series.
+    '''
+    #-------------------------------------------------------------------------------------
+    # Calculate seasonal mean timeseries and climatology for both 2-d and point time series
+    # The season to be calculated is defined by moB and moE; moE>=moB always
+    #-------------------------------------------------------------------------------------
+    # Extract months from time variable
+    yy = np.empty(nT)
+    mm = np.empty(nT)
+    for t in np.arange(nT):
+        yy[t] = time[t].year
+        mm[t] = time[t].month
+    if t2.ndim == 3:
+        tSeries = ma.zeros((nYR, ngrdY, ngrdX))
+        i = 0
+        for myunit in np.unique(yy):
+            wh = (yy == myunit) & (mm >= mB) & (mm <= mE)
+            data = t2[wh, :, :]
+            tSeries[i, :, :] = ma.average(data, axis = 0)
+            #print 'data.shape= ',data.shape,'  i= ',i,'  yy= ',yy
+            i += 1
+        means = ma.zeros((ngrdY, ngrdX))
+        means = ma.average(tSeries, axis = 0)
+    elif t2.ndim == 1:
+        tSeries = ma.zeros((nYR))
+        i = 0
+        for myunit in np.unique(yy):
+            wh = (yy == myunit) & (mm >= mB) & (mm <= mE)
+            data = t2[wh]
+            tSeries[i] = ma.average(data, axis = 0)
+            #print 'data.shape= ',data.shape,'  i= ',i,'  yy= ',yy
+            i += 1
+        means = ma.zeros((ngrdY, ngrdX))
+        means = ma.average(tSeries, axis = 0)
+    return tSeries, means
+
+
+def calc_clim_mo(nYR, nT, ngrdY, ngrdX, t2, time):
+    '''
+    Calculate monthly means at every grid points and the annual time series of single model.
+    '''
+    #-------------------------------------------------------------------------------------
+    # JK20: This routine is modified from 'calc_clim_month'  with additional arguments and
+    #       output, the annual time series of single model output (mData)
+    # Calculate monthly means at every grid point including single point case (ndim=1)
+    #-------------------------------------------------------------------------------------
+    # Extract months and monthly time series from the time and raw variable, respectively
+    months = np.empty(nT)
+    for t in np.arange(nT):
+        months[t] = time[t].month
+        if t == 0:
+            yy0 = time[t].year
+        # for a 2-D time series data
+    if t2.ndim == 3:
+        mData = ma.empty((nYR, 12, ngrdY, ngrdX))
+        for t in np.arange(nT):
+            yy = time[t].year
+            mm = months[t]
+            yr = yy - yy0
+            mData[yr, mm, :, :] = t2[t, :, :]
+        # Calculate means month by month. means is an empty array to store means
+        means = ma.empty((12, ngrdY, ngrdX))
+        for i in np.arange(12) + 1:
+            means[i - 1, :, :] = t2[months == i, :, :].mean(0)
+        # for a point time series data
+    if t2.ndim == 1:
+        mData = ma.empty((nYR, 12))
+        for t in np.arange(nT):
+            yy = time[t].year
+            mm = months[t]
+            yr = yy - yy0
+            mData[yr, mm] = t2[t]
+        means = np.empty((12))
+        # Calculate means month by month. means is an empty array to store means
+        for i in np.arange(12) + 1:
+            means[i - 1] = t2[months == i].mean(0)
+    return mData, means
+
+
+def calc_clim_One_month(moID, nYR, nT, t2, time):
+    '''
+    Calculate the montly mean at every grid point for a specified month.
+    '''
+    #-------------------------------------------------------------------------------------
+    # Calculate monthly means at every grid point for a specified month
+    #-------------------------------------------------------------------------------------
+    # Extract months and the corresponding time series from time variable
+    months = np.empty(nT)
+    for t in np.arange(nT):
+        months[t] = time[t].month
+    if t2.ndim == 3:
+        mData = ma.empty((nYR, t2.shape[1], t2.shape[2])) # empty array to store time series
+        n = 0
+        if months[t] == moID:
+            mData[n, :, :] = t2[t, :, :]
+            n += 1
+        means = ma.empty((t2.shape[1], t2.shape[2])) # empty array to store means
+        # Calculate means for the month specified by moID
+        means[:, :] = t2[months == moID, :, :].mean(0)
+    return mData, means
+
+
+def calc_annual_cycle_means(data, time):
+    '''
+     Calculate monthly means for every grid point
+     
+     Inputs:: 
+     	data - masked 3d array of the model data (time, lon, lat)
+     	time - an array of python datetime objects
+    '''
+    # Extract months from time variable
+    months = np.empty(len(time))
+    
+    for t in np.arange(len(time)):
+        months[t] = time[t].month
+    
+    #if there is data varying in t and space
+    if data.ndim == 3:
+        # empty array to store means
+        means = ma.empty((12, data.shape[1], data.shape[2]))
+        
+        # Calculate means month by month
+        for i in np.arange(12) + 1:
+            means[i - 1, :, :] = data[months == i, :, :].mean(0)
+        
+    #if the data is a timeseries over area-averaged values
+    if data.ndim == 1:
+        # TODO - Investigate using ma per KDW
+        means = np.empty((12)) # empty array to store means??WHY NOT ma?
+        
+        # Calculate means month by month
+        for i in np.arange(12) + 1:
+            means[i - 1] = data[months == i].mean(0)
+    
+    return means
+
+
+def calc_annual_cycle_std(data, time):
+    '''
+     Calculate monthly standard deviations for every grid point
+    '''
+    # Extract months from time variable
+    months = np.empty(len(time))
+    
+    for t in np.arange(len(time)):
+        months[t] = time[t].month
+    
+    # empty array to store means
+    stds = np.empty((12, data.shape[1], data.shape[2]))
+    
+    # Calculate means month by month
+    for i in np.arange(12) + 1:
+        stds[i - 1, :, :] = data[months == i, :, :].std(axis = 0, ddof = 1)
+    
+    return stds
+
+
+def calc_annual_cycle_domain_means(data, time):
+    '''
+     Calculate domain means for each month of the year
+    '''
+    # Extract months from time variable
+    months = np.empty(len(time))
+    
+    for t in np.arange(len(time)):
+        months[t] = time[t].month
+       	
+    means = np.empty(12) # empty array to store means
+    
+    # Calculate means month by month
+    for i in np.arange(12) + 1:
+        means[i - 1] = data[months == i, :, :].mean()
+    
+    return means
+
+
+def calc_annual_cycle_domain_std(data, time):
+    '''
+     Calculate domain standard deviations for each month of the year
+    '''
+    # Extract months from time variable
+    months = np.empty(len(time))
+    
+    for t in np.arange(len(time)):
+        months[t] = time[t].month
+    
+    stds = np.empty(12) # empty array to store means
+    
+    # Calculate means month by month
+    for i in np.arange(12) + 1:
+        stds[i - 1] = data[months == i, :, :].std(ddof = 1)
+    
+    return stds
+
+
+def calc_bias_annual(t1, t2, optn):        # Mean Bias
+    '''
+    Calculate the mean difference between two fields over time for each grid point.
+    '''
+    # Calculate mean difference between two fields over time for each grid point
+    # Precrocessing of both obs and model data ensures the absence of missing values
+    diff = t1-t2
+    if(open == 'abs'): 
+        diff = abs(diff)
+    bias = diff.mean(axis = 0)
+    return bias
+
+
+def calc_bias(t1, t2):
+    '''
+    Calculate mean difference between two fields over time for each grid point
+    
+    Classify missing data resulting from multiple times (using threshold 
+    data requirement)
+    
+    i.e. if the working time unit is monthly data, and we are dealing with 
+    multiple months of data then when we show mean of several months, we need
+    to decide what threshold of missing data we tolerate before classifying a
+    data point as missing data.
+    '''
+    t1Mask = process.create_mask_using_threshold(t1, threshold = 0.75)
+    t2Mask = process.create_mask_using_threshold(t2, threshold = 0.75)
+    
+    diff = t1 - t2
+    bias = diff.mean(axis = 0)
+    
+    # Set mask for bias metric using missing data in obs or model data series
+    #   i.e. if obs contains more than threshold (e.g.50%) missing data 
+    #        then classify time average bias as missing data for that location. 
+    bias = ma.masked_array(bias.data, np.logical_or(t1Mask, t2Mask))
+    return bias
+
+
+def calc_bias_dom(t1, t2):
+    '''
+     Calculate domain mean difference between two fields over time
+    '''
+    diff = t1 - t2
+    bias = diff.mean()
+    return bias
+
+
+def calc_difference(t1, t2):
+    '''
+     Calculate mean difference between two fields over time for each grid point
+    '''
+    print 'Calculating difference'
+    diff = t1 - t2
+    return diff
+
+
+def calc_mae(t1, t2):
+    '''
+    Calculate mean difference between two fields over time for each grid point
+    
+    Classify missing data resulting from multiple times (using threshold 
+    data requirement) 
+    
+    i.e. if the working time unit is monthly data, and we are dealing with
+    multiple months of data then when we show mean of several months, we need
+    to decide what threshold of missing data we tolerate before classifying
+    a data point as missing data.
+    '''
+    t1Mask = process.create_mask_using_threshold(t1, threshold = 0.75)
+    t2Mask = process.create_mask_using_threshold(t2, threshold = 0.75)
+    
+    diff = t1 - t2
+    adiff = abs(diff)
+    
+    mae = adiff.mean(axis = 0)
+    
+    # Set mask for mae metric using missing data in obs or model data series
+    #   i.e. if obs contains more than threshold (e.g.50%) missing data 
+    #        then classify time average mae as missing data for that location. 
+    mae = ma.masked_array(mae.data, np.logical_or(t1Mask, t2Mask))
+    return mae
+
+
+def calc_mae_dom(t1, t2):
+    '''
+     Calculate domain mean difference between two fields over time
+    '''
+    diff = t1 - t2
+    adiff = abs(diff)
+    mae = adiff.mean()
+    return mae
+
+
+def calc_rms(t1, t2):
+    '''
+     Calculate mean difference between two fields over time for each grid point
+    '''
+    diff = t1 - t2
+    sqdiff = diff ** 2
+    msd = sqdiff.mean(axis = 0)
+    rms = np.sqrt(msd)
+    return rms
+
+
+def calc_rms_dom(t1, t2):
+    '''
+     Calculate domain mean difference between two fields over time
+    '''
+    diff = t1 - t2
+    sqdiff = diff ** 2
+    msd = sqdiff.mean()
+    rms = np.sqrt(msd)
+    return rms
+
+
+def calc_temporal_stdv(t1):
+    '''
+    Calculate the temporal standard deviation.
+
+    Input:
+        t1 - data array of any shape
+
+    Output:
+        A 2-D array of temporal standard deviation
+    '''
+    # TODO Make sure the first dimension of t1 is teh time axis.
+    stdv = t1.std(axis = 0)
+    return stdv
+
+
+def calc_temporal_anom_cor(mD, oD):
+    '''
+    Calculate the temporal anomaly correlation.
+
+    Assumption(s);
+        The first dimension of mD and oD is the time axis.
+
+    Input:
+        mD - model data array of any shape
+        oD - observation data array of any shape
+
+    Output:
+        A 2-D array of time series pattern correlation coefficients at each grid point.
+
+    REF: 277-281 in Stat methods in atmos sci by Wilks, 1995, Academic Press, 467pp.
+    '''
+    mo = oD.mean(axis = 0)
+    nt = oD.shape[0]
+    deno1 = ((mD - mo) * (mD - mo)).sum(axis = 0)
+    deno2 = ((oD - mo) * (oD - mo)).sum(axis = 0)
+    patcor = ((mD - mo) * (oD - mo)).sum(axis = 0) / sqrt(deno1 * deno2)
+    return patcor
+
+
+def calc_spatial_anom_cor(mD, oD):
+    '''
+    Calculate anomaly correlation between two 2-D arrays.
+
+    Input:
+        mD - 2-D array of model data
+        oD - 2-D array of observation data
+
+    Output:
+        The anomaly correlation between the two input arrays.
+    '''
+    mo = oD.mean()
+    d1 = ((mD - mo)*(mD - mo)).sum()
+    d1 = ((oD - mo)*(oD - mo)).sum()
+    patcor = ((mD - mo) * (oD - mo)).sum() / sqrt(d1 * d2)
+    return patcor
+
+
+def calc_temporal_pat_cor(t1, t2):
+    '''
+     Calculate the Temporal Pattern Correlation
+    
+      Input::
+        t1 - 3d array of model data
+        t2 - 3d array of obs data
+         
+      Output::
+        2d array of time series pattern correlation coefficients at each grid point.
+        **Note:** std_dev is standardized on 1 degree of freedom
+    '''
+    mt1 = t1[:, :, :].mean(axis = 0)
+    mt2 = t2[:, :, :].mean(axis = 0)
+    nt = t1.shape[0]
+    sigma_t1 = t1.std(axis = 0, ddof = 1)
+    sigma_t2 = t2.std(axis = 0, ddof = 1)
+    # TODO - What is ddof=1?  Will a user want to change this value?
+    patcor = ((((t1[:, :, :] - mt1) * 
+                (t2[:, :, :] - mt2)).sum(axis = 0)) / 
+              (nt)) / (sigma_t1 * sigma_t2)
+    
+    return patcor
+
+
+def calc_spatial_pat_cor(t1, t2, nY, nX):
+    '''
+    Calcualte pattern correlation between 2-D arrays.
+
+    Input:
+        t1 - 2-D array of model data
+        t2 - 2-D array of observation data
+        nY
+        nX
+
+    Output:
+        Pattern correlation between two input arrays.
+    '''
+    # TODO - Update docstring. What are nY and nX?
+    mt1 = t1.mean()
+    mt2 = t2.mean()
+    st1 = t1.std()
+    st2 = t2.std()
+    patcor = ((t1 - mt1) * (t2 - mt2)).sum() / (float(nX * nY) * st1 * st2)
+    return patcor
+
+
+def calc_pat_cor2D(t1, t2, nT):
+    '''
+    Calculate the pattern correlation between 3-D input arrays.
+
+    Input:
+        t1 - 3-D array of model data
+        t2 - 3-D array of observation data
+        nT
+
+    Output:
+        1-D array (time series) of pattern correlation coefficients.
+    '''
+    # TODO - Update docstring. What is nT?
+    nt = t1.shape[0]
+    if(nt != nT):
+        print 'input time levels do not match: Exit', nT, nt
+        return -1
+    # store results in list for convenience (then convert to numpy array at the end)
+    patcor = []
+    for t in xrange(nt):
+        mt1 = t1[t, :, :].mean()
+        mt2 = t2[t, :, :].mean()
+        sigma_t1 = t1[t, :, :].std()
+        sigma_t2 = t2[t, :, :].std()
+        # TODO: make means and standard deviations weighted by grid box area.
+        patcor.append((((((t1[t, :, :] - mt1) * (t2[t, :, :] - mt2)).sum()) / 
+                     (t1.shape[1] * t1.shape[2]) ) / (sigma_t1 * sigma_t2)))
+        print t, mt1.shape, mt2.shape, sigma_t1.shape, sigma_t2.shape, patcor[t]
+    # TODO: deal with missing data appropriately, i.e. mask out grid points with missing data above tolerence level
+    # convert from list into numpy array
+    patcor = numpy.array(patcor)
+    print patcor.shape
+    return patcor
+
+def calc_pat_cor(dataset_1, dataset_2):
+    '''
+     Purpose: Calculate the Pattern Correlation Timeseries
+
+     Assumption(s)::  
+     	Both dataset_1 and dataset_2 are the same shape.
+        * lat, lon must match up
+        * time steps must align (i.e. months vs. months)
+    
+     Input::
+        dataset_1 - 3d (time, lat, lon) array of data
+        dataset_2 - 3d (time, lat, lon) array of data
+         
+     Output:
+        patcor - a 1d array (time series) of pattern correlation coefficients.
+    
+     **Note:** Standard deviation is using 1 degree of freedom.  Debugging print 
+     statements to show the difference the n-1 makes. http://docs.scipy.org/doc/numpy/reference/generated/numpy.std.html
+    '''
+
+    # TODO:  Add in try block to ensure the shapes match
+    nt = dataset_1.shape[0]
+    # store results in list for convenience (then convert to numpy array)
+    patcor = []
+    for t in xrange(nt):
+        # find mean and std_dev 
+        mt1 = dataset_1[t, :, :].mean()
+        mt2 = dataset_2[t, :, :].mean()
+        sigma_t1 = dataset_1[t, :, :].std(ddof = 1)
+        sigma_t2 = dataset_2[t, :, :].std(ddof=1)
+        
+        # TODO: make means and standard deviations weighted by grid box area.
+        # Equation from Santer_et_al 1995 
+        #     patcor = (1/(N*M_std*O_std))*sum((M_i-M_bar)*(O_i-O_bar))
+        patcor.append((((((dataset_1[t, :, :] - mt1) * 
+                          (dataset_2[t, :, :] - mt2)).sum()) / 
+                        (dataset_1.shape[1] * dataset_1.shape[2])) / (sigma_t1 * sigma_t2)))
+        print t, mt1.shape, mt2.shape, sigma_t1.shape, sigma_t2.shape, patcor[t]
+        
+        # TODO: deal with missing data appropriately, i.e. mask out grid points
+        # with missing data above tolerance level
+
+    # convert from list into numpy array
+    patcor = np.array(patcor)
+    
+    print patcor.shape
+    return patcor
+
+
+def calc_anom_corn(dataset_1, dataset_2, climatology = None):
+    '''
+    Calculate the anomaly correlation.
+
+    Input:
+        dataset_1 - First input dataset
+        dataset_2 - Second input dataset
+        climatology - Optional climatology input array. Assumption is that it is for 
+            the same time period by default.
+
+    Output:
+        The anomaly correlation.
+    '''
+    # TODO: Update docstring with actual useful information
+
+    # store results in list for convenience (then convert to numpy array)
+    anomcor = []    
+    nt = dataset_1.shape[0]
+    #prompt for the third file, i.e. climo file...  
+    #include making sure the lat, lon and times are ok for comparision
+    # find the climo in here and then using for eg, if 100 yrs 
+    # is given for the climo file, but only looking at 10yrs
+    # ask if want to input climo dataset for use....if no, call previous 
+   
+    if climatology != None:
+        climoFileOption = raw_input('Would you like to use the full observation dataset as \
+                                     the climatology in this calculation? [y/n] \n>')
+        if climoFileOption == 'y':
+            base_dataset = climatology
+        else:
+            base_dataset = dataset_2
+    for t in xrange(nt):
+        mean_base = base_dataset[t, :, :].mean()
+        anomcor.append((((dataset_1[t, :, :] - mean_base) * (dataset_2[t, :, :] - mean_base)).sum()) / 
+                       np.sqrt(((dataset_1[t, :, :] - mean_base) ** 2).sum() * 
+                               ((dataset_2[t, :, :] - mean_base) ** 2).sum()))
+        print t, mean_base.shape, anomcor[t]
+
+    # TODO: deal with missing data appropriately, i.e. mask out grid points 
+    # with missing data above tolerence level
+    
+    # convert from list into numpy array
+    anomcor = np.array(anomcor)
+    print anomcor.shape, anomcor.ndim, anomcor
+    return anomcor
+
+
+def calc_anom_cor(t1, t2):
+    '''
+     Calculate the Anomaly Correlation (Deprecated)
+    '''
+    
+    nt = t1.shape[0]
+    
+    # store results in list for convenience (then convert to numpy 
+    # array at the end)
+    anomcor = []
+    for t in xrange(nt):
+        
+        mt2 = t2[t, :, :].mean()
+        
+        sigma_t1 = t1[t, :, :].std(ddof = 1)
+        sigma_t2 = t2[t, :, :].std(ddof = 1)
+        
+        # TODO: make means and standard deviations weighted by grid box area.
+        
+        anomcor.append(((((t1[t, :, :] - mt2) * (t2[t, :, :] - mt2)).sum()) / 
+                        (t1.shape[1] * t1.shape[2])) / (sigma_t1 * sigma_t2))
+        
+        print t, mt2.shape, sigma_t1.shape, sigma_t2.shape, anomcor[t]
+        
+        # TODO: deal with missing data appropriately, i.e. mask out grid points with 
+        #       missing data above tolerence level
+        
+    # convert from list into numpy array
+    anomcor = np.array(anomcor)
+    print anomcor.shape, anomcor.ndim, anomcor
+    return anomcor
+
+
+def calc_nash_sutcliff(dataset_1, dataset_2):
+    '''
+    Routine to calculate the Nash-Sutcliff coefficient of efficiency (E)
+    
+    Assumption(s)::  
+    	Both dataset_1 and dataset_2 are the same shape.
+        * lat, lon must match up
+        * time steps must align (i.e. months vs. months)
+    
+    Input::
+    	dataset_1 - 3d (time, lat, lon) array of data
+        dataset_2 - 3d (time, lat, lon) array of data
+    
+    Output:
+        nashcor - 1d array aligned along the time dimension of the input
+        datasets. Time Series of Nash-Sutcliff Coefficient of efficiency
+     
+     '''
+
+    nt = dataset_1.shape[0]
+    nashcor = []
+    for t in xrange(nt):
+        mean_dataset_2 = dataset_2[t, :, :].mean()
+        
+        nashcor.append(1 - ((((dataset_2[t, :, :] - dataset_1[t, :, :]) ** 2).sum()) / 
+                            ((dataset_2[t, :, :] - mean_dataset_2) ** 2).sum()))
+        
+        print t, mean_dataset_2.shape, nashcor[t]
+        
+    nashcor = np.array(nashcor)
+    print nashcor.shape, nashcor.ndim, nashcor
+    return nashcor
+
+
+def calc_pdf(dataset_1, dataset_2):
+    '''
+    Routine to calculate a normalized Probability Distribution Function with 
+    bins set according to data range.
+    Equation from Perkins et al. 2007
+
+        PS=sum(min(Z_O_i, Z_M_i)) where Z is the distribution (histogram of the data for either set)
+        called in do_rcmes_processing_sub.py
+         
+    Inputs::
+        2 arrays of data
+        t1 is the modelData and t2 is 3D obsdata - time,lat, lon NB, time here 
+        is the number of time values eg for time period 199001010000 - 199201010000 
+        
+        if annual means-opt 1, was chosen, then t2.shape = (2,lat,lon)
+        
+        if monthly means - opt 2, was choosen, then t2.shape = (24,lat,lon)
+        
+    User inputs: number of bins to use and edges (min and max)
+    Output:
+
+        one float which represents the PDF for the year
+
+    TODO:  Clean up this docstring so we have a single purpose statement
+     
+    Routine to calculate a normalised PDF with bins set according to data range.
+
+    Input::
+        2 data  arrays, modelData and obsData
+
+    Output::
+        PDF for the year
+
+    '''
+    #list to store PDFs of modelData and obsData
+    pdf_mod = []
+    pdf_obs = []
+    # float to store the final PDF similarity score
+    similarity_score = 0.0
+    d1_max = dataset_1.amax()
+    d1_min = dataset_1.amin()
+
+    print 'min modelData', dataset_1[:, :, :].min()
+    print 'max modelData', dataset_1[:, :, :].max()
+    print 'min obsData', dataset_2[:, :, :].min()
+    print 'max obsData', dataset_2[:, :, :].max()
+    # find a distribution for the entire dataset
+    #prompt the user to enter the min, max and number of bin values. 
+    # The max, min info above is to help guide the user with these choises
+    print '****PDF input values from user required **** \n'
+    nbins = int (raw_input('Please enter the number of bins to use. \n'))
+    minEdge = float(raw_input('Please enter the minimum value to use for the edge. \n'))
+    maxEdge = float(raw_input('Please enter the maximum value to use for the edge. \n'))
+    
+    mybins = np.linspace(minEdge, maxEdge, nbins)
+    print 'nbins is', nbins, 'mybins are', mybins
+    
+    
+    # TODO:  there is no 'new' kwargs for numpy.histogram 
+    # per: http://docs.scipy.org/doc/numpy/reference/generated/numpy.histogram.html
+    # PLAN: Replace new with density param.
+    pdf_mod, edges = np.histogram(dataset_1, bins = mybins, normed = True, new = True)  
+    print 'dataset_1 distribution and edges', pdf_mod, edges
+    pdf_obs, edges = np.histogram(dataset_2, bins = mybins, normed = True, new = True)           
+    print 'dataset_2 distribution and edges', pdf_obs, edges    
+    
+    # TODO: drop this
+    """
+    considering using pdf function from statistics package. It is not 
+     installed. Have to test on Mac.  
+     http://bonsai.hgc.jp/~mdehoon/software/python/Statistics/manual/index.xhtml#TOC31 
+    pdf_mod, edges = stats.pdf(dataset_1, bins=mybins)
+    print 'dataset_1 distribution and edges', pdf_mod, edges
+    pdf_obs,edges=stats.pdf(dataset_2,bins=mybins)           
+    print 'dataset_2 distribution and edges', pdf_obs, edges 
+    """
+
+    #find minimum at each bin between lists 
+    i = 0
+    for model_value in pdf_mod :
+        print 'model_value is', model_value, 'pdf_obs[', i, '] is', pdf_obs[i]
+        if model_value < pdf_obs[i]:
+            similarity_score += model_value
+        else:
+            similarity_score += pdf_obs[i] 
+        i += 1 
+    print 'similarity_score is', similarity_score
+    return similarity_score
+
+
+def calc_stdev(t1):
+    ''' 
+    Calculate the standard deviation for a given dataset.
+
+    Input:
+        t1 - Dataset to calculate the standard deviation on.
+
+    Output:
+        Array of the standard deviations for each month in the provided dataset.
+    '''
+    nt = t1.shape[0]
+    sigma_t1 = []
+    for t in xrange(nt):
+        sigma_t1.append(t1[t, :, :].std(ddof = 1))
+    sigma_t1 = np.array(sigma_t1)
+    print sigma_t1, sigma_t1.shape
+    return sigma_t1
+
+
+def metrics_plots(varName, numOBS, numMDL, nT, ngrdY, ngrdX, Times, lons,
+                  lats, obsData, mdlData, obsList, mdlList, workdir, subRegions, fileOutputOption):
+    '''
+    Calculate evaluation metrics and generate plots.
+    '''
+    ##################################################################################################################
+    # Routine to compute evaluation metrics and generate plots
+    #    (1)  metric calculation
+    #    (2) plot production
+    #    Input: 
+    #        numOBS           - the number of obs data. either 1 or >2 as obs ensemble is added for multi-obs cases
+    #        numMDL           - the number of mdl data. either 1 or >2 as obs ensemble is added for multi-mdl cases
+    #        nT               - the length of the data in the time dimension
+    #        ngrdY            - the length of the data in Y dimension
+    #        ngrdX            - the length of the data in the X dimension
+    #        Times            - time stamps
+    #        lons,lats        - longitude & latitude values of the data domain (same for model & obs)
+    #        obsData          - obs data, either a single or multiple + obs_ensemble, interpolated onto the time- and
+    #                           grid for analysis
+    #        mdlData          - mdl data, either a single or multiple + obs_ensemble, interpolated onto the time- and
+    #                           spatial grid for analysis
+    #JK2.0:  obsRgn           - obs time series averaged for subregions: Local variable in v2.0
+    #JK2.0:  mdlRgn           - obs time series averaged for subregions: Local variable in v2.0
+    #        obsList          - string describing the observation data files
+    #        mdlList          - string describing model file names
+    #        workdir        - string describing the directory path for storing results and plots
+    #        subRegions        - list of SubRegion Objects or False
+    #JK2.0:  mdlSelect        - the mdl data to be evaluated: Locally determined in v.2.0
+    #JK2.0:  obsSelect        - the obs data to be used as the reference for evaluation: Locally determined in v.2.0
+    #JK2.0:  numSubRgn        - the number of subregions: Locally determined in v.2.0
+    #JK2.0:  subRgnName       - the names of subregions: Locally determined in v.2.0
+    #JK2.0:  rgnSelect        - the region for which the area-mean time series is to be 
+    #                               evaluated/plotted: Locally determined in v.2.0
+    #        obsParameterId   - int, db parameter id. ** this is non-essential once the correct 
+    #                               metadata use is implemented
+    #      precipFlag       - to be removed once the correct metadata use is implemented
+    #        timeRegridOption - string: 'full'|'annual'|'monthly'|'daily'
+    #        seasonalCycleOption - int (=1 if set) (probably should be bool longterm) 
+    #      metricOption - string: 'bias'|'mae'|'acc'|'pdf'|'patcor'|'rms'|'diff'
+    #        titleOption - string describing title to use in plot graphic
+    #        plotFileNameOption - string describing filename stub to use for plot graphic i.e. {stub}.png
+    #    Output: image files of plots + possibly data
+    #******************************************************
+    # JK2.0: Only the data interpolated temporally and spatially onto the analysis grid 
+    #        are transferred into this routine. The rest of processing (e.g., area-averaging, etc.) 
+    #        are to be performed in this routine. Do not overwrite obsData[numOBs,nt,ngrdY,ngrdX] & 
+    #        mdlData[numMDL,nt,ngrdY,ngrdX]. These are the raw, re-gridded data to be used repeatedly 
+    #        for multiple evaluation steps as desired by an evaluator
+    ##################################################################################################################
+
+    #####################################################################################################
+    # JK2.0: Compute evaluation metrics and plots to visualize the results
+    #####################################################################################################
+    # (mp.001) Sub-regions for local timeseries analysis
+    #--------------------------------
+    # Enter the location of the subrgns via screen input of data; 
+    # modify this to add an option to read-in from data file(s)
+    #----------------------------------------------------------------------------------------------------
+    if subRegions:
+        numSubRgn = len(subRegions)
+        subRgnName = [ x.name   for x in subRegions ]
+        subRgnLon0 = [ x.lonMin for x in subRegions ]
+        subRgnLon1 = [ x.lonMax for x in subRegions ]
+        subRgnLat0 = [ x.latMin for x in subRegions ]
+        subRgnLat1 = [ x.latMax for x in subRegions ]
+    else:
+        print ''
+        ans = raw_input('Calculate area-mean timeseries for subregions? y/n: [n] \n')
+        print ''
+        if ans == 'y':
+            ans = raw_input('Input subregion info interactively? y/n: \n> ')
+            if ans == 'y':
+                numSubRgn, subRgnName, subRgnLon0, subRgnLon1, subRgnLat0, subRgnLat1 = misc.assign_subRgns_interactively()
+            else:
+                print 'Read subregion info from a pre-fabricated text file'
+                ans = raw_input('Read from a defaule file (workdir + "/sub_regions.txt")? y/n: \n> ')
+                if ans == 'y':
+                    subRgnFileName = workdir + "/sub_regions.txt"
+                else:
+                    subRgnFileName = raw_input('Enter the subRgnFileName to read from \n')
+                print 'subRgnFileName ', subRgnFileName
+                numSubRgn, subRgnName, subRgnLon0, subRgnLon1, subRgnLat0, subRgnLat1 = misc.assign_subRgns_from_a_text_file(subRgnFileName)
+            print subRgnName, subRgnLon0, subRgnLon1, subRgnLat0, subRgnLat1
+        else:
+            numSubRgn = 0
+    # compute the area-mean timeseries for all subregions if subregion(s) are defined.
+    #   the number of subregions is usually small and memory usage is usually not a concern
+    
+    obsRgn = ma.zeros((numOBS, numSubRgn, nT))
+    mdlRgn = ma.zeros((numMDL, numSubRgn, nT))
+            
+    if subRegions:        
+        print 'Enter area-averaging: mdlData.shape, obsData.shape ', mdlData.shape, obsData.shape
+        print 'Using Latitude/Longitude Mask for Area Averaging'  
+        for n in np.arange(numSubRgn):
+            # Define mask using regular lat/lon box specified by users ('mask=True' defines the area to be excluded)
+            maskLonMin = subRegions[n].lonMin 
+            maskLonMax = subRegions[n].lonMax
+            maskLatMin = subRegions[n].latMin
+            maskLatMax = subRegions[n].latMax
+            mask = np.logical_or(np.logical_or(lats <= maskLatMin, lats >= maskLatMax), 
+                                np.logical_or(lons <= maskLonMin, lons >= maskLonMax))
+            
+            # Calculate area-weighted averages within this region and store in a new list
+            for k in np.arange(numOBS):           # area-average obs data
+                Store = []
+                for t in np.arange(nT):
+                    Store.append(process.calc_area_mean(obsData[k, t, :, :], lats, lons, mymask = mask))
+                obsRgn[k, n, :] = ma.array(Store[:])
+            for k in np.arange(numMDL):           # area-average mdl data
+                Store = []
+                for t in np.arange(nT):
+                    Store.append(process.calc_area_mean(mdlData[k, t, :, :], lats, lons, mymask = mask))
+                mdlRgn[k, n, :] = ma.array(Store[:])
+            Store = []                               # release the memory allocated by temporary vars
+
+    #-------------------------------------------------------------------------
+    # (mp.002) fileOutputOption: The option to create a binary or netCDF file of processed 
+    #                      (re-gridded and regionally-averaged) data for user-specific processing. 
+    #                      This option is useful for advanced users who need more than
+    #                      the metrics and vidualization provided in the basic package.
+    #----------------------------------------------------------------------------------------------------
+    print ''
+    if not fileOutputOption:
+        while fileOutputOption not in ['no', 'nc']:
+            fileOutputOption = raw_input('Option for output files of obs/model data: Enter no/nc \
+                                for no, netCDF file \n> ').lower()
+    print ''
+    # write a binary file for post-processing if desired
+    if fileOutputOption == 'bn':
+        fileName = workdir + '/lonlat_eval_domain' + '.bn'
+        if(os.path.exists(fileName) == True):
+            cmnd = 'rm -f ' + fileName
+            subprocess.call(cmnd, shell=True)
+        files.writeBN_lola(fileName, lons, lats)
+        fileName = workdir + '/Tseries_' + varName + '.bn'
+        print "Create regridded data file ", fileName, " for offline processingr"
+        print 'The file includes time series of ', numOBS, ' obs and ', numMDL, \
+            ' models ', nT, ' steps ', ngrdX, 'x', ngrdY, ' grids'
+        if(os.path.exists(fileName) == True):
+            cmnd = 'rm -f ' + fileName
+            subprocess.call(cmnd, shell=True)
+        files.writeBNdata(fileName, numOBS, numMDL, nT, ngrdX, ngrdY, numSubRgn, obsData, mdlData, obsRgn, mdlRgn)
+        print 'The regridded obs and model data are written in the binary file ', fileName
+
+    # write a netCDF file for post-processing if desired
+    if fileOutputOption == 'nc':
+        fileName = '%s/%s_Tseries' % (workdir, varName)
+        tempName = fileName + '.' + 'nc'
+        if(os.path.exists(tempName) == True):
+            print "removing %s from the local filesystem, so it can be replaced..." % (tempName,)
+            cmnd = 'rm -f ' + tempName
+            subprocess.call(cmnd, shell=True)
+        files.writeNCfile(fileName, numSubRgn, lons, lats, obsData, mdlData, obsRgn, mdlRgn, obsList, mdlList, subRegions)
+        print 'The regridded obs and model data are written in the netCDF file ', fileName
+
+
+    #####################################################################################################
+    ###################### Metrics calculation and plotting cycle starts from here ######################
+    #####################################################################################################
+
+    print ''
+    print 'OBS and MDL data have been prepared for the evaluation step'
+    print ''
+    doMetricsOption = raw_input('Want to calculate metrics and plot them? [y/n]\n> ').lower()
+    print ''
+
+    ####################################################
+    # Terminate job if no metrics are to be calculated #
+    ####################################################
+
+    neval = 0
+
+    while doMetricsOption == 'y':
+        neval += 1
+        print ' '
+        print 'neval= ', neval
+        print ' '
+        #--------------------------------
+        # (mp.003) Preparation
+        #----------------------------------------------------------------------------------------------------
+        # Determine info on years (the years in the record [YR] and its number[numYR])
+        yy = ma.zeros(nT, 'i')
+        for n in np.arange(nT):
+            yy[n] = Times[n].strftime("%Y")
+        YR = np.unique(yy)
+        yy = 0
+        nYR = len(YR)
+        print 'nYR, YR = ', nYR, YR
+
+        # Select the eval domain: over the entire domain (spatial distrib) or regional time series
+        anlDomain = 'n'
+        anlRgn = 'n'
+        print ' '
+        analSelect = int(raw_input('Eval over domain (Enter 0) or time series of selected Sub Regions (Enter 1) \n> '))
+        print ' '
+        if analSelect == 0:
+            anlDomain = 'y'
+        elif analSelect == 1:
+            anlRgn = 'y'
+        else:
+            print 'analSelect= ', analSelect, ' is Not a valid option: CRASH'
+            sys.exit()
+
+        #--------------------------------
+        # (mp.004) Select the model and data to be used in the evaluation step
+        #----------------------------------------------------------------------------------------------------
+        mdlSelect = misc.select_data(numMDL, Times, mdlList, 'mdl')
+        obsSelect = misc.select_data(numOBS, Times, obsList, 'obs')
+        mdlName = mdlList[mdlSelect]
+        obsName = obsList[obsSelect]
+        print 'selected obs and model for evaluation= ', obsName, mdlName
+
+
+        #--------------------------------
+        # (mp.005) Spatial distribution analysis/Evaluation (anlDomain='y')
+        #          All climatology variables are 2-d arrays (e.g., mClim = ma.zeros((ngrdY,ngrdX))
+        #----------------------------------------------------------------------------------------------------
+        if anlDomain == 'y':
+            # first determine the temporal properties to be evaluated
+            print ''
+            timeOption = misc.select_timOpt()
+            print ''
+            if timeOption == 1:
+                timeScale = 'Annual'
+                # compute the annual-mean time series and climatology. 
+                # mTser=ma.zeros((nYR,ngrdY,ngrdX)), mClim = ma.zeros((ngrdY,ngrdX))
+                mTser, mClim = calc_clim_year(nYR, nT, ngrdY, ngrdX, mdlData[mdlSelect, :, :, :], Times)
+                oTser, oClim = calc_clim_year(nYR, nT, ngrdY, ngrdX, obsData[obsSelect, :, :, :], Times)
+            elif timeOption == 2:
+                timeScale = 'Seasonal'
+                # select the timeseries and climatology for a season specifiec by a user
+                print ' '
+                moBgn = int(raw_input('Enter the beginning month for your season. 1-12: \n> '))
+                moEnd = int(raw_input('Enter the ending month for your season. 1-12: \n> '))
+                print ' '
+                if moEnd >= moBgn:
+                    nMoPerSeason = moEnd - moBgn + 1
+                    mTser, mClim = calc_clim_season(nYR, nT, moBgn, moEnd, ngrdY, ngrdX, 
+                                                                mdlData[mdlSelect, :, :, :], Times)
+                    oTser, oClim = calc_clim_season(nYR, nT, moBgn, moEnd, ngrdY, ngrdX, 
+                                                                obsData[obsSelect, :, :, :], Times)
+                elif moEnd == moBgn:
+                    # Eval for a single month. mTser, oTser are the annual time series 
+                    # for the specified month (moEnd), and  mClim, oClim are the corresponding climatology
+                    mTser, mClim = calc_clim_One_month(moEnd, nYR, nT, mdlData[mdlSelect, :, :, :], Times)
+                    oTser, oClim = calc_clim_One_month(moEnd, nYR, nT, obsData[obsSelect, :, :, :], Times)
+                elif moEnd < moBgn:        # have to lose the ending year. redefine nYR=nYR-1, and drop the YR[nYR]
+                    nMoS1 = 12 - moBgn + 1
+                    nMoS2 = moEnd
+                    nMoPerSeason = nMoS1 + nMoS2
+                    # calculate the seasonal timeseries and climatology for the model data
+                    mTser1, mClim1 = calc_clim_season(nYR, nT, moBgn, 12, ngrdY, ngrdX, 
+                                                                mdlData[mdlSelect, :, :, :], Times)
+                    mTser2, mClim2 = calc_clim_season(nYR, nT, 1, moEnd, ngrdY, ngrdX, 
+                                                                mdlData[mdlSelect, :, :, :], Times)
+                    mTser = ma.zeros((nYR - 1, ngrdY, ngrdX))
+                    for i in np.arange(nYR - 1):
+                        mTser[i, :, :] = (real(nMoS1) * mTser1[i, :, :] + 
+                            real(nMoS2) * mTser2[i + 1, :, :]) / nMoPerSeason
+                    mClim = ma.zeros((ngrdY, ngrdX))
+                    mClim = ma.average(mTser, axis=0)
+                    # repeat for the obs data
+                    mTser1, mClim1 = calc_clim_season(nYR, nT, moBgn, 12, ngrdY, ngrdX, 
+                                                                obsData[obsSelect, :, :, :], Times)
+                    mTser2, mClim2 = calc_clim_season(nYR, nT, 1, moEnd, ngrdY, ngrdX, 
+                                                                obsData[obsSelect, :, :, :], Times)
+                    oTser = ma.zeros((nYR - 1, ngrdY, ngrdX))
+                    for i in np.arange(nYR - 1):
+                        oTser[i, :, :] = (real(nMoS1) * mTser1[i, :, :] + 
+                            real(nMoS2) * mTser2[i + 1, :, :]) / nMoPerSeason
+                    oClim = ma.zeros((ngrdY, ngrdX))
+                    oClim = ma.average(oTser, axis=0)
+                    nYR = nYR - 1
+                    yy = ma.empty(nYR)
+                    for i in np.arange(nYR):
+                        yy[i] = YR[i]
+                    mTser1 = 0.
+                    mTser2 = 0.
+                    mClim1 = 0.
+                    mClim2 = 0.
+            elif timeOption == 3:
+                timeScale = 'Monthly'
+                # compute the monthly-mean time series and climatology
+                # Note that the shapes of the output vars are: 
+                #   mTser = ma.zeros((nYR,12,ngrdY,ngrdX)) & mClim = ma.zeros((12,ngrdY,ngrdX))
+                # Also same for oTser = ma.zeros((nYR,12,ngrdY,ngrdX)) &,oClim = ma.zeros((12,ngrdY,ngrdX))
+                mTser, mClim = calc_clim_mo(mdlData[mdlSelect, :, :, :], Times)
+                oTser, oClim = calc_clim_mo(obsData[mdlSelect, :, :, :], Times)
+            else:
+                # undefined process options. exit
+                print 'The desired temporal scale is not available this time. END the job'
+                sys.exit()
+
+            #--------------------------------
+            # (mp.006) Select metric to be calculated
+            # bias, mae, acct, accs, pcct, pccs, rmst, rmss, pdfSkillScore
+            #----------------------------------------------------------------------------------------------------
+            print ' '
+            metricOption = misc.select_metrics()
+            print ' '
+
+            # metrics below yields 2-d array, i.e., metricDat = ma.zeros((ngrdY,ngrdX))
+            if metricOption == 'BIAS':
+                metricDat = calc_bias(mTser, oTser)
+                oStdv = calc_temporal_stdv(oTser)
+            elif metricOption == 'MAE':
+                metricDat = calc_mae(mTser, oTser)
+            elif metricOption == 'ACCt':
+                metricDat = calc_temporal_anom_cor(mTser, oTser)
+            elif metricOption == 'PCCt':
+                metricDat = calc_temporal_pat_cor(mTser, oTser)
+            elif metricOption == 'RMSt':
+                metricDat = calc_rms(mTser, oTser)
+
+            # metrics below yields a scalar values
+            elif metricOption == 'ACCs':
+                metricDat = spatial_anom_cor(mClim, oClim)
+            elif metricOption == 'PCCs':
+                metricDat = spatial_pat_cor(mClim, oClim, ngrdY, ngrdX)
+            elif metricOption == 'RMSs':
+                metricDat = rms_dom(mClim, oClim)
+
+            #--------------------------------
+            # (mp.007) Plot the metrics. First, enter plot info
+            #----------------------------------------------------------------------------------------------------
+
+            # 2-d contour plots
+            if metricDat.ndim == 2:
+                # assign plot file name and delete old (un-saved) plot files
+                plotFileName = workdir + '/' + timeScale + '_' + varName + '_' + metricOption 
+                if(os.path.exists(plotFileName) == True):
+                    cmnd = 'rm -f ' + plotFileName
+                    subprocess.call(cmnd, shell=True)
+                # assign plot title
+                plotTitle = metricOption + '_' + varName
+                # Data-specific plot options: i.e. adjust model data units & set plot color bars
+                #cMap = 'rainbow'
+                cMap = 'BlRe'
+                #cMap = 'BlWhRe'
+                #cMap = 'BlueRed'
+                #cMap = 'GreyWhiteGrey'
+                # Calculate color bar ranges for data such that same range is used 
+                # in obs and model plots for like-with-like comparison.
+                obsDataMask = np.zeros_like(oClim.data[:, :])
+                metricDat = ma.masked_array(metricDat, obsDataMask)
+                oClim = ma.masked_array(oClim, obsDataMask)
+                oStdv = ma.masked_array(oStdv, obsDataMask)
+                plotDat = metricDat
+                mymax = plotDat.max()
+                mymin = plotDat.min()
+                if metricOption == 'BIAS':
+                    abs_mymin = abs(mymin)
+                    if abs_mymin <= mymax:
+                        mymin = -mymax
+                    else:
+                        mymax = abs_mymin
+                print 'Plot bias over the model domain: data MIN/MAX= ', mymin, mymax
+                ans = raw_input('Do you want to use different scale for plotting? [y/n]\n> ').lower()
+                if ans == 'y':
+                    mymin = float(raw_input('Enter the minimum plot scale \n> '))
+                    mymax = float(raw_input('Enter the maximum plot scale \n> '))
+                wksType = 'ps'
+                # TODO This shouldn't return anything. Handle a "status" the proper way
+                _ = plots.draw_cntr_map_single(plotDat, lons, lats, mymin, mymax, 
+                                                      plotTitle, plotFileName, cMap, wksType)
+                # if bias, plot also normalzied values and means: first, normalized by mean
+                if metricOption == 'BIAS':
+                    print ''
+                    makePlot = raw_input('Plot bias in terms of % of OBS mean? [y/n]\n> ').lower()
+                    print ''
+                    if makePlot == 'y':
+                        plotDat = 100.*metricDat / oClim
+                        mymax = plotDat.max()
+                        mymin = plotDat.min()
+                        mymn = -100.
+                        mymx = 105.
+                        print 'Plot mean-normalized bias: data MIN/MAX= ', mymin, mymax, \
+                            ' Default MIN/MAX= ', mymn, mymx
+                        ans = raw_input('Do you want to use different scale for plotting? [y/n]\n> ').lower()
+                        if ans == 'y':
+                            mymin = float(raw_input('Enter the minimum plot scale \n> '))
+                            mymax = float(raw_input('Enter the maximum plot scale \n> '))
+                        else:
+                            mymin = mymn
+                            mymax = mymx
+                        plotFileName = workdir + '/' + timeScale + '_' + varName + '_' + metricOption + '_Mean'
+                        if(os.path.exists(plotFileName) == True):
+                            cmnd = 'rm -f ' + plotFileName
+                            subprocess.call(cmnd, shell = True)
+                        plotTitle = 'Bias (% MEAN)'
+                        # TODO Again, this shouldn't return a status
+                        _ = plots.draw_cntr_map_single(plotDat, lons, lats, mymin, mymax, 
+                                                              plotTitle, plotFileName, cMap, wksType)
+                # normalized by sigma
+                makePlot = raw_input('Plot bias in terms of % of interann sigma? [y/n]\n> ').lower()
+                if makePlot == 'y':
+                    plotDat = 100.*metricDat / oStdv
+                    mymax = plotDat.max()
+                    mymin = plotDat.min()
+                    mymn = -200.
+                    mymx = 205.
+                    print 'Plot STD-normalized bias: data MIN/MAX= ', mymin, mymax, ' Default MIN/MAX= ', mymn, mymx
+                    ans = raw_input('Do you want to use different scale for plotting? [y/n]\n> ').lower()
+                    if ans == 'y':
+                        mymin = float(raw_input('Enter the minimum plot scale \n> '))
+                        mymax = float(raw_input('Enter the maximum plot scale \n> '))
+                    else:
+                        mymin = mymn
+                        mymax = mymx
+                    plotFileName = workdir + '/' + timeScale + '_' + varName + '_' + metricOption + '_SigT'
+                    if(os.path.exists(plotFileName) == True):
+                        cmnd = 'rm -f ' + plotFileName
+                        subprocess.call(cmnd, shell = True)
+                    plotTitle = 'Bias (% SIGMA_time)'
+                    # TODO Hay look! A todo re. status returns!
+                    _ = plots.draw_cntr_map_single(plotDat, lons, lats, mymin, mymax, 
+                                                          plotTitle, plotFileName, cMap, wksType)
+                # obs climatology
+                makePlot = raw_input('Plot observation? [y/n]\n> ').lower()
+                if makePlot == 'y':
+                    if varName == 'pr':
+                        cMap = 'precip2_17lev'
+                    else:
+                        cMap = 'BlRe'
+                    plotDat = oClim
+                    mymax = plotDat.max()
+                    mymin = plotDat.min()
+                    print 'Plot STD-normalized bias over the model domain: data MIN/MAX= ', mymin, mymax
+                    ans = raw_input('Do you want to use different scale for plotting? [y/n]\n> ').lower()
+                    if ans == 'y':
+                        mymin = float(raw_input('Enter the minimum plot scale \n> '))
+                        mymax = float(raw_input('Enter the maximum plot scale \n> '))
+                    plotFileName = workdir + '/' + timeScale + '_' + varName + '_OBS'
+                    if(os.path.exists(plotFileName) == True):
+                        cmnd = 'rm -f ' + plotFileName
+                        subprocess.call(cmnd, shell=True)
+                    plotTitle = 'OBS (mm/day)'
+                    # TODO Yep
+                    _ = plots.draw_cntr_map_single(plotDat, lons, lats, mymin, mymax, 
+                                                          plotTitle, plotFileName, cMap, wksType)
+
+                # Repeat for another metric
+                print ''
+                print 'Evaluation completed'
+                print ''
+                doMetricsOption = raw_input('Do you want to perform another evaluation? [y/n]\n> ').lower()
+                print ''
+
+        # metrics and plots for regional time series
+        elif anlRgn == 'y' and subRegions == False:
+            print 'No SubRegions have been defined.  Regional Time Series Plots cannot be created'
+
+        elif anlRgn == 'y':
+            # select the region(s) for evaluation. model and obs have been selected before entering this if block
+            print 'There are %s subregions. Select the subregion(s) for evaluation' % numSubRgn
+            rgnSelect = misc.selectSubRegion(subRegions)
+            print 'selected region for evaluation= ', rgnSelect
+            # Select the model & obs data to be evaluated
+            oData = ma.zeros(nT)
+            mData = ma.zeros(nT)
+            oData = obsRgn[obsSelect, rgnSelect, :]
+            mData = mdlRgn[mdlSelect, rgnSelect, :]
+
+            # compute the monthly-mean climatology to construct the annual cycle
+            obsAnnCyc = calc_annual_cycle_means(oData, Times)
+            mdlAnnCyc = calc_annual_cycle_means(mData, Times)
+            print 'obsAnnCyc= ', obsAnnCyc
+            print 'mdlAnnCyc= ', mdlAnnCyc
+
+            #--------------------------------
+            # (mp.008) Select performance metric
+            #----------------------------------------------------------------------------------------------------
+            #metricOption = misc.select_metrics()
+            # Temporarily, compute the RMSE and pattern correlation for the simulated 
+            # and observed annual cycle based on monthly means
+            # TODO tempRMS and tempCOR are not used in the code and throwing errors.
+#            tempRMS = calc_rms(mdlAnnCyc, obsAnnCyc)
+#            tempCOR = calc_temporal_pat_cor(mdlAnnCyc, obsAnnCyc)
+
+            #--------------------------------
+            # (mp.009) Plot results
+            #----------------------------------------------------------------------------------------------------
+            # Data-specific plot options: i.e. adjust model data units & set plot color bars
+            colorbar = 'rainbow'
+            if varName == 'pr':                      # set color bar for prcp
+                colorbar = 'precip2_17lev'
+
+            # 1-d data, e.g. Time series plots
+            plotFileName = 'anncyc_' + varName + '_' + subRegions[rgnSelect].name
+            if(os.path.exists(plotFileName) == True):
+                cmnd = 'rm -f ' + plotFileName
+                subprocess.call(cmnd, shell = True)
+            year_labels = False         # for annual cycle plots
+            mytitle = 'Annual Cycle of ' + varName + ' at Sub-Region ' + subRegions[rgnSelect].name
+            # Create a list of datetimes to represent the annual cycle, one per month.
+            times = []
+            for m in xrange(12):
+                times.append(datetime.datetime(2000, m + 1, 1, 0, 0, 0, 0))
+            #for i in np.arange(12):
+            #  times.append(i+1)
+            _ = plots.draw_time_series_plot(mdlAnnCyc, times, plotFileName, workdir, 
+                                                   data2 = obsAnnCyc, mytitle = mytitle, ytitle = 'Y', 
+                                                   xtitle = 'MONTH', year_labels = year_labels)
+
+            # Repeat for another metric
+            doMetricsOption = raw_input('Do you want to perform another evaluation? [y/n]\n> ').lower()
+
+    # Processing complete if a user enters 'n' for 'doMetricsOption'
+    print 'RCMES processing completed.'
+
+

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/rcmes/toolkit/.svn/text-base/plots.py.svn-base
----------------------------------------------------------------------
diff --git a/src/main/python/rcmes/toolkit/.svn/text-base/plots.py.svn-base b/src/main/python/rcmes/toolkit/.svn/text-base/plots.py.svn-base
new file mode 100755
index 0000000..deee64c
--- /dev/null
+++ b/src/main/python/rcmes/toolkit/.svn/text-base/plots.py.svn-base
@@ -0,0 +1,443 @@
+"""Module that handles the generation of data plots"""
+
+
+# Import Statements
+
+from math import floor, log
+import matplotlib
+import Ngl 
+import numpy as np
+import pylab
+import os
+
+
+def pow_round(x):
+    '''
+     Function to round x to the nearest power of 10
+    '''
+    return 10 ** (floor(log(x, 10) - log(0.5, 10)))
+
+def calc_nice_color_bar_values(mymin, mymax, target_nlevs):
+    '''
+     Function to help make nicer plots. 
+     
+     Calculates an appropriate min, max and number of intervals to use in a color bar 
+     such that the labels come out as round numbers.
+    
+     i.e. often, the color bar labels will come out as  0.1234  0.2343 0.35747 0.57546
+     when in fact you just want  0.1, 0.2, 0.3, 0.4, 0.5 etc
+    
+    
+     Method::
+         Adjusts the max,min and nlevels slightly so as to provide nice round numbers.
+    
+     Input::
+        mymin        - minimum of data range (or first guess at minimum color bar value)
+        mymax        - maximum of data range (or first guess at maximum color bar value)
+        target_nlevs - approximate number of levels/color bar intervals you would like to have
+    
+     Output::
+        newmin       - minimum value of color bar to use
+        newmax       - maximum value of color bar to use
+        new_nlevs    - number of intervals in color bar to use
+        * when all of the above are used, the color bar should have nice round number labels.
+    '''
+    myrange = mymax - mymin
+    # Find target color bar label interval, given target number of levels.
+    #  NB. this is likely to be not a nice rounded number.
+    target_interval = myrange / float(target_nlevs)
+    
+    # Find power of 10 that the target interval lies in
+    nearest_ten = pow_round(target_interval)
+    
+    # Possible interval levels, 
+    #  i.e.  labels of 1,2,3,4,5 etc are OK, 
+    #        labels of 2,4,6,8,10 etc are OK too
+    #        labels of 3,6,9,12 etc are NOT OK (as defined below)
+    #  NB.  this is also true for any multiple of 10 of these values
+    #    i.e.  0.01,0.02,0.03,0.04 etc are OK too.
+    pos_interval_levels = np.array([1, 2, 5])
+    
+    # Find possible intervals to use within this power of 10 range
+    candidate_intervals = (pos_interval_levels * nearest_ten)
+    
+    # Find which of the candidate levels is closest to the target level
+    absdiff = abs(target_interval - candidate_intervals)
+    
+    rounded_interval = candidate_intervals[np.where(absdiff == min(absdiff))]
+    
+    # Define actual nlevels to use in colorbar
+    nlevels = myrange / rounded_interval
+    
+    # Define the color bar labels
+    newmin = mymin - mymin % rounded_interval
+    
+    all_labels = np.arange(newmin, mymax + rounded_interval, rounded_interval) 
+    
+    newmin = all_labels.min()  
+    newmax = all_labels.max()
+    
+    new_nlevs = int(len(all_labels)) - 1
+    
+    return newmin, newmax, new_nlevs
+
+
+def draw_cntr_map_single(pVar, lon, lat, mnLvl, mxLvl, pTitle, pName, cMap, wksType):
+    """
+        File:
+          cn05p.py
+        Synopsis:
+          Draws an animation of global surface temperature over a map.
+        Category:
+          Contours over maps
+        Author:
+          Mary Haley (based on example of Tim Scheitlin)
+        Date of initial publication:    
+          November, 2005
+        Description:
+          This example draws an animation of filled contours over a map 
+          showing surface temperatures (if "Animate" is set to True).
+          Instead of calling Ngl.contour_map for every time step,
+          Ngl.set_values is used to change the data and title after the
+          initial time step.
+       Effects illustrated
+          o  Reading data from a netCDF file.
+          o  Creating a color map using RGB triplets.
+          o  Drawing color filled contours over a map.
+          o  Using Ngl.set_values to change the data for the animation.
+          o  Using a resource list to set many resources, for example to:
+               + set color map
+               + set contour levels
+               + set fill colors
+               + turn off contour lines and line labels
+               + set some labelbar, title,  and tickmark resources
+       Input:
+          pVar   : the field to be plotted (2d)
+          lon    : longitude (1-d)
+          lat    : latitude  (1-d)
+          mnLvl  : the minimum countour level
+          mxLvl  : the maximum countour level
+          spLvl  : label spacing
+          pTitle : plot title
+          pName  : name of the plot file
+          cMap   : color map
+          wksType: workstation type (character)
+       Output:
+          If "Animate" is set to True, then an animation of 31 frames
+          (one per day on January) is produced. Otherwise, just one frame
+          is produced.
+    """
+
+    # Open workstation
+    wres = Ngl.Resources()
+    wres.wkColorMap = cMap
+    # plot size setup for the pdf file option
+    if wksType == 'pdf':
+        wres.wkPaperSize = "A4"
+
+    wks = Ngl.open_wks(wksType, pName, wres)
+
+    # Set up variable to hold the various plot
+    # resources we want to set.
+    res = Ngl.Resources()
+    # assign resolution for png option (default = 1024x1024)
+    if wksType == 'png':
+        res.wkWidth = 1000
+        res.wkHeight = 1000
+
+    # Set some scalar field resources.
+    res.sfXArray = lon
+    res.sfYArray = lat
+    # Define map lat,lon limits
+    res.mpLimitMode = "LatLon"    # Limit the map view.
+    res.mpMinLonF = float(lon.min())
+    res.mpMaxLonF = float(lon.max())
+    res.mpMinLatF = float(lat.min())
+    res.mpMaxLatF = float(lat.max())
+    res.mpPerimOn = True        # Turn on map perimeter.
+    # Set some contour resources
+    res.cnFillOn = True
+    res.cnLinesOn = False             # draw (True) or not (False) contour lines
+    res.cnLineLabelsOn = False             # control the writing of contour labels
+    nsteps = 24
+    mnLvl, mxLvl, nsteps = calc_nice_color_bar_values(mnLvl, mxLvl, nsteps)
+    spLvl = (mxLvl - mnLvl) / nsteps
+    res.cnLevelSelectionMode = "ExplicitLevels" # Define own levels. valid values are "ManualLevels", "AutomaticLevels"
+    res.cnMinLevelValF = mnLvl
+    res.cnMaxLevelValF = mxLvl
+    res.cnLevels = np.arange(mnLvl, mxLvl, spLvl)
+    # Set some labelbar resources.
+    res.lbLabelsOn = True         # write or not the color-bar labels
+    res.lbBoxLinesOn = True
+    res.lbLabelStride = 2            # control the interval at which color-bar label is written (defult = 1)
+    res.lbLabelFont = "default"
+    res.lbLabelFontQuality = "High"
+    res.lbLabelFontHeightF = .015    # Label font height. Default = .02
+    res.lbLabelFontThicknessF = 2.   # default = 1.
+    res.lbOrientation = "Vertical"   # or "Horizontal"
+    res.lbBottomMarginF = 0.1        # default = 0.05
+    res.lbTopMarginF = 0.1        # default = 0.05
+    # Set a map resource.
+    res.mpGridAndLimbOn = False
+    res.mpGeophysicalLineColor = "Black"
+    # Set some title resources.
+    res.tiMainString = pTitle
+    res.tiMainFontHeightF = 0.02
+    # If 1d lat,lon array then assumed to be regular lat,lon grid
+    if len(lat.shape) == 1:
+        print 'Assuming the lat,lon grid is regularly spaced'
+        res.sfXCStartV = float(lon.min())
+        res.sfXCEndV = float(lon.max())
+        res.sfYCStartV = float(lat.min())
+        res.sfYCEndV = float(lat.max())
+
+    contourMap = Ngl.contour_map(wks,pVar,res)
+    # Clean up
+    Ngl.destroy(wks)
+    del contourMap
+    del res
+    del wks
+
+
+def draw_map_color_filled(data, lats, lons, filename, workdir, mytitle='', rangeMax='not set', rangeMin='not set', diff=False, nsteps=20, colorTable='rainbow', niceValues=False):
+    '''
+     Function to draw a color filled contour map using the masked array data
+     
+     Input:: 
+         data  -a masked numpy array of data masked by missing values
+         lats,lons  -1d numpy arrays of unique latitudes and longitudes of grid points
+         filename  -stub of png file created e.g. 'myfile' -> myfile.png
+         workdir - directory to save images in
+         mytitle - chart title
+         rangeMax - (optional) max range for color bar (including for difference plots)
+         rangeMin - (optional) min range for color bar
+         diff    - boolean flag to say if this is a difference plot or not
+     	 (if true then uses different color scale and ranges)
+         nsteps  - (optional) number of color bar intervals
+    	 colorTable - (optional) name of PyNGL color table
+         niceValues - (optional) use nice round values for color bar labels
+    
+     Output::
+    	 no data returned from function
+         Image file produced with name {filename}.png
+    '''
+
+    # set optional argument if not set by user
+    if(rangeMax == 'not set'):
+        rangeMax = data.max()
+
+    if(rangeMin == 'not set'):
+        rangeMin = data.min()
+ 
+    # For difference plots, we want color bar showing zero=white, positive=red, negative=blue
+    #  so set range centred about zero
+    if np.logical_and((diff == True), rangeMax == 'not set'):
+        absmax = np.abs(data).max()
+        rangeMin = -absmax
+        rangeMax = absmax
+
+    # Sometimes doing a difference plot, the plot becomes saturated by a few very high values
+    # In this case, you can specify the maximum range using rangeMax optional argument
+    if np.logical_and((diff == True), (rangeMax != 'not set')):
+        absmax = rangeMax
+        rangeMin = -absmax
+        rangeMax = absmax
+
+    print 'Making map plot with color filled contours'
+
+    # Map plot
+    wks_type = 'png'
+    res = Ngl.Resources()
+    res.wkWidth = 1000
+    res.wkHeight = 1000
+    res.wkColorMap = colorTable	 
+
+    if(diff == True):
+        res.wkColorMap = "BlueDarkRed18"
+
+    filePath = os.path.join(workdir, filename)
+    wks = Ngl.open_wks(wks_type, filePath, res)
+    
+    resources = Ngl.Resources()
+
+    resources.nglMaximize = True  # didn't seem to have any effect
+    resources.vpWidthF = 0.8
    resources.vpHeightF = resources.vpWidthF / 2.5
+
+    # Define data lat,lon limits
+    resources.cnFillOn = True     # Turn on contour fill.
+    # If 2d lat,lon arrays then may not be regular lat,lon grid
+    if len(lats.shape) > 1:
+        resources.sfXArray = lons  # Portion of map on which to overlay
+        resources.sfYArray = lats  # contour plot.
+
+    # If 1d lat,lon array then assumed to be regular lat,lon grid
+    if len(lats.shape) == 1:
+        resources.sfXCStartV = float(lons.min())
+        resources.sfXCEndV = float(lons.max())
+        resources.sfYCStartV = float(lats.min())
+        resources.sfYCEndV = float(lats.max())
+
+    # Define map lat,lon limits
+    resources.mpLimitMode = "LatLon"    # Limit the map view.
+
+    resources.mpMinLonF = float(lons.min())
+    resources.mpMaxLonF = float(lons.max())
+    resources.mpMinLatF = float(lats.min())
+    resources.mpMaxLatF = float(lats.max())
+
+    resources.mpPerimOn = True        # Turn on map perimeter.
+
+    resources.tiMainString = "~F22~" + mytitle
+    resources.tiMainFontHeightF = 0.01
+ 
+    resources.cnLineLabelsOn = False   # Turn off contour line lables
+    resources.cnLinesOn = False  # Turn off contour lines (only use color filled)
+
+    # Set up the contour levels
+    if(niceValues):
+        rangeMin, rangeMax, nsteps = calc_nice_color_bar_values(rangeMin, rangeMax, nsteps)
+
+
+    resources.cnLevelSelectionMode = "ExplicitLevels" # Define own levels.
+    resources.cnLevels = np.arange(rangeMin, rangeMax, (rangeMax - rangeMin) / nsteps)
+
+    plot = Ngl.contour_map(wks, data, resources)
+
+    # Clean up
+    Ngl.destroy(wks) 
+    del plot 
+    del resources
+    del wks
+
+
+def draw_time_series_plot(data, times, myfilename, myworkdir, data2='', mytitle='', ytitle='Y', xtitle='time', year_labels=True):
+    '''
+     Function to draw a time series plot
+     
+     Input:: 
+         data   -a masked numpy array of data masked by missing values		
+         times  -a list of python datetime objects
+         myfilename  -stub of png file created e.g. 'myfile' -> myfile.png
+         myworkdir - directory to save images in
+         data2 - (optional) second data line to plot assumes same time values)
+         mytitle - (optional) chart title
+    	 xtitle - (optional) y-axis title
+    	 ytitle - (optional) y-axis title
+    
+     Output:
+         no data returned from function
+         Image file produced with name {filename}.png
+    '''
+    print 'Producing time series plot'
+
+    fig = pylab.figure()
+    ax = fig.gca()
+
+    if year_labels == False:
+        xfmt = matplotlib.dates.DateFormatter('%b')
+        ax.xaxis.set_major_formatter(xfmt)
+
+    # x-axis title
+    pylab.xlabel(xtitle)
+
+    # y-axis title
+    pylab.ylabel(ytitle)
+
+    # Main title
+    fig.suptitle(mytitle, fontsize=12)
+
+    # Set y-range to sensible values
+    # NB. if plotting two lines, then make sure range appropriate for both datasets
+    ymin = data.min()
+    ymax = data.max()
+
+    # If data2 has been passed in, then set plot range to fit both lines.
+    # NB. if data2 has been passed in, then it is an array, otherwise it defaults to an empty string
+    if type(data2) != str:
+        ymin = min(data.min(), data2.min())
+        ymax = max(data.max(), data2.max())
+
+    # add a bit of padding so lines don't touch bottom and top of the plot
+    ymin = ymin - ((ymax - ymin) * 0.1)
+    ymax = ymax + ((ymax - ymin) * 0.1)
+
+    # Set y-axis range
+    pylab.ylim((ymin, ymax))
+
+    # Make plot, specifying marker style ('x'), linestyle ('-'), linewidth and line color
+    line1 = ax.plot_date(times, data, 'bo-', markersize=6, linewidth=2, color='#AAAAFF')
+    # Make second line, if data2 has been passed in.
+    # TODO:  Handle the optional second dataset better.  Maybe set the Default to None instead 
+    # of an empty string
+    if type(data2) != str:
+        line2 = ax.plot_date(times, data2, 'rx-', markersize=6, linewidth=2, color='#FFAAAA')
+        lines = []
+        lines.extend(line1)
+        lines.extend(line2)
+        fig.legend((lines), ('model', 'obs'), loc='upper right')
+
+    fig.savefig(myworkdir + '/' + myfilename + '.png')
+
+def draw_time_series_plot_old(data, times, myfilename, myworkdir, mytitle='', ytitle='Y', xtitle='time'):
+    '''
+     **DEPRECATED: This old version used PyNGL which couldn't handle dates.**
+     
+     New improved version (draw_time_series_plot) uses matplotlib which handles dates well.  
+     
+     Function to draw a time series plot
+     
+     Input:: 
+        data   -a masked numpy array of data masked by missing values
+        NB. for multiple lines use a list of arrays
+
+        times  -a list of python datetime objects
+        myfilename  -stub of png file created e.g. 'myfile' -> myfile.png
+        myworkdir - directory to save images in
+        mytitle - (optional) chart title
+        xtitle - (optional) y-axis title
+        ytitle - (optional) y-axis title
+
+     Output::
+         No data returned from function
+         Image file produced with name {filename}.png
+    '''
+    
+    wks_type = "png"
+    wks = Ngl.open_wks(wks_type, myworkdir + '/' + myfilename)  # Open a workstation.
+    t = np.arange(len(times))
+
+    #  Set resources for titling.
+    resources = Ngl.Resources()
+
+    resources.tiMainFont = "Helvetica" # Font for title
+    resources.tiXAxisFont = "Helvetica" # Font for X axis label
+    resources.tiYAxisFont = "Helvetica" # Font for Y axis label
+    resources.tiMainString = mytitle
+    resources.tiXAxisString = xtitle
+    resources.tiYAxisString = ytitle
+   
+    resources.xyLineThicknesses = [2.]    # Define line thicknesses
+
+    resources.xyMarkLineModes = ["MarkLines"]
+    resources.xyMarkers = [1]         # (none, dot, asterisk)
+    resources.xyMarkerSizeF = 0.02        # Marker size (default
+                                            # is 0.01)
+                                            # (1.0 is the default).
+
+    # Special handling dependent on if data is for a single line, 
+    #  or a multiple dimensions for mulitple lines
+    if len(data.shape) == 1:
+        resources.xyLineColors = [189]  # Define line colors.
+        resources.xyMarkerColor = [189]
+
+    if len(data.shape) > 1:
+        resources.xyLineColors = [189, 210]  # Define line colors.
+        resources.xyMarkerColor = [189, 210]
+
+    plot = Ngl.xy(wks, t, data, resources)   # Draw an XY plot.
+
+    # Clean up.
+    Ngl.destroy(wks) 
+    del plot 
+    del resources
+    del wks


[04/51] [abbrv] [partial] Adding Jinwon's custom RCMET

Posted by jo...@apache.org.
http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/build-essential/LICENSE
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/build-essential/LICENSE b/src/main/vm/src/cookbooks/build-essential/LICENSE
new file mode 100755
index 0000000..11069ed
--- /dev/null
+++ b/src/main/vm/src/cookbooks/build-essential/LICENSE
@@ -0,0 +1,201 @@
+                              Apache License
+                        Version 2.0, January 2004
+                     http://www.apache.org/licenses/
+
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+1. Definitions.
+
+   "License" shall mean the terms and conditions for use, reproduction,
+   and distribution as defined by Sections 1 through 9 of this document.
+
+   "Licensor" shall mean the copyright owner or entity authorized by
+   the copyright owner that is granting the License.
+
+   "Legal Entity" shall mean the union of the acting entity and all
+   other entities that control, are controlled by, or are under common
+   control with that entity. For the purposes of this definition,
+   "control" means (i) the power, direct or indirect, to cause the
+   direction or management of such entity, whether by contract or
+   otherwise, or (ii) ownership of fifty percent (50%) or more of the
+   outstanding shares, or (iii) beneficial ownership of such entity.
+
+   "You" (or "Your") shall mean an individual or Legal Entity
+   exercising permissions granted by this License.
+
+   "Source" form shall mean the preferred form for making modifications,
+   including but not limited to software source code, documentation
+   source, and configuration files.
+
+   "Object" form shall mean any form resulting from mechanical
+   transformation or translation of a Source form, including but
+   not limited to compiled object code, generated documentation,
+   and conversions to other media types.
+
+   "Work" shall mean the work of authorship, whether in Source or
+   Object form, made available under the License, as indicated by a
+   copyright notice that is included in or attached to the work
+   (an example is provided in the Appendix below).
+
+   "Derivative Works" shall mean any work, whether in Source or Object
+   form, that is based on (or derived from) the Work and for which the
+   editorial revisions, annotations, elaborations, or other modifications
+   represent, as a whole, an original work of authorship. For the purposes
+   of this License, Derivative Works shall not include works that remain
+   separable from, or merely link (or bind by name) to the interfaces of,
+   the Work and Derivative Works thereof.
+
+   "Contribution" shall mean any work of authorship, including
+   the original version of the Work and any modifications or additions
+   to that Work or Derivative Works thereof, that is intentionally
+   submitted to Licensor for inclusion in the Work by the copyright owner
+   or by an individual or Legal Entity authorized to submit on behalf of
+   the copyright owner. For the purposes of this definition, "submitted"
+   means any form of electronic, verbal, or written communication sent
+   to the Licensor or its representatives, including but not limited to
+   communication on electronic mailing lists, source code control systems,
+   and issue tracking systems that are managed by, or on behalf of, the
+   Licensor for the purpose of discussing and improving the Work, but
+   excluding communication that is conspicuously marked or otherwise
+   designated in writing by the copyright owner as "Not a Contribution."
+
+   "Contributor" shall mean Licensor and any individual or Legal Entity
+   on behalf of whom a Contribution has been received by Licensor and
+   subsequently incorporated within the Work.
+
+2. Grant of Copyright License. Subject to the terms and conditions of
+   this License, each Contributor hereby grants to You a perpetual,
+   worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+   copyright license to reproduce, prepare Derivative Works of,
+   publicly display, publicly perform, sublicense, and distribute the
+   Work and such Derivative Works in Source or Object form.
+
+3. Grant of Patent License. Subject to the terms and conditions of
+   this License, each Contributor hereby grants to You a perpetual,
+   worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+   (except as stated in this section) patent license to make, have made,
+   use, offer to sell, sell, import, and otherwise transfer the Work,
+   where such license applies only to those patent claims licensable
+   by such Contributor that are necessarily infringed by their
+   Contribution(s) alone or by combination of their Contribution(s)
+   with the Work to which such Contribution(s) was submitted. If You
+   institute patent litigation against any entity (including a
+   cross-claim or counterclaim in a lawsuit) alleging that the Work
+   or a Contribution incorporated within the Work constitutes direct
+   or contributory patent infringement, then any patent licenses
+   granted to You under this License for that Work shall terminate
+   as of the date such litigation is filed.
+
+4. Redistribution. You may reproduce and distribute copies of the
+   Work or Derivative Works thereof in any medium, with or without
+   modifications, and in Source or Object form, provided that You
+   meet the following conditions:
+
+   (a) You must give any other recipients of the Work or
+       Derivative Works a copy of this License; and
+
+   (b) You must cause any modified files to carry prominent notices
+       stating that You changed the files; and
+
+   (c) You must retain, in the Source form of any Derivative Works
+       that You distribute, all copyright, patent, trademark, and
+       attribution notices from the Source form of the Work,
+       excluding those notices that do not pertain to any part of
+       the Derivative Works; and
+
+   (d) If the Work includes a "NOTICE" text file as part of its
+       distribution, then any Derivative Works that You distribute must
+       include a readable copy of the attribution notices contained
+       within such NOTICE file, excluding those notices that do not
+       pertain to any part of the Derivative Works, in at least one
+       of the following places: within a NOTICE text file distributed
+       as part of the Derivative Works; within the Source form or
+       documentation, if provided along with the Derivative Works; or,
+       within a display generated by the Derivative Works, if and
+       wherever such third-party notices normally appear. The contents
+       of the NOTICE file are for informational purposes only and
+       do not modify the License. You may add Your own attribution
+       notices within Derivative Works that You distribute, alongside
+       or as an addendum to the NOTICE text from the Work, provided
+       that such additional attribution notices cannot be construed
+       as modifying the License.
+
+   You may add Your own copyright statement to Your modifications and
+   may provide additional or different license terms and conditions
+   for use, reproduction, or distribution of Your modifications, or
+   for any such Derivative Works as a whole, provided Your use,
+   reproduction, and distribution of the Work otherwise complies with
+   the conditions stated in this License.
+
+5. Submission of Contributions. Unless You explicitly state otherwise,
+   any Contribution intentionally submitted for inclusion in the Work
+   by You to the Licensor shall be under the terms and conditions of
+   this License, without any additional terms or conditions.
+   Notwithstanding the above, nothing herein shall supersede or modify
+   the terms of any separate license agreement you may have executed
+   with Licensor regarding such Contributions.
+
+6. Trademarks. This License does not grant permission to use the trade
+   names, trademarks, service marks, or product names of the Licensor,
+   except as required for reasonable and customary use in describing the
+   origin of the Work and reproducing the content of the NOTICE file.
+
+7. Disclaimer of Warranty. Unless required by applicable law or
+   agreed to in writing, Licensor provides the Work (and each
+   Contributor provides its Contributions) on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+   implied, including, without limitation, any warranties or conditions
+   of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+   PARTICULAR PURPOSE. You are solely responsible for determining the
+   appropriateness of using or redistributing the Work and assume any
+   risks associated with Your exercise of permissions under this License.
+
+8. Limitation of Liability. In no event and under no legal theory,
+   whether in tort (including negligence), contract, or otherwise,
+   unless required by applicable law (such as deliberate and grossly
+   negligent acts) or agreed to in writing, shall any Contributor be
+   liable to You for damages, including any direct, indirect, special,
+   incidental, or consequential damages of any character arising as a
+   result of this License or out of the use or inability to use the
+   Work (including but not limited to damages for loss of goodwill,
+   work stoppage, computer failure or malfunction, or any and all
+   other commercial damages or losses), even if such Contributor
+   has been advised of the possibility of such damages.
+
+9. Accepting Warranty or Additional Liability. While redistributing
+   the Work or Derivative Works thereof, You may choose to offer,
+   and charge a fee for, acceptance of support, warranty, indemnity,
+   or other liability obligations and/or rights consistent with this
+   License. However, in accepting such obligations, You may act only
+   on Your own behalf and on Your sole responsibility, not on behalf
+   of any other Contributor, and only if You agree to indemnify,
+   defend, and hold each Contributor harmless for any liability
+   incurred by, or claims asserted against, such Contributor by reason
+   of your accepting any such warranty or additional liability.
+
+END OF TERMS AND CONDITIONS
+
+APPENDIX: How to apply the Apache License to your work.
+
+   To apply the Apache License to your work, attach the following
+   boilerplate notice, with the fields enclosed by brackets "[]"
+   replaced with your own identifying information. (Don't include
+   the brackets!)  The text should be enclosed in the appropriate
+   comment syntax for the file format. We also recommend that a
+   file or class name and description of purpose be included on the
+   same "printed page" as the copyright notice for easier
+   identification within third-party archives.
+
+Copyright [yyyy] [name of copyright owner]
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/build-essential/README.md
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/build-essential/README.md b/src/main/vm/src/cookbooks/build-essential/README.md
new file mode 100755
index 0000000..218adf0
--- /dev/null
+++ b/src/main/vm/src/cookbooks/build-essential/README.md
@@ -0,0 +1,124 @@
+Description
+===========
+
+Installs packages required for compiling C software from source. Use
+this cookbook if you wish to compile C programs, or install RubyGems
+with native extensions.
+
+Requirements
+============
+
+## Platform
+
+Supported platforms by platform family:
+
+* Linux (debian, rhel, fedora)
+* Darwin (`mac_os_x` 10.6+)
+
+Attributes
+==========
+
+* `node['build_essential']['compiletime']` - Whether the resources in
+the default recipe should be configured at the "Compile" phase of the
+Chef run. Defaults to false, see __Usage__ for more information.
+* `node['build_essential']['osx']['gcc_installer_url']` - The URL of
+  the OS X GCC package installer (.pkg).
+* `node['build_essential']['osx']['gcc_installer_checksum']` - The
+  SHA256 checksum of the OS X GCC installer.
+
+Recipes
+=======
+
+This cookbook has one recipe, default.
+
+On Linux platforms (see __Platform__ above for a supported list of
+families), packages required to build C source projects are installed.
+This includes GCC, make, autconf and others. On Debian-family
+distributions, the apt-cache may need to be updated, especially during
+compile time installation. See __Usage__ for further information.
+
+On Mac OS X, the GCC standalone installer by Kenneth Reitz is
+installed. Note that this is *not* the Xcode CLI package, as that does
+not include all programs and headers required to build some common
+GNU-style C projects, such as those that are available from projects
+such as MacPorts or Homebrew. Changing the attributes for the GCC
+installer URL and checksum to the Xcode values may work, but this is
+untested.
+
+Usage
+=====
+
+Simply include the `build-essential` and the required tools will be
+installed to the system, and later recipes will be able to compile
+software from C source code.
+
+For RubyGems that include native C extensions you wish to use with
+Chef, you should do two things.
+
+0. Ensure that the C libraries, include files and other assorted "dev"
+type packages are installed. You should do this in the compile phase
+after the build-essential recipe.
+1. Use the `chef_gem` resource in your recipes. This requires Chef version 0.10.10+.
+2. Set the `compiletime` attribute in roles where such recipes are
+required. This will ensure that the build tools are available to
+compile the RubyGems' extensions, as `chef_gem` happens during the
+compile phase, too.
+
+Example installation of a devel package at compile-time in a recipe:
+
+    package "mypackage-dev" do
+      action :nothing
+    end.run_action(:install)
+
+Example use of `chef_gem`:
+
+    chef_gem "mygem"
+
+Example role:
+
+    name "myapp"
+    run_list(
+      "recipe[build-essential]",
+      "recipe[myapp]"
+    )
+    default_attributes(
+      "build_essential" => {
+        "compiletime" => true
+      }
+    )
+
+The compile time option (via the attribute) is to ensure that the
+proper packages are available at the right time in the Chef run. It is
+recommended that the build-essential recipe appear early in the run
+list.
+
+The Chef wiki has documentation on
+[the anatomy of a chef run](http://wiki.opscode.com/display/chef/Anatomy+of+a+Chef+Run).
+
+Limitations
+===========
+
+It is not in the scope of this cookbook to handle installing the
+required headers for individual software projects in order to compile
+them, or to compile RubyGems with native C extensions. You should
+create a cookbook for handling that.
+
+License and Author
+==================
+
+Author:: Joshua Timberman (<jo...@opscode.com>)
+Author:: Seth Chisamore (<sc...@opscode.com>)
+
+Copyright 2009-2011, Opscode, Inc. (<le...@opscode.com>)
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/build-essential/attributes/.svn/all-wcprops
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/build-essential/attributes/.svn/all-wcprops b/src/main/vm/src/cookbooks/build-essential/attributes/.svn/all-wcprops
new file mode 100755
index 0000000..46ecfef
--- /dev/null
+++ b/src/main/vm/src/cookbooks/build-essential/attributes/.svn/all-wcprops
@@ -0,0 +1,11 @@
+K 25
+svn:wc:ra_dav:version-url
+V 110
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks/build-essential/attributes
+END
+default.rb
+K 25
+svn:wc:ra_dav:version-url
+V 121
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks/build-essential/attributes/default.rb
+END

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/build-essential/attributes/.svn/entries
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/build-essential/attributes/.svn/entries b/src/main/vm/src/cookbooks/build-essential/attributes/.svn/entries
new file mode 100755
index 0000000..6013bf3
--- /dev/null
+++ b/src/main/vm/src/cookbooks/build-essential/attributes/.svn/entries
@@ -0,0 +1,62 @@
+10
+
+dir
+1485921
+https://svn.apache.org/repos/asf/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks/build-essential/attributes
+https://svn.apache.org/repos/asf
+
+
+
+2012-11-20T00:41:43.621075Z
+1474518
+ahart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+13f79535-47bb-0310-9956-ffa450edef68
+
+default.rb
+file
+
+
+
+
+2013-05-24T10:13:54.000000Z
+07dea6dad2d2e5b89732da802453bcea
+2012-11-20T00:41:43.621075Z
+1474518
+ahart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+1448
+

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/build-essential/attributes/.svn/text-base/default.rb.svn-base
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/build-essential/attributes/.svn/text-base/default.rb.svn-base b/src/main/vm/src/cookbooks/build-essential/attributes/.svn/text-base/default.rb.svn-base
new file mode 100755
index 0000000..3695e8d
--- /dev/null
+++ b/src/main/vm/src/cookbooks/build-essential/attributes/.svn/text-base/default.rb.svn-base
@@ -0,0 +1,33 @@
+#
+# Cookbook Name:: build-essential
+# Attributes:: default
+#
+# Copyright 2008-2012, Opscode, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+default['build_essential']['compiletime'] = false
+
+case platform
+when "mac_os_x"
+  case
+  when Chef::VersionConstraint.new("~> 10.7.0").include?(platform_version),
+       Chef::VersionConstraint.new("~> 10.8.0").include?(platform_version)
+    default['build_essential']['osx']['gcc_installer_url'] = "https://github.com/downloads/kennethreitz/osx-gcc-installer/GCC-10.7-v2.pkg"
+    default['build_essential']['osx']['gcc_installer_checksum'] = "df36aa87606feb99d0db9ac9a492819e"
+  when Chef::VersionConstraint.new("~> 10.6.0").include?(platform_version)
+    default['build_essential']['osx']['gcc_installer_url'] = "https://github.com/downloads/kennethreitz/osx-gcc-installer/GCC-10.6.pkg"
+    default['build_essential']['osx']['gcc_installer_checksum'] = "d1db5bab6a3f6b9f3b5577a130baeefa"
+  end
+end

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/build-essential/attributes/default.rb
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/build-essential/attributes/default.rb b/src/main/vm/src/cookbooks/build-essential/attributes/default.rb
new file mode 100755
index 0000000..3695e8d
--- /dev/null
+++ b/src/main/vm/src/cookbooks/build-essential/attributes/default.rb
@@ -0,0 +1,33 @@
+#
+# Cookbook Name:: build-essential
+# Attributes:: default
+#
+# Copyright 2008-2012, Opscode, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+default['build_essential']['compiletime'] = false
+
+case platform
+when "mac_os_x"
+  case
+  when Chef::VersionConstraint.new("~> 10.7.0").include?(platform_version),
+       Chef::VersionConstraint.new("~> 10.8.0").include?(platform_version)
+    default['build_essential']['osx']['gcc_installer_url'] = "https://github.com/downloads/kennethreitz/osx-gcc-installer/GCC-10.7-v2.pkg"
+    default['build_essential']['osx']['gcc_installer_checksum'] = "df36aa87606feb99d0db9ac9a492819e"
+  when Chef::VersionConstraint.new("~> 10.6.0").include?(platform_version)
+    default['build_essential']['osx']['gcc_installer_url'] = "https://github.com/downloads/kennethreitz/osx-gcc-installer/GCC-10.6.pkg"
+    default['build_essential']['osx']['gcc_installer_checksum'] = "d1db5bab6a3f6b9f3b5577a130baeefa"
+  end
+end

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/build-essential/metadata.json
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/build-essential/metadata.json b/src/main/vm/src/cookbooks/build-essential/metadata.json
new file mode 100755
index 0000000..c626b13
--- /dev/null
+++ b/src/main/vm/src/cookbooks/build-essential/metadata.json
@@ -0,0 +1,37 @@
+{
+  "name": "build-essential",
+  "description": "Installs C compiler / build tools",
+  "long_description": "",
+  "maintainer": "Opscode, Inc.",
+  "maintainer_email": "cookbooks@opscode.com",
+  "license": "Apache 2.0",
+  "platforms": {
+    "fedora": ">= 0.0.0",
+    "redhat": ">= 0.0.0",
+    "centos": ">= 0.0.0",
+    "ubuntu": ">= 0.0.0",
+    "debian": ">= 0.0.0",
+    "amazon": ">= 0.0.0",
+    "mac_os_x": ">= 10.6.0"
+  },
+  "dependencies": {
+  },
+  "recommendations": {
+  },
+  "suggestions": {
+  },
+  "conflicting": {
+  },
+  "providing": {
+  },
+  "replacing": {
+  },
+  "attributes": {
+  },
+  "groupings": {
+  },
+  "recipes": {
+    "build-essential": "Installs packages required for compiling C software from source."
+  },
+  "version": "1.1.2"
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/build-essential/metadata.rb
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/build-essential/metadata.rb b/src/main/vm/src/cookbooks/build-essential/metadata.rb
new file mode 100755
index 0000000..23df6aa
--- /dev/null
+++ b/src/main/vm/src/cookbooks/build-essential/metadata.rb
@@ -0,0 +1,12 @@
+maintainer        "Opscode, Inc."
+maintainer_email  "cookbooks@opscode.com"
+license           "Apache 2.0"
+description       "Installs C compiler / build tools"
+version           "1.1.2"
+recipe            "build-essential", "Installs packages required for compiling C software from source."
+
+%w{ fedora redhat centos ubuntu debian amazon }.each do |os|
+  supports os
+end
+
+supports "mac_os_x", ">= 10.6.0"

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/build-essential/recipes/.svn/all-wcprops
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/build-essential/recipes/.svn/all-wcprops b/src/main/vm/src/cookbooks/build-essential/recipes/.svn/all-wcprops
new file mode 100755
index 0000000..383abf2
--- /dev/null
+++ b/src/main/vm/src/cookbooks/build-essential/recipes/.svn/all-wcprops
@@ -0,0 +1,11 @@
+K 25
+svn:wc:ra_dav:version-url
+V 107
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks/build-essential/recipes
+END
+default.rb
+K 25
+svn:wc:ra_dav:version-url
+V 118
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks/build-essential/recipes/default.rb
+END

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/build-essential/recipes/.svn/entries
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/build-essential/recipes/.svn/entries b/src/main/vm/src/cookbooks/build-essential/recipes/.svn/entries
new file mode 100755
index 0000000..03785f7
--- /dev/null
+++ b/src/main/vm/src/cookbooks/build-essential/recipes/.svn/entries
@@ -0,0 +1,62 @@
+10
+
+dir
+1485921
+https://svn.apache.org/repos/asf/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks/build-essential/recipes
+https://svn.apache.org/repos/asf
+
+
+
+2012-11-20T00:41:43.621075Z
+1474518
+ahart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+13f79535-47bb-0310-9956-ffa450edef68
+
+default.rb
+file
+
+
+
+
+2013-05-24T10:13:54.000000Z
+d904dcd6d4205e6d404e76aecf4b6349
+2012-11-20T00:41:43.621075Z
+1474518
+ahart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+2571
+

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/build-essential/recipes/.svn/text-base/default.rb.svn-base
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/build-essential/recipes/.svn/text-base/default.rb.svn-base b/src/main/vm/src/cookbooks/build-essential/recipes/.svn/text-base/default.rb.svn-base
new file mode 100755
index 0000000..8b5629d
--- /dev/null
+++ b/src/main/vm/src/cookbooks/build-essential/recipes/.svn/text-base/default.rb.svn-base
@@ -0,0 +1,79 @@
+#
+# Cookbook Name:: build-essential
+# Recipe:: default
+#
+# Copyright 2008-2009, Opscode, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+require 'chef/shell_out'
+
+compiletime = node['build_essential']['compiletime']
+
+case node['os']
+when "linux"
+
+  # on apt-based platforms when first provisioning we need to force
+  # apt-get update at compiletime if we are going to try to install at compiletime
+  if node['platform_family'] == "debian"
+    execute "apt-get update" do
+      action :nothing
+      # tip: to suppress this running every time, just use the apt cookbook
+      not_if do
+        ::File.exists?('/var/lib/apt/periodic/update-success-stamp') &&
+        ::File.mtime('/var/lib/apt/periodic/update-success-stamp') > Time.now - 86400*2
+      end
+    end.run_action(:run) if compiletime
+  end
+
+  packages = case node['platform_family']
+    when "debian"
+      %w{build-essential binutils-doc}
+    when "rhel", "fedora"
+      %w{gcc gcc-c++ kernel-devel make}
+    end
+
+  packages.each do |pkg|
+    r = package pkg do
+      action ( compiletime ? :nothing : :install )
+    end
+    r.run_action(:install) if compiletime
+  end
+
+  %w{autoconf flex bison}.each do |pkg|
+    r = package pkg do
+      action ( compiletime ? :nothing : :install )
+    end
+    r.run_action(:install) if compiletime
+  end
+when "darwin"
+  result = Chef::ShellOut.new("pkgutil --pkgs").run_command
+  installed = result.stdout.split("\n").include?("com.apple.pkg.gcc4.2Leo")
+  pkg_filename = File.basename(node['build_essential']['osx']['gcc_installer_url'])
+  pkg_path = "#{Chef::Config[:file_cache_path]}/#{pkg_filename}"
+
+  r = remote_file pkg_path do
+    source node['build_essential']['osx']['gcc_installer_url']
+    checksum node['build_essential']['osx']['gcc_installer_checksum']
+    action ( compiletime ? :nothing : :create )
+    not_if { installed }
+  end
+  r.run_action(:create) if compiletime
+
+  r = execute "sudo installer -pkg \"#{pkg_path}\" -target /" do
+    action ( compiletime ? :nothing : :run )
+    not_if { installed }
+  end
+  r.run_action(:run) if compiletime
+end

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/build-essential/recipes/default.rb
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/build-essential/recipes/default.rb b/src/main/vm/src/cookbooks/build-essential/recipes/default.rb
new file mode 100755
index 0000000..8b5629d
--- /dev/null
+++ b/src/main/vm/src/cookbooks/build-essential/recipes/default.rb
@@ -0,0 +1,79 @@
+#
+# Cookbook Name:: build-essential
+# Recipe:: default
+#
+# Copyright 2008-2009, Opscode, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+require 'chef/shell_out'
+
+compiletime = node['build_essential']['compiletime']
+
+case node['os']
+when "linux"
+
+  # on apt-based platforms when first provisioning we need to force
+  # apt-get update at compiletime if we are going to try to install at compiletime
+  if node['platform_family'] == "debian"
+    execute "apt-get update" do
+      action :nothing
+      # tip: to suppress this running every time, just use the apt cookbook
+      not_if do
+        ::File.exists?('/var/lib/apt/periodic/update-success-stamp') &&
+        ::File.mtime('/var/lib/apt/periodic/update-success-stamp') > Time.now - 86400*2
+      end
+    end.run_action(:run) if compiletime
+  end
+
+  packages = case node['platform_family']
+    when "debian"
+      %w{build-essential binutils-doc}
+    when "rhel", "fedora"
+      %w{gcc gcc-c++ kernel-devel make}
+    end
+
+  packages.each do |pkg|
+    r = package pkg do
+      action ( compiletime ? :nothing : :install )
+    end
+    r.run_action(:install) if compiletime
+  end
+
+  %w{autoconf flex bison}.each do |pkg|
+    r = package pkg do
+      action ( compiletime ? :nothing : :install )
+    end
+    r.run_action(:install) if compiletime
+  end
+when "darwin"
+  result = Chef::ShellOut.new("pkgutil --pkgs").run_command
+  installed = result.stdout.split("\n").include?("com.apple.pkg.gcc4.2Leo")
+  pkg_filename = File.basename(node['build_essential']['osx']['gcc_installer_url'])
+  pkg_path = "#{Chef::Config[:file_cache_path]}/#{pkg_filename}"
+
+  r = remote_file pkg_path do
+    source node['build_essential']['osx']['gcc_installer_url']
+    checksum node['build_essential']['osx']['gcc_installer_checksum']
+    action ( compiletime ? :nothing : :create )
+    not_if { installed }
+  end
+  r.run_action(:create) if compiletime
+
+  r = execute "sudo installer -pkg \"#{pkg_path}\" -target /" do
+    action ( compiletime ? :nothing : :run )
+    not_if { installed }
+  end
+  r.run_action(:run) if compiletime
+end

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/python/.svn/all-wcprops
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/python/.svn/all-wcprops b/src/main/vm/src/cookbooks/python/.svn/all-wcprops
new file mode 100755
index 0000000..02ec2fd
--- /dev/null
+++ b/src/main/vm/src/cookbooks/python/.svn/all-wcprops
@@ -0,0 +1,41 @@
+K 25
+svn:wc:ra_dav:version-url
+V 90
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks/python
+END
+LICENSE
+K 25
+svn:wc:ra_dav:version-url
+V 98
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks/python/LICENSE
+END
+metadata.rb
+K 25
+svn:wc:ra_dav:version-url
+V 102
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks/python/metadata.rb
+END
+CHANGELOG.md
+K 25
+svn:wc:ra_dav:version-url
+V 103
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks/python/CHANGELOG.md
+END
+CONTRIBUTING
+K 25
+svn:wc:ra_dav:version-url
+V 103
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks/python/CONTRIBUTING
+END
+metadata.json
+K 25
+svn:wc:ra_dav:version-url
+V 104
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks/python/metadata.json
+END
+README.md
+K 25
+svn:wc:ra_dav:version-url
+V 100
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks/python/README.md
+END

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/python/.svn/entries
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/python/.svn/entries b/src/main/vm/src/cookbooks/python/.svn/entries
new file mode 100755
index 0000000..34b30e8
--- /dev/null
+++ b/src/main/vm/src/cookbooks/python/.svn/entries
@@ -0,0 +1,244 @@
+10
+
+dir
+1485921
+https://svn.apache.org/repos/asf/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks/python
+https://svn.apache.org/repos/asf
+
+
+
+2012-11-20T00:41:18.502817Z
+1474517
+ahart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+13f79535-47bb-0310-9956-ffa450edef68
+
+LICENSE
+file
+
+
+
+
+2013-05-24T10:13:51.000000Z
+8f7bb094c7232b058c7e9f2e431f389c
+2012-11-20T00:41:18.502817Z
+1474517
+ahart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+10850
+
+metadata.rb
+file
+
+
+
+
+2013-05-24T10:13:51.000000Z
+5393647a402ae58a135c325fd6613f67
+2012-11-20T00:41:18.502817Z
+1474517
+ahart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+739
+
+attributes
+dir
+
+CHANGELOG.md
+file
+
+
+
+
+2013-05-24T10:13:51.000000Z
+5ab6433e0507fa7d1c8263b86d6f1255
+2012-11-20T00:41:18.502817Z
+1474517
+ahart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+843
+
+CONTRIBUTING
+file
+
+
+
+
+2013-05-24T10:13:51.000000Z
+e5600a5296cb1b69f978b6c2c4a1b1c1
+2012-11-20T00:41:18.502817Z
+1474517
+ahart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+1233
+
+metadata.json
+file
+
+
+
+
+2013-05-24T10:13:51.000000Z
+29ce207473ccb029405ebf9a39abe5fc
+2012-11-20T00:41:18.502817Z
+1474517
+ahart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+1074
+
+recipes
+dir
+
+resources
+dir
+
+README.md
+file
+
+
+
+
+2013-05-24T10:13:51.000000Z
+aad8f4cb7051c0a9066ec39ea9f06672
+2012-11-20T00:41:18.502817Z
+1474517
+ahart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+4853
+
+providers
+dir
+

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/python/.svn/text-base/CHANGELOG.md.svn-base
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/python/.svn/text-base/CHANGELOG.md.svn-base b/src/main/vm/src/cookbooks/python/.svn/text-base/CHANGELOG.md.svn-base
new file mode 100755
index 0000000..5396d10
--- /dev/null
+++ b/src/main/vm/src/cookbooks/python/.svn/text-base/CHANGELOG.md.svn-base
@@ -0,0 +1,21 @@
+## v1.0.8:
+
+* [COOK-1016] - python package needs separate names for centos/rhel 5.x vs 6.x
+* [COOK-1048] - installation of pip does not honor selected python version
+* [COOK-1282] - catch Chef::Exceptions::ShellCommandFailed for chef 0.10.8 compatibility
+* [COOK-1311] - virtualenv should have options attribute
+* [COOK-1320] - pip provider doesn't catch correct exception
+* [COOK-1415] - use plain 'python' binary instead of versioned one for
+  default interpreter
+
+## v1.0.6:
+
+* [COOK-1036] - correctly grep for python-module version
+* [COOK-1046] - run pip inside the virtualenv
+
+## v1.0.4:
+
+* [COOK-960] - add timeout to python_pip
+* [COOK-651] - 'install_path' not correctly resolved when using python::source
+* [COOK-650] - Add ability to specify version when installing distribute.
+* [COOK-553] - FreeBSD support in the python cookbook

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/python/.svn/text-base/CONTRIBUTING.svn-base
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/python/.svn/text-base/CONTRIBUTING.svn-base b/src/main/vm/src/cookbooks/python/.svn/text-base/CONTRIBUTING.svn-base
new file mode 100755
index 0000000..89ac873
--- /dev/null
+++ b/src/main/vm/src/cookbooks/python/.svn/text-base/CONTRIBUTING.svn-base
@@ -0,0 +1,29 @@
+If you would like to contribute, please open a ticket in JIRA:
+
+* http://tickets.opscode.com
+
+Create the ticket in the COOK project and use the cookbook name as the
+component.
+
+For all code contributions, we ask that contributors sign a
+contributor license agreement (CLA). Instructions may be found here:
+
+* http://wiki.opscode.com/display/chef/How+to+Contribute
+
+When contributing changes to individual cookbooks, please do not
+modify the version number in the metadata.rb. Also please do not
+update the CHANGELOG.md for a new version. Not all changes to a
+cookbook may be merged and released in the same versions. Opscode will
+handle the version updates during the release process. You are welcome
+to correct typos or otherwise make updates to documentation in the
+README.
+
+If a contribution adds new platforms or platform versions, indicate
+such in the body of the commit message(s), and update the relevant
+COOK ticket. When writing commit messages, it is helpful for others if
+you indicate the COOK ticket. For example:
+
+    git commit -m '[COOK-1041] Updated pool resource to correctly delete.'
+
+In the ticket itself, it is also helpful if you include log output of
+a successful Chef run, but this is not absolutely required.

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/python/.svn/text-base/LICENSE.svn-base
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/python/.svn/text-base/LICENSE.svn-base b/src/main/vm/src/cookbooks/python/.svn/text-base/LICENSE.svn-base
new file mode 100755
index 0000000..11069ed
--- /dev/null
+++ b/src/main/vm/src/cookbooks/python/.svn/text-base/LICENSE.svn-base
@@ -0,0 +1,201 @@
+                              Apache License
+                        Version 2.0, January 2004
+                     http://www.apache.org/licenses/
+
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+1. Definitions.
+
+   "License" shall mean the terms and conditions for use, reproduction,
+   and distribution as defined by Sections 1 through 9 of this document.
+
+   "Licensor" shall mean the copyright owner or entity authorized by
+   the copyright owner that is granting the License.
+
+   "Legal Entity" shall mean the union of the acting entity and all
+   other entities that control, are controlled by, or are under common
+   control with that entity. For the purposes of this definition,
+   "control" means (i) the power, direct or indirect, to cause the
+   direction or management of such entity, whether by contract or
+   otherwise, or (ii) ownership of fifty percent (50%) or more of the
+   outstanding shares, or (iii) beneficial ownership of such entity.
+
+   "You" (or "Your") shall mean an individual or Legal Entity
+   exercising permissions granted by this License.
+
+   "Source" form shall mean the preferred form for making modifications,
+   including but not limited to software source code, documentation
+   source, and configuration files.
+
+   "Object" form shall mean any form resulting from mechanical
+   transformation or translation of a Source form, including but
+   not limited to compiled object code, generated documentation,
+   and conversions to other media types.
+
+   "Work" shall mean the work of authorship, whether in Source or
+   Object form, made available under the License, as indicated by a
+   copyright notice that is included in or attached to the work
+   (an example is provided in the Appendix below).
+
+   "Derivative Works" shall mean any work, whether in Source or Object
+   form, that is based on (or derived from) the Work and for which the
+   editorial revisions, annotations, elaborations, or other modifications
+   represent, as a whole, an original work of authorship. For the purposes
+   of this License, Derivative Works shall not include works that remain
+   separable from, or merely link (or bind by name) to the interfaces of,
+   the Work and Derivative Works thereof.
+
+   "Contribution" shall mean any work of authorship, including
+   the original version of the Work and any modifications or additions
+   to that Work or Derivative Works thereof, that is intentionally
+   submitted to Licensor for inclusion in the Work by the copyright owner
+   or by an individual or Legal Entity authorized to submit on behalf of
+   the copyright owner. For the purposes of this definition, "submitted"
+   means any form of electronic, verbal, or written communication sent
+   to the Licensor or its representatives, including but not limited to
+   communication on electronic mailing lists, source code control systems,
+   and issue tracking systems that are managed by, or on behalf of, the
+   Licensor for the purpose of discussing and improving the Work, but
+   excluding communication that is conspicuously marked or otherwise
+   designated in writing by the copyright owner as "Not a Contribution."
+
+   "Contributor" shall mean Licensor and any individual or Legal Entity
+   on behalf of whom a Contribution has been received by Licensor and
+   subsequently incorporated within the Work.
+
+2. Grant of Copyright License. Subject to the terms and conditions of
+   this License, each Contributor hereby grants to You a perpetual,
+   worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+   copyright license to reproduce, prepare Derivative Works of,
+   publicly display, publicly perform, sublicense, and distribute the
+   Work and such Derivative Works in Source or Object form.
+
+3. Grant of Patent License. Subject to the terms and conditions of
+   this License, each Contributor hereby grants to You a perpetual,
+   worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+   (except as stated in this section) patent license to make, have made,
+   use, offer to sell, sell, import, and otherwise transfer the Work,
+   where such license applies only to those patent claims licensable
+   by such Contributor that are necessarily infringed by their
+   Contribution(s) alone or by combination of their Contribution(s)
+   with the Work to which such Contribution(s) was submitted. If You
+   institute patent litigation against any entity (including a
+   cross-claim or counterclaim in a lawsuit) alleging that the Work
+   or a Contribution incorporated within the Work constitutes direct
+   or contributory patent infringement, then any patent licenses
+   granted to You under this License for that Work shall terminate
+   as of the date such litigation is filed.
+
+4. Redistribution. You may reproduce and distribute copies of the
+   Work or Derivative Works thereof in any medium, with or without
+   modifications, and in Source or Object form, provided that You
+   meet the following conditions:
+
+   (a) You must give any other recipients of the Work or
+       Derivative Works a copy of this License; and
+
+   (b) You must cause any modified files to carry prominent notices
+       stating that You changed the files; and
+
+   (c) You must retain, in the Source form of any Derivative Works
+       that You distribute, all copyright, patent, trademark, and
+       attribution notices from the Source form of the Work,
+       excluding those notices that do not pertain to any part of
+       the Derivative Works; and
+
+   (d) If the Work includes a "NOTICE" text file as part of its
+       distribution, then any Derivative Works that You distribute must
+       include a readable copy of the attribution notices contained
+       within such NOTICE file, excluding those notices that do not
+       pertain to any part of the Derivative Works, in at least one
+       of the following places: within a NOTICE text file distributed
+       as part of the Derivative Works; within the Source form or
+       documentation, if provided along with the Derivative Works; or,
+       within a display generated by the Derivative Works, if and
+       wherever such third-party notices normally appear. The contents
+       of the NOTICE file are for informational purposes only and
+       do not modify the License. You may add Your own attribution
+       notices within Derivative Works that You distribute, alongside
+       or as an addendum to the NOTICE text from the Work, provided
+       that such additional attribution notices cannot be construed
+       as modifying the License.
+
+   You may add Your own copyright statement to Your modifications and
+   may provide additional or different license terms and conditions
+   for use, reproduction, or distribution of Your modifications, or
+   for any such Derivative Works as a whole, provided Your use,
+   reproduction, and distribution of the Work otherwise complies with
+   the conditions stated in this License.
+
+5. Submission of Contributions. Unless You explicitly state otherwise,
+   any Contribution intentionally submitted for inclusion in the Work
+   by You to the Licensor shall be under the terms and conditions of
+   this License, without any additional terms or conditions.
+   Notwithstanding the above, nothing herein shall supersede or modify
+   the terms of any separate license agreement you may have executed
+   with Licensor regarding such Contributions.
+
+6. Trademarks. This License does not grant permission to use the trade
+   names, trademarks, service marks, or product names of the Licensor,
+   except as required for reasonable and customary use in describing the
+   origin of the Work and reproducing the content of the NOTICE file.
+
+7. Disclaimer of Warranty. Unless required by applicable law or
+   agreed to in writing, Licensor provides the Work (and each
+   Contributor provides its Contributions) on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+   implied, including, without limitation, any warranties or conditions
+   of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+   PARTICULAR PURPOSE. You are solely responsible for determining the
+   appropriateness of using or redistributing the Work and assume any
+   risks associated with Your exercise of permissions under this License.
+
+8. Limitation of Liability. In no event and under no legal theory,
+   whether in tort (including negligence), contract, or otherwise,
+   unless required by applicable law (such as deliberate and grossly
+   negligent acts) or agreed to in writing, shall any Contributor be
+   liable to You for damages, including any direct, indirect, special,
+   incidental, or consequential damages of any character arising as a
+   result of this License or out of the use or inability to use the
+   Work (including but not limited to damages for loss of goodwill,
+   work stoppage, computer failure or malfunction, or any and all
+   other commercial damages or losses), even if such Contributor
+   has been advised of the possibility of such damages.
+
+9. Accepting Warranty or Additional Liability. While redistributing
+   the Work or Derivative Works thereof, You may choose to offer,
+   and charge a fee for, acceptance of support, warranty, indemnity,
+   or other liability obligations and/or rights consistent with this
+   License. However, in accepting such obligations, You may act only
+   on Your own behalf and on Your sole responsibility, not on behalf
+   of any other Contributor, and only if You agree to indemnify,
+   defend, and hold each Contributor harmless for any liability
+   incurred by, or claims asserted against, such Contributor by reason
+   of your accepting any such warranty or additional liability.
+
+END OF TERMS AND CONDITIONS
+
+APPENDIX: How to apply the Apache License to your work.
+
+   To apply the Apache License to your work, attach the following
+   boilerplate notice, with the fields enclosed by brackets "[]"
+   replaced with your own identifying information. (Don't include
+   the brackets!)  The text should be enclosed in the appropriate
+   comment syntax for the file format. We also recommend that a
+   file or class name and description of purpose be included on the
+   same "printed page" as the copyright notice for easier
+   identification within third-party archives.
+
+Copyright [yyyy] [name of copyright owner]
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/python/.svn/text-base/README.md.svn-base
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/python/.svn/text-base/README.md.svn-base b/src/main/vm/src/cookbooks/python/.svn/text-base/README.md.svn-base
new file mode 100755
index 0000000..38ace13
--- /dev/null
+++ b/src/main/vm/src/cookbooks/python/.svn/text-base/README.md.svn-base
@@ -0,0 +1,176 @@
+Description
+===========
+
+Installs and configures Python.  Also includes LWRPs for managing python packages with `pip` and `virtualenv` isolated Python environments.
+
+Requirements
+============
+
+Platform
+--------
+
+* Debian, Ubuntu
+* CentOS, Red Hat, Fedora
+
+Cookbooks
+---------
+
+* build-essential
+* yum
+
+NOTE: The `yum` cookbook is a dependency of the cookbook, and will be used to install [EPEL](http://fedoraproject.org/wiki/EPEL) on RedHet/CentOS 5.x systems to provide the Python 2.6 packages.
+
+Attributes
+==========
+
+See `attributes/default.rb` for default values.
+
+* `node["python"]["install_method"]` - method to install python with, default `package`.
+
+The file also contains the following attributes:
+
+* platform specific locations and settings.
+* source installation settings
+
+Resource/Provider
+=================
+
+This cookbook includes LWRPs for managing:
+
+* pip packages
+* virtualenv isolated Python environments
+
+`python_pip`
+------------
+
+Install packages using the new hotness in Python package management...[`pip`](http://pypi.python.org/pypi/pip).  Yo dawg...easy_install is so 2009, you better ask your local Pythonista if you don't know! The usage semantics are like that of any normal package provider.
+
+# Actions
+
+- :install: Install a pip package - if version is provided, install that specific version
+- :upgrade: Upgrade a pip package - if version is provided, upgrade to that specific version
+- :remove: Remove a pip package
+- :purge: Purge a pip package (this usually entails removing configuration files as well as the package itself).  With pip packages this behaves the same as `:remove`
+
+# Attribute Parameters
+
+- package_name: name attribute. The name of the pip package to install
+- version: the version of the package to install/upgrade.  If no version is given latest is assumed.
+- virtualenv: virtualenv environment to install pip package into
+- options: Add additional options to the underlying pip package command
+- timeout: timeout in seconds for the command to execute. Useful for pip packages that may take a long time to install. Default 900 seconds.
+
+# Example
+
+    # install latest gunicorn into system path
+    python_pip "gunicorn" do
+      action :install
+    end
+
+    # target a virtualenv
+    python_pip "gunicorn" do
+      virtualenv "/home/ubunut/my_ve"
+      action :install
+    end
+
+    # install Django 1.1.4
+    python_pip "django" do
+      version "1.1.4"
+      action :install
+    end
+
+    # use this provider with the core package resource
+    package "django" do
+      provider Chef::Provider::PythonPip
+      action :install
+    end
+
+`python_virtualenv`
+-------------------
+
+[`virtualenv`](http://pypi.python.org/pypi/virtualenv) is a great tool that creates isolated python environments.  Think of it as RVM without all those hipsters and tight jeans.
+
+# Actions
+
+- :create: creates a new virtualenv
+- :delete: deletes an existing virtualenv
+
+# Attribute Parameters
+
+- path: name attribute. The path where the virtualenv will be created
+- interpreter: The Python interpreter to use. default is `python2.6`
+- owner: The owner for the virtualenv
+- group: The group owner of the file (string or id)
+- options : Command line options (string)
+
+# Example
+
+    # create a 2.6 virtualenv owned by ubuntu user
+    python_virtualenv "/home/ubuntu/my_cool_ve" do
+      owner "ubuntu"
+      group "ubuntu"
+      action :create
+    end
+
+    # create a Python 2.4 virtualenv
+    python_virtualenv "/home/ubuntu/my_old_ve" do
+      interpreter "python2.4"
+      owner "ubuntu"
+      group "ubuntu"
+      action :create
+    end
+
+    # create a Python 2.6 virtualenv with access to the global packages owned by ubuntu user
+    python_virtualenv "/home/ubuntu/my_old_ve" do
+      owner "ubuntu"
+      group "ubuntu"
+      options "--system-site-packages"
+      action :create
+    end
+
+Usage
+=====
+
+default
+-------
+
+Include default recipe in a run list, to get `python`, `pip` and `virtualenv`. Installs python by package or source depending on the platform.
+
+package
+-------
+
+Installs Python from packages.
+
+source
+------
+
+Installs Python from source.
+
+pip
+---
+
+Installs `pip` from source.
+
+virtualenv
+----------
+
+Installs virtualenv using the `python_pip` resource.
+
+License and Author
+==================
+
+Author:: Seth Chisamore (<sc...@opscode.com>)
+
+Copyright:: 2011, Opscode, Inc
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/python/.svn/text-base/metadata.json.svn-base
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/python/.svn/text-base/metadata.json.svn-base b/src/main/vm/src/cookbooks/python/.svn/text-base/metadata.json.svn-base
new file mode 100755
index 0000000..5b9dbf0
--- /dev/null
+++ b/src/main/vm/src/cookbooks/python/.svn/text-base/metadata.json.svn-base
@@ -0,0 +1,42 @@
+{
+  "name": "python",
+  "description": "Installs Python, pip and virtualenv. Includes LWRPs for managing Python packages with `pip` and `virtualenv` isolated Python environments.",
+  "long_description": "",
+  "maintainer": "Opscode, Inc.",
+  "maintainer_email": "cookbooks@opscode.com",
+  "license": "Apache 2.0",
+  "platforms": {
+    "debian": ">= 0.0.0",
+    "ubuntu": ">= 0.0.0",
+    "centos": ">= 0.0.0",
+    "redhat": ">= 0.0.0",
+    "fedora": ">= 0.0.0",
+    "freebsd": ">= 0.0.0"
+  },
+  "dependencies": {
+    "build-essential": ">= 0.0.0",
+    "yum": ">= 0.0.0"
+  },
+  "recommendations": {
+  },
+  "suggestions": {
+  },
+  "conflicting": {
+  },
+  "providing": {
+  },
+  "replacing": {
+  },
+  "attributes": {
+  },
+  "groupings": {
+  },
+  "recipes": {
+    "python": "Installs python, pip, and virtualenv",
+    "python::package": "Installs python using packages.",
+    "python::source": "Installs python from source.",
+    "python::pip": "Installs pip from source.",
+    "python::virtualenv": "Installs virtualenv using the python_pip resource."
+  },
+  "version": "1.0.8"
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/python/.svn/text-base/metadata.rb.svn-base
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/python/.svn/text-base/metadata.rb.svn-base b/src/main/vm/src/cookbooks/python/.svn/text-base/metadata.rb.svn-base
new file mode 100755
index 0000000..efca7b9
--- /dev/null
+++ b/src/main/vm/src/cookbooks/python/.svn/text-base/metadata.rb.svn-base
@@ -0,0 +1,18 @@
+maintainer        "Opscode, Inc."
+maintainer_email  "cookbooks@opscode.com"
+license           "Apache 2.0"
+description       "Installs Python, pip and virtualenv. Includes LWRPs for managing Python packages with `pip` and `virtualenv` isolated Python environments."
+version           "1.0.8"
+
+depends           "build-essential"
+depends           "yum"
+
+recipe "python", "Installs python, pip, and virtualenv"
+recipe "python::package", "Installs python using packages."
+recipe "python::source", "Installs python from source."
+recipe "python::pip", "Installs pip from source."
+recipe "python::virtualenv", "Installs virtualenv using the python_pip resource."
+
+%w{ debian ubuntu centos redhat fedora freebsd }.each do |os|
+  supports os
+end

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/python/CHANGELOG.md
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/python/CHANGELOG.md b/src/main/vm/src/cookbooks/python/CHANGELOG.md
new file mode 100755
index 0000000..5396d10
--- /dev/null
+++ b/src/main/vm/src/cookbooks/python/CHANGELOG.md
@@ -0,0 +1,21 @@
+## v1.0.8:
+
+* [COOK-1016] - python package needs separate names for centos/rhel 5.x vs 6.x
+* [COOK-1048] - installation of pip does not honor selected python version
+* [COOK-1282] - catch Chef::Exceptions::ShellCommandFailed for chef 0.10.8 compatibility
+* [COOK-1311] - virtualenv should have options attribute
+* [COOK-1320] - pip provider doesn't catch correct exception
+* [COOK-1415] - use plain 'python' binary instead of versioned one for
+  default interpreter
+
+## v1.0.6:
+
+* [COOK-1036] - correctly grep for python-module version
+* [COOK-1046] - run pip inside the virtualenv
+
+## v1.0.4:
+
+* [COOK-960] - add timeout to python_pip
+* [COOK-651] - 'install_path' not correctly resolved when using python::source
+* [COOK-650] - Add ability to specify version when installing distribute.
+* [COOK-553] - FreeBSD support in the python cookbook

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/python/CONTRIBUTING
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/python/CONTRIBUTING b/src/main/vm/src/cookbooks/python/CONTRIBUTING
new file mode 100755
index 0000000..89ac873
--- /dev/null
+++ b/src/main/vm/src/cookbooks/python/CONTRIBUTING
@@ -0,0 +1,29 @@
+If you would like to contribute, please open a ticket in JIRA:
+
+* http://tickets.opscode.com
+
+Create the ticket in the COOK project and use the cookbook name as the
+component.
+
+For all code contributions, we ask that contributors sign a
+contributor license agreement (CLA). Instructions may be found here:
+
+* http://wiki.opscode.com/display/chef/How+to+Contribute
+
+When contributing changes to individual cookbooks, please do not
+modify the version number in the metadata.rb. Also please do not
+update the CHANGELOG.md for a new version. Not all changes to a
+cookbook may be merged and released in the same versions. Opscode will
+handle the version updates during the release process. You are welcome
+to correct typos or otherwise make updates to documentation in the
+README.
+
+If a contribution adds new platforms or platform versions, indicate
+such in the body of the commit message(s), and update the relevant
+COOK ticket. When writing commit messages, it is helpful for others if
+you indicate the COOK ticket. For example:
+
+    git commit -m '[COOK-1041] Updated pool resource to correctly delete.'
+
+In the ticket itself, it is also helpful if you include log output of
+a successful Chef run, but this is not absolutely required.

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/python/LICENSE
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/python/LICENSE b/src/main/vm/src/cookbooks/python/LICENSE
new file mode 100755
index 0000000..11069ed
--- /dev/null
+++ b/src/main/vm/src/cookbooks/python/LICENSE
@@ -0,0 +1,201 @@
+                              Apache License
+                        Version 2.0, January 2004
+                     http://www.apache.org/licenses/
+
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+1. Definitions.
+
+   "License" shall mean the terms and conditions for use, reproduction,
+   and distribution as defined by Sections 1 through 9 of this document.
+
+   "Licensor" shall mean the copyright owner or entity authorized by
+   the copyright owner that is granting the License.
+
+   "Legal Entity" shall mean the union of the acting entity and all
+   other entities that control, are controlled by, or are under common
+   control with that entity. For the purposes of this definition,
+   "control" means (i) the power, direct or indirect, to cause the
+   direction or management of such entity, whether by contract or
+   otherwise, or (ii) ownership of fifty percent (50%) or more of the
+   outstanding shares, or (iii) beneficial ownership of such entity.
+
+   "You" (or "Your") shall mean an individual or Legal Entity
+   exercising permissions granted by this License.
+
+   "Source" form shall mean the preferred form for making modifications,
+   including but not limited to software source code, documentation
+   source, and configuration files.
+
+   "Object" form shall mean any form resulting from mechanical
+   transformation or translation of a Source form, including but
+   not limited to compiled object code, generated documentation,
+   and conversions to other media types.
+
+   "Work" shall mean the work of authorship, whether in Source or
+   Object form, made available under the License, as indicated by a
+   copyright notice that is included in or attached to the work
+   (an example is provided in the Appendix below).
+
+   "Derivative Works" shall mean any work, whether in Source or Object
+   form, that is based on (or derived from) the Work and for which the
+   editorial revisions, annotations, elaborations, or other modifications
+   represent, as a whole, an original work of authorship. For the purposes
+   of this License, Derivative Works shall not include works that remain
+   separable from, or merely link (or bind by name) to the interfaces of,
+   the Work and Derivative Works thereof.
+
+   "Contribution" shall mean any work of authorship, including
+   the original version of the Work and any modifications or additions
+   to that Work or Derivative Works thereof, that is intentionally
+   submitted to Licensor for inclusion in the Work by the copyright owner
+   or by an individual or Legal Entity authorized to submit on behalf of
+   the copyright owner. For the purposes of this definition, "submitted"
+   means any form of electronic, verbal, or written communication sent
+   to the Licensor or its representatives, including but not limited to
+   communication on electronic mailing lists, source code control systems,
+   and issue tracking systems that are managed by, or on behalf of, the
+   Licensor for the purpose of discussing and improving the Work, but
+   excluding communication that is conspicuously marked or otherwise
+   designated in writing by the copyright owner as "Not a Contribution."
+
+   "Contributor" shall mean Licensor and any individual or Legal Entity
+   on behalf of whom a Contribution has been received by Licensor and
+   subsequently incorporated within the Work.
+
+2. Grant of Copyright License. Subject to the terms and conditions of
+   this License, each Contributor hereby grants to You a perpetual,
+   worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+   copyright license to reproduce, prepare Derivative Works of,
+   publicly display, publicly perform, sublicense, and distribute the
+   Work and such Derivative Works in Source or Object form.
+
+3. Grant of Patent License. Subject to the terms and conditions of
+   this License, each Contributor hereby grants to You a perpetual,
+   worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+   (except as stated in this section) patent license to make, have made,
+   use, offer to sell, sell, import, and otherwise transfer the Work,
+   where such license applies only to those patent claims licensable
+   by such Contributor that are necessarily infringed by their
+   Contribution(s) alone or by combination of their Contribution(s)
+   with the Work to which such Contribution(s) was submitted. If You
+   institute patent litigation against any entity (including a
+   cross-claim or counterclaim in a lawsuit) alleging that the Work
+   or a Contribution incorporated within the Work constitutes direct
+   or contributory patent infringement, then any patent licenses
+   granted to You under this License for that Work shall terminate
+   as of the date such litigation is filed.
+
+4. Redistribution. You may reproduce and distribute copies of the
+   Work or Derivative Works thereof in any medium, with or without
+   modifications, and in Source or Object form, provided that You
+   meet the following conditions:
+
+   (a) You must give any other recipients of the Work or
+       Derivative Works a copy of this License; and
+
+   (b) You must cause any modified files to carry prominent notices
+       stating that You changed the files; and
+
+   (c) You must retain, in the Source form of any Derivative Works
+       that You distribute, all copyright, patent, trademark, and
+       attribution notices from the Source form of the Work,
+       excluding those notices that do not pertain to any part of
+       the Derivative Works; and
+
+   (d) If the Work includes a "NOTICE" text file as part of its
+       distribution, then any Derivative Works that You distribute must
+       include a readable copy of the attribution notices contained
+       within such NOTICE file, excluding those notices that do not
+       pertain to any part of the Derivative Works, in at least one
+       of the following places: within a NOTICE text file distributed
+       as part of the Derivative Works; within the Source form or
+       documentation, if provided along with the Derivative Works; or,
+       within a display generated by the Derivative Works, if and
+       wherever such third-party notices normally appear. The contents
+       of the NOTICE file are for informational purposes only and
+       do not modify the License. You may add Your own attribution
+       notices within Derivative Works that You distribute, alongside
+       or as an addendum to the NOTICE text from the Work, provided
+       that such additional attribution notices cannot be construed
+       as modifying the License.
+
+   You may add Your own copyright statement to Your modifications and
+   may provide additional or different license terms and conditions
+   for use, reproduction, or distribution of Your modifications, or
+   for any such Derivative Works as a whole, provided Your use,
+   reproduction, and distribution of the Work otherwise complies with
+   the conditions stated in this License.
+
+5. Submission of Contributions. Unless You explicitly state otherwise,
+   any Contribution intentionally submitted for inclusion in the Work
+   by You to the Licensor shall be under the terms and conditions of
+   this License, without any additional terms or conditions.
+   Notwithstanding the above, nothing herein shall supersede or modify
+   the terms of any separate license agreement you may have executed
+   with Licensor regarding such Contributions.
+
+6. Trademarks. This License does not grant permission to use the trade
+   names, trademarks, service marks, or product names of the Licensor,
+   except as required for reasonable and customary use in describing the
+   origin of the Work and reproducing the content of the NOTICE file.
+
+7. Disclaimer of Warranty. Unless required by applicable law or
+   agreed to in writing, Licensor provides the Work (and each
+   Contributor provides its Contributions) on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+   implied, including, without limitation, any warranties or conditions
+   of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+   PARTICULAR PURPOSE. You are solely responsible for determining the
+   appropriateness of using or redistributing the Work and assume any
+   risks associated with Your exercise of permissions under this License.
+
+8. Limitation of Liability. In no event and under no legal theory,
+   whether in tort (including negligence), contract, or otherwise,
+   unless required by applicable law (such as deliberate and grossly
+   negligent acts) or agreed to in writing, shall any Contributor be
+   liable to You for damages, including any direct, indirect, special,
+   incidental, or consequential damages of any character arising as a
+   result of this License or out of the use or inability to use the
+   Work (including but not limited to damages for loss of goodwill,
+   work stoppage, computer failure or malfunction, or any and all
+   other commercial damages or losses), even if such Contributor
+   has been advised of the possibility of such damages.
+
+9. Accepting Warranty or Additional Liability. While redistributing
+   the Work or Derivative Works thereof, You may choose to offer,
+   and charge a fee for, acceptance of support, warranty, indemnity,
+   or other liability obligations and/or rights consistent with this
+   License. However, in accepting such obligations, You may act only
+   on Your own behalf and on Your sole responsibility, not on behalf
+   of any other Contributor, and only if You agree to indemnify,
+   defend, and hold each Contributor harmless for any liability
+   incurred by, or claims asserted against, such Contributor by reason
+   of your accepting any such warranty or additional liability.
+
+END OF TERMS AND CONDITIONS
+
+APPENDIX: How to apply the Apache License to your work.
+
+   To apply the Apache License to your work, attach the following
+   boilerplate notice, with the fields enclosed by brackets "[]"
+   replaced with your own identifying information. (Don't include
+   the brackets!)  The text should be enclosed in the appropriate
+   comment syntax for the file format. We also recommend that a
+   file or class name and description of purpose be included on the
+   same "printed page" as the copyright notice for easier
+   identification within third-party archives.
+
+Copyright [yyyy] [name of copyright owner]
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/python/README.md
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/python/README.md b/src/main/vm/src/cookbooks/python/README.md
new file mode 100755
index 0000000..38ace13
--- /dev/null
+++ b/src/main/vm/src/cookbooks/python/README.md
@@ -0,0 +1,176 @@
+Description
+===========
+
+Installs and configures Python.  Also includes LWRPs for managing python packages with `pip` and `virtualenv` isolated Python environments.
+
+Requirements
+============
+
+Platform
+--------
+
+* Debian, Ubuntu
+* CentOS, Red Hat, Fedora
+
+Cookbooks
+---------
+
+* build-essential
+* yum
+
+NOTE: The `yum` cookbook is a dependency of the cookbook, and will be used to install [EPEL](http://fedoraproject.org/wiki/EPEL) on RedHet/CentOS 5.x systems to provide the Python 2.6 packages.
+
+Attributes
+==========
+
+See `attributes/default.rb` for default values.
+
+* `node["python"]["install_method"]` - method to install python with, default `package`.
+
+The file also contains the following attributes:
+
+* platform specific locations and settings.
+* source installation settings
+
+Resource/Provider
+=================
+
+This cookbook includes LWRPs for managing:
+
+* pip packages
+* virtualenv isolated Python environments
+
+`python_pip`
+------------
+
+Install packages using the new hotness in Python package management...[`pip`](http://pypi.python.org/pypi/pip).  Yo dawg...easy_install is so 2009, you better ask your local Pythonista if you don't know! The usage semantics are like that of any normal package provider.
+
+# Actions
+
+- :install: Install a pip package - if version is provided, install that specific version
+- :upgrade: Upgrade a pip package - if version is provided, upgrade to that specific version
+- :remove: Remove a pip package
+- :purge: Purge a pip package (this usually entails removing configuration files as well as the package itself).  With pip packages this behaves the same as `:remove`
+
+# Attribute Parameters
+
+- package_name: name attribute. The name of the pip package to install
+- version: the version of the package to install/upgrade.  If no version is given latest is assumed.
+- virtualenv: virtualenv environment to install pip package into
+- options: Add additional options to the underlying pip package command
+- timeout: timeout in seconds for the command to execute. Useful for pip packages that may take a long time to install. Default 900 seconds.
+
+# Example
+
+    # install latest gunicorn into system path
+    python_pip "gunicorn" do
+      action :install
+    end
+
+    # target a virtualenv
+    python_pip "gunicorn" do
+      virtualenv "/home/ubunut/my_ve"
+      action :install
+    end
+
+    # install Django 1.1.4
+    python_pip "django" do
+      version "1.1.4"
+      action :install
+    end
+
+    # use this provider with the core package resource
+    package "django" do
+      provider Chef::Provider::PythonPip
+      action :install
+    end
+
+`python_virtualenv`
+-------------------
+
+[`virtualenv`](http://pypi.python.org/pypi/virtualenv) is a great tool that creates isolated python environments.  Think of it as RVM without all those hipsters and tight jeans.
+
+# Actions
+
+- :create: creates a new virtualenv
+- :delete: deletes an existing virtualenv
+
+# Attribute Parameters
+
+- path: name attribute. The path where the virtualenv will be created
+- interpreter: The Python interpreter to use. default is `python2.6`
+- owner: The owner for the virtualenv
+- group: The group owner of the file (string or id)
+- options : Command line options (string)
+
+# Example
+
+    # create a 2.6 virtualenv owned by ubuntu user
+    python_virtualenv "/home/ubuntu/my_cool_ve" do
+      owner "ubuntu"
+      group "ubuntu"
+      action :create
+    end
+
+    # create a Python 2.4 virtualenv
+    python_virtualenv "/home/ubuntu/my_old_ve" do
+      interpreter "python2.4"
+      owner "ubuntu"
+      group "ubuntu"
+      action :create
+    end
+
+    # create a Python 2.6 virtualenv with access to the global packages owned by ubuntu user
+    python_virtualenv "/home/ubuntu/my_old_ve" do
+      owner "ubuntu"
+      group "ubuntu"
+      options "--system-site-packages"
+      action :create
+    end
+
+Usage
+=====
+
+default
+-------
+
+Include default recipe in a run list, to get `python`, `pip` and `virtualenv`. Installs python by package or source depending on the platform.
+
+package
+-------
+
+Installs Python from packages.
+
+source
+------
+
+Installs Python from source.
+
+pip
+---
+
+Installs `pip` from source.
+
+virtualenv
+----------
+
+Installs virtualenv using the `python_pip` resource.
+
+License and Author
+==================
+
+Author:: Seth Chisamore (<sc...@opscode.com>)
+
+Copyright:: 2011, Opscode, Inc
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/python/attributes/.svn/all-wcprops
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/python/attributes/.svn/all-wcprops b/src/main/vm/src/cookbooks/python/attributes/.svn/all-wcprops
new file mode 100755
index 0000000..0796ff8
--- /dev/null
+++ b/src/main/vm/src/cookbooks/python/attributes/.svn/all-wcprops
@@ -0,0 +1,11 @@
+K 25
+svn:wc:ra_dav:version-url
+V 101
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks/python/attributes
+END
+default.rb
+K 25
+svn:wc:ra_dav:version-url
+V 112
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks/python/attributes/default.rb
+END

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/python/attributes/.svn/entries
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/python/attributes/.svn/entries b/src/main/vm/src/cookbooks/python/attributes/.svn/entries
new file mode 100755
index 0000000..45bfe19
--- /dev/null
+++ b/src/main/vm/src/cookbooks/python/attributes/.svn/entries
@@ -0,0 +1,62 @@
+10
+
+dir
+1485921
+https://svn.apache.org/repos/asf/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks/python/attributes
+https://svn.apache.org/repos/asf
+
+
+
+2012-11-20T00:41:18.502817Z
+1474517
+ahart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+13f79535-47bb-0310-9956-ffa450edef68
+
+default.rb
+file
+
+
+
+
+2013-05-24T10:13:50.000000Z
+65238812685277bf503ec6dbb8bb6617
+2012-11-20T00:41:18.502817Z
+1474517
+ahart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+1431
+

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/python/attributes/.svn/text-base/default.rb.svn-base
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/python/attributes/.svn/text-base/default.rb.svn-base b/src/main/vm/src/cookbooks/python/attributes/.svn/text-base/default.rb.svn-base
new file mode 100755
index 0000000..794d873
--- /dev/null
+++ b/src/main/vm/src/cookbooks/python/attributes/.svn/text-base/default.rb.svn-base
@@ -0,0 +1,42 @@
+#
+# Author:: Seth Chisamore (<sc...@opscode.com>)
+# Cookbook Name:: python
+# Attribute:: default
+#
+# Copyright 2011, Opscode, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+default['python']['install_method'] = 'package'
+
+if python['install_method'] == 'package'
+  default['python']['prefix_dir']         = '/usr'
+else
+  default['python']['prefix_dir']         = '/usr/local'
+end
+
+case platform
+when "redhat","centos","scientific","fedora","suse","amazon"
+  set['python']['pip']['prefix_dir']  = '/usr'
+when "debian","ubuntu"
+  set['python']['pip']['prefix_dir']  = '/usr/local'
+else
+  set['python']['pip']['prefix_dir']  = '/usr/local'
+end
+
+default['python']['url'] = 'http://www.python.org/ftp/python'
+default['python']['version'] = '2.7.1'
+default['python']['checksum'] = '80e387bcf57eae8ce26726753584fd63e060ec11682d1145af921e85fd612292'
+default['python']['configure_options'] = %W{--prefix=#{python['prefix_dir']}}
+

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/python/attributes/default.rb
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/python/attributes/default.rb b/src/main/vm/src/cookbooks/python/attributes/default.rb
new file mode 100755
index 0000000..794d873
--- /dev/null
+++ b/src/main/vm/src/cookbooks/python/attributes/default.rb
@@ -0,0 +1,42 @@
+#
+# Author:: Seth Chisamore (<sc...@opscode.com>)
+# Cookbook Name:: python
+# Attribute:: default
+#
+# Copyright 2011, Opscode, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+default['python']['install_method'] = 'package'
+
+if python['install_method'] == 'package'
+  default['python']['prefix_dir']         = '/usr'
+else
+  default['python']['prefix_dir']         = '/usr/local'
+end
+
+case platform
+when "redhat","centos","scientific","fedora","suse","amazon"
+  set['python']['pip']['prefix_dir']  = '/usr'
+when "debian","ubuntu"
+  set['python']['pip']['prefix_dir']  = '/usr/local'
+else
+  set['python']['pip']['prefix_dir']  = '/usr/local'
+end
+
+default['python']['url'] = 'http://www.python.org/ftp/python'
+default['python']['version'] = '2.7.1'
+default['python']['checksum'] = '80e387bcf57eae8ce26726753584fd63e060ec11682d1145af921e85fd612292'
+default['python']['configure_options'] = %W{--prefix=#{python['prefix_dir']}}
+

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/python/metadata.json
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/python/metadata.json b/src/main/vm/src/cookbooks/python/metadata.json
new file mode 100755
index 0000000..5b9dbf0
--- /dev/null
+++ b/src/main/vm/src/cookbooks/python/metadata.json
@@ -0,0 +1,42 @@
+{
+  "name": "python",
+  "description": "Installs Python, pip and virtualenv. Includes LWRPs for managing Python packages with `pip` and `virtualenv` isolated Python environments.",
+  "long_description": "",
+  "maintainer": "Opscode, Inc.",
+  "maintainer_email": "cookbooks@opscode.com",
+  "license": "Apache 2.0",
+  "platforms": {
+    "debian": ">= 0.0.0",
+    "ubuntu": ">= 0.0.0",
+    "centos": ">= 0.0.0",
+    "redhat": ">= 0.0.0",
+    "fedora": ">= 0.0.0",
+    "freebsd": ">= 0.0.0"
+  },
+  "dependencies": {
+    "build-essential": ">= 0.0.0",
+    "yum": ">= 0.0.0"
+  },
+  "recommendations": {
+  },
+  "suggestions": {
+  },
+  "conflicting": {
+  },
+  "providing": {
+  },
+  "replacing": {
+  },
+  "attributes": {
+  },
+  "groupings": {
+  },
+  "recipes": {
+    "python": "Installs python, pip, and virtualenv",
+    "python::package": "Installs python using packages.",
+    "python::source": "Installs python from source.",
+    "python::pip": "Installs pip from source.",
+    "python::virtualenv": "Installs virtualenv using the python_pip resource."
+  },
+  "version": "1.0.8"
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/python/metadata.rb
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/python/metadata.rb b/src/main/vm/src/cookbooks/python/metadata.rb
new file mode 100755
index 0000000..efca7b9
--- /dev/null
+++ b/src/main/vm/src/cookbooks/python/metadata.rb
@@ -0,0 +1,18 @@
+maintainer        "Opscode, Inc."
+maintainer_email  "cookbooks@opscode.com"
+license           "Apache 2.0"
+description       "Installs Python, pip and virtualenv. Includes LWRPs for managing Python packages with `pip` and `virtualenv` isolated Python environments."
+version           "1.0.8"
+
+depends           "build-essential"
+depends           "yum"
+
+recipe "python", "Installs python, pip, and virtualenv"
+recipe "python::package", "Installs python using packages."
+recipe "python::source", "Installs python from source."
+recipe "python::pip", "Installs pip from source."
+recipe "python::virtualenv", "Installs virtualenv using the python_pip resource."
+
+%w{ debian ubuntu centos redhat fedora freebsd }.each do |os|
+  supports os
+end

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/python/providers/.svn/all-wcprops
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/python/providers/.svn/all-wcprops b/src/main/vm/src/cookbooks/python/providers/.svn/all-wcprops
new file mode 100755
index 0000000..c46e0d2
--- /dev/null
+++ b/src/main/vm/src/cookbooks/python/providers/.svn/all-wcprops
@@ -0,0 +1,17 @@
+K 25
+svn:wc:ra_dav:version-url
+V 100
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks/python/providers
+END
+virtualenv.rb
+K 25
+svn:wc:ra_dav:version-url
+V 114
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks/python/providers/virtualenv.rb
+END
+pip.rb
+K 25
+svn:wc:ra_dav:version-url
+V 107
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks/python/providers/pip.rb
+END

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/python/providers/.svn/entries
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/python/providers/.svn/entries b/src/main/vm/src/cookbooks/python/providers/.svn/entries
new file mode 100755
index 0000000..36043fb
--- /dev/null
+++ b/src/main/vm/src/cookbooks/python/providers/.svn/entries
@@ -0,0 +1,96 @@
+10
+
+dir
+1485921
+https://svn.apache.org/repos/asf/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks/python/providers
+https://svn.apache.org/repos/asf
+
+
+
+2012-11-20T00:41:18.502817Z
+1474517
+ahart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+13f79535-47bb-0310-9956-ffa450edef68
+
+virtualenv.rb
+file
+
+
+
+
+2013-05-24T10:13:51.000000Z
+f588bcea919b8a33d911eead788bd31e
+2012-11-20T00:41:18.502817Z
+1474517
+ahart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+2099
+
+pip.rb
+file
+
+
+
+
+2013-05-24T10:13:51.000000Z
+363d6fe4e761a78d6810a809893e5822
+2012-11-20T00:41:18.502817Z
+1474517
+ahart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+5278
+


[08/51] [abbrv] [partial] Adding Jinwon's custom RCMET

Posted by jo...@apache.org.
http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/definitions/apache_module.rb
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/definitions/apache_module.rb b/src/main/vm/src/cookbooks/apache2/definitions/apache_module.rb
new file mode 100755
index 0000000..2bd739e
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/definitions/apache_module.rb
@@ -0,0 +1,43 @@
+#
+# Cookbook Name:: apache2
+# Definition:: apache_module
+#
+# Copyright 2008-2009, Opscode, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+define :apache_module, :enable => true, :conf => false do
+  include_recipe "apache2"
+ 
+  if params[:conf]
+    apache_conf params[:name]
+  end
+ 
+  if params[:enable]
+    execute "a2enmod #{params[:name]}" do
+      command "/usr/sbin/a2enmod #{params[:name]}"
+      notifies :restart, resources(:service => "apache2")
+      not_if do (File.symlink?("#{node[:apache][:dir]}/mods-enabled/#{params[:name]}.load") and
+            ((File.exists?("#{node[:apache][:dir]}/mods-available/#{params[:name]}.conf"))?
+              (File.symlink?("#{node[:apache][:dir]}/mods-enabled/#{params[:name]}.conf")):(true)))
+      end
+    end    
+  else
+    execute "a2dismod #{params[:name]}" do
+      command "/usr/sbin/a2dismod #{params[:name]}"
+      notifies :restart, resources(:service => "apache2")
+      only_if do File.symlink?("#{node[:apache][:dir]}/mods-enabled/#{params[:name]}.load") end
+    end
+  end
+end

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/definitions/apache_site.rb
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/definitions/apache_site.rb b/src/main/vm/src/cookbooks/apache2/definitions/apache_site.rb
new file mode 100755
index 0000000..7316e01
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/definitions/apache_site.rb
@@ -0,0 +1,40 @@
+#
+# Cookbook Name:: apache2
+# Definition:: apache_site
+#
+# Copyright 2008-2009, Opscode, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+define :apache_site, :enable => true do
+  include_recipe "apache2"
+  
+  if params[:enable]
+    execute "a2ensite #{params[:name]}" do
+      command "/usr/sbin/a2ensite #{params[:name]}"
+      notifies :restart, resources(:service => "apache2")
+      not_if do 
+        File.symlink?("#{node[:apache][:dir]}/sites-enabled/#{params[:name]}") or
+          File.symlink?("#{node[:apache][:dir]}/sites-enabled/000-#{params[:name]}")
+      end
+      only_if do File.exists?("#{node[:apache][:dir]}/sites-available/#{params[:name]}") end
+    end
+  else
+    execute "a2dissite #{params[:name]}" do
+      command "/usr/sbin/a2dissite #{params[:name]}"
+      notifies :restart, resources(:service => "apache2")
+      only_if do File.symlink?("#{node[:apache][:dir]}/sites-enabled/#{params[:name]}") end
+    end
+  end
+end

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/definitions/web_app.rb
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/definitions/web_app.rb b/src/main/vm/src/cookbooks/apache2/definitions/web_app.rb
new file mode 100755
index 0000000..b532708
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/definitions/web_app.rb
@@ -0,0 +1,49 @@
+#
+# Cookbook Name:: apache2
+# Definition:: web_app
+#
+# Copyright 2008-2009, Opscode, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+define :web_app, :template => "web_app.conf.erb" do
+  
+  application_name = params[:name]
+
+  include_recipe "apache2"
+  include_recipe "apache2::mod_rewrite"
+  include_recipe "apache2::mod_deflate"
+  include_recipe "apache2::mod_headers"
+  
+  template "#{node[:apache][:dir]}/sites-available/#{application_name}.conf" do
+    source params[:template]
+    owner "root"
+    group "root"
+    mode 0644
+    if params[:cookbook]
+      cookbook params[:cookbook]
+    end
+    variables(
+      :application_name => application_name,
+      :params => params
+    )
+    if File.exists?("#{node[:apache][:dir]}/sites-enabled/#{application_name}.conf")
+      notifies :reload, resources(:service => "apache2"), :delayed
+    end
+  end
+  
+  apache_site "#{params[:name]}.conf" do
+    enable enable_setting
+  end
+end

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/files/.svn/all-wcprops
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/files/.svn/all-wcprops b/src/main/vm/src/cookbooks/apache2/files/.svn/all-wcprops
new file mode 100755
index 0000000..95ba8dc
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/files/.svn/all-wcprops
@@ -0,0 +1,5 @@
+K 25
+svn:wc:ra_dav:version-url
+V 97
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks/apache2/files
+END

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/files/.svn/entries
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/files/.svn/entries b/src/main/vm/src/cookbooks/apache2/files/.svn/entries
new file mode 100755
index 0000000..e6841a4
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/files/.svn/entries
@@ -0,0 +1,31 @@
+10
+
+dir
+1485921
+https://svn.apache.org/repos/asf/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks/apache2/files
+https://svn.apache.org/repos/asf
+
+
+
+2012-10-10T00:49:17.045897Z
+1474264
+ahart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+13f79535-47bb-0310-9956-ffa450edef68
+
+default
+dir
+

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/files/default/.svn/all-wcprops
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/files/default/.svn/all-wcprops b/src/main/vm/src/cookbooks/apache2/files/default/.svn/all-wcprops
new file mode 100755
index 0000000..422e5f5
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/files/default/.svn/all-wcprops
@@ -0,0 +1,11 @@
+K 25
+svn:wc:ra_dav:version-url
+V 105
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks/apache2/files/default
+END
+apache2_module_conf_generate.pl
+K 25
+svn:wc:ra_dav:version-url
+V 137
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks/apache2/files/default/apache2_module_conf_generate.pl
+END

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/files/default/.svn/entries
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/files/default/.svn/entries b/src/main/vm/src/cookbooks/apache2/files/default/.svn/entries
new file mode 100755
index 0000000..01301bf
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/files/default/.svn/entries
@@ -0,0 +1,62 @@
+10
+
+dir
+1485921
+https://svn.apache.org/repos/asf/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks/apache2/files/default
+https://svn.apache.org/repos/asf
+
+
+
+2012-10-10T00:49:17.045897Z
+1474264
+ahart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+13f79535-47bb-0310-9956-ffa450edef68
+
+apache2_module_conf_generate.pl
+file
+
+
+
+
+2013-05-24T10:13:51.000000Z
+72b1767bbcfe18d79d2c834c41ed5db3
+2012-10-10T00:49:17.045897Z
+1474264
+ahart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+848
+

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/files/default/.svn/text-base/apache2_module_conf_generate.pl.svn-base
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/files/default/.svn/text-base/apache2_module_conf_generate.pl.svn-base b/src/main/vm/src/cookbooks/apache2/files/default/.svn/text-base/apache2_module_conf_generate.pl.svn-base
new file mode 100755
index 0000000..83f849e
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/files/default/.svn/text-base/apache2_module_conf_generate.pl.svn-base
@@ -0,0 +1,41 @@
+#!/usr/bin/perl
+
+=begin
+
+Generates Ubuntu style module.load files.
+ 
+./apache2_module_conf_generate.pl /usr/lib64/httpd/modules /etc/httpd/mods-available
+
+ARGV[0] is the apache modules directory, ARGV[1] is where you want 'em.
+
+=cut
+
+use File::Find;
+
+use strict;
+use warnings;
+
+die "Must have '/path/to/modules' and '/path/to/modules.load'"
+  unless $ARGV[0] && $ARGV[1];
+
+find(
+  {
+    wanted => sub {
+      return 1 if $File::Find::name !~ /\.so$/;
+      my $modfile = $_;
+      $modfile =~ /(lib|mod_)(.+)\.so$/;
+      my $modname  = $2;
+      my $filename = "$ARGV[1]/$modname.load";
+      unless ( -f $filename ) {
+        open( FILE, ">", $filename ) or die "Cannot open $filename";
+        print FILE "LoadModule " . $modname . "_module $File::Find::name\n";
+        close(FILE);
+      }
+    },
+    follow => 1,
+  },
+  $ARGV[0]
+);
+
+exit 0;
+

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/files/default/apache2_module_conf_generate.pl
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/files/default/apache2_module_conf_generate.pl b/src/main/vm/src/cookbooks/apache2/files/default/apache2_module_conf_generate.pl
new file mode 100755
index 0000000..83f849e
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/files/default/apache2_module_conf_generate.pl
@@ -0,0 +1,41 @@
+#!/usr/bin/perl
+
+=begin
+
+Generates Ubuntu style module.load files.
+ 
+./apache2_module_conf_generate.pl /usr/lib64/httpd/modules /etc/httpd/mods-available
+
+ARGV[0] is the apache modules directory, ARGV[1] is where you want 'em.
+
+=cut
+
+use File::Find;
+
+use strict;
+use warnings;
+
+die "Must have '/path/to/modules' and '/path/to/modules.load'"
+  unless $ARGV[0] && $ARGV[1];
+
+find(
+  {
+    wanted => sub {
+      return 1 if $File::Find::name !~ /\.so$/;
+      my $modfile = $_;
+      $modfile =~ /(lib|mod_)(.+)\.so$/;
+      my $modname  = $2;
+      my $filename = "$ARGV[1]/$modname.load";
+      unless ( -f $filename ) {
+        open( FILE, ">", $filename ) or die "Cannot open $filename";
+        print FILE "LoadModule " . $modname . "_module $File::Find::name\n";
+        close(FILE);
+      }
+    },
+    follow => 1,
+  },
+  $ARGV[0]
+);
+
+exit 0;
+

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/metadata.json
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/metadata.json b/src/main/vm/src/cookbooks/apache2/metadata.json
new file mode 100755
index 0000000..a9280ea
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/metadata.json
@@ -0,0 +1,497 @@
+{
+    "suggestions": {
+    },
+    "attributes": {
+      "apache/traceenable": {
+        "required": "optional",
+        "calculated": false,
+        "choice": [
+
+        ],
+        "default": "On",
+        "type": "string",
+        "recipes": [
+
+        ],
+        "description": "Determine behavior of TRACE requests",
+        "display_name": "Apache Trace Enable"
+      },
+      "apache/serversignature": {
+        "required": "optional",
+        "calculated": false,
+        "choice": [
+
+        ],
+        "default": "On",
+        "type": "string",
+        "recipes": [
+
+        ],
+        "description": "Configure footer on server-generated documents",
+        "display_name": "Apache Server Signature"
+      },
+      "apache/contact": {
+        "required": "optional",
+        "calculated": false,
+        "choice": [
+
+        ],
+        "default": "ops@example.com",
+        "type": "string",
+        "recipes": [
+
+        ],
+        "description": "Email address of webmaster",
+        "display_name": "Apache Contact"
+      },
+      "apache/icondir": {
+        "required": "optional",
+        "calculated": false,
+        "choice": [
+
+        ],
+        "default": "/usr/share/apache2/icons",
+        "type": "string",
+        "recipes": [
+
+        ],
+        "description": "Directory location for icons",
+        "display_name": "Apache Icondir"
+      },
+      "apache/user": {
+        "required": "optional",
+        "calculated": false,
+        "choice": [
+
+        ],
+        "default": "www-data",
+        "type": "string",
+        "recipes": [
+
+        ],
+        "description": "User Apache runs as",
+        "display_name": "Apache User"
+      },
+      "apache/worker/threadsperchild": {
+        "required": "optional",
+        "calculated": false,
+        "choice": [
+
+        ],
+        "default": "64",
+        "type": "string",
+        "recipes": [
+
+        ],
+        "description": "Constant number of worker threads in each server process",
+        "display_name": "Apache Worker MPM ThreadsPerChild"
+      },
+      "apache/worker/maxclients": {
+        "required": "optional",
+        "calculated": false,
+        "choice": [
+
+        ],
+        "default": "1024",
+        "type": "string",
+        "recipes": [
+
+        ],
+        "description": "Maximum number of simultaneous connections",
+        "display_name": "Apache Worker MPM MaxClients"
+      },
+      "apache/worker": {
+        "required": "optional",
+        "calculated": false,
+        "choice": [
+
+        ],
+        "type": "hash",
+        "recipes": [
+
+        ],
+        "description": "Hash of Apache prefork tuning attributes.",
+        "display_name": "Apache Worker"
+      },
+      "apache/keepaliverequests": {
+        "required": "optional",
+        "calculated": false,
+        "choice": [
+
+        ],
+        "default": "100",
+        "type": "string",
+        "recipes": [
+
+        ],
+        "description": "Number of requests allowed on a persistent connection",
+        "display_name": "Apache Keepalive Requests"
+      },
+      "apache/timeout": {
+        "required": "optional",
+        "calculated": false,
+        "choice": [
+
+        ],
+        "default": "300",
+        "type": "string",
+        "recipes": [
+
+        ],
+        "description": "Connection timeout value",
+        "display_name": "Apache Timeout"
+      },
+      "apache/worker/maxrequestsperchild": {
+        "required": "optional",
+        "calculated": false,
+        "choice": [
+
+        ],
+        "default": "0",
+        "type": "string",
+        "recipes": [
+
+        ],
+        "description": "Maximum number of request a child process will handle",
+        "display_name": "Apache Worker MPM MaxRequestsPerChild"
+      },
+      "apache/dir": {
+        "required": "optional",
+        "calculated": false,
+        "choice": [
+
+        ],
+        "default": "/etc/apache2",
+        "type": "string",
+        "recipes": [
+
+        ],
+        "description": "Location for Apache configuration",
+        "display_name": "Apache Directory"
+      },
+      "apache/prefork/serverlimit": {
+        "required": "optional",
+        "calculated": false,
+        "choice": [
+
+        ],
+        "default": "400",
+        "type": "string",
+        "recipes": [
+
+        ],
+        "description": "Upper limit on configurable server processes",
+        "display_name": "Apache Prefork MPM ServerLimit"
+      },
+      "apache/prefork/minspareservers": {
+        "required": "optional",
+        "calculated": false,
+        "choice": [
+
+        ],
+        "default": "16",
+        "type": "string",
+        "recipes": [
+
+        ],
+        "description": "Minimum number of spare server processes",
+        "display_name": "Apache Prefork MPM MinSpareServers"
+      },
+      "apache/allowed_openids": {
+        "required": "optional",
+        "calculated": false,
+        "choice": [
+
+        ],
+        "default": "",
+        "type": "string",
+        "recipes": [
+
+        ],
+        "description": "Array of OpenIDs allowed to authenticate",
+        "display_name": "Apache Allowed OpenIDs"
+      },
+      "apache/binary": {
+        "required": "optional",
+        "calculated": false,
+        "choice": [
+
+        ],
+        "default": "/usr/sbin/apache2",
+        "type": "string",
+        "recipes": [
+
+        ],
+        "description": "Apache server daemon program",
+        "display_name": "Apache Binary"
+      },
+      "apache/prefork/startservers": {
+        "required": "optional",
+        "calculated": false,
+        "choice": [
+
+        ],
+        "default": "16",
+        "type": "string",
+        "recipes": [
+
+        ],
+        "description": "Number of MPM servers to start",
+        "display_name": "Apache Prefork MPM StartServers"
+      },
+      "apache/listen_ports": {
+        "required": "optional",
+        "calculated": false,
+        "choice": [
+
+        ],
+        "default": [
+          "80",
+          "443"
+        ],
+        "type": "array",
+        "recipes": [
+
+        ],
+        "description": "Ports that Apache should listen on",
+        "display_name": "Apache Listen Ports"
+      },
+      "apache/prefork/maxrequestsperchild": {
+        "required": "optional",
+        "calculated": false,
+        "choice": [
+
+        ],
+        "default": "10000",
+        "type": "string",
+        "recipes": [
+
+        ],
+        "description": "Maximum number of request a child process will handle",
+        "display_name": "Apache Prefork MPM MaxRequestsPerChild"
+      },
+      "apache/keepalivetimeout": {
+        "required": "optional",
+        "calculated": false,
+        "choice": [
+
+        ],
+        "default": "5",
+        "type": "string",
+        "recipes": [
+
+        ],
+        "description": "Time to wait for requests on persistent connection",
+        "display_name": "Apache Keepalive Timeout"
+      },
+      "apache/keepalive": {
+        "required": "optional",
+        "calculated": false,
+        "choice": [
+
+        ],
+        "default": "On",
+        "type": "string",
+        "recipes": [
+
+        ],
+        "description": "HTTP persistent connections",
+        "display_name": "Apache Keepalive"
+      },
+      "apache": {
+        "required": "optional",
+        "calculated": false,
+        "choice": [
+
+        ],
+        "type": "hash",
+        "recipes": [
+
+        ],
+        "description": "Hash of Apache attributes",
+        "display_name": "Apache Hash"
+      },
+      "apache/worker/maxsparethreads": {
+        "required": "optional",
+        "calculated": false,
+        "choice": [
+
+        ],
+        "default": "192",
+        "type": "string",
+        "recipes": [
+
+        ],
+        "description": "Maximum number of spare worker threads",
+        "display_name": "Apache Worker MPM MaxSpareThreads"
+      },
+      "apache/worker/startservers": {
+        "required": "optional",
+        "calculated": false,
+        "choice": [
+
+        ],
+        "default": "4",
+        "type": "string",
+        "recipes": [
+
+        ],
+        "description": "Initial number of server processes to start",
+        "display_name": "Apache Worker MPM StartServers"
+      },
+      "apache/prefork/maxclients": {
+        "required": "optional",
+        "calculated": false,
+        "choice": [
+
+        ],
+        "default": "400",
+        "type": "string",
+        "recipes": [
+
+        ],
+        "description": "Maximum number of simultaneous connections",
+        "display_name": "Apache Prefork MPM MaxClients"
+      },
+      "apache/prefork": {
+        "required": "optional",
+        "calculated": false,
+        "choice": [
+
+        ],
+        "type": "hash",
+        "recipes": [
+
+        ],
+        "description": "Hash of Apache prefork tuning attributes.",
+        "display_name": "Apache Prefork"
+      },
+      "apache/servertokens": {
+        "required": "optional",
+        "calculated": false,
+        "choice": [
+
+        ],
+        "default": "Prod",
+        "type": "string",
+        "recipes": [
+
+        ],
+        "description": "Server response header",
+        "display_name": "Apache Server Tokens"
+      },
+      "apache/log_dir": {
+        "required": "optional",
+        "calculated": false,
+        "choice": [
+
+        ],
+        "default": "/etc/apache2",
+        "type": "string",
+        "recipes": [
+
+        ],
+        "description": "Location for Apache logs",
+        "display_name": "Apache Log Directory"
+      },
+      "apache/worker/minsparethreads": {
+        "required": "optional",
+        "calculated": false,
+        "choice": [
+
+        ],
+        "default": "64",
+        "type": "string",
+        "recipes": [
+
+        ],
+        "description": "Minimum number of spare worker threads",
+        "display_name": "Apache Worker MPM MinSpareThreads"
+      },
+      "apache/prefork/maxspareservers": {
+        "required": "optional",
+        "calculated": false,
+        "choice": [
+
+        ],
+        "default": "32",
+        "type": "string",
+        "recipes": [
+
+        ],
+        "description": "Maximum number of spare server processes",
+        "display_name": "Apache Prefork MPM MaxSpareServers"
+      }
+    },
+    "maintainer_email": "cookbooks@opscode.com",
+    "conflicting": {
+    },
+    "dependencies": {
+    },
+    "recipes": {
+      "apache2::mod_dav": "Apache module 'dav'",
+      "apache2::mod_proxy_ajp": "Apache module 'proxy_ajp'",
+      "apache2::mod_php5": "Apache module 'php5'",
+      "apache2::mod_mime": "Apache module 'mime' with config file",
+      "apache2::mod_deflate": "Apache module 'deflate' with config file",
+      "apache2::mod_ssl": "Apache module 'ssl' with config file, adds port 443 to listen_ports",
+      "apache2::mod_setenvif": "Apache module 'setenvif' with config file",
+      "apache2::mod_python": "Apache module 'python'",
+      "apache2::mod_negotiation": "Apache module 'negotiation' with config file",
+      "apache2::mod_cgi": "Apache module 'cgi'",
+      "apache2::mod_authz_groupfile": "Apache module 'authz_groupfile'",
+      "apache2::mod_auth_basic": "Apache module 'auth_basic'",
+      "apache2::mod_rewrite": "Apache module 'rewrite'",
+      "apache2::mod_dav_svn": "Apache module 'dav_svn'",
+      "apache2::mod_autoindex": "Apache module 'autoindex' with config file",
+      "apache2::mod_authz_host": "Apache module 'authz_host'",
+      "apache2::mod_headers": "Apache module 'headers'",
+      "apache2::mod_authz_user": "Apache module 'authz_user'",
+      "apache2::mod_proxy_connect": "Apache module 'proxy_connect'",
+      "apache2::mod_proxy": "Apache module 'proxy' with config file",
+      "apache2::mod_fcgid": "Apache module 'fcgid', package on ubuntu/debian, rhel/centos, compile source on suse; with config file",
+      "apache2::mod_authnz_ldap": "Apache module 'authnz_ldap'",
+      "apache2::mod_auth_digest": "Apache module 'auth_digest'",
+      "apache2::mod_env": "Apache module 'env'",
+      "apache2::mod_status": "Apache module 'status' with config file",
+      "apache2::mod_proxy_http": "Apache module 'proxy_http'",
+      "apache2::mod_log_config": "Apache module 'log_config'",
+      "apache2::mod_ldap": "Apache module 'ldap'",
+      "apache2::mod_expires": "Apache module 'expires'",
+      "apache2::mod_alias": "Apache module 'alias' with config file",
+      "apache2": "Main Apache configuration",
+      "apache2::mod_authn_file": "Apache module 'authn_file'",
+      "apache2::mod_auth_openid": "Apache module 'authopenid'",
+      "apache2::mod_proxy_balancer": "Apache module 'proxy_balancer'",
+      "apache2::mod_dir": "Apache module 'dir' with config file",
+      "apache2::mod_authz_default": "Apache module 'authz_default'"
+    },
+    "providing": {
+    },
+    "platforms": {
+      "debian": [
+
+      ],
+      "centos": [
+
+      ],
+      "ubuntu": [
+
+      ],
+      "redhat": [
+
+      ]
+    },
+    "license": "Apache 2.0",
+    "version": "0.12.2",
+    "replacing": {
+    },
+    "groupings": {
+    },
+    "name": "apache2",
+    "recommendations": {
+    },
+    "description": "Installs and configures all aspects of apache2 using Debian style symlinks with helper definitions",
+    "maintainer": "Opscode, Inc.",
+    "long_description": "= DESCRIPTION:\n\nComplete Debian/Ubuntu style Apache2 configuration.\n\n= REQUIREMENTS:\n\nDebian or Ubuntu preferred.\n\nRed Hat/CentOS and Fedora can be used but will be converted to a Debian/Ubuntu style Apache as it's far easier to manage with chef. \n\n= ATTRIBUTES:\n\nThe file attributes/apache.rb contains the following attribute types:\n\n* platform specific locations and settings.\n* general settings\n* prefork attributes\n* worker attributes\n\nGeneral settings and prefork/worker attributes are tunable.\n\n= USAGE:\n\nInclude the apache2 recipe to install Apache2 and get 'sane' default settings. Configuration is modularized through Apache vhost sites a la Debian style configuration.\n\nFor Red Hat, CentOS and Fedora you should first disable selinux as it's not supported (yet), then remove the stock httpd and all it's dependencies prior to attempting to use this recipe. Many packages in these distributions drop conflicting configs into conf.d, all o
 f which haven't been accounted for yet. Starting from scratch will also make it far easier to debug.\n\n== Defines:\n\n* apache_module: sets up an Apache module.\n* apache_conf: sets up a config file for an apache module.\n* apache_site: sets up a vhost site. The conf file must be available.\n* web_app: copies the template for a web app and enables it as a site via apache_site.\n\n== Web Apps:\n\nVarious applications that can be set up with Apache as the front end, such as PHP, Django, Rails and others can use the web_app define to set up the template and the Apache site. The define is kind of dumb, so the template needs have the application implementation settings, since we don't know what your app is or what is needed from Apache.\n\nWe only prototype one parameter for the web_app define, \"template\". This is used to specify the name of the template to use in the current cookbook. When you use web_app, you can set up any parameters you want to use in your template. They will get 
 passed to the template through the params hash. For example, the sample web_app.conf.erb template in this cookbook makes use of these.\n\n* docroot\n* server_name\n* server_aliases\n\nThese are available as @params[:docroot], @params[:server_name], @params[:server_aliases] within the template. \n\nIf 'cookbook' and 'template' are not specified, the current cookbook's templates/default/web_app.conf.erb will be used. If this template is not suitable for your application, copy it to your cookbook and customize as needed.\n\n== God Monitor:\n\nThere's a new recipe, apache2::god_monitor. You will need to make sure to include the 'god' recipe before using the apache2::god_monitor recipe in your cookbook.\n\n== OpenID Auth\n\nInstalls the mod_auth_openid module from source. Specify an array of OpenIDs that are allowed to authenticate with the attribute apache[:allowed_openids]. Use the following in a vhost to protect with OpenID authentication:\n\n    AuthOpenIDEnabled On\n    AuthOpenIDDB
 Location /var/cache/apache2/mod_auth_openid.db\n    AuthOpenIDUserProgram /usr/local/bin/mod_auth_openid.rb\n\nChange the DBLocation as appropriate for your platform. You'll need to change the file in the recipe to match. The UserProgram is optional if you don't want to limit access by certain OpenIDs.\n\n= LICENSE & AUTHOR:\n\nAuthor:: Joshua Timberman (<jo...@opscode.com>)\nCopyright:: 2009, Opscode, Inc\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n    http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n"
+  }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/metadata.rb
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/metadata.rb b/src/main/vm/src/cookbooks/apache2/metadata.rb
new file mode 100755
index 0000000..51f2977
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/metadata.rb
@@ -0,0 +1,197 @@
+maintainer        "Opscode, Inc."
+maintainer_email  "cookbooks@opscode.com"
+license           "Apache 2.0"
+description       "Installs and configures all aspects of apache2 using Debian style symlinks with helper definitions"
+long_description  IO.read(File.join(File.dirname(__FILE__), 'README.rdoc'))
+version           "0.12.2"
+recipe            "apache2", "Main Apache configuration"
+recipe            "apache2::mod_alias", "Apache module 'alias' with config file"
+recipe            "apache2::mod_auth_basic", "Apache module 'auth_basic'"
+recipe            "apache2::mod_auth_digest", "Apache module 'auth_digest'"
+recipe            "apache2::mod_auth_openid", "Apache module 'authopenid'"
+recipe            "apache2::mod_authn_file", "Apache module 'authn_file'"
+recipe            "apache2::mod_authnz_ldap", "Apache module 'authnz_ldap'"
+recipe            "apache2::mod_authz_default", "Apache module 'authz_default'"
+recipe            "apache2::mod_authz_groupfile", "Apache module 'authz_groupfile'"
+recipe            "apache2::mod_authz_host", "Apache module 'authz_host'"
+recipe            "apache2::mod_authz_user", "Apache module 'authz_user'"
+recipe            "apache2::mod_autoindex", "Apache module 'autoindex' with config file"
+recipe            "apache2::mod_cgi", "Apache module 'cgi'"
+recipe            "apache2::mod_dav", "Apache module 'dav'"
+recipe            "apache2::mod_dav_svn", "Apache module 'dav_svn'"
+recipe            "apache2::mod_deflate", "Apache module 'deflate' with config file"
+recipe            "apache2::mod_dir", "Apache module 'dir' with config file"
+recipe            "apache2::mod_env", "Apache module 'env'"
+recipe            "apache2::mod_expires", "Apache module 'expires'"
+recipe            "apache2::mod_fcgid", "Apache module 'fcgid', package on ubuntu/debian, rhel/centos, compile source on suse; with config file"
+recipe            "apache2::mod_headers", "Apache module 'headers'"
+recipe            "apache2::mod_ldap", "Apache module 'ldap'"
+recipe            "apache2::mod_log_config", "Apache module 'log_config'"
+recipe            "apache2::mod_mime", "Apache module 'mime' with config file"
+recipe            "apache2::mod_negotiation", "Apache module 'negotiation' with config file"
+recipe            "apache2::mod_php5", "Apache module 'php5'"
+recipe            "apache2::mod_proxy", "Apache module 'proxy' with config file"
+recipe            "apache2::mod_proxy_ajp", "Apache module 'proxy_ajp'"
+recipe            "apache2::mod_proxy_balancer", "Apache module 'proxy_balancer'"
+recipe            "apache2::mod_proxy_connect", "Apache module 'proxy_connect'"
+recipe            "apache2::mod_proxy_http", "Apache module 'proxy_http'"
+recipe            "apache2::mod_python", "Apache module 'python'"
+recipe            "apache2::mod_rewrite", "Apache module 'rewrite'"
+recipe            "apache2::mod_setenvif", "Apache module 'setenvif' with config file"
+recipe            "apache2::mod_ssl", "Apache module 'ssl' with config file, adds port 443 to listen_ports"
+recipe            "apache2::mod_status", "Apache module 'status' with config file"
+
+%w{redhat centos debian ubuntu}.each do |os|
+  supports os
+end
+
+attribute "apache",
+  :display_name => "Apache Hash",
+  :description => "Hash of Apache attributes",
+  :type => "hash"
+
+attribute "apache/dir",
+  :display_name => "Apache Directory",
+  :description => "Location for Apache configuration",
+  :default => "/etc/apache2"
+
+attribute "apache/log_dir",
+  :display_name => "Apache Log Directory",
+  :description => "Location for Apache logs",
+  :default => "/etc/apache2"
+
+attribute "apache/user",
+  :display_name => "Apache User",
+  :description => "User Apache runs as",
+  :default => "www-data"
+
+attribute "apache/binary",
+  :display_name => "Apache Binary",
+  :description => "Apache server daemon program",
+  :default => "/usr/sbin/apache2"
+
+attribute "apache/icondir", 
+  :display_name => "Apache Icondir",
+  :description => "Directory location for icons",
+  :default => "/usr/share/apache2/icons"
+
+attribute "apache/listen_ports",
+  :display_name => "Apache Listen Ports",
+  :description => "Ports that Apache should listen on",
+  :type => "array",
+  :default => [ "80", "443" ]
+
+attribute "apache/contact",
+  :display_name => "Apache Contact",
+  :description => "Email address of webmaster",
+  :default => "ops@example.com"
+
+attribute "apache/timeout",
+  :display_name => "Apache Timeout",
+  :description => "Connection timeout value",
+  :default => "300"
+
+attribute "apache/keepalive",
+  :display_name => "Apache Keepalive",
+  :description => "HTTP persistent connections",
+  :default => "On"
+
+attribute "apache/keepaliverequests",
+  :display_name => "Apache Keepalive Requests",
+  :description => "Number of requests allowed on a persistent connection",
+  :default => "100"
+
+attribute "apache/keepalivetimeout",
+  :display_name => "Apache Keepalive Timeout",
+  :description => "Time to wait for requests on persistent connection",
+  :default => "5"
+
+attribute "apache/servertokens",
+  :display_name => "Apache Server Tokens",
+  :description => "Server response header",
+  :default => "Prod"
+
+attribute "apache/serversignature",
+  :display_name => "Apache Server Signature",
+  :description => "Configure footer on server-generated documents",
+  :default => "On"
+
+attribute "apache/traceenable",
+  :display_name => "Apache Trace Enable",
+  :description => "Determine behavior of TRACE requests",
+  :default => "On"
+
+attribute "apache/allowed_openids",
+  :display_name => "Apache Allowed OpenIDs",
+  :description => "Array of OpenIDs allowed to authenticate",
+  :default => ""
+
+attribute "apache/prefork",
+  :display_name => "Apache Prefork",
+  :description => "Hash of Apache prefork tuning attributes.",
+  :type => "hash"
+
+attribute "apache/prefork/startservers",
+  :display_name => "Apache Prefork MPM StartServers",
+  :description => "Number of MPM servers to start",
+  :default => "16"
+
+attribute "apache/prefork/minspareservers",
+  :display_name => "Apache Prefork MPM MinSpareServers",
+  :description => "Minimum number of spare server processes",
+  :default => "16"
+
+attribute "apache/prefork/maxspareservers",
+  :display_name => "Apache Prefork MPM MaxSpareServers",
+  :description => "Maximum number of spare server processes",
+  :default => "32"
+
+attribute "apache/prefork/serverlimit",
+  :display_name => "Apache Prefork MPM ServerLimit",
+  :description => "Upper limit on configurable server processes",
+  :default => "400"
+
+attribute "apache/prefork/maxclients",
+  :display_name => "Apache Prefork MPM MaxClients",
+  :description => "Maximum number of simultaneous connections",
+  :default => "400"
+
+attribute "apache/prefork/maxrequestsperchild",
+  :display_name => "Apache Prefork MPM MaxRequestsPerChild",
+  :description => "Maximum number of request a child process will handle",
+  :default => "10000"
+
+attribute "apache/worker",
+  :display_name => "Apache Worker",
+  :description => "Hash of Apache prefork tuning attributes.",
+  :type => "hash"
+
+attribute "apache/worker/startservers",
+  :display_name => "Apache Worker MPM StartServers",
+  :description => "Initial number of server processes to start",
+  :default => "4"
+
+attribute "apache/worker/maxclients",
+  :display_name => "Apache Worker MPM MaxClients",
+  :description => "Maximum number of simultaneous connections",
+  :default => "1024"
+
+attribute "apache/worker/minsparethreads",
+  :display_name => "Apache Worker MPM MinSpareThreads",
+  :description => "Minimum number of spare worker threads",
+  :default => "64"
+
+attribute "apache/worker/maxsparethreads",
+  :display_name => "Apache Worker MPM MaxSpareThreads",
+  :description => "Maximum number of spare worker threads",
+  :default => "192"
+
+attribute "apache/worker/threadsperchild",
+  :display_name => "Apache Worker MPM ThreadsPerChild",
+  :description => "Constant number of worker threads in each server process",
+  :default => "64"
+
+attribute "apache/worker/maxrequestsperchild",
+  :display_name => "Apache Worker MPM MaxRequestsPerChild",
+  :description => "Maximum number of request a child process will handle",
+  :default => "0"

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/recipes/.svn/all-wcprops
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/recipes/.svn/all-wcprops b/src/main/vm/src/cookbooks/apache2/recipes/.svn/all-wcprops
new file mode 100755
index 0000000..6c4ef7e
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/recipes/.svn/all-wcprops
@@ -0,0 +1,233 @@
+K 25
+svn:wc:ra_dav:version-url
+V 99
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks/apache2/recipes
+END
+mod_dir.rb
+K 25
+svn:wc:ra_dav:version-url
+V 110
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks/apache2/recipes/mod_dir.rb
+END
+mod_authn_file.rb
+K 25
+svn:wc:ra_dav:version-url
+V 117
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks/apache2/recipes/mod_authn_file.rb
+END
+mod_expires.rb
+K 25
+svn:wc:ra_dav:version-url
+V 114
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks/apache2/recipes/mod_expires.rb
+END
+mod_negotiation.rb
+K 25
+svn:wc:ra_dav:version-url
+V 118
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks/apache2/recipes/mod_negotiation.rb
+END
+mod_ldap.rb
+K 25
+svn:wc:ra_dav:version-url
+V 111
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks/apache2/recipes/mod_ldap.rb
+END
+mod_proxy.rb
+K 25
+svn:wc:ra_dav:version-url
+V 112
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks/apache2/recipes/mod_proxy.rb
+END
+mod_setenvif.rb
+K 25
+svn:wc:ra_dav:version-url
+V 115
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks/apache2/recipes/mod_setenvif.rb
+END
+default.rb
+K 25
+svn:wc:ra_dav:version-url
+V 110
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks/apache2/recipes/default.rb
+END
+mod_mime.rb
+K 25
+svn:wc:ra_dav:version-url
+V 111
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks/apache2/recipes/mod_mime.rb
+END
+mod_authz_host.rb
+K 25
+svn:wc:ra_dav:version-url
+V 117
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks/apache2/recipes/mod_authz_host.rb
+END
+mod_authz_user.rb
+K 25
+svn:wc:ra_dav:version-url
+V 117
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks/apache2/recipes/mod_authz_user.rb
+END
+mod_proxy_connect.rb
+K 25
+svn:wc:ra_dav:version-url
+V 120
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks/apache2/recipes/mod_proxy_connect.rb
+END
+mod_auth_openid.rb
+K 25
+svn:wc:ra_dav:version-url
+V 118
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks/apache2/recipes/mod_auth_openid.rb
+END
+mod_auth_digest.rb
+K 25
+svn:wc:ra_dav:version-url
+V 118
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks/apache2/recipes/mod_auth_digest.rb
+END
+mod_autoindex.rb
+K 25
+svn:wc:ra_dav:version-url
+V 116
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks/apache2/recipes/mod_autoindex.rb
+END
+mod_dav_svn.rb
+K 25
+svn:wc:ra_dav:version-url
+V 114
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks/apache2/recipes/mod_dav_svn.rb
+END
+mod_auth_basic.rb
+K 25
+svn:wc:ra_dav:version-url
+V 117
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks/apache2/recipes/mod_auth_basic.rb
+END
+mod_deflate.rb
+K 25
+svn:wc:ra_dav:version-url
+V 114
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks/apache2/recipes/mod_deflate.rb
+END
+mod_authnz_ldap.rb
+K 25
+svn:wc:ra_dav:version-url
+V 118
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks/apache2/recipes/mod_authnz_ldap.rb
+END
+mod_wsgi.rb
+K 25
+svn:wc:ra_dav:version-url
+V 111
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks/apache2/recipes/mod_wsgi.rb
+END
+mod_fcgid.rb
+K 25
+svn:wc:ra_dav:version-url
+V 112
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks/apache2/recipes/mod_fcgid.rb
+END
+mod_proxy_http.rb
+K 25
+svn:wc:ra_dav:version-url
+V 117
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks/apache2/recipes/mod_proxy_http.rb
+END
+god_monitor.rb
+K 25
+svn:wc:ra_dav:version-url
+V 114
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks/apache2/recipes/god_monitor.rb
+END
+mod_python.rb
+K 25
+svn:wc:ra_dav:version-url
+V 113
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks/apache2/recipes/mod_python.rb
+END
+mod_rewrite.rb
+K 25
+svn:wc:ra_dav:version-url
+V 114
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks/apache2/recipes/mod_rewrite.rb
+END
+mod_status.rb
+K 25
+svn:wc:ra_dav:version-url
+V 113
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks/apache2/recipes/mod_status.rb
+END
+mod_env.rb
+K 25
+svn:wc:ra_dav:version-url
+V 110
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks/apache2/recipes/mod_env.rb
+END
+mod_alias.rb
+K 25
+svn:wc:ra_dav:version-url
+V 112
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks/apache2/recipes/mod_alias.rb
+END
+mod_authz_default.rb
+K 25
+svn:wc:ra_dav:version-url
+V 120
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks/apache2/recipes/mod_authz_default.rb
+END
+mod_ssl.rb
+K 25
+svn:wc:ra_dav:version-url
+V 110
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks/apache2/recipes/mod_ssl.rb
+END
+mod_cgi.rb
+K 25
+svn:wc:ra_dav:version-url
+V 110
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks/apache2/recipes/mod_cgi.rb
+END
+mod_log_config.rb
+K 25
+svn:wc:ra_dav:version-url
+V 117
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks/apache2/recipes/mod_log_config.rb
+END
+mod_authz_groupfile.rb
+K 25
+svn:wc:ra_dav:version-url
+V 122
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks/apache2/recipes/mod_authz_groupfile.rb
+END
+mod_proxy_balancer.rb
+K 25
+svn:wc:ra_dav:version-url
+V 121
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks/apache2/recipes/mod_proxy_balancer.rb
+END
+mod_dav.rb
+K 25
+svn:wc:ra_dav:version-url
+V 110
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks/apache2/recipes/mod_dav.rb
+END
+mod_proxy_ajp.rb
+K 25
+svn:wc:ra_dav:version-url
+V 116
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks/apache2/recipes/mod_proxy_ajp.rb
+END
+mod_headers.rb
+K 25
+svn:wc:ra_dav:version-url
+V 114
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks/apache2/recipes/mod_headers.rb
+END
+mod_php5.rb
+K 25
+svn:wc:ra_dav:version-url
+V 111
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks/apache2/recipes/mod_php5.rb
+END

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/recipes/.svn/entries
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/recipes/.svn/entries b/src/main/vm/src/cookbooks/apache2/recipes/.svn/entries
new file mode 100755
index 0000000..3d87166
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/recipes/.svn/entries
@@ -0,0 +1,1320 @@
+10
+
+dir
+1485921
+https://svn.apache.org/repos/asf/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks/apache2/recipes
+https://svn.apache.org/repos/asf
+
+
+
+2012-10-10T00:49:17.045897Z
+1474264
+ahart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+13f79535-47bb-0310-9956-ffa450edef68
+
+mod_dir.rb
+file
+
+
+
+
+2013-05-24T10:13:52.000000Z
+d4b0501a8e72a8237d433d63e8a26833
+2012-10-10T00:49:17.045897Z
+1474264
+ahart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+672
+
+mod_authn_file.rb
+file
+
+
+
+
+2013-05-24T10:13:52.000000Z
+08fb2dd248315d7145a28a7b1bb74771
+2012-10-10T00:49:17.045897Z
+1474264
+ahart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+666
+
+mod_expires.rb
+file
+
+
+
+
+2013-05-24T10:13:52.000000Z
+91d720f227bc38c3f78bb8ab8206b50b
+2012-10-10T00:49:17.045897Z
+1474264
+ahart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+660
+
+mod_negotiation.rb
+file
+
+
+
+
+2013-05-24T10:13:52.000000Z
+9daa5f1afb0f08c8828927184d6d4c05
+2012-10-10T00:49:17.045897Z
+1474264
+ahart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+687
+
+mod_ldap.rb
+file
+
+
+
+
+2013-05-24T10:13:52.000000Z
+a01a7b5839b012830e416b8614eba081
+2012-10-10T00:49:17.045897Z
+1474264
+ahart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+654
+
+mod_proxy.rb
+file
+
+
+
+
+2013-05-24T10:13:52.000000Z
+6f61d8883cff20d72c384d562b9a2ea7
+2012-10-10T00:49:17.045897Z
+1474264
+ahart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+675
+
+mod_setenvif.rb
+file
+
+
+
+
+2013-05-24T10:13:52.000000Z
+149c98c0aa89ab5cca07bfce2eb3aef9
+2012-10-10T00:49:17.045897Z
+1474264
+ahart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+681
+
+default.rb
+file
+
+
+
+
+2013-05-24T10:13:52.000000Z
+1a70078dc9caa25bb2bdd866af6012d4
+2012-10-10T00:49:17.045897Z
+1474264
+ahart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+5265
+
+mod_mime.rb
+file
+
+
+
+
+2013-05-24T10:13:52.000000Z
+7709eb03ccacf46317acee757e27c26c
+2012-10-10T00:49:17.045897Z
+1474264
+ahart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+673
+
+mod_authz_host.rb
+file
+
+
+
+
+2013-05-24T10:13:52.000000Z
+abc49522bc269c995dd4296a4671888a
+2012-10-10T00:49:17.045897Z
+1474264
+ahart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+666
+
+mod_authz_user.rb
+file
+
+
+
+
+2013-05-24T10:13:52.000000Z
+2121993aa594bb1f55251309ca7a0612
+2012-10-10T00:49:17.045897Z
+1474264
+ahart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+666
+
+mod_proxy_connect.rb
+file
+
+
+
+
+2013-05-24T10:13:52.000000Z
+8520056403b26270fcddd033fe00ebff
+2012-10-10T00:49:17.045897Z
+1474264
+ahart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+664
+
+mod_auth_openid.rb
+file
+
+
+
+
+2013-05-24T10:13:52.000000Z
+a53da98efdeb5b5b097c37120454ebf9
+2012-10-10T00:49:17.045897Z
+1474264
+ahart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+1622
+
+mod_dav_svn.rb
+file
+
+
+
+
+2013-05-24T10:13:52.000000Z
+0ac6b33f63f234264cf5432c3b75b1f9
+2012-10-10T00:49:17.045897Z
+1474264
+ahart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+686
+
+mod_auth_digest.rb
+file
+
+
+
+
+2013-05-24T10:13:52.000000Z
+2f33fab3bde2a39d8a68fc0824a881a8
+2012-10-10T00:49:17.045897Z
+1474264
+ahart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+668
+
+mod_autoindex.rb
+file
+
+
+
+
+2013-05-24T10:13:52.000000Z
+d41e781d9b4a3c8144ad7a193bd0f534
+2012-10-10T00:49:17.045897Z
+1474264
+ahart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+683
+
+mod_auth_basic.rb
+file
+
+
+
+
+2013-05-24T10:13:52.000000Z
+ee9323dc3c8ecac8369bd4a13baa0349
+2012-10-10T00:49:17.045897Z
+1474264
+ahart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+666
+
+mod_deflate.rb
+file
+
+
+
+
+2013-05-24T10:13:52.000000Z
+f626ed24a129a4f89103b0b2f43f5542
+2012-10-10T00:49:17.045897Z
+1474264
+ahart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+679
+
+mod_authnz_ldap.rb
+file
+
+
+
+
+2013-05-24T10:13:52.000000Z
+3e9f12c311cd6c0524d25ca17edfa6bd
+2012-10-10T00:49:17.045897Z
+1474264
+ahart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+668
+
+mod_wsgi.rb
+file
+
+
+
+
+2013-05-24T10:13:52.000000Z
+ae41634ce05a53b1298726b6fd7490ae
+2012-10-10T00:49:17.045897Z
+1474264
+ahart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+790
+
+mod_fcgid.rb
+file
+
+
+
+
+2013-05-24T10:13:52.000000Z
+90e4c6629372e70c2a3a624956813329
+2012-10-10T00:49:17.045897Z
+1474264
+ahart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+1451
+
+mod_proxy_http.rb
+file
+
+
+
+
+2013-05-24T10:13:52.000000Z
+99007d041a525c7c5c335a4d3f02942b
+2012-10-10T00:49:17.045897Z
+1474264
+ahart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+666
+
+god_monitor.rb
+file
+
+
+
+
+2013-05-24T10:13:52.000000Z
+b1be95d4d44d8be4c158936e55a2a703
+2012-10-10T00:49:17.045897Z
+1474264
+ahart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+1171
+
+mod_python.rb
+file
+
+
+
+
+2013-05-24T10:13:52.000000Z
+cb9a45e86ae40cee20f148dbd9499915
+2012-10-10T00:49:17.045897Z
+1474264
+ahart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+691
+
+mod_rewrite.rb
+file
+
+
+
+
+2013-05-24T10:13:52.000000Z
+3923941ada6bf8378ea35a6208e8a34e
+2012-10-10T00:49:17.045897Z
+1474264
+ahart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+660
+
+mod_status.rb
+file
+
+
+
+
+2013-05-24T10:13:52.000000Z
+d41a55c93371095b32513964ab8d9b0f
+2012-10-10T00:49:17.045897Z
+1474264
+ahart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+677
+
+mod_env.rb
+file
+
+
+
+
+2013-05-24T10:13:52.000000Z
+07eb49c91211e6ffa502295bf2ecef22
+2012-10-10T00:49:17.045897Z
+1474264
+ahart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+652
+
+mod_alias.rb
+file
+
+
+
+
+2013-05-24T10:13:52.000000Z
+5311d9085100054d059d0de65c922b4c
+2012-10-10T00:49:17.045897Z
+1474264
+ahart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+675
+
+mod_authz_default.rb
+file
+
+
+
+
+2013-05-24T10:13:52.000000Z
+e395be129fbf6e72ef050365f7124960
+2012-10-10T00:49:17.045897Z
+1474264
+ahart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+672
+
+mod_ssl.rb
+file
+
+
+
+
+2013-05-24T10:13:52.000000Z
+dc594d85a2269f5d01617229ee0859ce
+2012-10-10T00:49:17.045897Z
+1474264
+ahart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+1250
+
+mod_cgi.rb
+file
+
+
+
+
+2013-05-24T10:13:52.000000Z
+5e873ba05385ad112d21441e79559c0d
+2012-10-10T00:49:17.045897Z
+1474264
+ahart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+652
+
+mod_log_config.rb
+file
+
+
+
+
+2013-05-24T10:13:52.000000Z
+01a934d3f94fe73c16be6cc162e63e06
+2012-10-10T00:49:17.045897Z
+1474264
+ahart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+755
+
+mod_authz_groupfile.rb
+file
+
+
+
+
+2013-05-24T10:13:52.000000Z
+e5b305c49abcc08c5093badb8b281c3d
+2012-10-10T00:49:17.045897Z
+1474264
+ahart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+676
+
+mod_proxy_balancer.rb
+file
+
+
+
+
+2013-05-24T10:13:52.000000Z
+63774b0373244cc4229341a47b564116
+2012-10-10T00:49:17.045897Z
+1474264
+ahart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+665
+
+mod_dav.rb
+file
+
+
+
+
+2013-05-24T10:13:52.000000Z
+9085a2ae95e9753dc75e04dc97cfe19d
+2012-10-10T00:49:17.045897Z
+1474264
+ahart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+652
+
+mod_proxy_ajp.rb
+file
+
+
+
+
+2013-05-24T10:13:52.000000Z
+9ac3d0d9b7fe77607317e87eeeca1975
+2012-10-10T00:49:17.045897Z
+1474264
+ahart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+660
+
+mod_headers.rb
+file
+
+
+
+
+2013-05-24T10:13:52.000000Z
+ab1792e9de7461ddf4861e461c0c8a24
+2012-10-10T00:49:17.045897Z
+1474264
+ahart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+660
+
+mod_php5.rb
+file
+
+
+
+
+2013-05-24T10:13:52.000000Z
+7deeb4657aedd27e90538c3d4fd7b344
+2012-10-10T00:49:17.045897Z
+1474264
+ahart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+925
+

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/recipes/.svn/text-base/default.rb.svn-base
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/recipes/.svn/text-base/default.rb.svn-base b/src/main/vm/src/cookbooks/apache2/recipes/.svn/text-base/default.rb.svn-base
new file mode 100755
index 0000000..7aef323
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/recipes/.svn/text-base/default.rb.svn-base
@@ -0,0 +1,191 @@
+#
+# Cookbook Name:: apache2
+# Recipe:: default
+#
+# Copyright 2008-2009, Opscode, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+package "apache2" do
+  case node[:platform]
+  when "centos","redhat","fedora","suse"
+    package_name "httpd"
+  when "debian","ubuntu"
+    package_name "apache2"
+  end
+  action :install
+end
+
+service "apache2" do
+  case node[:platform]
+  when "centos","redhat","fedora","suse"
+    service_name "httpd"
+    # If restarted/reloaded too quickly httpd has a habit of failing.
+    # This may happen with multiple recipes notifying apache to restart - like
+    # during the initial bootstrap.
+    restart_command "/sbin/service httpd restart && sleep 1"
+    reload_command "/sbin/service httpd reload && sleep 1"
+  when "debian","ubuntu"
+    service_name "apache2"
+  end
+  supports value_for_platform(
+    "debian" => { "4.0" => [ :restart, :reload ], "default" => [ :restart, :reload, :status ] },
+    "ubuntu" => { "default" => [ :restart, :reload, :status ] },
+    "centos" => { "default" => [ :restart, :reload, :status ] },
+    "redhat" => { "default" => [ :restart, :reload, :status ] },
+    "fedora" => { "default" => [ :restart, :reload, :status ] },
+    "default" => { "default" => [:restart, :reload ] }
+  )
+  action :enable
+end
+
+if platform?("centos", "redhat", "fedora", "suse")
+  directory node[:apache][:log_dir] do
+    mode 0755
+    action :create
+  end
+  
+  cookbook_file "/usr/local/bin/apache2_module_conf_generate.pl" do
+    source "apache2_module_conf_generate.pl"
+    mode 0755
+    owner "root"
+    group "root"
+  end
+
+  %w{sites-available sites-enabled mods-available mods-enabled}.each do |dir|
+    directory "#{node[:apache][:dir]}/#{dir}" do
+      mode 0755
+      owner "root"
+      group "root"
+      action :create
+    end
+  end
+    
+  execute "generate-module-list" do
+    if node[:kernel][:machine] == "x86_64" 
+      libdir = "lib64"
+    else 
+      libdir = "lib"
+    end
+    command "/usr/local/bin/apache2_module_conf_generate.pl /usr/#{libdir}/httpd/modules /etc/httpd/mods-available"
+    
+    action :run
+  end
+  
+  %w{a2ensite a2dissite a2enmod a2dismod}.each do |modscript|
+    template "/usr/sbin/#{modscript}" do
+      source "#{modscript}.erb"
+      mode 0755
+      owner "root"
+      group "root"
+    end  
+  end
+
+  # installed by default on centos/rhel, remove in favour of mods-enabled
+  file "#{node[:apache][:dir]}/conf.d/proxy_ajp.conf" do
+    action :delete
+    backup false
+  end
+  file "#{node[:apache][:dir]}/conf.d/README" do
+    action :delete
+    backup false
+  end
+  
+  # welcome page moved to the default-site.rb temlate
+  file "#{node[:apache][:dir]}/conf.d/welcome.conf" do
+    action :delete
+    backup false
+  end
+end
+
+directory "#{node[:apache][:dir]}/ssl" do
+  action :create
+  mode 0755
+  owner "root"
+  group "root"
+end
+
+template "apache2.conf" do
+  case node[:platform]
+  when "centos","redhat","fedora"
+    path "#{node[:apache][:dir]}/conf/httpd.conf"
+  when "debian","ubuntu"
+    path "#{node[:apache][:dir]}/apache2.conf"
+  end
+  source "apache2.conf.erb"
+  owner "root"
+  group "root"
+  mode 0644
+  notifies :restart, resources(:service => "apache2")
+end
+
+template "security" do
+  path "#{node[:apache][:dir]}/conf.d/security"
+  source "security.erb"
+  owner "root"
+  group "root"
+  mode 0644
+  backup false
+  notifies :restart, resources(:service => "apache2")
+end
+
+template "charset" do
+  path "#{node[:apache][:dir]}/conf.d/charset"
+  source "charset.erb"
+  owner "root"
+  group "root"
+  mode 0644
+  backup false
+  notifies :restart, resources(:service => "apache2")
+end
+
+template "#{node[:apache][:dir]}/ports.conf" do
+  source "ports.conf.erb"
+  group "root"
+  owner "root"
+  variables :apache_listen_ports => node[:apache][:listen_ports]
+  mode 0644
+  notifies :restart, resources(:service => "apache2")
+end
+
+template "#{node[:apache][:dir]}/sites-available/default" do
+  source "default-site.erb"
+  owner "root"
+  group "root"
+  mode 0644
+  notifies :restart, resources(:service => "apache2")
+end
+
+include_recipe "apache2::mod_status"
+include_recipe "apache2::mod_alias"
+include_recipe "apache2::mod_auth_basic"
+include_recipe "apache2::mod_authn_file"
+include_recipe "apache2::mod_authz_default"
+include_recipe "apache2::mod_authz_groupfile"
+include_recipe "apache2::mod_authz_host"
+include_recipe "apache2::mod_authz_user"
+include_recipe "apache2::mod_autoindex"
+include_recipe "apache2::mod_dir"
+include_recipe "apache2::mod_env"
+include_recipe "apache2::mod_mime"
+include_recipe "apache2::mod_negotiation"
+include_recipe "apache2::mod_setenvif"
+include_recipe "apache2::mod_log_config" if platform?("centos", "redhat", "suse")
+
+# uncomment to get working example site on centos/redhat/fedora
+#apache_site "default"
+
+service "apache2" do
+  action :start
+end

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/recipes/.svn/text-base/god_monitor.rb.svn-base
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/recipes/.svn/text-base/god_monitor.rb.svn-base b/src/main/vm/src/cookbooks/apache2/recipes/.svn/text-base/god_monitor.rb.svn-base
new file mode 100755
index 0000000..b3c49eb
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/recipes/.svn/text-base/god_monitor.rb.svn-base
@@ -0,0 +1,33 @@
+#
+# Cookbook Name:: apache2
+# Recipe:: god_monitor
+#
+# Copyright 2008-2009, Opscode, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+apache_service = service "apache2" do
+  action :nothing
+end
+
+start_command = apache_service.start_command
+stop_command = apache_service.stop_command
+restart_command = apache_service.restart_command
+
+god_monitor "apache2" do
+  config "apache2.god.erb"
+  start (start_command)?start_command : "/etc/init.d/#{apache_service.service_name} start"
+  restart (restart_command)?restart_command : "/etc/init.d/#{apache_service.service_name} restart"
+  stop (stop_command)?stop_command : "/etc/init.d/#{apache_service.service_name} stop"
+end

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/recipes/.svn/text-base/mod_alias.rb.svn-base
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/recipes/.svn/text-base/mod_alias.rb.svn-base b/src/main/vm/src/cookbooks/apache2/recipes/.svn/text-base/mod_alias.rb.svn-base
new file mode 100755
index 0000000..a4618ed
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/recipes/.svn/text-base/mod_alias.rb.svn-base
@@ -0,0 +1,22 @@
+#
+# Cookbook Name:: apache2
+# Recipe:: alias 
+#
+# Copyright 2008-2009, Opscode, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+apache_module "alias" do
+  conf true
+end

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/recipes/.svn/text-base/mod_auth_basic.rb.svn-base
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/recipes/.svn/text-base/mod_auth_basic.rb.svn-base b/src/main/vm/src/cookbooks/apache2/recipes/.svn/text-base/mod_auth_basic.rb.svn-base
new file mode 100755
index 0000000..d30264f
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/recipes/.svn/text-base/mod_auth_basic.rb.svn-base
@@ -0,0 +1,20 @@
+#
+# Cookbook Name:: apache2
+# Recipe:: auth_basic 
+#
+# Copyright 2008-2009, Opscode, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+apache_module "auth_basic"

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/recipes/.svn/text-base/mod_auth_digest.rb.svn-base
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/recipes/.svn/text-base/mod_auth_digest.rb.svn-base b/src/main/vm/src/cookbooks/apache2/recipes/.svn/text-base/mod_auth_digest.rb.svn-base
new file mode 100755
index 0000000..5aef926
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/recipes/.svn/text-base/mod_auth_digest.rb.svn-base
@@ -0,0 +1,20 @@
+#
+# Cookbook Name:: apache2
+# Recipe:: auth_digest 
+#
+# Copyright 2008-2009, Opscode, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+apache_module "auth_digest"

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/recipes/.svn/text-base/mod_auth_openid.rb.svn-base
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/recipes/.svn/text-base/mod_auth_openid.rb.svn-base b/src/main/vm/src/cookbooks/apache2/recipes/.svn/text-base/mod_auth_openid.rb.svn-base
new file mode 100755
index 0000000..83cc220
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/recipes/.svn/text-base/mod_auth_openid.rb.svn-base
@@ -0,0 +1,59 @@
+#
+# Cookbook Name:: apache2
+# Recipe:: mod_auth_openid
+#
+# Copyright 2008-2009, Opscode, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+%w{ apache2-prefork-dev libopkele-dev libopkele3 }.each do |pkg|
+  package pkg
+end
+
+remote_file "/tmp/mod_auth_openid-0.4.tar.gz" do
+  source "http://butterfat.net/releases/mod_auth_openid/mod_auth_openid-0.4.tar.gz"
+  mode 0644
+end
+
+bash "install mod_auth_openid" do
+  cwd "/tmp"
+  code <<-EOH
+  tar zxvf mod_auth_openid-0.4.tar.gz
+  cd mod_auth_openid-0.4 && ./configure
+  perl -pi -e "s/-i -a -n 'authopenid'/-i -n 'authopenid'/g" Makefile
+  make && make install
+  EOH
+  not_if { File.exists?("/usr/lib/apache2/modules/mod_auth_openid.so") }
+end
+
+file "/var/cache/apache2/mod_auth_openid.db" do
+  owner node[:apache][:user]
+  mode 0600
+end
+
+template "#{node[:apache][:dir]}/mods-available/authopenid.load" do
+  source "mods/authopenid.load.erb"
+  owner "root"
+  group "root"
+  mode 0644
+end
+
+apache_module "authopenid"
+
+template "/usr/local/bin/mod_auth_openid.rb" do
+  source "mod_auth_openid.rb.erb"
+  owner node[:apache][:user]
+  group node[:apache][:user]
+  mode 0750
+end

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/recipes/.svn/text-base/mod_authn_file.rb.svn-base
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/recipes/.svn/text-base/mod_authn_file.rb.svn-base b/src/main/vm/src/cookbooks/apache2/recipes/.svn/text-base/mod_authn_file.rb.svn-base
new file mode 100755
index 0000000..872caa7
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/recipes/.svn/text-base/mod_authn_file.rb.svn-base
@@ -0,0 +1,20 @@
+#
+# Cookbook Name:: apache2
+# Recipe:: authn_file 
+#
+# Copyright 2008-2009, Opscode, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+apache_module "authn_file"

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/recipes/.svn/text-base/mod_authnz_ldap.rb.svn-base
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/recipes/.svn/text-base/mod_authnz_ldap.rb.svn-base b/src/main/vm/src/cookbooks/apache2/recipes/.svn/text-base/mod_authnz_ldap.rb.svn-base
new file mode 100755
index 0000000..0310d24
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/recipes/.svn/text-base/mod_authnz_ldap.rb.svn-base
@@ -0,0 +1,20 @@
+#
+# Cookbook Name:: apache2
+# Recipe:: authnz_ldap 
+#
+# Copyright 2008-2009, Opscode, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+apache_module "authnz_ldap"

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/recipes/.svn/text-base/mod_authz_default.rb.svn-base
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/recipes/.svn/text-base/mod_authz_default.rb.svn-base b/src/main/vm/src/cookbooks/apache2/recipes/.svn/text-base/mod_authz_default.rb.svn-base
new file mode 100755
index 0000000..123536d
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/recipes/.svn/text-base/mod_authz_default.rb.svn-base
@@ -0,0 +1,20 @@
+#
+# Cookbook Name:: apache2
+# Recipe:: authz_default 
+#
+# Copyright 2008-2009, Opscode, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+apache_module "authz_default"

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/recipes/.svn/text-base/mod_authz_groupfile.rb.svn-base
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/recipes/.svn/text-base/mod_authz_groupfile.rb.svn-base b/src/main/vm/src/cookbooks/apache2/recipes/.svn/text-base/mod_authz_groupfile.rb.svn-base
new file mode 100755
index 0000000..b2833b2
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/recipes/.svn/text-base/mod_authz_groupfile.rb.svn-base
@@ -0,0 +1,20 @@
+#
+# Cookbook Name:: apache2
+# Recipe:: authz_groupfile 
+#
+# Copyright 2008-2009, Opscode, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+apache_module "authz_groupfile"

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/recipes/.svn/text-base/mod_authz_host.rb.svn-base
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/recipes/.svn/text-base/mod_authz_host.rb.svn-base b/src/main/vm/src/cookbooks/apache2/recipes/.svn/text-base/mod_authz_host.rb.svn-base
new file mode 100755
index 0000000..87c1a4b
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/recipes/.svn/text-base/mod_authz_host.rb.svn-base
@@ -0,0 +1,20 @@
+#
+# Cookbook Name:: apache2
+# Recipe:: authz_host 
+#
+# Copyright 2008-2009, Opscode, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+apache_module "authz_host"

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/recipes/.svn/text-base/mod_authz_user.rb.svn-base
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/recipes/.svn/text-base/mod_authz_user.rb.svn-base b/src/main/vm/src/cookbooks/apache2/recipes/.svn/text-base/mod_authz_user.rb.svn-base
new file mode 100755
index 0000000..8dd46df
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/recipes/.svn/text-base/mod_authz_user.rb.svn-base
@@ -0,0 +1,20 @@
+#
+# Cookbook Name:: apache2
+# Recipe:: authz_user 
+#
+# Copyright 2008-2009, Opscode, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+apache_module "authz_user"

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/recipes/.svn/text-base/mod_autoindex.rb.svn-base
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/recipes/.svn/text-base/mod_autoindex.rb.svn-base b/src/main/vm/src/cookbooks/apache2/recipes/.svn/text-base/mod_autoindex.rb.svn-base
new file mode 100755
index 0000000..622a66e
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/recipes/.svn/text-base/mod_autoindex.rb.svn-base
@@ -0,0 +1,22 @@
+#
+# Cookbook Name:: apache2
+# Recipe:: autoindex 
+#
+# Copyright 2008-2009, Opscode, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+apache_module "autoindex" do
+  conf true
+end

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/recipes/.svn/text-base/mod_cgi.rb.svn-base
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/recipes/.svn/text-base/mod_cgi.rb.svn-base b/src/main/vm/src/cookbooks/apache2/recipes/.svn/text-base/mod_cgi.rb.svn-base
new file mode 100755
index 0000000..6c15a05
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/recipes/.svn/text-base/mod_cgi.rb.svn-base
@@ -0,0 +1,20 @@
+#
+# Cookbook Name:: apache2
+# Recipe:: cgi 
+#
+# Copyright 2008-2009, Opscode, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+apache_module "cgi"

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/recipes/.svn/text-base/mod_dav.rb.svn-base
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/recipes/.svn/text-base/mod_dav.rb.svn-base b/src/main/vm/src/cookbooks/apache2/recipes/.svn/text-base/mod_dav.rb.svn-base
new file mode 100755
index 0000000..fef656a
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/recipes/.svn/text-base/mod_dav.rb.svn-base
@@ -0,0 +1,20 @@
+#
+# Cookbook Name:: apache2
+# Recipe:: dav 
+#
+# Copyright 2008-2009, Opscode, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+apache_module "dav"

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/recipes/.svn/text-base/mod_dav_svn.rb.svn-base
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/recipes/.svn/text-base/mod_dav_svn.rb.svn-base b/src/main/vm/src/cookbooks/apache2/recipes/.svn/text-base/mod_dav_svn.rb.svn-base
new file mode 100755
index 0000000..ce50d54
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/recipes/.svn/text-base/mod_dav_svn.rb.svn-base
@@ -0,0 +1,22 @@
+#
+# Cookbook Name:: apache2
+# Recipe:: dav_svn 
+#
+# Copyright 2008-2009, Opscode, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+package "libapache2-svn"
+
+apache_module "dav_svn"

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/recipes/.svn/text-base/mod_deflate.rb.svn-base
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/recipes/.svn/text-base/mod_deflate.rb.svn-base b/src/main/vm/src/cookbooks/apache2/recipes/.svn/text-base/mod_deflate.rb.svn-base
new file mode 100755
index 0000000..b568f30
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/recipes/.svn/text-base/mod_deflate.rb.svn-base
@@ -0,0 +1,22 @@
+#
+# Cookbook Name:: apache2
+# Recipe:: deflate 
+#
+# Copyright 2008-2009, Opscode, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+apache_module "deflate" do
+  conf true
+end

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/recipes/.svn/text-base/mod_dir.rb.svn-base
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/recipes/.svn/text-base/mod_dir.rb.svn-base b/src/main/vm/src/cookbooks/apache2/recipes/.svn/text-base/mod_dir.rb.svn-base
new file mode 100755
index 0000000..9930c3a
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/recipes/.svn/text-base/mod_dir.rb.svn-base
@@ -0,0 +1,22 @@
+#
+# Cookbook Name:: apache2
+# Recipe:: dir 
+#
+# Copyright 2008-2009, Opscode, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+apache_module "dir" do 
+  conf true
+end

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/recipes/.svn/text-base/mod_env.rb.svn-base
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/recipes/.svn/text-base/mod_env.rb.svn-base b/src/main/vm/src/cookbooks/apache2/recipes/.svn/text-base/mod_env.rb.svn-base
new file mode 100755
index 0000000..d345503
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/recipes/.svn/text-base/mod_env.rb.svn-base
@@ -0,0 +1,20 @@
+#
+# Cookbook Name:: apache2
+# Recipe:: env 
+#
+# Copyright 2008-2009, Opscode, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+apache_module "env"

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/recipes/.svn/text-base/mod_expires.rb.svn-base
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/recipes/.svn/text-base/mod_expires.rb.svn-base b/src/main/vm/src/cookbooks/apache2/recipes/.svn/text-base/mod_expires.rb.svn-base
new file mode 100755
index 0000000..9e5042e
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/recipes/.svn/text-base/mod_expires.rb.svn-base
@@ -0,0 +1,20 @@
+#
+# Cookbook Name:: apache2
+# Recipe:: expires 
+#
+# Copyright 2008-2009, Opscode, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+apache_module "expires"

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/recipes/.svn/text-base/mod_fcgid.rb.svn-base
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/recipes/.svn/text-base/mod_fcgid.rb.svn-base b/src/main/vm/src/cookbooks/apache2/recipes/.svn/text-base/mod_fcgid.rb.svn-base
new file mode 100755
index 0000000..ea7ec3e
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/recipes/.svn/text-base/mod_fcgid.rb.svn-base
@@ -0,0 +1,46 @@
+#
+# Cookbook Name:: apache2
+# Recipe:: fcgid 
+#
+# Copyright 2008-2009, Opscode, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+if platform?("debian", "ubuntu")
+  package "libapache2-mod-fcgid"
+elsif platform?("centos", "redhat", "fedora")
+  package "mod_fcgid" do
+    notifies :run, resources(:execute => "generate-module-list"), :immediately
+  end
+
+  file "#{node[:apache][:dir]}/conf.d/fcgid.conf" do
+    action :delete
+    backup false 
+  end
+elsif platform?("suse")
+  apache_lib_path = node[:architecture] == "i386" ? "/usr/lib/httpd" : "/usr/lib64/httpd"
+  package "httpd-devel"
+  bash "install-fcgid" do
+    code <<-EOH
+(cd /tmp; wget http://superb-east.dl.sourceforge.net/sourceforge/mod-fcgid/mod_fcgid.2.2.tgz)
+(cd /tmp; tar zxvf mod_fcgid.2.2.tgz)
+(cd /tmp; perl -pi -e 's!/usr/local/apache2!#{apache_lib_path}!g' ./mod_fcgid.2.2/Makefile)
+(cd /tmp/mod_fcgid.2.2; make install)
+EOH
+  end
+end
+
+apache_module "fcgid" do
+  conf true
+end

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/recipes/.svn/text-base/mod_headers.rb.svn-base
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/recipes/.svn/text-base/mod_headers.rb.svn-base b/src/main/vm/src/cookbooks/apache2/recipes/.svn/text-base/mod_headers.rb.svn-base
new file mode 100755
index 0000000..5e6b94d
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/recipes/.svn/text-base/mod_headers.rb.svn-base
@@ -0,0 +1,20 @@
+#
+# Cookbook Name:: apache2
+# Recipe:: headers 
+#
+# Copyright 2008-2009, Opscode, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+apache_module "headers"

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/recipes/.svn/text-base/mod_ldap.rb.svn-base
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/recipes/.svn/text-base/mod_ldap.rb.svn-base b/src/main/vm/src/cookbooks/apache2/recipes/.svn/text-base/mod_ldap.rb.svn-base
new file mode 100755
index 0000000..0877694
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/recipes/.svn/text-base/mod_ldap.rb.svn-base
@@ -0,0 +1,20 @@
+#
+# Cookbook Name:: apache2
+# Recipe:: ldap 
+#
+# Copyright 2008-2009, Opscode, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+apache_module "ldap"


[27/51] [abbrv] [partial] Adding Jinwon's custom RCMET

Posted by jo...@apache.org.
http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/app/js/.svn/text-base/bootstrap.min.js.svn-base
----------------------------------------------------------------------
diff --git a/src/main/ui/app/js/.svn/text-base/bootstrap.min.js.svn-base b/src/main/ui/app/js/.svn/text-base/bootstrap.min.js.svn-base
new file mode 100755
index 0000000..95c5ac5
--- /dev/null
+++ b/src/main/ui/app/js/.svn/text-base/bootstrap.min.js.svn-base
@@ -0,0 +1,6 @@
+/*!
+* Bootstrap.js by @fat & @mdo
+* Copyright 2012 Twitter, Inc.
+* http://www.apache.org/licenses/LICENSE-2.0.txt
+*/
+!function(e){"use strict";e(function(){e.support.transition=function(){var e=function(){var e=document.createElement("bootstrap"),t={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd otransitionend",transition:"transitionend"},n;for(n in t)if(e.style[n]!==undefined)return t[n]}();return e&&{end:e}}()})}(window.jQuery),!function(e){"use strict";var t='[data-dismiss="alert"]',n=function(n){e(n).on("click",t,this.close)};n.prototype.close=function(t){function s(){i.trigger("closed").remove()}var n=e(this),r=n.attr("data-target"),i;r||(r=n.attr("href"),r=r&&r.replace(/.*(?=#[^\s]*$)/,"")),i=e(r),t&&t.preventDefault(),i.length||(i=n.hasClass("alert")?n:n.parent()),i.trigger(t=e.Event("close"));if(t.isDefaultPrevented())return;i.removeClass("in"),e.support.transition&&i.hasClass("fade")?i.on(e.support.transition.end,s):s()};var r=e.fn.alert;e.fn.alert=function(t){return this.each(function(){var r=e(this),i=r.data("alert");i||r.data("alert",i=
 new n(this)),typeof t=="string"&&i[t].call(r)})},e.fn.alert.Constructor=n,e.fn.alert.noConflict=function(){return e.fn.alert=r,this},e(document).on("click.alert.data-api",t,n.prototype.close)}(window.jQuery),!function(e){"use strict";var t=function(t,n){this.$element=e(t),this.options=e.extend({},e.fn.button.defaults,n)};t.prototype.setState=function(e){var t="disabled",n=this.$element,r=n.data(),i=n.is("input")?"val":"html";e+="Text",r.resetText||n.data("resetText",n[i]()),n[i](r[e]||this.options[e]),setTimeout(function(){e=="loadingText"?n.addClass(t).attr(t,t):n.removeClass(t).removeAttr(t)},0)},t.prototype.toggle=function(){var e=this.$element.closest('[data-toggle="buttons-radio"]');e&&e.find(".active").removeClass("active"),this.$element.toggleClass("active")};var n=e.fn.button;e.fn.button=function(n){return this.each(function(){var r=e(this),i=r.data("button"),s=typeof n=="object"&&n;i||r.data("button",i=new t(this,s)),n=="toggle"?i.toggle():n&&i.setState(n)})},e.fn.button.de
 faults={loadingText:"loading..."},e.fn.button.Constructor=t,e.fn.button.noConflict=function(){return e.fn.button=n,this},e(document).on("click.button.data-api","[data-toggle^=button]",function(t){var n=e(t.target);n.hasClass("btn")||(n=n.closest(".btn")),n.button("toggle")})}(window.jQuery),!function(e){"use strict";var t=function(t,n){this.$element=e(t),this.$indicators=this.$element.find(".carousel-indicators"),this.options=n,this.options.pause=="hover"&&this.$element.on("mouseenter",e.proxy(this.pause,this)).on("mouseleave",e.proxy(this.cycle,this))};t.prototype={cycle:function(t){return t||(this.paused=!1),this.interval&&clearInterval(this.interval),this.options.interval&&!this.paused&&(this.interval=setInterval(e.proxy(this.next,this),this.options.interval)),this},getActiveIndex:function(){return this.$active=this.$element.find(".item.active"),this.$items=this.$active.parent().children(),this.$items.index(this.$active)},to:function(t){var n=this.getActiveIndex(),r=this;if(t>thi
 s.$items.length-1||t<0)return;return this.sliding?this.$element.one("slid",function(){r.to(t)}):n==t?this.pause().cycle():this.slide(t>n?"next":"prev",e(this.$items[t]))},pause:function(t){return t||(this.paused=!0),this.$element.find(".next, .prev").length&&e.support.transition.end&&(this.$element.trigger(e.support.transition.end),this.cycle(!0)),clearInterval(this.interval),this.interval=null,this},next:function(){if(this.sliding)return;return this.slide("next")},prev:function(){if(this.sliding)return;return this.slide("prev")},slide:function(t,n){var r=this.$element.find(".item.active"),i=n||r[t](),s=this.interval,o=t=="next"?"left":"right",u=t=="next"?"first":"last",a=this,f;this.sliding=!0,s&&this.pause(),i=i.length?i:this.$element.find(".item")[u](),f=e.Event("slide",{relatedTarget:i[0],direction:o});if(i.hasClass("active"))return;this.$indicators.length&&(this.$indicators.find(".active").removeClass("active"),this.$element.one("slid",function(){var t=e(a.$indicators.children(
 )[a.getActiveIndex()]);t&&t.addClass("active")}));if(e.support.transition&&this.$element.hasClass("slide")){this.$element.trigger(f);if(f.isDefaultPrevented())return;i.addClass(t),i[0].offsetWidth,r.addClass(o),i.addClass(o),this.$element.one(e.support.transition.end,function(){i.removeClass([t,o].join(" ")).addClass("active"),r.removeClass(["active",o].join(" ")),a.sliding=!1,setTimeout(function(){a.$element.trigger("slid")},0)})}else{this.$element.trigger(f);if(f.isDefaultPrevented())return;r.removeClass("active"),i.addClass("active"),this.sliding=!1,this.$element.trigger("slid")}return s&&this.cycle(),this}};var n=e.fn.carousel;e.fn.carousel=function(n){return this.each(function(){var r=e(this),i=r.data("carousel"),s=e.extend({},e.fn.carousel.defaults,typeof n=="object"&&n),o=typeof n=="string"?n:s.slide;i||r.data("carousel",i=new t(this,s)),typeof n=="number"?i.to(n):o?i[o]():s.interval&&i.pause().cycle()})},e.fn.carousel.defaults={interval:5e3,pause:"hover"},e.fn.carousel.Const
 ructor=t,e.fn.carousel.noConflict=function(){return e.fn.carousel=n,this},e(document).on("click.carousel.data-api","[data-slide], [data-slide-to]",function(t){var n=e(this),r,i=e(n.attr("data-target")||(r=n.attr("href"))&&r.replace(/.*(?=#[^\s]+$)/,"")),s=e.extend({},i.data(),n.data()),o;i.carousel(s),(o=n.attr("data-slide-to"))&&i.data("carousel").pause().to(o).cycle(),t.preventDefault()})}(window.jQuery),!function(e){"use strict";var t=function(t,n){this.$element=e(t),this.options=e.extend({},e.fn.collapse.defaults,n),this.options.parent&&(this.$parent=e(this.options.parent)),this.options.toggle&&this.toggle()};t.prototype={constructor:t,dimension:function(){var e=this.$element.hasClass("width");return e?"width":"height"},show:function(){var t,n,r,i;if(this.transitioning||this.$element.hasClass("in"))return;t=this.dimension(),n=e.camelCase(["scroll",t].join("-")),r=this.$parent&&this.$parent.find("> .accordion-group > .in");if(r&&r.length){i=r.data("collapse");if(i&&i.transitionin
 g)return;r.collapse("hide"),i||r.data("collapse",null)}this.$element[t](0),this.transition("addClass",e.Event("show"),"shown"),e.support.transition&&this.$element[t](this.$element[0][n])},hide:function(){var t;if(this.transitioning||!this.$element.hasClass("in"))return;t=this.dimension(),this.reset(this.$element[t]()),this.transition("removeClass",e.Event("hide"),"hidden"),this.$element[t](0)},reset:function(e){var t=this.dimension();return this.$element.removeClass("collapse")[t](e||"auto")[0].offsetWidth,this.$element[e!==null?"addClass":"removeClass"]("collapse"),this},transition:function(t,n,r){var i=this,s=function(){n.type=="show"&&i.reset(),i.transitioning=0,i.$element.trigger(r)};this.$element.trigger(n);if(n.isDefaultPrevented())return;this.transitioning=1,this.$element[t]("in"),e.support.transition&&this.$element.hasClass("collapse")?this.$element.one(e.support.transition.end,s):s()},toggle:function(){this[this.$element.hasClass("in")?"hide":"show"]()}};var n=e.fn.collapse
 ;e.fn.collapse=function(n){return this.each(function(){var r=e(this),i=r.data("collapse"),s=e.extend({},e.fn.collapse.defaults,r.data(),typeof n=="object"&&n);i||r.data("collapse",i=new t(this,s)),typeof n=="string"&&i[n]()})},e.fn.collapse.defaults={toggle:!0},e.fn.collapse.Constructor=t,e.fn.collapse.noConflict=function(){return e.fn.collapse=n,this},e(document).on("click.collapse.data-api","[data-toggle=collapse]",function(t){var n=e(this),r,i=n.attr("data-target")||t.preventDefault()||(r=n.attr("href"))&&r.replace(/.*(?=#[^\s]+$)/,""),s=e(i).data("collapse")?"toggle":n.data();n[e(i).hasClass("in")?"addClass":"removeClass"]("collapsed"),e(i).collapse(s)})}(window.jQuery),!function(e){"use strict";function r(){e(t).each(function(){i(e(this)).removeClass("open")})}function i(t){var n=t.attr("data-target"),r;n||(n=t.attr("href"),n=n&&/#/.test(n)&&n.replace(/.*(?=#[^\s]*$)/,"")),r=n&&e(n);if(!r||!r.length)r=t.parent();return r}var t="[data-toggle=dropdown]",n=function(t){var n=e(t).o
 n("click.dropdown.data-api",this.toggle);e("html").on("click.dropdown.data-api",function(){n.parent().removeClass("open")})};n.prototype={constructor:n,toggle:function(t){var n=e(this),s,o;if(n.is(".disabled, :disabled"))return;return s=i(n),o=s.hasClass("open"),r(),o||s.toggleClass("open"),n.focus(),!1},keydown:function(n){var r,s,o,u,a,f;if(!/(38|40|27)/.test(n.keyCode))return;r=e(this),n.preventDefault(),n.stopPropagation();if(r.is(".disabled, :disabled"))return;u=i(r),a=u.hasClass("open");if(!a||a&&n.keyCode==27)return n.which==27&&u.find(t).focus(),r.click();s=e("[role=menu] li:not(.divider):visible a",u);if(!s.length)return;f=s.index(s.filter(":focus")),n.keyCode==38&&f>0&&f--,n.keyCode==40&&f<s.length-1&&f++,~f||(f=0),s.eq(f).focus()}};var s=e.fn.dropdown;e.fn.dropdown=function(t){return this.each(function(){var r=e(this),i=r.data("dropdown");i||r.data("dropdown",i=new n(this)),typeof t=="string"&&i[t].call(r)})},e.fn.dropdown.Constructor=n,e.fn.dropdown.noConflict=function()
 {return e.fn.dropdown=s,this},e(document).on("click.dropdown.data-api",r).on("click.dropdown.data-api",".dropdown form",function(e){e.stopPropagation()}).on("click.dropdown-menu",function(e){e.stopPropagation()}).on("click.dropdown.data-api",t,n.prototype.toggle).on("keydown.dropdown.data-api",t+", [role=menu]",n.prototype.keydown)}(window.jQuery),!function(e){"use strict";var t=function(t,n){this.options=n,this.$element=e(t).delegate('[data-dismiss="modal"]',"click.dismiss.modal",e.proxy(this.hide,this)),this.options.remote&&this.$element.find(".modal-body").load(this.options.remote)};t.prototype={constructor:t,toggle:function(){return this[this.isShown?"hide":"show"]()},show:function(){var t=this,n=e.Event("show");this.$element.trigger(n);if(this.isShown||n.isDefaultPrevented())return;this.isShown=!0,this.escape(),this.backdrop(function(){var n=e.support.transition&&t.$element.hasClass("fade");t.$element.parent().length||t.$element.appendTo(document.body),t.$element.show(),n&&t.$e
 lement[0].offsetWidth,t.$element.addClass("in").attr("aria-hidden",!1),t.enforceFocus(),n?t.$element.one(e.support.transition.end,function(){t.$element.focus().trigger("shown")}):t.$element.focus().trigger("shown")})},hide:function(t){t&&t.preventDefault();var n=this;t=e.Event("hide"),this.$element.trigger(t);if(!this.isShown||t.isDefaultPrevented())return;this.isShown=!1,this.escape(),e(document).off("focusin.modal"),this.$element.removeClass("in").attr("aria-hidden",!0),e.support.transition&&this.$element.hasClass("fade")?this.hideWithTransition():this.hideModal()},enforceFocus:function(){var t=this;e(document).on("focusin.modal",function(e){t.$element[0]!==e.target&&!t.$element.has(e.target).length&&t.$element.focus()})},escape:function(){var e=this;this.isShown&&this.options.keyboard?this.$element.on("keyup.dismiss.modal",function(t){t.which==27&&e.hide()}):this.isShown||this.$element.off("keyup.dismiss.modal")},hideWithTransition:function(){var t=this,n=setTimeout(function(){t.
 $element.off(e.support.transition.end),t.hideModal()},500);this.$element.one(e.support.transition.end,function(){clearTimeout(n),t.hideModal()})},hideModal:function(){var e=this;this.$element.hide(),this.backdrop(function(){e.removeBackdrop(),e.$element.trigger("hidden")})},removeBackdrop:function(){this.$backdrop&&this.$backdrop.remove(),this.$backdrop=null},backdrop:function(t){var n=this,r=this.$element.hasClass("fade")?"fade":"";if(this.isShown&&this.options.backdrop){var i=e.support.transition&&r;this.$backdrop=e('<div class="modal-backdrop '+r+'" />').appendTo(document.body),this.$backdrop.click(this.options.backdrop=="static"?e.proxy(this.$element[0].focus,this.$element[0]):e.proxy(this.hide,this)),i&&this.$backdrop[0].offsetWidth,this.$backdrop.addClass("in");if(!t)return;i?this.$backdrop.one(e.support.transition.end,t):t()}else!this.isShown&&this.$backdrop?(this.$backdrop.removeClass("in"),e.support.transition&&this.$element.hasClass("fade")?this.$backdrop.one(e.support.tra
 nsition.end,t):t()):t&&t()}};var n=e.fn.modal;e.fn.modal=function(n){return this.each(function(){var r=e(this),i=r.data("modal"),s=e.extend({},e.fn.modal.defaults,r.data(),typeof n=="object"&&n);i||r.data("modal",i=new t(this,s)),typeof n=="string"?i[n]():s.show&&i.show()})},e.fn.modal.defaults={backdrop:!0,keyboard:!0,show:!0},e.fn.modal.Constructor=t,e.fn.modal.noConflict=function(){return e.fn.modal=n,this},e(document).on("click.modal.data-api",'[data-toggle="modal"]',function(t){var n=e(this),r=n.attr("href"),i=e(n.attr("data-target")||r&&r.replace(/.*(?=#[^\s]+$)/,"")),s=i.data("modal")?"toggle":e.extend({remote:!/#/.test(r)&&r},i.data(),n.data());t.preventDefault(),i.modal(s).one("hide",function(){n.focus()})})}(window.jQuery),!function(e){"use strict";var t=function(e,t){this.init("tooltip",e,t)};t.prototype={constructor:t,init:function(t,n,r){var i,s,o,u,a;this.type=t,this.$element=e(n),this.options=this.getOptions(r),this.enabled=!0,o=this.options.trigger.split(" ");for(a=o
 .length;a--;)u=o[a],u=="click"?this.$element.on("click."+this.type,this.options.selector,e.proxy(this.toggle,this)):u!="manual"&&(i=u=="hover"?"mouseenter":"focus",s=u=="hover"?"mouseleave":"blur",this.$element.on(i+"."+this.type,this.options.selector,e.proxy(this.enter,this)),this.$element.on(s+"."+this.type,this.options.selector,e.proxy(this.leave,this)));this.options.selector?this._options=e.extend({},this.options,{trigger:"manual",selector:""}):this.fixTitle()},getOptions:function(t){return t=e.extend({},e.fn[this.type].defaults,this.$element.data(),t),t.delay&&typeof t.delay=="number"&&(t.delay={show:t.delay,hide:t.delay}),t},enter:function(t){var n=e.fn[this.type].defaults,r={},i;this._options&&e.each(this._options,function(e,t){n[e]!=t&&(r[e]=t)},this),i=e(t.currentTarget)[this.type](r).data(this.type);if(!i.options.delay||!i.options.delay.show)return i.show();clearTimeout(this.timeout),i.hoverState="in",this.timeout=setTimeout(function(){i.hoverState=="in"&&i.show()},i.optio
 ns.delay.show)},leave:function(t){var n=e(t.currentTarget)[this.type](this._options).data(this.type);this.timeout&&clearTimeout(this.timeout);if(!n.options.delay||!n.options.delay.hide)return n.hide();n.hoverState="out",this.timeout=setTimeout(function(){n.hoverState=="out"&&n.hide()},n.options.delay.hide)},show:function(){var t,n,r,i,s,o,u=e.Event("show");if(this.hasContent()&&this.enabled){this.$element.trigger(u);if(u.isDefaultPrevented())return;t=this.tip(),this.setContent(),this.options.animation&&t.addClass("fade"),s=typeof this.options.placement=="function"?this.options.placement.call(this,t[0],this.$element[0]):this.options.placement,t.detach().css({top:0,left:0,display:"block"}),this.options.container?t.appendTo(this.options.container):t.insertAfter(this.$element),n=this.getPosition(),r=t[0].offsetWidth,i=t[0].offsetHeight;switch(s){case"bottom":o={top:n.top+n.height,left:n.left+n.width/2-r/2};break;case"top":o={top:n.top-i,left:n.left+n.width/2-r/2};break;case"left":o={top
 :n.top+n.height/2-i/2,left:n.left-r};break;case"right":o={top:n.top+n.height/2-i/2,left:n.left+n.width}}this.applyPlacement(o,s),this.$element.trigger("shown")}},applyPlacement:function(e,t){var n=this.tip(),r=n[0].offsetWidth,i=n[0].offsetHeight,s,o,u,a;n.offset(e).addClass(t).addClass("in"),s=n[0].offsetWidth,o=n[0].offsetHeight,t=="top"&&o!=i&&(e.top=e.top+i-o,a=!0),t=="bottom"||t=="top"?(u=0,e.left<0&&(u=e.left*-2,e.left=0,n.offset(e),s=n[0].offsetWidth,o=n[0].offsetHeight),this.replaceArrow(u-r+s,s,"left")):this.replaceArrow(o-i,o,"top"),a&&n.offset(e)},replaceArrow:function(e,t,n){this.arrow().css(n,e?50*(1-e/t)+"%":"")},setContent:function(){var e=this.tip(),t=this.getTitle();e.find(".tooltip-inner")[this.options.html?"html":"text"](t),e.removeClass("fade in top bottom left right")},hide:function(){function i(){var t=setTimeout(function(){n.off(e.support.transition.end).detach()},500);n.one(e.support.transition.end,function(){clearTimeout(t),n.detach()})}var t=this,n=this.tip
 (),r=e.Event("hide");this.$element.trigger(r);if(r.isDefaultPrevented())return;return n.removeClass("in"),e.support.transition&&this.$tip.hasClass("fade")?i():n.detach(),this.$element.trigger("hidden"),this},fixTitle:function(){var e=this.$element;(e.attr("title")||typeof e.attr("data-original-title")!="string")&&e.attr("data-original-title",e.attr("title")||"").attr("title","")},hasContent:function(){return this.getTitle()},getPosition:function(){var t=this.$element[0];return e.extend({},typeof t.getBoundingClientRect=="function"?t.getBoundingClientRect():{width:t.offsetWidth,height:t.offsetHeight},this.$element.offset())},getTitle:function(){var e,t=this.$element,n=this.options;return e=t.attr("data-original-title")||(typeof n.title=="function"?n.title.call(t[0]):n.title),e},tip:function(){return this.$tip=this.$tip||e(this.options.template)},arrow:function(){return this.$arrow=this.$arrow||this.tip().find(".tooltip-arrow")},validate:function(){this.$element[0].parentNode||(this.h
 ide(),this.$element=null,this.options=null)},enable:function(){this.enabled=!0},disable:function(){this.enabled=!1},toggleEnabled:function(){this.enabled=!this.enabled},toggle:function(t){var n=t?e(t.currentTarget)[this.type](this._options).data(this.type):this;n.tip().hasClass("in")?n.hide():n.show()},destroy:function(){this.hide().$element.off("."+this.type).removeData(this.type)}};var n=e.fn.tooltip;e.fn.tooltip=function(n){return this.each(function(){var r=e(this),i=r.data("tooltip"),s=typeof n=="object"&&n;i||r.data("tooltip",i=new t(this,s)),typeof n=="string"&&i[n]()})},e.fn.tooltip.Constructor=t,e.fn.tooltip.defaults={animation:!0,placement:"top",selector:!1,template:'<div class="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>',trigger:"hover focus",title:"",delay:0,html:!1,container:!1},e.fn.tooltip.noConflict=function(){return e.fn.tooltip=n,this}}(window.jQuery),!function(e){"use strict";var t=function(e,t){this.init("popover",e,t)};t.pro
 totype=e.extend({},e.fn.tooltip.Constructor.prototype,{constructor:t,setContent:function(){var e=this.tip(),t=this.getTitle(),n=this.getContent();e.find(".popover-title")[this.options.html?"html":"text"](t),e.find(".popover-content")[this.options.html?"html":"text"](n),e.removeClass("fade top bottom left right in")},hasContent:function(){return this.getTitle()||this.getContent()},getContent:function(){var e,t=this.$element,n=this.options;return e=(typeof n.content=="function"?n.content.call(t[0]):n.content)||t.attr("data-content"),e},tip:function(){return this.$tip||(this.$tip=e(this.options.template)),this.$tip},destroy:function(){this.hide().$element.off("."+this.type).removeData(this.type)}});var n=e.fn.popover;e.fn.popover=function(n){return this.each(function(){var r=e(this),i=r.data("popover"),s=typeof n=="object"&&n;i||r.data("popover",i=new t(this,s)),typeof n=="string"&&i[n]()})},e.fn.popover.Constructor=t,e.fn.popover.defaults=e.extend({},e.fn.tooltip.defaults,{placement:"
 right",trigger:"click",content:"",template:'<div class="popover"><div class="arrow"></div><h3 class="popover-title"></h3><div class="popover-content"></div></div>'}),e.fn.popover.noConflict=function(){return e.fn.popover=n,this}}(window.jQuery),!function(e){"use strict";function t(t,n){var r=e.proxy(this.process,this),i=e(t).is("body")?e(window):e(t),s;this.options=e.extend({},e.fn.scrollspy.defaults,n),this.$scrollElement=i.on("scroll.scroll-spy.data-api",r),this.selector=(this.options.target||(s=e(t).attr("href"))&&s.replace(/.*(?=#[^\s]+$)/,"")||"")+" .nav li > a",this.$body=e("body"),this.refresh(),this.process()}t.prototype={constructor:t,refresh:function(){var t=this,n;this.offsets=e([]),this.targets=e([]),n=this.$body.find(this.selector).map(function(){var n=e(this),r=n.data("target")||n.attr("href"),i=/^#\w/.test(r)&&e(r);return i&&i.length&&[[i.position().top+(!e.isWindow(t.$scrollElement.get(0))&&t.$scrollElement.scrollTop()),r]]||null}).sort(function(e,t){return e[0]-t[0]
 }).each(function(){t.offsets.push(this[0]),t.targets.push(this[1])})},process:function(){var e=this.$scrollElement.scrollTop()+this.options.offset,t=this.$scrollElement[0].scrollHeight||this.$body[0].scrollHeight,n=t-this.$scrollElement.height(),r=this.offsets,i=this.targets,s=this.activeTarget,o;if(e>=n)return s!=(o=i.last()[0])&&this.activate(o);for(o=r.length;o--;)s!=i[o]&&e>=r[o]&&(!r[o+1]||e<=r[o+1])&&this.activate(i[o])},activate:function(t){var n,r;this.activeTarget=t,e(this.selector).parent(".active").removeClass("active"),r=this.selector+'[data-target="'+t+'"],'+this.selector+'[href="'+t+'"]',n=e(r).parent("li").addClass("active"),n.parent(".dropdown-menu").length&&(n=n.closest("li.dropdown").addClass("active")),n.trigger("activate")}};var n=e.fn.scrollspy;e.fn.scrollspy=function(n){return this.each(function(){var r=e(this),i=r.data("scrollspy"),s=typeof n=="object"&&n;i||r.data("scrollspy",i=new t(this,s)),typeof n=="string"&&i[n]()})},e.fn.scrollspy.Constructor=t,e.fn.scr
 ollspy.defaults={offset:10},e.fn.scrollspy.noConflict=function(){return e.fn.scrollspy=n,this},e(window).on("load",function(){e('[data-spy="scroll"]').each(function(){var t=e(this);t.scrollspy(t.data())})})}(window.jQuery),!function(e){"use strict";var t=function(t){this.element=e(t)};t.prototype={constructor:t,show:function(){var t=this.element,n=t.closest("ul:not(.dropdown-menu)"),r=t.attr("data-target"),i,s,o;r||(r=t.attr("href"),r=r&&r.replace(/.*(?=#[^\s]*$)/,""));if(t.parent("li").hasClass("active"))return;i=n.find(".active:last a")[0],o=e.Event("show",{relatedTarget:i}),t.trigger(o);if(o.isDefaultPrevented())return;s=e(r),this.activate(t.parent("li"),n),this.activate(s,s.parent(),function(){t.trigger({type:"shown",relatedTarget:i})})},activate:function(t,n,r){function o(){i.removeClass("active").find("> .dropdown-menu > .active").removeClass("active"),t.addClass("active"),s?(t[0].offsetWidth,t.addClass("in")):t.removeClass("fade"),t.parent(".dropdown-menu")&&t.closest("li.dro
 pdown").addClass("active"),r&&r()}var i=n.find("> .active"),s=r&&e.support.transition&&i.hasClass("fade");s?i.one(e.support.transition.end,o):o(),i.removeClass("in")}};var n=e.fn.tab;e.fn.tab=function(n){return this.each(function(){var r=e(this),i=r.data("tab");i||r.data("tab",i=new t(this)),typeof n=="string"&&i[n]()})},e.fn.tab.Constructor=t,e.fn.tab.noConflict=function(){return e.fn.tab=n,this},e(document).on("click.tab.data-api",'[data-toggle="tab"], [data-toggle="pill"]',function(t){t.preventDefault(),e(this).tab("show")})}(window.jQuery),!function(e){"use strict";var t=function(t,n){this.$element=e(t),this.options=e.extend({},e.fn.typeahead.defaults,n),this.matcher=this.options.matcher||this.matcher,this.sorter=this.options.sorter||this.sorter,this.highlighter=this.options.highlighter||this.highlighter,this.updater=this.options.updater||this.updater,this.source=this.options.source,this.$menu=e(this.options.menu),this.shown=!1,this.listen()};t.prototype={constructor:t,select:fu
 nction(){var e=this.$menu.find(".active").attr("data-value");return this.$element.val(this.updater(e)).change(),this.hide()},updater:function(e){return e},show:function(){var t=e.extend({},this.$element.position(),{height:this.$element[0].offsetHeight});return this.$menu.insertAfter(this.$element).css({top:t.top+t.height,left:t.left}).show(),this.shown=!0,this},hide:function(){return this.$menu.hide(),this.shown=!1,this},lookup:function(t){var n;return this.query=this.$element.val(),!this.query||this.query.length<this.options.minLength?this.shown?this.hide():this:(n=e.isFunction(this.source)?this.source(this.query,e.proxy(this.process,this)):this.source,n?this.process(n):this)},process:function(t){var n=this;return t=e.grep(t,function(e){return n.matcher(e)}),t=this.sorter(t),t.length?this.render(t.slice(0,this.options.items)).show():this.shown?this.hide():this},matcher:function(e){return~e.toLowerCase().indexOf(this.query.toLowerCase())},sorter:function(e){var t=[],n=[],r=[],i;whil
 e(i=e.shift())i.toLowerCase().indexOf(this.query.toLowerCase())?~i.indexOf(this.query)?n.push(i):r.push(i):t.push(i);return t.concat(n,r)},highlighter:function(e){var t=this.query.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g,"\\$&");return e.replace(new RegExp("("+t+")","ig"),function(e,t){return"<strong>"+t+"</strong>"})},render:function(t){var n=this;return t=e(t).map(function(t,r){return t=e(n.options.item).attr("data-value",r),t.find("a").html(n.highlighter(r)),t[0]}),t.first().addClass("active"),this.$menu.html(t),this},next:function(t){var n=this.$menu.find(".active").removeClass("active"),r=n.next();r.length||(r=e(this.$menu.find("li")[0])),r.addClass("active")},prev:function(e){var t=this.$menu.find(".active").removeClass("active"),n=t.prev();n.length||(n=this.$menu.find("li").last()),n.addClass("active")},listen:function(){this.$element.on("focus",e.proxy(this.focus,this)).on("blur",e.proxy(this.blur,this)).on("keypress",e.proxy(this.keypress,this)).on("keyup",e.proxy(this.keyup,t
 his)),this.eventSupported("keydown")&&this.$element.on("keydown",e.proxy(this.keydown,this)),this.$menu.on("click",e.proxy(this.click,this)).on("mouseenter","li",e.proxy(this.mouseenter,this)).on("mouseleave","li",e.proxy(this.mouseleave,this))},eventSupported:function(e){var t=e in this.$element;return t||(this.$element.setAttribute(e,"return;"),t=typeof this.$element[e]=="function"),t},move:function(e){if(!this.shown)return;switch(e.keyCode){case 9:case 13:case 27:e.preventDefault();break;case 38:e.preventDefault(),this.prev();break;case 40:e.preventDefault(),this.next()}e.stopPropagation()},keydown:function(t){this.suppressKeyPressRepeat=~e.inArray(t.keyCode,[40,38,9,13,27]),this.move(t)},keypress:function(e){if(this.suppressKeyPressRepeat)return;this.move(e)},keyup:function(e){switch(e.keyCode){case 40:case 38:case 16:case 17:case 18:break;case 9:case 13:if(!this.shown)return;this.select();break;case 27:if(!this.shown)return;this.hide();break;default:this.lookup()}e.stopPropagat
 ion(),e.preventDefault()},focus:function(e){this.focused=!0},blur:function(e){this.focused=!1,!this.mousedover&&this.shown&&this.hide()},click:function(e){e.stopPropagation(),e.preventDefault(),this.select(),this.$element.focus()},mouseenter:function(t){this.mousedover=!0,this.$menu.find(".active").removeClass("active"),e(t.currentTarget).addClass("active")},mouseleave:function(e){this.mousedover=!1,!this.focused&&this.shown&&this.hide()}};var n=e.fn.typeahead;e.fn.typeahead=function(n){return this.each(function(){var r=e(this),i=r.data("typeahead"),s=typeof n=="object"&&n;i||r.data("typeahead",i=new t(this,s)),typeof n=="string"&&i[n]()})},e.fn.typeahead.defaults={source:[],items:8,menu:'<ul class="typeahead dropdown-menu"></ul>',item:'<li><a href="#"></a></li>',minLength:1},e.fn.typeahead.Constructor=t,e.fn.typeahead.noConflict=function(){return e.fn.typeahead=n,this},e(document).on("focus.typeahead.data-api",'[data-provide="typeahead"]',function(t){var n=e(this);if(n.data("typeah
 ead"))return;n.typeahead(n.data())})}(window.jQuery),!function(e){"use strict";var t=function(t,n){this.options=e.extend({},e.fn.affix.defaults,n),this.$window=e(window).on("scroll.affix.data-api",e.proxy(this.checkPosition,this)).on("click.affix.data-api",e.proxy(function(){setTimeout(e.proxy(this.checkPosition,this),1)},this)),this.$element=e(t),this.checkPosition()};t.prototype.checkPosition=function(){if(!this.$element.is(":visible"))return;var t=e(document).height(),n=this.$window.scrollTop(),r=this.$element.offset(),i=this.options.offset,s=i.bottom,o=i.top,u="affix affix-top affix-bottom",a;typeof i!="object"&&(s=o=i),typeof o=="function"&&(o=i.top()),typeof s=="function"&&(s=i.bottom()),a=this.unpin!=null&&n+this.unpin<=r.top?!1:s!=null&&r.top+this.$element.height()>=t-s?"bottom":o!=null&&n<=o?"top":!1;if(this.affixed===a)return;this.affixed=a,this.unpin=a=="bottom"?r.top-n:null,this.$element.removeClass(u).addClass("affix"+(a?"-"+a:""))};var n=e.fn.affix;e.fn.affix=function(
 n){return this.each(function(){var r=e(this),i=r.data("affix"),s=typeof n=="object"&&n;i||r.data("affix",i=new t(this,s)),typeof n=="string"&&i[n]()})},e.fn.affix.Constructor=t,e.fn.affix.defaults={offset:0},e.fn.affix.noConflict=function(){return e.fn.affix=n,this},e(window).on("load",function(){e('[data-spy="affix"]').each(function(){var t=e(this),n=t.data();n.offset=n.offset||{},n.offsetBottom&&(n.offset.bottom=n.offsetBottom),n.offsetTop&&(n.offset.top=n.offsetTop),t.affix(n)})})}(window.jQuery);
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/app/js/.svn/text-base/controllers.js.svn-base
----------------------------------------------------------------------
diff --git a/src/main/ui/app/js/.svn/text-base/controllers.js.svn-base b/src/main/ui/app/js/.svn/text-base/controllers.js.svn-base
new file mode 100755
index 0000000..e68094f
--- /dev/null
+++ b/src/main/ui/app/js/.svn/text-base/controllers.js.svn-base
@@ -0,0 +1,572 @@
+'use strict';
+
+// Controller for the world map
+function WorldMapCtrl($rootScope, $scope, selectedDatasetInformation, regionSelectParams) {
+	$scope.datasets = selectedDatasetInformation.getDatasets();
+	$scope.regionParams = regionSelectParams.getParameters();
+
+	$scope.updateMap = function() {
+ 		
+ 		// Clear Group of layers from map if it exists
+ 		if ("rectangleGroup" in $rootScope) {
+ 			$rootScope.rectangleGroup.clearLayers();
+ 		}
+
+		// Don't process if we don't have any datasets added!!
+		if ($scope.datasets.length == 0)
+			return;
+ 		
+ 		if ("map" in $rootScope) {
+ 			// Create Group to add all rectangles to map
+ 			$rootScope.rectangleGroup = L.layerGroup();
+ 			
+ 			// Loop through datasets and add rectangles to Group 
+			var i = 0;
+ 			angular.forEach($scope.datasets, function(dataset) {
+ 				// Get bounds from dataset 
+ 				var maplatlon = dataset.latlonVals;
+ 				var bounds = [[maplatlon.latMax, maplatlon.lonMin], 
+ 				              [maplatlon.latMin, maplatlon.lonMax]];
+ 	
+ 				var polygon = L.rectangle(bounds,{
+					stroke: false,
+					fillColor: $rootScope.fillColors[i],
+ 				    fillOpacity: 0.3
+ 				});
+
+ 				// Add layer to Group
+ 				$rootScope.rectangleGroup.addLayer(polygon);
+				i++;
+ 			});
+
+			// Draw user selected region
+			if ($scope.regionParams.latMin != "" && $scope.regionParams.latMax != "" && 
+				$scope.regionParams.lonMin != "" && $scope.regionParams.lonMax != "") {
+
+				var bounds = [[$scope.regionParams.latMax, $scope.regionParams.lonMin],
+							  [$scope.regionParams.latMin, $scope.regionParams.lonMax]];
+
+				var polygon = L.rectangle(bounds, {
+					color: '#000000',
+					opacity: 1.0,
+					fill: false,
+				});
+
+				$rootScope.rectangleGroup.addLayer(polygon);
+			}
+
+ 			// Add rectangle Group to map
+ 			$rootScope.rectangleGroup.addTo($rootScope.map);
+ 		}
+	};
+
+	$scope.$watch('datasets', function() {
+		$scope.updateMap();
+	}, true);
+
+	$scope.$watch('regionParams', function() {
+		$scope.updateMap();
+	}, true);
+};
+
+// Controller for dataset parameter selection/modification
+function ParameterSelectCtrl($rootScope, $scope, $http, $timeout, selectedDatasetInformation, regionSelectParams) {
+	$scope.datasets = selectedDatasetInformation.getDatasets();
+
+	// The min/max lat/lon values from the selected datasets
+	$scope.latMin = -90;
+	$scope.latMax = 90;
+	$scope.lonMin = -180;
+	$scope.lonMax = 180;
+	$scope.start = "1980-01-01 00:00:00";
+	$scope.end = "2030-01-01 00:00:00";
+
+	// The min/max lat/lon values entered by the user
+	$scope.enteredLatMin = "";
+	$scope.enteredLatMax = "";
+	$scope.enteredLonMin = "";
+	$scope.enteredLonMax = "";
+	$scope.enteredStart = "";
+	$scope.enteredEnd = "";
+
+	// The min/max lat/lon values that are displayed
+	$scope.displayParams = regionSelectParams.getParameters();
+
+	$scope.runningEval = false;
+	
+	var updateDisplayValues = function() {
+		// Update the displayed lat/lon values. We give precedence to users entered values assuming
+		// they're valid given the current set of datasets selected.
+		//
+		// If the user has entered a value for latMin
+		if ($scope.enteredLatMin != "") {
+			// If it's not a valid value...
+			if ($scope.enteredLatMin < $scope.latMin) {
+				// Reset enteredLatMin to the "unmodified" state and display the correct value.
+				$scope.displayParams.latMin = $scope.latMin;
+			} else {
+				$scope.displayParams.latMin = $scope.enteredLatMin;
+			}
+		// Otherwise, just display the value.
+		} else { 
+			$scope.displayParams.latMin = $scope.latMin;
+		}
+		// Update latMax
+		if ($scope.enteredLatMin != "") {
+			if ($scope.enteredLatMax > $scope.latMax) {
+				$scope.displayParams.latMax = $scope.latMax;
+			} else {
+				$scope.displayParams.latMax = $scope.enteredLatMax;
+			}
+		} else { 
+			$scope.displayParams.latMax = $scope.latMax;
+		}
+		// Update lonMin
+		if ($scope.enteredLonMin != "") {
+			if ($scope.enteredLonMin < $scope.lonMin) {
+				$scope.displayParams.lonMin = $scope.lonMin;
+			} else {
+				$scope.displayParams.lonMin = $scope.enteredLonMin;
+			}
+		} else { 
+			$scope.displayParams.lonMin = $scope.lonMin;
+		}
+		// Update lonMax
+		if ($scope.enteredLonMax != "") {
+			if ($scope.enteredLonMax > $scope.lonMax) {
+				$scope.displayParams.lonMax = $scope.lonMax;
+			} else {
+				$scope.displayParams.lonMax = $scope.enteredLonMax;
+			}
+		} else { 
+			$scope.displayParams.lonMax = $scope.lonMax;
+		}
+		// Update Start time
+		if ($scope.enteredStart != "") {
+			if ($scope.enteredStart < $scope.start) {
+				$scope.displayParams.start = $scope.start;
+			} else {
+				$scope.displayParams.start = $scope.enteredStart;
+			}
+		} else {
+			$scope.displayParams.start = $scope.start;
+		}
+		// Update End time
+		if ($scope.enteredEnd != "") {
+			if ($scope.enteredEnd > $scope.end) {
+				$scope.displayParams.end = $scope.end;
+			} else {
+				$scope.displayParams.end = $scope.enteredEnd;
+			}
+		} else {
+			$scope.displayParams.end = $scope.end;
+		}
+	}
+
+	$scope.shouldDisableControls = function() {
+		return (selectedDatasetInformation.getDatasetCount() < 2);
+	}
+
+	$scope.shouldDisableEvaluate = function() {
+		return ($scope.shouldDisableControls() || $scope.runningEval);
+	}
+
+	$scope.shouldDisableClearButton = function() {
+		return (selectedDatasetInformation.getDatasetCount() == 0);
+	}
+
+	$scope.shouldDisableResultsView = function() {
+		var res = false;
+
+		if ($rootScope.evalResults == "")
+			res = true;
+
+		return res;
+	}
+
+	$scope.clearDatasets = function() {
+		selectedDatasetInformation.clearDatasets();
+	}
+
+	$scope.runEvaluation = function() {
+		$scope.runningEval = true;
+
+		// TODO
+		// Currently this has the 1 model, 1 observation format hard coded in. This shouldn't
+		// be the long-term case! This needs to be changed!!!!!!!!
+		var obsIndex = -1,
+			modelIndex = -1;
+
+		for (var i = 0; i < $scope.datasets.length; i++) {
+			if ($scope.datasets[i]['isObs'] == 1)
+				obsIndex = i;
+			else
+				modelIndex = i;
+		}
+
+		// You might wonder why this is using a jQuery ajax call instead of a built
+		// in $http.post call. The reason would be that it wasn't working with the 
+		// $http.post call but it is with this. So...there you go! This should be
+		// changed eventually!!
+		$.ajax({
+			type: 'POST',
+			url: $rootScope.baseURL + '/rcmes/run/', 
+			data: { 
+				'obsDatasetId'     : $scope.datasets[obsIndex]['id'],
+				'obsParameterId'   : $scope.datasets[obsIndex]['param'],
+				'startTime'        : $scope.displayParams.start,
+				'endTime'          : $scope.displayParams.end,
+				'latMin'           : $scope.displayParams.latMin,
+				'latMax'           : $scope.displayParams.latMax,
+				'lonMin'           : $scope.displayParams.lonMin,
+				'lonMax'           : $scope.displayParams.lonMax,
+				'filelist'         : $scope.datasets[modelIndex]['id'],
+				'modelVarName'     : $scope.datasets[modelIndex]['param'],
+				'modelTimeVarName' : $scope.datasets[modelIndex]['time'],
+				'modelLatVarName'  : $scope.datasets[modelIndex]['lat'],
+				'modelLonVarName'  : $scope.datasets[modelIndex]['lon'],
+				'regridOption'     : 'model',
+				'timeRegridOption' : 'monthly',
+				'metricOption'     : 'bias',
+			},
+			success: function(data) {
+				var comp = data['comparisonPath'].split('/');
+				var model = data['modelPath'].split('/');
+				var obs = data['obsPath'].split('/');
+
+				$rootScope.evalResults = {};
+				$rootScope.evalResults.comparisonPath = comp[comp.length - 1];
+				$rootScope.evalResults.modelPath = model[model.length - 1];
+				$rootScope.evalResults.obsPath = obs[obs.length - 1];
+
+				$scope.runningEval = false;
+
+				$timeout(function() {
+					$('#evaluationResults').trigger('modalOpen', true, true);
+				}, 100);
+			},
+			error: function(xhr, status, error) {
+				$scope.runningEval = false;
+			},
+		});
+	}
+
+	$scope.updateParameters = function() {
+		// Save the user input, even if it isn't valid.
+		$scope.enteredLatMin = $scope.displayParams.latMin;
+		$scope.enteredLatMax = $scope.displayParams.latMax;
+		$scope.enteredLonMin = $scope.displayParams.lonMin;
+		$scope.enteredLonMax = $scope.displayParams.lonMax;
+		$scope.enteredStart  = $scope.displayParams.start;
+		$scope.enteredEnd    = $scope.displayParams.end;
+
+		// Check if the user values are valid and update the display values.
+		updateDisplayValues();
+	}
+
+	$scope.$watch('datasets', 
+		function() { 
+			var numDatasets = $scope.datasets.length;
+
+ 			if (numDatasets) {
+				var latMin = -90,
+					latMax = 90,
+					lonMin = -180,
+					lonMax = 180,
+					start  = "1980-01-01 00:00:00",
+					end    = "2030-01-01 00:00:00";
+ 			
+ 				// Get the valid lat/lon range in the selected datasets.
+ 				for (var i = 0; i < numDatasets; i++) {
+ 					var curDataset = $scope.datasets[i];
+ 	
+ 					latMin = (curDataset['latlonVals']['latMin'] > latMin) ? curDataset['latlonVals']['latMin'] : latMin;
+ 					latMax = (curDataset['latlonVals']['latMax'] < latMax) ? curDataset['latlonVals']['latMax'] : latMax;
+ 					lonMin = (curDataset['latlonVals']['lonMin'] > lonMin) ? curDataset['latlonVals']['lonMin'] : lonMin;
+ 					lonMax = (curDataset['latlonVals']['lonMax'] < lonMax) ? curDataset['latlonVals']['lonMax'] : lonMax;
+ 					start = (curDataset['timeVals']['start'] > start) ? curDataset['timeVals']['start'] : start;
+ 					end = (curDataset['timeVals']['end'] < end) ? curDataset['timeVals']['end'] : end;
+				}
+			}
+
+			$scope.latMin = latMin;
+			$scope.latMax = latMax;
+			$scope.lonMin = lonMin;
+			$scope.lonMax = lonMax;
+			$scope.start = start;
+			$scope.end = end;
+
+			updateDisplayValues();
+		}, true);
+}
+
+// Controller for dataset display
+function DatasetDisplayCtrl($rootScope, $scope, selectedDatasetInformation) {
+	$scope.datasets = selectedDatasetInformation.getDatasets();
+
+	$scope.removeDataset = function($index) {
+		selectedDatasetInformation.removeDataset($index);
+	}
+}
+
+// Controller for observation selection in modal
+function ObservationSelectCtrl($rootScope, $scope, $http, $q, $timeout, selectedDatasetInformation) {
+	// Grab a copy of the datasets so we can display a count to the user!
+	$scope.datasetCount = selectedDatasetInformation.getDatasets();
+
+	// Initalize the option arrays and default to the first element
+	$scope.params      = ["Please select a file above"];
+	$scope.paramSelect = $scope.params[0];
+	$scope.lats        = ["Please select a file above"];
+	$scope.latsSelect  = $scope.lats[0];
+	$scope.lons        = ["Please select a file above"];
+	$scope.lonsSelect  = $scope.lons[0];
+	$scope.times       = ["Please select a file above"];
+	$scope.timeSelect  = $scope.times[0];
+
+	// Grab the path leader information that the webserver is using to limit directory access.
+	$scope.pathLeader = 'False';
+	$http.jsonp($rootScope.baseURL + '/getPathLeader/?callback=JSON_CALLBACK').
+		success(function(data) {
+			$scope.pathLeader = data.leader;
+	});
+
+	// Toggle load button view depending on upload state of selected files
+	$scope.loadingFile = false;
+
+	// Toggle display of a confirmation when loading a dataset
+	$scope.fileAdded = false;
+
+	$scope.latLonVals = [];
+	$scope.timeVals = [];
+	$scope.localSelectForm = {};
+
+	$scope.uploadLocalFile = function() {
+		$scope.loadingFile = true;
+
+		// TODO: Need to try to validate the input a bit. At least make sure we're not
+		// pointing at a directory perhaps?
+		
+		// TODO: Two-way binding with ng-model isn't being used here because it fails to update
+		// properly with the auto-complete that we're using on the input box. So we're doing
+		// it the wrong way temporarily...
+		var input = $('#observationFileInput').val();
+
+		// If the backend is limiting directory access we need to add that leader to our path
+		// so it remains valid!
+		if ($scope.pathLeader != 'False') {
+			input = $scope.pathLeader + input
+		}
+
+		// TODO: We're not really handling the case where there is a failure here at all. 
+		// Should check for fails and allow the user to make changes.
+		//
+		// Get model variables
+		var varsPromise = $http.jsonp($rootScope.baseURL + '/list/vars/"' + input + '"?callback=JSON_CALLBACK');
+		// Get Lat and Lon variables
+		var latlonPromise = $http.jsonp($rootScope.baseURL + '/list/latlon/"' + input + '"?callback=JSON_CALLBACK');
+		// Get Time variables
+		var timesPromise = $http.jsonp($rootScope.baseURL + '/list/time/"' + input + '"?callback=JSON_CALLBACK');
+
+		$q.all([varsPromise, latlonPromise, timesPromise]).then(
+			// Handle success fetches!
+			function(arrayOfResults) {
+				$scope.loadingFile = false;
+
+				// Handle lat/lon results
+				var data = arrayOfResults[1].data;
+				$scope.lats = [data.latname];
+				$scope.lons = [data.lonname];
+				$scope.latLonVals = [data.latMin, data.latMax, data.lonMin, data.lonMax];
+
+				// If there is more than one option for the user, tell them they need to pick one!
+				if ($scope.lats.length > 1) $scope.lats.splice(0, 0, "Please select an option");
+				if ($scope.lons.length > 1) $scope.lons.splice(0, 0, "Please select an option");
+				// Default the display to the first available option.
+				$scope.latsSelect = $scope.lats[0];
+				$scope.lonsSelect = $scope.lons[0];
+
+				// Handle time results
+				var data = arrayOfResults[2].data
+				$scope.times = [data.timename];
+
+				if ($scope.times.length > 1) $scope.times.splice(0, 0, "Please select an option");
+				$scope.timeSelect = $scope.times[0];
+
+				// Handle parameter results
+				var data = arrayOfResults[0].data.variables;
+				$scope.params = (data instanceof Array) ? data : [data];
+				$scope.params = $.grep($scope.params, 
+									function(val) {
+										return ($.inArray(val, $scope.lats)  != 0 && 
+												$.inArray(val, $scope.lons)  != 0 && 
+												$.inArray(val, $scope.times) != 0);
+									});
+				
+				if ($scope.params.length > 1) $scope.params.splice(0, 0, "Please select an option");
+				$scope.paramSelect = $scope.params[0];
+			},
+			// Uh oh! AT LEAST on of our fetches failed
+			function(arrayOfFailure) {
+				$scope.loadingFile = false;
+
+				$scope.params      = ["Unable to load variable(s)"];
+				$scope.paramSelect = $scope.params[0];
+				$scope.lats        = ["Unable to load variable(s)"];
+				$scope.latsSelect  = $scope.lats[0];
+				$scope.lons        = ["Unable to load variable(s)"];
+				$scope.lonsSelect  = $scope.lons[0];
+				$scope.times       = ["Unable to load variable(s)"];
+				$scope.timeSelect  = $scope.times[0];
+			}
+		);
+	};
+
+	$scope.addDataSet = function() {
+		// TODO: Need to verify that all the variables selected are correct!!!
+		// TODO: We shouldn't allow different parameters to match the same variables!!
+
+		var newDataset = {};
+		var input = $('#observationFileInput').val();
+
+		// If the backend is limiting directory access we need to add that leader to our path
+		// so it remains valid!
+		if ($scope.pathLeader != 'False') {
+			input = $scope.pathLeader + input
+		}
+
+		newDataset['isObs'] = 0;
+		// Save the model path. Note that the path is effectively the "id" for the model.
+		newDataset['id'] = input;
+		// Grab the file name later for display purposes.
+		var splitFilePath = input.split('/');
+		newDataset['name'] = splitFilePath[splitFilePath.length - 1];
+		// Save the model parameter variable. We save it twice for consistency and display convenience.
+		newDataset['param'] = $scope.paramSelect;
+		newDataset['paramName'] = newDataset['param'];
+		// Save the lat/lon information
+		newDataset['lat'] = $scope.latsSelect;
+		newDataset['lon'] = $scope.lonsSelect;
+
+		newDataset['latlonVals'] = {"latMin": $scope.latLonVals[0], "latMax": $scope.latLonVals[1],
+									"lonMin": $scope.latLonVals[2], "lonMax": $scope.latLonVals[3]};
+		// Get the time information
+		newDataset['time'] = $scope.timeSelect;
+		newDataset['timeVals'] = {"start": $scope.timeVals[0], "end": $scope.timeVals[1]};
+
+		selectedDatasetInformation.addDataset(newDataset);
+
+		// Reset all the fields!!
+		$scope.params = ["Please select a file above"];
+		$scope.paramSelect = $scope.params[0];
+		$scope.lats = ["Please select a file above"];
+		$scope.latsSelect = $scope.lats[0];
+		$scope.lons = ["Please select a file above"];
+		$scope.lonsSelect = $scope.lons[0];
+		$scope.times = ["Please select a file above"];
+		$scope.timeSelect = $scope.times[0];
+		$scope.latLonVals = [];
+		$scope.timeVals = [];
+
+		// Clear the input box
+		$('#observationFileInput').val("");
+
+		// Display a confirmation message for a little bit
+		$scope.fileAdded = true;
+		$timeout(function() {
+			$scope.fileAdded = false;
+		}, 2000);
+	}
+
+	$scope.shouldDisableLoadButton = function() {
+		return $scope.loadingFile;
+	}
+}
+
+function RcmedSelectionCtrl($rootScope, $scope, $http, $timeout, selectedDatasetInformation) {
+	// Grab a copy of the datasets so we can display a count to the user!
+	$scope.datasetCount = selectedDatasetInformation.getDatasets();
+	$scope.fileAdded = false;
+
+	var getObservations = function() {
+		$http.jsonp($rootScope.baseURL + '/getObsDatasets?callback=JSON_CALLBACK').
+			success(function(data) {
+				$scope.availableObs = data;
+				$scope.availableObs.splice(0, 0, {longname: 'Please select an option'});
+				$scope.datasetSelection = $scope.availableObs[0];
+			}).
+			error(function(data) {
+				$scope.availableObs = ["Unable to query RCMED"]
+			});
+	};
+
+	var getObservationTimeRange = function(datasetID) {
+		var times = {
+			'1' : {'start' : '1989-01-01 00:00:00','end' : '2009-12-31 00:00:00'},	// ERA-Interim
+			'2' : {'start' : '2002-08-31 00:00:00','end' : '2010-01-01 00:00:00'},	// AIRS
+			'3' : {'start' : '1998-01-01 00:00:00','end' : '2010-01-01 00:00:00'},	// TRMM
+			'4' : {'start' : '1948-01-01 00:00:00','end' : '2010-01-01 00:00:00'},	// URD
+			'5' : {'start' : '2000-02-24 00:00:00','end' : '2010-05-30 00:00:00'},	// MODIS
+			'6' : {'start' : '1901-01-01 00:00:00','end' : '2006-12-01 00:00:00'}   // CRU
+		};
+
+		return ((datasetID in times) ? times[datasetID] : false);
+	};
+
+	$scope.dataSelectUpdated = function() {
+		var urlString = $rootScope.baseURL + '/getDatasetParam?dataset=' + 
+							$scope.datasetSelection["shortname"] + 
+							"&callback=JSON_CALLBACK";
+		$http.jsonp(urlString).
+			success(function(data) {
+				$scope.retrievedObsParams = data;
+				if ($scope.retrievedObsParams.length > 1) 
+					$scope.retrievedObsParams.splice(0, 0, {shortname: 'Please select a parameter'});
+				$scope.parameterSelection = $scope.retrievedObsParams[0];
+			});
+	};
+
+	$scope.addObservation = function() {
+		// This is a horrible hack for temporarily getting a valid time range
+		// for the selected observation. Eventually we need to handle this more
+		// elegantly than indexing into an array...
+		var timeRange = getObservationTimeRange($scope.datasetSelection["dataset_id"]);
+
+		var newDataset = {};
+
+		newDataset['isObs'] = 1;
+		// Save the dataset id (the important part) and name (for display purposes)
+		newDataset['id'] = $scope.datasetSelection['dataset_id'];
+		newDataset['name'] = $scope.datasetSelection['longname'];
+		// Save the parameter id (the important part) and name (for display purposes)
+		newDataset['param'] = $scope.parameterSelection['parameter_id'];
+		newDataset['paramName'] = $scope.parameterSelection['longname'];
+		// Save the (fake) lat/lon information. Our datasets cover the entire globe (I think...)
+		newDataset['latlonVals'] = {"latMin": -90, "latMax": 90, "lonMin": -180, "lonMax": 180};
+		// Set some defaults for lat/lon variable names. This just helps us display stuff later.
+		newDataset['lat'] = "N/A";
+		newDataset['lon'] = "N/A";
+		// Save time range information. If we don't have saved data for this observation then
+		// we set the values to extreme values so they'll be ignored when calculating overlaps.
+		newDataset['timeVals'] = {"start": (timeRange) ? timeRange['start'] : "1901-01-01 00:00:00",
+								  "end": (timeRange) ? timeRange['end'] : "2050-01-01 00:00:00"};
+		// Set a default for the time variable names for display convenience.
+		newDataset['time'] = "N/A";
+
+		selectedDatasetInformation.addDataset(newDataset);
+
+		// Clear the user selections by requery-ing RCMED. This is really hacky, but it works for now...
+		$scope.availableObs = [];
+		$scope.retrievedObsParams = [];
+		getObservations();
+
+		// Display a confirmation message for a little bit
+		$scope.fileAdded = true;
+		$timeout(function() {
+			$scope.fileAdded = false;
+		}, 2000);
+	};
+
+	// Grab the available observations from RCMED
+	getObservations();
+}

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/app/js/.svn/text-base/directives.js.svn-base
----------------------------------------------------------------------
diff --git a/src/main/ui/app/js/.svn/text-base/directives.js.svn-base b/src/main/ui/app/js/.svn/text-base/directives.js.svn-base
new file mode 100755
index 0000000..46a7627
--- /dev/null
+++ b/src/main/ui/app/js/.svn/text-base/directives.js.svn-base
@@ -0,0 +1,374 @@
+'use strict';
+
+// Directive for dealing with the Leaflet map
+angular.module('rcmes').
+directive('sap', function($rootScope) {
+	return {
+		restrict: 'E',
+		replace: true,
+		template: '<div></div>',
+		link: function(scope, element, attrs) {
+			$rootScope.map = L.map(attrs.id, {
+				center: [40, 0],
+				zoom: 2,
+				scrollWheelZoom: false,
+			});
+			//create a CloudMade tile layer and add it to the map
+			L.tileLayer('http://{s}.tile.cloudmade.com/57cbb6ca8cac418dbb1a402586df4528/997/256/{z}/{x}/{y}.png', {
+				maxZoom: 4, minZoom: 2,
+			}).addTo($rootScope.map);
+		}
+	};
+}).
+// Directive for inserting bootstrap modals
+directive('bootstrapModal', function($timeout) {
+	var link = function(scope, elem, attrs) {
+		var escapeEvent;
+		var openModal;
+		var closeModal;
+
+		escapeEvent = function(e) {
+			if (e.which == 27)
+				closeModal();
+		}
+
+		openModal = function(event, toggleBackground, toggleKeyboardEscape) {
+			// Grab the current modal tag based on the modalId attribute in the bootstrapModal tag
+			var modal = $('#' + attrs.modalId);
+
+			// Make all the modal's children of class "close" call the appropriate function for closing!
+			$('.close', modal).bind('click', closeModal);
+
+			modal.modal({
+				show: true,
+				backdrop: toggleBackground,
+				keyboard: toggleKeyboardEscape,
+			});
+		};
+
+		closeModal = function(event) {
+			$('#' + attrs.modalId).modal('hide');
+			
+		};
+
+		// We need to bind the close and open modal events so outside elements can trigger the modal.
+		// This has to wait until the template has been fully inserted, so just wait a bit of time
+		// before we set them. I'm sure there's a better way of handling this...
+		$timeout(function() {
+			$('#' + attrs.modalId).
+				bind('modalOpen', openModal).
+				bind('modalClose', closeModal);
+		}, 100);
+	};
+
+	return {
+		link: link,
+		replace: true,
+		restrict: 'E',
+		scope: {
+			modalId: '@' 
+		},
+		template: '<div id="{{modalId}}" class="modal hide fade" tabindex="-1"><div ng-transclude></div></div>',
+		transclude: true
+	};
+}).
+// This directive process bootstrap-modal-open attributes. This lets the user bind the opening of a specific modal
+// as well as specifying how that modal should open.
+directive('bootstrapModalOpen', function() {
+	return {
+		restrict: 'A',
+		link: function(scope, elem, attrs) {
+			// Default to showing the background if the user didn't specify a value for this.
+			var hasBackground = (attrs.background === undefined ? true : attrs.background);
+			// Enable keyboard closing of modal with escape key.
+			var hasKeyboardEscape = (attrs.keyboard === undefined ? true : attrs.keyboard);
+
+			$(elem).bind('click', function() {
+				$('#' + attrs.bootstrapModalOpen).trigger('modalOpen', [hasBackground, hasKeyboardEscape]);
+			});
+		}
+	};
+}).
+// Setup a text input that the user will use to input a path to a local file.
+directive('predictiveFileBrowserInput', function() {
+	var link = function($scope, $elem, $attrs) {
+		$scope.autocomplete = [];
+		
+		/*
+		 * We need a place to dump our auto-completion options
+		 */
+		$($elem).parent().append('<ul id="autoCompletePath"><ul>');
+
+		// Handle user clicks on auto-complete path options
+		$(document).on('click', '#autoCompletePath li span', function(e) {
+			// Set the input text box's value to that of the user selected path
+			var val = $(e.target).text();
+			$($elem).val(val);
+
+			// If the user selected a directory, find more results..
+			if (val[val.length - 1] == '/') {
+				$scope.fetchFiles($($elem).val());
+			// Otherwise, remove the auto-complete options...
+			} else {
+				$('#autoCompletePath li').remove();
+			}
+		});
+
+		/*
+		 * Handle key-down events on the input box
+		 *
+		 * We need to ignore <TAB> presses here so we can auto-complete with <TAB>.
+		 * If we don't ignore here then <TAB> will move the user to the next field
+		 * in the form and our common-prefix-fill won't work later.
+		 */
+		$($elem).keydown(function(e) {
+			var code = e.keyCode || e.which;
+			var BACKSPACE = 8,
+				TAB = 9;
+
+			if (code == TAB)
+				return false;
+		});
+
+		/*
+		 * Handle key-up events on the input box
+		 */
+		$($elem).keyup(function(e) {
+			var code = e.keyCode || e.which;
+			var BACKSPACE = 8,
+				TAB = 9,
+				FORWARD_SLASH = 191;
+
+			if (code === FORWARD_SLASH) {
+				// Fetch new directory information from the server.
+				$scope.fetchFiles($(this).val());
+			} else if (code === TAB) {
+				// Attempt to auto-fill for the user.
+				$scope.handleTabPress();
+			} else if (code == BACKSPACE) {
+				// Need to properly handle the removal of directory information
+				// and the displaying of auto-complete options
+				$scope.handleBackSpace();
+			} else {
+				// Filter auto-complete options based on user input..
+				$scope.handleMiscKeyPress();
+			}
+
+			// This is being used so we can handle backspacing. The user might hold
+			// down the backspace key or select a section of text and delete. This allows
+			// us to compare the result to its prior state, which makes handling
+			// backspaces easier.
+			$scope.lastInputContents = $elem.val();
+		});
+
+		/*
+		 * Grab additional path information from the web-server
+		 *
+		 * Params:
+		 *		path - The path to get a directory listing of.
+		 */
+		// TODO Make this use $HTTP
+		$scope.fetchFiles = function(path) {
+			$.get($scope.baseURL + '/getDirInfo/' + path, {},
+				 function(data) {
+					 $scope.setNewData(data);
+					 $scope.updateAutoComplete();
+				 }, 'json');
+		};
+
+		/*
+		 * Grab additional path information from the web-server and filter the
+		 * results based on the current input text.
+		 *
+		 * Params:
+		 *		path - The path to get a directory listing of.
+		 *
+		 * This is needed to handle deletion of selected text. It is possible that
+		 * the user will select text and delete only part of a word. The results
+		 * need to be filtered based on this partial input.
+		 */
+		// TODO Why isn't this using $http?!?!?! Because I copy and pasted!!!!
+		$scope.fetchFilesAndFilter = function(path) {
+			$.get($scope.baseURL + '/getDirInfo/' + path, {},
+				 function(data) {
+					 $scope.setNewData(data);
+					 $scope.filterResults();
+					 $scope.updateAutoComplete();
+				 }, 'json');
+		};
+
+		/*
+		 * Handle directory data from the server.
+		 *
+		 * We store the entire directory information along with the remaining
+		 * possible options given the users current input. This lets us avoid
+		 * unnecessary calls to the server for directory information every time
+		 * the user deletes something.
+		 */
+		$scope.setNewData = function(data) {
+			$scope.autocomplete = data.sort();
+			$scope.possibleCompletes = $scope.autocomplete;
+		};
+
+		/* 
+		 * Handle <TAB> presses.
+		 *
+		 * Attempt to auto-complete options when the user presses <TAB>.
+		 */
+		$scope.handleTabPress = function() {
+			// If there's only one option available there's no points in trying to
+			// find a common prefix! Just set the value!
+			if ($scope.possibleCompletes.length === 1) {
+				$elem.val($scope.possibleCompletes[0]);
+
+				// Make sure more options are displayed if a directory was selected.
+				$scope.checkForMoreOptions();
+				$scope.updateAutoComplete();
+				return;
+			}
+
+			// Find the greatest common prefix amongst the remaining choices and set
+			// the input text to it.
+			var prefix = $scope.getLargestCommonPrefix($scope.possibleCompletes);
+			$elem.val(prefix);
+			$scope.updateAutoComplete();
+		};
+
+		/*
+		 * Handle Backspacing and option displaying.
+		 *
+		 * The auto-complete options needs to be displayed correctly when the user
+		 * removes directory information.
+		 */
+		$scope.handleBackSpace = function() {
+			var curInputVal = $elem.val();
+
+			// If the user deletes everything in the input box all we need to do
+			// is make sure that the auto-complete options aren't displayed.
+			if (curInputVal.length === 0) {
+				$('#autoCompletePath li').remove();
+				return;
+			}
+
+			// Figure out how much text the user removed from the input box.
+			var lengthDiff = $scope.lastInputContents.length - curInputVal.length;
+			// Grab the removed text.
+			var removedText = $scope.lastInputContents.substr(-lengthDiff);
+
+			// If the user deleted over a directory we need to fetch information on the
+			// previous directory for auto-completion.
+			if (removedText.indexOf('/') !== -1) {
+				var lastSlashIndex = curInputVal.lastIndexOf('/');
+
+				// If the remaining path still contains a directory...
+				if (lastSlashIndex !== -1) {
+					// Grab the section of the path that points to a valid directory,
+					// fetch the listing, and update the results.
+					var pathToSearch = curInputVal.slice(0, lastSlashIndex + 1);
+					$scope.fetchFilesAndFilter(pathToSearch);
+				} else {
+					// Delete the old auto-complete information in the case where the user
+					// completely removed path information.
+					$('#autoCompletePath li').remove();
+				}
+			} else {
+				// Otherwise, we just need to filter results based on the remaining input.
+				$scope.filterResults();
+				$scope.updateAutoComplete();
+			}
+		};
+
+		/* 
+		 * Handle all other key presses in the input box
+		 *
+		 * Filter the auto-complete options as the user types to ensure that only options
+		 * which are possible given the current input text are still displayed.
+		 */
+		$scope.handleMiscKeyPress = function() {
+			// Safely exit when there are no options available.
+			if ($scope.autocomplete === [])
+				return;
+
+			// Otherwise, filter the results.
+			$scope.filterResults();
+			$scope.updateAutoComplete();
+		};
+
+		/* 
+		 * When a path is auto-completed with <TAB> we need to check to see if it points
+		 * to a directory. If it does, we still need to fetch results!
+		 */
+		$scope.checkForMoreOptions = function() {
+			var path = $elem.val();
+			if (path[path.length - 1] === '/') {
+				$scope.fetchFiles(path);
+			}
+		};
+
+		/* 
+		 * Calculate the greatest common prefix of the passed options.
+		 *
+		 * Params:
+		 *		Options - An array of strings in which the greatest common prefix
+		 *				  should be found
+		 *
+		 * Returns:
+		 *		The greatest common prefix of the strings.
+		 *
+		 *
+		 * Note - For us, there will always be a prefix of at least '/' since this can't
+		 * possible be called without the users entering a starting directory. As a result,
+		 * we don't explicitly handle the case where there is 0 length common prefix.
+		 */
+		$scope.getLargestCommonPrefix = function(options) {
+			var index = 1;
+			var shortestString = options.reduce(function(a, b) { return a.length < b.length ? a : b; });
+			var longestString = options.reduce(function(a, b) { return a.length > b.length ? a : b; });
+			var	substringToCheck = shortestString[0];
+
+			while (longestString.indexOf(substringToCheck) !== -1) {
+				substringToCheck = shortestString.slice(0, ++index);
+			}
+
+			return longestString.slice(0, index - 1);
+		};
+
+		/* 
+		 * Filter the auto-complete options based on the current input.
+		 */
+		$scope.filterResults = function() {
+			$scope.possibleCompletes = $scope.autocomplete.filter(function(item, index, array) {
+				return (~item.indexOf($($elem).val()));
+			});
+
+			$scope.possibleCompletes.sort();
+		};
+
+		/*
+		 * Update the display of auto-complete options.
+		 */
+		$scope.updateAutoComplete = function() {
+			// Remove all the existing options
+			$('#autoCompletePath li').remove();
+
+			// We don't need to show anything if the user has completely selected
+			// the only existing option available.
+			if ($scope.possibleCompletes.length === 1) {
+				if ($scope.possibleCompletes[0] === $elem.val()) {
+					return;
+				}
+			}
+
+			// Display all the possible completes
+			$.each($scope.possibleCompletes, function(i, v) {
+				$('#autoCompletePath').append($('<li>').html($('<span>').text(v)));
+			});
+		};
+	};
+
+	return {
+		link: link,
+		scope: true,
+		restrict: 'A'
+	};
+});

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/app/js/.svn/text-base/filters.js.svn-base
----------------------------------------------------------------------
diff --git a/src/main/ui/app/js/.svn/text-base/filters.js.svn-base b/src/main/ui/app/js/.svn/text-base/filters.js.svn-base
new file mode 100755
index 0000000..259dd4e
--- /dev/null
+++ b/src/main/ui/app/js/.svn/text-base/filters.js.svn-base
@@ -0,0 +1,10 @@
+'use strict';
+
+/* Filters */
+
+angular.module('myApp.filters', []).
+  filter('interpolate', ['version', function(version) {
+    return function(text) {
+      return String(text).replace(/\%VERSION\%/mg, version);
+    }
+  }]);

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/app/js/.svn/text-base/jasny-bootstrap.min.js.svn-base
----------------------------------------------------------------------
diff --git a/src/main/ui/app/js/.svn/text-base/jasny-bootstrap.min.js.svn-base b/src/main/ui/app/js/.svn/text-base/jasny-bootstrap.min.js.svn-base
new file mode 100755
index 0000000..320fff4
--- /dev/null
+++ b/src/main/ui/app/js/.svn/text-base/jasny-bootstrap.min.js.svn-base
@@ -0,0 +1,6 @@
+/*!
+* Jasny-bootstrap.js by @ArnoldDaniels
+* Copyright 2012 Arnold Daniels
+* http://www.apache.org/licenses/LICENSE-2.0.txt
+*/
+!function(e){"use strict";var t=function(t,n){this.$element=e(t),this.options=e.extend({},e.fn.typeahead.defaults,n),this.options.target&&(this.$target=e(this.options.target)),this.matcher=this.options.matcher||this.matcher,this.sorter=this.options.sorter||this.sorter,this.highlighter=this.options.highlighter||this.highlighter,this.updater=this.options.updater||this.updater,this.source=this.options.source,this.strict=this.options.strict,this.$menu=e(this.options.menu),this.shown=!1,typeof this.source=="string"&&(this.url=this.source,this.source=this.searchAjax),t.nodeName=="SELECT"&&this.replaceSelect(),this.text=this.$element.val(),this.$element.attr("data-text",this.value).attr("autocomplete","off"),typeof this.$target!="undefined"?this.$element.attr("data-value",this.$target.val()):typeof this.$element.attr("data-value")=="undefined"&&this.$element.attr("data-value",this.strict?"":this.value),this.$menu.css("min-width",this.$element.width()+12),this.listen()};t.prototype={constru
 ctor:t,replaceSelect:function(){this.$target=this.$element,this.$element=e('<input type="text" />'),this.source={},this.strict=!0;var t=this.$target.find("option"),n;for(var r=0;r<t.length;r++){n=e(t[r]);if(n.val()===""){this.$element.attr("placeholder",n.html());continue}this.source[n.val()]=n.html(),this.$target.val()==n.val()&&this.$element.val(n.html())}var i=this.$target[0].attributes;for(r=0;r<i.length;r++)i[r].nodeName!="type"&&i[r].nodeName!="name"&&i[r].nodeName!="id"&&i[r].nodeName!="data-provide"&&!i[r].nodeName.match(/^on/)&&this.$element.attr(i[r].nodeName,i[r].nodeValue);this.$element.insertAfter(this.$target),this.$target.attr("autofocus")&&this.$element.trigger("focus").select(),this.$target.attr("autofocus",!1),this.$target.hide()},destroyReplacement:function(){typeof this.$target!="undefined"&&this.$target[0].nodeName=="SELECT"&&this.$element.replaceWith("")},select:function(){var e=this.$menu.find(".active"),t=e.attr("data-value"),n=e.find(".item-text").length>0?e
 .find(".item-text").text():e.text();return t=this.updater(t,"value"),n=this.updater(n,"text"),this.$element.val(n).attr("data-value",t),this.text=n,typeof this.$target!="undefined"&&this.$target.val(t).trigger("change"),this.$element.trigger("change"),this.hide()},updater:function(e,t){return e},show:function(){var t=e.extend({},this.$element.position(),{height:this.$element[0].offsetHeight});return this.$menu.insertAfter(this.$element).css({top:t.top+t.height,left:t.left}).show(),this.shown=!0,this},hide:function(){return this.$menu.hide(),this.shown=!1,this},lookup:function(t){var n;return this.query=this.$element.val(),!this.query||this.query.length<this.options.minLength?this.shown?this.hide():this:(n=e.isFunction(this.source)?this.source(this.query,e.proxy(this.process,this)):this.source,n?this.process(n):this)},process:function(t){return e.isArray(t)?this.processArray(t):this.processObject(t)},processArray:function(t){var n=this;return t=e.grep(t,function(e){return n.matcher(e
 )}),t=this.sorter(t),t.length?this.render(t.slice(0,this.options.items)).show():this.shown?this.hide():this},processObject:function(t){var n=this,r={},i=0;return e.each(t,function(e,t){n.matcher(t)&&(r[e]=t)}),r=this.sorter(r),e.isEmptyObject(r)?this.shown?this.hide():this:(e.each(r,function(e,t){i++>=n.options.items&&delete r[e]}),this.render(r).show())},searchAjax:function(t,n){var r=this;this.ajaxTimeout&&clearTimeout(this.ajaxTimeout),this.ajaxTimeout=setTimeout(function(){r.ajaxTimeout&&clearTimeout(r.ajaxTimeout);if(t===""){r.hide();return}e.get(r.url,{q:t,limit:r.options.items},function(e){typeof e=="string"&&(e=JSON.parse(e)),n(e)})},this.options.ajaxdelay)},matcher:function(e){return~e.toLowerCase().indexOf(this.query.toLowerCase())},sorter:function(t){return e.isArray(t)?this.sortArray(t):this.sortObject(t)},sortArray:function(e){var t=[],n=[],r=[],i;while(i=e.shift())i.toLowerCase().indexOf(this.query.toLowerCase())?~i.indexOf(this.query)?n.push(i):r.push(i):t.push(i);ret
 urn t.concat(n,r)},sortObject:function(e){var t={},n;for(n in e)e[n].toLowerCase().indexOf(this.query.toLowerCase())||(t[n]=e[n],delete e[n]);for(n in e)~e[n].indexOf(this.query)&&(t[n]=e[n],delete e[n]);for(n in e)t[n]=e[n];return t},highlighter:function(e){var t=this.query.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g,"\\$&");return e.replace(new RegExp("("+t+")","ig"),function(e,t){return"<strong>"+t+"</strong>"})},render:function(t){var n=this,r=e([]);return e.map(t,function(i,s){if(r.length>=n.options.items)return;var o,u;e.isArray(t)&&(s=i),o=e(n.options.item),u=o.find("a").length?o.find("a"):o,u.html(n.highlighter(i)),o.attr("data-value",s),o.find("a").length===0&&o.addClass("dropdown-header"),r.push(o[0])}),r.not(".dropdown-header").first().addClass("active"),this.$menu.html(r),this},next:function(t){var n=this.$menu.find(".active").removeClass("active"),r=n.nextAll("li:not(.dropdown-header)").first();r.length||(r=e(this.$menu.find("li:not(.dropdown-header)")[0])),r.addClass("active
 ")},prev:function(e){var t=this.$menu.find(".active").removeClass("active"),n=t.prevAll("li:not(.dropdown-header)").first();n.length||(n=this.$menu.find("li:not(.dropdown-header)").last()),n.addClass("active")},listen:function(){this.$element.on("focus",e.proxy(this.focus,this)).on("blur",e.proxy(this.blur,this)).on("change",e.proxy(this.change,this)).on("keypress",e.proxy(this.keypress,this)).on("keyup",e.proxy(this.keyup,this)),this.eventSupported("keydown")&&this.$element.on("keydown",e.proxy(this.keydown,this)),this.$menu.on("click",e.proxy(this.click,this)).on("mouseenter","li",e.proxy(this.mouseenter,this)).on("mouseleave","li",e.proxy(this.mouseleave,this)),e(window).on("unload",e.proxy(this.destroyReplacement,this))},eventSupported:function(e){var t=e in this.$element;return t||(this.$element.setAttribute(e,"return;"),t=typeof this.$element[e]=="function"),t},move:function(e){if(!this.shown)return;switch(e.keyCode){case 9:case 13:case 27:e.preventDefault();break;case 38:e.pr
 eventDefault(),this.prev();break;case 40:e.preventDefault(),this.next()}e.stopPropagation()},keydown:function(t){this.suppressKeyPressRepeat=~e.inArray(t.keyCode,[40,38,9,13,27]),this.move(t)},keypress:function(e){if(this.suppressKeyPressRepeat)return;this.move(e)},keyup:function(e){switch(e.keyCode){case 40:case 38:case 16:case 17:case 18:break;case 9:case 13:if(!this.shown)return;this.select();break;case 27:if(!this.shown)return;this.hide();break;default:this.lookup()}e.stopPropagation(),e.preventDefault()},change:function(e){var t;this.$element.val()!=this.text&&(t=this.$element.val()===""||this.strict?"":this.$element.val(),this.$element.val(t),this.$element.attr("data-value",t),this.text=t,typeof this.$target!="undefined"&&this.$target.val(t))},focus:function(e){this.focused=!0},blur:function(e){this.focused=!1,!this.mousedover&&this.shown&&this.hide()},click:function(e){e.stopPropagation(),e.preventDefault(),this.select(),this.$element.focus()},mouseenter:function(t){this.mous
 edover=!0,this.$menu.find(".active").removeClass("active"),e(t.currentTarget).addClass("active")},mouseleave:function(e){this.mousedover=!1,!this.focused&&this.shown&&this.hide()}};var n=e.fn.typeahead;e.fn.typeahead=function(n){return this.each(function(){var r=e(this),i=r.data("typeahead"),s=typeof n=="object"&&n;i||r.data("typeahead",i=new t(this,s)),typeof n=="string"&&i[n]()})},e.fn.typeahead.defaults={source:[],items:8,menu:'<ul class="typeahead dropdown-menu"></ul>',item:'<li><a href="#"></a></li>',ajaxdelay:400,minLength:1},e.fn.typeahead.Constructor=t,e.fn.typeahead.noConflict=function(){return e.fn.typeahead=n,this},e(document).off("focus.typeahead.data-api").on("focus.typeahead.data-api",'[data-provide="typeahead"]',function(t){var n=e(this);if(n.data("typeahead"))return;n.is("select")&&n.attr("autofocus",!0),t.preventDefault(),n.typeahead(n.data())})}(window.jQuery),!function(e){"use strict";var t=window.orientation!==undefined,n=navigator.userAgent.toLowerCase().indexOf
 ("android")>-1,r=function(t,r){if(n)return;this.$element=e(t),this.options=e.extend({},e.fn.inputmask.defaults,r),this.mask=String(r.mask),this.init(),this.listen(),this.checkVal()};r.prototype={init:function(){var t=this.options.definitions,n=this.mask.length;this.tests=[],this.partialPosition=this.mask.length,this.firstNonMaskPos=null,e.each(this.mask.split(""),e.proxy(function(e,r){r=="?"?(n--,this.partialPosition=e):t[r]?(this.tests.push(new RegExp(t[r])),this.firstNonMaskPos===null&&(this.firstNonMaskPos=this.tests.length-1)):this.tests.push(null)},this)),this.buffer=e.map(this.mask.split(""),e.proxy(function(e,n){if(e!="?")return t[e]?this.options.placeholder:e},this)),this.focusText=this.$element.val(),this.$element.data("rawMaskFn",e.proxy(function(){return e.map(this.buffer,function(e,t){return this.tests[t]&&e!=this.options.placeholder?e:null}).join("")},this))},listen:function(){if(this.$element.attr("readonly"))return;var t=(navigator.userAgent.match(/msie/i)?"paste":"in
 put")+".mask";this.$element.on("unmask",e.proxy(this.unmask,this)).on("focus.mask",e.proxy(this.focusEvent,this)).on("blur.mask",e.proxy(this.blurEvent,this)).on("keydown.mask",e.proxy(this.keydownEvent,this)).on("keypress.mask",e.proxy(this.keypressEvent,this)).on(t,e.proxy(this.pasteEvent,this))},caret:function(e,t){if(this.$element.length===0)return;if(typeof e=="number")return t=typeof t=="number"?t:e,this.$element.each(function(){if(this.setSelectionRange)this.setSelectionRange(e,t);else if(this.createTextRange){var n=this.createTextRange();n.collapse(!0),n.moveEnd("character",t),n.moveStart("character",e),n.select()}});if(this.$element[0].setSelectionRange)e=this.$element[0].selectionStart,t=this.$element[0].selectionEnd;else if(document.selection&&document.selection.createRange){var n=document.selection.createRange();e=0-n.duplicate().moveStart("character",-1e5),t=e+n.text.length}return{begin:e,end:t}},seekNext:function(e){var t=this.mask.length;while(++e<=t&&!this.tests[e]);
 return e},seekPrev:function(e){while(--e>=0&&!this.tests[e]);return e},shiftL:function(e,t){var n=this.mask.length;if(e<0)return;for(var r=e,i=this.seekNext(t);r<n;r++)if(this.tests[r]){if(!(i<n&&this.tests[r].test(this.buffer[i])))break;this.buffer[r]=this.buffer[i],this.buffer[i]=this.options.placeholder,i=this.seekNext(i)}this.writeBuffer(),this.caret(Math.max(this.firstNonMaskPos,e))},shiftR:function(e){var t=this.mask.length;for(var n=e,r=this.options.placeholder;n<t;n++)if(this.tests[n]){var i=this.seekNext(n),s=this.buffer[n];this.buffer[n]=r;if(!(i<t&&this.tests[i].test(s)))break;r=s}},unmask:function(){this.$element.unbind(".mask").removeData("inputmask")},focusEvent:function(){this.focusText=this.$element.val();var t=this.mask.length,n=this.checkVal();this.writeBuffer();var r=this,i=function(){n==t?r.caret(0,n):r.caret(n)};e.browser.msie?i():setTimeout(i,0)},blurEvent:function(){this.checkVal(),this.$element.val()!=this.focusText&&this.$element.trigger("change")},keydownEv
 ent:function(e){var n=e.which;if(n==8||n==46||t&&n==127){var r=this.caret(),i=r.begin,s=r.end;return s-i===0&&(i=n!=46?this.seekPrev(i):s=this.seekNext(i-1),s=n==46?this.seekNext(s):s),this.clearBuffer(i,s),this.shiftL(i,s-1),!1}if(n==27)return this.$element.val(this.focusText),this.caret(0,this.checkVal()),!1},keypressEvent:function(e){var t=this.mask.length,n=e.which,r=this.caret();if(e.ctrlKey||e.altKey||e.metaKey||n<32)return!0;if(n){r.end-r.begin!==0&&(this.clearBuffer(r.begin,r.end),this.shiftL(r.begin,r.end-1));var i=this.seekNext(r.begin-1);if(i<t){var s=String.fromCharCode(n);if(this.tests[i].test(s)){this.shiftR(i),this.buffer[i]=s,this.writeBuffer();var o=this.seekNext(i);this.caret(o)}}return!1}},pasteEvent:function(){var e=this;setTimeout(function(){e.caret(e.checkVal(!0))},0)},clearBuffer:function(e,t){var n=this.mask.length;for(var r=e;r<t&&r<n;r++)this.tests[r]&&(this.buffer[r]=this.options.placeholder)},writeBuffer:function(){return this.$element.val(this.buffer.joi
 n("")).val()},checkVal:function(e){var t=this.mask.length,n=this.$element.val(),r=-1;for(var i=0,s=0;i<t;i++)if(this.tests[i]){this.buffer[i]=this.options.placeholder;while(s++<n.length){var o=n.charAt(s-1);if(this.tests[i].test(o)){this.buffer[i]=o,r=i;break}}if(s>n.length)break}else this.buffer[i]==n.charAt(s)&&i!=this.partialPosition&&(s++,r=i);if(!e&&r+1<this.partialPosition)this.$element.val(""),this.clearBuffer(0,t);else if(e||r+1>=this.partialPosition)this.writeBuffer(),e||this.$element.val(this.$element.val().substring(0,r+1));return this.partialPosition?i:this.firstNonMaskPos}},e.fn.inputmask=function(t){return this.each(function(){var n=e(this),i=n.data("inputmask");i||n.data("inputmask",i=new r(this,t))})},e.fn.inputmask.defaults={mask:"",placeholder:"_",definitions:{9:"[0-9]",a:"[A-Za-z]","?":"[A-Za-z0-9]","*":"."}},e.fn.inputmask.Constructor=r,e(document).on("focus.inputmask.data-api","[data-mask]",function(t){var n=e(this);if(n.data("inputmask"))return;t.preventDefault
 (),n.inputmask(n.data())})}(window.jQuery),!function(e){"use strict";var t=function(t,n){n=e.extend({},e.fn.rowlink.defaults,n);var r=t.nodeName.toLowerCase()=="tr"?e(t):e(t).find("tr:has(td)");r.each(function(){var t=e(this).find(n.target).first();if(!t.length)return;var r=t.attr("href");e(this).find("td").not(".nolink").click(function(){window.location=r}),e(this).addClass("rowlink"),t.replaceWith(t.html())})};e.fn.rowlink=function(n){return this.each(function(){var r=e(this),i=r.data("rowlink");i||r.data("rowlink",i=new t(this,n))})},e.fn.rowlink.defaults={target:"a"},e.fn.rowlink.Constructor=t,e(function(){e('[data-provide="rowlink"],[data-provides="rowlink"]').each(function(){e(this).rowlink(e(this).data())})})}(window.jQuery),!function(e){"use strict";var t=function(t,n){this.$element=e(t),this.type=this.$element.data("uploadtype")||(this.$element.find(".thumbnail").length>0?"image":"file"),this.$input=this.$element.find(":file");if(this.$input.length===0)return;this.name=this
 .$input.attr("name")||n.name,this.$hidden=this.$element.find('input[type=hidden][name="'+this.name+'"]'),this.$hidden.length===0&&(this.$hidden=e('<input type="hidden" />'),this.$element.prepend(this.$hidden)),this.$preview=this.$element.find(".fileupload-preview");var r=this.$preview.css("height");this.$preview.css("display")!="inline"&&r!="0px"&&r!="none"&&this.$preview.css("line-height",r),this.original={exists:this.$element.hasClass("fileupload-exists"),preview:this.$preview.html(),hiddenVal:this.$hidden.val()},this.$remove=this.$element.find('[data-dismiss="fileupload"]'),this.$element.find('[data-trigger="fileupload"]').on("click.fileupload",e.proxy(this.trigger,this)),this.listen()};t.prototype={listen:function(){this.$input.on("change.fileupload",e.proxy(this.change,this)),e(this.$input[0].form).on("reset.fileupload",e.proxy(this.reset,this)),this.$remove&&this.$remove.on("click.fileupload",e.proxy(this.clear,this))},change:function(e,t){if(t==="clear")return;var n=e.target.
 files!==undefined?e.target.files[0]:e.target.value?{name:e.target.value.replace(/^.+\\/,"")}:null;if(!n){this.clear();return}this.$hidden.val(""),this.$hidden.attr("name",""),this.$input.attr("name",this.name);if(this.type==="image"&&this.$preview.length>0&&(typeof n.type!="undefined"?n.type.match("image.*"):n.name.match(/\.(gif|png|jpe?g)$/i))&&typeof FileReader!="undefined"){var r=new FileReader,i=this.$preview,s=this.$element;r.onload=function(e){i.html('<img src="'+e.target.result+'" '+(i.css("max-height")!="none"?'style="max-height: '+i.css("max-height")+';"':"")+" />"),s.addClass("fileupload-exists").removeClass("fileupload-new")},r.readAsDataURL(n)}else this.$preview.text(n.name),this.$element.addClass("fileupload-exists").removeClass("fileupload-new")},clear:function(e){this.$hidden.val(""),this.$hidden.attr("name",this.name),this.$input.attr("name","");if(navigator.userAgent.match(/msie/i)){var t=this.$input.clone(!0);this.$input.after(t),this.$input.remove(),this.$input=t}
 else this.$input.val("");this.$preview.html(""),this.$element.addClass("fileupload-new").removeClass("fileupload-exists"),e&&(this.$input.trigger("change",["clear"]),e.preventDefault())},reset:function(e){this.clear(),this.$hidden.val(this.original.hiddenVal),this.$preview.html(this.original.preview),this.original.exists?this.$element.addClass("fileupload-exists").removeClass("fileupload-new"):this.$element.addClass("fileupload-new").removeClass("fileupload-exists")},trigger:function(e){this.$input.trigger("click"),e.preventDefault()}},e.fn.fileupload=function(n){return this.each(function(){var r=e(this),i=r.data("fileupload");i||r.data("fileupload",i=new t(this,n)),typeof n=="string"&&i[n]()})},e.fn.fileupload.Constructor=t,e(document).on("click.fileupload.data-api",'[data-provides="fileupload"]',function(t){var n=e(this);if(n.data("fileupload"))return;n.fileupload(n.data());var r=e(t.target).closest('[data-dismiss="fileupload"],[data-trigger="fileupload"]');r.length>0&&(r.trigger(
 "click.fileupload"),t.preventDefault())})}(window.jQuery);
\ No newline at end of file


[17/51] [abbrv] [partial] Adding Jinwon's custom RCMET

Posted by jo...@apache.org.
http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/app/lib/angular/angular-loader.js
----------------------------------------------------------------------
diff --git a/src/main/ui/app/lib/angular/angular-loader.js b/src/main/ui/app/lib/angular/angular-loader.js
new file mode 100755
index 0000000..c4325dc
--- /dev/null
+++ b/src/main/ui/app/lib/angular/angular-loader.js
@@ -0,0 +1,276 @@
+/**
+ * @license AngularJS v1.0.5
+ * (c) 2010-2012 Google, Inc. http://angularjs.org
+ * License: MIT
+ */
+
+(
+
+/**
+ * @ngdoc interface
+ * @name angular.Module
+ * @description
+ *
+ * Interface for configuring angular {@link angular.module modules}.
+ */
+
+function setupModuleLoader(window) {
+
+  function ensure(obj, name, factory) {
+    return obj[name] || (obj[name] = factory());
+  }
+
+  return ensure(ensure(window, 'angular', Object), 'module', function() {
+    /** @type {Object.<string, angular.Module>} */
+    var modules = {};
+
+    /**
+     * @ngdoc function
+     * @name angular.module
+     * @description
+     *
+     * The `angular.module` is a global place for creating and registering Angular modules. All
+     * modules (angular core or 3rd party) that should be available to an application must be
+     * registered using this mechanism.
+     *
+     *
+     * # Module
+     *
+     * A module is a collocation of services, directives, filters, and configuration information. Module
+     * is used to configure the {@link AUTO.$injector $injector}.
+     *
+     * <pre>
+     * // Create a new module
+     * var myModule = angular.module('myModule', []);
+     *
+     * // register a new service
+     * myModule.value('appName', 'MyCoolApp');
+     *
+     * // configure existing services inside initialization blocks.
+     * myModule.config(function($locationProvider) {
+'use strict';
+     *   // Configure existing providers
+     *   $locationProvider.hashPrefix('!');
+     * });
+     * </pre>
+     *
+     * Then you can create an injector and load your modules like this:
+     *
+     * <pre>
+     * var injector = angular.injector(['ng', 'MyModule'])
+     * </pre>
+     *
+     * However it's more likely that you'll just use
+     * {@link ng.directive:ngApp ngApp} or
+     * {@link angular.bootstrap} to simplify this process for you.
+     *
+     * @param {!string} name The name of the module to create or retrieve.
+     * @param {Array.<string>=} requires If specified then new module is being created. If unspecified then the
+     *        the module is being retrieved for further configuration.
+     * @param {Function} configFn Optional configuration function for the module. Same as
+     *        {@link angular.Module#config Module#config()}.
+     * @returns {module} new module with the {@link angular.Module} api.
+     */
+    return function module(name, requires, configFn) {
+      if (requires && modules.hasOwnProperty(name)) {
+        modules[name] = null;
+      }
+      return ensure(modules, name, function() {
+        if (!requires) {
+          throw Error('No module: ' + name);
+        }
+
+        /** @type {!Array.<Array.<*>>} */
+        var invokeQueue = [];
+
+        /** @type {!Array.<Function>} */
+        var runBlocks = [];
+
+        var config = invokeLater('$injector', 'invoke');
+
+        /** @type {angular.Module} */
+        var moduleInstance = {
+          // Private state
+          _invokeQueue: invokeQueue,
+          _runBlocks: runBlocks,
+
+          /**
+           * @ngdoc property
+           * @name angular.Module#requires
+           * @propertyOf angular.Module
+           * @returns {Array.<string>} List of module names which must be loaded before this module.
+           * @description
+           * Holds the list of modules which the injector will load before the current module is loaded.
+           */
+          requires: requires,
+
+          /**
+           * @ngdoc property
+           * @name angular.Module#name
+           * @propertyOf angular.Module
+           * @returns {string} Name of the module.
+           * @description
+           */
+          name: name,
+
+
+          /**
+           * @ngdoc method
+           * @name angular.Module#provider
+           * @methodOf angular.Module
+           * @param {string} name service name
+           * @param {Function} providerType Construction function for creating new instance of the service.
+           * @description
+           * See {@link AUTO.$provide#provider $provide.provider()}.
+           */
+          provider: invokeLater('$provide', 'provider'),
+
+          /**
+           * @ngdoc method
+           * @name angular.Module#factory
+           * @methodOf angular.Module
+           * @param {string} name service name
+           * @param {Function} providerFunction Function for creating new instance of the service.
+           * @description
+           * See {@link AUTO.$provide#factory $provide.factory()}.
+           */
+          factory: invokeLater('$provide', 'factory'),
+
+          /**
+           * @ngdoc method
+           * @name angular.Module#service
+           * @methodOf angular.Module
+           * @param {string} name service name
+           * @param {Function} constructor A constructor function that will be instantiated.
+           * @description
+           * See {@link AUTO.$provide#service $provide.service()}.
+           */
+          service: invokeLater('$provide', 'service'),
+
+          /**
+           * @ngdoc method
+           * @name angular.Module#value
+           * @methodOf angular.Module
+           * @param {string} name service name
+           * @param {*} object Service instance object.
+           * @description
+           * See {@link AUTO.$provide#value $provide.value()}.
+           */
+          value: invokeLater('$provide', 'value'),
+
+          /**
+           * @ngdoc method
+           * @name angular.Module#constant
+           * @methodOf angular.Module
+           * @param {string} name constant name
+           * @param {*} object Constant value.
+           * @description
+           * Because the constant are fixed, they get applied before other provide methods.
+           * See {@link AUTO.$provide#constant $provide.constant()}.
+           */
+          constant: invokeLater('$provide', 'constant', 'unshift'),
+
+          /**
+           * @ngdoc method
+           * @name angular.Module#filter
+           * @methodOf angular.Module
+           * @param {string} name Filter name.
+           * @param {Function} filterFactory Factory function for creating new instance of filter.
+           * @description
+           * See {@link ng.$filterProvider#register $filterProvider.register()}.
+           */
+          filter: invokeLater('$filterProvider', 'register'),
+
+          /**
+           * @ngdoc method
+           * @name angular.Module#controller
+           * @methodOf angular.Module
+           * @param {string} name Controller name.
+           * @param {Function} constructor Controller constructor function.
+           * @description
+           * See {@link ng.$controllerProvider#register $controllerProvider.register()}.
+           */
+          controller: invokeLater('$controllerProvider', 'register'),
+
+          /**
+           * @ngdoc method
+           * @name angular.Module#directive
+           * @methodOf angular.Module
+           * @param {string} name directive name
+           * @param {Function} directiveFactory Factory function for creating new instance of
+           * directives.
+           * @description
+           * See {@link ng.$compileProvider#directive $compileProvider.directive()}.
+           */
+          directive: invokeLater('$compileProvider', 'directive'),
+
+          /**
+           * @ngdoc method
+           * @name angular.Module#config
+           * @methodOf angular.Module
+           * @param {Function} configFn Execute this function on module load. Useful for service
+           *    configuration.
+           * @description
+           * Use this method to register work which needs to be performed on module loading.
+           */
+          config: config,
+
+          /**
+           * @ngdoc method
+           * @name angular.Module#run
+           * @methodOf angular.Module
+           * @param {Function} initializationFn Execute this function after injector creation.
+           *    Useful for application initialization.
+           * @description
+           * Use this method to register work which should be performed when the injector is done
+           * loading all modules.
+           */
+          run: function(block) {
+            runBlocks.push(block);
+            return this;
+          }
+        };
+
+        if (configFn) {
+          config(configFn);
+        }
+
+        return  moduleInstance;
+
+        /**
+         * @param {string} provider
+         * @param {string} method
+         * @param {String=} insertMethod
+         * @returns {angular.Module}
+         */
+        function invokeLater(provider, method, insertMethod) {
+          return function() {
+            invokeQueue[insertMethod || 'push']([provider, method, arguments]);
+            return moduleInstance;
+          }
+        }
+      });
+    };
+  });
+
+}
+)(window);
+
+/**
+ * Closure compiler type information
+ *
+ * @typedef { {
+ *   requires: !Array.<string>,
+ *   invokeQueue: !Array.<Array.<*>>,
+ *
+ *   service: function(string, Function):angular.Module,
+ *   factory: function(string, Function):angular.Module,
+ *   value: function(string, *):angular.Module,
+ *
+ *   filter: function(string, Function):angular.Module,
+ *
+ *   init: function(Function):angular.Module
+ * } }
+ */
+angular.Module;
+

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/app/lib/angular/angular-loader.min.js
----------------------------------------------------------------------
diff --git a/src/main/ui/app/lib/angular/angular-loader.min.js b/src/main/ui/app/lib/angular/angular-loader.min.js
new file mode 100755
index 0000000..a264fbe
--- /dev/null
+++ b/src/main/ui/app/lib/angular/angular-loader.min.js
@@ -0,0 +1,7 @@
+/*
+ AngularJS v1.0.5
+ (c) 2010-2012 Google, Inc. http://angularjs.org
+ License: MIT
+*/
+(function(i){'use strict';function d(c,b,e){return c[b]||(c[b]=e())}return d(d(i,"angular",Object),"module",function(){var c={};return function(b,e,f){e&&c.hasOwnProperty(b)&&(c[b]=null);return d(c,b,function(){function a(a,b,d){return function(){c[d||"push"]([a,b,arguments]);return g}}if(!e)throw Error("No module: "+b);var c=[],d=[],h=a("$injector","invoke"),g={_invokeQueue:c,_runBlocks:d,requires:e,name:b,provider:a("$provide","provider"),factory:a("$provide","factory"),service:a("$provide","service"),
+value:a("$provide","value"),constant:a("$provide","constant","unshift"),filter:a("$filterProvider","register"),controller:a("$controllerProvider","register"),directive:a("$compileProvider","directive"),config:h,run:function(a){d.push(a);return this}};f&&h(f);return g})}})})(window);

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/app/lib/angular/angular-resource.js
----------------------------------------------------------------------
diff --git a/src/main/ui/app/lib/angular/angular-resource.js b/src/main/ui/app/lib/angular/angular-resource.js
new file mode 100755
index 0000000..a74c483
--- /dev/null
+++ b/src/main/ui/app/lib/angular/angular-resource.js
@@ -0,0 +1,445 @@
+/**
+ * @license AngularJS v1.0.5
+ * (c) 2010-2012 Google, Inc. http://angularjs.org
+ * License: MIT
+ */
+(function(window, angular, undefined) {
+'use strict';
+
+/**
+ * @ngdoc overview
+ * @name ngResource
+ * @description
+ */
+
+/**
+ * @ngdoc object
+ * @name ngResource.$resource
+ * @requires $http
+ *
+ * @description
+ * A factory which creates a resource object that lets you interact with
+ * [RESTful](http://en.wikipedia.org/wiki/Representational_State_Transfer) server-side data sources.
+ *
+ * The returned resource object has action methods which provide high-level behaviors without
+ * the need to interact with the low level {@link ng.$http $http} service.
+ *
+ * @param {string} url A parameterized URL template with parameters prefixed by `:` as in
+ *   `/user/:username`. If you are using a URL with a port number (e.g. 
+ *   `http://example.com:8080/api`), you'll need to escape the colon character before the port
+ *   number, like this: `$resource('http://example.com\\:8080/api')`.
+ *
+ * @param {Object=} paramDefaults Default values for `url` parameters. These can be overridden in
+ *   `actions` methods.
+ *
+ *   Each key value in the parameter object is first bound to url template if present and then any
+ *   excess keys are appended to the url search query after the `?`.
+ *
+ *   Given a template `/path/:verb` and parameter `{verb:'greet', salutation:'Hello'}` results in
+ *   URL `/path/greet?salutation=Hello`.
+ *
+ *   If the parameter value is prefixed with `@` then the value of that parameter is extracted from
+ *   the data object (useful for non-GET operations).
+ *
+ * @param {Object.<Object>=} actions Hash with declaration of custom action that should extend the
+ *   default set of resource actions. The declaration should be created in the following format:
+ *
+ *       {action1: {method:?, params:?, isArray:?},
+ *        action2: {method:?, params:?, isArray:?},
+ *        ...}
+ *
+ *   Where:
+ *
+ *   - `action` – {string} – The name of action. This name becomes the name of the method on your
+ *     resource object.
+ *   - `method` – {string} – HTTP request method. Valid methods are: `GET`, `POST`, `PUT`, `DELETE`,
+ *     and `JSONP`
+ *   - `params` – {object=} – Optional set of pre-bound parameters for this action.
+ *   - isArray – {boolean=} – If true then the returned object for this action is an array, see
+ *     `returns` section.
+ *
+ * @returns {Object} A resource "class" object with methods for the default set of resource actions
+ *   optionally extended with custom `actions`. The default set contains these actions:
+ *
+ *       { 'get':    {method:'GET'},
+ *         'save':   {method:'POST'},
+ *         'query':  {method:'GET', isArray:true},
+ *         'remove': {method:'DELETE'},
+ *         'delete': {method:'DELETE'} };
+ *
+ *   Calling these methods invoke an {@link ng.$http} with the specified http method,
+ *   destination and parameters. When the data is returned from the server then the object is an
+ *   instance of the resource class. The actions `save`, `remove` and `delete` are available on it
+ *   as  methods with the `$` prefix. This allows you to easily perform CRUD operations (create,
+ *   read, update, delete) on server-side data like this:
+ *   <pre>
+        var User = $resource('/user/:userId', {userId:'@id'});
+        var user = User.get({userId:123}, function() {
+          user.abc = true;
+          user.$save();
+        });
+     </pre>
+ *
+ *   It is important to realize that invoking a $resource object method immediately returns an
+ *   empty reference (object or array depending on `isArray`). Once the data is returned from the
+ *   server the existing reference is populated with the actual data. This is a useful trick since
+ *   usually the resource is assigned to a model which is then rendered by the view. Having an empty
+ *   object results in no rendering, once the data arrives from the server then the object is
+ *   populated with the data and the view automatically re-renders itself showing the new data. This
+ *   means that in most case one never has to write a callback function for the action methods.
+ *
+ *   The action methods on the class object or instance object can be invoked with the following
+ *   parameters:
+ *
+ *   - HTTP GET "class" actions: `Resource.action([parameters], [success], [error])`
+ *   - non-GET "class" actions: `Resource.action([parameters], postData, [success], [error])`
+ *   - non-GET instance actions:  `instance.$action([parameters], [success], [error])`
+ *
+ *
+ * @example
+ *
+ * # Credit card resource
+ *
+ * <pre>
+     // Define CreditCard class
+     var CreditCard = $resource('/user/:userId/card/:cardId',
+      {userId:123, cardId:'@id'}, {
+       charge: {method:'POST', params:{charge:true}}
+      });
+
+     // We can retrieve a collection from the server
+     var cards = CreditCard.query(function() {
+       // GET: /user/123/card
+       // server returns: [ {id:456, number:'1234', name:'Smith'} ];
+
+       var card = cards[0];
+       // each item is an instance of CreditCard
+       expect(card instanceof CreditCard).toEqual(true);
+       card.name = "J. Smith";
+       // non GET methods are mapped onto the instances
+       card.$save();
+       // POST: /user/123/card/456 {id:456, number:'1234', name:'J. Smith'}
+       // server returns: {id:456, number:'1234', name: 'J. Smith'};
+
+       // our custom method is mapped as well.
+       card.$charge({amount:9.99});
+       // POST: /user/123/card/456?amount=9.99&charge=true {id:456, number:'1234', name:'J. Smith'}
+     });
+
+     // we can create an instance as well
+     var newCard = new CreditCard({number:'0123'});
+     newCard.name = "Mike Smith";
+     newCard.$save();
+     // POST: /user/123/card {number:'0123', name:'Mike Smith'}
+     // server returns: {id:789, number:'01234', name: 'Mike Smith'};
+     expect(newCard.id).toEqual(789);
+ * </pre>
+ *
+ * The object returned from this function execution is a resource "class" which has "static" method
+ * for each action in the definition.
+ *
+ * Calling these methods invoke `$http` on the `url` template with the given `method` and `params`.
+ * When the data is returned from the server then the object is an instance of the resource type and
+ * all of the non-GET methods are available with `$` prefix. This allows you to easily support CRUD
+ * operations (create, read, update, delete) on server-side data.
+
+   <pre>
+     var User = $resource('/user/:userId', {userId:'@id'});
+     var user = User.get({userId:123}, function() {
+       user.abc = true;
+       user.$save();
+     });
+   </pre>
+ *
+ * It's worth noting that the success callback for `get`, `query` and other method gets passed
+ * in the response that came from the server as well as $http header getter function, so one
+ * could rewrite the above example and get access to http headers as:
+ *
+   <pre>
+     var User = $resource('/user/:userId', {userId:'@id'});
+     User.get({userId:123}, function(u, getResponseHeaders){
+       u.abc = true;
+       u.$save(function(u, putResponseHeaders) {
+         //u => saved user object
+         //putResponseHeaders => $http header getter
+       });
+     });
+   </pre>
+
+ * # Buzz client
+
+   Let's look at what a buzz client created with the `$resource` service looks like:
+    <doc:example>
+      <doc:source jsfiddle="false">
+       <script>
+         function BuzzController($resource) {
+           this.userId = 'googlebuzz';
+           this.Activity = $resource(
+             'https://www.googleapis.com/buzz/v1/activities/:userId/:visibility/:activityId/:comments',
+             {alt:'json', callback:'JSON_CALLBACK'},
+             {get:{method:'JSONP', params:{visibility:'@self'}}, replies: {method:'JSONP', params:{visibility:'@self', comments:'@comments'}}}
+           );
+         }
+
+         BuzzController.prototype = {
+           fetch: function() {
+             this.activities = this.Activity.get({userId:this.userId});
+           },
+           expandReplies: function(activity) {
+             activity.replies = this.Activity.replies({userId:this.userId, activityId:activity.id});
+           }
+         };
+         BuzzController.$inject = ['$resource'];
+       </script>
+
+       <div ng-controller="BuzzController">
+         <input ng-model="userId"/>
+         <button ng-click="fetch()">fetch</button>
+         <hr/>
+         <div ng-repeat="item in activities.data.items">
+           <h1 style="font-size: 15px;">
+             <img src="{{item.actor.thumbnailUrl}}" style="max-height:30px;max-width:30px;"/>
+             <a href="{{item.actor.profileUrl}}">{{item.actor.name}}</a>
+             <a href ng-click="expandReplies(item)" style="float: right;">Expand replies: {{item.links.replies[0].count}}</a>
+           </h1>
+           {{item.object.content | html}}
+           <div ng-repeat="reply in item.replies.data.items" style="margin-left: 20px;">
+             <img src="{{reply.actor.thumbnailUrl}}" style="max-height:30px;max-width:30px;"/>
+             <a href="{{reply.actor.profileUrl}}">{{reply.actor.name}}</a>: {{reply.content | html}}
+           </div>
+         </div>
+       </div>
+      </doc:source>
+      <doc:scenario>
+      </doc:scenario>
+    </doc:example>
+ */
+angular.module('ngResource', ['ng']).
+  factory('$resource', ['$http', '$parse', function($http, $parse) {
+    var DEFAULT_ACTIONS = {
+      'get':    {method:'GET'},
+      'save':   {method:'POST'},
+      'query':  {method:'GET', isArray:true},
+      'remove': {method:'DELETE'},
+      'delete': {method:'DELETE'}
+    };
+    var noop = angular.noop,
+        forEach = angular.forEach,
+        extend = angular.extend,
+        copy = angular.copy,
+        isFunction = angular.isFunction,
+        getter = function(obj, path) {
+          return $parse(path)(obj);
+        };
+
+    /**
+     * We need our custom method because encodeURIComponent is too aggressive and doesn't follow
+     * http://www.ietf.org/rfc/rfc3986.txt with regards to the character set (pchar) allowed in path
+     * segments:
+     *    segment       = *pchar
+     *    pchar         = unreserved / pct-encoded / sub-delims / ":" / "@"
+     *    pct-encoded   = "%" HEXDIG HEXDIG
+     *    unreserved    = ALPHA / DIGIT / "-" / "." / "_" / "~"
+     *    sub-delims    = "!" / "$" / "&" / "'" / "(" / ")"
+     *                     / "*" / "+" / "," / ";" / "="
+     */
+    function encodeUriSegment(val) {
+      return encodeUriQuery(val, true).
+        replace(/%26/gi, '&').
+        replace(/%3D/gi, '=').
+        replace(/%2B/gi, '+');
+    }
+
+
+    /**
+     * This method is intended for encoding *key* or *value* parts of query component. We need a custom
+     * method becuase encodeURIComponent is too agressive and encodes stuff that doesn't have to be
+     * encoded per http://tools.ietf.org/html/rfc3986:
+     *    query       = *( pchar / "/" / "?" )
+     *    pchar         = unreserved / pct-encoded / sub-delims / ":" / "@"
+     *    unreserved    = ALPHA / DIGIT / "-" / "." / "_" / "~"
+     *    pct-encoded   = "%" HEXDIG HEXDIG
+     *    sub-delims    = "!" / "$" / "&" / "'" / "(" / ")"
+     *                     / "*" / "+" / "," / ";" / "="
+     */
+    function encodeUriQuery(val, pctEncodeSpaces) {
+      return encodeURIComponent(val).
+        replace(/%40/gi, '@').
+        replace(/%3A/gi, ':').
+        replace(/%24/g, '$').
+        replace(/%2C/gi, ',').
+        replace((pctEncodeSpaces ? null : /%20/g), '+');
+    }
+
+    function Route(template, defaults) {
+      this.template = template = template + '#';
+      this.defaults = defaults || {};
+      var urlParams = this.urlParams = {};
+      forEach(template.split(/\W/), function(param){
+        if (param && (new RegExp("(^|[^\\\\]):" + param + "\\W").test(template))) {
+          urlParams[param] = true;
+        }
+      });
+      this.template = template.replace(/\\:/g, ':');
+    }
+
+    Route.prototype = {
+      url: function(params) {
+        var self = this,
+            url = this.template,
+            val,
+            encodedVal;
+
+        params = params || {};
+        forEach(this.urlParams, function(_, urlParam){
+          val = params.hasOwnProperty(urlParam) ? params[urlParam] : self.defaults[urlParam];
+          if (angular.isDefined(val) && val !== null) {
+            encodedVal = encodeUriSegment(val);
+            url = url.replace(new RegExp(":" + urlParam + "(\\W)", "g"), encodedVal + "$1");
+          } else {
+            url = url.replace(new RegExp("(\/?):" + urlParam + "(\\W)", "g"), function(match,
+                leadingSlashes, tail) {
+              if (tail.charAt(0) == '/') {
+                return tail;
+              } else {
+                return leadingSlashes + tail;
+              }
+            });
+          }
+        });
+        url = url.replace(/\/?#$/, '');
+        var query = [];
+        forEach(params, function(value, key){
+          if (!self.urlParams[key]) {
+            query.push(encodeUriQuery(key) + '=' + encodeUriQuery(value));
+          }
+        });
+        query.sort();
+        url = url.replace(/\/*$/, '');
+        return url + (query.length ? '?' + query.join('&') : '');
+      }
+    };
+
+
+    function ResourceFactory(url, paramDefaults, actions) {
+      var route = new Route(url);
+
+      actions = extend({}, DEFAULT_ACTIONS, actions);
+
+      function extractParams(data, actionParams){
+        var ids = {};
+        actionParams = extend({}, paramDefaults, actionParams);
+        forEach(actionParams, function(value, key){
+          ids[key] = value.charAt && value.charAt(0) == '@' ? getter(data, value.substr(1)) : value;
+        });
+        return ids;
+      }
+
+      function Resource(value){
+        copy(value || {}, this);
+      }
+
+      forEach(actions, function(action, name) {
+        action.method = angular.uppercase(action.method);
+        var hasBody = action.method == 'POST' || action.method == 'PUT' || action.method == 'PATCH';
+        Resource[name] = function(a1, a2, a3, a4) {
+          var params = {};
+          var data;
+          var success = noop;
+          var error = null;
+          switch(arguments.length) {
+          case 4:
+            error = a4;
+            success = a3;
+            //fallthrough
+          case 3:
+          case 2:
+            if (isFunction(a2)) {
+              if (isFunction(a1)) {
+                success = a1;
+                error = a2;
+                break;
+              }
+
+              success = a2;
+              error = a3;
+              //fallthrough
+            } else {
+              params = a1;
+              data = a2;
+              success = a3;
+              break;
+            }
+          case 1:
+            if (isFunction(a1)) success = a1;
+            else if (hasBody) data = a1;
+            else params = a1;
+            break;
+          case 0: break;
+          default:
+            throw "Expected between 0-4 arguments [params, data, success, error], got " +
+              arguments.length + " arguments.";
+          }
+
+          var value = this instanceof Resource ? this : (action.isArray ? [] : new Resource(data));
+          $http({
+            method: action.method,
+            url: route.url(extend({}, extractParams(data, action.params || {}), params)),
+            data: data
+          }).then(function(response) {
+              var data = response.data;
+
+              if (data) {
+                if (action.isArray) {
+                  value.length = 0;
+                  forEach(data, function(item) {
+                    value.push(new Resource(item));
+                  });
+                } else {
+                  copy(data, value);
+                }
+              }
+              (success||noop)(value, response.headers);
+            }, error);
+
+          return value;
+        };
+
+
+        Resource.prototype['$' + name] = function(a1, a2, a3) {
+          var params = extractParams(this),
+              success = noop,
+              error;
+
+          switch(arguments.length) {
+          case 3: params = a1; success = a2; error = a3; break;
+          case 2:
+          case 1:
+            if (isFunction(a1)) {
+              success = a1;
+              error = a2;
+            } else {
+              params = a1;
+              success = a2 || noop;
+            }
+          case 0: break;
+          default:
+            throw "Expected between 1-3 arguments [params, success, error], got " +
+              arguments.length + " arguments.";
+          }
+          var data = hasBody ? this : undefined;
+          Resource[name].call(this, params, data, success, error);
+        };
+      });
+
+      Resource.bind = function(additionalParamDefaults){
+        return ResourceFactory(url, extend({}, paramDefaults, additionalParamDefaults), actions);
+      };
+
+      return Resource;
+    }
+
+    return ResourceFactory;
+  }]);
+
+})(window, window.angular);

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/app/lib/angular/angular-resource.min.js
----------------------------------------------------------------------
diff --git a/src/main/ui/app/lib/angular/angular-resource.min.js b/src/main/ui/app/lib/angular/angular-resource.min.js
new file mode 100755
index 0000000..f37559c
--- /dev/null
+++ b/src/main/ui/app/lib/angular/angular-resource.min.js
@@ -0,0 +1,10 @@
+/*
+ AngularJS v1.0.5
+ (c) 2010-2012 Google, Inc. http://angularjs.org
+ License: MIT
+*/
+(function(C,d,w){'use strict';d.module("ngResource",["ng"]).factory("$resource",["$http","$parse",function(x,y){function s(b,e){return encodeURIComponent(b).replace(/%40/gi,"@").replace(/%3A/gi,":").replace(/%24/g,"$").replace(/%2C/gi,",").replace(e?null:/%20/g,"+")}function t(b,e){this.template=b+="#";this.defaults=e||{};var a=this.urlParams={};h(b.split(/\W/),function(f){f&&RegExp("(^|[^\\\\]):"+f+"\\W").test(b)&&(a[f]=!0)});this.template=b.replace(/\\:/g,":")}function u(b,e,a){function f(m,a){var b=
+{},a=o({},e,a);h(a,function(a,z){var c;a.charAt&&a.charAt(0)=="@"?(c=a.substr(1),c=y(c)(m)):c=a;b[z]=c});return b}function g(a){v(a||{},this)}var k=new t(b),a=o({},A,a);h(a,function(a,b){a.method=d.uppercase(a.method);var e=a.method=="POST"||a.method=="PUT"||a.method=="PATCH";g[b]=function(b,c,d,B){var j={},i,l=p,q=null;switch(arguments.length){case 4:q=B,l=d;case 3:case 2:if(r(c)){if(r(b)){l=b;q=c;break}l=c;q=d}else{j=b;i=c;l=d;break}case 1:r(b)?l=b:e?i=b:j=b;break;case 0:break;default:throw"Expected between 0-4 arguments [params, data, success, error], got "+
+arguments.length+" arguments.";}var n=this instanceof g?this:a.isArray?[]:new g(i);x({method:a.method,url:k.url(o({},f(i,a.params||{}),j)),data:i}).then(function(b){var c=b.data;if(c)a.isArray?(n.length=0,h(c,function(a){n.push(new g(a))})):v(c,n);(l||p)(n,b.headers)},q);return n};g.prototype["$"+b]=function(a,d,h){var m=f(this),j=p,i;switch(arguments.length){case 3:m=a;j=d;i=h;break;case 2:case 1:r(a)?(j=a,i=d):(m=a,j=d||p);case 0:break;default:throw"Expected between 1-3 arguments [params, success, error], got "+
+arguments.length+" arguments.";}g[b].call(this,m,e?this:w,j,i)}});g.bind=function(d){return u(b,o({},e,d),a)};return g}var A={get:{method:"GET"},save:{method:"POST"},query:{method:"GET",isArray:!0},remove:{method:"DELETE"},"delete":{method:"DELETE"}},p=d.noop,h=d.forEach,o=d.extend,v=d.copy,r=d.isFunction;t.prototype={url:function(b){var e=this,a=this.template,f,g,b=b||{};h(this.urlParams,function(h,c){f=b.hasOwnProperty(c)?b[c]:e.defaults[c];d.isDefined(f)&&f!==null?(g=s(f,!0).replace(/%26/gi,"&").replace(/%3D/gi,
+"=").replace(/%2B/gi,"+"),a=a.replace(RegExp(":"+c+"(\\W)","g"),g+"$1")):a=a.replace(RegExp("(/?):"+c+"(\\W)","g"),function(a,b,c){return c.charAt(0)=="/"?c:b+c})});var a=a.replace(/\/?#$/,""),k=[];h(b,function(a,b){e.urlParams[b]||k.push(s(b)+"="+s(a))});k.sort();a=a.replace(/\/*$/,"");return a+(k.length?"?"+k.join("&"):"")}};return u}])})(window,window.angular);

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/app/lib/angular/angular-sanitize.js
----------------------------------------------------------------------
diff --git a/src/main/ui/app/lib/angular/angular-sanitize.js b/src/main/ui/app/lib/angular/angular-sanitize.js
new file mode 100755
index 0000000..39e72bf
--- /dev/null
+++ b/src/main/ui/app/lib/angular/angular-sanitize.js
@@ -0,0 +1,535 @@
+/**
+ * @license AngularJS v1.0.5
+ * (c) 2010-2012 Google, Inc. http://angularjs.org
+ * License: MIT
+ */
+(function(window, angular, undefined) {
+'use strict';
+
+/**
+ * @ngdoc overview
+ * @name ngSanitize
+ * @description
+ */
+
+/*
+ * HTML Parser By Misko Hevery (misko@hevery.com)
+ * based on:  HTML Parser By John Resig (ejohn.org)
+ * Original code by Erik Arvidsson, Mozilla Public License
+ * http://erik.eae.net/simplehtmlparser/simplehtmlparser.js
+ *
+ * // Use like so:
+ * htmlParser(htmlString, {
+ *     start: function(tag, attrs, unary) {},
+ *     end: function(tag) {},
+ *     chars: function(text) {},
+ *     comment: function(text) {}
+ * });
+ *
+ */
+
+
+/**
+ * @ngdoc service
+ * @name ngSanitize.$sanitize
+ * @function
+ *
+ * @description
+ *   The input is sanitized by parsing the html into tokens. All safe tokens (from a whitelist) are
+ *   then serialized back to properly escaped html string. This means that no unsafe input can make
+ *   it into the returned string, however, since our parser is more strict than a typical browser
+ *   parser, it's possible that some obscure input, which would be recognized as valid HTML by a
+ *   browser, won't make it through the sanitizer.
+ *
+ * @param {string} html Html input.
+ * @returns {string} Sanitized html.
+ *
+ * @example
+   <doc:example module="ngSanitize">
+     <doc:source>
+       <script>
+         function Ctrl($scope) {
+           $scope.snippet =
+             '<p style="color:blue">an html\n' +
+             '<em onmouseover="this.textContent=\'PWN3D!\'">click here</em>\n' +
+             'snippet</p>';
+         }
+       </script>
+       <div ng-controller="Ctrl">
+          Snippet: <textarea ng-model="snippet" cols="60" rows="3"></textarea>
+           <table>
+             <tr>
+               <td>Filter</td>
+               <td>Source</td>
+               <td>Rendered</td>
+             </tr>
+             <tr id="html-filter">
+               <td>html filter</td>
+               <td>
+                 <pre>&lt;div ng-bind-html="snippet"&gt;<br/>&lt;/div&gt;</pre>
+               </td>
+               <td>
+                 <div ng-bind-html="snippet"></div>
+               </td>
+             </tr>
+             <tr id="escaped-html">
+               <td>no filter</td>
+               <td><pre>&lt;div ng-bind="snippet"&gt;<br/>&lt;/div&gt;</pre></td>
+               <td><div ng-bind="snippet"></div></td>
+             </tr>
+             <tr id="html-unsafe-filter">
+               <td>unsafe html filter</td>
+               <td><pre>&lt;div ng-bind-html-unsafe="snippet"&gt;<br/>&lt;/div&gt;</pre></td>
+               <td><div ng-bind-html-unsafe="snippet"></div></td>
+             </tr>
+           </table>
+         </div>
+     </doc:source>
+     <doc:scenario>
+       it('should sanitize the html snippet ', function() {
+         expect(using('#html-filter').element('div').html()).
+           toBe('<p>an html\n<em>click here</em>\nsnippet</p>');
+       });
+
+       it('should escape snippet without any filter', function() {
+         expect(using('#escaped-html').element('div').html()).
+           toBe("&lt;p style=\"color:blue\"&gt;an html\n" +
+                "&lt;em onmouseover=\"this.textContent='PWN3D!'\"&gt;click here&lt;/em&gt;\n" +
+                "snippet&lt;/p&gt;");
+       });
+
+       it('should inline raw snippet if filtered as unsafe', function() {
+         expect(using('#html-unsafe-filter').element("div").html()).
+           toBe("<p style=\"color:blue\">an html\n" +
+                "<em onmouseover=\"this.textContent='PWN3D!'\">click here</em>\n" +
+                "snippet</p>");
+       });
+
+       it('should update', function() {
+         input('snippet').enter('new <b>text</b>');
+         expect(using('#html-filter').binding('snippet')).toBe('new <b>text</b>');
+         expect(using('#escaped-html').element('div').html()).toBe("new &lt;b&gt;text&lt;/b&gt;");
+         expect(using('#html-unsafe-filter').binding("snippet")).toBe('new <b>text</b>');
+       });
+     </doc:scenario>
+   </doc:example>
+ */
+var $sanitize = function(html) {
+  var buf = [];
+    htmlParser(html, htmlSanitizeWriter(buf));
+    return buf.join('');
+};
+
+
+// Regular Expressions for parsing tags and attributes
+var START_TAG_REGEXP = /^<\s*([\w:-]+)((?:\s+[\w:-]+(?:\s*=\s*(?:(?:"[^"]*")|(?:'[^']*')|[^>\s]+))?)*)\s*(\/?)\s*>/,
+  END_TAG_REGEXP = /^<\s*\/\s*([\w:-]+)[^>]*>/,
+  ATTR_REGEXP = /([\w:-]+)(?:\s*=\s*(?:(?:"((?:[^"])*)")|(?:'((?:[^'])*)')|([^>\s]+)))?/g,
+  BEGIN_TAG_REGEXP = /^</,
+  BEGING_END_TAGE_REGEXP = /^<\s*\//,
+  COMMENT_REGEXP = /<!--(.*?)-->/g,
+  CDATA_REGEXP = /<!\[CDATA\[(.*?)]]>/g,
+  URI_REGEXP = /^((ftp|https?):\/\/|mailto:|#)/,
+  NON_ALPHANUMERIC_REGEXP = /([^\#-~| |!])/g; // Match everything outside of normal chars and " (quote character)
+
+
+// Good source of info about elements and attributes
+// http://dev.w3.org/html5/spec/Overview.html#semantics
+// http://simon.html5.org/html-elements
+
+// Safe Void Elements - HTML5
+// http://dev.w3.org/html5/spec/Overview.html#void-elements
+var voidElements = makeMap("area,br,col,hr,img,wbr");
+
+// Elements that you can, intentionally, leave open (and which close themselves)
+// http://dev.w3.org/html5/spec/Overview.html#optional-tags
+var optionalEndTagBlockElements = makeMap("colgroup,dd,dt,li,p,tbody,td,tfoot,th,thead,tr"),
+    optionalEndTagInlineElements = makeMap("rp,rt"),
+    optionalEndTagElements = angular.extend({}, optionalEndTagInlineElements, optionalEndTagBlockElements);
+
+// Safe Block Elements - HTML5
+var blockElements = angular.extend({}, optionalEndTagBlockElements, makeMap("address,article,aside," +
+        "blockquote,caption,center,del,dir,div,dl,figure,figcaption,footer,h1,h2,h3,h4,h5,h6," +
+        "header,hgroup,hr,ins,map,menu,nav,ol,pre,script,section,table,ul"));
+
+// Inline Elements - HTML5
+var inlineElements = angular.extend({}, optionalEndTagInlineElements, makeMap("a,abbr,acronym,b,bdi,bdo," +
+        "big,br,cite,code,del,dfn,em,font,i,img,ins,kbd,label,map,mark,q,ruby,rp,rt,s,samp,small," +
+        "span,strike,strong,sub,sup,time,tt,u,var"));
+
+
+// Special Elements (can contain anything)
+var specialElements = makeMap("script,style");
+
+var validElements = angular.extend({}, voidElements, blockElements, inlineElements, optionalEndTagElements);
+
+//Attributes that have href and hence need to be sanitized
+var uriAttrs = makeMap("background,cite,href,longdesc,src,usemap");
+var validAttrs = angular.extend({}, uriAttrs, makeMap(
+    'abbr,align,alt,axis,bgcolor,border,cellpadding,cellspacing,class,clear,'+
+    'color,cols,colspan,compact,coords,dir,face,headers,height,hreflang,hspace,'+
+    'ismap,lang,language,nohref,nowrap,rel,rev,rows,rowspan,rules,'+
+    'scope,scrolling,shape,span,start,summary,target,title,type,'+
+    'valign,value,vspace,width'));
+
+function makeMap(str) {
+  var obj = {}, items = str.split(','), i;
+  for (i = 0; i < items.length; i++) obj[items[i]] = true;
+  return obj;
+}
+
+
+/**
+ * @example
+ * htmlParser(htmlString, {
+ *     start: function(tag, attrs, unary) {},
+ *     end: function(tag) {},
+ *     chars: function(text) {},
+ *     comment: function(text) {}
+ * });
+ *
+ * @param {string} html string
+ * @param {object} handler
+ */
+function htmlParser( html, handler ) {
+  var index, chars, match, stack = [], last = html;
+  stack.last = function() { return stack[ stack.length - 1 ]; };
+
+  while ( html ) {
+    chars = true;
+
+    // Make sure we're not in a script or style element
+    if ( !stack.last() || !specialElements[ stack.last() ] ) {
+
+      // Comment
+      if ( html.indexOf("<!--") === 0 ) {
+        index = html.indexOf("-->");
+
+        if ( index >= 0 ) {
+          if (handler.comment) handler.comment( html.substring( 4, index ) );
+          html = html.substring( index + 3 );
+          chars = false;
+        }
+
+      // end tag
+      } else if ( BEGING_END_TAGE_REGEXP.test(html) ) {
+        match = html.match( END_TAG_REGEXP );
+
+        if ( match ) {
+          html = html.substring( match[0].length );
+          match[0].replace( END_TAG_REGEXP, parseEndTag );
+          chars = false;
+        }
+
+      // start tag
+      } else if ( BEGIN_TAG_REGEXP.test(html) ) {
+        match = html.match( START_TAG_REGEXP );
+
+        if ( match ) {
+          html = html.substring( match[0].length );
+          match[0].replace( START_TAG_REGEXP, parseStartTag );
+          chars = false;
+        }
+      }
+
+      if ( chars ) {
+        index = html.indexOf("<");
+
+        var text = index < 0 ? html : html.substring( 0, index );
+        html = index < 0 ? "" : html.substring( index );
+
+        if (handler.chars) handler.chars( decodeEntities(text) );
+      }
+
+    } else {
+      html = html.replace(new RegExp("(.*)<\\s*\\/\\s*" + stack.last() + "[^>]*>", 'i'), function(all, text){
+        text = text.
+          replace(COMMENT_REGEXP, "$1").
+          replace(CDATA_REGEXP, "$1");
+
+        if (handler.chars) handler.chars( decodeEntities(text) );
+
+        return "";
+      });
+
+      parseEndTag( "", stack.last() );
+    }
+
+    if ( html == last ) {
+      throw "Parse Error: " + html;
+    }
+    last = html;
+  }
+
+  // Clean up any remaining tags
+  parseEndTag();
+
+  function parseStartTag( tag, tagName, rest, unary ) {
+    tagName = angular.lowercase(tagName);
+    if ( blockElements[ tagName ] ) {
+      while ( stack.last() && inlineElements[ stack.last() ] ) {
+        parseEndTag( "", stack.last() );
+      }
+    }
+
+    if ( optionalEndTagElements[ tagName ] && stack.last() == tagName ) {
+      parseEndTag( "", tagName );
+    }
+
+    unary = voidElements[ tagName ] || !!unary;
+
+    if ( !unary )
+      stack.push( tagName );
+
+    var attrs = {};
+
+    rest.replace(ATTR_REGEXP, function(match, name, doubleQuotedValue, singleQoutedValue, unqoutedValue) {
+      var value = doubleQuotedValue
+        || singleQoutedValue
+        || unqoutedValue
+        || '';
+
+      attrs[name] = decodeEntities(value);
+    });
+    if (handler.start) handler.start( tagName, attrs, unary );
+  }
+
+  function parseEndTag( tag, tagName ) {
+    var pos = 0, i;
+    tagName = angular.lowercase(tagName);
+    if ( tagName )
+      // Find the closest opened tag of the same type
+      for ( pos = stack.length - 1; pos >= 0; pos-- )
+        if ( stack[ pos ] == tagName )
+          break;
+
+    if ( pos >= 0 ) {
+      // Close all the open elements, up the stack
+      for ( i = stack.length - 1; i >= pos; i-- )
+        if (handler.end) handler.end( stack[ i ] );
+
+      // Remove the open elements from the stack
+      stack.length = pos;
+    }
+  }
+}
+
+/**
+ * decodes all entities into regular string
+ * @param value
+ * @returns {string} A string with decoded entities.
+ */
+var hiddenPre=document.createElement("pre");
+function decodeEntities(value) {
+  hiddenPre.innerHTML=value.replace(/</g,"&lt;");
+  return hiddenPre.innerText || hiddenPre.textContent || '';
+}
+
+/**
+ * Escapes all potentially dangerous characters, so that the
+ * resulting string can be safely inserted into attribute or
+ * element text.
+ * @param value
+ * @returns escaped text
+ */
+function encodeEntities(value) {
+  return value.
+    replace(/&/g, '&amp;').
+    replace(NON_ALPHANUMERIC_REGEXP, function(value){
+      return '&#' + value.charCodeAt(0) + ';';
+    }).
+    replace(/</g, '&lt;').
+    replace(/>/g, '&gt;');
+}
+
+/**
+ * create an HTML/XML writer which writes to buffer
+ * @param {Array} buf use buf.jain('') to get out sanitized html string
+ * @returns {object} in the form of {
+ *     start: function(tag, attrs, unary) {},
+ *     end: function(tag) {},
+ *     chars: function(text) {},
+ *     comment: function(text) {}
+ * }
+ */
+function htmlSanitizeWriter(buf){
+  var ignore = false;
+  var out = angular.bind(buf, buf.push);
+  return {
+    start: function(tag, attrs, unary){
+      tag = angular.lowercase(tag);
+      if (!ignore && specialElements[tag]) {
+        ignore = tag;
+      }
+      if (!ignore && validElements[tag] == true) {
+        out('<');
+        out(tag);
+        angular.forEach(attrs, function(value, key){
+          var lkey=angular.lowercase(key);
+          if (validAttrs[lkey]==true && (uriAttrs[lkey]!==true || value.match(URI_REGEXP))) {
+            out(' ');
+            out(key);
+            out('="');
+            out(encodeEntities(value));
+            out('"');
+          }
+        });
+        out(unary ? '/>' : '>');
+      }
+    },
+    end: function(tag){
+        tag = angular.lowercase(tag);
+        if (!ignore && validElements[tag] == true) {
+          out('</');
+          out(tag);
+          out('>');
+        }
+        if (tag == ignore) {
+          ignore = false;
+        }
+      },
+    chars: function(chars){
+        if (!ignore) {
+          out(encodeEntities(chars));
+        }
+      }
+  };
+}
+
+
+// define ngSanitize module and register $sanitize service
+angular.module('ngSanitize', []).value('$sanitize', $sanitize);
+
+/**
+ * @ngdoc directive
+ * @name ngSanitize.directive:ngBindHtml
+ *
+ * @description
+ * Creates a binding that will sanitize the result of evaluating the `expression` with the
+ * {@link ngSanitize.$sanitize $sanitize} service and innerHTML the result into the current element.
+ *
+ * See {@link ngSanitize.$sanitize $sanitize} docs for examples.
+ *
+ * @element ANY
+ * @param {expression} ngBindHtml {@link guide/expression Expression} to evaluate.
+ */
+angular.module('ngSanitize').directive('ngBindHtml', ['$sanitize', function($sanitize) {
+  return function(scope, element, attr) {
+    element.addClass('ng-binding').data('$binding', attr.ngBindHtml);
+    scope.$watch(attr.ngBindHtml, function ngBindHtmlWatchAction(value) {
+      value = $sanitize(value);
+      element.html(value || '');
+    });
+  };
+}]);
+/**
+ * @ngdoc filter
+ * @name ngSanitize.filter:linky
+ * @function
+ *
+ * @description
+ *   Finds links in text input and turns them into html links. Supports http/https/ftp/mailto and
+ *   plain email address links.
+ *
+ * @param {string} text Input text.
+ * @returns {string} Html-linkified text.
+ *
+ * @usage
+   <span ng-bind-html="linky_expression | linky"></span>
+ *
+ * @example
+   <doc:example module="ngSanitize">
+     <doc:source>
+       <script>
+         function Ctrl($scope) {
+           $scope.snippet =
+             'Pretty text with some links:\n'+
+             'http://angularjs.org/,\n'+
+             'mailto:us@somewhere.org,\n'+
+             'another@somewhere.org,\n'+
+             'and one more: ftp://127.0.0.1/.';
+         }
+       </script>
+       <div ng-controller="Ctrl">
+       Snippet: <textarea ng-model="snippet" cols="60" rows="3"></textarea>
+       <table>
+         <tr>
+           <td>Filter</td>
+           <td>Source</td>
+           <td>Rendered</td>
+         </tr>
+         <tr id="linky-filter">
+           <td>linky filter</td>
+           <td>
+             <pre>&lt;div ng-bind-html="snippet | linky"&gt;<br>&lt;/div&gt;</pre>
+           </td>
+           <td>
+             <div ng-bind-html="snippet | linky"></div>
+           </td>
+         </tr>
+         <tr id="escaped-html">
+           <td>no filter</td>
+           <td><pre>&lt;div ng-bind="snippet"&gt;<br>&lt;/div&gt;</pre></td>
+           <td><div ng-bind="snippet"></div></td>
+         </tr>
+       </table>
+     </doc:source>
+     <doc:scenario>
+       it('should linkify the snippet with urls', function() {
+         expect(using('#linky-filter').binding('snippet | linky')).
+           toBe('Pretty text with some links:&#10;' +
+                '<a href="http://angularjs.org/">http://angularjs.org/</a>,&#10;' +
+                '<a href="mailto:us@somewhere.org">us@somewhere.org</a>,&#10;' +
+                '<a href="mailto:another@somewhere.org">another@somewhere.org</a>,&#10;' +
+                'and one more: <a href="ftp://127.0.0.1/">ftp://127.0.0.1/</a>.');
+       });
+
+       it ('should not linkify snippet without the linky filter', function() {
+         expect(using('#escaped-html').binding('snippet')).
+           toBe("Pretty text with some links:\n" +
+                "http://angularjs.org/,\n" +
+                "mailto:us@somewhere.org,\n" +
+                "another@somewhere.org,\n" +
+                "and one more: ftp://127.0.0.1/.");
+       });
+
+       it('should update', function() {
+         input('snippet').enter('new http://link.');
+         expect(using('#linky-filter').binding('snippet | linky')).
+           toBe('new <a href="http://link">http://link</a>.');
+         expect(using('#escaped-html').binding('snippet')).toBe('new http://link.');
+       });
+     </doc:scenario>
+   </doc:example>
+ */
+angular.module('ngSanitize').filter('linky', function() {
+  var LINKY_URL_REGEXP = /((ftp|https?):\/\/|(mailto:)?[A-Za-z0-9._%+-]+@)\S*[^\s\.\;\,\(\)\{\}\<\>]/,
+      MAILTO_REGEXP = /^mailto:/;
+
+  return function(text) {
+    if (!text) return text;
+    var match;
+    var raw = text;
+    var html = [];
+    // TODO(vojta): use $sanitize instead
+    var writer = htmlSanitizeWriter(html);
+    var url;
+    var i;
+    while ((match = raw.match(LINKY_URL_REGEXP))) {
+      // We can not end in these as they are sometimes found at the end of the sentence
+      url = match[0];
+      // if we did not match ftp/http/mailto then assume mailto
+      if (match[2] == match[3]) url = 'mailto:' + url;
+      i = match.index;
+      writer.chars(raw.substr(0, i));
+      writer.start('a', {href:url});
+      writer.chars(match[0].replace(MAILTO_REGEXP, ''));
+      writer.end('a');
+      raw = raw.substring(i + match[0].length);
+    }
+    writer.chars(raw);
+    return html.join('');
+  };
+});
+
+})(window, window.angular);

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/app/lib/angular/angular-sanitize.min.js
----------------------------------------------------------------------
diff --git a/src/main/ui/app/lib/angular/angular-sanitize.min.js b/src/main/ui/app/lib/angular/angular-sanitize.min.js
new file mode 100755
index 0000000..212a90a
--- /dev/null
+++ b/src/main/ui/app/lib/angular/angular-sanitize.min.js
@@ -0,0 +1,13 @@
+/*
+ AngularJS v1.0.5
+ (c) 2010-2012 Google, Inc. http://angularjs.org
+ License: MIT
+*/
+(function(I,g){'use strict';function i(a){var d={},a=a.split(","),b;for(b=0;b<a.length;b++)d[a[b]]=!0;return d}function z(a,d){function b(a,b,c,h){b=g.lowercase(b);if(m[b])for(;f.last()&&n[f.last()];)e("",f.last());o[b]&&f.last()==b&&e("",b);(h=p[b]||!!h)||f.push(b);var j={};c.replace(A,function(a,b,d,e,c){j[b]=k(d||e||c||"")});d.start&&d.start(b,j,h)}function e(a,b){var e=0,c;if(b=g.lowercase(b))for(e=f.length-1;e>=0;e--)if(f[e]==b)break;if(e>=0){for(c=f.length-1;c>=e;c--)d.end&&d.end(f[c]);f.length=
+e}}var c,h,f=[],j=a;for(f.last=function(){return f[f.length-1]};a;){h=!0;if(!f.last()||!q[f.last()]){if(a.indexOf("<\!--")===0)c=a.indexOf("--\>"),c>=0&&(d.comment&&d.comment(a.substring(4,c)),a=a.substring(c+3),h=!1);else if(B.test(a)){if(c=a.match(r))a=a.substring(c[0].length),c[0].replace(r,e),h=!1}else if(C.test(a)&&(c=a.match(s)))a=a.substring(c[0].length),c[0].replace(s,b),h=!1;h&&(c=a.indexOf("<"),h=c<0?a:a.substring(0,c),a=c<0?"":a.substring(c),d.chars&&d.chars(k(h)))}else a=a.replace(RegExp("(.*)<\\s*\\/\\s*"+
+f.last()+"[^>]*>","i"),function(b,a){a=a.replace(D,"$1").replace(E,"$1");d.chars&&d.chars(k(a));return""}),e("",f.last());if(a==j)throw"Parse Error: "+a;j=a}e()}function k(a){l.innerHTML=a.replace(/</g,"&lt;");return l.innerText||l.textContent||""}function t(a){return a.replace(/&/g,"&amp;").replace(F,function(a){return"&#"+a.charCodeAt(0)+";"}).replace(/</g,"&lt;").replace(/>/g,"&gt;")}function u(a){var d=!1,b=g.bind(a,a.push);return{start:function(a,c,h){a=g.lowercase(a);!d&&q[a]&&(d=a);!d&&v[a]==
+!0&&(b("<"),b(a),g.forEach(c,function(a,c){var e=g.lowercase(c);if(G[e]==!0&&(w[e]!==!0||a.match(H)))b(" "),b(c),b('="'),b(t(a)),b('"')}),b(h?"/>":">"))},end:function(a){a=g.lowercase(a);!d&&v[a]==!0&&(b("</"),b(a),b(">"));a==d&&(d=!1)},chars:function(a){d||b(t(a))}}}var s=/^<\s*([\w:-]+)((?:\s+[\w:-]+(?:\s*=\s*(?:(?:"[^"]*")|(?:'[^']*')|[^>\s]+))?)*)\s*(\/?)\s*>/,r=/^<\s*\/\s*([\w:-]+)[^>]*>/,A=/([\w:-]+)(?:\s*=\s*(?:(?:"((?:[^"])*)")|(?:'((?:[^'])*)')|([^>\s]+)))?/g,C=/^</,B=/^<\s*\//,D=/<\!--(.*?)--\>/g,
+E=/<!\[CDATA\[(.*?)]]\>/g,H=/^((ftp|https?):\/\/|mailto:|#)/,F=/([^\#-~| |!])/g,p=i("area,br,col,hr,img,wbr"),x=i("colgroup,dd,dt,li,p,tbody,td,tfoot,th,thead,tr"),y=i("rp,rt"),o=g.extend({},y,x),m=g.extend({},x,i("address,article,aside,blockquote,caption,center,del,dir,div,dl,figure,figcaption,footer,h1,h2,h3,h4,h5,h6,header,hgroup,hr,ins,map,menu,nav,ol,pre,script,section,table,ul")),n=g.extend({},y,i("a,abbr,acronym,b,bdi,bdo,big,br,cite,code,del,dfn,em,font,i,img,ins,kbd,label,map,mark,q,ruby,rp,rt,s,samp,small,span,strike,strong,sub,sup,time,tt,u,var")),
+q=i("script,style"),v=g.extend({},p,m,n,o),w=i("background,cite,href,longdesc,src,usemap"),G=g.extend({},w,i("abbr,align,alt,axis,bgcolor,border,cellpadding,cellspacing,class,clear,color,cols,colspan,compact,coords,dir,face,headers,height,hreflang,hspace,ismap,lang,language,nohref,nowrap,rel,rev,rows,rowspan,rules,scope,scrolling,shape,span,start,summary,target,title,type,valign,value,vspace,width")),l=document.createElement("pre");g.module("ngSanitize",[]).value("$sanitize",function(a){var d=[];
+z(a,u(d));return d.join("")});g.module("ngSanitize").directive("ngBindHtml",["$sanitize",function(a){return function(d,b,e){b.addClass("ng-binding").data("$binding",e.ngBindHtml);d.$watch(e.ngBindHtml,function(c){c=a(c);b.html(c||"")})}}]);g.module("ngSanitize").filter("linky",function(){var a=/((ftp|https?):\/\/|(mailto:)?[A-Za-z0-9._%+-]+@)\S*[^\s\.\;\,\(\)\{\}\<\>]/,d=/^mailto:/;return function(b){if(!b)return b;for(var e=b,c=[],h=u(c),f,g;b=e.match(a);)f=b[0],b[2]==b[3]&&(f="mailto:"+f),g=b.index,
+h.chars(e.substr(0,g)),h.start("a",{href:f}),h.chars(b[0].replace(d,"")),h.end("a"),e=e.substring(g+b[0].length);h.chars(e);return c.join("")}})})(window,window.angular);


[07/51] [abbrv] [partial] Adding Jinwon's custom RCMET

Posted by jo...@apache.org.
http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/recipes/.svn/text-base/mod_log_config.rb.svn-base
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/recipes/.svn/text-base/mod_log_config.rb.svn-base b/src/main/vm/src/cookbooks/apache2/recipes/.svn/text-base/mod_log_config.rb.svn-base
new file mode 100755
index 0000000..fa8a484
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/recipes/.svn/text-base/mod_log_config.rb.svn-base
@@ -0,0 +1,24 @@
+#
+# Cookbook Name:: apache2
+# Recipe:: log_config 
+#
+# Copyright 2008-2009, Opscode, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+if platform?("centos", "redhat", "fedora", "suse")
+  apache_module "log_config"
+else
+  include_recipe "apache2"
+end

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/recipes/.svn/text-base/mod_mime.rb.svn-base
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/recipes/.svn/text-base/mod_mime.rb.svn-base b/src/main/vm/src/cookbooks/apache2/recipes/.svn/text-base/mod_mime.rb.svn-base
new file mode 100755
index 0000000..16aee1a
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/recipes/.svn/text-base/mod_mime.rb.svn-base
@@ -0,0 +1,22 @@
+#
+# Cookbook Name:: apache2
+# Recipe:: mime 
+#
+# Copyright 2008-2009, Opscode, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+apache_module "mime" do
+  conf true
+end

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/recipes/.svn/text-base/mod_negotiation.rb.svn-base
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/recipes/.svn/text-base/mod_negotiation.rb.svn-base b/src/main/vm/src/cookbooks/apache2/recipes/.svn/text-base/mod_negotiation.rb.svn-base
new file mode 100755
index 0000000..348e11f
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/recipes/.svn/text-base/mod_negotiation.rb.svn-base
@@ -0,0 +1,22 @@
+#
+# Cookbook Name:: apache2
+# Recipe:: negotiation 
+#
+# Copyright 2008-2009, Opscode, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+apache_module "negotiation" do
+  conf true
+end

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/recipes/.svn/text-base/mod_php5.rb.svn-base
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/recipes/.svn/text-base/mod_php5.rb.svn-base b/src/main/vm/src/cookbooks/apache2/recipes/.svn/text-base/mod_php5.rb.svn-base
new file mode 100755
index 0000000..b6ae2c0
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/recipes/.svn/text-base/mod_php5.rb.svn-base
@@ -0,0 +1,32 @@
+#
+# Cookbook Name:: apache2
+# Recipe:: php5 
+#
+# Copyright 2008-2009, Opscode, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+case node[:platform]
+when "debian", "ubuntu"
+  package "libapache2-mod-php5" do
+    action :install
+  end  
+when "centos", "redhat", "fedora"
+  package "php" do
+    action :install
+    notifies :run, resources(:execute => "generate-module-list"), :immediately
+  end
+end
+
+apache_module "php5"

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/recipes/.svn/text-base/mod_proxy.rb.svn-base
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/recipes/.svn/text-base/mod_proxy.rb.svn-base b/src/main/vm/src/cookbooks/apache2/recipes/.svn/text-base/mod_proxy.rb.svn-base
new file mode 100755
index 0000000..fff7627
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/recipes/.svn/text-base/mod_proxy.rb.svn-base
@@ -0,0 +1,22 @@
+#
+# Cookbook Name:: apache2
+# Recipe:: proxy 
+#
+# Copyright 2008-2009, Opscode, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+apache_module "proxy" do
+  conf true
+end

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/recipes/.svn/text-base/mod_proxy_ajp.rb.svn-base
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/recipes/.svn/text-base/mod_proxy_ajp.rb.svn-base b/src/main/vm/src/cookbooks/apache2/recipes/.svn/text-base/mod_proxy_ajp.rb.svn-base
new file mode 100755
index 0000000..617a2c2
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/recipes/.svn/text-base/mod_proxy_ajp.rb.svn-base
@@ -0,0 +1,20 @@
+#
+# Cookbook Name:: apache2
+# Recipe:: proxy 
+#
+# Copyright 2008-2009, Opscode, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+apache_module "proxy_ajp"

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/recipes/.svn/text-base/mod_proxy_balancer.rb.svn-base
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/recipes/.svn/text-base/mod_proxy_balancer.rb.svn-base b/src/main/vm/src/cookbooks/apache2/recipes/.svn/text-base/mod_proxy_balancer.rb.svn-base
new file mode 100755
index 0000000..dc62a71
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/recipes/.svn/text-base/mod_proxy_balancer.rb.svn-base
@@ -0,0 +1,20 @@
+#
+# Cookbook Name:: apache2
+# Recipe:: proxy 
+#
+# Copyright 2008-2009, Opscode, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+apache_module "proxy_balancer"

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/recipes/.svn/text-base/mod_proxy_connect.rb.svn-base
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/recipes/.svn/text-base/mod_proxy_connect.rb.svn-base b/src/main/vm/src/cookbooks/apache2/recipes/.svn/text-base/mod_proxy_connect.rb.svn-base
new file mode 100755
index 0000000..f41954f
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/recipes/.svn/text-base/mod_proxy_connect.rb.svn-base
@@ -0,0 +1,20 @@
+#
+# Cookbook Name:: apache2
+# Recipe:: proxy 
+#
+# Copyright 2008-2009, Opscode, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+apache_module "proxy_connect"

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/recipes/.svn/text-base/mod_proxy_http.rb.svn-base
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/recipes/.svn/text-base/mod_proxy_http.rb.svn-base b/src/main/vm/src/cookbooks/apache2/recipes/.svn/text-base/mod_proxy_http.rb.svn-base
new file mode 100755
index 0000000..ddff3ea
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/recipes/.svn/text-base/mod_proxy_http.rb.svn-base
@@ -0,0 +1,20 @@
+#
+# Cookbook Name:: apache2
+# Recipe:: proxy_http 
+#
+# Copyright 2008-2009, Opscode, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+apache_module "proxy_http"

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/recipes/.svn/text-base/mod_python.rb.svn-base
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/recipes/.svn/text-base/mod_python.rb.svn-base b/src/main/vm/src/cookbooks/apache2/recipes/.svn/text-base/mod_python.rb.svn-base
new file mode 100755
index 0000000..feaca03
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/recipes/.svn/text-base/mod_python.rb.svn-base
@@ -0,0 +1,22 @@
+#
+# Cookbook Name:: apache2
+# Recipe:: python 
+#
+# Copyright 2008-2009, Opscode, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+package "libapache2-mod-python"
+
+apache_module "python"

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/recipes/.svn/text-base/mod_rewrite.rb.svn-base
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/recipes/.svn/text-base/mod_rewrite.rb.svn-base b/src/main/vm/src/cookbooks/apache2/recipes/.svn/text-base/mod_rewrite.rb.svn-base
new file mode 100755
index 0000000..df388a6
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/recipes/.svn/text-base/mod_rewrite.rb.svn-base
@@ -0,0 +1,20 @@
+#
+# Cookbook Name:: apache2
+# Recipe:: rewrite 
+#
+# Copyright 2008-2009, Opscode, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+apache_module "rewrite"

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/recipes/.svn/text-base/mod_setenvif.rb.svn-base
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/recipes/.svn/text-base/mod_setenvif.rb.svn-base b/src/main/vm/src/cookbooks/apache2/recipes/.svn/text-base/mod_setenvif.rb.svn-base
new file mode 100755
index 0000000..4048a5f
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/recipes/.svn/text-base/mod_setenvif.rb.svn-base
@@ -0,0 +1,22 @@
+#
+# Cookbook Name:: apache2
+# Recipe:: setenvif 
+#
+# Copyright 2008-2009, Opscode, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+apache_module "setenvif" do
+  conf true
+end

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/recipes/.svn/text-base/mod_ssl.rb.svn-base
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/recipes/.svn/text-base/mod_ssl.rb.svn-base b/src/main/vm/src/cookbooks/apache2/recipes/.svn/text-base/mod_ssl.rb.svn-base
new file mode 100755
index 0000000..e82b9d1
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/recipes/.svn/text-base/mod_ssl.rb.svn-base
@@ -0,0 +1,42 @@
+#
+# Cookbook Name:: apache2
+# Recipe:: ssl 
+#
+# Copyright 2008-2009, Opscode, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+if platform?("centos", "redhat", "fedora")
+  package "mod_ssl" do
+    action :install
+    notifies :run, resources(:execute => "generate-module-list"), :immediately
+  end
+
+  file "#{node[:apache][:dir]}/conf.d/ssl.conf" do
+    action :delete
+    backup false 
+  end
+end
+
+ports = node[:apache][:listen_ports].include?("443") ? node[:apache][:listen_ports] : [node[:apache][:listen_ports], "443"].flatten
+
+template "#{node[:apache][:dir]}/ports.conf" do
+  source "ports.conf.erb"
+  variables :apache_listen_ports => ports
+  notifies :restart, resources(:service => "apache2")
+end
+
+apache_module "ssl" do
+  conf true
+end

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/recipes/.svn/text-base/mod_status.rb.svn-base
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/recipes/.svn/text-base/mod_status.rb.svn-base b/src/main/vm/src/cookbooks/apache2/recipes/.svn/text-base/mod_status.rb.svn-base
new file mode 100755
index 0000000..3e71727
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/recipes/.svn/text-base/mod_status.rb.svn-base
@@ -0,0 +1,22 @@
+#
+# Cookbook Name:: apache2
+# Recipe:: status 
+#
+# Copyright 2008-2009, Opscode, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+apache_module "status" do
+  conf true
+end

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/recipes/.svn/text-base/mod_wsgi.rb.svn-base
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/recipes/.svn/text-base/mod_wsgi.rb.svn-base b/src/main/vm/src/cookbooks/apache2/recipes/.svn/text-base/mod_wsgi.rb.svn-base
new file mode 100755
index 0000000..f54919f
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/recipes/.svn/text-base/mod_wsgi.rb.svn-base
@@ -0,0 +1,27 @@
+#
+# Cookbook Name:: apache2
+# Recipe:: python 
+#
+# Copyright 2008-2009, Opscode, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+case node[:platform]
+when "debian","ubuntu"
+  package "libapache2-mod-wsgi"
+when "redhat","centos","fedora"
+  package "mod_wsgi"
+end
+
+apache_module "wsgi"

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/recipes/default.rb
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/recipes/default.rb b/src/main/vm/src/cookbooks/apache2/recipes/default.rb
new file mode 100755
index 0000000..7aef323
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/recipes/default.rb
@@ -0,0 +1,191 @@
+#
+# Cookbook Name:: apache2
+# Recipe:: default
+#
+# Copyright 2008-2009, Opscode, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+package "apache2" do
+  case node[:platform]
+  when "centos","redhat","fedora","suse"
+    package_name "httpd"
+  when "debian","ubuntu"
+    package_name "apache2"
+  end
+  action :install
+end
+
+service "apache2" do
+  case node[:platform]
+  when "centos","redhat","fedora","suse"
+    service_name "httpd"
+    # If restarted/reloaded too quickly httpd has a habit of failing.
+    # This may happen with multiple recipes notifying apache to restart - like
+    # during the initial bootstrap.
+    restart_command "/sbin/service httpd restart && sleep 1"
+    reload_command "/sbin/service httpd reload && sleep 1"
+  when "debian","ubuntu"
+    service_name "apache2"
+  end
+  supports value_for_platform(
+    "debian" => { "4.0" => [ :restart, :reload ], "default" => [ :restart, :reload, :status ] },
+    "ubuntu" => { "default" => [ :restart, :reload, :status ] },
+    "centos" => { "default" => [ :restart, :reload, :status ] },
+    "redhat" => { "default" => [ :restart, :reload, :status ] },
+    "fedora" => { "default" => [ :restart, :reload, :status ] },
+    "default" => { "default" => [:restart, :reload ] }
+  )
+  action :enable
+end
+
+if platform?("centos", "redhat", "fedora", "suse")
+  directory node[:apache][:log_dir] do
+    mode 0755
+    action :create
+  end
+  
+  cookbook_file "/usr/local/bin/apache2_module_conf_generate.pl" do
+    source "apache2_module_conf_generate.pl"
+    mode 0755
+    owner "root"
+    group "root"
+  end
+
+  %w{sites-available sites-enabled mods-available mods-enabled}.each do |dir|
+    directory "#{node[:apache][:dir]}/#{dir}" do
+      mode 0755
+      owner "root"
+      group "root"
+      action :create
+    end
+  end
+    
+  execute "generate-module-list" do
+    if node[:kernel][:machine] == "x86_64" 
+      libdir = "lib64"
+    else 
+      libdir = "lib"
+    end
+    command "/usr/local/bin/apache2_module_conf_generate.pl /usr/#{libdir}/httpd/modules /etc/httpd/mods-available"
+    
+    action :run
+  end
+  
+  %w{a2ensite a2dissite a2enmod a2dismod}.each do |modscript|
+    template "/usr/sbin/#{modscript}" do
+      source "#{modscript}.erb"
+      mode 0755
+      owner "root"
+      group "root"
+    end  
+  end
+
+  # installed by default on centos/rhel, remove in favour of mods-enabled
+  file "#{node[:apache][:dir]}/conf.d/proxy_ajp.conf" do
+    action :delete
+    backup false
+  end
+  file "#{node[:apache][:dir]}/conf.d/README" do
+    action :delete
+    backup false
+  end
+  
+  # welcome page moved to the default-site.rb temlate
+  file "#{node[:apache][:dir]}/conf.d/welcome.conf" do
+    action :delete
+    backup false
+  end
+end
+
+directory "#{node[:apache][:dir]}/ssl" do
+  action :create
+  mode 0755
+  owner "root"
+  group "root"
+end
+
+template "apache2.conf" do
+  case node[:platform]
+  when "centos","redhat","fedora"
+    path "#{node[:apache][:dir]}/conf/httpd.conf"
+  when "debian","ubuntu"
+    path "#{node[:apache][:dir]}/apache2.conf"
+  end
+  source "apache2.conf.erb"
+  owner "root"
+  group "root"
+  mode 0644
+  notifies :restart, resources(:service => "apache2")
+end
+
+template "security" do
+  path "#{node[:apache][:dir]}/conf.d/security"
+  source "security.erb"
+  owner "root"
+  group "root"
+  mode 0644
+  backup false
+  notifies :restart, resources(:service => "apache2")
+end
+
+template "charset" do
+  path "#{node[:apache][:dir]}/conf.d/charset"
+  source "charset.erb"
+  owner "root"
+  group "root"
+  mode 0644
+  backup false
+  notifies :restart, resources(:service => "apache2")
+end
+
+template "#{node[:apache][:dir]}/ports.conf" do
+  source "ports.conf.erb"
+  group "root"
+  owner "root"
+  variables :apache_listen_ports => node[:apache][:listen_ports]
+  mode 0644
+  notifies :restart, resources(:service => "apache2")
+end
+
+template "#{node[:apache][:dir]}/sites-available/default" do
+  source "default-site.erb"
+  owner "root"
+  group "root"
+  mode 0644
+  notifies :restart, resources(:service => "apache2")
+end
+
+include_recipe "apache2::mod_status"
+include_recipe "apache2::mod_alias"
+include_recipe "apache2::mod_auth_basic"
+include_recipe "apache2::mod_authn_file"
+include_recipe "apache2::mod_authz_default"
+include_recipe "apache2::mod_authz_groupfile"
+include_recipe "apache2::mod_authz_host"
+include_recipe "apache2::mod_authz_user"
+include_recipe "apache2::mod_autoindex"
+include_recipe "apache2::mod_dir"
+include_recipe "apache2::mod_env"
+include_recipe "apache2::mod_mime"
+include_recipe "apache2::mod_negotiation"
+include_recipe "apache2::mod_setenvif"
+include_recipe "apache2::mod_log_config" if platform?("centos", "redhat", "suse")
+
+# uncomment to get working example site on centos/redhat/fedora
+#apache_site "default"
+
+service "apache2" do
+  action :start
+end

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/recipes/god_monitor.rb
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/recipes/god_monitor.rb b/src/main/vm/src/cookbooks/apache2/recipes/god_monitor.rb
new file mode 100755
index 0000000..b3c49eb
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/recipes/god_monitor.rb
@@ -0,0 +1,33 @@
+#
+# Cookbook Name:: apache2
+# Recipe:: god_monitor
+#
+# Copyright 2008-2009, Opscode, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+apache_service = service "apache2" do
+  action :nothing
+end
+
+start_command = apache_service.start_command
+stop_command = apache_service.stop_command
+restart_command = apache_service.restart_command
+
+god_monitor "apache2" do
+  config "apache2.god.erb"
+  start (start_command)?start_command : "/etc/init.d/#{apache_service.service_name} start"
+  restart (restart_command)?restart_command : "/etc/init.d/#{apache_service.service_name} restart"
+  stop (stop_command)?stop_command : "/etc/init.d/#{apache_service.service_name} stop"
+end

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/recipes/mod_alias.rb
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/recipes/mod_alias.rb b/src/main/vm/src/cookbooks/apache2/recipes/mod_alias.rb
new file mode 100755
index 0000000..a4618ed
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/recipes/mod_alias.rb
@@ -0,0 +1,22 @@
+#
+# Cookbook Name:: apache2
+# Recipe:: alias 
+#
+# Copyright 2008-2009, Opscode, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+apache_module "alias" do
+  conf true
+end

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/recipes/mod_auth_basic.rb
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/recipes/mod_auth_basic.rb b/src/main/vm/src/cookbooks/apache2/recipes/mod_auth_basic.rb
new file mode 100755
index 0000000..d30264f
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/recipes/mod_auth_basic.rb
@@ -0,0 +1,20 @@
+#
+# Cookbook Name:: apache2
+# Recipe:: auth_basic 
+#
+# Copyright 2008-2009, Opscode, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+apache_module "auth_basic"

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/recipes/mod_auth_digest.rb
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/recipes/mod_auth_digest.rb b/src/main/vm/src/cookbooks/apache2/recipes/mod_auth_digest.rb
new file mode 100755
index 0000000..5aef926
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/recipes/mod_auth_digest.rb
@@ -0,0 +1,20 @@
+#
+# Cookbook Name:: apache2
+# Recipe:: auth_digest 
+#
+# Copyright 2008-2009, Opscode, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+apache_module "auth_digest"

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/recipes/mod_auth_openid.rb
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/recipes/mod_auth_openid.rb b/src/main/vm/src/cookbooks/apache2/recipes/mod_auth_openid.rb
new file mode 100755
index 0000000..83cc220
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/recipes/mod_auth_openid.rb
@@ -0,0 +1,59 @@
+#
+# Cookbook Name:: apache2
+# Recipe:: mod_auth_openid
+#
+# Copyright 2008-2009, Opscode, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+%w{ apache2-prefork-dev libopkele-dev libopkele3 }.each do |pkg|
+  package pkg
+end
+
+remote_file "/tmp/mod_auth_openid-0.4.tar.gz" do
+  source "http://butterfat.net/releases/mod_auth_openid/mod_auth_openid-0.4.tar.gz"
+  mode 0644
+end
+
+bash "install mod_auth_openid" do
+  cwd "/tmp"
+  code <<-EOH
+  tar zxvf mod_auth_openid-0.4.tar.gz
+  cd mod_auth_openid-0.4 && ./configure
+  perl -pi -e "s/-i -a -n 'authopenid'/-i -n 'authopenid'/g" Makefile
+  make && make install
+  EOH
+  not_if { File.exists?("/usr/lib/apache2/modules/mod_auth_openid.so") }
+end
+
+file "/var/cache/apache2/mod_auth_openid.db" do
+  owner node[:apache][:user]
+  mode 0600
+end
+
+template "#{node[:apache][:dir]}/mods-available/authopenid.load" do
+  source "mods/authopenid.load.erb"
+  owner "root"
+  group "root"
+  mode 0644
+end
+
+apache_module "authopenid"
+
+template "/usr/local/bin/mod_auth_openid.rb" do
+  source "mod_auth_openid.rb.erb"
+  owner node[:apache][:user]
+  group node[:apache][:user]
+  mode 0750
+end

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/recipes/mod_authn_file.rb
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/recipes/mod_authn_file.rb b/src/main/vm/src/cookbooks/apache2/recipes/mod_authn_file.rb
new file mode 100755
index 0000000..872caa7
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/recipes/mod_authn_file.rb
@@ -0,0 +1,20 @@
+#
+# Cookbook Name:: apache2
+# Recipe:: authn_file 
+#
+# Copyright 2008-2009, Opscode, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+apache_module "authn_file"

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/recipes/mod_authnz_ldap.rb
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/recipes/mod_authnz_ldap.rb b/src/main/vm/src/cookbooks/apache2/recipes/mod_authnz_ldap.rb
new file mode 100755
index 0000000..0310d24
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/recipes/mod_authnz_ldap.rb
@@ -0,0 +1,20 @@
+#
+# Cookbook Name:: apache2
+# Recipe:: authnz_ldap 
+#
+# Copyright 2008-2009, Opscode, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+apache_module "authnz_ldap"

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/recipes/mod_authz_default.rb
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/recipes/mod_authz_default.rb b/src/main/vm/src/cookbooks/apache2/recipes/mod_authz_default.rb
new file mode 100755
index 0000000..123536d
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/recipes/mod_authz_default.rb
@@ -0,0 +1,20 @@
+#
+# Cookbook Name:: apache2
+# Recipe:: authz_default 
+#
+# Copyright 2008-2009, Opscode, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+apache_module "authz_default"

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/recipes/mod_authz_groupfile.rb
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/recipes/mod_authz_groupfile.rb b/src/main/vm/src/cookbooks/apache2/recipes/mod_authz_groupfile.rb
new file mode 100755
index 0000000..b2833b2
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/recipes/mod_authz_groupfile.rb
@@ -0,0 +1,20 @@
+#
+# Cookbook Name:: apache2
+# Recipe:: authz_groupfile 
+#
+# Copyright 2008-2009, Opscode, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+apache_module "authz_groupfile"

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/recipes/mod_authz_host.rb
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/recipes/mod_authz_host.rb b/src/main/vm/src/cookbooks/apache2/recipes/mod_authz_host.rb
new file mode 100755
index 0000000..87c1a4b
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/recipes/mod_authz_host.rb
@@ -0,0 +1,20 @@
+#
+# Cookbook Name:: apache2
+# Recipe:: authz_host 
+#
+# Copyright 2008-2009, Opscode, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+apache_module "authz_host"

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/recipes/mod_authz_user.rb
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/recipes/mod_authz_user.rb b/src/main/vm/src/cookbooks/apache2/recipes/mod_authz_user.rb
new file mode 100755
index 0000000..8dd46df
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/recipes/mod_authz_user.rb
@@ -0,0 +1,20 @@
+#
+# Cookbook Name:: apache2
+# Recipe:: authz_user 
+#
+# Copyright 2008-2009, Opscode, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+apache_module "authz_user"

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/recipes/mod_autoindex.rb
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/recipes/mod_autoindex.rb b/src/main/vm/src/cookbooks/apache2/recipes/mod_autoindex.rb
new file mode 100755
index 0000000..622a66e
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/recipes/mod_autoindex.rb
@@ -0,0 +1,22 @@
+#
+# Cookbook Name:: apache2
+# Recipe:: autoindex 
+#
+# Copyright 2008-2009, Opscode, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+apache_module "autoindex" do
+  conf true
+end

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/recipes/mod_cgi.rb
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/recipes/mod_cgi.rb b/src/main/vm/src/cookbooks/apache2/recipes/mod_cgi.rb
new file mode 100755
index 0000000..6c15a05
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/recipes/mod_cgi.rb
@@ -0,0 +1,20 @@
+#
+# Cookbook Name:: apache2
+# Recipe:: cgi 
+#
+# Copyright 2008-2009, Opscode, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+apache_module "cgi"

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/recipes/mod_dav.rb
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/recipes/mod_dav.rb b/src/main/vm/src/cookbooks/apache2/recipes/mod_dav.rb
new file mode 100755
index 0000000..fef656a
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/recipes/mod_dav.rb
@@ -0,0 +1,20 @@
+#
+# Cookbook Name:: apache2
+# Recipe:: dav 
+#
+# Copyright 2008-2009, Opscode, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+apache_module "dav"

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/recipes/mod_dav_svn.rb
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/recipes/mod_dav_svn.rb b/src/main/vm/src/cookbooks/apache2/recipes/mod_dav_svn.rb
new file mode 100755
index 0000000..ce50d54
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/recipes/mod_dav_svn.rb
@@ -0,0 +1,22 @@
+#
+# Cookbook Name:: apache2
+# Recipe:: dav_svn 
+#
+# Copyright 2008-2009, Opscode, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+package "libapache2-svn"
+
+apache_module "dav_svn"

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/recipes/mod_deflate.rb
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/recipes/mod_deflate.rb b/src/main/vm/src/cookbooks/apache2/recipes/mod_deflate.rb
new file mode 100755
index 0000000..b568f30
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/recipes/mod_deflate.rb
@@ -0,0 +1,22 @@
+#
+# Cookbook Name:: apache2
+# Recipe:: deflate 
+#
+# Copyright 2008-2009, Opscode, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+apache_module "deflate" do
+  conf true
+end

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/recipes/mod_dir.rb
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/recipes/mod_dir.rb b/src/main/vm/src/cookbooks/apache2/recipes/mod_dir.rb
new file mode 100755
index 0000000..9930c3a
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/recipes/mod_dir.rb
@@ -0,0 +1,22 @@
+#
+# Cookbook Name:: apache2
+# Recipe:: dir 
+#
+# Copyright 2008-2009, Opscode, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+apache_module "dir" do 
+  conf true
+end

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/recipes/mod_env.rb
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/recipes/mod_env.rb b/src/main/vm/src/cookbooks/apache2/recipes/mod_env.rb
new file mode 100755
index 0000000..d345503
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/recipes/mod_env.rb
@@ -0,0 +1,20 @@
+#
+# Cookbook Name:: apache2
+# Recipe:: env 
+#
+# Copyright 2008-2009, Opscode, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+apache_module "env"

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/recipes/mod_expires.rb
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/recipes/mod_expires.rb b/src/main/vm/src/cookbooks/apache2/recipes/mod_expires.rb
new file mode 100755
index 0000000..9e5042e
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/recipes/mod_expires.rb
@@ -0,0 +1,20 @@
+#
+# Cookbook Name:: apache2
+# Recipe:: expires 
+#
+# Copyright 2008-2009, Opscode, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+apache_module "expires"

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/recipes/mod_fcgid.rb
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/recipes/mod_fcgid.rb b/src/main/vm/src/cookbooks/apache2/recipes/mod_fcgid.rb
new file mode 100755
index 0000000..ea7ec3e
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/recipes/mod_fcgid.rb
@@ -0,0 +1,46 @@
+#
+# Cookbook Name:: apache2
+# Recipe:: fcgid 
+#
+# Copyright 2008-2009, Opscode, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+if platform?("debian", "ubuntu")
+  package "libapache2-mod-fcgid"
+elsif platform?("centos", "redhat", "fedora")
+  package "mod_fcgid" do
+    notifies :run, resources(:execute => "generate-module-list"), :immediately
+  end
+
+  file "#{node[:apache][:dir]}/conf.d/fcgid.conf" do
+    action :delete
+    backup false 
+  end
+elsif platform?("suse")
+  apache_lib_path = node[:architecture] == "i386" ? "/usr/lib/httpd" : "/usr/lib64/httpd"
+  package "httpd-devel"
+  bash "install-fcgid" do
+    code <<-EOH
+(cd /tmp; wget http://superb-east.dl.sourceforge.net/sourceforge/mod-fcgid/mod_fcgid.2.2.tgz)
+(cd /tmp; tar zxvf mod_fcgid.2.2.tgz)
+(cd /tmp; perl -pi -e 's!/usr/local/apache2!#{apache_lib_path}!g' ./mod_fcgid.2.2/Makefile)
+(cd /tmp/mod_fcgid.2.2; make install)
+EOH
+  end
+end
+
+apache_module "fcgid" do
+  conf true
+end

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/recipes/mod_headers.rb
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/recipes/mod_headers.rb b/src/main/vm/src/cookbooks/apache2/recipes/mod_headers.rb
new file mode 100755
index 0000000..5e6b94d
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/recipes/mod_headers.rb
@@ -0,0 +1,20 @@
+#
+# Cookbook Name:: apache2
+# Recipe:: headers 
+#
+# Copyright 2008-2009, Opscode, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+apache_module "headers"

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/recipes/mod_ldap.rb
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/recipes/mod_ldap.rb b/src/main/vm/src/cookbooks/apache2/recipes/mod_ldap.rb
new file mode 100755
index 0000000..0877694
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/recipes/mod_ldap.rb
@@ -0,0 +1,20 @@
+#
+# Cookbook Name:: apache2
+# Recipe:: ldap 
+#
+# Copyright 2008-2009, Opscode, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+apache_module "ldap"

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/recipes/mod_log_config.rb
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/recipes/mod_log_config.rb b/src/main/vm/src/cookbooks/apache2/recipes/mod_log_config.rb
new file mode 100755
index 0000000..fa8a484
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/recipes/mod_log_config.rb
@@ -0,0 +1,24 @@
+#
+# Cookbook Name:: apache2
+# Recipe:: log_config 
+#
+# Copyright 2008-2009, Opscode, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+if platform?("centos", "redhat", "fedora", "suse")
+  apache_module "log_config"
+else
+  include_recipe "apache2"
+end

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/recipes/mod_mime.rb
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/recipes/mod_mime.rb b/src/main/vm/src/cookbooks/apache2/recipes/mod_mime.rb
new file mode 100755
index 0000000..16aee1a
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/recipes/mod_mime.rb
@@ -0,0 +1,22 @@
+#
+# Cookbook Name:: apache2
+# Recipe:: mime 
+#
+# Copyright 2008-2009, Opscode, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+apache_module "mime" do
+  conf true
+end

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/recipes/mod_negotiation.rb
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/recipes/mod_negotiation.rb b/src/main/vm/src/cookbooks/apache2/recipes/mod_negotiation.rb
new file mode 100755
index 0000000..348e11f
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/recipes/mod_negotiation.rb
@@ -0,0 +1,22 @@
+#
+# Cookbook Name:: apache2
+# Recipe:: negotiation 
+#
+# Copyright 2008-2009, Opscode, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+apache_module "negotiation" do
+  conf true
+end

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/recipes/mod_php5.rb
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/recipes/mod_php5.rb b/src/main/vm/src/cookbooks/apache2/recipes/mod_php5.rb
new file mode 100755
index 0000000..b6ae2c0
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/recipes/mod_php5.rb
@@ -0,0 +1,32 @@
+#
+# Cookbook Name:: apache2
+# Recipe:: php5 
+#
+# Copyright 2008-2009, Opscode, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+case node[:platform]
+when "debian", "ubuntu"
+  package "libapache2-mod-php5" do
+    action :install
+  end  
+when "centos", "redhat", "fedora"
+  package "php" do
+    action :install
+    notifies :run, resources(:execute => "generate-module-list"), :immediately
+  end
+end
+
+apache_module "php5"

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/recipes/mod_proxy.rb
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/recipes/mod_proxy.rb b/src/main/vm/src/cookbooks/apache2/recipes/mod_proxy.rb
new file mode 100755
index 0000000..fff7627
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/recipes/mod_proxy.rb
@@ -0,0 +1,22 @@
+#
+# Cookbook Name:: apache2
+# Recipe:: proxy 
+#
+# Copyright 2008-2009, Opscode, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+apache_module "proxy" do
+  conf true
+end

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/recipes/mod_proxy_ajp.rb
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/recipes/mod_proxy_ajp.rb b/src/main/vm/src/cookbooks/apache2/recipes/mod_proxy_ajp.rb
new file mode 100755
index 0000000..617a2c2
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/recipes/mod_proxy_ajp.rb
@@ -0,0 +1,20 @@
+#
+# Cookbook Name:: apache2
+# Recipe:: proxy 
+#
+# Copyright 2008-2009, Opscode, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+apache_module "proxy_ajp"

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/recipes/mod_proxy_balancer.rb
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/recipes/mod_proxy_balancer.rb b/src/main/vm/src/cookbooks/apache2/recipes/mod_proxy_balancer.rb
new file mode 100755
index 0000000..dc62a71
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/recipes/mod_proxy_balancer.rb
@@ -0,0 +1,20 @@
+#
+# Cookbook Name:: apache2
+# Recipe:: proxy 
+#
+# Copyright 2008-2009, Opscode, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+apache_module "proxy_balancer"

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/recipes/mod_proxy_connect.rb
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/recipes/mod_proxy_connect.rb b/src/main/vm/src/cookbooks/apache2/recipes/mod_proxy_connect.rb
new file mode 100755
index 0000000..f41954f
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/recipes/mod_proxy_connect.rb
@@ -0,0 +1,20 @@
+#
+# Cookbook Name:: apache2
+# Recipe:: proxy 
+#
+# Copyright 2008-2009, Opscode, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+apache_module "proxy_connect"

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/recipes/mod_proxy_http.rb
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/recipes/mod_proxy_http.rb b/src/main/vm/src/cookbooks/apache2/recipes/mod_proxy_http.rb
new file mode 100755
index 0000000..ddff3ea
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/recipes/mod_proxy_http.rb
@@ -0,0 +1,20 @@
+#
+# Cookbook Name:: apache2
+# Recipe:: proxy_http 
+#
+# Copyright 2008-2009, Opscode, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+apache_module "proxy_http"

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/recipes/mod_python.rb
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/recipes/mod_python.rb b/src/main/vm/src/cookbooks/apache2/recipes/mod_python.rb
new file mode 100755
index 0000000..feaca03
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/recipes/mod_python.rb
@@ -0,0 +1,22 @@
+#
+# Cookbook Name:: apache2
+# Recipe:: python 
+#
+# Copyright 2008-2009, Opscode, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+package "libapache2-mod-python"
+
+apache_module "python"

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/recipes/mod_rewrite.rb
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/recipes/mod_rewrite.rb b/src/main/vm/src/cookbooks/apache2/recipes/mod_rewrite.rb
new file mode 100755
index 0000000..df388a6
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/recipes/mod_rewrite.rb
@@ -0,0 +1,20 @@
+#
+# Cookbook Name:: apache2
+# Recipe:: rewrite 
+#
+# Copyright 2008-2009, Opscode, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+apache_module "rewrite"

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/recipes/mod_setenvif.rb
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/recipes/mod_setenvif.rb b/src/main/vm/src/cookbooks/apache2/recipes/mod_setenvif.rb
new file mode 100755
index 0000000..4048a5f
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/recipes/mod_setenvif.rb
@@ -0,0 +1,22 @@
+#
+# Cookbook Name:: apache2
+# Recipe:: setenvif 
+#
+# Copyright 2008-2009, Opscode, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+apache_module "setenvif" do
+  conf true
+end

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/recipes/mod_ssl.rb
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/recipes/mod_ssl.rb b/src/main/vm/src/cookbooks/apache2/recipes/mod_ssl.rb
new file mode 100755
index 0000000..e82b9d1
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/recipes/mod_ssl.rb
@@ -0,0 +1,42 @@
+#
+# Cookbook Name:: apache2
+# Recipe:: ssl 
+#
+# Copyright 2008-2009, Opscode, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+if platform?("centos", "redhat", "fedora")
+  package "mod_ssl" do
+    action :install
+    notifies :run, resources(:execute => "generate-module-list"), :immediately
+  end
+
+  file "#{node[:apache][:dir]}/conf.d/ssl.conf" do
+    action :delete
+    backup false 
+  end
+end
+
+ports = node[:apache][:listen_ports].include?("443") ? node[:apache][:listen_ports] : [node[:apache][:listen_ports], "443"].flatten
+
+template "#{node[:apache][:dir]}/ports.conf" do
+  source "ports.conf.erb"
+  variables :apache_listen_ports => ports
+  notifies :restart, resources(:service => "apache2")
+end
+
+apache_module "ssl" do
+  conf true
+end

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/recipes/mod_status.rb
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/recipes/mod_status.rb b/src/main/vm/src/cookbooks/apache2/recipes/mod_status.rb
new file mode 100755
index 0000000..3e71727
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/recipes/mod_status.rb
@@ -0,0 +1,22 @@
+#
+# Cookbook Name:: apache2
+# Recipe:: status 
+#
+# Copyright 2008-2009, Opscode, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+apache_module "status" do
+  conf true
+end

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/recipes/mod_wsgi.rb
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/recipes/mod_wsgi.rb b/src/main/vm/src/cookbooks/apache2/recipes/mod_wsgi.rb
new file mode 100755
index 0000000..f54919f
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/recipes/mod_wsgi.rb
@@ -0,0 +1,27 @@
+#
+# Cookbook Name:: apache2
+# Recipe:: python 
+#
+# Copyright 2008-2009, Opscode, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+case node[:platform]
+when "debian","ubuntu"
+  package "libapache2-mod-wsgi"
+when "redhat","centos","fedora"
+  package "mod_wsgi"
+end
+
+apache_module "wsgi"

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/templates/.svn/all-wcprops
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/templates/.svn/all-wcprops b/src/main/vm/src/cookbooks/apache2/templates/.svn/all-wcprops
new file mode 100755
index 0000000..e1280dc
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/templates/.svn/all-wcprops
@@ -0,0 +1,5 @@
+K 25
+svn:wc:ra_dav:version-url
+V 101
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks/apache2/templates
+END

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/templates/.svn/entries
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/templates/.svn/entries b/src/main/vm/src/cookbooks/apache2/templates/.svn/entries
new file mode 100755
index 0000000..2d85b31
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/templates/.svn/entries
@@ -0,0 +1,31 @@
+10
+
+dir
+1485921
+https://svn.apache.org/repos/asf/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks/apache2/templates
+https://svn.apache.org/repos/asf
+
+
+
+2012-10-10T00:49:17.045897Z
+1474264
+ahart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+13f79535-47bb-0310-9956-ffa450edef68
+
+default
+dir
+

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/templates/default/.svn/all-wcprops
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/templates/default/.svn/all-wcprops b/src/main/vm/src/cookbooks/apache2/templates/default/.svn/all-wcprops
new file mode 100755
index 0000000..a0f0b19
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/templates/default/.svn/all-wcprops
@@ -0,0 +1,83 @@
+K 25
+svn:wc:ra_dav:version-url
+V 109
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks/apache2/templates/default
+END
+charset.erb
+K 25
+svn:wc:ra_dav:version-url
+V 121
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks/apache2/templates/default/charset.erb
+END
+a2ensite.erb
+K 25
+svn:wc:ra_dav:version-url
+V 122
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks/apache2/templates/default/a2ensite.erb
+END
+apache2.god.erb
+K 25
+svn:wc:ra_dav:version-url
+V 125
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks/apache2/templates/default/apache2.god.erb
+END
+ports.conf.erb
+K 25
+svn:wc:ra_dav:version-url
+V 124
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks/apache2/templates/default/ports.conf.erb
+END
+mod_auth_openid.rb.erb
+K 25
+svn:wc:ra_dav:version-url
+V 132
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks/apache2/templates/default/mod_auth_openid.rb.erb
+END
+web_app.conf.erb
+K 25
+svn:wc:ra_dav:version-url
+V 126
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks/apache2/templates/default/web_app.conf.erb
+END
+a2dismod.erb
+K 25
+svn:wc:ra_dav:version-url
+V 122
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks/apache2/templates/default/a2dismod.erb
+END
+a2enmod.erb
+K 25
+svn:wc:ra_dav:version-url
+V 121
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks/apache2/templates/default/a2enmod.erb
+END
+port_apache.erb
+K 25
+svn:wc:ra_dav:version-url
+V 125
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks/apache2/templates/default/port_apache.erb
+END
+default-site.erb
+K 25
+svn:wc:ra_dav:version-url
+V 126
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks/apache2/templates/default/default-site.erb
+END
+a2dissite.erb
+K 25
+svn:wc:ra_dav:version-url
+V 123
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks/apache2/templates/default/a2dissite.erb
+END
+apache2.conf.erb
+K 25
+svn:wc:ra_dav:version-url
+V 126
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks/apache2/templates/default/apache2.conf.erb
+END
+security.erb
+K 25
+svn:wc:ra_dav:version-url
+V 122
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks/apache2/templates/default/security.erb
+END

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/templates/default/.svn/entries
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/templates/default/.svn/entries b/src/main/vm/src/cookbooks/apache2/templates/default/.svn/entries
new file mode 100755
index 0000000..13ae497
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/templates/default/.svn/entries
@@ -0,0 +1,473 @@
+10
+
+dir
+1485921
+https://svn.apache.org/repos/asf/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks/apache2/templates/default
+https://svn.apache.org/repos/asf
+
+
+
+2012-10-10T00:49:17.045897Z
+1474264
+ahart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+13f79535-47bb-0310-9956-ffa450edef68
+
+charset.erb
+file
+
+
+
+
+2013-05-24T10:13:53.000000Z
+e6fbb8adf631932851d6cc522c1e48d7
+2012-10-10T00:49:17.045897Z
+1474264
+ahart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+269
+
+a2ensite.erb
+file
+
+
+
+
+2013-05-24T10:13:53.000000Z
+56579df79e6ff12511cc2a1522fd7af2
+2012-10-10T00:49:17.045897Z
+1474264
+ahart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+1020
+
+mods
+dir
+
+apache2.god.erb
+file
+
+
+
+
+2013-05-24T10:13:54.000000Z
+0bf184a24259c8943c1357d5197df969
+2012-10-10T00:49:17.045897Z
+1474264
+ahart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+486
+
+ports.conf.erb
+file
+
+
+
+
+2013-05-24T10:13:54.000000Z
+09ed7d522079615834a13990bdef2542
+2012-10-10T00:49:17.045897Z
+1474264
+ahart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+147
+
+mod_auth_openid.rb.erb
+file
+
+
+
+
+2013-05-24T10:13:54.000000Z
+e438e3ed68630263c50bf6d93eb32ed8
+2012-10-10T00:49:17.045897Z
+1474264
+ahart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+215
+
+web_app.conf.erb
+file
+
+
+
+
+2013-05-24T10:13:54.000000Z
+b5395d7925e5f3f2040a49b829d24f9b
+2012-10-10T00:49:17.045897Z
+1474264
+ahart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+1263
+
+a2dismod.erb
+file
+
+
+
+
+2013-05-24T10:13:54.000000Z
+802640853e3c8243e9229bddabe5d971
+2012-10-10T00:49:17.045897Z
+1474264
+ahart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+629
+
+a2enmod.erb
+file
+
+
+
+
+2013-05-24T10:13:54.000000Z
+5555e79ad578ad44cc00b3dd7ad85e53
+2012-10-10T00:49:17.045897Z
+1474264
+ahart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+1120
+
+port_apache.erb
+file
+
+
+
+
+2013-05-24T10:13:54.000000Z
+6012594d39fef96f9392e69c6dd8801f
+2012-10-10T00:49:17.045897Z
+1474264
+ahart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+72
+
+default-site.erb
+file
+
+
+
+
+2013-05-24T10:13:54.000000Z
+2ab19e5f7f0d33adc82004877b792ecb
+2012-10-10T00:49:17.045897Z
+1474264
+ahart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+2001
+
+a2dissite.erb
+file
+
+
+
+
+2013-05-24T10:13:54.000000Z
+6d7682704bba38227a18a7336ad0f8b9
+2012-10-10T00:49:17.045897Z
+1474264
+ahart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+810
+
+apache2.conf.erb
+file
+
+
+
+
+2013-05-24T10:13:54.000000Z
+b4930933223f4be047c732f2101f4f47
+2012-10-10T00:49:17.045897Z
+1474264
+ahart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+8491
+
+security.erb
+file
+
+
+
+
+2013-05-24T10:13:54.000000Z
+ebc22b863b112905b2de1c3af87ba341
+2012-10-10T00:49:17.045897Z
+1474264
+ahart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+1566
+

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/templates/default/.svn/text-base/a2dismod.erb.svn-base
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/templates/default/.svn/text-base/a2dismod.erb.svn-base b/src/main/vm/src/cookbooks/apache2/templates/default/.svn/text-base/a2dismod.erb.svn-base
new file mode 100755
index 0000000..06fb6b3
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/templates/default/.svn/text-base/a2dismod.erb.svn-base
@@ -0,0 +1,22 @@
+#!/bin/sh -e
+
+SYSCONFDIR='<%= node[:apache][:dir] %>'
+
+if [ -z $1 ]; then
+        echo "Which module would you like to disable?"
+        echo -n "Your choices are: "
+        ls $SYSCONFDIR/mods-enabled/*.load | \
+        sed -e "s,$SYSCONFDIR/mods-enabled/,,g" | sed -e 's/\.load$//g;' | xargs echo
+        echo -n "Module name? "
+        read MODNAME
+else
+        MODNAME=$1
+fi
+
+if ! [ -e $SYSCONFDIR/mods-enabled/$MODNAME.load ]; then
+        echo "This module is already disabled, or does not exist!"
+        exit 1
+fi
+
+rm -f $SYSCONFDIR/mods-enabled/$MODNAME.*
+echo "Module $MODNAME disabled; reload apache to fully disable."
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/templates/default/.svn/text-base/a2dissite.erb.svn-base
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/templates/default/.svn/text-base/a2dissite.erb.svn-base b/src/main/vm/src/cookbooks/apache2/templates/default/.svn/text-base/a2dissite.erb.svn-base
new file mode 100755
index 0000000..41feda5
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/templates/default/.svn/text-base/a2dissite.erb.svn-base
@@ -0,0 +1,29 @@
+#!/bin/sh -e
+
+SYSCONFDIR='<%= node[:apache][:dir] %>'
+
+if [ -z $1 ]; then
+        echo "Which site would you like to disable?"
+        echo -n "Your choices are: "
+        ls $node[:apache][:dir]/sites-enabled/* | \
+        sed -e "s,$SYSCONFDIR/sites-enabled/,,g" | xargs echo
+        echo -n "Site name? "
+        read SITENAME
+else
+        SITENAME=$1
+fi
+
+if [ $SITENAME = "default" ]; then
+        PRIORITY="000"
+fi
+
+if ! [ -e $SYSCONFDIR/sites-enabled/$SITENAME -o \
+       -e $SYSCONFDIR/sites-enabled/"$PRIORITY"-"$SITENAME" ]; then
+        echo "This site is already disabled, or does not exist!"
+        exit 1
+fi
+
+if ! rm $SYSCONFDIR/sites-enabled/$SITENAME 2>/dev/null; then
+        rm -f $SYSCONFDIR/sites-enabled/"$PRIORITY"-"$SITENAME"
+fi
+echo "Site $SITENAME disabled; reload apache to disable."
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/templates/default/.svn/text-base/a2enmod.erb.svn-base
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/templates/default/.svn/text-base/a2enmod.erb.svn-base b/src/main/vm/src/cookbooks/apache2/templates/default/.svn/text-base/a2enmod.erb.svn-base
new file mode 100755
index 0000000..a59c72f
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/templates/default/.svn/text-base/a2enmod.erb.svn-base
@@ -0,0 +1,37 @@
+#!/bin/sh -e
+
+SYSCONFDIR='<%= node[:apache][:dir] %>'
+
+if [ -z $1 ]; then
+        echo "Which module would you like to enable?"
+        echo -n "Your choices are: "
+        ls $SYSCONFDIR/mods-available/*.load | \
+        sed -e "s,$SYSCONFDIR/mods-available/,,g" | sed -e 's/\.load$//g;' | xargs echo
+        echo -n "Module name? "
+        read MODNAME
+else
+        MODNAME=$1
+fi
+
+#figure out if we're on a prefork or threaded mpm
+if [ -x /usr/sbin/apache2 ]; then
+        PREFORK=`/usr/sbin/apache2 -l | grep prefork || true`
+fi
+
+if [ -e $SYSCONFDIR/mods-enabled/$MODNAME.load && -e $SYSCONFDIR/mods-enabled/$MODNAME.conf ]; then
+        echo "This module is already enabled!"
+        exit 0 
+fi
+
+if ! [ -e $SYSCONFDIR/mods-available/$MODNAME.load ]; then
+        echo "This module does not exist!"
+        exit 1
+fi
+
+for i in conf load; do 
+        if [ -e $SYSCONFDIR/mods-available/$MODNAME.$i -a ! -e $SYSCONFDIR/mods-enabled/$MODNAME.$i ]; then
+        ln -sf $SYSCONFDIR/mods-available/$MODNAME.$i $SYSCONFDIR/mods-enabled/$MODNAME.$i;
+        fi
+done
+
+echo "Module $MODNAME installed; reload apache to enable."
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/templates/default/.svn/text-base/a2ensite.erb.svn-base
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/templates/default/.svn/text-base/a2ensite.erb.svn-base b/src/main/vm/src/cookbooks/apache2/templates/default/.svn/text-base/a2ensite.erb.svn-base
new file mode 100755
index 0000000..4288869
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/templates/default/.svn/text-base/a2ensite.erb.svn-base
@@ -0,0 +1,38 @@
+#!/bin/sh -e
+
+SYSCONFDIR='<%= node[:apache][:dir] %>'
+
+if [ -z $1 ]; then
+        echo "Which site would you like to enable?"
+        echo -n "Your choices are: "
+        ls $SYSCONFDIR/sites-available/* | \
+        sed -e "s,$SYSCONFDIR/sites-available/,,g" | xargs echo
+        echo -n "Site name? "
+        read SITENAME
+else
+        SITENAME=$1
+fi
+
+if [ $SITENAME = "default" ]; then
+        PRIORITY="000"
+fi
+
+if [ -e $SYSCONFDIR/sites-enabled/$SITENAME -o \
+     -e $SYSCONFDIR/sites-enabled/"$PRIORITY"-"$SITENAME" ]; then
+        echo "This site is already enabled!"
+        exit 0
+fi
+
+if ! [ -e $SYSCONFDIR/sites-available/$SITENAME ]; then
+        echo "This site does not exist!"
+        exit 1
+fi
+
+if [ $SITENAME = "default" ]; then
+        ln -sf $SYSCONFDIR/sites-available/$SITENAME \
+               $SYSCONFDIR/sites-enabled/"$PRIORITY"-"$SITENAME"
+else
+        ln -sf $SYSCONFDIR/sites-available/$SITENAME $SYSCONFDIR/sites-enabled/$SITENAME
+fi
+
+echo "Site $SITENAME installed; reload apache to enable."
\ No newline at end of file


[28/51] [abbrv] [partial] Adding Jinwon's custom RCMET

Posted by jo...@apache.org.
http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/app/font/fontawesome-webfont.woff
----------------------------------------------------------------------
diff --git a/src/main/ui/app/font/fontawesome-webfont.woff b/src/main/ui/app/font/fontawesome-webfont.woff
new file mode 100755
index 0000000..3c89ae0
Binary files /dev/null and b/src/main/ui/app/font/fontawesome-webfont.woff differ

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/app/img/.svn/all-wcprops
----------------------------------------------------------------------
diff --git a/src/main/ui/app/img/.svn/all-wcprops b/src/main/ui/app/img/.svn/all-wcprops
new file mode 100755
index 0000000..d72c861
--- /dev/null
+++ b/src/main/ui/app/img/.svn/all-wcprops
@@ -0,0 +1,17 @@
+K 25
+svn:wc:ra_dav:version-url
+V 77
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/ui/app/img
+END
+glyphicons-halflings-white.png
+K 25
+svn:wc:ra_dav:version-url
+V 108
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/ui/app/img/glyphicons-halflings-white.png
+END
+glyphicons-halflings.png
+K 25
+svn:wc:ra_dav:version-url
+V 102
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/ui/app/img/glyphicons-halflings.png
+END

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/app/img/.svn/entries
----------------------------------------------------------------------
diff --git a/src/main/ui/app/img/.svn/entries b/src/main/ui/app/img/.svn/entries
new file mode 100755
index 0000000..2fd18a9
--- /dev/null
+++ b/src/main/ui/app/img/.svn/entries
@@ -0,0 +1,96 @@
+10
+
+dir
+1485921
+https://svn.apache.org/repos/asf/incubator/climate/trunk/rcmet/src/main/ui/app/img
+https://svn.apache.org/repos/asf
+
+
+
+2013-03-13T02:34:36.621563Z
+1475138
+mjjoyce
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+13f79535-47bb-0310-9956-ffa450edef68
+
+glyphicons-halflings-white.png
+file
+
+
+
+
+2013-05-24T10:13:57.000000Z
+9bbc6e9602998a385c2ea13df56470fd
+2013-03-13T02:34:36.621563Z
+1475138
+mjjoyce
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+8777
+
+glyphicons-halflings.png
+file
+
+
+
+
+2013-05-24T10:13:57.000000Z
+2516339970d710819585f90773aebe0a
+2013-03-13T02:34:36.621563Z
+1475138
+mjjoyce
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+12799
+

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/app/img/.svn/text-base/glyphicons-halflings-white.png.svn-base
----------------------------------------------------------------------
diff --git a/src/main/ui/app/img/.svn/text-base/glyphicons-halflings-white.png.svn-base b/src/main/ui/app/img/.svn/text-base/glyphicons-halflings-white.png.svn-base
new file mode 100755
index 0000000..3bf6484
Binary files /dev/null and b/src/main/ui/app/img/.svn/text-base/glyphicons-halflings-white.png.svn-base differ

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/app/img/.svn/text-base/glyphicons-halflings.png.svn-base
----------------------------------------------------------------------
diff --git a/src/main/ui/app/img/.svn/text-base/glyphicons-halflings.png.svn-base b/src/main/ui/app/img/.svn/text-base/glyphicons-halflings.png.svn-base
new file mode 100755
index 0000000..a996999
Binary files /dev/null and b/src/main/ui/app/img/.svn/text-base/glyphicons-halflings.png.svn-base differ

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/app/img/glyphicons-halflings-white.png
----------------------------------------------------------------------
diff --git a/src/main/ui/app/img/glyphicons-halflings-white.png b/src/main/ui/app/img/glyphicons-halflings-white.png
new file mode 100755
index 0000000..3bf6484
Binary files /dev/null and b/src/main/ui/app/img/glyphicons-halflings-white.png differ

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/app/img/glyphicons-halflings.png
----------------------------------------------------------------------
diff --git a/src/main/ui/app/img/glyphicons-halflings.png b/src/main/ui/app/img/glyphicons-halflings.png
new file mode 100755
index 0000000..a996999
Binary files /dev/null and b/src/main/ui/app/img/glyphicons-halflings.png differ

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/app/index-async.html
----------------------------------------------------------------------
diff --git a/src/main/ui/app/index-async.html b/src/main/ui/app/index-async.html
new file mode 100755
index 0000000..b530660
--- /dev/null
+++ b/src/main/ui/app/index-async.html
@@ -0,0 +1,57 @@
+<!doctype html>
+<html lang="en">
+<head>
+  <meta charset="utf-8">
+  <style>
+    [ng-cloak] {
+      display: none;
+    }
+  </style>
+  <script>
+    // include angular loader, which allows the files to load in any order
+    /*
+     AngularJS v1.0.0rc1
+     (c) 2010-2012 AngularJS http://angularjs.org
+     License: MIT
+    */
+    'use strict';(function(i){function d(c,a,e){return c[a]||(c[a]=e())}return d(d(i,"angular",Object),"module",function(){var c={};return function(a,e,f){e&&c.hasOwnProperty(a)&&(c[a]=null);return d(c,a,function(){function b(a,b,d){return function(){c[d||"push"]([a,b,arguments]);return g}}if(!e)throw Error("No module: "+a);var c=[],d=[],h=b("$injector","invoke"),g={_invokeQueue:c,_runBlocks:d,requires:e,name:a,provider:b("$provide","provider"),factory:b("$provide","factory"),service:b("$provide","service"),
+    value:b("$provide","value"),constant:b("$provide","constant","unshift"),filter:b("$filterProvider","register"),directive:b("$compileProvider","directive"),config:h,run:function(a){d.push(a);return this}};f&&h(f);return g})}})})(window);
+
+    // include a third-party async loader library
+    /*!
+     * $script.js v1.3
+     * https://github.com/ded/script.js
+     * Copyright: @ded & @fat - Dustin Diaz, Jacob Thornton 2011
+     * Follow our software http://twitter.com/dedfat
+     * License: MIT
+     */
+    !function(a,b,c){function t(a,c){var e=b.createElement("script"),f=j;e.onload=e.onerror=e[o]=function(){e[m]&&!/^c|loade/.test(e[m])||f||(e.onload=e[o]=null,f=1,c())},e.async=1,e.src=a,d.insertBefore(e,d.firstChild)}function q(a,b){p(a,function(a){return!b(a)})}var d=b.getElementsByTagName("head")[0],e={},f={},g={},h={},i="string",j=!1,k="push",l="DOMContentLoaded",m="readyState",n="addEventListener",o="onreadystatechange",p=function(a,b){for(var c=0,d=a.length;c<d;++c)if(!b(a[c]))return j;return 1};!b[m]&&b[n]&&(b[n](l,function r(){b.removeEventListener(l,r,j),b[m]="complete"},j),b[m]="loading");var s=function(a,b,d){function o(){if(!--m){e[l]=1,j&&j();for(var a in g)p(a.split("|"),n)&&!q(g[a],n)&&(g[a]=[])}}function n(a){return a.call?a():e[a]}a=a[k]?a:[a];var i=b&&b.call,j=i?b:d,l=i?a.join(""):b,m=a.length;c(function(){q(a,function(a){h[a]?(l&&(f[l]=1),o()):(h[a]=1,l&&(f[l]=1),t(s.path?s.path+a+".js":a,o))})},0);return s};s.get=t,s.ready=function(a,b,c){a=a[k]?a:[a];var d=[];
 !q(a,function(a){e[a]||d[k](a)})&&p(a,function(a){return e[a]})?b():!function(a){g[a]=g[a]||[],g[a][k](b),c&&c(d)}(a.join("|"));return s};var u=a.$script;s.noConflict=function(){a.$script=u;return this},typeof module!="undefined"&&module.exports?module.exports=s:a.$script=s}(this,document,setTimeout)
+
+    // load all of the dependencies asynchronously.
+    $script([
+      'lib/angular/angular.js',
+      'js/app.js',
+      'js/services.js',
+      'js/controllers.js',
+      'js/filters.js',
+      'js/directives.js'
+    ], function() {
+      // when all is done, execute bootstrap angular application
+      angular.bootstrap(document, ['myApp']);
+    });
+  </script>
+  <title>My AngularJS App</title>
+  <link rel="stylesheet" href="css/app.css">
+</head>
+<body ng-cloak>
+  <ul class="menu">
+    <li><a href="#/view1">view1</a></li>
+    <li><a href="#/view2">view2</a></li>
+  </ul>
+
+  <div ng-view></div>
+
+  <div>Angular seed app: v<span app-version></span></div>
+
+</body>
+</html>

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/app/index.html
----------------------------------------------------------------------
diff --git a/src/main/ui/app/index.html b/src/main/ui/app/index.html
new file mode 100755
index 0000000..db85cf4
--- /dev/null
+++ b/src/main/ui/app/index.html
@@ -0,0 +1,192 @@
+<!doctype html>
+<html lang="en" ng-app="rcmes">
+<head>
+  <meta charset="utf-8">
+  <meta name="viewport" content="width=device-width, initial-scale=1.0">
+  <title>RCMET UI</title>
+  <link rel="stylesheet" href="css/bootstrap.min.css"/>
+  <link rel="stylesheet" href="css/bootstrap-responsive.min.css"/>
+  <link rel="stylesheet" href="css/jasny-bootstrap.min.css"/>
+  <link rel="stylesheet" href="css/jasny-bootstrap-responsive.min.css"/>
+  <link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet-0.5/leaflet.css" />
+  <link rel="stylesheet" href="css/font-awesome.min.css"/>
+  <!--[if lte IE 8]>
+    <link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet-0.5/leaflet.ie.css" />
+  <![endif]-->
+  <link rel="stylesheet" href="css/app.css"/>
+</head>
+<body>
+  <bootstrap-modal modal-id="datasetSelect">
+	<div class="modal-header">
+		<button class="close">&times;</button>
+		<h3>Dataset Select</h3>
+	</div>
+	<div class="modal-body">
+		<div ng-view></div>
+	</div>
+	<div class="modal-footer">
+		<a href="#" class="btn btn-primary close">Close</a>
+	</div>
+  </bootstrap-modal>
+
+  <bootstrap-modal modal-id="evaluationResults">
+  <div class="modal-header">
+  	<button class="close">&times;</button>
+  	<h3>Evaluation Results</h3>
+  </div>
+  <div class="modal-body">
+	  <p>
+	  Comparison: <a href="{{baseURL}}/static/evalResults/{{evalResults.comparisonPath}}">
+		  {{evalResults.comparisonPath}}</a>
+	  </p>
+	  <p>
+	  Model: <a href="{{baseURL}}/static/evalResults/{{evalResults.modelPath}}">
+		  {{evalResults.modelPath}}</a>
+	  </p>
+	  <p>
+	  Observation: <a href="{{baseURL}}/static/evalResults/{{evalResults.obsPath}}">
+		  {{evalResults.obsPath}}</a>
+	  </p>
+	  <p><img src="{{baseURL}}/static/evalResults/{{evalResults.comparisonPath}}" alt="" /></p>
+	  <p><img src="{{baseURL}}/static/evalResults/{{evalResults.modelPath}}" alt="" /></p>
+	  <p><img src="{{baseURL}}/static/evalResults/{{evalResults.obsPath}}" alt="" /></p>
+  </div>
+  <div class="modal-footer">
+	  <a href="#" class="btn btn-primary close">Close</a>
+  </div>
+  </bootstrap-modal>
+
+  <h1 id="rcmetHeader">RCMET UI</h1>
+  <div ng-controller="WorldMapCtrl">
+    <sap id="map"></sap>
+  </div>
+
+  <div ng-controller="ParameterSelectCtrl">
+    <div class="row">
+      <div class="span1 offset2 text-center">Start Date:</div>
+      <div class="span2">
+        <form>
+      <input ng-model="displayParams.start" type="text" class="span2" />
+        </form>
+      </div>
+      <div class="span1 text-center">End Date:</div>
+      <div class="span2">
+        <form>
+		  <input ng-model="displayParams.end" type="text" class="span2" />
+        </form>
+      </div>
+      <div class="span1">
+		<button ng-click="runEvaluation()" ng-disabled="shouldDisableEvaluate()" class="btn btn-block btn-primary">
+		  <div ng-hide="runningEval">Evaluate</div>
+		  <div ng-show="runningEval"><i class="icon-spinner icon-spin"></i></div>
+		</button>
+      </div>
+      <div class="span2">
+        <button class="btn btn-block btn-success" bootstrap-modal-open="datasetSelect">Select a Dataset</button>
+      </div>
+	  <div class="span1">
+		  <button class="btn btn-block btn-primary" ng-disabled="shouldDisableResultsView()" bootstrap-modal-open="evaluationResults">Results</button>
+	  </div>
+    </div>
+    <div class="row">
+      <div class="span1 offset2 text-center">North:</div>
+      <div class="span2">
+        <form action="">
+		  <input ng-model="displayParams.latMax" type="text" class="span2" />
+        </form>
+      </div>
+      <div class="span1 text-center">East:</div>
+      <div class="span2">
+        <form>
+		  <input ng-model="displayParams.lonMax" type="text" class="span2" />
+        </form>
+      </div>
+      <div class="span1">
+        <button ng-click="updateParameters()" ng-disabled="shouldDisableControls()" class="btn btn-block btn-info">Update</button>
+      </div>
+	  <div class="span2">
+		<button ng-click="clearDatasets()" ng-disabled="shouldDisableClearButton()" class="btn btn-block btn-warning">Clear Datasets</button>
+	  </div>
+    </div>
+    <div class="row">
+      <div class="span1 offset2 text-center">South:</div>
+      <div class="span2">
+        <form action="">
+		  <input ng-model="displayParams.latMin" type="text" class="span2" />
+        </form>
+      </div>
+      <div class="span1 text-center">West:</div>
+      <div class="span2">
+        <form>
+		  <input ng-model="displayParams.lonMin" type="text" class="span2" />
+        </form>
+      </div>
+    </div>
+  </div>
+  <!--Dataset display-->
+  <div ng-controller="DatasetDisplayCtrl">
+    <div ng-repeat="dataset in datasets">
+	  <div class="row displayRow">
+  	    <div class="span10 offset2"><hr /></div>
+	  </div>
+	  <div class="row displayRow">
+		<div class="span4 offset2">
+		  <input class="span6 text-center" type="text" value="{{dataset.name}}" />
+		</div>
+	  </div>
+	  <!--Time Values!-->
+      <div class="row displayRow">
+        <div class="span1 offset2 text-center">Start Date:</div>
+		<div class="span2">
+		  <input class="span2 text-center" type="text" value="{{dataset.timeVals.start}}" readonly/>
+		</div>
+        <div class="span1 text-center">End Date:</div>
+		<div class="span2">
+		  <input class="span2 text-center" type="text" value="{{dataset.timeVals.end}}" readonly/>
+		</div>
+	  </div>
+	  <!--Lat/Long Values!-->
+      <div class="row displayRow">
+        <div class="span1 offset2 text-center">North:</div>
+		<div class="span2">
+		  <input class="span2 text-center" type="text" value="{{dataset.latlonVals.latMax}}" readonly/>
+		</div>
+        <div class="span1 text-center">East:</div>
+		<div class="span2">
+		  <input class="span2 text-center" type="text" value="{{dataset.latlonVals.lonMax}}" readonly/>
+		</div>
+		<div class="span2">
+		  <a class="btn btn-block" ng-click="removeDataset($index)">Remove Dataset</a>
+		</div>
+    <div class="span1" style="background-color: {{fillColors[$index]}}; height: 28px; width: 28px;"></div>
+	  </div>
+      <div class="row displayRow">
+        <div class="span1 offset2 text-center">South:</div>
+		<div class="span2">
+		  <input class="span2 text-center" type="text" value="{{dataset.latlonVals.latMin}}" readonly/>
+		</div>
+        <div class="span1 text-center">West:</div>
+		<div class="span2">
+		  <input class="span2 text-center" type="text" value="{{dataset.latlonVals.lonMin}}" readonly/>
+		</div>
+	  </div>
+    </div>
+  </div>
+
+  <!-- In production use:
+  <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.0.4/angular.min.js"></script>
+  -->
+  <!--<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>-->
+  <script src="http://code.jquery.com/jquery.js"></script>
+  <!--<script src="js/bootstrap.min.js"></script>-->
+  <script src="js/bootstrap.js"></script>
+  <script src="js/jasny-bootstrap.min.js"></script>
+  <script src="lib/angular/angular.js"></script>
+  <script src="http://cdn.leafletjs.com/leaflet-0.5/leaflet.js"></script>
+  <script src="js/app.js"></script>
+  <script src="js/services.js"></script>
+  <script src="js/controllers.js"></script>
+  <script src="js/filters.js"></script>
+  <script src="js/directives.js"></script>
+</body>
+</html>

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/app/js/.svn/all-wcprops
----------------------------------------------------------------------
diff --git a/src/main/ui/app/js/.svn/all-wcprops b/src/main/ui/app/js/.svn/all-wcprops
new file mode 100755
index 0000000..73e76ec
--- /dev/null
+++ b/src/main/ui/app/js/.svn/all-wcprops
@@ -0,0 +1,65 @@
+K 25
+svn:wc:ra_dav:version-url
+V 76
+/repos/asf/!svn/ver/1485460/incubator/climate/trunk/rcmet/src/main/ui/app/js
+END
+jquery-1.9.1.min.js
+K 25
+svn:wc:ra_dav:version-url
+V 96
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/ui/app/js/jquery-1.9.1.min.js
+END
+controllers.js
+K 25
+svn:wc:ra_dav:version-url
+V 91
+/repos/asf/!svn/ver/1485460/incubator/climate/trunk/rcmet/src/main/ui/app/js/controllers.js
+END
+filters.js
+K 25
+svn:wc:ra_dav:version-url
+V 87
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/ui/app/js/filters.js
+END
+leaflet.js
+K 25
+svn:wc:ra_dav:version-url
+V 87
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/ui/app/js/leaflet.js
+END
+bootstrap.js
+K 25
+svn:wc:ra_dav:version-url
+V 89
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/ui/app/js/bootstrap.js
+END
+bootstrap.min.js
+K 25
+svn:wc:ra_dav:version-url
+V 93
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/ui/app/js/bootstrap.min.js
+END
+app.js
+K 25
+svn:wc:ra_dav:version-url
+V 83
+/repos/asf/!svn/ver/1485460/incubator/climate/trunk/rcmet/src/main/ui/app/js/app.js
+END
+directives.js
+K 25
+svn:wc:ra_dav:version-url
+V 90
+/repos/asf/!svn/ver/1485460/incubator/climate/trunk/rcmet/src/main/ui/app/js/directives.js
+END
+jasny-bootstrap.min.js
+K 25
+svn:wc:ra_dav:version-url
+V 99
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/ui/app/js/jasny-bootstrap.min.js
+END
+services.js
+K 25
+svn:wc:ra_dav:version-url
+V 88
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/ui/app/js/services.js
+END

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/app/js/.svn/entries
----------------------------------------------------------------------
diff --git a/src/main/ui/app/js/.svn/entries b/src/main/ui/app/js/.svn/entries
new file mode 100755
index 0000000..aa31055
--- /dev/null
+++ b/src/main/ui/app/js/.svn/entries
@@ -0,0 +1,368 @@
+10
+
+dir
+1485921
+https://svn.apache.org/repos/asf/incubator/climate/trunk/rcmet/src/main/ui/app/js
+https://svn.apache.org/repos/asf
+
+
+
+2013-05-22T22:03:47.963281Z
+1485460
+joyce
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+13f79535-47bb-0310-9956-ffa450edef68
+
+jquery-1.9.1.min.js
+file
+
+
+
+
+2013-05-24T10:13:57.000000Z
+397754ba49e9e0cf4e7c190da78dda05
+2013-03-13T02:34:46.909552Z
+1475146
+mjjoyce
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+92629
+
+controllers.js
+file
+
+
+
+
+2013-05-24T10:13:57.000000Z
+aa6527ef6f079c64c282ccb7263451a5
+2013-05-22T22:03:47.963281Z
+1485460
+joyce
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+20198
+
+filters.js
+file
+
+
+
+
+2013-05-24T10:13:57.000000Z
+d07dd2d5fb6d70fe1ea77c7d5e00ad19
+2013-03-13T02:34:30.834306Z
+1475137
+mjjoyce
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+225
+
+leaflet.js
+file
+
+
+
+
+2013-05-24T10:13:57.000000Z
+bae2b6d5c49c0106494ae69cabd0a286
+2013-03-13T02:34:46.909552Z
+1475146
+mjjoyce
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+112650
+
+bootstrap.js
+file
+
+
+
+
+2013-05-24T10:13:57.000000Z
+4c24933a54aa9164ff84cf837821ac85
+2013-03-13T02:34:46.909552Z
+1475146
+mjjoyce
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+61752
+
+bootstrap.min.js
+file
+
+
+
+
+2013-05-24T10:13:57.000000Z
+2916bdd0ab40bc45f6cb6d5b99e34368
+2013-03-13T02:34:46.909552Z
+1475146
+mjjoyce
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+28538
+
+app.js
+file
+
+
+
+
+2013-05-24T10:13:57.000000Z
+7cf3b265c8e03751e875076387647efa
+2013-05-22T22:03:47.963281Z
+1485460
+joyce
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+1375
+
+directives.js
+file
+
+
+
+
+2013-05-24T10:13:57.000000Z
+03f470b0f0547608190912a438c219d6
+2013-05-22T22:03:47.963281Z
+1485460
+joyce
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+11712
+
+jasny-bootstrap.min.js
+file
+
+
+
+
+2013-05-24T10:13:57.000000Z
+d1e483216804fa436b02cf02c53cc743
+2013-03-25T17:12:04.245722Z
+1475246
+mjjoyce
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+17134
+
+services.js
+file
+
+
+
+
+2013-05-24T10:13:57.000000Z
+2ef365dc571d74da361c4e0d9577291e
+2013-03-13T02:34:30.834306Z
+1475137
+mjjoyce
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+183
+

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/app/js/.svn/prop-base/app.js.svn-base
----------------------------------------------------------------------
diff --git a/src/main/ui/app/js/.svn/prop-base/app.js.svn-base b/src/main/ui/app/js/.svn/prop-base/app.js.svn-base
new file mode 100755
index 0000000..869ac71
--- /dev/null
+++ b/src/main/ui/app/js/.svn/prop-base/app.js.svn-base
@@ -0,0 +1,5 @@
+K 14
+svn:executable
+V 1
+*
+END

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/app/js/.svn/prop-base/bootstrap.min.js.svn-base
----------------------------------------------------------------------
diff --git a/src/main/ui/app/js/.svn/prop-base/bootstrap.min.js.svn-base b/src/main/ui/app/js/.svn/prop-base/bootstrap.min.js.svn-base
new file mode 100755
index 0000000..869ac71
--- /dev/null
+++ b/src/main/ui/app/js/.svn/prop-base/bootstrap.min.js.svn-base
@@ -0,0 +1,5 @@
+K 14
+svn:executable
+V 1
+*
+END

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/app/js/.svn/prop-base/controllers.js.svn-base
----------------------------------------------------------------------
diff --git a/src/main/ui/app/js/.svn/prop-base/controllers.js.svn-base b/src/main/ui/app/js/.svn/prop-base/controllers.js.svn-base
new file mode 100755
index 0000000..869ac71
--- /dev/null
+++ b/src/main/ui/app/js/.svn/prop-base/controllers.js.svn-base
@@ -0,0 +1,5 @@
+K 14
+svn:executable
+V 1
+*
+END

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/app/js/.svn/prop-base/directives.js.svn-base
----------------------------------------------------------------------
diff --git a/src/main/ui/app/js/.svn/prop-base/directives.js.svn-base b/src/main/ui/app/js/.svn/prop-base/directives.js.svn-base
new file mode 100755
index 0000000..869ac71
--- /dev/null
+++ b/src/main/ui/app/js/.svn/prop-base/directives.js.svn-base
@@ -0,0 +1,5 @@
+K 14
+svn:executable
+V 1
+*
+END

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/app/js/.svn/prop-base/filters.js.svn-base
----------------------------------------------------------------------
diff --git a/src/main/ui/app/js/.svn/prop-base/filters.js.svn-base b/src/main/ui/app/js/.svn/prop-base/filters.js.svn-base
new file mode 100755
index 0000000..869ac71
--- /dev/null
+++ b/src/main/ui/app/js/.svn/prop-base/filters.js.svn-base
@@ -0,0 +1,5 @@
+K 14
+svn:executable
+V 1
+*
+END

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/app/js/.svn/prop-base/services.js.svn-base
----------------------------------------------------------------------
diff --git a/src/main/ui/app/js/.svn/prop-base/services.js.svn-base b/src/main/ui/app/js/.svn/prop-base/services.js.svn-base
new file mode 100755
index 0000000..869ac71
--- /dev/null
+++ b/src/main/ui/app/js/.svn/prop-base/services.js.svn-base
@@ -0,0 +1,5 @@
+K 14
+svn:executable
+V 1
+*
+END

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/app/js/.svn/text-base/app.js.svn-base
----------------------------------------------------------------------
diff --git a/src/main/ui/app/js/.svn/text-base/app.js.svn-base b/src/main/ui/app/js/.svn/text-base/app.js.svn-base
new file mode 100755
index 0000000..47b9e73
--- /dev/null
+++ b/src/main/ui/app/js/.svn/text-base/app.js.svn-base
@@ -0,0 +1,53 @@
+'use strict';
+
+angular.module('rcmes', []).
+	config(['$routeProvider', function($routeProvider) {
+		$routeProvider.
+			when('/obs', {templateUrl: 'partials/selectObservation.html',   controller: ObservationSelectCtrl}).
+			when('/rcmed', {templateUrl: 'partials/selectRcmed.html', controller: RcmedSelectionCtrl}).
+			otherwise({redirectTo: '/obs'});
+	}]).
+	run(function($rootScope) {
+		$rootScope.evalResults = ""; 
+		$rootScope.fillColors = ['#ff0000', '#00c90d', '#cd0074', '#f3fd00'];
+		$rootScope.surroundColors = ['#a60000', '#008209', '#8f004b', '#93a400']
+		$rootScope.baseURL = 'http://localhost:8082';
+	}).
+	service('selectedDatasetInformation', function() {
+		var datasets = [];
+
+		return {
+			getDatasets: function() {
+				return datasets;
+			},
+			getDatasetCount: function() {
+				return datasets.length;
+			},
+			// TODO: Define the structure of the objects that are added with addDataset.
+			addDataset: function(dataset) {
+				datasets.push(dataset);
+			},
+			removeDataset: function(index) {
+				datasets.splice(index, 1);
+			},
+			clearDatasets: function() {
+				datasets.length = 0;
+			},
+		};
+	}).
+	service('regionSelectParams', function() {
+		var parameters = {
+			"latMin": "",
+			"latMax": "",
+			"lonMin": "",
+			"lonMax": "",
+			"start" : "",
+			"end"   : "",
+		};
+
+		return {
+			getParameters: function() {
+				return parameters;
+			},
+		};
+   });

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/app/js/.svn/text-base/bootstrap.js.svn-base
----------------------------------------------------------------------
diff --git a/src/main/ui/app/js/.svn/text-base/bootstrap.js.svn-base b/src/main/ui/app/js/.svn/text-base/bootstrap.js.svn-base
new file mode 100755
index 0000000..c298ee4
--- /dev/null
+++ b/src/main/ui/app/js/.svn/text-base/bootstrap.js.svn-base
@@ -0,0 +1,2276 @@
+/* ===================================================
+ * bootstrap-transition.js v2.3.1
+ * http://twitter.github.com/bootstrap/javascript.html#transitions
+ * ===================================================
+ * Copyright 2012 Twitter, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ========================================================== */
+
+
+!function ($) {
+
+  "use strict"; // jshint ;_;
+
+
+  /* CSS TRANSITION SUPPORT (http://www.modernizr.com/)
+   * ======================================================= */
+
+  $(function () {
+
+    $.support.transition = (function () {
+
+      var transitionEnd = (function () {
+
+        var el = document.createElement('bootstrap')
+          , transEndEventNames = {
+               'WebkitTransition' : 'webkitTransitionEnd'
+            ,  'MozTransition'    : 'transitionend'
+            ,  'OTransition'      : 'oTransitionEnd otransitionend'
+            ,  'transition'       : 'transitionend'
+            }
+          , name
+
+        for (name in transEndEventNames){
+          if (el.style[name] !== undefined) {
+            return transEndEventNames[name]
+          }
+        }
+
+      }())
+
+      return transitionEnd && {
+        end: transitionEnd
+      }
+
+    })()
+
+  })
+
+}(window.jQuery);/* ==========================================================
+ * bootstrap-alert.js v2.3.1
+ * http://twitter.github.com/bootstrap/javascript.html#alerts
+ * ==========================================================
+ * Copyright 2012 Twitter, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ========================================================== */
+
+
+!function ($) {
+
+  "use strict"; // jshint ;_;
+
+
+ /* ALERT CLASS DEFINITION
+  * ====================== */
+
+  var dismiss = '[data-dismiss="alert"]'
+    , Alert = function (el) {
+        $(el).on('click', dismiss, this.close)
+      }
+
+  Alert.prototype.close = function (e) {
+    var $this = $(this)
+      , selector = $this.attr('data-target')
+      , $parent
+
+    if (!selector) {
+      selector = $this.attr('href')
+      selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') //strip for ie7
+    }
+
+    $parent = $(selector)
+
+    e && e.preventDefault()
+
+    $parent.length || ($parent = $this.hasClass('alert') ? $this : $this.parent())
+
+    $parent.trigger(e = $.Event('close'))
+
+    if (e.isDefaultPrevented()) return
+
+    $parent.removeClass('in')
+
+    function removeElement() {
+      $parent
+        .trigger('closed')
+        .remove()
+    }
+
+    $.support.transition && $parent.hasClass('fade') ?
+      $parent.on($.support.transition.end, removeElement) :
+      removeElement()
+  }
+
+
+ /* ALERT PLUGIN DEFINITION
+  * ======================= */
+
+  var old = $.fn.alert
+
+  $.fn.alert = function (option) {
+    return this.each(function () {
+      var $this = $(this)
+        , data = $this.data('alert')
+      if (!data) $this.data('alert', (data = new Alert(this)))
+      if (typeof option == 'string') data[option].call($this)
+    })
+  }
+
+  $.fn.alert.Constructor = Alert
+
+
+ /* ALERT NO CONFLICT
+  * ================= */
+
+  $.fn.alert.noConflict = function () {
+    $.fn.alert = old
+    return this
+  }
+
+
+ /* ALERT DATA-API
+  * ============== */
+
+  $(document).on('click.alert.data-api', dismiss, Alert.prototype.close)
+
+}(window.jQuery);/* ============================================================
+ * bootstrap-button.js v2.3.1
+ * http://twitter.github.com/bootstrap/javascript.html#buttons
+ * ============================================================
+ * Copyright 2012 Twitter, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============================================================ */
+
+
+!function ($) {
+
+  "use strict"; // jshint ;_;
+
+
+ /* BUTTON PUBLIC CLASS DEFINITION
+  * ============================== */
+
+  var Button = function (element, options) {
+    this.$element = $(element)
+    this.options = $.extend({}, $.fn.button.defaults, options)
+  }
+
+  Button.prototype.setState = function (state) {
+    var d = 'disabled'
+      , $el = this.$element
+      , data = $el.data()
+      , val = $el.is('input') ? 'val' : 'html'
+
+    state = state + 'Text'
+    data.resetText || $el.data('resetText', $el[val]())
+
+    $el[val](data[state] || this.options[state])
+
+    // push to event loop to allow forms to submit
+    setTimeout(function () {
+      state == 'loadingText' ?
+        $el.addClass(d).attr(d, d) :
+        $el.removeClass(d).removeAttr(d)
+    }, 0)
+  }
+
+  Button.prototype.toggle = function () {
+    var $parent = this.$element.closest('[data-toggle="buttons-radio"]')
+
+    $parent && $parent
+      .find('.active')
+      .removeClass('active')
+
+    this.$element.toggleClass('active')
+  }
+
+
+ /* BUTTON PLUGIN DEFINITION
+  * ======================== */
+
+  var old = $.fn.button
+
+  $.fn.button = function (option) {
+    return this.each(function () {
+      var $this = $(this)
+        , data = $this.data('button')
+        , options = typeof option == 'object' && option
+      if (!data) $this.data('button', (data = new Button(this, options)))
+      if (option == 'toggle') data.toggle()
+      else if (option) data.setState(option)
+    })
+  }
+
+  $.fn.button.defaults = {
+    loadingText: 'loading...'
+  }
+
+  $.fn.button.Constructor = Button
+
+
+ /* BUTTON NO CONFLICT
+  * ================== */
+
+  $.fn.button.noConflict = function () {
+    $.fn.button = old
+    return this
+  }
+
+
+ /* BUTTON DATA-API
+  * =============== */
+
+  $(document).on('click.button.data-api', '[data-toggle^=button]', function (e) {
+    var $btn = $(e.target)
+    if (!$btn.hasClass('btn')) $btn = $btn.closest('.btn')
+    $btn.button('toggle')
+  })
+
+}(window.jQuery);/* ==========================================================
+ * bootstrap-carousel.js v2.3.1
+ * http://twitter.github.com/bootstrap/javascript.html#carousel
+ * ==========================================================
+ * Copyright 2012 Twitter, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ========================================================== */
+
+
+!function ($) {
+
+  "use strict"; // jshint ;_;
+
+
+ /* CAROUSEL CLASS DEFINITION
+  * ========================= */
+
+  var Carousel = function (element, options) {
+    this.$element = $(element)
+    this.$indicators = this.$element.find('.carousel-indicators')
+    this.options = options
+    this.options.pause == 'hover' && this.$element
+      .on('mouseenter', $.proxy(this.pause, this))
+      .on('mouseleave', $.proxy(this.cycle, this))
+  }
+
+  Carousel.prototype = {
+
+    cycle: function (e) {
+      if (!e) this.paused = false
+      if (this.interval) clearInterval(this.interval);
+      this.options.interval
+        && !this.paused
+        && (this.interval = setInterval($.proxy(this.next, this), this.options.interval))
+      return this
+    }
+
+  , getActiveIndex: function () {
+      this.$active = this.$element.find('.item.active')
+      this.$items = this.$active.parent().children()
+      return this.$items.index(this.$active)
+    }
+
+  , to: function (pos) {
+      var activeIndex = this.getActiveIndex()
+        , that = this
+
+      if (pos > (this.$items.length - 1) || pos < 0) return
+
+      if (this.sliding) {
+        return this.$element.one('slid', function () {
+          that.to(pos)
+        })
+      }
+
+      if (activeIndex == pos) {
+        return this.pause().cycle()
+      }
+
+      return this.slide(pos > activeIndex ? 'next' : 'prev', $(this.$items[pos]))
+    }
+
+  , pause: function (e) {
+      if (!e) this.paused = true
+      if (this.$element.find('.next, .prev').length && $.support.transition.end) {
+        this.$element.trigger($.support.transition.end)
+        this.cycle(true)
+      }
+      clearInterval(this.interval)
+      this.interval = null
+      return this
+    }
+
+  , next: function () {
+      if (this.sliding) return
+      return this.slide('next')
+    }
+
+  , prev: function () {
+      if (this.sliding) return
+      return this.slide('prev')
+    }
+
+  , slide: function (type, next) {
+      var $active = this.$element.find('.item.active')
+        , $next = next || $active[type]()
+        , isCycling = this.interval
+        , direction = type == 'next' ? 'left' : 'right'
+        , fallback  = type == 'next' ? 'first' : 'last'
+        , that = this
+        , e
+
+      this.sliding = true
+
+      isCycling && this.pause()
+
+      $next = $next.length ? $next : this.$element.find('.item')[fallback]()
+
+      e = $.Event('slide', {
+        relatedTarget: $next[0]
+      , direction: direction
+      })
+
+      if ($next.hasClass('active')) return
+
+      if (this.$indicators.length) {
+        this.$indicators.find('.active').removeClass('active')
+        this.$element.one('slid', function () {
+          var $nextIndicator = $(that.$indicators.children()[that.getActiveIndex()])
+          $nextIndicator && $nextIndicator.addClass('active')
+        })
+      }
+
+      if ($.support.transition && this.$element.hasClass('slide')) {
+        this.$element.trigger(e)
+        if (e.isDefaultPrevented()) return
+        $next.addClass(type)
+        $next[0].offsetWidth // force reflow
+        $active.addClass(direction)
+        $next.addClass(direction)
+        this.$element.one($.support.transition.end, function () {
+          $next.removeClass([type, direction].join(' ')).addClass('active')
+          $active.removeClass(['active', direction].join(' '))
+          that.sliding = false
+          setTimeout(function () { that.$element.trigger('slid') }, 0)
+        })
+      } else {
+        this.$element.trigger(e)
+        if (e.isDefaultPrevented()) return
+        $active.removeClass('active')
+        $next.addClass('active')
+        this.sliding = false
+        this.$element.trigger('slid')
+      }
+
+      isCycling && this.cycle()
+
+      return this
+    }
+
+  }
+
+
+ /* CAROUSEL PLUGIN DEFINITION
+  * ========================== */
+
+  var old = $.fn.carousel
+
+  $.fn.carousel = function (option) {
+    return this.each(function () {
+      var $this = $(this)
+        , data = $this.data('carousel')
+        , options = $.extend({}, $.fn.carousel.defaults, typeof option == 'object' && option)
+        , action = typeof option == 'string' ? option : options.slide
+      if (!data) $this.data('carousel', (data = new Carousel(this, options)))
+      if (typeof option == 'number') data.to(option)
+      else if (action) data[action]()
+      else if (options.interval) data.pause().cycle()
+    })
+  }
+
+  $.fn.carousel.defaults = {
+    interval: 5000
+  , pause: 'hover'
+  }
+
+  $.fn.carousel.Constructor = Carousel
+
+
+ /* CAROUSEL NO CONFLICT
+  * ==================== */
+
+  $.fn.carousel.noConflict = function () {
+    $.fn.carousel = old
+    return this
+  }
+
+ /* CAROUSEL DATA-API
+  * ================= */
+
+  $(document).on('click.carousel.data-api', '[data-slide], [data-slide-to]', function (e) {
+    var $this = $(this), href
+      , $target = $($this.attr('data-target') || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '')) //strip for ie7
+      , options = $.extend({}, $target.data(), $this.data())
+      , slideIndex
+
+    $target.carousel(options)
+
+    if (slideIndex = $this.attr('data-slide-to')) {
+      $target.data('carousel').pause().to(slideIndex).cycle()
+    }
+
+    e.preventDefault()
+  })
+
+}(window.jQuery);/* =============================================================
+ * bootstrap-collapse.js v2.3.1
+ * http://twitter.github.com/bootstrap/javascript.html#collapse
+ * =============================================================
+ * Copyright 2012 Twitter, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============================================================ */
+
+
+!function ($) {
+
+  "use strict"; // jshint ;_;
+
+
+ /* COLLAPSE PUBLIC CLASS DEFINITION
+  * ================================ */
+
+  var Collapse = function (element, options) {
+    this.$element = $(element)
+    this.options = $.extend({}, $.fn.collapse.defaults, options)
+
+    if (this.options.parent) {
+      this.$parent = $(this.options.parent)
+    }
+
+    this.options.toggle && this.toggle()
+  }
+
+  Collapse.prototype = {
+
+    constructor: Collapse
+
+  , dimension: function () {
+      var hasWidth = this.$element.hasClass('width')
+      return hasWidth ? 'width' : 'height'
+    }
+
+  , show: function () {
+      var dimension
+        , scroll
+        , actives
+        , hasData
+
+      if (this.transitioning || this.$element.hasClass('in')) return
+
+      dimension = this.dimension()
+      scroll = $.camelCase(['scroll', dimension].join('-'))
+      actives = this.$parent && this.$parent.find('> .accordion-group > .in')
+
+      if (actives && actives.length) {
+        hasData = actives.data('collapse')
+        if (hasData && hasData.transitioning) return
+        actives.collapse('hide')
+        hasData || actives.data('collapse', null)
+      }
+
+      this.$element[dimension](0)
+      this.transition('addClass', $.Event('show'), 'shown')
+      $.support.transition && this.$element[dimension](this.$element[0][scroll])
+    }
+
+  , hide: function () {
+      var dimension
+      if (this.transitioning || !this.$element.hasClass('in')) return
+      dimension = this.dimension()
+      this.reset(this.$element[dimension]())
+      this.transition('removeClass', $.Event('hide'), 'hidden')
+      this.$element[dimension](0)
+    }
+
+  , reset: function (size) {
+      var dimension = this.dimension()
+
+      this.$element
+        .removeClass('collapse')
+        [dimension](size || 'auto')
+        [0].offsetWidth
+
+      this.$element[size !== null ? 'addClass' : 'removeClass']('collapse')
+
+      return this
+    }
+
+  , transition: function (method, startEvent, completeEvent) {
+      var that = this
+        , complete = function () {
+            if (startEvent.type == 'show') that.reset()
+            that.transitioning = 0
+            that.$element.trigger(completeEvent)
+          }
+
+      this.$element.trigger(startEvent)
+
+      if (startEvent.isDefaultPrevented()) return
+
+      this.transitioning = 1
+
+      this.$element[method]('in')
+
+      $.support.transition && this.$element.hasClass('collapse') ?
+        this.$element.one($.support.transition.end, complete) :
+        complete()
+    }
+
+  , toggle: function () {
+      this[this.$element.hasClass('in') ? 'hide' : 'show']()
+    }
+
+  }
+
+
+ /* COLLAPSE PLUGIN DEFINITION
+  * ========================== */
+
+  var old = $.fn.collapse
+
+  $.fn.collapse = function (option) {
+    return this.each(function () {
+      var $this = $(this)
+        , data = $this.data('collapse')
+        , options = $.extend({}, $.fn.collapse.defaults, $this.data(), typeof option == 'object' && option)
+      if (!data) $this.data('collapse', (data = new Collapse(this, options)))
+      if (typeof option == 'string') data[option]()
+    })
+  }
+
+  $.fn.collapse.defaults = {
+    toggle: true
+  }
+
+  $.fn.collapse.Constructor = Collapse
+
+
+ /* COLLAPSE NO CONFLICT
+  * ==================== */
+
+  $.fn.collapse.noConflict = function () {
+    $.fn.collapse = old
+    return this
+  }
+
+
+ /* COLLAPSE DATA-API
+  * ================= */
+
+  $(document).on('click.collapse.data-api', '[data-toggle=collapse]', function (e) {
+    var $this = $(this), href
+      , target = $this.attr('data-target')
+        || e.preventDefault()
+        || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') //strip for ie7
+      , option = $(target).data('collapse') ? 'toggle' : $this.data()
+    $this[$(target).hasClass('in') ? 'addClass' : 'removeClass']('collapsed')
+    $(target).collapse(option)
+  })
+
+}(window.jQuery);/* ============================================================
+ * bootstrap-dropdown.js v2.3.1
+ * http://twitter.github.com/bootstrap/javascript.html#dropdowns
+ * ============================================================
+ * Copyright 2012 Twitter, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============================================================ */
+
+
+!function ($) {
+
+  "use strict"; // jshint ;_;
+
+
+ /* DROPDOWN CLASS DEFINITION
+  * ========================= */
+
+  var toggle = '[data-toggle=dropdown]'
+    , Dropdown = function (element) {
+        var $el = $(element).on('click.dropdown.data-api', this.toggle)
+        $('html').on('click.dropdown.data-api', function () {
+          $el.parent().removeClass('open')
+        })
+      }
+
+  Dropdown.prototype = {
+
+    constructor: Dropdown
+
+  , toggle: function (e) {
+      var $this = $(this)
+        , $parent
+        , isActive
+
+      if ($this.is('.disabled, :disabled')) return
+
+      $parent = getParent($this)
+
+      isActive = $parent.hasClass('open')
+
+      clearMenus()
+
+      if (!isActive) {
+        $parent.toggleClass('open')
+      }
+
+      $this.focus()
+
+      return false
+    }
+
+  , keydown: function (e) {
+      var $this
+        , $items
+        , $active
+        , $parent
+        , isActive
+        , index
+
+      if (!/(38|40|27)/.test(e.keyCode)) return
+
+      $this = $(this)
+
+      e.preventDefault()
+      e.stopPropagation()
+
+      if ($this.is('.disabled, :disabled')) return
+
+      $parent = getParent($this)
+
+      isActive = $parent.hasClass('open')
+
+      if (!isActive || (isActive && e.keyCode == 27)) {
+        if (e.which == 27) $parent.find(toggle).focus()
+        return $this.click()
+      }
+
+      $items = $('[role=menu] li:not(.divider):visible a', $parent)
+
+      if (!$items.length) return
+
+      index = $items.index($items.filter(':focus'))
+
+      if (e.keyCode == 38 && index > 0) index--                                        // up
+      if (e.keyCode == 40 && index < $items.length - 1) index++                        // down
+      if (!~index) index = 0
+
+      $items
+        .eq(index)
+        .focus()
+    }
+
+  }
+
+  function clearMenus() {
+    $(toggle).each(function () {
+      getParent($(this)).removeClass('open')
+    })
+  }
+
+  function getParent($this) {
+    var selector = $this.attr('data-target')
+      , $parent
+
+    if (!selector) {
+      selector = $this.attr('href')
+      selector = selector && /#/.test(selector) && selector.replace(/.*(?=#[^\s]*$)/, '') //strip for ie7
+    }
+
+    $parent = selector && $(selector)
+
+    if (!$parent || !$parent.length) $parent = $this.parent()
+
+    return $parent
+  }
+
+
+  /* DROPDOWN PLUGIN DEFINITION
+   * ========================== */
+
+  var old = $.fn.dropdown
+
+  $.fn.dropdown = function (option) {
+    return this.each(function () {
+      var $this = $(this)
+        , data = $this.data('dropdown')
+      if (!data) $this.data('dropdown', (data = new Dropdown(this)))
+      if (typeof option == 'string') data[option].call($this)
+    })
+  }
+
+  $.fn.dropdown.Constructor = Dropdown
+
+
+ /* DROPDOWN NO CONFLICT
+  * ==================== */
+
+  $.fn.dropdown.noConflict = function () {
+    $.fn.dropdown = old
+    return this
+  }
+
+
+  /* APPLY TO STANDARD DROPDOWN ELEMENTS
+   * =================================== */
+
+  $(document)
+    .on('click.dropdown.data-api', clearMenus)
+    .on('click.dropdown.data-api', '.dropdown form', function (e) { e.stopPropagation() })
+    .on('click.dropdown-menu', function (e) { e.stopPropagation() })
+    .on('click.dropdown.data-api'  , toggle, Dropdown.prototype.toggle)
+    .on('keydown.dropdown.data-api', toggle + ', [role=menu]' , Dropdown.prototype.keydown)
+
+}(window.jQuery);
+/* =========================================================
+ * bootstrap-modal.js v2.3.1
+ * http://twitter.github.com/bootstrap/javascript.html#modals
+ * =========================================================
+ * Copyright 2012 Twitter, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ========================================================= */
+
+
+!function ($) {
+
+  "use strict"; // jshint ;_;
+
+
+ /* MODAL CLASS DEFINITION
+  * ====================== */
+
+  var Modal = function (element, options) {
+    this.options = options
+    this.$element = $(element)
+      .delegate('[data-dismiss="modal"]', 'click.dismiss.modal', $.proxy(this.hide, this))
+    this.options.remote && this.$element.find('.modal-body').load(this.options.remote)
+  }
+
+  Modal.prototype = {
+
+      constructor: Modal
+
+    , toggle: function () {
+        return this[!this.isShown ? 'show' : 'hide']()
+      }
+
+    , show: function () {
+        var that = this
+          , e = $.Event('show')
+
+        this.$element.trigger(e)
+
+        if (this.isShown || e.isDefaultPrevented()) return
+
+        this.isShown = true
+
+        this.escape()
+
+        this.backdrop(function () {
+          var transition = $.support.transition && that.$element.hasClass('fade')
+
+          if (!that.$element.parent().length) {
+            that.$element.appendTo(document.body) //don't move modals dom position
+          }
+
+          that.$element.show()
+
+          if (transition) {
+            that.$element[0].offsetWidth // force reflow
+          }
+
+          that.$element
+            .addClass('in')
+            .attr('aria-hidden', false)
+
+          that.enforceFocus()
+
+          transition ?
+            that.$element.one($.support.transition.end, function () { that.$element.focus().trigger('shown') }) :
+            that.$element.focus().trigger('shown')
+
+        })
+      }
+
+    , hide: function (e) {
+        e && e.preventDefault()
+
+        var that = this
+
+        e = $.Event('hide')
+
+        this.$element.trigger(e)
+
+        if (!this.isShown || e.isDefaultPrevented()) return
+
+        this.isShown = false
+
+        this.escape()
+
+        $(document).off('focusin.modal')
+
+        this.$element
+          .removeClass('in')
+          .attr('aria-hidden', true)
+
+        $.support.transition && this.$element.hasClass('fade') ?
+          this.hideWithTransition() :
+          this.hideModal()
+      }
+
+    , enforceFocus: function () {
+        var that = this
+        $(document).on('focusin.modal', function (e) {
+          if (that.$element[0] !== e.target && !that.$element.has(e.target).length) {
+            that.$element.focus()
+          }
+        })
+      }
+
+    , escape: function () {
+        var that = this
+        if (this.isShown && this.options.keyboard) {
+          this.$element.on('keyup.dismiss.modal', function ( e ) {
+            e.which == 27 && that.hide()
+          })
+        } else if (!this.isShown) {
+          this.$element.off('keyup.dismiss.modal')
+        }
+      }
+
+    , hideWithTransition: function () {
+        var that = this
+          , timeout = setTimeout(function () {
+              that.$element.off($.support.transition.end)
+              that.hideModal()
+            }, 500)
+
+        this.$element.one($.support.transition.end, function () {
+          clearTimeout(timeout)
+          that.hideModal()
+        })
+      }
+
+    , hideModal: function () {
+        var that = this
+        this.$element.hide()
+        this.backdrop(function () {
+          that.removeBackdrop()
+          that.$element.trigger('hidden')
+        })
+      }
+
+    , removeBackdrop: function () {
+        this.$backdrop && this.$backdrop.remove()
+        this.$backdrop = null
+      }
+
+    , backdrop: function (callback) {
+        var that = this
+          , animate = this.$element.hasClass('fade') ? 'fade' : ''
+
+        if (this.isShown && this.options.backdrop) {
+          var doAnimate = $.support.transition && animate
+
+          this.$backdrop = $('<div class="modal-backdrop ' + animate + '" />')
+            .appendTo(document.body)
+
+          this.$backdrop.click(
+            this.options.backdrop == 'static' ?
+              $.proxy(this.$element[0].focus, this.$element[0])
+            : $.proxy(this.hide, this)
+          )
+
+          if (doAnimate) this.$backdrop[0].offsetWidth // force reflow
+
+          this.$backdrop.addClass('in')
+
+          if (!callback) return
+
+          doAnimate ?
+            this.$backdrop.one($.support.transition.end, callback) :
+            callback()
+
+        } else if (!this.isShown && this.$backdrop) {
+          this.$backdrop.removeClass('in')
+
+          $.support.transition && this.$element.hasClass('fade')?
+            this.$backdrop.one($.support.transition.end, callback) :
+            callback()
+
+        } else if (callback) {
+          callback()
+        }
+      }
+  }
+
+
+ /* MODAL PLUGIN DEFINITION
+  * ======================= */
+
+  var old = $.fn.modal
+
+  $.fn.modal = function (option) {
+    return this.each(function () {
+      var $this = $(this)
+        , data = $this.data('modal')
+        , options = $.extend({}, $.fn.modal.defaults, $this.data(), typeof option == 'object' && option)
+      if (!data) $this.data('modal', (data = new Modal(this, options)))
+      if (typeof option == 'string') data[option]()
+      else if (options.show) data.show()
+    })
+  }
+
+  $.fn.modal.defaults = {
+      backdrop: true
+    , keyboard: true
+    , show: true
+  }
+
+  $.fn.modal.Constructor = Modal
+
+
+ /* MODAL NO CONFLICT
+  * ================= */
+
+  $.fn.modal.noConflict = function () {
+    $.fn.modal = old
+    return this
+  }
+
+
+ /* MODAL DATA-API
+  * ============== */
+
+  $(document).on('click.modal.data-api', '[data-toggle="modal"]', function (e) {
+    var $this = $(this)
+      , href = $this.attr('href')
+      , $target = $($this.attr('data-target') || (href && href.replace(/.*(?=#[^\s]+$)/, ''))) //strip for ie7
+      , option = $target.data('modal') ? 'toggle' : $.extend({ remote:!/#/.test(href) && href }, $target.data(), $this.data())
+
+    e.preventDefault()
+
+    $target
+      .modal(option)
+      .one('hide', function () {
+        $this.focus()
+      })
+  })
+
+}(window.jQuery);
+/* ===========================================================
+ * bootstrap-tooltip.js v2.3.1
+ * http://twitter.github.com/bootstrap/javascript.html#tooltips
+ * Inspired by the original jQuery.tipsy by Jason Frame
+ * ===========================================================
+ * Copyright 2012 Twitter, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ========================================================== */
+
+
+!function ($) {
+
+  "use strict"; // jshint ;_;
+
+
+ /* TOOLTIP PUBLIC CLASS DEFINITION
+  * =============================== */
+
+  var Tooltip = function (element, options) {
+    this.init('tooltip', element, options)
+  }
+
+  Tooltip.prototype = {
+
+    constructor: Tooltip
+
+  , init: function (type, element, options) {
+      var eventIn
+        , eventOut
+        , triggers
+        , trigger
+        , i
+
+      this.type = type
+      this.$element = $(element)
+      this.options = this.getOptions(options)
+      this.enabled = true
+
+      triggers = this.options.trigger.split(' ')
+
+      for (i = triggers.length; i--;) {
+        trigger = triggers[i]
+        if (trigger == 'click') {
+          this.$element.on('click.' + this.type, this.options.selector, $.proxy(this.toggle, this))
+        } else if (trigger != 'manual') {
+          eventIn = trigger == 'hover' ? 'mouseenter' : 'focus'
+          eventOut = trigger == 'hover' ? 'mouseleave' : 'blur'
+          this.$element.on(eventIn + '.' + this.type, this.options.selector, $.proxy(this.enter, this))
+          this.$element.on(eventOut + '.' + this.type, this.options.selector, $.proxy(this.leave, this))
+        }
+      }
+
+      this.options.selector ?
+        (this._options = $.extend({}, this.options, { trigger: 'manual', selector: '' })) :
+        this.fixTitle()
+    }
+
+  , getOptions: function (options) {
+      options = $.extend({}, $.fn[this.type].defaults, this.$element.data(), options)
+
+      if (options.delay && typeof options.delay == 'number') {
+        options.delay = {
+          show: options.delay
+        , hide: options.delay
+        }
+      }
+
+      return options
+    }
+
+  , enter: function (e) {
+      var defaults = $.fn[this.type].defaults
+        , options = {}
+        , self
+
+      this._options && $.each(this._options, function (key, value) {
+        if (defaults[key] != value) options[key] = value
+      }, this)
+
+      self = $(e.currentTarget)[this.type](options).data(this.type)
+
+      if (!self.options.delay || !self.options.delay.show) return self.show()
+
+      clearTimeout(this.timeout)
+      self.hoverState = 'in'
+      this.timeout = setTimeout(function() {
+        if (self.hoverState == 'in') self.show()
+      }, self.options.delay.show)
+    }
+
+  , leave: function (e) {
+      var self = $(e.currentTarget)[this.type](this._options).data(this.type)
+
+      if (this.timeout) clearTimeout(this.timeout)
+      if (!self.options.delay || !self.options.delay.hide) return self.hide()
+
+      self.hoverState = 'out'
+      this.timeout = setTimeout(function() {
+        if (self.hoverState == 'out') self.hide()
+      }, self.options.delay.hide)
+    }
+
+  , show: function () {
+      var $tip
+        , pos
+        , actualWidth
+        , actualHeight
+        , placement
+        , tp
+        , e = $.Event('show')
+
+      if (this.hasContent() && this.enabled) {
+        this.$element.trigger(e)
+        if (e.isDefaultPrevented()) return
+        $tip = this.tip()
+        this.setContent()
+
+        if (this.options.animation) {
+          $tip.addClass('fade')
+        }
+
+        placement = typeof this.options.placement == 'function' ?
+          this.options.placement.call(this, $tip[0], this.$element[0]) :
+          this.options.placement
+
+        $tip
+          .detach()
+          .css({ top: 0, left: 0, display: 'block' })
+
+        this.options.container ? $tip.appendTo(this.options.container) : $tip.insertAfter(this.$element)
+
+        pos = this.getPosition()
+
+        actualWidth = $tip[0].offsetWidth
+        actualHeight = $tip[0].offsetHeight
+
+        switch (placement) {
+          case 'bottom':
+            tp = {top: pos.top + pos.height, left: pos.left + pos.width / 2 - actualWidth / 2}
+            break
+          case 'top':
+            tp = {top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2}
+            break
+          case 'left':
+            tp = {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth}
+            break
+          case 'right':
+            tp = {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width}
+            break
+        }
+
+        this.applyPlacement(tp, placement)
+        this.$element.trigger('shown')
+      }
+    }
+
+  , applyPlacement: function(offset, placement){
+      var $tip = this.tip()
+        , width = $tip[0].offsetWidth
+        , height = $tip[0].offsetHeight
+        , actualWidth
+        , actualHeight
+        , delta
+        , replace
+
+      $tip
+        .offset(offset)
+        .addClass(placement)
+        .addClass('in')
+
+      actualWidth = $tip[0].offsetWidth
+      actualHeight = $tip[0].offsetHeight
+
+      if (placement == 'top' && actualHeight != height) {
+        offset.top = offset.top + height - actualHeight
+        replace = true
+      }
+
+      if (placement == 'bottom' || placement == 'top') {
+        delta = 0
+
+        if (offset.left < 0){
+          delta = offset.left * -2
+          offset.left = 0
+          $tip.offset(offset)
+          actualWidth = $tip[0].offsetWidth
+          actualHeight = $tip[0].offsetHeight
+        }
+
+        this.replaceArrow(delta - width + actualWidth, actualWidth, 'left')
+      } else {
+        this.replaceArrow(actualHeight - height, actualHeight, 'top')
+      }
+
+      if (replace) $tip.offset(offset)
+    }
+
+  , replaceArrow: function(delta, dimension, position){
+      this
+        .arrow()
+        .css(position, delta ? (50 * (1 - delta / dimension) + "%") : '')
+    }
+
+  , setContent: function () {
+      var $tip = this.tip()
+        , title = this.getTitle()
+
+      $tip.find('.tooltip-inner')[this.options.html ? 'html' : 'text'](title)
+      $tip.removeClass('fade in top bottom left right')
+    }
+
+  , hide: function () {
+      var that = this
+        , $tip = this.tip()
+        , e = $.Event('hide')
+
+      this.$element.trigger(e)
+      if (e.isDefaultPrevented()) return
+
+      $tip.removeClass('in')
+
+      function removeWithAnimation() {
+        var timeout = setTimeout(function () {
+          $tip.off($.support.transition.end).detach()
+        }, 500)
+
+        $tip.one($.support.transition.end, function () {
+          clearTimeout(timeout)
+          $tip.detach()
+        })
+      }
+
+      $.support.transition && this.$tip.hasClass('fade') ?
+        removeWithAnimation() :
+        $tip.detach()
+
+      this.$element.trigger('hidden')
+
+      return this
+    }
+
+  , fixTitle: function () {
+      var $e = this.$element
+      if ($e.attr('title') || typeof($e.attr('data-original-title')) != 'string') {
+        $e.attr('data-original-title', $e.attr('title') || '').attr('title', '')
+      }
+    }
+
+  , hasContent: function () {
+      return this.getTitle()
+    }
+
+  , getPosition: function () {
+      var el = this.$element[0]
+      return $.extend({}, (typeof el.getBoundingClientRect == 'function') ? el.getBoundingClientRect() : {
+        width: el.offsetWidth
+      , height: el.offsetHeight
+      }, this.$element.offset())
+    }
+
+  , getTitle: function () {
+      var title
+        , $e = this.$element
+        , o = this.options
+
+      title = $e.attr('data-original-title')
+        || (typeof o.title == 'function' ? o.title.call($e[0]) :  o.title)
+
+      return title
+    }
+
+  , tip: function () {
+      return this.$tip = this.$tip || $(this.options.template)
+    }
+
+  , arrow: function(){
+      return this.$arrow = this.$arrow || this.tip().find(".tooltip-arrow")
+    }
+
+  , validate: function () {
+      if (!this.$element[0].parentNode) {
+        this.hide()
+        this.$element = null
+        this.options = null
+      }
+    }
+
+  , enable: function () {
+      this.enabled = true
+    }
+
+  , disable: function () {
+      this.enabled = false
+    }
+
+  , toggleEnabled: function () {
+      this.enabled = !this.enabled
+    }
+
+  , toggle: function (e) {
+      var self = e ? $(e.currentTarget)[this.type](this._options).data(this.type) : this
+      self.tip().hasClass('in') ? self.hide() : self.show()
+    }
+
+  , destroy: function () {
+      this.hide().$element.off('.' + this.type).removeData(this.type)
+    }
+
+  }
+
+
+ /* TOOLTIP PLUGIN DEFINITION
+  * ========================= */
+
+  var old = $.fn.tooltip
+
+  $.fn.tooltip = function ( option ) {
+    return this.each(function () {
+      var $this = $(this)
+        , data = $this.data('tooltip')
+        , options = typeof option == 'object' && option
+      if (!data) $this.data('tooltip', (data = new Tooltip(this, options)))
+      if (typeof option == 'string') data[option]()
+    })
+  }
+
+  $.fn.tooltip.Constructor = Tooltip
+
+  $.fn.tooltip.defaults = {
+    animation: true
+  , placement: 'top'
+  , selector: false
+  , template: '<div class="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>'
+  , trigger: 'hover focus'
+  , title: ''
+  , delay: 0
+  , html: false
+  , container: false
+  }
+
+
+ /* TOOLTIP NO CONFLICT
+  * =================== */
+
+  $.fn.tooltip.noConflict = function () {
+    $.fn.tooltip = old
+    return this
+  }
+
+}(window.jQuery);
+/* ===========================================================
+ * bootstrap-popover.js v2.3.1
+ * http://twitter.github.com/bootstrap/javascript.html#popovers
+ * ===========================================================
+ * Copyright 2012 Twitter, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =========================================================== */
+
+
+!function ($) {
+
+  "use strict"; // jshint ;_;
+
+
+ /* POPOVER PUBLIC CLASS DEFINITION
+  * =============================== */
+
+  var Popover = function (element, options) {
+    this.init('popover', element, options)
+  }
+
+
+  /* NOTE: POPOVER EXTENDS BOOTSTRAP-TOOLTIP.js
+     ========================================== */
+
+  Popover.prototype = $.extend({}, $.fn.tooltip.Constructor.prototype, {
+
+    constructor: Popover
+
+  , setContent: function () {
+      var $tip = this.tip()
+        , title = this.getTitle()
+        , content = this.getContent()
+
+      $tip.find('.popover-title')[this.options.html ? 'html' : 'text'](title)
+      $tip.find('.popover-content')[this.options.html ? 'html' : 'text'](content)
+
+      $tip.removeClass('fade top bottom left right in')
+    }
+
+  , hasContent: function () {
+      return this.getTitle() || this.getContent()
+    }
+
+  , getContent: function () {
+      var content
+        , $e = this.$element
+        , o = this.options
+
+      content = (typeof o.content == 'function' ? o.content.call($e[0]) :  o.content)
+        || $e.attr('data-content')
+
+      return content
+    }
+
+  , tip: function () {
+      if (!this.$tip) {
+        this.$tip = $(this.options.template)
+      }
+      return this.$tip
+    }
+
+  , destroy: function () {
+      this.hide().$element.off('.' + this.type).removeData(this.type)
+    }
+
+  })
+
+
+ /* POPOVER PLUGIN DEFINITION
+  * ======================= */
+
+  var old = $.fn.popover
+
+  $.fn.popover = function (option) {
+    return this.each(function () {
+      var $this = $(this)
+        , data = $this.data('popover')
+        , options = typeof option == 'object' && option
+      if (!data) $this.data('popover', (data = new Popover(this, options)))
+      if (typeof option == 'string') data[option]()
+    })
+  }
+
+  $.fn.popover.Constructor = Popover
+
+  $.fn.popover.defaults = $.extend({} , $.fn.tooltip.defaults, {
+    placement: 'right'
+  , trigger: 'click'
+  , content: ''
+  , template: '<div class="popover"><div class="arrow"></div><h3 class="popover-title"></h3><div class="popover-content"></div></div>'
+  })
+
+
+ /* POPOVER NO CONFLICT
+  * =================== */
+
+  $.fn.popover.noConflict = function () {
+    $.fn.popover = old
+    return this
+  }
+
+}(window.jQuery);
+/* =============================================================
+ * bootstrap-scrollspy.js v2.3.1
+ * http://twitter.github.com/bootstrap/javascript.html#scrollspy
+ * =============================================================
+ * Copyright 2012 Twitter, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============================================================== */
+
+
+!function ($) {
+
+  "use strict"; // jshint ;_;
+
+
+ /* SCROLLSPY CLASS DEFINITION
+  * ========================== */
+
+  function ScrollSpy(element, options) {
+    var process = $.proxy(this.process, this)
+      , $element = $(element).is('body') ? $(window) : $(element)
+      , href
+    this.options = $.extend({}, $.fn.scrollspy.defaults, options)
+    this.$scrollElement = $element.on('scroll.scroll-spy.data-api', process)
+    this.selector = (this.options.target
+      || ((href = $(element).attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '')) //strip for ie7
+      || '') + ' .nav li > a'
+    this.$body = $('body')
+    this.refresh()
+    this.process()
+  }
+
+  ScrollSpy.prototype = {
+
+      constructor: ScrollSpy
+
+    , refresh: function () {
+        var self = this
+          , $targets
+
+        this.offsets = $([])
+        this.targets = $([])
+
+        $targets = this.$body
+          .find(this.selector)
+          .map(function () {
+            var $el = $(this)
+              , href = $el.data('target') || $el.attr('href')
+              , $href = /^#\w/.test(href) && $(href)
+            return ( $href
+              && $href.length
+              && [[ $href.position().top + (!$.isWindow(self.$scrollElement.get(0)) && self.$scrollElement.scrollTop()), href ]] ) || null
+          })
+          .sort(function (a, b) { return a[0] - b[0] })
+          .each(function () {
+            self.offsets.push(this[0])
+            self.targets.push(this[1])
+          })
+      }
+
+    , process: function () {
+        var scrollTop = this.$scrollElement.scrollTop() + this.options.offset
+          , scrollHeight = this.$scrollElement[0].scrollHeight || this.$body[0].scrollHeight
+          , maxScroll = scrollHeight - this.$scrollElement.height()
+          , offsets = this.offsets
+          , targets = this.targets
+          , activeTarget = this.activeTarget
+          , i
+
+        if (scrollTop >= maxScroll) {
+          return activeTarget != (i = targets.last()[0])
+            && this.activate ( i )
+        }
+
+        for (i = offsets.length; i--;) {
+          activeTarget != targets[i]
+            && scrollTop >= offsets[i]
+            && (!offsets[i + 1] || scrollTop <= offsets[i + 1])
+            && this.activate( targets[i] )
+        }
+      }
+
+    , activate: function (target) {
+        var active
+          , selector
+
+        this.activeTarget = target
+
+        $(this.selector)
+          .parent('.active')
+          .removeClass('active')
+
+        selector = this.selector
+          + '[data-target="' + target + '"],'
+          + this.selector + '[href="' + target + '"]'
+
+        active = $(selector)
+          .parent('li')
+          .addClass('active')
+
+        if (active.parent('.dropdown-menu').length)  {
+          active = active.closest('li.dropdown').addClass('active')
+        }
+
+        active.trigger('activate')
+      }
+
+  }
+
+
+ /* SCROLLSPY PLUGIN DEFINITION
+  * =========================== */
+
+  var old = $.fn.scrollspy
+
+  $.fn.scrollspy = function (option) {
+    return this.each(function () {
+      var $this = $(this)
+        , data = $this.data('scrollspy')
+        , options = typeof option == 'object' && option
+      if (!data) $this.data('scrollspy', (data = new ScrollSpy(this, options)))
+      if (typeof option == 'string') data[option]()
+    })
+  }
+
+  $.fn.scrollspy.Constructor = ScrollSpy
+
+  $.fn.scrollspy.defaults = {
+    offset: 10
+  }
+
+
+ /* SCROLLSPY NO CONFLICT
+  * ===================== */
+
+  $.fn.scrollspy.noConflict = function () {
+    $.fn.scrollspy = old
+    return this
+  }
+
+
+ /* SCROLLSPY DATA-API
+  * ================== */
+
+  $(window).on('load', function () {
+    $('[data-spy="scroll"]').each(function () {
+      var $spy = $(this)
+      $spy.scrollspy($spy.data())
+    })
+  })
+
+}(window.jQuery);/* ========================================================
+ * bootstrap-tab.js v2.3.1
+ * http://twitter.github.com/bootstrap/javascript.html#tabs
+ * ========================================================
+ * Copyright 2012 Twitter, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ======================================================== */
+
+
+!function ($) {
+
+  "use strict"; // jshint ;_;
+
+
+ /* TAB CLASS DEFINITION
+  * ==================== */
+
+  var Tab = function (element) {
+    this.element = $(element)
+  }
+
+  Tab.prototype = {
+
+    constructor: Tab
+
+  , show: function () {
+      var $this = this.element
+        , $ul = $this.closest('ul:not(.dropdown-menu)')
+        , selector = $this.attr('data-target')
+        , previous
+        , $target
+        , e
+
+      if (!selector) {
+        selector = $this.attr('href')
+        selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') //strip for ie7
+      }
+
+      if ( $this.parent('li').hasClass('active') ) return
+
+      previous = $ul.find('.active:last a')[0]
+
+      e = $.Event('show', {
+        relatedTarget: previous
+      })
+
+      $this.trigger(e)
+
+      if (e.isDefaultPrevented()) return
+
+      $target = $(selector)
+
+      this.activate($this.parent('li'), $ul)
+      this.activate($target, $target.parent(), function () {
+        $this.trigger({
+          type: 'shown'
+        , relatedTarget: previous
+        })
+      })
+    }
+
+  , activate: function ( element, container, callback) {
+      var $active = container.find('> .active')
+        , transition = callback
+            && $.support.transition
+            && $active.hasClass('fade')
+
+      function next() {
+        $active
+          .removeClass('active')
+          .find('> .dropdown-menu > .active')
+          .removeClass('active')
+
+        element.addClass('active')
+
+        if (transition) {
+          element[0].offsetWidth // reflow for transition
+          element.addClass('in')
+        } else {
+          element.removeClass('fade')
+        }
+
+        if ( element.parent('.dropdown-menu') ) {
+          element.closest('li.dropdown').addClass('active')
+        }
+
+        callback && callback()
+      }
+
+      transition ?
+        $active.one($.support.transition.end, next) :
+        next()
+
+      $active.removeClass('in')
+    }
+  }
+
+
+ /* TAB PLUGIN DEFINITION
+  * ===================== */
+
+  var old = $.fn.tab
+
+  $.fn.tab = function ( option ) {
+    return this.each(function () {
+      var $this = $(this)
+        , data = $this.data('tab')
+      if (!data) $this.data('tab', (data = new Tab(this)))
+      if (typeof option == 'string') data[option]()
+    })
+  }
+
+  $.fn.tab.Constructor = Tab
+
+
+ /* TAB NO CONFLICT
+  * =============== */
+
+  $.fn.tab.noConflict = function () {
+    $.fn.tab = old
+    return this
+  }
+
+
+ /* TAB DATA-API
+  * ============ */
+
+  $(document).on('click.tab.data-api', '[data-toggle="tab"], [data-toggle="pill"]', function (e) {
+    e.preventDefault()
+    $(this).tab('show')
+  })
+
+}(window.jQuery);/* =============================================================
+ * bootstrap-typeahead.js v2.3.1
+ * http://twitter.github.com/bootstrap/javascript.html#typeahead
+ * =============================================================
+ * Copyright 2012 Twitter, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============================================================ */
+
+
+!function($){
+
+  "use strict"; // jshint ;_;
+
+
+ /* TYPEAHEAD PUBLIC CLASS DEFINITION
+  * ================================= */
+
+  var Typeahead = function (element, options) {
+    this.$element = $(element)
+    this.options = $.extend({}, $.fn.typeahead.defaults, options)
+    this.matcher = this.options.matcher || this.matcher
+    this.sorter = this.options.sorter || this.sorter
+    this.highlighter = this.options.highlighter || this.highlighter
+    this.updater = this.options.updater || this.updater
+    this.source = this.options.source
+    this.$menu = $(this.options.menu)
+    this.shown = false
+    this.listen()
+  }
+
+  Typeahead.prototype = {
+
+    constructor: Typeahead
+
+  , select: function () {
+      var val = this.$menu.find('.active').attr('data-value')
+      this.$element
+        .val(this.updater(val))
+        .change()
+      return this.hide()
+    }
+
+  , updater: function (item) {
+      return item
+    }
+
+  , show: function () {
+      var pos = $.extend({}, this.$element.position(), {
+        height: this.$element[0].offsetHeight
+      })
+
+      this.$menu
+        .insertAfter(this.$element)
+        .css({
+          top: pos.top + pos.height
+        , left: pos.left
+        })
+        .show()
+
+      this.shown = true
+      return this
+    }
+
+  , hide: function () {
+      this.$menu.hide()
+      this.shown = false
+      return this
+    }
+
+  , lookup: function (event) {
+      var items
+
+      this.query = this.$element.val()
+
+      if (!this.query || this.query.length < this.options.minLength) {
+        return this.shown ? this.hide() : this
+      }
+
+      items = $.isFunction(this.source) ? this.source(this.query, $.proxy(this.process, this)) : this.source
+
+      return items ? this.process(items) : this
+    }
+
+  , process: function (items) {
+      var that = this
+
+      items = $.grep(items, function (item) {
+        return that.matcher(item)
+      })
+
+      items = this.sorter(items)
+
+      if (!items.length) {
+        return this.shown ? this.hide() : this
+      }
+
+      return this.render(items.slice(0, this.options.items)).show()
+    }
+
+  , matcher: function (item) {
+      return ~item.toLowerCase().indexOf(this.query.toLowerCase())
+    }
+
+  , sorter: function (items) {
+      var beginswith = []
+        , caseSensitive = []
+        , caseInsensitive = []
+        , item
+
+      while (item = items.shift()) {
+        if (!item.toLowerCase().indexOf(this.query.toLowerCase())) beginswith.push(item)
+        else if (~item.indexOf(this.query)) caseSensitive.push(item)
+        else caseInsensitive.push(item)
+      }
+
+      return beginswith.concat(caseSensitive, caseInsensitive)
+    }
+
+  , highlighter: function (item) {
+      var query = this.query.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g, '\\$&')
+      return item.replace(new RegExp('(' + query + ')', 'ig'), function ($1, match) {
+        return '<strong>' + match + '</strong>'
+      })
+    }
+
+  , render: function (items) {
+      var that = this
+
+      items = $(items).map(function (i, item) {
+        i = $(that.options.item).attr('data-value', item)
+        i.find('a').html(that.highlighter(item))
+        return i[0]
+      })
+
+      items.first().addClass('active')
+      this.$menu.html(items)
+      return this
+    }
+
+  , next: function (event) {
+      var active = this.$menu.find('.active').removeClass('active')
+        , next = active.next()
+
+      if (!next.length) {
+        next = $(this.$menu.find('li')[0])
+      }
+
+      next.addClass('active')
+    }
+
+  , prev: function (event) {
+      var active = this.$menu.find('.active').removeClass('active')
+        , prev = active.prev()
+
+      if (!prev.length) {
+        prev = this.$menu.find('li').last()
+      }
+
+      prev.addClass('active')
+    }
+
+  , listen: function () {
+      this.$element
+        .on('focus',    $.proxy(this.focus, this))
+        .on('blur',     $.proxy(this.blur, this))
+        .on('keypress', $.proxy(this.keypress, this))
+        .on('keyup',    $.proxy(this.keyup, this))
+
+      if (this.eventSupported('keydown')) {
+        this.$element.on('keydown', $.proxy(this.keydown, this))
+      }
+
+      this.$menu
+        .on('click', $.proxy(this.click, this))
+        .on('mouseenter', 'li', $.proxy(this.mouseenter, this))
+        .on('mouseleave', 'li', $.proxy(this.mouseleave, this))
+    }
+
+  , eventSupported: function(eventName) {
+      var isSupported = eventName in this.$element
+      if (!isSupported) {
+        this.$element.setAttribute(eventName, 'return;')
+        isSupported = typeof this.$element[eventName] === 'function'
+      }
+      return isSupported
+    }
+
+  , move: function (e) {
+      if (!this.shown) return
+
+      switch(e.keyCode) {
+        case 9: // tab
+        case 13: // enter
+        case 27: // escape
+          e.preventDefault()
+          break
+
+        case 38: // up arrow
+          e.preventDefault()
+          this.prev()
+          break
+
+        case 40: // down arrow
+          e.preventDefault()
+          this.next()
+          break
+      }
+
+      e.stopPropagation()
+    }
+
+  , keydown: function (e) {
+      this.suppressKeyPressRepeat = ~$.inArray(e.keyCode, [40,38,9,13,27])
+      this.move(e)
+    }
+
+  , keypress: function (e) {
+      if (this.suppressKeyPressRepeat) return
+      this.move(e)
+    }
+
+  , keyup: function (e) {
+      switch(e.keyCode) {
+        case 40: // down arrow
+        case 38: // up arrow
+        case 16: // shift
+        case 17: // ctrl
+        case 18: // alt
+          break
+
+        case 9: // tab
+        case 13: // enter
+          if (!this.shown) return
+          this.select()
+          break
+
+        case 27: // escape
+          if (!this.shown) return
+          this.hide()
+          break
+
+        default:
+          this.lookup()
+      }
+
+      e.stopPropagation()
+      e.preventDefault()
+  }
+
+  , focus: function (e) {
+      this.focused = true
+    }
+
+  , blur: function (e) {
+      this.focused = false
+      if (!this.mousedover && this.shown) this.hide()
+    }
+
+  , click: function (e) {
+      e.stopPropagation()
+      e.preventDefault()
+      this.select()
+      this.$element.focus()
+    }
+
+  , mouseenter: function (e) {
+      this.mousedover = true
+      this.$menu.find('.active').removeClass('active')
+      $(e.currentTarget).addClass('active')
+    }
+
+  , mouseleave: function (e) {
+      this.mousedover = false
+      if (!this.focused && this.shown) this.hide()
+    }
+
+  }
+
+
+  /* TYPEAHEAD PLUGIN DEFINITION
+   * =========================== */
+
+  var old = $.fn.typeahead
+
+  $.fn.typeahead = function (option) {
+    return this.each(function () {
+      var $this = $(this)
+        , data = $this.data('typeahead')
+        , options = typeof option == 'object' && option
+      if (!data) $this.data('typeahead', (data = new Typeahead(this, options)))
+      if (typeof option == 'string') data[option]()
+    })
+  }
+
+  $.fn.typeahead.defaults = {
+    source: []
+  , items: 8
+  , menu: '<ul class="typeahead dropdown-menu"></ul>'
+  , item: '<li><a href="#"></a></li>'
+  , minLength: 1
+  }
+
+  $.fn.typeahead.Constructor = Typeahead
+
+
+ /* TYPEAHEAD NO CONFLICT
+  * =================== */
+
+  $.fn.typeahead.noConflict = function () {
+    $.fn.typeahead = old
+    return this
+  }
+
+
+ /* TYPEAHEAD DATA-API
+  * ================== */
+
+  $(document).on('focus.typeahead.data-api', '[data-provide="typeahead"]', function (e) {
+    var $this = $(this)
+    if ($this.data('typeahead')) return
+    $this.typeahead($this.data())
+  })
+
+}(window.jQuery);
+/* ==========================================================
+ * bootstrap-affix.js v2.3.1
+ * http://twitter.github.com/bootstrap/javascript.html#affix
+ * ==========================================================
+ * Copyright 2012 Twitter, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ========================================================== */
+
+
+!function ($) {
+
+  "use strict"; // jshint ;_;
+
+
+ /* AFFIX CLASS DEFINITION
+  * ====================== */
+
+  var Affix = function (element, options) {
+    this.options = $.extend({}, $.fn.affix.defaults, options)
+    this.$window = $(window)
+      .on('scroll.affix.data-api', $.proxy(this.checkPosition, this))
+      .on('click.affix.data-api',  $.proxy(function () { setTimeout($.proxy(this.checkPosition, this), 1) }, this))
+    this.$element = $(element)
+    this.checkPosition()
+  }
+
+  Affix.prototype.checkPosition = function () {
+    if (!this.$element.is(':visible')) return
+
+    var scrollHeight = $(document).height()
+      , scrollTop = this.$window.scrollTop()
+      , position = this.$element.offset()
+      , offset = this.options.offset
+      , offsetBottom = offset.bottom
+      , offsetTop = offset.top
+      , reset = 'affix affix-top affix-bottom'
+      , affix
+
+    if (typeof offset != 'object') offsetBottom = offsetTop = offset
+    if (typeof offsetTop == 'function') offsetTop = offset.top()
+    if (typeof offsetBottom == 'function') offsetBottom = offset.bottom()
+
+    affix = this.unpin != null && (scrollTop + this.unpin <= position.top) ?
+      false    : offsetBottom != null && (position.top + this.$element.height() >= scrollHeight - offsetBottom) ?
+      'bottom' : offsetTop != null && scrollTop <= offsetTop ?
+      'top'    : false
+
+    if (this.affixed === affix) return
+
+    this.affixed = affix
+    this.unpin = affix == 'bottom' ? position.top - scrollTop : null
+
+    this.$element.removeClass(reset).addClass('affix' + (affix ? '-' + affix : ''))
+  }
+
+
+ /* AFFIX PLUGIN DEFINITION
+  * ======================= */
+
+  var old = $.fn.affix
+
+  $.fn.affix = function (option) {
+    return this.each(function () {
+      var $this = $(this)
+        , data = $this.data('affix')
+        , options = typeof option == 'object' && option
+      if (!data) $this.data('affix', (data = new Affix(this, options)))
+      if (typeof option == 'string') data[option]()
+    })
+  }
+
+  $.fn.affix.Constructor = Affix
+
+  $.fn.affix.defaults = {
+    offset: 0
+  }
+
+
+ /* AFFIX NO CONFLICT
+  * ================= */
+
+  $.fn.affix.noConflict = function () {
+    $.fn.affix = old
+    return this
+  }
+
+
+ /* AFFIX DATA-API
+  * ============== */
+
+  $(window).on('load', function () {
+    $('[data-spy="affix"]').each(function () {
+      var $spy = $(this)
+        , data = $spy.data()
+
+      data.offset = data.offset || {}
+
+      data.offsetBottom && (data.offset.bottom = data.offsetBottom)
+      data.offsetTop && (data.offset.top = data.offsetTop)
+
+      $spy.affix(data)
+    })
+  })
+
+
+}(window.jQuery);
\ No newline at end of file


[05/51] [abbrv] [partial] Adding Jinwon's custom RCMET

Posted by jo...@apache.org.
http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/templates/default/mods/negotiation.conf.erb
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/templates/default/mods/negotiation.conf.erb b/src/main/vm/src/cookbooks/apache2/templates/default/mods/negotiation.conf.erb
new file mode 100755
index 0000000..0e3455b
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/templates/default/mods/negotiation.conf.erb
@@ -0,0 +1,18 @@
+<IfModule mod_negotiation.c>
+#
+# LanguagePriority allows you to give precedence to some languages
+# in case of a tie during content negotiation.
+#
+# Just list the languages in decreasing order of preference. We have
+# more or less alphabetized them here. You probably want to change this.
+#
+LanguagePriority en ca cs da de el eo es et fr he hr it ja ko ltz nl nn no pl pt pt-BR ru sv tr zh-CN zh-TW
+
+#
+# ForceLanguagePriority allows you to serve a result page rather than
+# MULTIPLE CHOICES (Prefer) [in case of a tie] or NOT ACCEPTABLE (Fallback)
+# [in case no accepted languages matched the available variants]
+#
+ForceLanguagePriority Prefer Fallback
+
+</IfModule>

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/templates/default/mods/proxy.conf.erb
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/templates/default/mods/proxy.conf.erb b/src/main/vm/src/cookbooks/apache2/templates/default/mods/proxy.conf.erb
new file mode 100755
index 0000000..46407a1
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/templates/default/mods/proxy.conf.erb
@@ -0,0 +1,19 @@
+<IfModule mod_proxy.c>
+        #turning ProxyRequests on and allowing proxying from all may allow
+        #spammers to use your proxy to send email.
+
+        ProxyRequests Off
+
+        <Proxy *>
+                AddDefaultCharset off
+                Order deny,allow
+                Deny from all
+                #Allow from .example.com
+        </Proxy>
+
+        # Enable/disable the handling of HTTP/1.1 "Via:" headers.
+        # ("Full" adds the server version; "Block" removes all outgoing Via: headers)
+        # Set to one of: Off | On | Full | Block
+
+        ProxyVia On
+</IfModule>

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/templates/default/mods/setenvif.conf.erb
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/templates/default/mods/setenvif.conf.erb b/src/main/vm/src/cookbooks/apache2/templates/default/mods/setenvif.conf.erb
new file mode 100755
index 0000000..6b7d6e2
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/templates/default/mods/setenvif.conf.erb
@@ -0,0 +1,28 @@
+<IfModule mod_setenvif.c>
+
+#
+# The following directives modify normal HTTP response behavior to
+# handle known problems with browser implementations.
+#
+BrowserMatch "Mozilla/2" nokeepalive
+BrowserMatch "MSIE 4\.0b2;" nokeepalive downgrade-1.0 force-response-1.0
+BrowserMatch "RealPlayer 4\.0" force-response-1.0
+BrowserMatch "Java/1\.0" force-response-1.0
+BrowserMatch "JDK/1\.0" force-response-1.0
+
+#
+# The following directive disables redirects on non-GET requests for
+# a directory that does not include the trailing slash.  This fixes a 
+# problem with Microsoft WebFolders which does not appropriately handle 
+# redirects for folders with DAV methods.
+# Same deal with Apple's DAV filesystem and Gnome VFS support for DAV.
+#
+BrowserMatch "Microsoft Data Access Internet Publishing Provider" redirect-carefully
+BrowserMatch "MS FrontPage" redirect-carefully
+BrowserMatch "^WebDrive" redirect-carefully
+BrowserMatch "^WebDAVFS/1.[012]" redirect-carefully
+BrowserMatch "^gnome-vfs/1.0" redirect-carefully
+BrowserMatch "^XML Spy" redirect-carefully
+BrowserMatch "^Dreamweaver-WebDAV-SCM1" redirect-carefully
+
+</IfModule>

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/templates/default/mods/ssl.conf.erb
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/templates/default/mods/ssl.conf.erb b/src/main/vm/src/cookbooks/apache2/templates/default/mods/ssl.conf.erb
new file mode 100755
index 0000000..3b7735f
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/templates/default/mods/ssl.conf.erb
@@ -0,0 +1,72 @@
+<IfModule mod_ssl.c>
+#
+# Pseudo Random Number Generator (PRNG):
+# Configure one or more sources to seed the PRNG of the SSL library.
+# The seed data should be of good random quality.
+# WARNING! On some platforms /dev/random blocks if not enough entropy
+# is available. This means you then cannot use the /dev/random device
+# because it would lead to very long connection times (as long as
+# it requires to make more entropy available). But usually those
+# platforms additionally provide a /dev/urandom device which doesn't
+# block. So, if available, use this one instead. Read the mod_ssl User
+# Manual for more details.
+#
+SSLRandomSeed startup builtin
+SSLRandomSeed startup file:/dev/urandom 512
+SSLRandomSeed connect builtin
+SSLRandomSeed connect file:/dev/urandom 512
+
+##
+##  SSL Global Context
+##
+##  All SSL configuration in this context applies both to
+##  the main server and all SSL-enabled virtual hosts.
+##
+
+#
+#   Some MIME-types for downloading Certificates and CRLs
+#
+AddType application/x-x509-ca-cert .crt
+AddType application/x-pkcs7-crl    .crl
+
+#   Pass Phrase Dialog:
+#   Configure the pass phrase gathering process.
+#   The filtering dialog program (`builtin' is a internal
+#   terminal dialog) has to provide the pass phrase on stdout.
+SSLPassPhraseDialog  builtin
+
+#   Inter-Process Session Cache:
+#   Configure the SSL Session Cache: First the mechanism 
+#   to use and second the expiring timeout (in seconds).
+#SSLSessionCache         dbm:/var/run/apache2/ssl_scache
+<% if node[:platform] == "centos" || node[:platform] == "redhat" || node[:platform] == "fedora" -%>
+SSLSessionCache        shmcb:/var/cache/mod_ssl/scache(512000)
+<% else -%>
+SSLSessionCache        shmcb:/var/run/apache2/ssl_scache
+<% end -%> 
+SSLSessionCacheTimeout  300
+
+#   Semaphore:
+#   Configure the path to the mutual exclusion semaphore the
+#   SSL engine uses internally for inter-process synchronization. 
+<% if node[:platform] == "centos" || node[:platform] == "redhat" || node[:platform] == "fedora" -%>
+SSLMutex  default
+<% else -%>
+SSLMutex  file:/var/run/apache2/ssl_mutex
+<% end -%>
+
+#   SSL Cipher Suite:
+#   List the ciphers that the client is permitted to negotiate.
+#   See the mod_ssl documentation for a complete list.
+#   enable only secure ciphers:
+SSLCipherSuite HIGH:MEDIUM:!ADH
+#   Use this instead if you want to allow cipher upgrades via SGC facility.
+#   In this case you also have to use something like 
+#        SSLRequire %{SSL_CIPHER_USEKEYSIZE} >= 128
+#   see http://httpd.apache.org/docs/2.2/ssl/ssl_howto.html.en#upgradeenc
+#SSLCipherSuite ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP:+eNULL
+
+# enable only secure protocols: SSLv3 and TLSv1, but not SSLv2
+SSLProtocol all -SSLv2
+
+</IfModule>

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/templates/default/mods/status.conf.erb
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/templates/default/mods/status.conf.erb b/src/main/vm/src/cookbooks/apache2/templates/default/mods/status.conf.erb
new file mode 100755
index 0000000..679d111
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/templates/default/mods/status.conf.erb
@@ -0,0 +1,16 @@
+<IfModule mod_status.c>
+#
+# Allow server status reports generated by mod_status,
+# with the URL of http://servername/server-status
+# Uncomment and change the ".example.com" to allow
+# access from other hosts.
+#
+<Location /server-status>
+    SetHandler server-status
+    Order deny,allow
+    Deny from all
+    Allow from localhost ip6-localhost
+#    Allow from .example.com
+</Location>
+
+</IfModule>

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/templates/default/port_apache.erb
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/templates/default/port_apache.erb b/src/main/vm/src/cookbooks/apache2/templates/default/port_apache.erb
new file mode 100755
index 0000000..f6078dd
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/templates/default/port_apache.erb
@@ -0,0 +1,2 @@
+# Port <%= @port %> 
+-A FWR -p tcp -m tcp --dport <%= @port %> -j ACCEPT
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/templates/default/ports.conf.erb
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/templates/default/ports.conf.erb b/src/main/vm/src/cookbooks/apache2/templates/default/ports.conf.erb
new file mode 100755
index 0000000..cc3631e
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/templates/default/ports.conf.erb
@@ -0,0 +1,6 @@
+#This file generated via template by Chef.
+<% @apache_listen_ports.each do |port| -%>
+Listen <%= port %>
+NameVirtualHost *:<%= port %>
+
+<% end -%>

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/templates/default/security.erb
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/templates/default/security.erb b/src/main/vm/src/cookbooks/apache2/templates/default/security.erb
new file mode 100755
index 0000000..70c97ad
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/templates/default/security.erb
@@ -0,0 +1,50 @@
+#
+# Disable access to the entire file system except for the directories that
+# are explicitly allowed later.
+#
+# This currently breaks the configurations that come with some web application
+# Debian packages. It will be made the default for the release after lenny.
+#
+#<Directory />
+#	AllowOverride None
+#	Order Deny,Allow
+#	Deny from all
+#</Directory>
+
+
+# Changing the following options will not really affect the security of the
+# server, but might make attacks slightly more difficult in some cases.
+
+#
+# ServerTokens
+# This directive configures what you return as the Server HTTP response
+# Header. The default is 'Full' which sends information about the OS-Type
+# and compiled in modules.
+# Set to one of:  Full | OS | Minimal | Minor | Major | Prod
+# where Full conveys the most information, and Prod the least.
+#
+#ServerTokens Minimal
+ServerTokens <%= node[:apache][:servertokens] %> 
+
+#
+# Optionally add a line containing the server version and virtual host
+# name to server-generated pages (internal error documents, FTP directory
+# listings, mod_status and mod_info output etc., but not CGI generated
+# documents or custom error documents).
+# Set to "EMail" to also include a mailto: link to the ServerAdmin.
+# Set to one of:  On | Off | EMail
+#
+#ServerSignature Off
+ServerSignature <%= node[:apache][:serversignature] %> 
+
+#
+# Allow TRACE method
+#
+# Set to "extended" to also reflect the request body (only for testing and
+# diagnostic purposes).
+#
+# Set to one of:  On | Off | extended
+#
+#TraceEnable Off
+TraceEnable <%= node[:apache][:traceenable] %> 
+

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apache2/templates/default/web_app.conf.erb
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apache2/templates/default/web_app.conf.erb b/src/main/vm/src/cookbooks/apache2/templates/default/web_app.conf.erb
new file mode 100755
index 0000000..6be3fc9
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apache2/templates/default/web_app.conf.erb
@@ -0,0 +1,43 @@
+<VirtualHost *:80>
+  ServerName <%= @params[:server_name] %>
+  ServerAlias <% @params[:server_aliases].each do |a| %><%= "#{a}" %> <% end %>
+  DocumentRoot <%= @params[:docroot] %>
+  RewriteEngine On
+  
+  <Directory <%= @params[:docroot] %>>
+    Options FollowSymLinks
+    AllowOverride None
+    Order allow,deny
+    Allow from all
+  </Directory>
+  
+  <Directory />
+    Options FollowSymLinks
+    AllowOverride None
+  </Directory>
+
+  <Location /server-status>
+    SetHandler server-status
+
+    Order Deny,Allow
+    Deny from all
+    Allow from 127.0.0.1
+  </Location>
+
+  LogLevel info
+  ErrorLog <%= node[:apache][:log_dir] %>/<%= @params[:name] %>-error.log
+  CustomLog <%= node[:apache][:log_dir] %>/<%= @params[:name] %>-access.log combined
+
+  RewriteEngine On
+  RewriteLog <%= node[:apache][:log_dir] %>/<%= @application_name %>-rewrite.log
+  RewriteLogLevel 0
+
+  # Canonical host, <%= @params[:server_name] %>
+  RewriteCond %{HTTP_HOST}   !^<%= @params[:server_name] %> [NC]
+  RewriteCond %{HTTP_HOST}   !^$
+  RewriteRule ^/(.*)$        http://<%= @params[:server_name] %>/$1 [L,R=301]
+
+  RewriteCond %{DOCUMENT_ROOT}/system/maintenance.html -f
+  RewriteCond %{SCRIPT_FILENAME} !maintenance.html
+  RewriteRule ^.*$ /system/maintenance.html [L]
+</VirtualHost>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apt/.svn/all-wcprops
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apt/.svn/all-wcprops b/src/main/vm/src/cookbooks/apt/.svn/all-wcprops
new file mode 100755
index 0000000..9e5cb92
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apt/.svn/all-wcprops
@@ -0,0 +1,17 @@
+K 25
+svn:wc:ra_dav:version-url
+V 87
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks/apt
+END
+metadata.rb
+K 25
+svn:wc:ra_dav:version-url
+V 99
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks/apt/metadata.rb
+END
+metadata.json
+K 25
+svn:wc:ra_dav:version-url
+V 101
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks/apt/metadata.json
+END

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apt/.svn/entries
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apt/.svn/entries b/src/main/vm/src/cookbooks/apt/.svn/entries
new file mode 100755
index 0000000..ef29c77
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apt/.svn/entries
@@ -0,0 +1,102 @@
+10
+
+dir
+1485921
+https://svn.apache.org/repos/asf/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks/apt
+https://svn.apache.org/repos/asf
+
+
+
+2012-10-10T00:49:17.045897Z
+1474264
+ahart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+13f79535-47bb-0310-9956-ffa450edef68
+
+files
+dir
+
+metadata.rb
+file
+
+
+
+
+2013-05-24T10:13:54.000000Z
+83ca6021a53685468bc0a2b7da3cf8ba
+2012-10-10T00:49:17.045897Z
+1474264
+ahart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+344
+
+metadata.json
+file
+
+
+
+
+2013-05-24T10:13:54.000000Z
+87374ef8db12e7295d7264d327a6a3a4
+2012-10-10T00:49:17.045897Z
+1474264
+ahart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+655
+
+recipes
+dir
+

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apt/.svn/text-base/metadata.json.svn-base
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apt/.svn/text-base/metadata.json.svn-base b/src/main/vm/src/cookbooks/apt/.svn/text-base/metadata.json.svn-base
new file mode 100755
index 0000000..00a5b18
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apt/.svn/text-base/metadata.json.svn-base
@@ -0,0 +1,37 @@
+{
+    "dependencies": {
+    },
+    "replacing": {
+    },
+    "description": "Configures apt and apt services",
+    "groupings": {
+    },
+    "platforms": {
+      "ubuntu": [
+
+      ],
+      "debian": [
+
+      ]
+    },
+    "version": "0.8.0",
+    "recommendations": {
+    },
+    "name": "apt",
+    "maintainer": "Opscode, Inc.",
+    "long_description": "",
+    "recipes": {
+      "apt::proxy": "Set up an APT proxy",
+      "apt::cacher": "Set up an APT cache"
+    },
+    "suggestions": {
+    },
+    "maintainer_email": "cookbooks@opscode.com",
+    "attributes": {
+    },
+    "conflicting": {
+    },
+    "license": "Apache 2.0",
+    "providing": {
+    }
+  }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apt/.svn/text-base/metadata.rb.svn-base
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apt/.svn/text-base/metadata.rb.svn-base b/src/main/vm/src/cookbooks/apt/.svn/text-base/metadata.rb.svn-base
new file mode 100755
index 0000000..cb6e712
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apt/.svn/text-base/metadata.rb.svn-base
@@ -0,0 +1,11 @@
+maintainer        "Opscode, Inc."
+maintainer_email  "cookbooks@opscode.com"
+license           "Apache 2.0"
+description       "Configures apt and apt services"
+version           "0.8"
+recipe            "apt::cacher", "Set up an APT cache"
+recipe            "apt::proxy", "Set up an APT proxy"
+
+%w{ ubuntu debian }.each do |os|
+  supports os
+end

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apt/files/.svn/all-wcprops
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apt/files/.svn/all-wcprops b/src/main/vm/src/cookbooks/apt/files/.svn/all-wcprops
new file mode 100755
index 0000000..03eab64
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apt/files/.svn/all-wcprops
@@ -0,0 +1,5 @@
+K 25
+svn:wc:ra_dav:version-url
+V 93
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks/apt/files
+END

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apt/files/.svn/entries
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apt/files/.svn/entries b/src/main/vm/src/cookbooks/apt/files/.svn/entries
new file mode 100755
index 0000000..aecb2ab
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apt/files/.svn/entries
@@ -0,0 +1,31 @@
+10
+
+dir
+1485921
+https://svn.apache.org/repos/asf/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks/apt/files
+https://svn.apache.org/repos/asf
+
+
+
+2012-10-10T00:49:17.045897Z
+1474264
+ahart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+13f79535-47bb-0310-9956-ffa450edef68
+
+default
+dir
+

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apt/files/default/.svn/all-wcprops
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apt/files/default/.svn/all-wcprops b/src/main/vm/src/cookbooks/apt/files/default/.svn/all-wcprops
new file mode 100755
index 0000000..95a1b35
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apt/files/default/.svn/all-wcprops
@@ -0,0 +1,23 @@
+K 25
+svn:wc:ra_dav:version-url
+V 101
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks/apt/files/default
+END
+apt-cacher
+K 25
+svn:wc:ra_dav:version-url
+V 112
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks/apt/files/default/apt-cacher
+END
+apt-cacher.conf
+K 25
+svn:wc:ra_dav:version-url
+V 117
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks/apt/files/default/apt-cacher.conf
+END
+apt-proxy-v2.conf
+K 25
+svn:wc:ra_dav:version-url
+V 119
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks/apt/files/default/apt-proxy-v2.conf
+END

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apt/files/default/.svn/entries
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apt/files/default/.svn/entries b/src/main/vm/src/cookbooks/apt/files/default/.svn/entries
new file mode 100755
index 0000000..609effe
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apt/files/default/.svn/entries
@@ -0,0 +1,130 @@
+10
+
+dir
+1485921
+https://svn.apache.org/repos/asf/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks/apt/files/default
+https://svn.apache.org/repos/asf
+
+
+
+2012-10-10T00:49:17.045897Z
+1474264
+ahart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+13f79535-47bb-0310-9956-ffa450edef68
+
+apt-cacher
+file
+
+
+
+
+2013-05-24T10:13:54.000000Z
+046661f9e728b783ea90738769219d71
+2012-10-10T00:49:17.045897Z
+1474264
+ahart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+276
+
+apt-cacher.conf
+file
+
+
+
+
+2013-05-24T10:13:54.000000Z
+3e4afb4ca7cb38b707b803cbb2a316a7
+2012-10-10T00:49:17.045897Z
+1474264
+ahart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+7338
+
+apt-proxy-v2.conf
+file
+
+
+
+
+2013-05-24T10:13:54.000000Z
+a67a0204d4c54848aad67a8e9de5cad1
+2012-10-10T00:49:17.045897Z
+1474264
+ahart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+1120
+

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apt/files/default/.svn/text-base/apt-cacher.conf.svn-base
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apt/files/default/.svn/text-base/apt-cacher.conf.svn-base b/src/main/vm/src/cookbooks/apt/files/default/.svn/text-base/apt-cacher.conf.svn-base
new file mode 100755
index 0000000..32ca3c3
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apt/files/default/.svn/text-base/apt-cacher.conf.svn-base
@@ -0,0 +1,144 @@
+# This file has been modified by ./apt-proxy-to-apt-cacher
+# Some lines may have been appended at the bottom of this file
+# This file has been modified by /usr/share/apt-cacher/apt-proxy-to-apt-cacher
+# Some lines may have been appended at the bottom of this file
+#################################################################
+# This is the config file for apt-cacher. On most Debian systems
+# you can safely leave the defaults alone.
+#################################################################
+
+# cache_dir is used to set the location of the local cache. This can
+# become quite large, so make sure it is somewhere with plenty of space.
+cache_dir=/var/cache/apt-cacher
+
+# The email address of the administrator is displayed in the info page
+# and traffic reports.
+admin_email=root@localhost
+
+# For the daemon startup settings please edit the file /etc/default/apt-cacher.
+
+# Daemon port setting, only useful in stand-alone mode. You need to run the
+# daemon as root to use privileged ports (<1024).
+daemon_port = 3142
+
+# optional settings, user and group to run the daemon as. Make sure they have
+# sufficient permissions on the cache and log directories. Comment the settings
+# to run apt-cacher as the native user.
+group=www-data
+user=www-data
+
+# optional setting, binds the listening daemon to one specified IP. Use IP
+# ranges for more advanced configuration, see below.
+# daemon_addr=localhost
+
+# If your apt-cacher machine is directly exposed to the Internet and you are
+# worried about unauthorised machines fetching packages through it, you can
+# specify a list of IPv4 addresses which are allowed to use it and another
+# list of IPv4 addresses which aren't.
+# Localhost (127.0.0.1) is always allowed. Other addresses must be matched
+# by allowed_hosts and not by denied_hosts to be permitted to use the cache.
+# Setting allowed_hosts to "*" means "allow all".
+# Otherwise the format is a comma-separated list containing addresses,
+# optionally with masks (like 10.0.0.0/22), or ranges of addresses (two
+# addresses separated by a hyphen, no masks, like '192.168.0.3-192.168.0.56').
+allowed_hosts=*
+denied_hosts=
+
+# And similiarly for IPv6 with allowed_hosts_6 and denied_hosts_6.
+# Note that IPv4-mapped IPv6 addresses (::ffff:w.x.y.z) are truncated to
+# w.x.y.z and are handled as IPv4.
+allowed_hosts_6=fec0::/16
+denied_hosts_6=
+
+# This thing can be done by Apache but is much simplier here - limit access to
+# Debian mirrors based on server names in the URLs
+#allowed_locations=ftp.uni-kl.de,ftp.nerim.net,debian.tu-bs.de
+
+# Apt-cacher can generate usage reports every 24 hours if you set this
+# directive to 1. You can view the reports in a web browser by pointing
+# to your cache machine with '/apt-cacher/report' on the end, like this:
+#      http://yourcache.example.com/apt-cacher/report
+# Generating reports is very fast even with many thousands of logfile
+# lines, so you can safely turn this on without creating much 
+# additional system load.
+generate_reports=1
+
+# Apt-cacher can clean up its cache directory every 24 hours if you set
+# this directive to 1. Cleaning the cache can take some time to run
+# (generally in the order of a few minutes) and removes all package
+# files that are not mentioned in any existing 'Packages' lists. This
+# has the effect of deleting packages that have been superseded by an
+# updated 'Packages' list.
+clean_cache=1
+
+# The directory to use for apt-cacher access and error logs.
+# The access log records every request in the format:
+# date-time|client ip address|HIT/MISS/EXPIRED|object size|object name
+# The error log is slightly more free-form, and is also used for debug
+# messages if debug mode is turned on.
+# Note that the old 'logfile' and 'errorfile' directives are
+# deprecated: if you set them explicitly they will be honoured, but it's
+# better to just get rid of them from old config files.
+logdir=/var/log/apt-cacher
+
+# apt-cacher can use different methods to decide whether package lists need to
+# be updated,
+# A) looking at the age of the cached files
+# B) getting HTTP header from server and comparing that with cached data. This
+# method is more reliable and avoids desynchronisation of data and index files
+# but needs to transfer few bytes from the server every time somebody requests
+# the files ("apt-get update")
+# Set the following value to the maximum age (in hours) for method A or to 0
+# for method B
+expire_hours=0
+
+# Apt-cacher can pass all its requests to an external http proxy like
+# Squid, which could be very useful if you are using an ISP that blocks
+# port 80 and requires all web traffic to go through its proxy. The
+# format is 'hostname:port', eg: 'proxy.example.com:8080'.
+http_proxy=proxy.example.com:8080
+
+# Use of an external proxy can be turned on or off with this flag.
+# Value should be either 0 (off) or 1 (on).
+use_proxy=0
+
+# External http proxy sometimes need authentication to get full access. The
+# format is 'username:password'.
+http_proxy_auth=proxyuser:proxypass
+
+# Use of external proxy authentication can be turned on or off with this flag.
+# Value should be either 0 (off) or 1 (on).
+use_proxy_auth=0
+
+# Rate limiting sets the maximum bandwidth in bytes per second to use
+# for fetching packages. Syntax is fully defined in 'man wget'.
+# Use 'k' or 'm' to use kilobits or megabits / second: eg, 'limit=25k'.
+# Use 0 or a negative value for no rate limiting.
+limit=0
+
+# Debug mode makes apt-cacher spew a lot of extra debug junk to the
+# error log (whose location is defined with the 'logdir' directive).
+# Leave this off unless you need it, or your error log will get very
+# big. Acceptable values are 0 or 1.
+debug=0
+
+# Adapt the line in the usage info web page to match your server configuration
+# example_sources_line=deb&nbsp;http://<b>my.cacher.server:3142/</b>ftp.au.debian.org/debian&nbsp;unstable&nbsp;main&nbsp;contrib&nbsp;non-free
+
+# Print a 410 (Gone) HTTP message with the specified text when accessed via
+# CGI. Useful to tell users to adapt their sources.list files when the
+# apt-cacher server is beeing relocated (via apt-get's error messages while
+# running "update")
+#cgi_advise_to_use = Please use http://cacheserver:3142/ as apt-cacher access URL
+#cgi_advise_to_use = Server relocated. To change sources.list, run perl -pe "s,/apt-cacher\??,:3142," -i /etc/apt/sources.list
+
+# Server mapping - this allows to hide real server names behind virtual paths
+# that appear in the access URL. This method is known from apt-proxy. This is
+# also the only method to use FTP access to the target hosts. The syntax is simple, the part of the beginning to replace, followed by a list of mirror urls, all space separated. Multiple profile are separated by semicolons
+# path_map = debian ftp.uni-kl.de/pub/linux/debian ftp2.de.debian.org/debian ; ubuntu archive.ubuntu.com/ubuntu ; security security.debian.org/debian-security ftp2.de.debian.org/debian-security
+# Note that you need to specify all target servers in the allowed_locations
+# options if you make use of it. Also note that the paths should not overlap
+# each other. FTP access method not supported yet, maybe in the future.
+
+# extra setting from apt-proxy configuration
+path_map =  ubuntu us.archive.ubuntu.com/ubuntu ; ubuntu-security security.ubuntu.com/ubuntu ; debian debian.osuosl.org/debian/ ; security security.debian.org/debian-security

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apt/files/default/.svn/text-base/apt-cacher.svn-base
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apt/files/default/.svn/text-base/apt-cacher.svn-base b/src/main/vm/src/cookbooks/apt/files/default/.svn/text-base/apt-cacher.svn-base
new file mode 100755
index 0000000..dab9488
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apt/files/default/.svn/text-base/apt-cacher.svn-base
@@ -0,0 +1,9 @@
+# apt-cacher startup configuration file
+
+# IMPORTANT: check the apt-cacher.conf file before using apt-cacher as daemon.
+
+# set to 1 to start the daemon at boot time
+AUTOSTART=1
+
+# extra settings to override the ones in apt-cacher.conf
+# EXTRAOPT=" daemon_port=3142 limit=30 "

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apt/files/default/.svn/text-base/apt-proxy-v2.conf.svn-base
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apt/files/default/.svn/text-base/apt-proxy-v2.conf.svn-base b/src/main/vm/src/cookbooks/apt/files/default/.svn/text-base/apt-proxy-v2.conf.svn-base
new file mode 100755
index 0000000..6541f25
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apt/files/default/.svn/text-base/apt-proxy-v2.conf.svn-base
@@ -0,0 +1,50 @@
+[DEFAULT]
+;; All times are in seconds, but you can add a suffix
+;; for minutes(m), hours(h) or days(d)
+
+;; commented out address so apt-proxy will listen on all IPs
+;; address = 127.0.0.1
+port = 9999
+cache_dir = /var/cache/apt-proxy
+
+;; Control files (Packages/Sources/Contents) refresh rate
+min_refresh_delay = 1s
+complete_clientless_downloads = 1
+
+;; Debugging settings.
+debug = all:4 db:0
+
+time = 30
+passive_ftp = on
+
+;;--------------------------------------------------------------
+;; Cache housekeeping
+
+cleanup_freq = 1d
+max_age = 120d
+max_versions = 3
+
+;;---------------------------------------------------------------
+;; Backend servers
+;;
+;; Place each server in its own [section]
+
+[ubuntu]
+; Ubuntu archive
+backends =
+        http://us.archive.ubuntu.com/ubuntu
+
+[ubuntu-security]
+; Ubuntu security updates
+backends = http://security.ubuntu.com/ubuntu
+
+[debian]
+;; Backend servers, in order of preference
+backends = 
+        http://debian.osuosl.org/debian/
+
+[security]
+;; Debian security archive
+backends = 
+        http://security.debian.org/debian-security
+        http://ftp2.de.debian.org/debian-security

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apt/files/default/apt-cacher
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apt/files/default/apt-cacher b/src/main/vm/src/cookbooks/apt/files/default/apt-cacher
new file mode 100755
index 0000000..dab9488
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apt/files/default/apt-cacher
@@ -0,0 +1,9 @@
+# apt-cacher startup configuration file
+
+# IMPORTANT: check the apt-cacher.conf file before using apt-cacher as daemon.
+
+# set to 1 to start the daemon at boot time
+AUTOSTART=1
+
+# extra settings to override the ones in apt-cacher.conf
+# EXTRAOPT=" daemon_port=3142 limit=30 "

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apt/files/default/apt-cacher.conf
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apt/files/default/apt-cacher.conf b/src/main/vm/src/cookbooks/apt/files/default/apt-cacher.conf
new file mode 100755
index 0000000..32ca3c3
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apt/files/default/apt-cacher.conf
@@ -0,0 +1,144 @@
+# This file has been modified by ./apt-proxy-to-apt-cacher
+# Some lines may have been appended at the bottom of this file
+# This file has been modified by /usr/share/apt-cacher/apt-proxy-to-apt-cacher
+# Some lines may have been appended at the bottom of this file
+#################################################################
+# This is the config file for apt-cacher. On most Debian systems
+# you can safely leave the defaults alone.
+#################################################################
+
+# cache_dir is used to set the location of the local cache. This can
+# become quite large, so make sure it is somewhere with plenty of space.
+cache_dir=/var/cache/apt-cacher
+
+# The email address of the administrator is displayed in the info page
+# and traffic reports.
+admin_email=root@localhost
+
+# For the daemon startup settings please edit the file /etc/default/apt-cacher.
+
+# Daemon port setting, only useful in stand-alone mode. You need to run the
+# daemon as root to use privileged ports (<1024).
+daemon_port = 3142
+
+# optional settings, user and group to run the daemon as. Make sure they have
+# sufficient permissions on the cache and log directories. Comment the settings
+# to run apt-cacher as the native user.
+group=www-data
+user=www-data
+
+# optional setting, binds the listening daemon to one specified IP. Use IP
+# ranges for more advanced configuration, see below.
+# daemon_addr=localhost
+
+# If your apt-cacher machine is directly exposed to the Internet and you are
+# worried about unauthorised machines fetching packages through it, you can
+# specify a list of IPv4 addresses which are allowed to use it and another
+# list of IPv4 addresses which aren't.
+# Localhost (127.0.0.1) is always allowed. Other addresses must be matched
+# by allowed_hosts and not by denied_hosts to be permitted to use the cache.
+# Setting allowed_hosts to "*" means "allow all".
+# Otherwise the format is a comma-separated list containing addresses,
+# optionally with masks (like 10.0.0.0/22), or ranges of addresses (two
+# addresses separated by a hyphen, no masks, like '192.168.0.3-192.168.0.56').
+allowed_hosts=*
+denied_hosts=
+
+# And similiarly for IPv6 with allowed_hosts_6 and denied_hosts_6.
+# Note that IPv4-mapped IPv6 addresses (::ffff:w.x.y.z) are truncated to
+# w.x.y.z and are handled as IPv4.
+allowed_hosts_6=fec0::/16
+denied_hosts_6=
+
+# This thing can be done by Apache but is much simplier here - limit access to
+# Debian mirrors based on server names in the URLs
+#allowed_locations=ftp.uni-kl.de,ftp.nerim.net,debian.tu-bs.de
+
+# Apt-cacher can generate usage reports every 24 hours if you set this
+# directive to 1. You can view the reports in a web browser by pointing
+# to your cache machine with '/apt-cacher/report' on the end, like this:
+#      http://yourcache.example.com/apt-cacher/report
+# Generating reports is very fast even with many thousands of logfile
+# lines, so you can safely turn this on without creating much 
+# additional system load.
+generate_reports=1
+
+# Apt-cacher can clean up its cache directory every 24 hours if you set
+# this directive to 1. Cleaning the cache can take some time to run
+# (generally in the order of a few minutes) and removes all package
+# files that are not mentioned in any existing 'Packages' lists. This
+# has the effect of deleting packages that have been superseded by an
+# updated 'Packages' list.
+clean_cache=1
+
+# The directory to use for apt-cacher access and error logs.
+# The access log records every request in the format:
+# date-time|client ip address|HIT/MISS/EXPIRED|object size|object name
+# The error log is slightly more free-form, and is also used for debug
+# messages if debug mode is turned on.
+# Note that the old 'logfile' and 'errorfile' directives are
+# deprecated: if you set them explicitly they will be honoured, but it's
+# better to just get rid of them from old config files.
+logdir=/var/log/apt-cacher
+
+# apt-cacher can use different methods to decide whether package lists need to
+# be updated,
+# A) looking at the age of the cached files
+# B) getting HTTP header from server and comparing that with cached data. This
+# method is more reliable and avoids desynchronisation of data and index files
+# but needs to transfer few bytes from the server every time somebody requests
+# the files ("apt-get update")
+# Set the following value to the maximum age (in hours) for method A or to 0
+# for method B
+expire_hours=0
+
+# Apt-cacher can pass all its requests to an external http proxy like
+# Squid, which could be very useful if you are using an ISP that blocks
+# port 80 and requires all web traffic to go through its proxy. The
+# format is 'hostname:port', eg: 'proxy.example.com:8080'.
+http_proxy=proxy.example.com:8080
+
+# Use of an external proxy can be turned on or off with this flag.
+# Value should be either 0 (off) or 1 (on).
+use_proxy=0
+
+# External http proxy sometimes need authentication to get full access. The
+# format is 'username:password'.
+http_proxy_auth=proxyuser:proxypass
+
+# Use of external proxy authentication can be turned on or off with this flag.
+# Value should be either 0 (off) or 1 (on).
+use_proxy_auth=0
+
+# Rate limiting sets the maximum bandwidth in bytes per second to use
+# for fetching packages. Syntax is fully defined in 'man wget'.
+# Use 'k' or 'm' to use kilobits or megabits / second: eg, 'limit=25k'.
+# Use 0 or a negative value for no rate limiting.
+limit=0
+
+# Debug mode makes apt-cacher spew a lot of extra debug junk to the
+# error log (whose location is defined with the 'logdir' directive).
+# Leave this off unless you need it, or your error log will get very
+# big. Acceptable values are 0 or 1.
+debug=0
+
+# Adapt the line in the usage info web page to match your server configuration
+# example_sources_line=deb&nbsp;http://<b>my.cacher.server:3142/</b>ftp.au.debian.org/debian&nbsp;unstable&nbsp;main&nbsp;contrib&nbsp;non-free
+
+# Print a 410 (Gone) HTTP message with the specified text when accessed via
+# CGI. Useful to tell users to adapt their sources.list files when the
+# apt-cacher server is beeing relocated (via apt-get's error messages while
+# running "update")
+#cgi_advise_to_use = Please use http://cacheserver:3142/ as apt-cacher access URL
+#cgi_advise_to_use = Server relocated. To change sources.list, run perl -pe "s,/apt-cacher\??,:3142," -i /etc/apt/sources.list
+
+# Server mapping - this allows to hide real server names behind virtual paths
+# that appear in the access URL. This method is known from apt-proxy. This is
+# also the only method to use FTP access to the target hosts. The syntax is simple, the part of the beginning to replace, followed by a list of mirror urls, all space separated. Multiple profile are separated by semicolons
+# path_map = debian ftp.uni-kl.de/pub/linux/debian ftp2.de.debian.org/debian ; ubuntu archive.ubuntu.com/ubuntu ; security security.debian.org/debian-security ftp2.de.debian.org/debian-security
+# Note that you need to specify all target servers in the allowed_locations
+# options if you make use of it. Also note that the paths should not overlap
+# each other. FTP access method not supported yet, maybe in the future.
+
+# extra setting from apt-proxy configuration
+path_map =  ubuntu us.archive.ubuntu.com/ubuntu ; ubuntu-security security.ubuntu.com/ubuntu ; debian debian.osuosl.org/debian/ ; security security.debian.org/debian-security

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apt/files/default/apt-proxy-v2.conf
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apt/files/default/apt-proxy-v2.conf b/src/main/vm/src/cookbooks/apt/files/default/apt-proxy-v2.conf
new file mode 100755
index 0000000..6541f25
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apt/files/default/apt-proxy-v2.conf
@@ -0,0 +1,50 @@
+[DEFAULT]
+;; All times are in seconds, but you can add a suffix
+;; for minutes(m), hours(h) or days(d)
+
+;; commented out address so apt-proxy will listen on all IPs
+;; address = 127.0.0.1
+port = 9999
+cache_dir = /var/cache/apt-proxy
+
+;; Control files (Packages/Sources/Contents) refresh rate
+min_refresh_delay = 1s
+complete_clientless_downloads = 1
+
+;; Debugging settings.
+debug = all:4 db:0
+
+time = 30
+passive_ftp = on
+
+;;--------------------------------------------------------------
+;; Cache housekeeping
+
+cleanup_freq = 1d
+max_age = 120d
+max_versions = 3
+
+;;---------------------------------------------------------------
+;; Backend servers
+;;
+;; Place each server in its own [section]
+
+[ubuntu]
+; Ubuntu archive
+backends =
+        http://us.archive.ubuntu.com/ubuntu
+
+[ubuntu-security]
+; Ubuntu security updates
+backends = http://security.ubuntu.com/ubuntu
+
+[debian]
+;; Backend servers, in order of preference
+backends = 
+        http://debian.osuosl.org/debian/
+
+[security]
+;; Debian security archive
+backends = 
+        http://security.debian.org/debian-security
+        http://ftp2.de.debian.org/debian-security

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apt/metadata.json
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apt/metadata.json b/src/main/vm/src/cookbooks/apt/metadata.json
new file mode 100755
index 0000000..00a5b18
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apt/metadata.json
@@ -0,0 +1,37 @@
+{
+    "dependencies": {
+    },
+    "replacing": {
+    },
+    "description": "Configures apt and apt services",
+    "groupings": {
+    },
+    "platforms": {
+      "ubuntu": [
+
+      ],
+      "debian": [
+
+      ]
+    },
+    "version": "0.8.0",
+    "recommendations": {
+    },
+    "name": "apt",
+    "maintainer": "Opscode, Inc.",
+    "long_description": "",
+    "recipes": {
+      "apt::proxy": "Set up an APT proxy",
+      "apt::cacher": "Set up an APT cache"
+    },
+    "suggestions": {
+    },
+    "maintainer_email": "cookbooks@opscode.com",
+    "attributes": {
+    },
+    "conflicting": {
+    },
+    "license": "Apache 2.0",
+    "providing": {
+    }
+  }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apt/metadata.rb
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apt/metadata.rb b/src/main/vm/src/cookbooks/apt/metadata.rb
new file mode 100755
index 0000000..cb6e712
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apt/metadata.rb
@@ -0,0 +1,11 @@
+maintainer        "Opscode, Inc."
+maintainer_email  "cookbooks@opscode.com"
+license           "Apache 2.0"
+description       "Configures apt and apt services"
+version           "0.8"
+recipe            "apt::cacher", "Set up an APT cache"
+recipe            "apt::proxy", "Set up an APT proxy"
+
+%w{ ubuntu debian }.each do |os|
+  supports os
+end

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apt/recipes/.svn/all-wcprops
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apt/recipes/.svn/all-wcprops b/src/main/vm/src/cookbooks/apt/recipes/.svn/all-wcprops
new file mode 100755
index 0000000..16128ba
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apt/recipes/.svn/all-wcprops
@@ -0,0 +1,23 @@
+K 25
+svn:wc:ra_dav:version-url
+V 95
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks/apt/recipes
+END
+proxy.rb
+K 25
+svn:wc:ra_dav:version-url
+V 104
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks/apt/recipes/proxy.rb
+END
+default.rb
+K 25
+svn:wc:ra_dav:version-url
+V 106
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks/apt/recipes/default.rb
+END
+cacher.rb
+K 25
+svn:wc:ra_dav:version-url
+V 105
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks/apt/recipes/cacher.rb
+END

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apt/recipes/.svn/entries
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apt/recipes/.svn/entries b/src/main/vm/src/cookbooks/apt/recipes/.svn/entries
new file mode 100755
index 0000000..c3dcc09
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apt/recipes/.svn/entries
@@ -0,0 +1,130 @@
+10
+
+dir
+1485921
+https://svn.apache.org/repos/asf/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks/apt/recipes
+https://svn.apache.org/repos/asf
+
+
+
+2012-10-10T00:49:17.045897Z
+1474264
+ahart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+13f79535-47bb-0310-9956-ffa450edef68
+
+proxy.rb
+file
+
+
+
+
+2013-05-24T10:13:54.000000Z
+6828328a6630ea1c87160c2cc71dda23
+2012-10-10T00:49:17.045897Z
+1474264
+ahart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+959
+
+default.rb
+file
+
+
+
+
+2013-05-24T10:13:54.000000Z
+112a8c22a020417dcc1c1fd06a4312ef
+2012-10-10T00:49:17.045897Z
+1474264
+ahart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+874
+
+cacher.rb
+file
+
+
+
+
+2013-05-24T10:13:54.000000Z
+fd845e36bdb8231419e15fd854b96525
+2012-10-10T00:49:17.045897Z
+1474264
+ahart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+1126
+

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apt/recipes/.svn/text-base/cacher.rb.svn-base
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apt/recipes/.svn/text-base/cacher.rb.svn-base b/src/main/vm/src/cookbooks/apt/recipes/.svn/text-base/cacher.rb.svn-base
new file mode 100755
index 0000000..2377408
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apt/recipes/.svn/text-base/cacher.rb.svn-base
@@ -0,0 +1,42 @@
+#
+# Cookbook Name:: apt
+# Recipe:: cacher
+#
+# Copyright 2008-2009, Opscode, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+package "apt-cacher" do
+  action :install
+end
+
+service "apt-cacher" do
+  supports :restart => true, :status => false
+  action [ :enable, :start ]
+end
+
+remote_file "/etc/apt-cacher/apt-cacher.conf" do
+  source "apt-cacher.conf"
+  owner "root"
+  group "root"
+  mode 0644
+  notifies :restart, resources(:service => "apt-cacher")
+end
+
+remote_file "/etc/default/apt-cacher" do
+  source "apt-cacher"
+  owner "root"
+  group "root"
+  mode 0644
+  notifies :restart, resources(:service => "apt-cacher")
+end

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apt/recipes/.svn/text-base/default.rb.svn-base
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apt/recipes/.svn/text-base/default.rb.svn-base b/src/main/vm/src/cookbooks/apt/recipes/.svn/text-base/default.rb.svn-base
new file mode 100755
index 0000000..d1117a7
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apt/recipes/.svn/text-base/default.rb.svn-base
@@ -0,0 +1,33 @@
+#
+# Cookbook Name:: apt
+# Recipe:: default
+#
+# Copyright 2008-2009, Opscode, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+e = execute "apt-get update" do
+  action :nothing
+end
+
+e.run_action(:run)
+
+%w{/var/cache/local /var/cache/local/preseeding}.each do |dirname|
+  directory dirname do
+    owner "root"
+    group "root"
+    mode  0755
+    action :create
+  end
+end

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apt/recipes/.svn/text-base/proxy.rb.svn-base
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apt/recipes/.svn/text-base/proxy.rb.svn-base b/src/main/vm/src/cookbooks/apt/recipes/.svn/text-base/proxy.rb.svn-base
new file mode 100755
index 0000000..3eede34
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apt/recipes/.svn/text-base/proxy.rb.svn-base
@@ -0,0 +1,34 @@
+#
+# Cookbook Name:: apt
+# Recipe:: proxy
+#
+# Copyright 2008-2009, Opscode, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+package "apt-proxy" do 
+  action :install
+end
+
+service "apt-proxy" do
+  supports :restart => true, :status => false
+  action [ :enable, :start ]
+end
+
+remote_file "/etc/apt-proxy/apt-proxy-v2.conf" do
+  source "apt-proxy-v2.conf"
+  owner "root"
+  group "root"
+  mode 0644
+  notifies :restart, resources(:service => "apt-proxy")
+end

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apt/recipes/cacher.rb
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apt/recipes/cacher.rb b/src/main/vm/src/cookbooks/apt/recipes/cacher.rb
new file mode 100755
index 0000000..2377408
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apt/recipes/cacher.rb
@@ -0,0 +1,42 @@
+#
+# Cookbook Name:: apt
+# Recipe:: cacher
+#
+# Copyright 2008-2009, Opscode, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+package "apt-cacher" do
+  action :install
+end
+
+service "apt-cacher" do
+  supports :restart => true, :status => false
+  action [ :enable, :start ]
+end
+
+remote_file "/etc/apt-cacher/apt-cacher.conf" do
+  source "apt-cacher.conf"
+  owner "root"
+  group "root"
+  mode 0644
+  notifies :restart, resources(:service => "apt-cacher")
+end
+
+remote_file "/etc/default/apt-cacher" do
+  source "apt-cacher"
+  owner "root"
+  group "root"
+  mode 0644
+  notifies :restart, resources(:service => "apt-cacher")
+end

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apt/recipes/default.rb
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apt/recipes/default.rb b/src/main/vm/src/cookbooks/apt/recipes/default.rb
new file mode 100755
index 0000000..d1117a7
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apt/recipes/default.rb
@@ -0,0 +1,33 @@
+#
+# Cookbook Name:: apt
+# Recipe:: default
+#
+# Copyright 2008-2009, Opscode, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+e = execute "apt-get update" do
+  action :nothing
+end
+
+e.run_action(:run)
+
+%w{/var/cache/local /var/cache/local/preseeding}.each do |dirname|
+  directory dirname do
+    owner "root"
+    group "root"
+    mode  0755
+    action :create
+  end
+end

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/apt/recipes/proxy.rb
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/apt/recipes/proxy.rb b/src/main/vm/src/cookbooks/apt/recipes/proxy.rb
new file mode 100755
index 0000000..3eede34
--- /dev/null
+++ b/src/main/vm/src/cookbooks/apt/recipes/proxy.rb
@@ -0,0 +1,34 @@
+#
+# Cookbook Name:: apt
+# Recipe:: proxy
+#
+# Copyright 2008-2009, Opscode, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+package "apt-proxy" do 
+  action :install
+end
+
+service "apt-proxy" do
+  supports :restart => true, :status => false
+  action [ :enable, :start ]
+end
+
+remote_file "/etc/apt-proxy/apt-proxy-v2.conf" do
+  source "apt-proxy-v2.conf"
+  owner "root"
+  group "root"
+  mode 0644
+  notifies :restart, resources(:service => "apt-proxy")
+end

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/build-essential/.svn/all-wcprops
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/build-essential/.svn/all-wcprops b/src/main/vm/src/cookbooks/build-essential/.svn/all-wcprops
new file mode 100755
index 0000000..5fe7f60
--- /dev/null
+++ b/src/main/vm/src/cookbooks/build-essential/.svn/all-wcprops
@@ -0,0 +1,41 @@
+K 25
+svn:wc:ra_dav:version-url
+V 99
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks/build-essential
+END
+LICENSE
+K 25
+svn:wc:ra_dav:version-url
+V 107
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks/build-essential/LICENSE
+END
+metadata.rb
+K 25
+svn:wc:ra_dav:version-url
+V 111
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks/build-essential/metadata.rb
+END
+CHANGELOG.md
+K 25
+svn:wc:ra_dav:version-url
+V 112
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks/build-essential/CHANGELOG.md
+END
+CONTRIBUTING
+K 25
+svn:wc:ra_dav:version-url
+V 112
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks/build-essential/CONTRIBUTING
+END
+metadata.json
+K 25
+svn:wc:ra_dav:version-url
+V 113
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks/build-essential/metadata.json
+END
+README.md
+K 25
+svn:wc:ra_dav:version-url
+V 109
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks/build-essential/README.md
+END

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/build-essential/.svn/entries
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/build-essential/.svn/entries b/src/main/vm/src/cookbooks/build-essential/.svn/entries
new file mode 100755
index 0000000..a49a2c8
--- /dev/null
+++ b/src/main/vm/src/cookbooks/build-essential/.svn/entries
@@ -0,0 +1,238 @@
+10
+
+dir
+1485921
+https://svn.apache.org/repos/asf/incubator/climate/trunk/rcmet/src/main/vm/src/cookbooks/build-essential
+https://svn.apache.org/repos/asf
+
+
+
+2012-11-20T00:41:43.621075Z
+1474518
+ahart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+13f79535-47bb-0310-9956-ffa450edef68
+
+LICENSE
+file
+
+
+
+
+2013-05-24T10:13:54.000000Z
+8f7bb094c7232b058c7e9f2e431f389c
+2012-11-20T00:41:43.621075Z
+1474518
+ahart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+10850
+
+metadata.rb
+file
+
+
+
+
+2013-05-24T10:13:54.000000Z
+eefa8e3bc0c601ca62ca806748bfef80
+2012-11-20T00:41:43.621075Z
+1474518
+ahart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+405
+
+attributes
+dir
+
+CHANGELOG.md
+file
+
+
+
+
+2013-05-24T10:13:54.000000Z
+01a0d9bda931b3db0669386685b25a13
+2012-11-20T00:41:43.621075Z
+1474518
+ahart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+334
+
+CONTRIBUTING
+file
+
+
+
+
+2013-05-24T10:13:54.000000Z
+e5600a5296cb1b69f978b6c2c4a1b1c1
+2012-11-20T00:41:43.621075Z
+1474518
+ahart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+1233
+
+metadata.json
+file
+
+
+
+
+2013-05-24T10:13:54.000000Z
+395351c1ca1d3d15e3082dcc638a0a19
+2012-11-20T00:41:43.621075Z
+1474518
+ahart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+746
+
+recipes
+dir
+
+README.md
+file
+
+
+
+
+2013-05-24T10:13:54.000000Z
+a31c5d9fe330c754ecd0363b90b2f913
+2012-11-20T00:41:43.621075Z
+1474518
+ahart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+4076
+

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/build-essential/.svn/text-base/CHANGELOG.md.svn-base
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/build-essential/.svn/text-base/CHANGELOG.md.svn-base b/src/main/vm/src/cookbooks/build-essential/.svn/text-base/CHANGELOG.md.svn-base
new file mode 100755
index 0000000..853667d
--- /dev/null
+++ b/src/main/vm/src/cookbooks/build-essential/.svn/text-base/CHANGELOG.md.svn-base
@@ -0,0 +1,15 @@
+## v1.1.2:
+
+* [COOK-1620] - support OS X 10.8
+
+## v1.1.0:
+
+* [COOK-1098] - support amazon linux
+* [COOK-1149] - support Mac OS X
+* [COOK-1296] - allow for compile-time installation of packages
+  through an attribute (see README)
+
+## v1.0.2:
+
+* [COOK-1098] - Add Amazon Linux platform support
+* [COOK-1149] - Add OS X platform support

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/build-essential/.svn/text-base/CONTRIBUTING.svn-base
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/build-essential/.svn/text-base/CONTRIBUTING.svn-base b/src/main/vm/src/cookbooks/build-essential/.svn/text-base/CONTRIBUTING.svn-base
new file mode 100755
index 0000000..89ac873
--- /dev/null
+++ b/src/main/vm/src/cookbooks/build-essential/.svn/text-base/CONTRIBUTING.svn-base
@@ -0,0 +1,29 @@
+If you would like to contribute, please open a ticket in JIRA:
+
+* http://tickets.opscode.com
+
+Create the ticket in the COOK project and use the cookbook name as the
+component.
+
+For all code contributions, we ask that contributors sign a
+contributor license agreement (CLA). Instructions may be found here:
+
+* http://wiki.opscode.com/display/chef/How+to+Contribute
+
+When contributing changes to individual cookbooks, please do not
+modify the version number in the metadata.rb. Also please do not
+update the CHANGELOG.md for a new version. Not all changes to a
+cookbook may be merged and released in the same versions. Opscode will
+handle the version updates during the release process. You are welcome
+to correct typos or otherwise make updates to documentation in the
+README.
+
+If a contribution adds new platforms or platform versions, indicate
+such in the body of the commit message(s), and update the relevant
+COOK ticket. When writing commit messages, it is helpful for others if
+you indicate the COOK ticket. For example:
+
+    git commit -m '[COOK-1041] Updated pool resource to correctly delete.'
+
+In the ticket itself, it is also helpful if you include log output of
+a successful Chef run, but this is not absolutely required.

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/build-essential/.svn/text-base/LICENSE.svn-base
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/build-essential/.svn/text-base/LICENSE.svn-base b/src/main/vm/src/cookbooks/build-essential/.svn/text-base/LICENSE.svn-base
new file mode 100755
index 0000000..11069ed
--- /dev/null
+++ b/src/main/vm/src/cookbooks/build-essential/.svn/text-base/LICENSE.svn-base
@@ -0,0 +1,201 @@
+                              Apache License
+                        Version 2.0, January 2004
+                     http://www.apache.org/licenses/
+
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+1. Definitions.
+
+   "License" shall mean the terms and conditions for use, reproduction,
+   and distribution as defined by Sections 1 through 9 of this document.
+
+   "Licensor" shall mean the copyright owner or entity authorized by
+   the copyright owner that is granting the License.
+
+   "Legal Entity" shall mean the union of the acting entity and all
+   other entities that control, are controlled by, or are under common
+   control with that entity. For the purposes of this definition,
+   "control" means (i) the power, direct or indirect, to cause the
+   direction or management of such entity, whether by contract or
+   otherwise, or (ii) ownership of fifty percent (50%) or more of the
+   outstanding shares, or (iii) beneficial ownership of such entity.
+
+   "You" (or "Your") shall mean an individual or Legal Entity
+   exercising permissions granted by this License.
+
+   "Source" form shall mean the preferred form for making modifications,
+   including but not limited to software source code, documentation
+   source, and configuration files.
+
+   "Object" form shall mean any form resulting from mechanical
+   transformation or translation of a Source form, including but
+   not limited to compiled object code, generated documentation,
+   and conversions to other media types.
+
+   "Work" shall mean the work of authorship, whether in Source or
+   Object form, made available under the License, as indicated by a
+   copyright notice that is included in or attached to the work
+   (an example is provided in the Appendix below).
+
+   "Derivative Works" shall mean any work, whether in Source or Object
+   form, that is based on (or derived from) the Work and for which the
+   editorial revisions, annotations, elaborations, or other modifications
+   represent, as a whole, an original work of authorship. For the purposes
+   of this License, Derivative Works shall not include works that remain
+   separable from, or merely link (or bind by name) to the interfaces of,
+   the Work and Derivative Works thereof.
+
+   "Contribution" shall mean any work of authorship, including
+   the original version of the Work and any modifications or additions
+   to that Work or Derivative Works thereof, that is intentionally
+   submitted to Licensor for inclusion in the Work by the copyright owner
+   or by an individual or Legal Entity authorized to submit on behalf of
+   the copyright owner. For the purposes of this definition, "submitted"
+   means any form of electronic, verbal, or written communication sent
+   to the Licensor or its representatives, including but not limited to
+   communication on electronic mailing lists, source code control systems,
+   and issue tracking systems that are managed by, or on behalf of, the
+   Licensor for the purpose of discussing and improving the Work, but
+   excluding communication that is conspicuously marked or otherwise
+   designated in writing by the copyright owner as "Not a Contribution."
+
+   "Contributor" shall mean Licensor and any individual or Legal Entity
+   on behalf of whom a Contribution has been received by Licensor and
+   subsequently incorporated within the Work.
+
+2. Grant of Copyright License. Subject to the terms and conditions of
+   this License, each Contributor hereby grants to You a perpetual,
+   worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+   copyright license to reproduce, prepare Derivative Works of,
+   publicly display, publicly perform, sublicense, and distribute the
+   Work and such Derivative Works in Source or Object form.
+
+3. Grant of Patent License. Subject to the terms and conditions of
+   this License, each Contributor hereby grants to You a perpetual,
+   worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+   (except as stated in this section) patent license to make, have made,
+   use, offer to sell, sell, import, and otherwise transfer the Work,
+   where such license applies only to those patent claims licensable
+   by such Contributor that are necessarily infringed by their
+   Contribution(s) alone or by combination of their Contribution(s)
+   with the Work to which such Contribution(s) was submitted. If You
+   institute patent litigation against any entity (including a
+   cross-claim or counterclaim in a lawsuit) alleging that the Work
+   or a Contribution incorporated within the Work constitutes direct
+   or contributory patent infringement, then any patent licenses
+   granted to You under this License for that Work shall terminate
+   as of the date such litigation is filed.
+
+4. Redistribution. You may reproduce and distribute copies of the
+   Work or Derivative Works thereof in any medium, with or without
+   modifications, and in Source or Object form, provided that You
+   meet the following conditions:
+
+   (a) You must give any other recipients of the Work or
+       Derivative Works a copy of this License; and
+
+   (b) You must cause any modified files to carry prominent notices
+       stating that You changed the files; and
+
+   (c) You must retain, in the Source form of any Derivative Works
+       that You distribute, all copyright, patent, trademark, and
+       attribution notices from the Source form of the Work,
+       excluding those notices that do not pertain to any part of
+       the Derivative Works; and
+
+   (d) If the Work includes a "NOTICE" text file as part of its
+       distribution, then any Derivative Works that You distribute must
+       include a readable copy of the attribution notices contained
+       within such NOTICE file, excluding those notices that do not
+       pertain to any part of the Derivative Works, in at least one
+       of the following places: within a NOTICE text file distributed
+       as part of the Derivative Works; within the Source form or
+       documentation, if provided along with the Derivative Works; or,
+       within a display generated by the Derivative Works, if and
+       wherever such third-party notices normally appear. The contents
+       of the NOTICE file are for informational purposes only and
+       do not modify the License. You may add Your own attribution
+       notices within Derivative Works that You distribute, alongside
+       or as an addendum to the NOTICE text from the Work, provided
+       that such additional attribution notices cannot be construed
+       as modifying the License.
+
+   You may add Your own copyright statement to Your modifications and
+   may provide additional or different license terms and conditions
+   for use, reproduction, or distribution of Your modifications, or
+   for any such Derivative Works as a whole, provided Your use,
+   reproduction, and distribution of the Work otherwise complies with
+   the conditions stated in this License.
+
+5. Submission of Contributions. Unless You explicitly state otherwise,
+   any Contribution intentionally submitted for inclusion in the Work
+   by You to the Licensor shall be under the terms and conditions of
+   this License, without any additional terms or conditions.
+   Notwithstanding the above, nothing herein shall supersede or modify
+   the terms of any separate license agreement you may have executed
+   with Licensor regarding such Contributions.
+
+6. Trademarks. This License does not grant permission to use the trade
+   names, trademarks, service marks, or product names of the Licensor,
+   except as required for reasonable and customary use in describing the
+   origin of the Work and reproducing the content of the NOTICE file.
+
+7. Disclaimer of Warranty. Unless required by applicable law or
+   agreed to in writing, Licensor provides the Work (and each
+   Contributor provides its Contributions) on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+   implied, including, without limitation, any warranties or conditions
+   of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+   PARTICULAR PURPOSE. You are solely responsible for determining the
+   appropriateness of using or redistributing the Work and assume any
+   risks associated with Your exercise of permissions under this License.
+
+8. Limitation of Liability. In no event and under no legal theory,
+   whether in tort (including negligence), contract, or otherwise,
+   unless required by applicable law (such as deliberate and grossly
+   negligent acts) or agreed to in writing, shall any Contributor be
+   liable to You for damages, including any direct, indirect, special,
+   incidental, or consequential damages of any character arising as a
+   result of this License or out of the use or inability to use the
+   Work (including but not limited to damages for loss of goodwill,
+   work stoppage, computer failure or malfunction, or any and all
+   other commercial damages or losses), even if such Contributor
+   has been advised of the possibility of such damages.
+
+9. Accepting Warranty or Additional Liability. While redistributing
+   the Work or Derivative Works thereof, You may choose to offer,
+   and charge a fee for, acceptance of support, warranty, indemnity,
+   or other liability obligations and/or rights consistent with this
+   License. However, in accepting such obligations, You may act only
+   on Your own behalf and on Your sole responsibility, not on behalf
+   of any other Contributor, and only if You agree to indemnify,
+   defend, and hold each Contributor harmless for any liability
+   incurred by, or claims asserted against, such Contributor by reason
+   of your accepting any such warranty or additional liability.
+
+END OF TERMS AND CONDITIONS
+
+APPENDIX: How to apply the Apache License to your work.
+
+   To apply the Apache License to your work, attach the following
+   boilerplate notice, with the fields enclosed by brackets "[]"
+   replaced with your own identifying information. (Don't include
+   the brackets!)  The text should be enclosed in the appropriate
+   comment syntax for the file format. We also recommend that a
+   file or class name and description of purpose be included on the
+   same "printed page" as the copyright notice for easier
+   identification within third-party archives.
+
+Copyright [yyyy] [name of copyright owner]
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/build-essential/.svn/text-base/README.md.svn-base
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/build-essential/.svn/text-base/README.md.svn-base b/src/main/vm/src/cookbooks/build-essential/.svn/text-base/README.md.svn-base
new file mode 100755
index 0000000..218adf0
--- /dev/null
+++ b/src/main/vm/src/cookbooks/build-essential/.svn/text-base/README.md.svn-base
@@ -0,0 +1,124 @@
+Description
+===========
+
+Installs packages required for compiling C software from source. Use
+this cookbook if you wish to compile C programs, or install RubyGems
+with native extensions.
+
+Requirements
+============
+
+## Platform
+
+Supported platforms by platform family:
+
+* Linux (debian, rhel, fedora)
+* Darwin (`mac_os_x` 10.6+)
+
+Attributes
+==========
+
+* `node['build_essential']['compiletime']` - Whether the resources in
+the default recipe should be configured at the "Compile" phase of the
+Chef run. Defaults to false, see __Usage__ for more information.
+* `node['build_essential']['osx']['gcc_installer_url']` - The URL of
+  the OS X GCC package installer (.pkg).
+* `node['build_essential']['osx']['gcc_installer_checksum']` - The
+  SHA256 checksum of the OS X GCC installer.
+
+Recipes
+=======
+
+This cookbook has one recipe, default.
+
+On Linux platforms (see __Platform__ above for a supported list of
+families), packages required to build C source projects are installed.
+This includes GCC, make, autconf and others. On Debian-family
+distributions, the apt-cache may need to be updated, especially during
+compile time installation. See __Usage__ for further information.
+
+On Mac OS X, the GCC standalone installer by Kenneth Reitz is
+installed. Note that this is *not* the Xcode CLI package, as that does
+not include all programs and headers required to build some common
+GNU-style C projects, such as those that are available from projects
+such as MacPorts or Homebrew. Changing the attributes for the GCC
+installer URL and checksum to the Xcode values may work, but this is
+untested.
+
+Usage
+=====
+
+Simply include the `build-essential` and the required tools will be
+installed to the system, and later recipes will be able to compile
+software from C source code.
+
+For RubyGems that include native C extensions you wish to use with
+Chef, you should do two things.
+
+0. Ensure that the C libraries, include files and other assorted "dev"
+type packages are installed. You should do this in the compile phase
+after the build-essential recipe.
+1. Use the `chef_gem` resource in your recipes. This requires Chef version 0.10.10+.
+2. Set the `compiletime` attribute in roles where such recipes are
+required. This will ensure that the build tools are available to
+compile the RubyGems' extensions, as `chef_gem` happens during the
+compile phase, too.
+
+Example installation of a devel package at compile-time in a recipe:
+
+    package "mypackage-dev" do
+      action :nothing
+    end.run_action(:install)
+
+Example use of `chef_gem`:
+
+    chef_gem "mygem"
+
+Example role:
+
+    name "myapp"
+    run_list(
+      "recipe[build-essential]",
+      "recipe[myapp]"
+    )
+    default_attributes(
+      "build_essential" => {
+        "compiletime" => true
+      }
+    )
+
+The compile time option (via the attribute) is to ensure that the
+proper packages are available at the right time in the Chef run. It is
+recommended that the build-essential recipe appear early in the run
+list.
+
+The Chef wiki has documentation on
+[the anatomy of a chef run](http://wiki.opscode.com/display/chef/Anatomy+of+a+Chef+Run).
+
+Limitations
+===========
+
+It is not in the scope of this cookbook to handle installing the
+required headers for individual software projects in order to compile
+them, or to compile RubyGems with native C extensions. You should
+create a cookbook for handling that.
+
+License and Author
+==================
+
+Author:: Joshua Timberman (<jo...@opscode.com>)
+Author:: Seth Chisamore (<sc...@opscode.com>)
+
+Copyright 2009-2011, Opscode, Inc. (<le...@opscode.com>)
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/build-essential/.svn/text-base/metadata.json.svn-base
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/build-essential/.svn/text-base/metadata.json.svn-base b/src/main/vm/src/cookbooks/build-essential/.svn/text-base/metadata.json.svn-base
new file mode 100755
index 0000000..c626b13
--- /dev/null
+++ b/src/main/vm/src/cookbooks/build-essential/.svn/text-base/metadata.json.svn-base
@@ -0,0 +1,37 @@
+{
+  "name": "build-essential",
+  "description": "Installs C compiler / build tools",
+  "long_description": "",
+  "maintainer": "Opscode, Inc.",
+  "maintainer_email": "cookbooks@opscode.com",
+  "license": "Apache 2.0",
+  "platforms": {
+    "fedora": ">= 0.0.0",
+    "redhat": ">= 0.0.0",
+    "centos": ">= 0.0.0",
+    "ubuntu": ">= 0.0.0",
+    "debian": ">= 0.0.0",
+    "amazon": ">= 0.0.0",
+    "mac_os_x": ">= 10.6.0"
+  },
+  "dependencies": {
+  },
+  "recommendations": {
+  },
+  "suggestions": {
+  },
+  "conflicting": {
+  },
+  "providing": {
+  },
+  "replacing": {
+  },
+  "attributes": {
+  },
+  "groupings": {
+  },
+  "recipes": {
+    "build-essential": "Installs packages required for compiling C software from source."
+  },
+  "version": "1.1.2"
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/build-essential/.svn/text-base/metadata.rb.svn-base
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/build-essential/.svn/text-base/metadata.rb.svn-base b/src/main/vm/src/cookbooks/build-essential/.svn/text-base/metadata.rb.svn-base
new file mode 100755
index 0000000..23df6aa
--- /dev/null
+++ b/src/main/vm/src/cookbooks/build-essential/.svn/text-base/metadata.rb.svn-base
@@ -0,0 +1,12 @@
+maintainer        "Opscode, Inc."
+maintainer_email  "cookbooks@opscode.com"
+license           "Apache 2.0"
+description       "Installs C compiler / build tools"
+version           "1.1.2"
+recipe            "build-essential", "Installs packages required for compiling C software from source."
+
+%w{ fedora redhat centos ubuntu debian amazon }.each do |os|
+  supports os
+end
+
+supports "mac_os_x", ">= 10.6.0"

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/build-essential/CHANGELOG.md
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/build-essential/CHANGELOG.md b/src/main/vm/src/cookbooks/build-essential/CHANGELOG.md
new file mode 100755
index 0000000..853667d
--- /dev/null
+++ b/src/main/vm/src/cookbooks/build-essential/CHANGELOG.md
@@ -0,0 +1,15 @@
+## v1.1.2:
+
+* [COOK-1620] - support OS X 10.8
+
+## v1.1.0:
+
+* [COOK-1098] - support amazon linux
+* [COOK-1149] - support Mac OS X
+* [COOK-1296] - allow for compile-time installation of packages
+  through an attribute (see README)
+
+## v1.0.2:
+
+* [COOK-1098] - Add Amazon Linux platform support
+* [COOK-1149] - Add OS X platform support

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/vm/src/cookbooks/build-essential/CONTRIBUTING
----------------------------------------------------------------------
diff --git a/src/main/vm/src/cookbooks/build-essential/CONTRIBUTING b/src/main/vm/src/cookbooks/build-essential/CONTRIBUTING
new file mode 100755
index 0000000..89ac873
--- /dev/null
+++ b/src/main/vm/src/cookbooks/build-essential/CONTRIBUTING
@@ -0,0 +1,29 @@
+If you would like to contribute, please open a ticket in JIRA:
+
+* http://tickets.opscode.com
+
+Create the ticket in the COOK project and use the cookbook name as the
+component.
+
+For all code contributions, we ask that contributors sign a
+contributor license agreement (CLA). Instructions may be found here:
+
+* http://wiki.opscode.com/display/chef/How+to+Contribute
+
+When contributing changes to individual cookbooks, please do not
+modify the version number in the metadata.rb. Also please do not
+update the CHANGELOG.md for a new version. Not all changes to a
+cookbook may be merged and released in the same versions. Opscode will
+handle the version updates during the release process. You are welcome
+to correct typos or otherwise make updates to documentation in the
+README.
+
+If a contribution adds new platforms or platform versions, indicate
+such in the body of the commit message(s), and update the relevant
+COOK ticket. When writing commit messages, it is helpful for others if
+you indicate the COOK ticket. For example:
+
+    git commit -m '[COOK-1041] Updated pool resource to correctly delete.'
+
+In the ticket itself, it is also helpful if you include log output of
+a successful Chef run, but this is not absolutely required.


[13/51] [abbrv] [partial] Adding Jinwon's custom RCMET

Posted by jo...@apache.org.
http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/ui/test/lib/angular/.svn/text-base/angular-mocks.js.svn-base
----------------------------------------------------------------------
diff --git a/src/main/ui/test/lib/angular/.svn/text-base/angular-mocks.js.svn-base b/src/main/ui/test/lib/angular/.svn/text-base/angular-mocks.js.svn-base
new file mode 100755
index 0000000..b6ecc79
--- /dev/null
+++ b/src/main/ui/test/lib/angular/.svn/text-base/angular-mocks.js.svn-base
@@ -0,0 +1,1764 @@
+/**
+ * @license AngularJS v1.0.5
+ * (c) 2010-2012 Google, Inc. http://angularjs.org
+ * License: MIT
+ *
+ * TODO(vojta): wrap whole file into closure during build
+ */
+
+/**
+ * @ngdoc overview
+ * @name angular.mock
+ * @description
+ *
+ * Namespace from 'angular-mocks.js' which contains testing related code.
+ */
+angular.mock = {};
+
+/**
+ * ! This is a private undocumented service !
+ *
+ * @name ngMock.$browser
+ *
+ * @description
+ * This service is a mock implementation of {@link ng.$browser}. It provides fake
+ * implementation for commonly used browser apis that are hard to test, e.g. setTimeout, xhr,
+ * cookies, etc...
+ *
+ * The api of this service is the same as that of the real {@link ng.$browser $browser}, except
+ * that there are several helper methods available which can be used in tests.
+ */
+angular.mock.$BrowserProvider = function() {
+  this.$get = function(){
+    return new angular.mock.$Browser();
+  };
+};
+
+angular.mock.$Browser = function() {
+  var self = this;
+
+  this.isMock = true;
+  self.$$url = "http://server/";
+  self.$$lastUrl = self.$$url; // used by url polling fn
+  self.pollFns = [];
+
+  // TODO(vojta): remove this temporary api
+  self.$$completeOutstandingRequest = angular.noop;
+  self.$$incOutstandingRequestCount = angular.noop;
+
+
+  // register url polling fn
+
+  self.onUrlChange = function(listener) {
+    self.pollFns.push(
+      function() {
+        if (self.$$lastUrl != self.$$url) {
+          self.$$lastUrl = self.$$url;
+          listener(self.$$url);
+        }
+      }
+    );
+
+    return listener;
+  };
+
+  self.cookieHash = {};
+  self.lastCookieHash = {};
+  self.deferredFns = [];
+  self.deferredNextId = 0;
+
+  self.defer = function(fn, delay) {
+    delay = delay || 0;
+    self.deferredFns.push({time:(self.defer.now + delay), fn:fn, id: self.deferredNextId});
+    self.deferredFns.sort(function(a,b){ return a.time - b.time;});
+    return self.deferredNextId++;
+  };
+
+
+  self.defer.now = 0;
+
+
+  self.defer.cancel = function(deferId) {
+    var fnIndex;
+
+    angular.forEach(self.deferredFns, function(fn, index) {
+      if (fn.id === deferId) fnIndex = index;
+    });
+
+    if (fnIndex !== undefined) {
+      self.deferredFns.splice(fnIndex, 1);
+      return true;
+    }
+
+    return false;
+  };
+
+
+  /**
+   * @name ngMock.$browser#defer.flush
+   * @methodOf ngMock.$browser
+   *
+   * @description
+   * Flushes all pending requests and executes the defer callbacks.
+   *
+   * @param {number=} number of milliseconds to flush. See {@link #defer.now}
+   */
+  self.defer.flush = function(delay) {
+    if (angular.isDefined(delay)) {
+      self.defer.now += delay;
+    } else {
+      if (self.deferredFns.length) {
+        self.defer.now = self.deferredFns[self.deferredFns.length-1].time;
+      } else {
+        throw Error('No deferred tasks to be flushed');
+      }
+    }
+
+    while (self.deferredFns.length && self.deferredFns[0].time <= self.defer.now) {
+      self.deferredFns.shift().fn();
+    }
+  };
+  /**
+   * @name ngMock.$browser#defer.now
+   * @propertyOf ngMock.$browser
+   *
+   * @description
+   * Current milliseconds mock time.
+   */
+
+  self.$$baseHref = '';
+  self.baseHref = function() {
+    return this.$$baseHref;
+  };
+};
+angular.mock.$Browser.prototype = {
+
+/**
+  * @name ngMock.$browser#poll
+  * @methodOf ngMock.$browser
+  *
+  * @description
+  * run all fns in pollFns
+  */
+  poll: function poll() {
+    angular.forEach(this.pollFns, function(pollFn){
+      pollFn();
+    });
+  },
+
+  addPollFn: function(pollFn) {
+    this.pollFns.push(pollFn);
+    return pollFn;
+  },
+
+  url: function(url, replace) {
+    if (url) {
+      this.$$url = url;
+      return this;
+    }
+
+    return this.$$url;
+  },
+
+  cookies:  function(name, value) {
+    if (name) {
+      if (value == undefined) {
+        delete this.cookieHash[name];
+      } else {
+        if (angular.isString(value) &&       //strings only
+            value.length <= 4096) {          //strict cookie storage limits
+          this.cookieHash[name] = value;
+        }
+      }
+    } else {
+      if (!angular.equals(this.cookieHash, this.lastCookieHash)) {
+        this.lastCookieHash = angular.copy(this.cookieHash);
+        this.cookieHash = angular.copy(this.cookieHash);
+      }
+      return this.cookieHash;
+    }
+  },
+
+  notifyWhenNoOutstandingRequests: function(fn) {
+    fn();
+  }
+};
+
+
+/**
+ * @ngdoc object
+ * @name ngMock.$exceptionHandlerProvider
+ *
+ * @description
+ * Configures the mock implementation of {@link ng.$exceptionHandler} to rethrow or to log errors passed
+ * into the `$exceptionHandler`.
+ */
+
+/**
+ * @ngdoc object
+ * @name ngMock.$exceptionHandler
+ *
+ * @description
+ * Mock implementation of {@link ng.$exceptionHandler} that rethrows or logs errors passed
+ * into it. See {@link ngMock.$exceptionHandlerProvider $exceptionHandlerProvider} for configuration
+ * information.
+ *
+ *
+ * <pre>
+ *   describe('$exceptionHandlerProvider', function() {
+ *
+ *     it('should capture log messages and exceptions', function() {
+ *
+ *       module(function($exceptionHandlerProvider) {
+ *         $exceptionHandlerProvider.mode('log');
+ *       });
+ *
+ *       inject(function($log, $exceptionHandler, $timeout) {
+ *         $timeout(function() { $log.log(1); });
+ *         $timeout(function() { $log.log(2); throw 'banana peel'; });
+ *         $timeout(function() { $log.log(3); });
+ *         expect($exceptionHandler.errors).toEqual([]);
+ *         expect($log.assertEmpty());
+ *         $timeout.flush();
+ *         expect($exceptionHandler.errors).toEqual(['banana peel']);
+ *         expect($log.log.logs).toEqual([[1], [2], [3]]);
+ *       });
+ *     });
+ *   });
+ * </pre>
+ */
+
+angular.mock.$ExceptionHandlerProvider = function() {
+  var handler;
+
+  /**
+   * @ngdoc method
+   * @name ngMock.$exceptionHandlerProvider#mode
+   * @methodOf ngMock.$exceptionHandlerProvider
+   *
+   * @description
+   * Sets the logging mode.
+   *
+   * @param {string} mode Mode of operation, defaults to `rethrow`.
+   *
+   *   - `rethrow`: If any errors are are passed into the handler in tests, it typically
+   *                means that there is a bug in the application or test, so this mock will
+   *                make these tests fail.
+   *   - `log`: Sometimes it is desirable to test that an error is throw, for this case the `log` mode stores an
+   *            array of errors in `$exceptionHandler.errors`, to allow later assertion of them.
+   *            See {@link ngMock.$log#assertEmpty assertEmpty()} and
+   *             {@link ngMock.$log#reset reset()}
+   */
+  this.mode = function(mode) {
+    switch(mode) {
+      case 'rethrow':
+        handler = function(e) {
+          throw e;
+        };
+        break;
+      case 'log':
+        var errors = [];
+
+        handler = function(e) {
+          if (arguments.length == 1) {
+            errors.push(e);
+          } else {
+            errors.push([].slice.call(arguments, 0));
+          }
+        };
+
+        handler.errors = errors;
+        break;
+      default:
+        throw Error("Unknown mode '" + mode + "', only 'log'/'rethrow' modes are allowed!");
+    }
+  };
+
+  this.$get = function() {
+    return handler;
+  };
+
+  this.mode('rethrow');
+};
+
+
+/**
+ * @ngdoc service
+ * @name ngMock.$log
+ *
+ * @description
+ * Mock implementation of {@link ng.$log} that gathers all logged messages in arrays
+ * (one array per logging level). These arrays are exposed as `logs` property of each of the
+ * level-specific log function, e.g. for level `error` the array is exposed as `$log.error.logs`.
+ *
+ */
+angular.mock.$LogProvider = function() {
+
+  function concat(array1, array2, index) {
+    return array1.concat(Array.prototype.slice.call(array2, index));
+  }
+
+
+  this.$get = function () {
+    var $log = {
+      log: function() { $log.log.logs.push(concat([], arguments, 0)); },
+      warn: function() { $log.warn.logs.push(concat([], arguments, 0)); },
+      info: function() { $log.info.logs.push(concat([], arguments, 0)); },
+      error: function() { $log.error.logs.push(concat([], arguments, 0)); }
+    };
+
+    /**
+     * @ngdoc method
+     * @name ngMock.$log#reset
+     * @methodOf ngMock.$log
+     *
+     * @description
+     * Reset all of the logging arrays to empty.
+     */
+    $log.reset = function () {
+      /**
+       * @ngdoc property
+       * @name ngMock.$log#log.logs
+       * @propertyOf ngMock.$log
+       *
+       * @description
+       * Array of logged messages.
+       */
+      $log.log.logs = [];
+      /**
+       * @ngdoc property
+       * @name ngMock.$log#warn.logs
+       * @propertyOf ngMock.$log
+       *
+       * @description
+       * Array of logged messages.
+       */
+      $log.warn.logs = [];
+      /**
+       * @ngdoc property
+       * @name ngMock.$log#info.logs
+       * @propertyOf ngMock.$log
+       *
+       * @description
+       * Array of logged messages.
+       */
+      $log.info.logs = [];
+      /**
+       * @ngdoc property
+       * @name ngMock.$log#error.logs
+       * @propertyOf ngMock.$log
+       *
+       * @description
+       * Array of logged messages.
+       */
+      $log.error.logs = [];
+    };
+
+    /**
+     * @ngdoc method
+     * @name ngMock.$log#assertEmpty
+     * @methodOf ngMock.$log
+     *
+     * @description
+     * Assert that the all of the logging methods have no logged messages. If messages present, an exception is thrown.
+     */
+    $log.assertEmpty = function() {
+      var errors = [];
+      angular.forEach(['error', 'warn', 'info', 'log'], function(logLevel) {
+        angular.forEach($log[logLevel].logs, function(log) {
+          angular.forEach(log, function (logItem) {
+            errors.push('MOCK $log (' + logLevel + '): ' + String(logItem) + '\n' + (logItem.stack || ''));
+          });
+        });
+      });
+      if (errors.length) {
+        errors.unshift("Expected $log to be empty! Either a message was logged unexpectedly, or an expected " +
+          "log message was not checked and removed:");
+        errors.push('');
+        throw new Error(errors.join('\n---------\n'));
+      }
+    };
+
+    $log.reset();
+    return $log;
+  };
+};
+
+
+(function() {
+  var R_ISO8061_STR = /^(\d{4})-?(\d\d)-?(\d\d)(?:T(\d\d)(?:\:?(\d\d)(?:\:?(\d\d)(?:\.(\d{3}))?)?)?(Z|([+-])(\d\d):?(\d\d)))?$/;
+
+  function jsonStringToDate(string){
+    var match;
+    if (match = string.match(R_ISO8061_STR)) {
+      var date = new Date(0),
+          tzHour = 0,
+          tzMin  = 0;
+      if (match[9]) {
+        tzHour = int(match[9] + match[10]);
+        tzMin = int(match[9] + match[11]);
+      }
+      date.setUTCFullYear(int(match[1]), int(match[2]) - 1, int(match[3]));
+      date.setUTCHours(int(match[4]||0) - tzHour, int(match[5]||0) - tzMin, int(match[6]||0), int(match[7]||0));
+      return date;
+    }
+    return string;
+  }
+
+  function int(str) {
+    return parseInt(str, 10);
+  }
+
+  function padNumber(num, digits, trim) {
+    var neg = '';
+    if (num < 0) {
+      neg =  '-';
+      num = -num;
+    }
+    num = '' + num;
+    while(num.length < digits) num = '0' + num;
+    if (trim)
+      num = num.substr(num.length - digits);
+    return neg + num;
+  }
+
+
+  /**
+   * @ngdoc object
+   * @name angular.mock.TzDate
+   * @description
+   *
+   * *NOTE*: this is not an injectable instance, just a globally available mock class of `Date`.
+   *
+   * Mock of the Date type which has its timezone specified via constroctor arg.
+   *
+   * The main purpose is to create Date-like instances with timezone fixed to the specified timezone
+   * offset, so that we can test code that depends on local timezone settings without dependency on
+   * the time zone settings of the machine where the code is running.
+   *
+   * @param {number} offset Offset of the *desired* timezone in hours (fractions will be honored)
+   * @param {(number|string)} timestamp Timestamp representing the desired time in *UTC*
+   *
+   * @example
+   * !!!! WARNING !!!!!
+   * This is not a complete Date object so only methods that were implemented can be called safely.
+   * To make matters worse, TzDate instances inherit stuff from Date via a prototype.
+   *
+   * We do our best to intercept calls to "unimplemented" methods, but since the list of methods is
+   * incomplete we might be missing some non-standard methods. This can result in errors like:
+   * "Date.prototype.foo called on incompatible Object".
+   *
+   * <pre>
+   * var newYearInBratislava = new TzDate(-1, '2009-12-31T23:00:00Z');
+   * newYearInBratislava.getTimezoneOffset() => -60;
+   * newYearInBratislava.getFullYear() => 2010;
+   * newYearInBratislava.getMonth() => 0;
+   * newYearInBratislava.getDate() => 1;
+   * newYearInBratislava.getHours() => 0;
+   * newYearInBratislava.getMinutes() => 0;
+   * </pre>
+   *
+   */
+  angular.mock.TzDate = function (offset, timestamp) {
+    var self = new Date(0);
+    if (angular.isString(timestamp)) {
+      var tsStr = timestamp;
+
+      self.origDate = jsonStringToDate(timestamp);
+
+      timestamp = self.origDate.getTime();
+      if (isNaN(timestamp))
+        throw {
+          name: "Illegal Argument",
+          message: "Arg '" + tsStr + "' passed into TzDate constructor is not a valid date string"
+        };
+    } else {
+      self.origDate = new Date(timestamp);
+    }
+
+    var localOffset = new Date(timestamp).getTimezoneOffset();
+    self.offsetDiff = localOffset*60*1000 - offset*1000*60*60;
+    self.date = new Date(timestamp + self.offsetDiff);
+
+    self.getTime = function() {
+      return self.date.getTime() - self.offsetDiff;
+    };
+
+    self.toLocaleDateString = function() {
+      return self.date.toLocaleDateString();
+    };
+
+    self.getFullYear = function() {
+      return self.date.getFullYear();
+    };
+
+    self.getMonth = function() {
+      return self.date.getMonth();
+    };
+
+    self.getDate = function() {
+      return self.date.getDate();
+    };
+
+    self.getHours = function() {
+      return self.date.getHours();
+    };
+
+    self.getMinutes = function() {
+      return self.date.getMinutes();
+    };
+
+    self.getSeconds = function() {
+      return self.date.getSeconds();
+    };
+
+    self.getTimezoneOffset = function() {
+      return offset * 60;
+    };
+
+    self.getUTCFullYear = function() {
+      return self.origDate.getUTCFullYear();
+    };
+
+    self.getUTCMonth = function() {
+      return self.origDate.getUTCMonth();
+    };
+
+    self.getUTCDate = function() {
+      return self.origDate.getUTCDate();
+    };
+
+    self.getUTCHours = function() {
+      return self.origDate.getUTCHours();
+    };
+
+    self.getUTCMinutes = function() {
+      return self.origDate.getUTCMinutes();
+    };
+
+    self.getUTCSeconds = function() {
+      return self.origDate.getUTCSeconds();
+    };
+
+    self.getUTCMilliseconds = function() {
+      return self.origDate.getUTCMilliseconds();
+    };
+
+    self.getDay = function() {
+      return self.date.getDay();
+    };
+
+    // provide this method only on browsers that already have it
+    if (self.toISOString) {
+      self.toISOString = function() {
+        return padNumber(self.origDate.getUTCFullYear(), 4) + '-' +
+              padNumber(self.origDate.getUTCMonth() + 1, 2) + '-' +
+              padNumber(self.origDate.getUTCDate(), 2) + 'T' +
+              padNumber(self.origDate.getUTCHours(), 2) + ':' +
+              padNumber(self.origDate.getUTCMinutes(), 2) + ':' +
+              padNumber(self.origDate.getUTCSeconds(), 2) + '.' +
+              padNumber(self.origDate.getUTCMilliseconds(), 3) + 'Z'
+      }
+    }
+
+    //hide all methods not implemented in this mock that the Date prototype exposes
+    var unimplementedMethods = ['getMilliseconds', 'getUTCDay',
+        'getYear', 'setDate', 'setFullYear', 'setHours', 'setMilliseconds',
+        'setMinutes', 'setMonth', 'setSeconds', 'setTime', 'setUTCDate', 'setUTCFullYear',
+        'setUTCHours', 'setUTCMilliseconds', 'setUTCMinutes', 'setUTCMonth', 'setUTCSeconds',
+        'setYear', 'toDateString', 'toGMTString', 'toJSON', 'toLocaleFormat', 'toLocaleString',
+        'toLocaleTimeString', 'toSource', 'toString', 'toTimeString', 'toUTCString', 'valueOf'];
+
+    angular.forEach(unimplementedMethods, function(methodName) {
+      self[methodName] = function() {
+        throw Error("Method '" + methodName + "' is not implemented in the TzDate mock");
+      };
+    });
+
+    return self;
+  };
+
+  //make "tzDateInstance instanceof Date" return true
+  angular.mock.TzDate.prototype = Date.prototype;
+})();
+
+
+/**
+ * @ngdoc function
+ * @name angular.mock.dump
+ * @description
+ *
+ * *NOTE*: this is not an injectable instance, just a globally available function.
+ *
+ * Method for serializing common angular objects (scope, elements, etc..) into strings, useful for debugging.
+ *
+ * This method is also available on window, where it can be used to display objects on debug console.
+ *
+ * @param {*} object - any object to turn into string.
+ * @return {string} a serialized string of the argument
+ */
+angular.mock.dump = function(object) {
+  return serialize(object);
+
+  function serialize(object) {
+    var out;
+
+    if (angular.isElement(object)) {
+      object = angular.element(object);
+      out = angular.element('<div></div>');
+      angular.forEach(object, function(element) {
+        out.append(angular.element(element).clone());
+      });
+      out = out.html();
+    } else if (angular.isArray(object)) {
+      out = [];
+      angular.forEach(object, function(o) {
+        out.push(serialize(o));
+      });
+      out = '[ ' + out.join(', ') + ' ]';
+    } else if (angular.isObject(object)) {
+      if (angular.isFunction(object.$eval) && angular.isFunction(object.$apply)) {
+        out = serializeScope(object);
+      } else if (object instanceof Error) {
+        out = object.stack || ('' + object.name + ': ' + object.message);
+      } else {
+        out = angular.toJson(object, true);
+      }
+    } else {
+      out = String(object);
+    }
+
+    return out;
+  }
+
+  function serializeScope(scope, offset) {
+    offset = offset ||  '  ';
+    var log = [offset + 'Scope(' + scope.$id + '): {'];
+    for ( var key in scope ) {
+      if (scope.hasOwnProperty(key) && !key.match(/^(\$|this)/)) {
+        log.push('  ' + key + ': ' + angular.toJson(scope[key]));
+      }
+    }
+    var child = scope.$$childHead;
+    while(child) {
+      log.push(serializeScope(child, offset + '  '));
+      child = child.$$nextSibling;
+    }
+    log.push('}');
+    return log.join('\n' + offset);
+  }
+};
+
+/**
+ * @ngdoc object
+ * @name ngMock.$httpBackend
+ * @description
+ * Fake HTTP backend implementation suitable for unit testing application that use the
+ * {@link ng.$http $http service}.
+ *
+ * *Note*: For fake http backend implementation suitable for end-to-end testing or backend-less
+ * development please see {@link ngMockE2E.$httpBackend e2e $httpBackend mock}.
+ *
+ * During unit testing, we want our unit tests to run quickly and have no external dependencies so
+ * we don’t want to send {@link https://developer.mozilla.org/en/xmlhttprequest XHR} or
+ * {@link http://en.wikipedia.org/wiki/JSONP JSONP} requests to a real server. All we really need is
+ * to verify whether a certain request has been sent or not, or alternatively just let the
+ * application make requests, respond with pre-trained responses and assert that the end result is
+ * what we expect it to be.
+ *
+ * This mock implementation can be used to respond with static or dynamic responses via the
+ * `expect` and `when` apis and their shortcuts (`expectGET`, `whenPOST`, etc).
+ *
+ * When an Angular application needs some data from a server, it calls the $http service, which
+ * sends the request to a real server using $httpBackend service. With dependency injection, it is
+ * easy to inject $httpBackend mock (which has the same API as $httpBackend) and use it to verify
+ * the requests and respond with some testing data without sending a request to real server.
+ *
+ * There are two ways to specify what test data should be returned as http responses by the mock
+ * backend when the code under test makes http requests:
+ *
+ * - `$httpBackend.expect` - specifies a request expectation
+ * - `$httpBackend.when` - specifies a backend definition
+ *
+ *
+ * # Request Expectations vs Backend Definitions
+ *
+ * Request expectations provide a way to make assertions about requests made by the application and
+ * to define responses for those requests. The test will fail if the expected requests are not made
+ * or they are made in the wrong order.
+ *
+ * Backend definitions allow you to define a fake backend for your application which doesn't assert
+ * if a particular request was made or not, it just returns a trained response if a request is made.
+ * The test will pass whether or not the request gets made during testing.
+ *
+ *
+ * <table class="table">
+ *   <tr><th width="220px"></th><th>Request expectations</th><th>Backend definitions</th></tr>
+ *   <tr>
+ *     <th>Syntax</th>
+ *     <td>.expect(...).respond(...)</td>
+ *     <td>.when(...).respond(...)</td>
+ *   </tr>
+ *   <tr>
+ *     <th>Typical usage</th>
+ *     <td>strict unit tests</td>
+ *     <td>loose (black-box) unit testing</td>
+ *   </tr>
+ *   <tr>
+ *     <th>Fulfills multiple requests</th>
+ *     <td>NO</td>
+ *     <td>YES</td>
+ *   </tr>
+ *   <tr>
+ *     <th>Order of requests matters</th>
+ *     <td>YES</td>
+ *     <td>NO</td>
+ *   </tr>
+ *   <tr>
+ *     <th>Request required</th>
+ *     <td>YES</td>
+ *     <td>NO</td>
+ *   </tr>
+ *   <tr>
+ *     <th>Response required</th>
+ *     <td>optional (see below)</td>
+ *     <td>YES</td>
+ *   </tr>
+ * </table>
+ *
+ * In cases where both backend definitions and request expectations are specified during unit
+ * testing, the request expectations are evaluated first.
+ *
+ * If a request expectation has no response specified, the algorithm will search your backend
+ * definitions for an appropriate response.
+ *
+ * If a request didn't match any expectation or if the expectation doesn't have the response
+ * defined, the backend definitions are evaluated in sequential order to see if any of them match
+ * the request. The response from the first matched definition is returned.
+ *
+ *
+ * # Flushing HTTP requests
+ *
+ * The $httpBackend used in production, always responds to requests with responses asynchronously.
+ * If we preserved this behavior in unit testing, we'd have to create async unit tests, which are
+ * hard to write, follow and maintain. At the same time the testing mock, can't respond
+ * synchronously because that would change the execution of the code under test. For this reason the
+ * mock $httpBackend has a `flush()` method, which allows the test to explicitly flush pending
+ * requests and thus preserving the async api of the backend, while allowing the test to execute
+ * synchronously.
+ *
+ *
+ * # Unit testing with mock $httpBackend
+ *
+ * <pre>
+   // controller
+   function MyController($scope, $http) {
+     $http.get('/auth.py').success(function(data) {
+       $scope.user = data;
+     });
+
+     this.saveMessage = function(message) {
+       $scope.status = 'Saving...';
+       $http.post('/add-msg.py', message).success(function(response) {
+         $scope.status = '';
+       }).error(function() {
+         $scope.status = 'ERROR!';
+       });
+     };
+   }
+
+   // testing controller
+   var $httpBackend;
+
+   beforeEach(inject(function($injector) {
+     $httpBackend = $injector.get('$httpBackend');
+
+     // backend definition common for all tests
+     $httpBackend.when('GET', '/auth.py').respond({userId: 'userX'}, {'A-Token': 'xxx'});
+   }));
+
+
+   afterEach(function() {
+     $httpBackend.verifyNoOutstandingExpectation();
+     $httpBackend.verifyNoOutstandingRequest();
+   });
+
+
+   it('should fetch authentication token', function() {
+     $httpBackend.expectGET('/auth.py');
+     var controller = scope.$new(MyController);
+     $httpBackend.flush();
+   });
+
+
+   it('should send msg to server', function() {
+     // now you don’t care about the authentication, but
+     // the controller will still send the request and
+     // $httpBackend will respond without you having to
+     // specify the expectation and response for this request
+     $httpBackend.expectPOST('/add-msg.py', 'message content').respond(201, '');
+
+     var controller = scope.$new(MyController);
+     $httpBackend.flush();
+     controller.saveMessage('message content');
+     expect(controller.status).toBe('Saving...');
+     $httpBackend.flush();
+     expect(controller.status).toBe('');
+   });
+
+
+   it('should send auth header', function() {
+     $httpBackend.expectPOST('/add-msg.py', undefined, function(headers) {
+       // check if the header was send, if it wasn't the expectation won't
+       // match the request and the test will fail
+       return headers['Authorization'] == 'xxx';
+     }).respond(201, '');
+
+     var controller = scope.$new(MyController);
+     controller.saveMessage('whatever');
+     $httpBackend.flush();
+   });
+   </pre>
+ */
+angular.mock.$HttpBackendProvider = function() {
+  this.$get = [createHttpBackendMock];
+};
+
+/**
+ * General factory function for $httpBackend mock.
+ * Returns instance for unit testing (when no arguments specified):
+ *   - passing through is disabled
+ *   - auto flushing is disabled
+ *
+ * Returns instance for e2e testing (when `$delegate` and `$browser` specified):
+ *   - passing through (delegating request to real backend) is enabled
+ *   - auto flushing is enabled
+ *
+ * @param {Object=} $delegate Real $httpBackend instance (allow passing through if specified)
+ * @param {Object=} $browser Auto-flushing enabled if specified
+ * @return {Object} Instance of $httpBackend mock
+ */
+function createHttpBackendMock($delegate, $browser) {
+  var definitions = [],
+      expectations = [],
+      responses = [],
+      responsesPush = angular.bind(responses, responses.push);
+
+  function createResponse(status, data, headers) {
+    if (angular.isFunction(status)) return status;
+
+    return function() {
+      return angular.isNumber(status)
+          ? [status, data, headers]
+          : [200, status, data];
+    };
+  }
+
+  // TODO(vojta): change params to: method, url, data, headers, callback
+  function $httpBackend(method, url, data, callback, headers) {
+    var xhr = new MockXhr(),
+        expectation = expectations[0],
+        wasExpected = false;
+
+    function prettyPrint(data) {
+      return (angular.isString(data) || angular.isFunction(data) || data instanceof RegExp)
+          ? data
+          : angular.toJson(data);
+    }
+
+    if (expectation && expectation.match(method, url)) {
+      if (!expectation.matchData(data))
+        throw Error('Expected ' + expectation + ' with different data\n' +
+            'EXPECTED: ' + prettyPrint(expectation.data) + '\nGOT:      ' + data);
+
+      if (!expectation.matchHeaders(headers))
+        throw Error('Expected ' + expectation + ' with different headers\n' +
+            'EXPECTED: ' + prettyPrint(expectation.headers) + '\nGOT:      ' +
+            prettyPrint(headers));
+
+      expectations.shift();
+
+      if (expectation.response) {
+        responses.push(function() {
+          var response = expectation.response(method, url, data, headers);
+          xhr.$$respHeaders = response[2];
+          callback(response[0], response[1], xhr.getAllResponseHeaders());
+        });
+        return;
+      }
+      wasExpected = true;
+    }
+
+    var i = -1, definition;
+    while ((definition = definitions[++i])) {
+      if (definition.match(method, url, data, headers || {})) {
+        if (definition.response) {
+          // if $browser specified, we do auto flush all requests
+          ($browser ? $browser.defer : responsesPush)(function() {
+            var response = definition.response(method, url, data, headers);
+            xhr.$$respHeaders = response[2];
+            callback(response[0], response[1], xhr.getAllResponseHeaders());
+          });
+        } else if (definition.passThrough) {
+          $delegate(method, url, data, callback, headers);
+        } else throw Error('No response defined !');
+        return;
+      }
+    }
+    throw wasExpected ?
+        Error('No response defined !') :
+        Error('Unexpected request: ' + method + ' ' + url + '\n' +
+              (expectation ? 'Expected ' + expectation : 'No more request expected'));
+  }
+
+  /**
+   * @ngdoc method
+   * @name ngMock.$httpBackend#when
+   * @methodOf ngMock.$httpBackend
+   * @description
+   * Creates a new backend definition.
+   *
+   * @param {string} method HTTP method.
+   * @param {string|RegExp} url HTTP url.
+   * @param {(string|RegExp)=} data HTTP request body.
+   * @param {(Object|function(Object))=} headers HTTP headers or function that receives http header
+   *   object and returns true if the headers match the current definition.
+   * @returns {requestHandler} Returns an object with `respond` method that control how a matched
+   *   request is handled.
+   *
+   *  - respond – `{function([status,] data[, headers])|function(function(method, url, data, headers)}`
+   *    – The respond method takes a set of static data to be returned or a function that can return
+   *    an array containing response status (number), response data (string) and response headers
+   *    (Object).
+   */
+  $httpBackend.when = function(method, url, data, headers) {
+    var definition = new MockHttpExpectation(method, url, data, headers),
+        chain = {
+          respond: function(status, data, headers) {
+            definition.response = createResponse(status, data, headers);
+          }
+        };
+
+    if ($browser) {
+      chain.passThrough = function() {
+        definition.passThrough = true;
+      };
+    }
+
+    definitions.push(definition);
+    return chain;
+  };
+
+  /**
+   * @ngdoc method
+   * @name ngMock.$httpBackend#whenGET
+   * @methodOf ngMock.$httpBackend
+   * @description
+   * Creates a new backend definition for GET requests. For more info see `when()`.
+   *
+   * @param {string|RegExp} url HTTP url.
+   * @param {(Object|function(Object))=} headers HTTP headers.
+   * @returns {requestHandler} Returns an object with `respond` method that control how a matched
+   * request is handled.
+   */
+
+  /**
+   * @ngdoc method
+   * @name ngMock.$httpBackend#whenHEAD
+   * @methodOf ngMock.$httpBackend
+   * @description
+   * Creates a new backend definition for HEAD requests. For more info see `when()`.
+   *
+   * @param {string|RegExp} url HTTP url.
+   * @param {(Object|function(Object))=} headers HTTP headers.
+   * @returns {requestHandler} Returns an object with `respond` method that control how a matched
+   * request is handled.
+   */
+
+  /**
+   * @ngdoc method
+   * @name ngMock.$httpBackend#whenDELETE
+   * @methodOf ngMock.$httpBackend
+   * @description
+   * Creates a new backend definition for DELETE requests. For more info see `when()`.
+   *
+   * @param {string|RegExp} url HTTP url.
+   * @param {(Object|function(Object))=} headers HTTP headers.
+   * @returns {requestHandler} Returns an object with `respond` method that control how a matched
+   * request is handled.
+   */
+
+  /**
+   * @ngdoc method
+   * @name ngMock.$httpBackend#whenPOST
+   * @methodOf ngMock.$httpBackend
+   * @description
+   * Creates a new backend definition for POST requests. For more info see `when()`.
+   *
+   * @param {string|RegExp} url HTTP url.
+   * @param {(string|RegExp)=} data HTTP request body.
+   * @param {(Object|function(Object))=} headers HTTP headers.
+   * @returns {requestHandler} Returns an object with `respond` method that control how a matched
+   * request is handled.
+   */
+
+  /**
+   * @ngdoc method
+   * @name ngMock.$httpBackend#whenPUT
+   * @methodOf ngMock.$httpBackend
+   * @description
+   * Creates a new backend definition for PUT requests.  For more info see `when()`.
+   *
+   * @param {string|RegExp} url HTTP url.
+   * @param {(string|RegExp)=} data HTTP request body.
+   * @param {(Object|function(Object))=} headers HTTP headers.
+   * @returns {requestHandler} Returns an object with `respond` method that control how a matched
+   * request is handled.
+   */
+
+  /**
+   * @ngdoc method
+   * @name ngMock.$httpBackend#whenJSONP
+   * @methodOf ngMock.$httpBackend
+   * @description
+   * Creates a new backend definition for JSONP requests. For more info see `when()`.
+   *
+   * @param {string|RegExp} url HTTP url.
+   * @returns {requestHandler} Returns an object with `respond` method that control how a matched
+   * request is handled.
+   */
+  createShortMethods('when');
+
+
+  /**
+   * @ngdoc method
+   * @name ngMock.$httpBackend#expect
+   * @methodOf ngMock.$httpBackend
+   * @description
+   * Creates a new request expectation.
+   *
+   * @param {string} method HTTP method.
+   * @param {string|RegExp} url HTTP url.
+   * @param {(string|RegExp)=} data HTTP request body.
+   * @param {(Object|function(Object))=} headers HTTP headers or function that receives http header
+   *   object and returns true if the headers match the current expectation.
+   * @returns {requestHandler} Returns an object with `respond` method that control how a matched
+   *  request is handled.
+   *
+   *  - respond – `{function([status,] data[, headers])|function(function(method, url, data, headers)}`
+   *    – The respond method takes a set of static data to be returned or a function that can return
+   *    an array containing response status (number), response data (string) and response headers
+   *    (Object).
+   */
+  $httpBackend.expect = function(method, url, data, headers) {
+    var expectation = new MockHttpExpectation(method, url, data, headers);
+    expectations.push(expectation);
+    return {
+      respond: function(status, data, headers) {
+        expectation.response = createResponse(status, data, headers);
+      }
+    };
+  };
+
+
+  /**
+   * @ngdoc method
+   * @name ngMock.$httpBackend#expectGET
+   * @methodOf ngMock.$httpBackend
+   * @description
+   * Creates a new request expectation for GET requests. For more info see `expect()`.
+   *
+   * @param {string|RegExp} url HTTP url.
+   * @param {Object=} headers HTTP headers.
+   * @returns {requestHandler} Returns an object with `respond` method that control how a matched
+   * request is handled. See #expect for more info.
+   */
+
+  /**
+   * @ngdoc method
+   * @name ngMock.$httpBackend#expectHEAD
+   * @methodOf ngMock.$httpBackend
+   * @description
+   * Creates a new request expectation for HEAD requests. For more info see `expect()`.
+   *
+   * @param {string|RegExp} url HTTP url.
+   * @param {Object=} headers HTTP headers.
+   * @returns {requestHandler} Returns an object with `respond` method that control how a matched
+   *   request is handled.
+   */
+
+  /**
+   * @ngdoc method
+   * @name ngMock.$httpBackend#expectDELETE
+   * @methodOf ngMock.$httpBackend
+   * @description
+   * Creates a new request expectation for DELETE requests. For more info see `expect()`.
+   *
+   * @param {string|RegExp} url HTTP url.
+   * @param {Object=} headers HTTP headers.
+   * @returns {requestHandler} Returns an object with `respond` method that control how a matched
+   *   request is handled.
+   */
+
+  /**
+   * @ngdoc method
+   * @name ngMock.$httpBackend#expectPOST
+   * @methodOf ngMock.$httpBackend
+   * @description
+   * Creates a new request expectation for POST requests. For more info see `expect()`.
+   *
+   * @param {string|RegExp} url HTTP url.
+   * @param {(string|RegExp)=} data HTTP request body.
+   * @param {Object=} headers HTTP headers.
+   * @returns {requestHandler} Returns an object with `respond` method that control how a matched
+   *   request is handled.
+   */
+
+  /**
+   * @ngdoc method
+   * @name ngMock.$httpBackend#expectPUT
+   * @methodOf ngMock.$httpBackend
+   * @description
+   * Creates a new request expectation for PUT requests. For more info see `expect()`.
+   *
+   * @param {string|RegExp} url HTTP url.
+   * @param {(string|RegExp)=} data HTTP request body.
+   * @param {Object=} headers HTTP headers.
+   * @returns {requestHandler} Returns an object with `respond` method that control how a matched
+   *   request is handled.
+   */
+
+  /**
+   * @ngdoc method
+   * @name ngMock.$httpBackend#expectPATCH
+   * @methodOf ngMock.$httpBackend
+   * @description
+   * Creates a new request expectation for PATCH requests. For more info see `expect()`.
+   *
+   * @param {string|RegExp} url HTTP url.
+   * @param {(string|RegExp)=} data HTTP request body.
+   * @param {Object=} headers HTTP headers.
+   * @returns {requestHandler} Returns an object with `respond` method that control how a matched
+   *   request is handled.
+   */
+
+  /**
+   * @ngdoc method
+   * @name ngMock.$httpBackend#expectJSONP
+   * @methodOf ngMock.$httpBackend
+   * @description
+   * Creates a new request expectation for JSONP requests. For more info see `expect()`.
+   *
+   * @param {string|RegExp} url HTTP url.
+   * @returns {requestHandler} Returns an object with `respond` method that control how a matched
+   *   request is handled.
+   */
+  createShortMethods('expect');
+
+
+  /**
+   * @ngdoc method
+   * @name ngMock.$httpBackend#flush
+   * @methodOf ngMock.$httpBackend
+   * @description
+   * Flushes all pending requests using the trained responses.
+   *
+   * @param {number=} count Number of responses to flush (in the order they arrived). If undefined,
+   *   all pending requests will be flushed. If there are no pending requests when the flush method
+   *   is called an exception is thrown (as this typically a sign of programming error).
+   */
+  $httpBackend.flush = function(count) {
+    if (!responses.length) throw Error('No pending request to flush !');
+
+    if (angular.isDefined(count)) {
+      while (count--) {
+        if (!responses.length) throw Error('No more pending request to flush !');
+        responses.shift()();
+      }
+    } else {
+      while (responses.length) {
+        responses.shift()();
+      }
+    }
+    $httpBackend.verifyNoOutstandingExpectation();
+  };
+
+
+  /**
+   * @ngdoc method
+   * @name ngMock.$httpBackend#verifyNoOutstandingExpectation
+   * @methodOf ngMock.$httpBackend
+   * @description
+   * Verifies that all of the requests defined via the `expect` api were made. If any of the
+   * requests were not made, verifyNoOutstandingExpectation throws an exception.
+   *
+   * Typically, you would call this method following each test case that asserts requests using an
+   * "afterEach" clause.
+   *
+   * <pre>
+   *   afterEach($httpBackend.verifyExpectations);
+   * </pre>
+   */
+  $httpBackend.verifyNoOutstandingExpectation = function() {
+    if (expectations.length) {
+      throw Error('Unsatisfied requests: ' + expectations.join(', '));
+    }
+  };
+
+
+  /**
+   * @ngdoc method
+   * @name ngMock.$httpBackend#verifyNoOutstandingRequest
+   * @methodOf ngMock.$httpBackend
+   * @description
+   * Verifies that there are no outstanding requests that need to be flushed.
+   *
+   * Typically, you would call this method following each test case that asserts requests using an
+   * "afterEach" clause.
+   *
+   * <pre>
+   *   afterEach($httpBackend.verifyNoOutstandingRequest);
+   * </pre>
+   */
+  $httpBackend.verifyNoOutstandingRequest = function() {
+    if (responses.length) {
+      throw Error('Unflushed requests: ' + responses.length);
+    }
+  };
+
+
+  /**
+   * @ngdoc method
+   * @name ngMock.$httpBackend#resetExpectations
+   * @methodOf ngMock.$httpBackend
+   * @description
+   * Resets all request expectations, but preserves all backend definitions. Typically, you would
+   * call resetExpectations during a multiple-phase test when you want to reuse the same instance of
+   * $httpBackend mock.
+   */
+  $httpBackend.resetExpectations = function() {
+    expectations.length = 0;
+    responses.length = 0;
+  };
+
+  return $httpBackend;
+
+
+  function createShortMethods(prefix) {
+    angular.forEach(['GET', 'DELETE', 'JSONP'], function(method) {
+     $httpBackend[prefix + method] = function(url, headers) {
+       return $httpBackend[prefix](method, url, undefined, headers)
+     }
+    });
+
+    angular.forEach(['PUT', 'POST', 'PATCH'], function(method) {
+      $httpBackend[prefix + method] = function(url, data, headers) {
+        return $httpBackend[prefix](method, url, data, headers)
+      }
+    });
+  }
+}
+
+function MockHttpExpectation(method, url, data, headers) {
+
+  this.data = data;
+  this.headers = headers;
+
+  this.match = function(m, u, d, h) {
+    if (method != m) return false;
+    if (!this.matchUrl(u)) return false;
+    if (angular.isDefined(d) && !this.matchData(d)) return false;
+    if (angular.isDefined(h) && !this.matchHeaders(h)) return false;
+    return true;
+  };
+
+  this.matchUrl = function(u) {
+    if (!url) return true;
+    if (angular.isFunction(url.test)) return url.test(u);
+    return url == u;
+  };
+
+  this.matchHeaders = function(h) {
+    if (angular.isUndefined(headers)) return true;
+    if (angular.isFunction(headers)) return headers(h);
+    return angular.equals(headers, h);
+  };
+
+  this.matchData = function(d) {
+    if (angular.isUndefined(data)) return true;
+    if (data && angular.isFunction(data.test)) return data.test(d);
+    if (data && !angular.isString(data)) return angular.toJson(data) == d;
+    return data == d;
+  };
+
+  this.toString = function() {
+    return method + ' ' + url;
+  };
+}
+
+function MockXhr() {
+
+  // hack for testing $http, $httpBackend
+  MockXhr.$$lastInstance = this;
+
+  this.open = function(method, url, async) {
+    this.$$method = method;
+    this.$$url = url;
+    this.$$async = async;
+    this.$$reqHeaders = {};
+    this.$$respHeaders = {};
+  };
+
+  this.send = function(data) {
+    this.$$data = data;
+  };
+
+  this.setRequestHeader = function(key, value) {
+    this.$$reqHeaders[key] = value;
+  };
+
+  this.getResponseHeader = function(name) {
+    // the lookup must be case insensitive, that's why we try two quick lookups and full scan at last
+    var header = this.$$respHeaders[name];
+    if (header) return header;
+
+    name = angular.lowercase(name);
+    header = this.$$respHeaders[name];
+    if (header) return header;
+
+    header = undefined;
+    angular.forEach(this.$$respHeaders, function(headerVal, headerName) {
+      if (!header && angular.lowercase(headerName) == name) header = headerVal;
+    });
+    return header;
+  };
+
+  this.getAllResponseHeaders = function() {
+    var lines = [];
+
+    angular.forEach(this.$$respHeaders, function(value, key) {
+      lines.push(key + ': ' + value);
+    });
+    return lines.join('\n');
+  };
+
+  this.abort = angular.noop;
+}
+
+
+/**
+ * @ngdoc function
+ * @name ngMock.$timeout
+ * @description
+ *
+ * This service is just a simple decorator for {@link ng.$timeout $timeout} service
+ * that adds a "flush" method.
+ */
+
+/**
+ * @ngdoc method
+ * @name ngMock.$timeout#flush
+ * @methodOf ngMock.$timeout
+ * @description
+ *
+ * Flushes the queue of pending tasks.
+ */
+
+/**
+ *
+ */
+angular.mock.$RootElementProvider = function() {
+  this.$get = function() {
+    return angular.element('<div ng-app></div>');
+  }
+};
+
+/**
+ * @ngdoc overview
+ * @name ngMock
+ * @description
+ *
+ * The `ngMock` is an angular module which is used with `ng` module and adds unit-test configuration as well as useful
+ * mocks to the {@link AUTO.$injector $injector}.
+ */
+angular.module('ngMock', ['ng']).provider({
+  $browser: angular.mock.$BrowserProvider,
+  $exceptionHandler: angular.mock.$ExceptionHandlerProvider,
+  $log: angular.mock.$LogProvider,
+  $httpBackend: angular.mock.$HttpBackendProvider,
+  $rootElement: angular.mock.$RootElementProvider
+}).config(function($provide) {
+  $provide.decorator('$timeout', function($delegate, $browser) {
+    $delegate.flush = function() {
+      $browser.defer.flush();
+    };
+    return $delegate;
+  });
+});
+
+
+/**
+ * @ngdoc overview
+ * @name ngMockE2E
+ * @description
+ *
+ * The `ngMockE2E` is an angular module which contains mocks suitable for end-to-end testing.
+ * Currently there is only one mock present in this module -
+ * the {@link ngMockE2E.$httpBackend e2e $httpBackend} mock.
+ */
+angular.module('ngMockE2E', ['ng']).config(function($provide) {
+  $provide.decorator('$httpBackend', angular.mock.e2e.$httpBackendDecorator);
+});
+
+/**
+ * @ngdoc object
+ * @name ngMockE2E.$httpBackend
+ * @description
+ * Fake HTTP backend implementation suitable for end-to-end testing or backend-less development of
+ * applications that use the {@link ng.$http $http service}.
+ *
+ * *Note*: For fake http backend implementation suitable for unit testing please see
+ * {@link ngMock.$httpBackend unit-testing $httpBackend mock}.
+ *
+ * This implementation can be used to respond with static or dynamic responses via the `when` api
+ * and its shortcuts (`whenGET`, `whenPOST`, etc) and optionally pass through requests to the
+ * real $httpBackend for specific requests (e.g. to interact with certain remote apis or to fetch
+ * templates from a webserver).
+ *
+ * As opposed to unit-testing, in an end-to-end testing scenario or in scenario when an application
+ * is being developed with the real backend api replaced with a mock, it is often desirable for
+ * certain category of requests to bypass the mock and issue a real http request (e.g. to fetch
+ * templates or static files from the webserver). To configure the backend with this behavior
+ * use the `passThrough` request handler of `when` instead of `respond`.
+ *
+ * Additionally, we don't want to manually have to flush mocked out requests like we do during unit
+ * testing. For this reason the e2e $httpBackend automatically flushes mocked out requests
+ * automatically, closely simulating the behavior of the XMLHttpRequest object.
+ *
+ * To setup the application to run with this http backend, you have to create a module that depends
+ * on the `ngMockE2E` and your application modules and defines the fake backend:
+ *
+ * <pre>
+ *   myAppDev = angular.module('myAppDev', ['myApp', 'ngMockE2E']);
+ *   myAppDev.run(function($httpBackend) {
+ *     phones = [{name: 'phone1'}, {name: 'phone2'}];
+ *
+ *     // returns the current list of phones
+ *     $httpBackend.whenGET('/phones').respond(phones);
+ *
+ *     // adds a new phone to the phones array
+ *     $httpBackend.whenPOST('/phones').respond(function(method, url, data) {
+ *       phones.push(angular.fromJSON(data));
+ *     });
+ *     $httpBackend.whenGET(/^\/templates\//).passThrough();
+ *     //...
+ *   });
+ * </pre>
+ *
+ * Afterwards, bootstrap your app with this new module.
+ */
+
+/**
+ * @ngdoc method
+ * @name ngMockE2E.$httpBackend#when
+ * @methodOf ngMockE2E.$httpBackend
+ * @description
+ * Creates a new backend definition.
+ *
+ * @param {string} method HTTP method.
+ * @param {string|RegExp} url HTTP url.
+ * @param {(string|RegExp)=} data HTTP request body.
+ * @param {(Object|function(Object))=} headers HTTP headers or function that receives http header
+ *   object and returns true if the headers match the current definition.
+ * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that
+ *   control how a matched request is handled.
+ *
+ *  - respond – `{function([status,] data[, headers])|function(function(method, url, data, headers)}`
+ *    – The respond method takes a set of static data to be returned or a function that can return
+ *    an array containing response status (number), response data (string) and response headers
+ *    (Object).
+ *  - passThrough – `{function()}` – Any request matching a backend definition with `passThrough`
+ *    handler, will be pass through to the real backend (an XHR request will be made to the
+ *    server.
+ */
+
+/**
+ * @ngdoc method
+ * @name ngMockE2E.$httpBackend#whenGET
+ * @methodOf ngMockE2E.$httpBackend
+ * @description
+ * Creates a new backend definition for GET requests. For more info see `when()`.
+ *
+ * @param {string|RegExp} url HTTP url.
+ * @param {(Object|function(Object))=} headers HTTP headers.
+ * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that
+ *   control how a matched request is handled.
+ */
+
+/**
+ * @ngdoc method
+ * @name ngMockE2E.$httpBackend#whenHEAD
+ * @methodOf ngMockE2E.$httpBackend
+ * @description
+ * Creates a new backend definition for HEAD requests. For more info see `when()`.
+ *
+ * @param {string|RegExp} url HTTP url.
+ * @param {(Object|function(Object))=} headers HTTP headers.
+ * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that
+ *   control how a matched request is handled.
+ */
+
+/**
+ * @ngdoc method
+ * @name ngMockE2E.$httpBackend#whenDELETE
+ * @methodOf ngMockE2E.$httpBackend
+ * @description
+ * Creates a new backend definition for DELETE requests. For more info see `when()`.
+ *
+ * @param {string|RegExp} url HTTP url.
+ * @param {(Object|function(Object))=} headers HTTP headers.
+ * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that
+ *   control how a matched request is handled.
+ */
+
+/**
+ * @ngdoc method
+ * @name ngMockE2E.$httpBackend#whenPOST
+ * @methodOf ngMockE2E.$httpBackend
+ * @description
+ * Creates a new backend definition for POST requests. For more info see `when()`.
+ *
+ * @param {string|RegExp} url HTTP url.
+ * @param {(string|RegExp)=} data HTTP request body.
+ * @param {(Object|function(Object))=} headers HTTP headers.
+ * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that
+ *   control how a matched request is handled.
+ */
+
+/**
+ * @ngdoc method
+ * @name ngMockE2E.$httpBackend#whenPUT
+ * @methodOf ngMockE2E.$httpBackend
+ * @description
+ * Creates a new backend definition for PUT requests.  For more info see `when()`.
+ *
+ * @param {string|RegExp} url HTTP url.
+ * @param {(string|RegExp)=} data HTTP request body.
+ * @param {(Object|function(Object))=} headers HTTP headers.
+ * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that
+ *   control how a matched request is handled.
+ */
+
+/**
+ * @ngdoc method
+ * @name ngMockE2E.$httpBackend#whenPATCH
+ * @methodOf ngMockE2E.$httpBackend
+ * @description
+ * Creates a new backend definition for PATCH requests.  For more info see `when()`.
+ *
+ * @param {string|RegExp} url HTTP url.
+ * @param {(string|RegExp)=} data HTTP request body.
+ * @param {(Object|function(Object))=} headers HTTP headers.
+ * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that
+ *   control how a matched request is handled.
+ */
+
+/**
+ * @ngdoc method
+ * @name ngMockE2E.$httpBackend#whenJSONP
+ * @methodOf ngMockE2E.$httpBackend
+ * @description
+ * Creates a new backend definition for JSONP requests. For more info see `when()`.
+ *
+ * @param {string|RegExp} url HTTP url.
+ * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that
+ *   control how a matched request is handled.
+ */
+angular.mock.e2e = {};
+angular.mock.e2e.$httpBackendDecorator = ['$delegate', '$browser', createHttpBackendMock];
+
+
+angular.mock.clearDataCache = function() {
+  var key,
+      cache = angular.element.cache;
+
+  for(key in cache) {
+    if (cache.hasOwnProperty(key)) {
+      var handle = cache[key].handle;
+
+      handle && angular.element(handle.elem).unbind();
+      delete cache[key];
+    }
+  }
+};
+
+
+window.jstestdriver && (function(window) {
+  /**
+   * Global method to output any number of objects into JSTD console. Useful for debugging.
+   */
+  window.dump = function() {
+    var args = [];
+    angular.forEach(arguments, function(arg) {
+      args.push(angular.mock.dump(arg));
+    });
+    jstestdriver.console.log.apply(jstestdriver.console, args);
+    if (window.console) {
+      window.console.log.apply(window.console, args);
+    }
+  };
+})(window);
+
+
+window.jasmine && (function(window) {
+
+  afterEach(function() {
+    var spec = getCurrentSpec();
+    var injector = spec.$injector;
+
+    spec.$injector = null;
+    spec.$modules = null;
+
+    if (injector) {
+      injector.get('$rootElement').unbind();
+      injector.get('$browser').pollFns.length = 0;
+    }
+
+    angular.mock.clearDataCache();
+
+    // clean up jquery's fragment cache
+    angular.forEach(angular.element.fragments, function(val, key) {
+      delete angular.element.fragments[key];
+    });
+
+    MockXhr.$$lastInstance = null;
+
+    angular.forEach(angular.callbacks, function(val, key) {
+      delete angular.callbacks[key];
+    });
+    angular.callbacks.counter = 0;
+  });
+
+  function getCurrentSpec() {
+    return jasmine.getEnv().currentSpec;
+  }
+
+  function isSpecRunning() {
+    var spec = getCurrentSpec();
+    return spec && spec.queue.running;
+  }
+
+  /**
+   * @ngdoc function
+   * @name angular.mock.module
+   * @description
+   *
+   * *NOTE*: This is function is also published on window for easy access.<br>
+   * *NOTE*: Only available with {@link http://pivotal.github.com/jasmine/ jasmine}.
+   *
+   * This function registers a module configuration code. It collects the configuration information
+   * which will be used when the injector is created by {@link angular.mock.inject inject}.
+   *
+   * See {@link angular.mock.inject inject} for usage example
+   *
+   * @param {...(string|Function)} fns any number of modules which are represented as string
+   *        aliases or as anonymous module initialization functions. The modules are used to
+   *        configure the injector. The 'ng' and 'ngMock' modules are automatically loaded.
+   */
+  window.module = angular.mock.module = function() {
+    var moduleFns = Array.prototype.slice.call(arguments, 0);
+    return isSpecRunning() ? workFn() : workFn;
+    /////////////////////
+    function workFn() {
+      var spec = getCurrentSpec();
+      if (spec.$injector) {
+        throw Error('Injector already created, can not register a module!');
+      } else {
+        var modules = spec.$modules || (spec.$modules = []);
+        angular.forEach(moduleFns, function(module) {
+          modules.push(module);
+        });
+      }
+    }
+  };
+
+  /**
+   * @ngdoc function
+   * @name angular.mock.inject
+   * @description
+   *
+   * *NOTE*: This is function is also published on window for easy access.<br>
+   * *NOTE*: Only available with {@link http://pivotal.github.com/jasmine/ jasmine}.
+   *
+   * The inject function wraps a function into an injectable function. The inject() creates new
+   * instance of {@link AUTO.$injector $injector} per test, which is then used for
+   * resolving references.
+   *
+   * See also {@link angular.mock.module module}
+   *
+   * Example of what a typical jasmine tests looks like with the inject method.
+   * <pre>
+   *
+   *   angular.module('myApplicationModule', [])
+   *       .value('mode', 'app')
+   *       .value('version', 'v1.0.1');
+   *
+   *
+   *   describe('MyApp', function() {
+   *
+   *     // You need to load modules that you want to test,
+   *     // it loads only the "ng" module by default.
+   *     beforeEach(module('myApplicationModule'));
+   *
+   *
+   *     // inject() is used to inject arguments of all given functions
+   *     it('should provide a version', inject(function(mode, version) {
+   *       expect(version).toEqual('v1.0.1');
+   *       expect(mode).toEqual('app');
+   *     }));
+   *
+   *
+   *     // The inject and module method can also be used inside of the it or beforeEach
+   *     it('should override a version and test the new version is injected', function() {
+   *       // module() takes functions or strings (module aliases)
+   *       module(function($provide) {
+   *         $provide.value('version', 'overridden'); // override version here
+   *       });
+   *
+   *       inject(function(version) {
+   *         expect(version).toEqual('overridden');
+   *       });
+   *     ));
+   *   });
+   *
+   * </pre>
+   *
+   * @param {...Function} fns any number of functions which will be injected using the injector.
+   */
+  window.inject = angular.mock.inject = function() {
+    var blockFns = Array.prototype.slice.call(arguments, 0);
+    var errorForStack = new Error('Declaration Location');
+    return isSpecRunning() ? workFn() : workFn;
+    /////////////////////
+    function workFn() {
+      var spec = getCurrentSpec();
+      var modules = spec.$modules || [];
+      modules.unshift('ngMock');
+      modules.unshift('ng');
+      var injector = spec.$injector;
+      if (!injector) {
+        injector = spec.$injector = angular.injector(modules);
+      }
+      for(var i = 0, ii = blockFns.length; i < ii; i++) {
+        try {
+          injector.invoke(blockFns[i] || angular.noop, this);
+        } catch (e) {
+          if(e.stack) e.stack +=  '\n' + errorForStack.stack;
+          throw e;
+        } finally {
+          errorForStack = null;
+        }
+      }
+    }
+  };
+})(window);


[50/51] [abbrv] [partial] Adding Jinwon's custom RCMET

Posted by jo...@apache.org.
http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/bin/.svn/text-base/rcmet.py.svn-base
----------------------------------------------------------------------
diff --git a/src/main/python/bin/.svn/text-base/rcmet.py.svn-base b/src/main/python/bin/.svn/text-base/rcmet.py.svn-base
new file mode 100755
index 0000000..588d583
--- /dev/null
+++ b/src/main/python/bin/.svn/text-base/rcmet.py.svn-base
@@ -0,0 +1,247 @@
+#!/usr/local/bin/python
+""" DOCSTRING"""
+
+# Python Standard Lib Imports
+import argparse
+import ConfigParser
+import datetime
+import glob
+import os
+import sys
+
+
+# RCMES Imports
+import storage.rcmed as db
+from toolkit import do_data_prep, process, metrics
+from utils import misc
+from classes import JobProperties, Model, GridBox
+from cli import rcmet_ui as ui
+
+parser = argparse.ArgumentParser(description='Regional Climate Model Evaluation Toolkit.  Use -h for help and options')
+parser.add_argument('-c', '--config', dest='CONFIG', help='Path to an evaluation configuration file')
+args = parser.parse_args()
+
+def checkConfigSettings(config):
+    """ This function will check the SETTINGS block of the user supplied config file.
+    This will only check if the working and cache dirs are writable from this program.
+    Additional configuration parameters can be checked here later on.
+    
+    Input::
+        config - ConfigParser configuration object
+    
+    Output::
+        none - An exception will be raised if something goes wrong
+    """
+    settings = config.items('SETTINGS')
+    for key_val in settings:
+        # Check the user provided directories are valid
+        if key_val[0] == 'workDir' or key_val[0] == 'cacheDir':
+            _ =  misc.isDirGood(os.path.abspath(key_val[1]))
+
+        else:
+            pass    
+
+def setSettings(settings, config):
+    """
+    This function is used to set the values within the 'SETTINGS' dictionary when a user provides an external
+    configuration file.
+    
+    Input::
+        settings - Python Dictionary object that will collect the key : value pairs
+        config - A configparse object that contains the external config values
+    
+    Output::
+        None - The settings dictionary will be updated in place.
+    """
+    pass
+
+def generateModels(modelConfig):
+    """
+    This function will return a list of Model objects that can easily be used for 
+    metric computation and other processing tasks.
+    
+    Input::  
+        modelConfig - list of ('key', 'value') tuples.  Below is a list of valid keys
+            filenamepattern - string i.e. '/nas/run/model/output/MOD*precip*.nc'
+            latvariable - string i.e. 'latitude'
+            lonvariable - string i.e. 'longitude'
+            timevariable - string i.e. 't'
+            timestep - string 'monthly' | 'daily' | 'annual'
+            varname - string i.e. 'pr'
+
+    Output::
+        modelList - List of Model objects
+    """
+    # Setup the config Data Dictionary to make parsing easier later
+    configData = {}
+    for entry in modelConfig:
+        configData[entry[0]] = entry[1]
+
+    modelFileList = None
+    for keyValTuple in modelConfig:
+        if keyValTuple[0] == 'filenamePattern':
+            modelFileList = glob.glob(keyValTuple[1])
+            modelFileList.sort()
+
+    # Remove the filenamePattern from the dict since it is no longer used
+    configData.pop('filenamePattern')
+    
+    models = []
+    for modelFile in modelFileList:
+        # use getModelTimes(modelFile,timeVarName) to generate the modelTimeStep and time list
+        _ , configData['timeStep'] = process.getModelTimes(modelFile, configData['timeVariable'])
+        configData['filename'] = modelFile
+        model = Model(**configData)
+        models.append(model)
+    
+    return models
+
+def generateSettings(config):
+    """
+    Helper function to decouple the argument parsing from the Settings object creation
+    
+    Input::  
+        config - list of ('key', 'value') tuples.
+            workdir - string i.e. '/nas/run/rcmet/work/'
+            cachedir - string i.e. '/tmp/rcmet/cache/'
+    Output::
+        JobProperties - JobProperties Object
+    """
+    # Setup the config Data Dictionary to make parsing easier later
+    configData = {}
+    for entry in config:
+        configData[entry[0]] = entry[1]
+        
+    return JobProperties(**configData)
+
+def makeDatasetsDictionary(rcmedConfig):
+    """
+    Helper function to decouple the argument parsing from the RCMEDDataset object creation
+
+    Input::  
+        rcmedConfig - list of ('key', 'value') tuples.
+            obsDatasetId=3,10
+            obsParamId=36,32
+            obsTimeStep=monthly,monthly
+
+    Output::
+        datasetDict - Dictionary with dataset metadata
+    # Setup the config Data Dictionary to make parsing easier later
+    """
+    delimiter = ','
+    configData = {}
+    for entry in rcmedConfig:
+        if delimiter in entry[1]:
+            # print 'delim found - %s' % entry[1]
+            valueList = entry[1].split(delimiter)
+            configData[entry[0]] = valueList
+        else:
+            configData[entry[0]] = entry[1:]
+
+    return configData
+
+def tempGetYears():
+    startYear = int(raw_input('Enter start year YYYY \n'))
+    endYear = int(raw_input('Enter end year YYYY \n'))
+    # CGOODALE - Updating the Static endTime to be 31-DEC
+    startTime = datetime.datetime(startYear, 1, 1, 0, 0)
+    endTime = datetime.datetime(endYear, 12, 31, 0, 0)
+    return (startTime, endTime)
+
+
+def runUsingConfig(argsConfig):
+    """
+    This function is called when a user provides a configuration file to specify an evaluation job.
+
+    Input::
+        argsConfig - Path to a ConfigParser compliant file
+
+    Output::
+        Plots that visualize the evaluation job. These will be output to SETTINGS.workDir from the config file
+    """
+    
+    print 'Running using config file: %s' % argsConfig
+    # Parse the Config file
+    userConfig = ConfigParser.SafeConfigParser()
+    userConfig.optionxform = str # This is so the case is preserved on the items in the config file
+    userConfig.read(argsConfig)
+
+    try:
+        checkConfigSettings(userConfig)
+    except:
+        raise
+
+    jobProperties = generateSettings(userConfig.items('SETTINGS'))
+    workdir = jobProperties.workDir
+    
+    try:
+        gridBox = GridBox(jobProperties.latMin, jobProperties.lonMin, jobProperties.latMax,
+                          jobProperties.lonMax, jobProperties.gridLonStep, jobProperties.gridLatStep)
+    except:
+        gridBox = None
+
+    models = generateModels(userConfig.items('MODEL'))
+    
+    datasetDict = makeDatasetsDictionary(userConfig.items('RCMED'))
+
+
+    # Go get the parameter listing from the database
+    try:
+        params = db.getParams()
+    except:
+        raise
+
+    obsDatasetList = []
+    for param_id in datasetDict['obsParamId']:
+        for param in params:
+            if param['parameter_id'] == int(param_id):
+                obsDatasetList.append(param)
+            else:
+                pass
+
+    #TODO: Unhardcode this when we decided where this belongs in the Config File
+    jobProperties.maskOption = True
+    # User must provide startTime and endTime if not defined
+    if jobProperties.startDate == None or jobProperties.endDate == None:
+        jobProperties.startDate, jobProperties.endDate = misc.userDefinedStartEndTimes(obsDatasetList, models)
+
+    numOBS, numMDL, nT, ngrdY, ngrdX, Times, lons, lats, obsData, mdlData, obsList, mdlName = do_data_prep.prep_data(jobProperties, obsDatasetList, gridBox, models)
+
+    print 'Input and regridding of both obs and model data are completed. now move to metrics calculations'
+    
+    try:
+        subRegionConfig = misc.configToDict(userConfig.items('SUB_REGION'))
+        subRegions = misc.parseSubRegions(subRegionConfig)
+        # REORDER SUBREGION OBJECTS until we standardize on Python 2.7
+        # TODO Remove once Python 2.7 support is finalized
+        if subRegions:
+            subRegions.sort(key=lambda x:x.name)
+        
+    except ConfigParser.NoSectionError:
+        
+        counts = {'observations': numOBS,
+                  'models'      : numMDL,
+                  'times'       : nT}
+        subRegions = misc.getSubRegionsInteractively(counts, workdir)
+        
+        if len(subRegions) == 0:
+            print 'Processing without SubRegion support'
+        
+
+    # TODO: New function Call
+    fileOutputOption = jobProperties.writeOutFile
+    modelVarName = models[0].varName
+    metrics.metrics_plots(modelVarName, numOBS, numMDL, nT, ngrdY, ngrdX, Times, lons, lats, obsData, mdlData, obsList, mdlName, workdir, subRegions, fileOutputOption)
+
+
+if __name__ == "__main__":
+    
+    if args.CONFIG:
+        
+        runUsingConfig(args.CONFIG)
+
+    else:
+        print 'Interactive mode has been enabled'
+        ui.rcmetUI()
+
+    #rcmet_cordexAF()

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/bin/rcmet.py
----------------------------------------------------------------------
diff --git a/src/main/python/bin/rcmet.py b/src/main/python/bin/rcmet.py
new file mode 100755
index 0000000..32e0167
--- /dev/null
+++ b/src/main/python/bin/rcmet.py
@@ -0,0 +1,305 @@
+#!/usr/local/python27
+""" DOCSTRING"""
+
+# Python Standard Lib Imports
+import argparse
+import ConfigParser
+import datetime
+import glob
+import os
+import sys
+import numpy as np
+import numpy.ma as ma
+
+
+# RCMES Imports
+import storage.rcmed as db
+from toolkit import do_data_prep, process, metrics
+from utils import misc
+from classes import JobProperties, Model, GridBox
+from cli import rcmet_ui as ui
+
+parser = argparse.ArgumentParser(description='Regional Climate Model Evaluation Toolkit.  Use -h for help and options')
+parser.add_argument('-c', '--config', dest='CONFIG', help='Path to an evaluation configuration file')
+args = parser.parse_args()
+
+def checkConfigSettings(config):
+    """ This function will check the SETTINGS block of the user supplied config file.
+    This will only check if the working and cache dirs are writable from this program.
+    Additional configuration parameters can be checked here later on.
+    
+    Input::
+        config - ConfigParser configuration object
+    
+    Output::
+        none - An exception will be raised if something goes wrong
+    """
+    settings = config.items('SETTINGS')
+    for key_val in settings:
+        # Check the user provided directories are valid
+        if key_val[0] == 'workDir' or key_val[0] == 'cacheDir':
+            _ =  misc.isDirGood(os.path.abspath(key_val[1]))
+
+        else:
+            pass    
+
+def setSettings(settings, config):
+    """
+    This function is used to set the values within the 'SETTINGS' dictionary when a user provides an external
+    configuration file.
+    
+    Input::
+        settings - Python Dictionary object that will collect the key : value pairs
+        config - A configparse object that contains the external config values
+    
+    Output::
+        None - The settings dictionary will be updated in place.
+    """
+    pass
+
+def generateModels(modelConfig):
+    """
+    This function will return a list of Model objects that can easily be used for 
+    metric computation and other processing tasks.
+    
+    Input::  
+        modelConfig - list of ('key', 'value') tuples.  Below is a list of valid keys
+            filenamepattern - string i.e. '/nas/run/model/output/MOD*precip*.nc'
+            latvariable - string i.e. 'latitude'
+            lonvariable - string i.e. 'longitude'
+            timevariable - string i.e. 't'
+            timestep - string 'monthly' | 'daily' | 'annual'
+            varname - string i.e. 'pr'
+
+    Output::
+        modelList - List of Model objects
+    """
+    # Setup the config Data Dictionary to make parsing easier later
+    configData = {}
+    for entry in modelConfig:
+        configData[entry[0]] = entry[1]
+
+    modelFileList = None
+    for keyValTuple in modelConfig:
+        if keyValTuple[0] == 'filenamePattern':
+            modelFileList = glob.glob(keyValTuple[1])
+            modelFileList.sort()
+
+    # Remove the filenamePattern from the dict since it is no longer used
+    configData.pop('filenamePattern')
+    
+    models = []
+    for modelFile in modelFileList:
+        # use getModelTimes(modelFile,timeVarName) to generate the modelTimeStep and time list
+        _ , configData['timeStep'] = process.getModelTimes(modelFile, configData['timeVariable'])
+        configData['filename'] = modelFile
+        model = Model(**configData)
+        models.append(model)
+    
+    return models
+
+def generateSettings(config):
+    """
+    Helper function to decouple the argument parsing from the Settings object creation
+    
+    Input::  
+        config - list of ('key', 'value') tuples.
+            workdir - string i.e. '/nas/run/rcmet/work/'
+            cachedir - string i.e. '/tmp/rcmet/cache/'
+    Output::
+        JobProperties - JobProperties Object
+    """
+    # Setup the config Data Dictionary to make parsing easier later
+    configData = {}
+    for entry in config:
+        configData[entry[0]] = entry[1]
+        
+    return JobProperties(**configData)
+
+def makeDatasetsDictionary(rcmedConfig):
+    """
+    Helper function to decouple the argument parsing from the RCMEDDataset object creation
+
+    Input::  
+        rcmedConfig - list of ('key', 'value') tuples.
+            obsDatasetId=3,10
+            obsParamId=36,32
+            obsTimeStep=monthly,monthly
+
+    Output::
+        datasetDict - Dictionary with dataset metadata
+    # Setup the config Data Dictionary to make parsing easier later
+    """
+    delimiter = ','
+    configData = {}
+    for entry in rcmedConfig:
+        if delimiter in entry[1]:
+            # print 'delim found - %s' % entry[1]
+            valueList = entry[1].split(delimiter)
+            configData[entry[0]] = valueList
+        else:
+            configData[entry[0]] = entry[1:]
+
+    return configData
+
+def tempGetYears():
+    startYear = int(raw_input('Enter start year YYYY \n'))
+    endYear = int(raw_input('Enter end year YYYY \n'))
+    # CGOODALE - Updating the Static endTime to be 31-DEC
+    startTime = datetime.datetime(startYear, 1, 1, 0, 0)
+    endTime = datetime.datetime(endYear, 12, 31, 0, 0)
+    return (startTime, endTime)
+
+
+def runUsingConfig(argsConfig):
+    """
+    This function is called when a user provides a configuration file to specify an evaluation job.
+
+    Input::
+        argsConfig - Path to a ConfigParser compliant file
+
+    Output::
+        Plots that visualize the evaluation job. These will be output to SETTINGS.workDir from the config file
+    """
+    
+    print 'Running using config file: %s' % argsConfig
+    # Parse the Config file
+    userConfig = ConfigParser.SafeConfigParser()
+    userConfig.optionxform = str # This is so the case is preserved on the items in the config file
+    userConfig.read(argsConfig)
+
+    try:
+        checkConfigSettings(userConfig)
+    except:
+        raise
+
+    jobProperties = generateSettings(userConfig.items('SETTINGS'))
+    workdir = jobProperties.workDir
+    
+    try:
+        gridBox = GridBox(jobProperties.latMin, jobProperties.lonMin, jobProperties.latMax,
+                          jobProperties.lonMax, jobProperties.gridLonStep, jobProperties.gridLatStep)
+    except:
+        gridBox = None
+
+    models = generateModels(userConfig.items('MODEL'))
+    
+    # 5/28/2013, JK: The RCMED block has been modified to accommodate ref data input from users' local disk
+
+    datasetDict = makeDatasetsDictionary(userConfig.items('RCMED'))
+
+
+    # Go get the parameter listing from the database
+    try:
+        params = db.getParams()
+    except:
+        raise
+
+    obsDatasetList = []
+    obsList = []
+    obsVarName = datasetDict['obsVarName'][0]
+    obsTimeName = datasetDict['obsTimeVar'][0]
+    obsLonName = datasetDict['obsLonVar'][0]
+    obsLatName = datasetDict['obsLatVar'][0]
+    obsTimestep = []
+    obsSource = int(datasetDict['obsSource'][0])
+    #print 'Obs datasetDict'
+    #print datasetDict
+
+    if obsSource < 0:                             # no obs data to be processed
+        obsVarName = []
+        obsTimeName = []
+        obsLonName = []
+        obsLatName = []
+    elif obsSource == 0:                          # input from RCMED
+        for param_id in datasetDict['obsParamId']:
+            for param in params:
+                if param['parameter_id'] == int(param_id):
+                    obsDatasetList.append(param)
+                else:
+                    pass
+    elif obsSource == 1:                        # input from local disk
+        for param in datasetDict['obsInputFile']:
+            obsDatasetList.append(param)
+        for param in datasetDict['obsFileName']:
+            obsList.append(param)
+        for param in datasetDict['obsDltaTime']:
+            obsTimestep.append(param)
+    #print obsSource,obsDatasetList,obsList,obsTimeName,obsTimestep
+
+    #TODO: Unhardcode this when we decided where this belongs in the Config File
+    jobProperties.maskOption = True
+    # User must provide startTime and endTime if not defined
+    if jobProperties.startDate == None or jobProperties.endDate == None:
+        jobProperties.startDate,jobProperties.endDate = misc.userDefinedStartEndTimes(obsSource,obsList,obsTimeName,obsDatasetList,models)
+
+    numOBS,numMDL,nT,ngrdY,ngrdX,Times,lons,lats,obsData,mdlData,obsName,mdlName = do_data_prep.prep_data   \
+          (jobProperties,obsSource,obsDatasetList,obsList,obsVarName,obsLonName,obsLatName,obsTimeName,obsTimestep,gridBox,models)
+
+    # 6/3/2013: Combine the regridded reference and model datasets. The packing order is: 
+    #               First pack all ref (obs) data with the ref enseble in the end (if exists).
+    #               Then pack all model data with the model ensemble in the end (if exists)
+    #           Release 'obsData' and 'mdlData' after their values are transferred to 'allData'
+    print 'Input and regridding of both obs and model data are completed. Combine the obs and model data'
+    numDatasets = numOBS + numMDL
+    allData = ma.zeros((numDatasets, nT, ngrdY, ngrdX))
+    if (numOBS>0) & (numMDL>0):
+        dataName = obsName + mdlName
+        allData[0:numOBS, :, :, :] = obsData[0:numOBS, :, :, :]
+        allData[numOBS:numDatasets, :, :, :] = mdlData[0:numMDL, :, :, :]
+        obsData = 0.
+        mdlData = 0.
+    elif numOBS==0:
+        dataName = mdlName
+        allData = mdlData
+        mdlData = 0.
+    else:
+        dataName = obsName
+        allData = obsData
+        obsData = 0
+    print ''
+    print 'dataName: ',dataName,' shape of all data= ',allData.shape
+
+    ##################################################################################
+    # calculate metrics and make plots using the regridded reference and model data. #
+    ##################################################################################
+    print 'Data preparation is completed; now move to metrics calculations'
+    
+    try:
+        subRegionConfig = misc.configToDict(userConfig.items('SUB_REGION'))
+        subRegions = misc.parseSubRegions(subRegionConfig)
+        # REORDER SUBREGION OBJECTS until we standardize on Python 2.7
+        # TODO Remove once Python 2.7 support is finalized
+        if subRegions:
+            subRegions.sort(key=lambda x:x.name)
+        
+    except ConfigParser.NoSectionError:
+        
+        counts = {'observations': numOBS,
+                  'models'      : numMDL,
+                  'times'       : nT}
+        subRegions = misc.getSubRegionsInteractively(counts, workdir)
+        
+        if len(subRegions) == 0:
+            print 'Processing without SubRegion support'
+        
+
+    # TODO: New function Call
+    timeRegridOption = jobProperties.temporalGrid
+    fileOutputOption = jobProperties.writeOutFile
+    modelVarName = models[0].varName
+    metrics.metrics_plots(modelVarName, numOBS, numMDL, nT, ngrdY, ngrdX, Times, lons, lats, allData, dataName, workdir, subRegions, \
+                          timeRegridOption, fileOutputOption)
+
+
+if __name__ == "__main__":
+    
+    if args.CONFIG:
+        
+        runUsingConfig(args.CONFIG)
+
+    else:
+        print 'Interactive mode has been enabled'
+        ui.rcmetUI()
+
+    #rcmet_cordexAF()

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/docs/.svn/all-wcprops
----------------------------------------------------------------------
diff --git a/src/main/python/docs/.svn/all-wcprops b/src/main/python/docs/.svn/all-wcprops
new file mode 100755
index 0000000..0d9e7b3
--- /dev/null
+++ b/src/main/python/docs/.svn/all-wcprops
@@ -0,0 +1,77 @@
+K 25
+svn:wc:ra_dav:version-url
+V 78
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/python/docs
+END
+RCMET_documentation.docx
+K 25
+svn:wc:ra_dav:version-url
+V 103
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/python/docs/RCMET_documentation.docx
+END
+rcmes.utils.rst
+K 25
+svn:wc:ra_dav:version-url
+V 94
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/python/docs/rcmes.utils.rst
+END
+rcmes.rst
+K 25
+svn:wc:ra_dav:version-url
+V 88
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/python/docs/rcmes.rst
+END
+make.bat
+K 25
+svn:wc:ra_dav:version-url
+V 87
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/python/docs/make.bat
+END
+rcmes.services.rst
+K 25
+svn:wc:ra_dav:version-url
+V 97
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/python/docs/rcmes.services.rst
+END
+rcmes.storage.rst
+K 25
+svn:wc:ra_dav:version-url
+V 96
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/python/docs/rcmes.storage.rst
+END
+rcmes.toolkit.rst
+K 25
+svn:wc:ra_dav:version-url
+V 96
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/python/docs/rcmes.toolkit.rst
+END
+rcmes.cli.rst
+K 25
+svn:wc:ra_dav:version-url
+V 92
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/python/docs/rcmes.cli.rst
+END
+conf.py
+K 25
+svn:wc:ra_dav:version-url
+V 86
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/python/docs/conf.py
+END
+Makefile
+K 25
+svn:wc:ra_dav:version-url
+V 87
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/python/docs/Makefile
+END
+Bottle Web Service Documentation.docx
+K 25
+svn:wc:ra_dav:version-url
+V 122
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/python/docs/Bottle%20Web%20Service%20Documentation.docx
+END
+index.rst
+K 25
+svn:wc:ra_dav:version-url
+V 88
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/python/docs/index.rst
+END

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/docs/.svn/dir-prop-base
----------------------------------------------------------------------
diff --git a/src/main/python/docs/.svn/dir-prop-base b/src/main/python/docs/.svn/dir-prop-base
new file mode 100755
index 0000000..f2190f3
--- /dev/null
+++ b/src/main/python/docs/.svn/dir-prop-base
@@ -0,0 +1,6 @@
+K 10
+svn:ignore
+V 7
+_build
+
+END

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/docs/.svn/entries
----------------------------------------------------------------------
diff --git a/src/main/python/docs/.svn/entries b/src/main/python/docs/.svn/entries
new file mode 100755
index 0000000..9055335
--- /dev/null
+++ b/src/main/python/docs/.svn/entries
@@ -0,0 +1,442 @@
+10
+
+dir
+1485921
+https://svn.apache.org/repos/asf/incubator/climate/trunk/rcmet/src/main/python/docs
+https://svn.apache.org/repos/asf
+
+
+
+2012-08-21T16:37:01.209194Z
+1473912
+cgoodale
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+13f79535-47bb-0310-9956-ffa450edef68
+
+RCMET_documentation.docx
+file
+
+
+
+
+2013-05-24T10:13:48.000000Z
+503f1d675c951321de9cc2daaaa0d5dc
+2012-08-14T20:53:09.633133Z
+1473862
+pramirez
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+190254
+
+rcmes.utils.rst
+file
+
+
+
+
+2013-05-24T10:13:48.000000Z
+4143b6ca0b9519480c7537624ccca03d
+2012-08-14T21:47:34.802218Z
+1473865
+pramirez
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+310
+
+rcmes.rst
+file
+
+
+
+
+2013-05-24T10:13:48.000000Z
+6bdc8133e6099f6688633a7a7393da66
+2012-08-14T21:47:34.802218Z
+1473865
+pramirez
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+286
+
+make.bat
+file
+
+
+
+
+2013-05-24T10:13:48.000000Z
+450481b40c1254f2859f97bb5bb4ab9f
+2012-08-14T21:47:34.802218Z
+1473865
+pramirez
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+5094
+
+rcmes.services.rst
+file
+
+
+
+
+2013-05-24T10:13:48.000000Z
+d0fb7e23806d46105c34877fd5548c13
+2012-08-14T21:47:34.802218Z
+1473865
+pramirez
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+1031
+
+rcmes.storage.rst
+file
+
+
+
+
+2013-05-24T10:13:48.000000Z
+0272a00e93d6bb0de865712afbb594ea
+2012-08-14T21:47:34.802218Z
+1473865
+pramirez
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+429
+
+rcmes.toolkit.rst
+file
+
+
+
+
+2013-05-24T10:13:48.000000Z
+b13d0d9fb964d4d3edce538199ca77fd
+2012-08-14T21:47:34.802218Z
+1473865
+pramirez
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+450
+
+_static
+dir
+
+rcmes.cli.rst
+file
+
+
+
+
+2013-05-24T10:13:48.000000Z
+1bdd186d89222ef2ad78d598765fda46
+2012-08-14T21:47:34.802218Z
+1473865
+pramirez
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+350
+
+conf.py
+file
+
+
+
+
+2013-05-24T10:13:48.000000Z
+8cfd82994c7b0be05b39cf890c41d993
+2012-08-14T21:47:34.802218Z
+1473865
+pramirez
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+8295
+
+_templates
+dir
+
+Makefile
+file
+
+
+
+
+2013-05-24T10:13:48.000000Z
+0b19f3cfe7f48422ea0e79ccef9eba27
+2012-08-14T21:47:34.802218Z
+1473865
+pramirez
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+5560
+
+Bottle Web Service Documentation.docx
+file
+
+
+
+
+2013-05-24T10:13:48.000000Z
+9151bd470e9e51f4948f1225e39070d3
+2012-08-16T17:18:33.692401Z
+1473889
+mattmann
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+179630
+
+index.rst
+file
+
+
+
+
+2013-05-24T10:13:48.000000Z
+eaec512a1e2dd049aef883bbf373d37d
+2012-08-14T21:47:34.802218Z
+1473865
+pramirez
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+420
+

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/docs/.svn/prop-base/Bottle Web Service Documentation.docx.svn-base
----------------------------------------------------------------------
diff --git a/src/main/python/docs/.svn/prop-base/Bottle Web Service Documentation.docx.svn-base b/src/main/python/docs/.svn/prop-base/Bottle Web Service Documentation.docx.svn-base
new file mode 100755
index 0000000..5e9587e
--- /dev/null
+++ b/src/main/python/docs/.svn/prop-base/Bottle Web Service Documentation.docx.svn-base	
@@ -0,0 +1,5 @@
+K 13
+svn:mime-type
+V 24
+application/octet-stream
+END

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/docs/.svn/prop-base/RCMET_documentation.docx.svn-base
----------------------------------------------------------------------
diff --git a/src/main/python/docs/.svn/prop-base/RCMET_documentation.docx.svn-base b/src/main/python/docs/.svn/prop-base/RCMET_documentation.docx.svn-base
new file mode 100755
index 0000000..5e9587e
--- /dev/null
+++ b/src/main/python/docs/.svn/prop-base/RCMET_documentation.docx.svn-base
@@ -0,0 +1,5 @@
+K 13
+svn:mime-type
+V 24
+application/octet-stream
+END

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/docs/.svn/prop-base/conf.py.svn-base
----------------------------------------------------------------------
diff --git a/src/main/python/docs/.svn/prop-base/conf.py.svn-base b/src/main/python/docs/.svn/prop-base/conf.py.svn-base
new file mode 100755
index 0000000..614166f
--- /dev/null
+++ b/src/main/python/docs/.svn/prop-base/conf.py.svn-base
@@ -0,0 +1,5 @@
+K 12
+svn:keywords
+V 11
+Id Revision
+END

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/docs/.svn/prop-base/index.rst.svn-base
----------------------------------------------------------------------
diff --git a/src/main/python/docs/.svn/prop-base/index.rst.svn-base b/src/main/python/docs/.svn/prop-base/index.rst.svn-base
new file mode 100755
index 0000000..614166f
--- /dev/null
+++ b/src/main/python/docs/.svn/prop-base/index.rst.svn-base
@@ -0,0 +1,5 @@
+K 12
+svn:keywords
+V 11
+Id Revision
+END

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/docs/.svn/prop-base/make.bat.svn-base
----------------------------------------------------------------------
diff --git a/src/main/python/docs/.svn/prop-base/make.bat.svn-base b/src/main/python/docs/.svn/prop-base/make.bat.svn-base
new file mode 100755
index 0000000..614166f
--- /dev/null
+++ b/src/main/python/docs/.svn/prop-base/make.bat.svn-base
@@ -0,0 +1,5 @@
+K 12
+svn:keywords
+V 11
+Id Revision
+END

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/docs/.svn/prop-base/rcmes.cli.rst.svn-base
----------------------------------------------------------------------
diff --git a/src/main/python/docs/.svn/prop-base/rcmes.cli.rst.svn-base b/src/main/python/docs/.svn/prop-base/rcmes.cli.rst.svn-base
new file mode 100755
index 0000000..614166f
--- /dev/null
+++ b/src/main/python/docs/.svn/prop-base/rcmes.cli.rst.svn-base
@@ -0,0 +1,5 @@
+K 12
+svn:keywords
+V 11
+Id Revision
+END

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/docs/.svn/prop-base/rcmes.rst.svn-base
----------------------------------------------------------------------
diff --git a/src/main/python/docs/.svn/prop-base/rcmes.rst.svn-base b/src/main/python/docs/.svn/prop-base/rcmes.rst.svn-base
new file mode 100755
index 0000000..614166f
--- /dev/null
+++ b/src/main/python/docs/.svn/prop-base/rcmes.rst.svn-base
@@ -0,0 +1,5 @@
+K 12
+svn:keywords
+V 11
+Id Revision
+END

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/docs/.svn/prop-base/rcmes.services.rst.svn-base
----------------------------------------------------------------------
diff --git a/src/main/python/docs/.svn/prop-base/rcmes.services.rst.svn-base b/src/main/python/docs/.svn/prop-base/rcmes.services.rst.svn-base
new file mode 100755
index 0000000..614166f
--- /dev/null
+++ b/src/main/python/docs/.svn/prop-base/rcmes.services.rst.svn-base
@@ -0,0 +1,5 @@
+K 12
+svn:keywords
+V 11
+Id Revision
+END

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/docs/.svn/prop-base/rcmes.storage.rst.svn-base
----------------------------------------------------------------------
diff --git a/src/main/python/docs/.svn/prop-base/rcmes.storage.rst.svn-base b/src/main/python/docs/.svn/prop-base/rcmes.storage.rst.svn-base
new file mode 100755
index 0000000..614166f
--- /dev/null
+++ b/src/main/python/docs/.svn/prop-base/rcmes.storage.rst.svn-base
@@ -0,0 +1,5 @@
+K 12
+svn:keywords
+V 11
+Id Revision
+END

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/docs/.svn/prop-base/rcmes.toolkit.rst.svn-base
----------------------------------------------------------------------
diff --git a/src/main/python/docs/.svn/prop-base/rcmes.toolkit.rst.svn-base b/src/main/python/docs/.svn/prop-base/rcmes.toolkit.rst.svn-base
new file mode 100755
index 0000000..614166f
--- /dev/null
+++ b/src/main/python/docs/.svn/prop-base/rcmes.toolkit.rst.svn-base
@@ -0,0 +1,5 @@
+K 12
+svn:keywords
+V 11
+Id Revision
+END

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/docs/.svn/prop-base/rcmes.utils.rst.svn-base
----------------------------------------------------------------------
diff --git a/src/main/python/docs/.svn/prop-base/rcmes.utils.rst.svn-base b/src/main/python/docs/.svn/prop-base/rcmes.utils.rst.svn-base
new file mode 100755
index 0000000..614166f
--- /dev/null
+++ b/src/main/python/docs/.svn/prop-base/rcmes.utils.rst.svn-base
@@ -0,0 +1,5 @@
+K 12
+svn:keywords
+V 11
+Id Revision
+END

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/docs/.svn/text-base/Bottle Web Service Documentation.docx.svn-base
----------------------------------------------------------------------
diff --git a/src/main/python/docs/.svn/text-base/Bottle Web Service Documentation.docx.svn-base b/src/main/python/docs/.svn/text-base/Bottle Web Service Documentation.docx.svn-base
new file mode 100755
index 0000000..a6fdd6f
Binary files /dev/null and b/src/main/python/docs/.svn/text-base/Bottle Web Service Documentation.docx.svn-base differ

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/docs/.svn/text-base/Makefile.svn-base
----------------------------------------------------------------------
diff --git a/src/main/python/docs/.svn/text-base/Makefile.svn-base b/src/main/python/docs/.svn/text-base/Makefile.svn-base
new file mode 100755
index 0000000..9cf4b97
--- /dev/null
+++ b/src/main/python/docs/.svn/text-base/Makefile.svn-base
@@ -0,0 +1,153 @@
+# Makefile for Sphinx documentation
+#
+
+# You can set these variables from the command line.
+SPHINXOPTS    =
+SPHINXBUILD   = sphinx-build
+PAPER         =
+BUILDDIR      = _build
+
+# Internal variables.
+PAPEROPT_a4     = -D latex_paper_size=a4
+PAPEROPT_letter = -D latex_paper_size=letter
+ALLSPHINXOPTS   = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
+# the i18n builder cannot share the environment and doctrees with the others
+I18NSPHINXOPTS  = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
+
+.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext
+
+help:
+	@echo "Please use \`make <target>' where <target> is one of"
+	@echo "  html       to make standalone HTML files"
+	@echo "  dirhtml    to make HTML files named index.html in directories"
+	@echo "  singlehtml to make a single large HTML file"
+	@echo "  pickle     to make pickle files"
+	@echo "  json       to make JSON files"
+	@echo "  htmlhelp   to make HTML files and a HTML help project"
+	@echo "  qthelp     to make HTML files and a qthelp project"
+	@echo "  devhelp    to make HTML files and a Devhelp project"
+	@echo "  epub       to make an epub"
+	@echo "  latex      to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
+	@echo "  latexpdf   to make LaTeX files and run them through pdflatex"
+	@echo "  text       to make text files"
+	@echo "  man        to make manual pages"
+	@echo "  texinfo    to make Texinfo files"
+	@echo "  info       to make Texinfo files and run them through makeinfo"
+	@echo "  gettext    to make PO message catalogs"
+	@echo "  changes    to make an overview of all changed/added/deprecated items"
+	@echo "  linkcheck  to check all external links for integrity"
+	@echo "  doctest    to run all doctests embedded in the documentation (if enabled)"
+
+clean:
+	-rm -rf $(BUILDDIR)/*
+
+html:
+	$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
+	@echo
+	@echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
+
+dirhtml:
+	$(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
+	@echo
+	@echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
+
+singlehtml:
+	$(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
+	@echo
+	@echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
+
+pickle:
+	$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
+	@echo
+	@echo "Build finished; now you can process the pickle files."
+
+json:
+	$(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
+	@echo
+	@echo "Build finished; now you can process the JSON files."
+
+htmlhelp:
+	$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
+	@echo
+	@echo "Build finished; now you can run HTML Help Workshop with the" \
+	      ".hhp project file in $(BUILDDIR)/htmlhelp."
+
+qthelp:
+	$(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
+	@echo
+	@echo "Build finished; now you can run "qcollectiongenerator" with the" \
+	      ".qhcp project file in $(BUILDDIR)/qthelp, like this:"
+	@echo "# qcollectiongenerator $(BUILDDIR)/qthelp/rcmes.qhcp"
+	@echo "To view the help file:"
+	@echo "# assistant -collectionFile $(BUILDDIR)/qthelp/rcmes.qhc"
+
+devhelp:
+	$(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
+	@echo
+	@echo "Build finished."
+	@echo "To view the help file:"
+	@echo "# mkdir -p $$HOME/.local/share/devhelp/rcmes"
+	@echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/rcmes"
+	@echo "# devhelp"
+
+epub:
+	$(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
+	@echo
+	@echo "Build finished. The epub file is in $(BUILDDIR)/epub."
+
+latex:
+	$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
+	@echo
+	@echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
+	@echo "Run \`make' in that directory to run these through (pdf)latex" \
+	      "(use \`make latexpdf' here to do that automatically)."
+
+latexpdf:
+	$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
+	@echo "Running LaTeX files through pdflatex..."
+	$(MAKE) -C $(BUILDDIR)/latex all-pdf
+	@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
+
+text:
+	$(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
+	@echo
+	@echo "Build finished. The text files are in $(BUILDDIR)/text."
+
+man:
+	$(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
+	@echo
+	@echo "Build finished. The manual pages are in $(BUILDDIR)/man."
+
+texinfo:
+	$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
+	@echo
+	@echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo."
+	@echo "Run \`make' in that directory to run these through makeinfo" \
+	      "(use \`make info' here to do that automatically)."
+
+info:
+	$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
+	@echo "Running Texinfo files through makeinfo..."
+	make -C $(BUILDDIR)/texinfo info
+	@echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo."
+
+gettext:
+	$(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale
+	@echo
+	@echo "Build finished. The message catalogs are in $(BUILDDIR)/locale."
+
+changes:
+	$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
+	@echo
+	@echo "The overview file is in $(BUILDDIR)/changes."
+
+linkcheck:
+	$(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
+	@echo
+	@echo "Link check complete; look for any errors in the above output " \
+	      "or in $(BUILDDIR)/linkcheck/output.txt."
+
+doctest:
+	$(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
+	@echo "Testing of doctests in the sources finished, look at the " \
+	      "results in $(BUILDDIR)/doctest/output.txt."

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/docs/.svn/text-base/RCMET_documentation.docx.svn-base
----------------------------------------------------------------------
diff --git a/src/main/python/docs/.svn/text-base/RCMET_documentation.docx.svn-base b/src/main/python/docs/.svn/text-base/RCMET_documentation.docx.svn-base
new file mode 100755
index 0000000..36cfd37
Binary files /dev/null and b/src/main/python/docs/.svn/text-base/RCMET_documentation.docx.svn-base differ

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/docs/.svn/text-base/conf.py.svn-base
----------------------------------------------------------------------
diff --git a/src/main/python/docs/.svn/text-base/conf.py.svn-base b/src/main/python/docs/.svn/text-base/conf.py.svn-base
new file mode 100755
index 0000000..0fc48d3
--- /dev/null
+++ b/src/main/python/docs/.svn/text-base/conf.py.svn-base
@@ -0,0 +1,242 @@
+# -*- coding: utf-8 -*-
+#
+# rcmes documentation build configuration file, created by
+# sphinx-quickstart on Tue Aug 14 14:18:41 2012.
+#
+# This file is execfile()d with the current directory set to its containing dir.
+#
+# Note that not all possible configuration values are present in this
+# autogenerated file.
+#
+# All configuration values have a default; values that are commented out
+# serve to show the default.
+
+import sys, os
+
+# If extensions (or modules to document with autodoc) are in another directory,
+# add these directories to sys.path here. If the directory is relative to the
+# documentation root, use os.path.abspath to make it absolute, like shown here.
+sys.path.insert(0, os.path.abspath('../'))
+
+# -- General configuration -----------------------------------------------------
+
+# If your documentation needs a minimal Sphinx version, state it here.
+#needs_sphinx = '1.0'
+
+# Add any Sphinx extension module names here, as strings. They can be extensions
+# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
+extensions = ['sphinx.ext.autodoc', 'sphinx.ext.todo', 'sphinx.ext.coverage']
+
+# Add any paths that contain templates here, relative to this directory.
+templates_path = ['_templates']
+
+# The suffix of source filenames.
+source_suffix = '.rst'
+
+# The encoding of source files.
+#source_encoding = 'utf-8-sig'
+
+# The master toctree document.
+master_doc = 'index'
+
+# General information about the project.
+project = u'rcmes'
+copyright = u'2012, Duane Waliser, Chris Mattmann, Jinwon Kim, Andrew Hart, Cameron Goodale, Paul Ramirez, Paul Zimdars, Kim Whitehall, Jesslyn Whittell, Peter Lean'
+
+# The version info for the project you're documenting, acts as replacement for
+# |version| and |release|, also used in various other places throughout the
+# built documents.
+#
+# The short X.Y version.
+version = '1.2'
+# The full version, including alpha/beta/rc tags.
+release = '1.2.0'
+
+# The language for content autogenerated by Sphinx. Refer to documentation
+# for a list of supported languages.
+#language = None
+
+# There are two options for replacing |today|: either, you set today to some
+# non-false value, then it is used:
+#today = ''
+# Else, today_fmt is used as the format for a strftime call.
+#today_fmt = '%B %d, %Y'
+
+# List of patterns, relative to source directory, that match files and
+# directories to ignore when looking for source files.
+exclude_patterns = ['_build']
+
+# The reST default role (used for this markup: `text`) to use for all documents.
+#default_role = None
+
+# If true, '()' will be appended to :func: etc. cross-reference text.
+#add_function_parentheses = True
+
+# If true, the current module name will be prepended to all description
+# unit titles (such as .. function::).
+#add_module_names = True
+
+# If true, sectionauthor and moduleauthor directives will be shown in the
+# output. They are ignored by default.
+#show_authors = False
+
+# The name of the Pygments (syntax highlighting) style to use.
+pygments_style = 'sphinx'
+
+# A list of ignored prefixes for module index sorting.
+#modindex_common_prefix = []
+
+
+# -- Options for HTML output ---------------------------------------------------
+
+# The theme to use for HTML and HTML Help pages.  See the documentation for
+# a list of builtin themes.
+html_theme = 'default'
+
+# Theme options are theme-specific and customize the look and feel of a theme
+# further.  For a list of options available for each theme, see the
+# documentation.
+#html_theme_options = {}
+
+# Add any paths that contain custom themes here, relative to this directory.
+#html_theme_path = []
+
+# The name for this set of Sphinx documents.  If None, it defaults to
+# "<project> v<release> documentation".
+#html_title = None
+
+# A shorter title for the navigation bar.  Default is the same as html_title.
+#html_short_title = None
+
+# The name of an image file (relative to this directory) to place at the top
+# of the sidebar.
+#html_logo = None
+
+# The name of an image file (within the static path) to use as favicon of the
+# docs.  This file should be a Windows icon file (.ico) being 16x16 or 32x32
+# pixels large.
+#html_favicon = None
+
+# Add any paths that contain custom static files (such as style sheets) here,
+# relative to this directory. They are copied after the builtin static files,
+# so a file named "default.css" will overwrite the builtin "default.css".
+html_static_path = ['_static']
+
+# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
+# using the given strftime format.
+#html_last_updated_fmt = '%b %d, %Y'
+
+# If true, SmartyPants will be used to convert quotes and dashes to
+# typographically correct entities.
+#html_use_smartypants = True
+
+# Custom sidebar templates, maps document names to template names.
+#html_sidebars = {}
+
+# Additional templates that should be rendered to pages, maps page names to
+# template names.
+#html_additional_pages = {}
+
+# If false, no module index is generated.
+#html_domain_indices = True
+
+# If false, no index is generated.
+#html_use_index = True
+
+# If true, the index is split into individual pages for each letter.
+#html_split_index = False
+
+# If true, links to the reST sources are added to the pages.
+#html_show_sourcelink = True
+
+# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
+#html_show_sphinx = True
+
+# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
+#html_show_copyright = True
+
+# If true, an OpenSearch description file will be output, and all pages will
+# contain a <link> tag referring to it.  The value of this option must be the
+# base URL from which the finished HTML is served.
+#html_use_opensearch = ''
+
+# This is the file name suffix for HTML files (e.g. ".xhtml").
+#html_file_suffix = None
+
+# Output file base name for HTML help builder.
+htmlhelp_basename = 'rcmesdoc'
+
+
+# -- Options for LaTeX output --------------------------------------------------
+
+latex_elements = {
+# The paper size ('letterpaper' or 'a4paper').
+#'papersize': 'letterpaper',
+
+# The font size ('10pt', '11pt' or '12pt').
+#'pointsize': '10pt',
+
+# Additional stuff for the LaTeX preamble.
+#'preamble': '',
+}
+
+# Grouping the document tree into LaTeX files. List of tuples
+# (source start file, target name, title, author, documentclass [howto/manual]).
+latex_documents = [
+  ('index', 'rcmes.tex', u'rcmes Documentation',
+   u'Duane Waliser, Chris Mattmann, Jinwon Kim, Andrew Hart, Cameron Goodale, Paul Ramirez, Paul Zimdars, Kim Whitehall, Jesslyn Whittell, Peter Lean', 'manual'),
+]
+
+# The name of an image file (relative to this directory) to place at the top of
+# the title page.
+#latex_logo = None
+
+# For "manual" documents, if this is true, then toplevel headings are parts,
+# not chapters.
+#latex_use_parts = False
+
+# If true, show page references after internal links.
+#latex_show_pagerefs = False
+
+# If true, show URL addresses after external links.
+#latex_show_urls = False
+
+# Documents to append as an appendix to all manuals.
+#latex_appendices = []
+
+# If false, no module index is generated.
+#latex_domain_indices = True
+
+
+# -- Options for manual page output --------------------------------------------
+
+# One entry per manual page. List of tuples
+# (source start file, name, description, authors, manual section).
+man_pages = [
+    ('index', 'rcmes', u'rcmes Documentation',
+     [u'Duane Waliser, Chris Mattmann, Jinwon Kim, Andrew Hart, Cameron Goodale, Paul Ramirez, Paul Zimdars, Kim Whitehall, Jesslyn Whittell, Peter Lean'], 1)
+]
+
+# If true, show URL addresses after external links.
+#man_show_urls = False
+
+
+# -- Options for Texinfo output ------------------------------------------------
+
+# Grouping the document tree into Texinfo files. List of tuples
+# (source start file, target name, title, author,
+#  dir menu entry, description, category)
+texinfo_documents = [
+  ('index', 'rcmes', u'rcmes Documentation',
+   u'Duane Waliser, Chris Mattmann, Jinwon Kim, Andrew Hart, Cameron Goodale, Paul Ramirez, Paul Zimdars, Kim Whitehall, Jesslyn Whittell, Peter Lean', 'rcmes', 'One line description of project.',
+   'Miscellaneous'),
+]
+
+# Documents to append as an appendix to all manuals.
+#texinfo_appendices = []
+
+# If false, no module index is generated.
+#texinfo_domain_indices = True
+
+# How to display URL addresses: 'footnote', 'no', or 'inline'.
+#texinfo_show_urls = 'footnote'

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/docs/.svn/text-base/index.rst.svn-base
----------------------------------------------------------------------
diff --git a/src/main/python/docs/.svn/text-base/index.rst.svn-base b/src/main/python/docs/.svn/text-base/index.rst.svn-base
new file mode 100755
index 0000000..bf4c50f
--- /dev/null
+++ b/src/main/python/docs/.svn/text-base/index.rst.svn-base
@@ -0,0 +1,22 @@
+.. rcmes documentation master file, created by
+   sphinx-quickstart on Tue Aug 14 14:18:41 2012.
+   You can adapt this file completely to your liking, but it should at least
+   contain the root `toctree` directive.
+
+Welcome to rcmes's documentation!
+=================================
+
+Contents:
+
+.. toctree::
+   :maxdepth: 2
+
+
+
+Indices and tables
+==================
+
+* :ref:`genindex`
+* :ref:`modindex`
+* :ref:`search`
+

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/docs/.svn/text-base/make.bat.svn-base
----------------------------------------------------------------------
diff --git a/src/main/python/docs/.svn/text-base/make.bat.svn-base b/src/main/python/docs/.svn/text-base/make.bat.svn-base
new file mode 100755
index 0000000..2225cc2
--- /dev/null
+++ b/src/main/python/docs/.svn/text-base/make.bat.svn-base
@@ -0,0 +1,190 @@
+@ECHO OFF
+
+REM Command file for Sphinx documentation
+
+if "%SPHINXBUILD%" == "" (
+	set SPHINXBUILD=sphinx-build
+)
+set BUILDDIR=_build
+set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% .
+set I18NSPHINXOPTS=%SPHINXOPTS% .
+if NOT "%PAPER%" == "" (
+	set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS%
+	set I18NSPHINXOPTS=-D latex_paper_size=%PAPER% %I18NSPHINXOPTS%
+)
+
+if "%1" == "" goto help
+
+if "%1" == "help" (
+	:help
+	echo.Please use `make ^<target^>` where ^<target^> is one of
+	echo.  html       to make standalone HTML files
+	echo.  dirhtml    to make HTML files named index.html in directories
+	echo.  singlehtml to make a single large HTML file
+	echo.  pickle     to make pickle files
+	echo.  json       to make JSON files
+	echo.  htmlhelp   to make HTML files and a HTML help project
+	echo.  qthelp     to make HTML files and a qthelp project
+	echo.  devhelp    to make HTML files and a Devhelp project
+	echo.  epub       to make an epub
+	echo.  latex      to make LaTeX files, you can set PAPER=a4 or PAPER=letter
+	echo.  text       to make text files
+	echo.  man        to make manual pages
+	echo.  texinfo    to make Texinfo files
+	echo.  gettext    to make PO message catalogs
+	echo.  changes    to make an overview over all changed/added/deprecated items
+	echo.  linkcheck  to check all external links for integrity
+	echo.  doctest    to run all doctests embedded in the documentation if enabled
+	goto end
+)
+
+if "%1" == "clean" (
+	for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i
+	del /q /s %BUILDDIR%\*
+	goto end
+)
+
+if "%1" == "html" (
+	%SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Build finished. The HTML pages are in %BUILDDIR%/html.
+	goto end
+)
+
+if "%1" == "dirhtml" (
+	%SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml.
+	goto end
+)
+
+if "%1" == "singlehtml" (
+	%SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml.
+	goto end
+)
+
+if "%1" == "pickle" (
+	%SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Build finished; now you can process the pickle files.
+	goto end
+)
+
+if "%1" == "json" (
+	%SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Build finished; now you can process the JSON files.
+	goto end
+)
+
+if "%1" == "htmlhelp" (
+	%SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Build finished; now you can run HTML Help Workshop with the ^
+.hhp project file in %BUILDDIR%/htmlhelp.
+	goto end
+)
+
+if "%1" == "qthelp" (
+	%SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Build finished; now you can run "qcollectiongenerator" with the ^
+.qhcp project file in %BUILDDIR%/qthelp, like this:
+	echo.^> qcollectiongenerator %BUILDDIR%\qthelp\rcmes.qhcp
+	echo.To view the help file:
+	echo.^> assistant -collectionFile %BUILDDIR%\qthelp\rcmes.ghc
+	goto end
+)
+
+if "%1" == "devhelp" (
+	%SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Build finished.
+	goto end
+)
+
+if "%1" == "epub" (
+	%SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Build finished. The epub file is in %BUILDDIR%/epub.
+	goto end
+)
+
+if "%1" == "latex" (
+	%SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Build finished; the LaTeX files are in %BUILDDIR%/latex.
+	goto end
+)
+
+if "%1" == "text" (
+	%SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Build finished. The text files are in %BUILDDIR%/text.
+	goto end
+)
+
+if "%1" == "man" (
+	%SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Build finished. The manual pages are in %BUILDDIR%/man.
+	goto end
+)
+
+if "%1" == "texinfo" (
+	%SPHINXBUILD% -b texinfo %ALLSPHINXOPTS% %BUILDDIR%/texinfo
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Build finished. The Texinfo files are in %BUILDDIR%/texinfo.
+	goto end
+)
+
+if "%1" == "gettext" (
+	%SPHINXBUILD% -b gettext %I18NSPHINXOPTS% %BUILDDIR%/locale
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Build finished. The message catalogs are in %BUILDDIR%/locale.
+	goto end
+)
+
+if "%1" == "changes" (
+	%SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.The overview file is in %BUILDDIR%/changes.
+	goto end
+)
+
+if "%1" == "linkcheck" (
+	%SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Link check complete; look for any errors in the above output ^
+or in %BUILDDIR%/linkcheck/output.txt.
+	goto end
+)
+
+if "%1" == "doctest" (
+	%SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Testing of doctests in the sources finished, look at the ^
+results in %BUILDDIR%/doctest/output.txt.
+	goto end
+)
+
+:end

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/docs/.svn/text-base/rcmes.cli.rst.svn-base
----------------------------------------------------------------------
diff --git a/src/main/python/docs/.svn/text-base/rcmes.cli.rst.svn-base b/src/main/python/docs/.svn/text-base/rcmes.cli.rst.svn-base
new file mode 100755
index 0000000..c337ec5
--- /dev/null
+++ b/src/main/python/docs/.svn/text-base/rcmes.cli.rst.svn-base
@@ -0,0 +1,19 @@
+cli Package
+===========
+
+:mod:`do_rcmes_processing_sub` Module
+-------------------------------------
+
+.. automodule:: rcmes.cli.do_rcmes_processing_sub
+    :members:
+    :undoc-members:
+    :show-inheritance:
+
+:mod:`rcmet_ui` Module
+----------------------
+
+.. automodule:: rcmes.cli.rcmet_ui
+    :members:
+    :undoc-members:
+    :show-inheritance:
+

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/docs/.svn/text-base/rcmes.rst.svn-base
----------------------------------------------------------------------
diff --git a/src/main/python/docs/.svn/text-base/rcmes.rst.svn-base b/src/main/python/docs/.svn/text-base/rcmes.rst.svn-base
new file mode 100755
index 0000000..29e4be5
--- /dev/null
+++ b/src/main/python/docs/.svn/text-base/rcmes.rst.svn-base
@@ -0,0 +1,22 @@
+rcmes Package
+=============
+
+:mod:`rcmes` Package
+--------------------
+
+.. automodule:: rcmes.__init__
+    :members:
+    :undoc-members:
+    :show-inheritance:
+
+Subpackages
+-----------
+
+.. toctree::
+
+    rcmes.cli
+    rcmes.services
+    rcmes.storage
+    rcmes.toolkit
+    rcmes.utils
+

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/docs/.svn/text-base/rcmes.services.rst.svn-base
----------------------------------------------------------------------
diff --git a/src/main/python/docs/.svn/text-base/rcmes.services.rst.svn-base b/src/main/python/docs/.svn/text-base/rcmes.services.rst.svn-base
new file mode 100755
index 0000000..d01b950
--- /dev/null
+++ b/src/main/python/docs/.svn/text-base/rcmes.services.rst.svn-base
@@ -0,0 +1,51 @@
+services Package
+================
+
+:mod:`decode_model_times` Module
+--------------------------------
+
+.. automodule:: rcmes.services.decode_model_times
+    :members:
+    :undoc-members:
+    :show-inheritance:
+
+:mod:`find_latlon_var` Module
+-----------------------------
+
+.. automodule:: rcmes.services.find_latlon_var
+    :members:
+    :undoc-members:
+    :show-inheritance:
+
+:mod:`find_time_var` Module
+---------------------------
+
+.. automodule:: rcmes.services.find_time_var
+    :members:
+    :undoc-members:
+    :show-inheritance:
+
+:mod:`list_vars_in_file` Module
+-------------------------------
+
+.. automodule:: rcmes.services.list_vars_in_file
+    :members:
+    :undoc-members:
+    :show-inheritance:
+
+:mod:`main_ws` Module
+---------------------
+
+.. automodule:: rcmes.services.main_ws
+    :members:
+    :undoc-members:
+    :show-inheritance:
+
+:mod:`run_rcmes_processing` Module
+----------------------------------
+
+.. automodule:: rcmes.services.run_rcmes_processing
+    :members:
+    :undoc-members:
+    :show-inheritance:
+

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/docs/.svn/text-base/rcmes.storage.rst.svn-base
----------------------------------------------------------------------
diff --git a/src/main/python/docs/.svn/text-base/rcmes.storage.rst.svn-base b/src/main/python/docs/.svn/text-base/rcmes.storage.rst.svn-base
new file mode 100755
index 0000000..f5b45c5
--- /dev/null
+++ b/src/main/python/docs/.svn/text-base/rcmes.storage.rst.svn-base
@@ -0,0 +1,27 @@
+storage Package
+===============
+
+:mod:`db` Module
+----------------
+
+.. automodule:: rcmes.storage.db
+    :members:
+    :undoc-members:
+    :show-inheritance:
+
+:mod:`files` Module
+-------------------
+
+.. automodule:: rcmes.storage.files
+    :members:
+    :undoc-members:
+    :show-inheritance:
+
+:mod:`rcmed` Module
+-------------------
+
+.. automodule:: rcmes.storage.rcmed
+    :members:
+    :undoc-members:
+    :show-inheritance:
+

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/docs/.svn/text-base/rcmes.toolkit.rst.svn-base
----------------------------------------------------------------------
diff --git a/src/main/python/docs/.svn/text-base/rcmes.toolkit.rst.svn-base b/src/main/python/docs/.svn/text-base/rcmes.toolkit.rst.svn-base
new file mode 100755
index 0000000..25fec30
--- /dev/null
+++ b/src/main/python/docs/.svn/text-base/rcmes.toolkit.rst.svn-base
@@ -0,0 +1,27 @@
+toolkit Package
+===============
+
+:mod:`metrics` Module
+---------------------
+
+.. automodule:: rcmes.toolkit.metrics
+    :members:
+    :undoc-members:
+    :show-inheritance:
+
+:mod:`plots` Module
+-------------------
+
+.. automodule:: rcmes.toolkit.plots
+    :members:
+    :undoc-members:
+    :show-inheritance:
+
+:mod:`process` Module
+---------------------
+
+.. automodule:: rcmes.toolkit.process
+    :members:
+    :undoc-members:
+    :show-inheritance:
+

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/docs/.svn/text-base/rcmes.utils.rst.svn-base
----------------------------------------------------------------------
diff --git a/src/main/python/docs/.svn/text-base/rcmes.utils.rst.svn-base b/src/main/python/docs/.svn/text-base/rcmes.utils.rst.svn-base
new file mode 100755
index 0000000..696005c
--- /dev/null
+++ b/src/main/python/docs/.svn/text-base/rcmes.utils.rst.svn-base
@@ -0,0 +1,19 @@
+utils Package
+=============
+
+:mod:`fortranfile` Module
+-------------------------
+
+.. automodule:: rcmes.utils.fortranfile
+    :members:
+    :undoc-members:
+    :show-inheritance:
+
+:mod:`misc` Module
+------------------
+
+.. automodule:: rcmes.utils.misc
+    :members:
+    :undoc-members:
+    :show-inheritance:
+

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/docs/Bottle Web Service Documentation.docx
----------------------------------------------------------------------
diff --git a/src/main/python/docs/Bottle Web Service Documentation.docx b/src/main/python/docs/Bottle Web Service Documentation.docx
new file mode 100755
index 0000000..a6fdd6f
Binary files /dev/null and b/src/main/python/docs/Bottle Web Service Documentation.docx differ

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/docs/Makefile
----------------------------------------------------------------------
diff --git a/src/main/python/docs/Makefile b/src/main/python/docs/Makefile
new file mode 100755
index 0000000..9cf4b97
--- /dev/null
+++ b/src/main/python/docs/Makefile
@@ -0,0 +1,153 @@
+# Makefile for Sphinx documentation
+#
+
+# You can set these variables from the command line.
+SPHINXOPTS    =
+SPHINXBUILD   = sphinx-build
+PAPER         =
+BUILDDIR      = _build
+
+# Internal variables.
+PAPEROPT_a4     = -D latex_paper_size=a4
+PAPEROPT_letter = -D latex_paper_size=letter
+ALLSPHINXOPTS   = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
+# the i18n builder cannot share the environment and doctrees with the others
+I18NSPHINXOPTS  = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
+
+.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext
+
+help:
+	@echo "Please use \`make <target>' where <target> is one of"
+	@echo "  html       to make standalone HTML files"
+	@echo "  dirhtml    to make HTML files named index.html in directories"
+	@echo "  singlehtml to make a single large HTML file"
+	@echo "  pickle     to make pickle files"
+	@echo "  json       to make JSON files"
+	@echo "  htmlhelp   to make HTML files and a HTML help project"
+	@echo "  qthelp     to make HTML files and a qthelp project"
+	@echo "  devhelp    to make HTML files and a Devhelp project"
+	@echo "  epub       to make an epub"
+	@echo "  latex      to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
+	@echo "  latexpdf   to make LaTeX files and run them through pdflatex"
+	@echo "  text       to make text files"
+	@echo "  man        to make manual pages"
+	@echo "  texinfo    to make Texinfo files"
+	@echo "  info       to make Texinfo files and run them through makeinfo"
+	@echo "  gettext    to make PO message catalogs"
+	@echo "  changes    to make an overview of all changed/added/deprecated items"
+	@echo "  linkcheck  to check all external links for integrity"
+	@echo "  doctest    to run all doctests embedded in the documentation (if enabled)"
+
+clean:
+	-rm -rf $(BUILDDIR)/*
+
+html:
+	$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
+	@echo
+	@echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
+
+dirhtml:
+	$(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
+	@echo
+	@echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
+
+singlehtml:
+	$(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
+	@echo
+	@echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
+
+pickle:
+	$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
+	@echo
+	@echo "Build finished; now you can process the pickle files."
+
+json:
+	$(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
+	@echo
+	@echo "Build finished; now you can process the JSON files."
+
+htmlhelp:
+	$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
+	@echo
+	@echo "Build finished; now you can run HTML Help Workshop with the" \
+	      ".hhp project file in $(BUILDDIR)/htmlhelp."
+
+qthelp:
+	$(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
+	@echo
+	@echo "Build finished; now you can run "qcollectiongenerator" with the" \
+	      ".qhcp project file in $(BUILDDIR)/qthelp, like this:"
+	@echo "# qcollectiongenerator $(BUILDDIR)/qthelp/rcmes.qhcp"
+	@echo "To view the help file:"
+	@echo "# assistant -collectionFile $(BUILDDIR)/qthelp/rcmes.qhc"
+
+devhelp:
+	$(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
+	@echo
+	@echo "Build finished."
+	@echo "To view the help file:"
+	@echo "# mkdir -p $$HOME/.local/share/devhelp/rcmes"
+	@echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/rcmes"
+	@echo "# devhelp"
+
+epub:
+	$(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
+	@echo
+	@echo "Build finished. The epub file is in $(BUILDDIR)/epub."
+
+latex:
+	$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
+	@echo
+	@echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
+	@echo "Run \`make' in that directory to run these through (pdf)latex" \
+	      "(use \`make latexpdf' here to do that automatically)."
+
+latexpdf:
+	$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
+	@echo "Running LaTeX files through pdflatex..."
+	$(MAKE) -C $(BUILDDIR)/latex all-pdf
+	@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
+
+text:
+	$(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
+	@echo
+	@echo "Build finished. The text files are in $(BUILDDIR)/text."
+
+man:
+	$(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
+	@echo
+	@echo "Build finished. The manual pages are in $(BUILDDIR)/man."
+
+texinfo:
+	$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
+	@echo
+	@echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo."
+	@echo "Run \`make' in that directory to run these through makeinfo" \
+	      "(use \`make info' here to do that automatically)."
+
+info:
+	$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
+	@echo "Running Texinfo files through makeinfo..."
+	make -C $(BUILDDIR)/texinfo info
+	@echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo."
+
+gettext:
+	$(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale
+	@echo
+	@echo "Build finished. The message catalogs are in $(BUILDDIR)/locale."
+
+changes:
+	$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
+	@echo
+	@echo "The overview file is in $(BUILDDIR)/changes."
+
+linkcheck:
+	$(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
+	@echo
+	@echo "Link check complete; look for any errors in the above output " \
+	      "or in $(BUILDDIR)/linkcheck/output.txt."
+
+doctest:
+	$(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
+	@echo "Testing of doctests in the sources finished, look at the " \
+	      "results in $(BUILDDIR)/doctest/output.txt."

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/docs/RCMET_documentation.docx
----------------------------------------------------------------------
diff --git a/src/main/python/docs/RCMET_documentation.docx b/src/main/python/docs/RCMET_documentation.docx
new file mode 100755
index 0000000..36cfd37
Binary files /dev/null and b/src/main/python/docs/RCMET_documentation.docx differ

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/docs/_static/.svn/all-wcprops
----------------------------------------------------------------------
diff --git a/src/main/python/docs/_static/.svn/all-wcprops b/src/main/python/docs/_static/.svn/all-wcprops
new file mode 100755
index 0000000..c1437c9
--- /dev/null
+++ b/src/main/python/docs/_static/.svn/all-wcprops
@@ -0,0 +1,5 @@
+K 25
+svn:wc:ra_dav:version-url
+V 86
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/python/docs/_static
+END

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/docs/_static/.svn/entries
----------------------------------------------------------------------
diff --git a/src/main/python/docs/_static/.svn/entries b/src/main/python/docs/_static/.svn/entries
new file mode 100755
index 0000000..a5b8f39
--- /dev/null
+++ b/src/main/python/docs/_static/.svn/entries
@@ -0,0 +1,28 @@
+10
+
+dir
+1485921
+https://svn.apache.org/repos/asf/incubator/climate/trunk/rcmet/src/main/python/docs/_static
+https://svn.apache.org/repos/asf
+
+
+
+2012-08-14T21:47:34.802218Z
+1473865
+pramirez
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+13f79535-47bb-0310-9956-ffa450edef68
+

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/docs/_templates/.svn/all-wcprops
----------------------------------------------------------------------
diff --git a/src/main/python/docs/_templates/.svn/all-wcprops b/src/main/python/docs/_templates/.svn/all-wcprops
new file mode 100755
index 0000000..55c8f8a
--- /dev/null
+++ b/src/main/python/docs/_templates/.svn/all-wcprops
@@ -0,0 +1,5 @@
+K 25
+svn:wc:ra_dav:version-url
+V 89
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/python/docs/_templates
+END

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/docs/_templates/.svn/entries
----------------------------------------------------------------------
diff --git a/src/main/python/docs/_templates/.svn/entries b/src/main/python/docs/_templates/.svn/entries
new file mode 100755
index 0000000..cbcc65b
--- /dev/null
+++ b/src/main/python/docs/_templates/.svn/entries
@@ -0,0 +1,28 @@
+10
+
+dir
+1485921
+https://svn.apache.org/repos/asf/incubator/climate/trunk/rcmet/src/main/python/docs/_templates
+https://svn.apache.org/repos/asf
+
+
+
+2012-08-14T21:47:34.802218Z
+1473865
+pramirez
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+13f79535-47bb-0310-9956-ffa450edef68
+

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/docs/conf.py
----------------------------------------------------------------------
diff --git a/src/main/python/docs/conf.py b/src/main/python/docs/conf.py
new file mode 100755
index 0000000..0fc48d3
--- /dev/null
+++ b/src/main/python/docs/conf.py
@@ -0,0 +1,242 @@
+# -*- coding: utf-8 -*-
+#
+# rcmes documentation build configuration file, created by
+# sphinx-quickstart on Tue Aug 14 14:18:41 2012.
+#
+# This file is execfile()d with the current directory set to its containing dir.
+#
+# Note that not all possible configuration values are present in this
+# autogenerated file.
+#
+# All configuration values have a default; values that are commented out
+# serve to show the default.
+
+import sys, os
+
+# If extensions (or modules to document with autodoc) are in another directory,
+# add these directories to sys.path here. If the directory is relative to the
+# documentation root, use os.path.abspath to make it absolute, like shown here.
+sys.path.insert(0, os.path.abspath('../'))
+
+# -- General configuration -----------------------------------------------------
+
+# If your documentation needs a minimal Sphinx version, state it here.
+#needs_sphinx = '1.0'
+
+# Add any Sphinx extension module names here, as strings. They can be extensions
+# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
+extensions = ['sphinx.ext.autodoc', 'sphinx.ext.todo', 'sphinx.ext.coverage']
+
+# Add any paths that contain templates here, relative to this directory.
+templates_path = ['_templates']
+
+# The suffix of source filenames.
+source_suffix = '.rst'
+
+# The encoding of source files.
+#source_encoding = 'utf-8-sig'
+
+# The master toctree document.
+master_doc = 'index'
+
+# General information about the project.
+project = u'rcmes'
+copyright = u'2012, Duane Waliser, Chris Mattmann, Jinwon Kim, Andrew Hart, Cameron Goodale, Paul Ramirez, Paul Zimdars, Kim Whitehall, Jesslyn Whittell, Peter Lean'
+
+# The version info for the project you're documenting, acts as replacement for
+# |version| and |release|, also used in various other places throughout the
+# built documents.
+#
+# The short X.Y version.
+version = '1.2'
+# The full version, including alpha/beta/rc tags.
+release = '1.2.0'
+
+# The language for content autogenerated by Sphinx. Refer to documentation
+# for a list of supported languages.
+#language = None
+
+# There are two options for replacing |today|: either, you set today to some
+# non-false value, then it is used:
+#today = ''
+# Else, today_fmt is used as the format for a strftime call.
+#today_fmt = '%B %d, %Y'
+
+# List of patterns, relative to source directory, that match files and
+# directories to ignore when looking for source files.
+exclude_patterns = ['_build']
+
+# The reST default role (used for this markup: `text`) to use for all documents.
+#default_role = None
+
+# If true, '()' will be appended to :func: etc. cross-reference text.
+#add_function_parentheses = True
+
+# If true, the current module name will be prepended to all description
+# unit titles (such as .. function::).
+#add_module_names = True
+
+# If true, sectionauthor and moduleauthor directives will be shown in the
+# output. They are ignored by default.
+#show_authors = False
+
+# The name of the Pygments (syntax highlighting) style to use.
+pygments_style = 'sphinx'
+
+# A list of ignored prefixes for module index sorting.
+#modindex_common_prefix = []
+
+
+# -- Options for HTML output ---------------------------------------------------
+
+# The theme to use for HTML and HTML Help pages.  See the documentation for
+# a list of builtin themes.
+html_theme = 'default'
+
+# Theme options are theme-specific and customize the look and feel of a theme
+# further.  For a list of options available for each theme, see the
+# documentation.
+#html_theme_options = {}
+
+# Add any paths that contain custom themes here, relative to this directory.
+#html_theme_path = []
+
+# The name for this set of Sphinx documents.  If None, it defaults to
+# "<project> v<release> documentation".
+#html_title = None
+
+# A shorter title for the navigation bar.  Default is the same as html_title.
+#html_short_title = None
+
+# The name of an image file (relative to this directory) to place at the top
+# of the sidebar.
+#html_logo = None
+
+# The name of an image file (within the static path) to use as favicon of the
+# docs.  This file should be a Windows icon file (.ico) being 16x16 or 32x32
+# pixels large.
+#html_favicon = None
+
+# Add any paths that contain custom static files (such as style sheets) here,
+# relative to this directory. They are copied after the builtin static files,
+# so a file named "default.css" will overwrite the builtin "default.css".
+html_static_path = ['_static']
+
+# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
+# using the given strftime format.
+#html_last_updated_fmt = '%b %d, %Y'
+
+# If true, SmartyPants will be used to convert quotes and dashes to
+# typographically correct entities.
+#html_use_smartypants = True
+
+# Custom sidebar templates, maps document names to template names.
+#html_sidebars = {}
+
+# Additional templates that should be rendered to pages, maps page names to
+# template names.
+#html_additional_pages = {}
+
+# If false, no module index is generated.
+#html_domain_indices = True
+
+# If false, no index is generated.
+#html_use_index = True
+
+# If true, the index is split into individual pages for each letter.
+#html_split_index = False
+
+# If true, links to the reST sources are added to the pages.
+#html_show_sourcelink = True
+
+# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
+#html_show_sphinx = True
+
+# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
+#html_show_copyright = True
+
+# If true, an OpenSearch description file will be output, and all pages will
+# contain a <link> tag referring to it.  The value of this option must be the
+# base URL from which the finished HTML is served.
+#html_use_opensearch = ''
+
+# This is the file name suffix for HTML files (e.g. ".xhtml").
+#html_file_suffix = None
+
+# Output file base name for HTML help builder.
+htmlhelp_basename = 'rcmesdoc'
+
+
+# -- Options for LaTeX output --------------------------------------------------
+
+latex_elements = {
+# The paper size ('letterpaper' or 'a4paper').
+#'papersize': 'letterpaper',
+
+# The font size ('10pt', '11pt' or '12pt').
+#'pointsize': '10pt',
+
+# Additional stuff for the LaTeX preamble.
+#'preamble': '',
+}
+
+# Grouping the document tree into LaTeX files. List of tuples
+# (source start file, target name, title, author, documentclass [howto/manual]).
+latex_documents = [
+  ('index', 'rcmes.tex', u'rcmes Documentation',
+   u'Duane Waliser, Chris Mattmann, Jinwon Kim, Andrew Hart, Cameron Goodale, Paul Ramirez, Paul Zimdars, Kim Whitehall, Jesslyn Whittell, Peter Lean', 'manual'),
+]
+
+# The name of an image file (relative to this directory) to place at the top of
+# the title page.
+#latex_logo = None
+
+# For "manual" documents, if this is true, then toplevel headings are parts,
+# not chapters.
+#latex_use_parts = False
+
+# If true, show page references after internal links.
+#latex_show_pagerefs = False
+
+# If true, show URL addresses after external links.
+#latex_show_urls = False
+
+# Documents to append as an appendix to all manuals.
+#latex_appendices = []
+
+# If false, no module index is generated.
+#latex_domain_indices = True
+
+
+# -- Options for manual page output --------------------------------------------
+
+# One entry per manual page. List of tuples
+# (source start file, name, description, authors, manual section).
+man_pages = [
+    ('index', 'rcmes', u'rcmes Documentation',
+     [u'Duane Waliser, Chris Mattmann, Jinwon Kim, Andrew Hart, Cameron Goodale, Paul Ramirez, Paul Zimdars, Kim Whitehall, Jesslyn Whittell, Peter Lean'], 1)
+]
+
+# If true, show URL addresses after external links.
+#man_show_urls = False
+
+
+# -- Options for Texinfo output ------------------------------------------------
+
+# Grouping the document tree into Texinfo files. List of tuples
+# (source start file, target name, title, author,
+#  dir menu entry, description, category)
+texinfo_documents = [
+  ('index', 'rcmes', u'rcmes Documentation',
+   u'Duane Waliser, Chris Mattmann, Jinwon Kim, Andrew Hart, Cameron Goodale, Paul Ramirez, Paul Zimdars, Kim Whitehall, Jesslyn Whittell, Peter Lean', 'rcmes', 'One line description of project.',
+   'Miscellaneous'),
+]
+
+# Documents to append as an appendix to all manuals.
+#texinfo_appendices = []
+
+# If false, no module index is generated.
+#texinfo_domain_indices = True
+
+# How to display URL addresses: 'footnote', 'no', or 'inline'.
+#texinfo_show_urls = 'footnote'

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/docs/index.rst
----------------------------------------------------------------------
diff --git a/src/main/python/docs/index.rst b/src/main/python/docs/index.rst
new file mode 100755
index 0000000..bf4c50f
--- /dev/null
+++ b/src/main/python/docs/index.rst
@@ -0,0 +1,22 @@
+.. rcmes documentation master file, created by
+   sphinx-quickstart on Tue Aug 14 14:18:41 2012.
+   You can adapt this file completely to your liking, but it should at least
+   contain the root `toctree` directive.
+
+Welcome to rcmes's documentation!
+=================================
+
+Contents:
+
+.. toctree::
+   :maxdepth: 2
+
+
+
+Indices and tables
+==================
+
+* :ref:`genindex`
+* :ref:`modindex`
+* :ref:`search`
+

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/docs/make.bat
----------------------------------------------------------------------
diff --git a/src/main/python/docs/make.bat b/src/main/python/docs/make.bat
new file mode 100755
index 0000000..2225cc2
--- /dev/null
+++ b/src/main/python/docs/make.bat
@@ -0,0 +1,190 @@
+@ECHO OFF
+
+REM Command file for Sphinx documentation
+
+if "%SPHINXBUILD%" == "" (
+	set SPHINXBUILD=sphinx-build
+)
+set BUILDDIR=_build
+set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% .
+set I18NSPHINXOPTS=%SPHINXOPTS% .
+if NOT "%PAPER%" == "" (
+	set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS%
+	set I18NSPHINXOPTS=-D latex_paper_size=%PAPER% %I18NSPHINXOPTS%
+)
+
+if "%1" == "" goto help
+
+if "%1" == "help" (
+	:help
+	echo.Please use `make ^<target^>` where ^<target^> is one of
+	echo.  html       to make standalone HTML files
+	echo.  dirhtml    to make HTML files named index.html in directories
+	echo.  singlehtml to make a single large HTML file
+	echo.  pickle     to make pickle files
+	echo.  json       to make JSON files
+	echo.  htmlhelp   to make HTML files and a HTML help project
+	echo.  qthelp     to make HTML files and a qthelp project
+	echo.  devhelp    to make HTML files and a Devhelp project
+	echo.  epub       to make an epub
+	echo.  latex      to make LaTeX files, you can set PAPER=a4 or PAPER=letter
+	echo.  text       to make text files
+	echo.  man        to make manual pages
+	echo.  texinfo    to make Texinfo files
+	echo.  gettext    to make PO message catalogs
+	echo.  changes    to make an overview over all changed/added/deprecated items
+	echo.  linkcheck  to check all external links for integrity
+	echo.  doctest    to run all doctests embedded in the documentation if enabled
+	goto end
+)
+
+if "%1" == "clean" (
+	for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i
+	del /q /s %BUILDDIR%\*
+	goto end
+)
+
+if "%1" == "html" (
+	%SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Build finished. The HTML pages are in %BUILDDIR%/html.
+	goto end
+)
+
+if "%1" == "dirhtml" (
+	%SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml.
+	goto end
+)
+
+if "%1" == "singlehtml" (
+	%SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml.
+	goto end
+)
+
+if "%1" == "pickle" (
+	%SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Build finished; now you can process the pickle files.
+	goto end
+)
+
+if "%1" == "json" (
+	%SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Build finished; now you can process the JSON files.
+	goto end
+)
+
+if "%1" == "htmlhelp" (
+	%SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Build finished; now you can run HTML Help Workshop with the ^
+.hhp project file in %BUILDDIR%/htmlhelp.
+	goto end
+)
+
+if "%1" == "qthelp" (
+	%SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Build finished; now you can run "qcollectiongenerator" with the ^
+.qhcp project file in %BUILDDIR%/qthelp, like this:
+	echo.^> qcollectiongenerator %BUILDDIR%\qthelp\rcmes.qhcp
+	echo.To view the help file:
+	echo.^> assistant -collectionFile %BUILDDIR%\qthelp\rcmes.ghc
+	goto end
+)
+
+if "%1" == "devhelp" (
+	%SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Build finished.
+	goto end
+)
+
+if "%1" == "epub" (
+	%SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Build finished. The epub file is in %BUILDDIR%/epub.
+	goto end
+)
+
+if "%1" == "latex" (
+	%SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Build finished; the LaTeX files are in %BUILDDIR%/latex.
+	goto end
+)
+
+if "%1" == "text" (
+	%SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Build finished. The text files are in %BUILDDIR%/text.
+	goto end
+)
+
+if "%1" == "man" (
+	%SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Build finished. The manual pages are in %BUILDDIR%/man.
+	goto end
+)
+
+if "%1" == "texinfo" (
+	%SPHINXBUILD% -b texinfo %ALLSPHINXOPTS% %BUILDDIR%/texinfo
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Build finished. The Texinfo files are in %BUILDDIR%/texinfo.
+	goto end
+)
+
+if "%1" == "gettext" (
+	%SPHINXBUILD% -b gettext %I18NSPHINXOPTS% %BUILDDIR%/locale
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Build finished. The message catalogs are in %BUILDDIR%/locale.
+	goto end
+)
+
+if "%1" == "changes" (
+	%SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.The overview file is in %BUILDDIR%/changes.
+	goto end
+)
+
+if "%1" == "linkcheck" (
+	%SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Link check complete; look for any errors in the above output ^
+or in %BUILDDIR%/linkcheck/output.txt.
+	goto end
+)
+
+if "%1" == "doctest" (
+	%SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Testing of doctests in the sources finished, look at the ^
+results in %BUILDDIR%/doctest/output.txt.
+	goto end
+)
+
+:end

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/docs/rcmes.cli.rst
----------------------------------------------------------------------
diff --git a/src/main/python/docs/rcmes.cli.rst b/src/main/python/docs/rcmes.cli.rst
new file mode 100755
index 0000000..c337ec5
--- /dev/null
+++ b/src/main/python/docs/rcmes.cli.rst
@@ -0,0 +1,19 @@
+cli Package
+===========
+
+:mod:`do_rcmes_processing_sub` Module
+-------------------------------------
+
+.. automodule:: rcmes.cli.do_rcmes_processing_sub
+    :members:
+    :undoc-members:
+    :show-inheritance:
+
+:mod:`rcmet_ui` Module
+----------------------
+
+.. automodule:: rcmes.cli.rcmet_ui
+    :members:
+    :undoc-members:
+    :show-inheritance:
+

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/docs/rcmes.rst
----------------------------------------------------------------------
diff --git a/src/main/python/docs/rcmes.rst b/src/main/python/docs/rcmes.rst
new file mode 100755
index 0000000..29e4be5
--- /dev/null
+++ b/src/main/python/docs/rcmes.rst
@@ -0,0 +1,22 @@
+rcmes Package
+=============
+
+:mod:`rcmes` Package
+--------------------
+
+.. automodule:: rcmes.__init__
+    :members:
+    :undoc-members:
+    :show-inheritance:
+
+Subpackages
+-----------
+
+.. toctree::
+
+    rcmes.cli
+    rcmes.services
+    rcmes.storage
+    rcmes.toolkit
+    rcmes.utils
+

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/docs/rcmes.services.rst
----------------------------------------------------------------------
diff --git a/src/main/python/docs/rcmes.services.rst b/src/main/python/docs/rcmes.services.rst
new file mode 100755
index 0000000..d01b950
--- /dev/null
+++ b/src/main/python/docs/rcmes.services.rst
@@ -0,0 +1,51 @@
+services Package
+================
+
+:mod:`decode_model_times` Module
+--------------------------------
+
+.. automodule:: rcmes.services.decode_model_times
+    :members:
+    :undoc-members:
+    :show-inheritance:
+
+:mod:`find_latlon_var` Module
+-----------------------------
+
+.. automodule:: rcmes.services.find_latlon_var
+    :members:
+    :undoc-members:
+    :show-inheritance:
+
+:mod:`find_time_var` Module
+---------------------------
+
+.. automodule:: rcmes.services.find_time_var
+    :members:
+    :undoc-members:
+    :show-inheritance:
+
+:mod:`list_vars_in_file` Module
+-------------------------------
+
+.. automodule:: rcmes.services.list_vars_in_file
+    :members:
+    :undoc-members:
+    :show-inheritance:
+
+:mod:`main_ws` Module
+---------------------
+
+.. automodule:: rcmes.services.main_ws
+    :members:
+    :undoc-members:
+    :show-inheritance:
+
+:mod:`run_rcmes_processing` Module
+----------------------------------
+
+.. automodule:: rcmes.services.run_rcmes_processing
+    :members:
+    :undoc-members:
+    :show-inheritance:
+

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/docs/rcmes.storage.rst
----------------------------------------------------------------------
diff --git a/src/main/python/docs/rcmes.storage.rst b/src/main/python/docs/rcmes.storage.rst
new file mode 100755
index 0000000..f5b45c5
--- /dev/null
+++ b/src/main/python/docs/rcmes.storage.rst
@@ -0,0 +1,27 @@
+storage Package
+===============
+
+:mod:`db` Module
+----------------
+
+.. automodule:: rcmes.storage.db
+    :members:
+    :undoc-members:
+    :show-inheritance:
+
+:mod:`files` Module
+-------------------
+
+.. automodule:: rcmes.storage.files
+    :members:
+    :undoc-members:
+    :show-inheritance:
+
+:mod:`rcmed` Module
+-------------------
+
+.. automodule:: rcmes.storage.rcmed
+    :members:
+    :undoc-members:
+    :show-inheritance:
+


[47/51] [abbrv] [partial] Adding Jinwon's custom RCMET

Posted by jo...@apache.org.
http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/rcmes/cli/do_rcmes_processing_sub.py
----------------------------------------------------------------------
diff --git a/src/main/python/rcmes/cli/do_rcmes_processing_sub.py b/src/main/python/rcmes/cli/do_rcmes_processing_sub.py
new file mode 100755
index 0000000..aa11f3c
--- /dev/null
+++ b/src/main/python/rcmes/cli/do_rcmes_processing_sub.py
@@ -0,0 +1,730 @@
+#!/usr/local/bin/python
+""" 
+    PENDING DEPRICATION - YOU SHOULD INSTEAD USE THE rcmet.py within the bin dir
+    
+    Module that is used to lauch the rcmes processing from the rcmet_ui.py
+    script.
+"""
+
+import sys
+import datetime
+import numpy
+import numpy.ma as ma 
+import toolkit.plots as plots
+
+import storage.db as db
+import storage.files as files
+import toolkit.process as process
+import toolkit.metrics as metrics
+
+
+def do_rcmes(settings, params, model, mask, options):
+    '''
+    Routine to perform full end-to-end RCMET processing.
+
+    i)    retrieve observations from the database
+    ii)   load in model data
+    iii)  temporal regridding
+    iv)   spatial regridding
+    v)    area-averaging
+    vi)   seasonal cycle compositing
+    vii)  metric calculation
+    viii) plot production
+
+    Input:
+        5 dictionaries which contain a huge argument list with all of the user options 
+        (which can be collected from the GUI)
+
+    settings - dictionary of rcmes run settings::
+    
+        settings = {"cacheDir": string describing directory path,
+                    "workDir": string describing directory path,
+                    "fileList": string describing model file name + path }
+
+    params - dictionary of rcmes run parameters::
+    
+        params = {"obsDatasetId": int( db dataset id ),
+                  "obsParamId": int( db parameter id ),
+                  "startTime": datetime object (needs to change to string + decode),
+                  "endTime": datetime object (needs to change to string + decode),
+                  "latMin": float,
+                  "latMax": float,
+                  "lonMin": float,
+                  "lonMax": float }
+
+    model - dictionary of model parameters::
+        
+        model = {"varName": string describing name of variable to evaluate (as written in model file),
+                 "timeVariable": string describing name of time variable (as written in model file), 	
+                 "latVariable": string describing name of latitude variable (as written in model file), 
+                 "lonVariable": string describing name of longitude variable (as written in model file) } 
+        
+    mask - dictionary of mask specific options (only used if options['mask']=True)::
+        
+        mask = {"latMin": float,
+                "latMax": float,
+                "lonMin": float,
+                "lonMax": float}
+        
+    options - dictionary full of different user supplied options::
+        
+        options = {"regrid": str( 'obs' | 'model' | 'regular' ),
+                   "timeRegrid": str( 'full' | 'annual' | 'monthly' | 'daily' ),
+                   "seasonalCycle": Boolean,
+                   "metric": str('bias'|'mae'|'acc'|'pdf'|'patcor'|'rms'|'diff'),
+                   "plotTitle": string describing title to use in plot graphic,
+                   "plotFilename": basename of file to use for plot graphic i.e. {plotFilename}.png,
+                   "mask": Boolean,
+                   "precip": Boolean }
+
+    Output: image files of plots + possibly data
+    '''
+
+    # check the number of model data files
+    if len(settings['fileList']) < 1:         # no input data file
+        print 'No input model data file. EXIT'
+        sys.exit()
+    # assign parameters that must be preserved throughout the process
+    if options['mask'] == True: 
+        options['seasonalCycle'] = True
+    
+    ###########################################################################
+    # Part 1: retrieve observation data from the database
+    #         NB. automatically uses local cache if already retrieved.
+    ###########################################################################
+    rcmedData = getDataFromRCMED( params, settings, options )
+
+    ###########################################################################
+    # Part 2: load in model data from file(s)
+    ###########################################################################
+    modelData = getDataFromModel( model, settings )
+
+    ###########################################################################
+    # Deal with some precipitation specific options
+    #      i.e. adjust units of model data and set plot color bars suitable for precip
+    ###########################################################################
+    colorbar = 'rainbow'
+    if options['precip'] == True:
+        modelData['data'] = modelData['data']*86400.  # convert from kgm-2s-1 into mm/day
+        colorbar = 'precip2_17lev'
+
+    # set color bar suitable for MODIS cloud data
+    if params['obsParamId'] == 31:
+        colorbar = 'gsdtol'
+
+    ##################################################################################################################
+    # Extract sub-selection of model data for required time range.
+    #   e.g. a single model file may contain data for 20 years,
+    #        but the user may have selected to only analyse data between 2003 and 2004.  
+    ##################################################################################################################
+
+    # Make list of indices where modelData['times'] are between params['startTime'] and params['endTime']
+    modelTimeOverlap = numpy.logical_and((numpy.array(modelData['times'])>=params['startTime']), 
+                                           (numpy.array(modelData['times'])<=params['endTime'])) 
+
+    # Make subset of modelData['times'] using full list of times and indices calculated above
+    modelData['times'] = list(numpy.array(modelData['times'])[modelTimeOverlap])
+
+    # Make subset of modelData['data'] using full model data and indices calculated above 
+    modelData['data'] = modelData['data'][modelTimeOverlap, :, :]
+
+    ##################################################################################################################
+    # Part 3: Temporal regridding
+    #      i.e. model data may be monthly, and observation data may be daily.
+    #           We need to compare like with like so the User Interface asks what time unit the user wants to work with
+    #              e.g. the user may select that they would like to regrid everything to 'monthly' data
+    #                   in which case, the daily observational data will be averaged onto monthly data
+    #                   so that it can be compared directly with the monthly model data.
+    ##################################################################################################################
+    print 'Temporal Regridding Started'
+
+    if(options['timeRegrid']):
+        # Run both obs and model data through temporal regridding routine.
+        #  NB. if regridding not required (e.g. monthly time units selected and model data is already monthly),
+        #      then subroutine detects this and returns data untouched.
+        rcmedData['data'], newObsTimes = process.calc_average_on_new_time_unit(rcmedData['data'], 
+                                                                                        rcmedData['times'],
+                                                                                        unit=options['timeRegrid'])
+        
+        modelData['data'], newModelTimes = process.calc_average_on_new_time_unit(modelData['data'],
+                                                                                          modelData['times'],
+                                                                                          unit=options['timeRegrid'])
+
+    # Set a new 'times' list which describes the common times used for both model and obs after the regrid.
+    if newObsTimes == newModelTimes:
+        times = newObsTimes
+
+    ###########################################################################
+    # Catch situations where after temporal regridding the times in model and obs don't match.
+    # If this occurs, take subset of data from times common to both model and obs only.
+    #   e.g. imagine you are looking at monthly model data,
+    #        the model times are set to the 15th of each month.
+    #        + you are comparing against daily obs data.
+    #        If you set the start date as Jan 1st, 1995 and the end date as Jan 1st, 1996
+    #           -then system will load all model data in this range with the last date as Dec 15th, 1995
+    #            loading the daily obs data from the database will have a last data item as Jan 1st, 1996.
+    #        If you then do temporal regridding of the obs data from daily -> monthly (to match the model)
+    #        Then there will be data for Jan 96 in the obs, but only up to Dec 95 for the model.
+    #              This section of code deals with this situation by only looking at data
+    #              from the common times between model and obs after temporal regridding.           
+    ###########################################################################
+    if newObsTimes != newModelTimes:
+        print 'Warning: after temporal regridding, times from observations and model do not match'
+        print 'Check if this is unexpected.'
+        print 'Proceeding with data from times common in both model and obs.'
+
+        # Create empty lists ready to store data
+        times = []
+        tempModelData = []
+        tempObsData = []
+
+        # Loop through each time that is common in both model and obs
+        for commonTime in numpy.intersect1d(newObsTimes, newModelTimes):
+            # build up lists of times, and model and obs data for each common time
+            #  NB. use lists for data for convenience (then convert to masked arrays at the end)
+            times.append(newObsTimes[numpy.where(numpy.array(newObsTimes) == commonTime)[0][0]])
+            tempModelData.append(modelData['data'][numpy.where(numpy.array(newModelTimes) == commonTime)[0][0], :, :])
+            tempObsData.append(rcmedData['data'][numpy.where(numpy.array(newObsTimes) == commonTime)[0][0], :, :])
+
+        # Convert data arrays from list back into full 3d arrays.
+        modelData['data'] = ma.array(tempModelData)
+        rcmedData['data'] = ma.array(tempObsData)
+
+        # Reset all time lists so representative of the data actually used.
+        newObsTimes = times
+        newModelTimes = times
+        rcmedData['times'] = times
+        modelData['times'] = times
+
+    ##################################################################################################################
+    # Part 4: spatial regridding
+    #         The model and obs are rarely on the same grid.
+    #         To compare the two, you need them to be on the same grid.
+    #         The User Interface asked the user if they'd like to regrid everything to the model grid or the obs grid.
+    #         Alternatively, they could chose to regrid both model and obs onto a third regular lat/lon grid as defined
+    #          by parameters that they enter.
+    #
+    #         NB. from this point on in the code, the 'lats' and 'lons' arrays are common to 
+    #             both rcmedData['data'] and modelData['data'].
+    ##################################################################################################################
+
+    ##################################################################################################################
+    # either i) Regrid obs data to model grid.
+    ##################################################################################################################
+    if options['regrid'] == 'model':
+        # User chose to regrid observations to the model grid
+        modelData['data'], rcmedData['data'], lats, lons = process.regrid_wrapper('0', rcmedData['data'], 
+                                                                                  rcmedData['lats'],
+                                                                                  rcmedData['lons'], 
+                                                                                  modelData['data'],
+                                                                                  modelData['lats'],
+                                                                                  modelData['lons'])
+
+    ##################################################################################################################
+    # or    ii) Regrid model data to obs grid.
+    ##################################################################################################################
+    if options['regrid'] == 'obs':
+        # User chose to regrid model data to the observation grid
+
+        modelData['data'], rcmedData['data'], lats, lons = process.regrid_wrapper('1', rcmedData['data'], 
+                                                                                  rcmedData['lats'], 
+                                                                                  rcmedData['lons'], 
+                                                                                  modelData['data'],
+                                                                                  modelData['lats'], 
+                                                                                  modelData['lons'])
+
+    ##################################################################################################################
+    # or    iii) Regrid both model data and obs data to new regular lat/lon grid.
+    ##################################################################################################################
+    if options['regrid'] == 'regular':
+        # User chose to regrid both model and obs data onto a newly defined regular lat/lon grid
+        # Construct lats, lons from grid parameters
+
+        # Create 1d lat and lon arrays
+        lat = numpy.arange(nLats)*dLat+Lat0
+        lon = numpy.arange(nLons)*dLon+Lon0
+
+        # Combine 1d lat and lon arrays into 2d arrays of lats and lons
+        lons, lats = numpy.meshgrid(lon, lat)
+
+        ###########################################################################################################
+        # Regrid model data for every time
+        #  NB. store new data in a list and convert back to an array at the end.
+        ###########################################################################################################
+        tmpModelData = []
+
+        timeCount = modelData['data'].shape[0]
+        for t in numpy.arange(timeCount):
+            tmpModelData.append(process.do_regrid(modelData['data'][t, :, :],
+                                                          modelData['lats'][:, :],
+                                                          modelData['lons'][:, :],
+                                                          rcmedData['lats'][:, :],
+                                                          rcmedData['lons'][:, :]))
+
+        # Convert list back into a masked array 
+        modelData['data'] = ma.array(tmpModelData)
+
+        ###########################################################################################################
+        # Regrid obs data for every time
+        #  NB. store new data in a list and convert back to an array at the end.
+        ###########################################################################################################
+        tempObsData = []
+        timeCount = rcmedData['data'].shape[0]
+        for t in numpy.arange(timeCount):
+            tempObsData.append(process.do_regrid(rcmedData['data'][t, :, :], 
+                                                         rcmedData['lats'][:, :], 
+                                                         rcmedData['lons'][:, :], 
+                                                         modelData['lats'][:, :], modelData['lons'][:, :]))
+
+        # Convert list back into a masked array 
+        rcmedData['data'] = ma.array(tempObsData)
+
+    ##################################################################################################################
+    # (Optional) Part 5: area-averaging
+    #
+    #      RCMET has the ability to either calculate metrics at every grid point, 
+    #      or to calculate metrics for quantities area-averaged over a defined (masked) region.
+    #
+    #      If the user has selected to perform area-averaging, 
+    #      then they have also selected how they want to define
+    #      the area to average over.
+    #      The options were:
+    #              -define masked region using regular lat/lon bounding box parameters
+    #              -read in masked region from file
+    #
+    #         either i) Load in the mask file (if required)
+    #             or ii) Create the mask using latlonbox  
+    #           then iii) Do the area-averaging
+    #
+    ###############################################################################################################
+    if options['mask'] == True:  # i.e. define regular lat/lon box for area-averaging
+        print 'Using Latitude/Longitude Mask for Area Averaging'
+
+        ###############################################################################################################
+        # Define mask using regular lat/lon box specified by users (i.e. ignore regions where mask = True)
+        ###############################################################################################################
+        mask = numpy.logical_or(numpy.logical_or(lats<=mask['latMin'], lats>=mask['latMax']), 
+                            numpy.logical_or(lons<=mask['lonMin'], lons>=mask['lonMax']))
+
+        ######################m########################################################################################
+        # Calculate area-weighted averages within this region and store in new lists
+        ###############################################################################################################
+        modelStore = []
+        timeCount = modelData['data'].shape[0]
+        for t in numpy.arange(timeCount):
+            modelStore.append(process.calc_area_mean(modelData['data'][t, :, :], lats, lons, mymask=mask))
+
+        obsStore = []
+        timeCount = rcmedData['data'].shape[0]
+        for t in numpy.arange(timeCount):
+            obsStore.append(process.calc_area_mean(rcmedData['data'][t, :, :], lats, lons, mymask=mask))
+  
+        ###############################################################################################################
+        # Now overwrite data arrays with the area-averaged values
+        ###############################################################################################################
+        modelData['data'] = ma.array(modelStore)
+        rcmedData['data'] = ma.array(obsStore)
+
+        ###############################################################################################################
+        # Free-up some memory by overwriting big variables
+        ###############################################################################################################
+        obsStore = 0
+        modelStore = 0
+
+        ##############################################################################################################
+        # NB. if area-averaging has been performed then the dimensions of the data arrays will have changed from 3D to 1D
+        #           i.e. only one value per time.
+        ##############################################################################################################
+
+    ##############################################################################################################
+    # (Optional) Part 6: seasonal cycle compositing
+    #
+    #      RCMET has the ability to calculate seasonal average values from a long time series of data.
+    #
+    #              e.g. for monthly data going from Jan 1980 - Dec 2010
+    #                   If the user selects to do seasonal cycle compositing,
+    #                   this section calculates the mean of all Januarys, mean of all Februarys, mean of all Marchs etc 
+    #                      -result has 12 times.
+    #
+    #      NB. this works with incoming 3D data or 1D data (e.g. time series after avea-averaging).
+    #
+    #          If no area-averaging has been performed in Section 5, 
+    #          then the incoming data is 3D, and the outgoing data will also be 3D, 
+    #          but with the number of times reduced to 12
+    #           i.e. you will get 12 map plots each one showing the average values for a month. (all Jans, all Febs etc)
+    #
+    #
+    #          If area-averaging has been performed in Section 5, 
+    #          then the incoming data is 1D, and the outgoing data will also be 1D, 
+    #          but with the number of times reduced to 12
+    #           i.e. you will get a time series of 12 data points 
+    #                each one showing the average values for a month. (all Jans, all Febs etc).
+    #
+    ##################################################################################################################
+    if options['seasonalCycle'] == True:
+        print 'Compositing data to calculate seasonal cycle'
+
+        modelData['data'] = metrics.calc_annual_cycle_means(modelData['data'], modelData['times'])
+        rcmedData['data'] = metrics.calc_annual_cycle_means(rcmedData['data'], modelData['times'])
+
+    ##################################################################################################################
+    # Part 7: metric calculation
+    #              Calculate performance metrics comparing rcmedData['data'] and modelData['data'].
+    #              All output is stored in metricData regardless of what metric was calculated.
+    #          
+    #      NB. the dimensions of metricData will vary depending on the dimensions of the incoming data
+    #          *and* on the type of metric being calculated.
+    #
+    #      e.g.    bias between incoming 1D model and 1D obs data (after area-averaging) will be a single number. 
+    #              bias between incoming 3D model and 3D obs data will be 2D, i.e. a map of mean bias.
+    #              correlation coefficient between incoming 3D model and 3D obs data will be 1D time series.
+    # 
+    ##################################################################################################################
+
+    if options['metric'] == 'bias':
+        metricData = metrics.calc_bias(modelData['data'], rcmedData['data'])
+        metricTitle = 'Bias'
+
+    if options['metric'] == 'mae':
+        metricData = metrics.calc_mae(modelData['data'], rcmedData['data'])
+        metricTitle = 'Mean Absolute Error'
+
+    if options['metric'] == 'rms':
+        metricData = metrics.calc_rms(modelData['data'], rcmedData['data'])
+        metricTitle = 'RMS error'
+ 
+    if options['metric'] == 'difference':
+        metricData = metrics.calc_difference(modelData['data'], rcmedData['data'])
+        metricTitle = 'Difference'
+
+    #if options['metric'] == 'patcor':
+        #metricData = metrics.calc_pat_cor2D(modelData['data'], rcmedData['data'])
+        #metricTitle = 'Pattern Correlation'
+
+    if options['metric'] == 'nacc':
+        metricData = metrics.calc_anom_corn(modelData['data'], rcmedData['data'])
+        metricTitle = 'Anomaly Correlation'
+
+    if options['metric'] == 'pdf':
+        metricData = metrics.calc_pdf(modelData['data'], rcmedData['data'])
+        metricTitle = 'Probability Distribution Function'
+
+    if options['metric'] == 'coe':
+        metricData = metrics.calc_nash_sutcliff(modelData['data'], rcmedData['data'])
+        metricTitle = 'Coefficient of Efficiency'
+
+    if options['metric'] == 'stddev':
+        metricData = metrics.calc_stdev(modelData['data'])
+        data2 = metrics.calc_stdev(rcmedData['data'])
+        metricTitle = 'Standard Deviation'
+
+    ##################################################################################################################
+    # Part 8: Plot production
+    #
+    #      Produce plots of metrics and obs, model data.
+    #      Type of plot produced depends on dimensions of incoming data.
+    #              e.g. 1D data is plotted as a time series.
+    #                   2D data is plotted as a map.
+    #                   3D data is plotted as a sequence of maps.
+    #
+    ##################################################################################################################
+
+    ##################################################################################################################
+    # 1 dimensional data, e.g. Time series plots
+    ##################################################################################################################
+    if metricData.ndim == 1:
+        print 'Producing time series plots ****'
+        print metricData
+        yearLabels = True
+        #   mytitle = 'Area-average model v obs'
+
+        ################################################################################################################
+        # If producing seasonal cycle plots, don't want to put year labels on the time series plots.
+        ################################################################################################################
+        if options['seasonalCycle'] == True:
+            yearLabels = False
+            mytitle = 'Annual cycle: area-average  model v obs'
+            # Create a list of datetimes to represent the annual cycle, one per month.
+            times = []
+            for m in xrange(12):
+                times.append(datetime.datetime(2000, m+1, 1, 0, 0, 0, 0))
+    
+        ###############################################################################################
+        # Special case for pattern correlation plots. TODO: think of a cleaner way of doing this.
+        # Only produce these plots if the metric is NOT pattern correlation.
+        ###############################################################################################
+    
+        # TODO - Clean up this if statement.  We can use a list of values then ask if not in LIST...
+        #KDW: change the if statement to if else to accommodate the 2D timeseries plots
+        if (options['metric'] != 'patcor')&(options['metric'] != 'acc')&(options['metric'] != 'nacc')&(options['metric'] != 'coe')&(options['metric'] != 'pdf'):
+            # for anomaly and pattern correlation,
+            # can't plot time series of model, obs as these are 3d fields
+            # ^^ This is the reason modelData['data'] has been swapped for metricData in
+            # the following function
+            # TODO: think of a cleaner way of dealing with this.
+    
+            ###########################################################################################
+            # Produce the time series plots with two lines: obs and model
+            ###########################################################################################
+            print 'two line timeseries'
+            #     mytitle = options['plotTitle']
+            mytitle = 'Area-average model v obs'
+            if options['plotTitle'] == 'default':
+                mytitle = metricTitle+' model & obs'
+            #plots.draw_time_series_plot(modelData['data'],times,options['plotFilename']+'both',
+            #                                           settings['workDir'],data2=rcmedData['data'],mytitle=mytitle,
+            #                                           ytitle='Y',xtitle='time',
+            #                                           year_labels=yearLabels)
+            plots.draw_time_series_plot(metricData, times, options['plotFilename']+'both',
+                                                       settings['workDir'], data2, mytitle=mytitle, 
+                                                       ytitle='Y', xtitle='time',
+                                                       year_labels=yearLabels)
+    
+        else: 
+            ###############################################################################################
+            # Produce the metric time series plot (one line only)
+            ###############################################################################################
+            mytitle = options['plotTitle']
+            if options['plotTitle'] == 'default':
+                mytitle = metricTitle+' model v obs'
+            print 'one line timeseries'
+            plots.draw_time_series_plot(metricData, times, options['plotFilename'], 
+                                                       settings['workDir'], mytitle=mytitle, ytitle='Y', xtitle='time',
+                                                       year_labels=yearLabels)
+
+    ###############################################################################################
+    # 2 dimensional data, e.g. Maps
+    ###############################################################################################
+    if metricData.ndim == 2:
+
+        ###########################################################################################
+        # Calculate color bar ranges for data such that same range is used in obs and model plots
+        # for like-with-like comparison.
+        ###########################################################################################
+        mymax = max(rcmedData['data'].mean(axis=0).max(), modelData['data'].mean(axis=0).max())
+        mymin = min(rcmedData['data'].mean(axis=0).min(), modelData['data'].mean(axis=0).min())
+
+        ###########################################################################################
+        # Time title labels need their format adjusting depending on the temporal regridding used,
+        #          e.g. if data are averaged to monthly,
+        #               then want to write 'Jan 2002', 'Feb 2002', etc instead of 'Jan 1st, 2002', 'Feb 1st, 2002'
+        #
+        #  Also, if doing seasonal cycle compositing 
+        #  then want to write 'Jan','Feb','Mar' instead of 'Jan 2002','Feb 2002','Mar 2002' etc 
+        #  as data are representative of all Jans, all Febs etc. 
+        ###########################################################################################
+        if(options['timeRegrid'] == 'daily'):
+            timeFormat = "%b %d, %Y"
+        if(options['timeRegrid'] == 'monthly'):
+            timeFormat = "%b %Y"
+        if(options['timeRegrid'] == 'annual'):
+            timeFormat = "%Y"
+        if(options['timeRegrid'] == 'full'):
+            timeFormat = "%b %d, %Y"
+
+        ###########################################################################################
+        # Special case: when plotting bias data, we also like to plot the mean obs and mean model data.
+        #               In this case, we need to calculate new time mean values for both obs and model.
+        #               When doing this time averaging, we also need to deal with missing data appropriately.
+        #
+        # Classify missing data resulting from multiple times (using threshold data requirment)
+        #   i.e. if the working time unit is monthly data, and we are dealing with multiple months of data
+        #        then when we show mean of several months, we need to decide what threshold of missing data we tolerate
+        #        before classifying a data point as missing data.
+        ###########################################################################################
+
+        ###########################################################################################
+        # Calculate time means of model and obs data
+        ###########################################################################################
+        modelDataMean = modelData['data'].mean(axis=0)
+        obsDataMean = rcmedData['data'].mean(axis=0)
+
+        ###########################################################################################
+        # Calculate missing data masks using tolerance threshold of missing data going into calculations
+        ###########################################################################################
+        obsDataMask = process.create_mask_using_threshold(rcmedData['data'], threshold=0.75)
+        modelDataMask = process.create_mask_using_threshold(modelData['data'], threshold=0.75)
+
+        ###########################################################################################
+        # Combine data and masks into masked arrays suitable for plotting.
+        ###########################################################################################
+        modelDataMean = ma.masked_array(modelDataMean, modelDataMask)
+        obsDataMean = ma.masked_array(obsDataMean, obsDataMask)
+
+        ###########################################################################################
+        # Plot model data
+        ###########################################################################################
+        mytitle = 'Model data: mean between %s and %s' % ( modelData['times'][0].strftime(timeFormat), 
+                                                           modelData['times'][-1].strftime(timeFormat) )
+        plots.draw_map_color_filled(modelDataMean, lats, lons, options['plotFilename']+'model',
+                                                   settings['workDir'], mytitle=mytitle, rangeMax=mymax,
+                                                   rangeMin=mymin, colorTable=colorbar, niceValues=True)
+
+        ###########################################################################################
+        # Plot obs data
+        ###########################################################################################
+        mytitle = 'Obs data: mean between %s and %s' % ( rcmedData['times'][0].strftime(timeFormat), 
+                                                        rcmedData['times'][-1].strftime(timeFormat) )
+        plots.draw_map_color_filled(obsDataMean, lats, lons, options['plotFilename']+'obs',
+                                                   settings['workDir'], mytitle=mytitle, rangeMax=mymax, 
+                                                   rangeMin=mymin, colorTable=colorbar, niceValues=True)
+
+        ###########################################################################################
+        # Plot metric
+        ###########################################################################################
+        mymax = metricData.max()
+        mymin = metricData.min()
+
+        mytitle = options['plotTitle']
+
+        if options['plotTitle'] == 'default':
+            mytitle = metricTitle+' model v obs %s to %s' % ( rcmedData['times'][0].strftime(timeFormat),
+                                                                rcmedData['times'][-1].strftime(timeFormat) )
+
+        plots.draw_map_color_filled(metricData, lats, lons, options['plotFilename'],
+                                                   settings['workDir'], mytitle=mytitle, 
+                                                   rangeMax=mymax, rangeMin=mymin, diff=True, 
+                                                   niceValues=True, nsteps=24)
+
+    ###############################################################################################
+    # 3 dimensional data, e.g. sequence of maps
+    ###############################################################################################
+    if metricData.ndim == 3:
+        print 'Generating series of map plots, each for a different time.'
+        for t in numpy.arange(rcmedData['data'].shape[0]):
+
+            #######################################################################################
+            # Calculate color bar ranges for data such that same range is used in obs and model plots
+            # for like-with-like comparison.
+            #######################################################################################
+            colorRangeMax = max(rcmedData['data'][t, :, :].max(), modelData['data'][t, :, :].max())
+            colorRangeMin = min(rcmedData['data'][t, :, :].min(), modelData['data'][t, :, :].min())
+
+            # Setup the timeTitle
+            timeSlice = times[t]
+            timeTitle = createTimeTitle( options, timeSlice, rcmedData, modelData )
+
+            #######################################################################################
+            # Plot model data
+            #######################################################################################
+            mytitle = 'Model data: mean '+timeTitle
+            plots.draw_map_color_filled(modelData['data'][t, :, :], lats, lons, 
+                                                       options['plotFilename']+'model'+str(t),
+                                                       settings['workDir'], mytitle=mytitle, 
+                                                       rangeMax=colorRangeMax, rangeMin=colorRangeMin,
+                                                       colorTable=colorbar, niceValues=True)
+
+            #######################################################################################
+            # Plot obs data
+            #######################################################################################
+            mytitle = 'Obs data: mean '+timeTitle
+            plots.draw_map_color_filled(rcmedData['data'][t, :, :], lats, lons, 
+                                                       options['plotFilename']+'obs'+str(t),
+                                                       settings['workDir'], mytitle=mytitle, 
+                                                       rangeMax=colorRangeMax, rangeMin=colorRangeMin,
+                                                       colorTable=colorbar, niceValues=True)
+
+            #######################################################################################
+            # Plot metric
+            #######################################################################################
+            mytitle = options['plotTitle']
+
+            if options['plotTitle'] == 'default':
+                mytitle = metricTitle +' model v obs : '+timeTitle
+
+            colorRangeMax = metricData.max()
+            colorRangeMin = metricData.min()
+
+            plots.draw_map_color_filled(metricData[t, :, :], lats, lons, 
+                                                       options['plotFilename']+str(t), settings['workDir'], 
+                                                       mytitle=mytitle, rangeMax=colorRangeMax, rangeMin=colorRangeMin, diff=True,
+                                                       niceValues=True, nsteps=24)
+
+
+def getDataFromRCMED( params, settings, options ):
+    """
+    This function takes in the params, settings, and options dictionaries and will return an rcmedData dictionary.
+    
+    return:
+        rcmedData = {"lats": 1-d numpy array of latitudes,
+                      "lons": 1-d numpy array of longitudes,
+                      "levels": 1-d numpy array of height/pressure levels (surface based data will have length == 1),
+                      "times": list of python datetime objects,
+                      "data": masked numpy arrays of data values}
+    """
+    rcmedData = {}
+    obsLats, obsLons, obsLevs, obsTimes, obsData =  db.extractData(params['obsDatasetId'],
+                                                                                 params['obsParamId'],
+                                                                                 params['latMin'],
+                                                                                 params['latMax'],
+                                                                                 params['lonMin'],
+                                                                                 params['lonMax'],
+                                                                                 params['startTime'],
+                                                                                 params['endTime'],
+                                                                                 settings['cacheDir'],
+										 options['timeRegrid'])
+    rcmedData['lats'] = obsLats
+    rcmedData['lons'] = obsLons
+    rcmedData['levels'] = obsLevs
+    rcmedData['times'] = obsTimes
+    rcmedData['data'] = obsData
+    
+    return rcmedData
+
+def getDataFromModel( model, settings ):
+    """
+    This function takes in the model and settings dictionaries and will return a model data dictionary.
+    
+    return:
+        model = {"lats": 1-d numpy array of latitudes,
+                 "lons": 1-d numpy array of longitudes,
+                 "times": list of python datetime objects,
+                 "data": numpy array containing data from all files}
+    """
+    model = files.read_data_from_file_list(settings['fileList'],
+                                                 model['varName'],
+                                                 model['timeVariable'],
+                                                 model['latVariable'],
+                                                 model['lonVariable'])
+    return model
+
+##################################################################################################################
+# Processing complete
+##################################################################################################################
+
+def createTimeTitle( options, timeSlice, rcmedData, modelData ):
+    """
+    Function that takes in the options dictionary and a specific timeSlice.
+    
+    Return:  string timeTitle properly formatted based on the 'timeRegrid' and 'seasonalCycle' options value.
+    
+    Time title labels need their format adjusting depending on the temporal regridding used
+    
+    e.g. if data are averaged to monthly, then want to write 'Jan 2002', 
+    'Feb 2002', etc instead of 'Jan 1st, 2002', 'Feb 1st, 2002'
+
+    Also, if doing seasonal cycle compositing then want to write 'Jan','Feb',
+    'Mar' instead of 'Jan 2002', 'Feb 2002','Mar 2002' etc as data are 
+    representative of all Jans, all Febs etc. 
+    """
+    if(options['timeRegrid'] == 'daily'):
+        timeTitle = timeSlice.strftime("%b %d, %Y")
+        if options['seasonalCycle'] == True:
+            timeTitle = timeSlice.strftime("%b %d (all years)")
+
+    if(options['timeRegrid'] == 'monthly'):
+        timeTitle = timeSlice.strftime("%b %Y")
+        if options['seasonalCycle'] == True:
+            timeTitle = timeSlice.strftime("%b (all years)")
+
+    if(options['timeRegrid'] == 'annual'):
+        timeTitle = timeSlice.strftime("%Y")
+    
+    if(options['timeRegrid'] == 'full'):
+        minTime = min(min(rcmedData['times']), min(modelData['times']))
+        maxTime = max(max(rcmedData['times']), max(modelData['times']))
+        timeTitle = minTime.strftime("%b %d, %Y")+' to '+maxTime.strftime("%b %d, %Y")
+    
+    return timeTitle
+
+

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/rcmes/cli/rcmet20_cordexAF.py
----------------------------------------------------------------------
diff --git a/src/main/python/rcmes/cli/rcmet20_cordexAF.py b/src/main/python/rcmes/cli/rcmet20_cordexAF.py
new file mode 100755
index 0000000..76ea5e5
--- /dev/null
+++ b/src/main/python/rcmes/cli/rcmet20_cordexAF.py
@@ -0,0 +1,980 @@
+#!/usr/local/bin/python
+
+# 0. Keep both Peter's original and modified libraries
+
+# Python Standard Lib Imports
+import argparse
+import ConfigParser
+import datetime
+import glob
+import os
+import sys
+import json
+
+# 3rd Party Modules
+import numpy as np
+import numpy.ma as ma
+
+# RCMES Imports
+# Appending rcmes via relative path
+#sys.path.append(os.path.abspath('../.'))
+import storage.files_v12
+import storage.rcmed as db
+import toolkit.do_data_prep
+import toolkit.do_metrics_20
+import toolkit.process as process
+from classes import Settings, Model, BoundingBox, SubRegion, GridBox
+
+parser = argparse.ArgumentParser(description='Regional Climate Model Evaluation Toolkit.  Use -h for help and options')
+parser.add_argument('-c', '--config', dest='CONFIG', help='Path to an evaluation configuration file')
+args = parser.parse_args()
+
+
+def getSettings(settings):
+    """
+    This function will collect 2 parameters from the user about the RCMET run they have started.
+    
+    Input::
+        settings - Empty Python Dictionary they will be used to store the user supplied inputs
+        
+    Output::
+        None - The user inputs will be added to the supplied dictionary.
+    """
+    settings['workDir'] = os.path.abspath(raw_input('Please enter workDir:\n> '))
+    if os.path.isdir(settings['workDir']):
+        pass
+    else:
+        makeDirectory(settings['workDir'])
+    
+    settings['cacheDir'] = os.path.abspath(raw_input('Please enter cacheDir:\n> '))
+    if os.path.isdir(settings['cacheDir']):
+        pass
+    else:
+        makeDirectory(settings['cacheDir'])    
+
+def setSettings(settings, config):
+    """
+    This function is used to set the values within the 'SETTINGS' dictionary when a user provides an external
+    configuration file.
+    
+    Input::
+        settings - Python Dictionary object that will collect the key : value pairs
+        config - A configparse object that contains the external config values
+    
+    Output::
+        None - The settings dictionary will be updated in place.
+    """
+    pass
+
+def makeDirectory(directory):
+    print "%s doesn't exist.  Trying to create it now." % directory
+    try:
+        os.mkdir(directory)
+    except OSError:
+        print "This program cannot create dir: %s due to permission issues." % directory
+        sys.exit()
+
+def rcmet_cordexAF():
+    """
+     Command Line User interface for RCMET.
+     Collects user options then runs RCMET to perform processing.
+     Duplicates job of GUI.
+     Peter Lean   March 2011
+     
+     Jul 2, 2011
+     Modified to process multiple models
+     Follow the logical variable "GUI" for interactive operations
+     
+     July 6, 2012: Jinwon Kim
+     * This version works with do_rcmes_processing_sub_v12cmip5multi.py *
+     Re-gridded data output options include both binary and netCDF.
+      Interpolation of both model and obs data onto a user-define grid system has been completed.
+      Allow generic treatment of both multiple model and observation data
+       * longitudes/latitudes are defined for individual datasets
+       * the metadata for observations will utilized Cameron's updates
+      Still works for the global observation coverage scheme (may involve missing/bad values)
+     * this version requires that all obs data are to be defined at the same temporal grid (monthly, daily)
+     * this version requires that all mdl data are to be defined at the same temporal grid (monthly, daily)
+    """
+    print 'Start RCMET'
+
+
+    """  COMMENTED OUT UN-USED CODE
+    # Specify GUI or nonGUI version [True/False]
+    GUI = False
+    user_input = int(raw_input('Enter interactive/specified run: [0/1]: \n> '))
+    if user_input == 0:
+        GUI = True
+
+    # 1.   Prescribe the directories and variable names for processing
+    #dir_rcmet = '/nas/share3-wf/jinwonki/rcmet'   # The path to the python script to process the cordex-AF data
+    if GUI: 
+        workdir = os.path.abspath(raw_input('Please enter workdir:\n> '))
+        cachedir = os.path.abspath(raw_input('Please enter cachedir:\n> '))
+        mdlDataDir = os.path.abspath(raw_input('Enter the model data directory (e.g., ~/data/cordex-af):\n> '))
+        modelVarName = raw_input('Enter the model variable name from above:\n> ')     # Input model variable name
+        modelLatVarName = raw_input('Enter the Latitude variable name:\n> ')     # Input model variable name
+        modelLonVarName = raw_input('Enter the Longitude variable name:\n> ')     # Input model variable name
+        modelTimeVarName = raw_input('Enter the Time variable name:\n> ')     # Input model variable name
+        mdlTimeStep = raw_input('Enter the model Time step (e.g., daily, monthly):\n> ')     # Input model variable name
+    else:
+        modelVarName = 'pr'
+        #modelVarName='tas'
+        #modelVarName='tasmax'
+        #modelVarName='tasmin'
+        #modelVarName='clt'
+        mdlTimeStep = 'monthly'
+        modelLatVarName = 'lat'
+        modelLonVarName = 'lon'
+        modelTimeVarName = 'time' # mdl var names for lat, long, & time coords
+        workdir = '../cases/cordex-af/wrk2'
+        cachedir = '../cases/cordex-af/cache'
+        mdlDataDir = '/nas/share4-cf/jinwonki/data/cordex-af'
+    if modelVarName == 'pr':
+        precipFlag = True
+    else:
+        precipFlag = False
+    """
+    # 2.   Metadata for the RCMED database
+    
+    # TODO:  WORK OUT THE RCMED PARAMETERS API USAGE - Prolly need to move this into a PARAMETERS Object
+    """  COMMENTED OUT HARDCODED VALUES
+    try:
+        parameters = db.getParams()
+    except Exception:
+        sys.exit()
+    
+    datasets = [parameter['longname'] for parameter in parameters]
+    
+    #   NOTE: the list must be updated whenever a new dataset is added to RCMED (current as of 11/22/2011)
+    db_datasets = ['TRMM', 'ERA-Interim', 'AIRS', 'MODIS', 'URD', 'CRU3.0', 'CRU3.1']
+    db_dataset_ids = [3, 1, 2, 5, 4, 6, 10]
+    db_dataset_startTimes = [datetime.datetime(1998, 1, 1, 0, 0, 0, 0), datetime.datetime(1989, 01, 01, 0, 0, 0, 0), datetime.datetime(2002, 8, 31, 0, 0, 0, 0), \
+                             datetime.datetime(2000, 2, 24, 0, 0, 0, 0), datetime.datetime(1948, 1, 1, 0, 0, 0, 0), datetime.datetime(1901, 1, 1, 0, 0, 0, 0), \
+                             datetime.datetime(1901, 1, 1, 0, 0, 0, 0)]
+    db_dataset_endTimes = [datetime.datetime(2010, 1, 1, 0, 0, 0, 0), datetime.datetime(2009, 12, 31, 0, 0, 0, 0), datetime.datetime(2010, 1, 1, 0, 0, 0, 0), \
+                           datetime.datetime(2010, 5, 30, 0, 0, 0, 0), datetime.datetime(2010, 1, 1, 0, 0, 0, 0), datetime.datetime(2006, 12, 1, 0, 0, 0, 0), \
+                           datetime.datetime(2009, 12, 31, 0, 0, 0, 0)] #adjusted the last end_time to 31-DEC-2009 instead of 01-DEC-2009
+    db_parameters = [['pr_day', 'pr_mon'], ['T2m', 'Tdew2m'], ['T2m'], ['cldFrac'], ['pr_day'], ['T2m', 'T2max', 'T2min', 'pr'], ['pr', 'T2m', 'T2max', 'T2min', 'cldFrac']]
+    db_parameter_ids = [[14, 36], [12, 13], [15], [31], [30], [33, 34, 35, 32], [37, 38, 39, 41, 42]]
+    
+     # Assign the obs dataset & and its attributes from the RCNMED dataset/parameter list above
+    idObsDat = []
+    idObsDatPara = []
+    obsTimeStep = []
+    
+    if GUI:
+        for n in np.arange(len(db_datasets)):
+            print n, db_datasets[n]
+
+        numOBSs = int(raw_input('Enter the number of observed datasets to be utilized:\n> '))
+        # assign the obs dataset id and the parameter id defined within the dataset into the lists "idObsDat" & "idObsDatPara".
+        for m in np.arange(numOBSs):
+            idObsDat.append(input=int(raw_input('Enter the observed dataset number from above:\n> ')))
+            for l in np.arange(len(db_parameters[input])):
+                print l, db_parameters[idObsDat][l]
+        
+            idObsDatPara.append(int(raw_input('Enter the observed data parameter from above:\n> ')))
+    else:
+        numOBSs = 2
+        idObsDat = [0, 6]
+        idObsDatPara = [1, 0]
+        obsTimeStep = ['monthly', 'monthly']
+        #numOBSs=1; idObsDat=[6]; idObsDatPara=[0]; obsTimeStep=['monthly']
+        #numOBSs=1; idObsDat=[5]; idObsDatPara=[3]; obsTimeStep=['monthly']
+        #numOBSs=1; idObsDat=[0]; idObsDatPara=[1]; obsTimeStep=['monthly']
+        ##### Data table to be replace with the use of metadata #################################
+        #idObsDat=0; idObsDatPara=0; obsTimeStep='monthly'                 # TRMM daily
+        #idObsDat=0; idObsDatPara=1; obsTimeStep='monthly'                 # TRMM monthly
+        #idObsDat=3; idObsDatPara=0; obsTimeStep='monthly'                 # MODIS cloud fraction
+        #idObsDat=5; idObsDatPara=0; obsTimeStep='monthly'                 # CRU3.0 - t2bar
+        #idObsDat=5; idObsDatPara=1; obsTimeStep='monthly'                 # CRU3.0 - t2max
+        #idObsDat=5; idObsDatPara=2; obsTimeStep='monthly'                 # CRU3.0 - t2min
+        #idObsDat=5; idObsDatPara=3; obsTimeStep='monthly'                 # CRU3.0 - pr
+        #idObsDat=6; idObsDatPara=0; obsTimeStep='monthly'                 # CRU3.1 - pr
+        #idObsDat=6; idObsDatPara=1; obsTimeStep='monthly'                 # CRU3.1 - t2bar
+        #idObsDat=6; idObsDatPara=2; obsTimeStep='monthly'                 # CRU3.1 - t2max
+        #idObsDat=6; idObsDatPara=3; obsTimeStep='monthly'                 # CRU3.1 - t2min
+        #idObsDat=6; idObsDatPara=4; obsTimeStep='monthly'                 # CRU3.1 - cloud fraction
+        ##### Data table to be replace with the use of metadata #################################
+    # assign observed data info: all variables are 'list'
+    obsDataset = []
+    data_type = []
+    obsDatasetId = []
+    obsParameterId = []
+    obsStartTime = []
+    obsEndTime = []
+    obsList = []
+
+    for m in np.arange(numOBSs):
+        obsDataset.append(db_datasets[idObsDat[m]])# obsDataset=db_datasets[idObsDat[m]]
+        data_type.append(db_parameters[idObsDat[m]][idObsDatPara[m]])# data_type = db_parameters[idObsDat[m]][idObsDatPara[m]]
+        obsDatasetId.append(db_dataset_ids[idObsDat[m]])# obsDatasetId = db_dataset_ids[idObsDat[m]]
+        obsParameterId.append(db_parameter_ids[idObsDat[m]][idObsDatPara[m]])# obsParameterId = db_parameter_ids[idObsDat[m]][idObsDatPara[m]]
+        obsStartTime.append(db_dataset_startTimes[idObsDat[m]])# obsStartTime = db_dataset_startTimes[idObsDat[m]]
+        obsEndTime.append(db_dataset_endTimes[idObsDat[m]])# obsEndTime = db_dataset_endTimes[idObsDat[m]]
+        obsList.append(db_datasets[idObsDat[m]] + '_' + db_parameters[idObsDat[m]][idObsDatPara[m]])
+                        TRMM_pr_mon
+                        CRU3.1_pr
+        
+    print'obsDatasetId,obsParameterId,obsList,obsStartTime,obsEndTime= ', obsDatasetId, obsParameterId, obsStartTime, obsEndTime# return -1
+    obsStartTmax = max(obsStartTime)
+    obsEndTmin = min(obsEndTime)
+    
+    ###################################################################
+    # 3.   Load model data and assign model-related processing info
+    ###################################################################
+    # 3a:  construct the list of model data files
+    if GUI:
+        FileList_instructions = raw_input('Enter model file (specify multiple files using wildcard: e.g., *pr.nc):\n> ')
+    else:
+        FileList_instructions = '*' + modelVarName + '.nc'
+        #FileList_instructions = '*' + 'ARPEGE51' + '*' + modelVarName + '.nc'
+    FileList_instructions = mdlDataDir + '/' + FileList_instructions
+    FileList = glob.glob(FileList_instructions)
+    n_infiles = len(FileList)
+    #print FileList_instructions,n_infiles,FileList
+
+    # 3b: (1) Attempt to auto-detect latitude and longitude variable names (removed in rcmes.files_v12.find_latlon_var_from_file)
+    #     (2) Find lat,lon limits from first file in FileList              (active)
+    file_type = 'nc'
+    laName = modelLatVarName
+    loName = modelLonVarName
+    latMin = ma.zeros(n_infiles)
+    latMax = ma.zeros(n_infiles)
+    lonMin = ma.zeros(n_infiles)
+    lonMax = ma.zeros(n_infiles)
+    
+    for n in np.arange(n_infiles):
+        ifile = FileList[n]
+        status, latMin[n], latMax[n], lonMin[n], lonMax[n] = storage.files_v12.find_latlon_var_from_file(ifile, file_type, laName, loName)
+        print 'Min/Max Lon & Lat: ', n, lonMin[n], lonMax[n], latMin[n], latMax[n]
+    if GUI:
+        instruction = raw_input('Do the long/lat ranges all model files match? (y/n)\n> ')
+
+    else:
+        instruction = 'y'
+    print instruction
+    if instruction != 'y':
+        print 'Long & lat ranges of model data files do not match: EXIT'; return -1
+    latMin = latMin[0]
+    latMax = latMax[0]
+    lonMin = lonMin[0]
+    lonMax = lonMax[0]
+    print 'Min/Max Lon & Lat:', lonMin, lonMax, latMin, latMax
+    print ''
+
+
+
+    # TODO:  Work out how to handle when model files have different ranges for Latitude, Longitude or Time
+
+    # 3c: Decode model times into a python datetime object (removed in rcmes.process_v12.decode_model_times; var name is hardwired in 1.)
+    #     Check the length of model data period. Retain only the files that contain the entire 20yr records
+    #     Also specify the model data time step. Not used for now, but will be used to control the selection of the obs data (4) & temporal regridding (7).
+    # Note July 25, 2011: model selection for analysis is moved and is combined with the determination of the evaluation period
+    timeName = modelTimeVarName
+    mdldataTimeStep = 'monthly'
+    file_type = 'nc'
+    n_mos = ma.zeros(n_infiles)
+    newFileList = []
+    mdlStartT = []
+    mdlEndT = []
+    mdlName = []
+    k = 0
+
+    for n in np.arange(n_infiles):
+        # extract model names for identification
+        # Provided that model results are named as 
+        # mdlDataDir/projectName_mdlName_(some other information)_variableName.nc
+        ifile = FileList[n]
+        name = ifile[len(mdlDataDir)+1:len(mdlDataDir)+20]  # +1 excludes '/'
+        name_wo_project = name[name.find('_')+1:]   # file name without its project name
+        
+        mdlName.append(name_wo_project[0:name_wo_project.find('_')]) # print'model name= ',name[0:name.find('_')]
+        # extract the temporal coverage of each model data file and the related time parameters
+        
+        modelTimes = process.getModelTimes(ifile, timeName)
+        
+        # NOW WE HAVE MODEL TIMES...WHAT ARE THEY USED FOR???
+        
+        # THIS APPEARS TO BE A MONTHLY SPECIFIC IMPLEMENTATAION DETAIL
+        n_mos[n] = len(modelTimes)
+        
+        # PARSE OUT THE Min(YEAR and MONTH) and Max(YEAR and MONTH)
+        # Could this merely be a MinTime and MaxTime so essentially a TimeRange?
+        
+        
+        y0 = min(modelTimes).strftime("%Y")
+        m0 = min(modelTimes).strftime("%m")
+        y1 = max(modelTimes).strftime("%Y")
+        m1 = max(modelTimes).strftime("%m")
+        
+        
+        
+        if mdlTimeStep == 'monthly':
+            d0 = 1
+            d1 = 1
+        else:
+            d0 = min(modelTimes).strftime("%d")
+            d1 = max(modelTimes).strftime("%d")
+            
+        minMdlT = datetime.datetime(int(y0), int(m0), int(d0), 0, 0, 0, 0)
+        maxMdlT = datetime.datetime(int(y1), int(m1), int(d1), 0, 0, 0, 0)
+        
+        # AFTER all the Datetime to string to int and back to datetime, we are left with the ModelTimeStart and ModelTimeEnd
+        mdlStartT.append(minMdlT)
+        mdlEndT.append(maxMdlT)
+
+    print 'Mdl Times decoded: n= ', n, ' Name: ', mdlName[n], ' length= ', len(modelTimes), \
+          ' 1st mdl time: ', mdlStartT[n].strftime("%Y/%m"), ' Lst mdl time: ', mdlEndT[n].strftime("%Y/%m")
+
+    #print 'mdlStartT'; print mdlStartT; print 'mdlEndT'; print mdlEndT
+    #print max(mdlStartT),min(mdlEndT)
+    
+    # get the list of models to be evaluated and the period of evaluation
+    # July 25, 2011: the selection of model and evaluation period are modified:
+    #   1. Default: If otherwise specified, select the longest overlapping period and exclude the model outputs that do not cover the default period
+    #   2. MaxMdl : Select the max number of models for evaluation. The evaluation period may be reduced
+    #   3. PrdSpc : The evaluation period is specified and the only data files that cover the specified period are included for evaluation.
+    #   4. Note that the analysis period is limited to the full annual cycle, i.e., starts in Jan and ends in Dec.
+    # 5:   Select the period for evaluation/analysis (defaults to overlapping times between model and obs)
+    # 5a: First calculate the overlapping period
+    startTime = []
+    endTime = []
+    
+    for n in np.arange(n_infiles):
+        startTime.append(max(mdlStartT[n], obsStartTmax))
+        endTime.append(min(mdlEndT[n], obsEndTmin))
+        
+        #print n,mdlStartT[n],mdlEndT[n],startTime[n],endTime[n]
+        yy = int(startTime[n].strftime("%Y"))
+        mm = int(startTime[n].strftime("%m"))
+        
+        if mm != 1:
+            yy = yy + 1
+            mm = 1
+
+        startTime[n] = datetime.datetime(int(yy), int(mm), 1, 0, 0, 0, 0)
+        yy = int(endTime[n].strftime("%Y"))
+        mm = int(endTime[n].strftime("%m"))
+        
+        if mm != 12:
+            yy = yy - 1
+            mm = 12
+        
+        endTime[n] = datetime.datetime(int(yy), int(mm), 1, 0, 0, 0, 0)
+        print mdlName[n], ' common start/end time: ', startTime[n], endTime[n]
+
+    maxAnlT0 = min(startTime)
+    maxAnlT1 = max(endTime)
+    minAnlT0 = max(startTime)
+    minAnlT1 = min(endTime)
+    #print startTime; print endTime
+    print 'max common period: ', maxAnlT0, '-', maxAnlT1; print 'min common period: ', minAnlT0, '-', minAnlT1
+    
+    # 5b: Determine the evaluation period and the models to be evaluated
+    if GUI:
+        print 'Select evaluation period. Depending on the selected period, the number of models may vary. See above common start/end times'
+        print 'Enter: 1 for max common period, 2 for min common period, 3 for your own choice: Note that all period starts from Jan and end at Dec'
+        choice = int(raw_input('Enter your choice from above [1,2,3] \n> '))
+    else:
+        choice = 3
+    if choice == 1:
+        startTime = maxAnlT0
+        endTime = maxAnlT1
+        print 'Maximum(model,obs) period is selected. Some models will be dropped from evaluation'
+        
+    if choice == 2:
+        startTime = minAnlT0
+        endTime = minAnlT1
+        print 'Minimum(model,obs) period is selected. All models will be evaluated except there are problems'
+      
+    if choice == 3:
+        startYear = int(raw_input('Enter start year YYYY \n'))
+        endYear = int(raw_input('Enter end year YYYY \n'))
+        
+        if startYear < int(maxAnlT0.strftime("%Y")):
+            print 'Your start year is earlier than the available data period: EXIT; return -1'
+            
+        if endYear > int(maxAnlT1.strftime("%Y")):
+            print 'Your end year is later than the available data period: EXIT; return -1'
+            
+        # CGOODALE - Updating the Static endTime to be 31-DEC
+        startTime = datetime.datetime(startYear, 1, 1, 0, 0)
+        endTime = datetime.datetime(endYear, 12, 31, 0, 0)
+        print 'Evaluation will be performed for a user-selected period'
+        
+    print 'Final: startTime/endTime: ', startTime, '/', endTime
+
+
+    # select model data for analysis and analysis period
+    k = 0
+    newFileList = []
+    name = []
+    print 'n_infiles= ', n_infiles
+    for n in np.arange(n_infiles): 
+        ifile = FileList[n]
+        nMos = n_mos[n]
+        print mdlName[n], n_mos[n], mdlStartT[n], startTime, mdlEndT[n], endTime
+        
+        # LOOP OVER THE MODEL START TIMES AND DETERMINE WHICH TO KEEP based on user entered Start/End Years
+        
+        if mdlStartT[n] <= startTime and mdlEndT[n] >= endTime:
+            newFileList.append(ifile)
+            name.append(mdlName[n])
+            k += 1
+    FileList = newFileList
+    newFileList = 0
+    FileList.sort()
+    print 'the number of select files = ', len(FileList)
+    mdlName = name
+    numMDLs = len(FileList)
+    
+    for n in np.arange(numMDLs):
+        print n, mdlName[n], FileList[n]
+    
+    # 6:   Select spatial regridding options
+    # PULLED DOWN INTO THE MAIN Loop
+    regridOption = 2      # for multi-model cases, this option can be selected only when all model data are on the same grid system.
+    naLons = 1
+    naLats = 1
+    dLon = 0.5
+    dLat = 0.5  # these are dummies for regridOption = 1 & 2
+    
+    if GUI:
+        print 'Spatial regridding options: '
+        print '[0] Use Observational grid'
+        print '[1] Use Model grid'
+        print '[2] Define new regular lat/lon grid to use'
+        regridOption = int(raw_input('Please make a selection from above:\n> '))
+        
+    if np.logical_or(regridOption > 2, regridOption < 0):
+        print 'Error: Non-existing spatial regridding option. EXIT'; return -1, -1, -1, -1
+    # specify the regridding option
+    if regridOption == 0: 
+        regridOption = 'obs'
+    if regridOption == 1:
+        regridOption = 'model'
+    # If requested, get new grid parameters: min/max long & lat values and their uniform increments; the # of longs and lats
+    
+    if regridOption == 2:
+        regridOption = 'regular'
+        dLon = 0.44
+        dLat = 0.44
+        lonMin = -24.64
+        lonMax = 60.28
+        latMin = -45.76
+        latMax = 42.24
+        naLons = int((lonMax - lonMin + 1.e-5 * dLon) / dLon) + 1
+        naLats = int((latMax - latMin + 1.e-5 * dLat) / dLat) + 1
+
+    if GUI:
+        if regridOption == 2:
+            regridOption = 'regular'
+            lonMin = float(raw_input('Please enter the longitude at the left edge of the domain:\n> '))
+            lonMax = float(raw_input('Please enter the longitude at the right edge of the domain:\n> '))
+            latMin = float(raw_input('Please enter the latitude at the lower edge of the domain:\n> '))
+            latMax = float(raw_input('Please enter the latitude at the upper edge of the domain:\n> '))
+            dLon = float(raw_input('Please enter the longitude spacing (in degrees) e.g. 0.5:\n> '))
+            dLat = float(raw_input('Please enter the latitude spacing (in degrees) e.g. 0.5:\n> '))
+            nLons = int((lonMax - lonMin + 1.e-5 * dLon) / dLon) + 1
+            nLats = int((latMax - latMin + 1.e-5 * dLat) / dLat) + 1
+            
+    print 'Spatial re-grid data on the ', regridOption, ' grid'
+
+
+    # 7:   Temporal regridding: Bring the model and obs data to the same temporal grid for comparison
+    #      (e.g., daily vs. daily; monthly vs. monthly)
+    timeRegridOption = 2
+    if GUI == True:
+        print 'Temporal regridding options: i.e. averaging from daily data -> monthly data'
+        print 'The time averaging will be performed on both model and observational data.'
+        print '[0] Calculate time mean for full period.'
+        print '[1] Calculate annual means'
+        print '[2] Calculate monthly means'
+        print '[3] Calculate daily means (from sub-daily data)'
+        timeRegridOption = int(raw_input('Please make a selection from above:\n> '))
+    # non-existing option is selected
+    if np.logical_or(timeRegridOption > 3, timeRegridOption < 0):
+        print 'Error: ', timeRegridOption, ' is a non-existing temporal regridding option. EXIT'; return -1, -1, -1, -1
+    # specify the temporal regridding option
+    if timeRegridOption == 0: 
+        timeRegridOption = 'mean over all times: i.e., annual-mean climatology'
+        
+    if timeRegridOption == 1: 
+        timeRegridOption = 'annual'
+        
+    if timeRegridOption == 2: 
+        timeRegridOption = 'monthly'
+        
+    if timeRegridOption == 3: 
+        timeRegridOption = 'daily'
+        
+    print 'timeRegridOption= ', timeRegridOption
+    
+
+    #******************************************************************************************************************
+    # 8:   Select whether to perform Area-Averaging over masked region
+    #      If choice != 'y', the analysis/evaluation will be performed at every grid points within the analysis domain
+    #******************************************************************************************************************
+    numSubRgn = 21
+    subRgnLon0 = ma.zeros(numSubRgn)
+    subRgnLon1 = ma.zeros(numSubRgn)
+    subRgnLat0 = ma.zeros(numSubRgn)
+    subRgnLat1 = ma.zeros(numSubRgn)
+    # 21 rgns: SMHI11 + W+C+E. Mediterrenean (JK) + 3 in UCT (Western Sahara, Somalia, Madagascar) + 4 in Mideast
+    subRgnLon0 = [-10.0, 0.0, 10.0, 20.0, -19.3, 15.0, -10.0, -10.0, 33.9, 44.2, 10.0, 10.0, 30.0, 13.6, 13.6, 20.0, 43.2, 33.0, 45.0, 43.0, 50.0]   # HYB 21 rgns
+    subRgnLon1 = [  0.0, 10.0, 20.0, 33.0, -10.2, 30.0, 10.0, 10.0, 40.0, 51.8, 25.0, 25.0, 40.0, 20.0, 20.0, 35.7, 50.3, 40.0, 50.0, 50.0, 58.0]   # HYB 21 rgns
+    subRgnLat0 = [ 29.0, 29.0, 25.0, 25.0, 12.0, 15.0, 7.3, 5.0, 6.9, 2.2, 0.0, -10.0, -15.0, -27.9, -35.0, -35.0, -25.8, 25.0, 28.0, 13.0, 20.0]   # HYB 21 rgns
+    subRgnLat1 = [ 36.5, 37.5, 32.5, 32.5, 20.0, 25.0, 15.0, 7.3, 15.0, 11.8, 10.0, 0.0, 0.0, -21.4, -27.9, -21.4, -11.7, 35.0, 35.0, 20.0, 27.5]   # HYB 21 rgns
+    subRgnName = ['R01', 'R02', 'R03', 'R04', 'R05', 'R06', 'R07', 'R08', 'R09', 'R10', 'R11', 'R12', 'R13', 'R14', 'R15', 'R16', 'R17', 'R18', 'R19', 'R20', 'R21']   # HYB 21 rgns
+    print subRgnName
+
+    maskOption = 0
+    maskLonMin = 0
+    maskLonMax = 0
+    maskLatMin = 0
+    maskLatMax = 0
+    rgnSelect = 0
+    
+    choice = 'y'
+
+    if GUI:
+        choice = raw_input('Do you want to calculate area averages over a masked region of interest? [y/n]\n> ').lower()
+        if choice == 'y':
+            maskOption = 1
+            #print '[0] Load spatial mask from file.'
+            #print '[1] Enter regular lat/lon box to use as mask.'
+            #print '[2] Use pre-determined mask ranges'
+            #try:
+            #  maskInputChoice = int(raw_input('Please make a selection from above:\n> '))
+            #if maskInputChoice==0:    # Read mask from file
+            #  maskFile = raw_input('Please enter the file containing the mask data (including full path):\n> ') 
+            #  maskFileVar = raw_input('Please enter variable name of the mask data in the file:\n> ')
+            #if maskInputChoice==1:
+            #  maskLonMin = float(raw_input('Please enter the longitude at the left edge of the mask region:\n> '))
+            #  maskLonMax = float(raw_input('Please enter the longitude at the right edge of the mask region:\n> '))
+            #  maskLatMin = float(raw_input('Please enter the latitude at the lower edge of the mask region:\n> '))
+            #  maskLatMax = float(raw_input('Please enter the latitude at the upper edge of the mask region:\n> '))
+    ## maskInputChoice = 0/1: Load spatial mask from file/specifify with long,lat range'
+
+    
+    if choice == 'y':
+        maskOption = 1
+        maskInputChoice = 1
+        if maskInputChoice == 1:
+            for n in np.arange(numSubRgn):
+                print 'Subregion [', n, '] ', subRgnName[n], subRgnLon0[n], 'E - ', subRgnLon1[n], ' E: ', subRgnLat0[n], 'N - ', subRgnLat1[n], 'N'
+            rgnSelect = 3
+            if GUI:
+                rgnSelect = raw_input('Select the region for which regional-mean timeseries are to be analyzed\n')
+
+        #if maskInputChoice==0:    # Read mask from file
+        #   maskFile = 'maskFileNameTBD'
+        #   maskFileVar = 'maskFileVarTBD'
+    
+    # 9.   Select properties to evaluate/analyze
+    # old Section 8: Select: calculate seasonal cycle composites
+    
+    seasonalCycleOption = 'y'
+    if GUI:
+        seasonalCycleOption = raw_input('Composite the data to show seasonal cycles? [y/n]\n> ').lower()
+    if seasonalCycleOption == 'y':
+        seasonalCycleOption = 1
+    else:
+        seasonalCycleOption = 0
+
+      
+    # Section 9: Select Peformance Metric
+    choice = 0
+    if GUI:
+        print 'Metric options'
+        print '[0] Bias: mean bias across full time range'
+        print '[1] Mean Absolute Error: across full time range'
+        print '[2] Difference: calculated at each time unit'
+        print '[3] Anomaly Correlation> '
+        print '[4] Pattern Correlation> '
+        print '[5] TODO: Probability Distribution Function similarity score'
+        print '[6] RMS error'
+        choice = int(raw_input('Please make a selection from the options above\n> '))
+    # assign the metrics to be calculated
+    if choice == 0: 
+        metricOption = 'bias'
+        
+    if choice == 1: 
+        metricOption = 'mae'
+        
+    if choice == 2:
+        metricOption = 'difference'
+    
+    if choice == 3:
+        metricOption = 'acc'
+    
+    if choice == 4:
+        metricOption = 'patcor'
+    
+    if choice == 5:
+        metricOption = 'pdf'
+    
+    if choice == 6:
+        metricOption = 'rms'
+
+
+    #  Select output option
+    FoutOption = 0
+    if GUI:
+        choice = raw_input('Option for output files of obs/model data: Enter no/bn/nc\n> ').lower()
+        if choice == 'no':
+            FoutOption = 0
+        if choice == 'bn':
+            FoutOption = 1
+        if choice == 'nc':
+            FoutOption = 2
+
+    ###################################################################################################
+    # Section 11: Select Plot Options
+    ###################################################################################################
+
+
+    modifyPlotOptions = 'no'
+    plotTitle = modelVarName + '_'
+    plotFilenameStub = modelVarName + '_'
+    
+    if GUI:
+        modifyPlotOptions = raw_input('Do you want to modify the default plot options? [y/n]\n> ').lower()
+        
+    if modifyPlotOptions == 'y':
+        plotTitle = raw_input('Enter the plot title:\n> ')
+        plotFilenameStub = raw_input('Enter the filename stub to use, without suffix e.g. files will be named <YOUR CHOICE>.png\n> ')
+
+
+
+    print'------------------------------'
+    print'End of preprocessor: Run RCMET'
+    print'------------------------------'
+
+    """
+
+
+    # Section 13: Run RCMET, passing in all of the user options
+
+    # TODO: **Cameron** Add an option to write a file that includes all options selected before this step to help repeating the same analysis.
+    # read-in and regrid both obs and model data onto a common grid system (temporally & spatially).
+    # the data are passed to compute metrics and plotting
+    # numOBSs & numMDLs will be increased by +1 for multiple obs & mdls, respectively, to accomodate obs and model ensembles
+    # nT: the number of time steps in the data
+    
+    
+#    numOBS, numMDL, nT, ngrdY, ngrdX, Times, obsData, mdlData, obsRgn, mdlRgn, obsList, mdlList = toolkit.do_data_prep.prep_data(\
+#         cachedir, workdir, \
+#         obsList, obsDatasetId, obsParameterId, \
+#         startTime, endTime, \
+#         latMin, latMax, lonMin, lonMax, dLat, dLon, naLats, naLons, \
+#         FileList, \
+#         numSubRgn, subRgnLon0, subRgnLon1, subRgnLat0, subRgnLat1, subRgnName, \
+#         modelVarName, precipFlag, modelTimeVarName, modelLatVarName, modelLonVarName, \
+#         regridOption, timeRegridOption, maskOption, FoutOption)
+
+    """
+    Parameter to Object Mapping
+    cachedir = settings.cacheDir
+    workdir = settings.cacheDir
+    obsList = obsDatasetList.each['longname']
+    """
+
+    numOBS, numMDL, nT, ngrdY, ngrdX, Times, obsData, mdlData, obsRgn, mdlRgn, obsList, mdlList = toolkit.do_data_prep(\
+          settings, obsDatasetList, gridBox, models, subRegionTuple)
+    
+    """
+    print 'Input and regridding of both obs and model data are completed. now move to metrics calculations'
+    # Input and regridding of both obs and model data are completed. now move to metrics calculations
+
+    print '-----------------------------------------------'
+    print 'mdlID  numMOs  mdlStartTime mdlEndTime fileName'
+    print '-----------------------------------------------'
+    
+    """
+    mdlSelect = numMDL - 1                      # numMDL-1 corresponds to the model ensemble
+
+    """
+    if GUI:
+        n = 0
+        while n < len(mdlList):
+            print n, n_mos[n], mdlStartT[n], mdlEndT[n], FileList[n][35:]
+            n += 1
+        ask = 'Enter the model ID to be evaluated from above:  ', len(FileList), ' for the model-ensemble: \n'
+        mdlSelect = int(raw_input(ask))
+
+    print '----------------------------------------------------------------------------------------------------------'
+
+    
+    if maskOption == 1:
+        seasonalCycleOption = 1
+    
+    # TODO:  This seems like we can just use numOBS to compute obsSelect (obsSelect = numbOBS -1)
+    if numOBS == 1:
+        obsSelect = 1
+    else:
+        #obsSelect = 1          #  1st obs (TRMM)
+        #obsSelect = 2          # 2nd obs (CRU3.1)
+        obsSelect = numOBS      # obs ensemble
+
+    obsSelect = obsSelect - 1   # convert to fit the indexing that starts from 0
+
+    toolkit.do_metrics_20.metrics_plots(numOBS, numMDL, nT, ngrdY, ngrdX, Times, obsData, mdlData, obsRgn, mdlRgn, obsList, mdlList, \
+                              workdir, \
+                              mdlSelect, obsSelect, \
+                              numSubRgn, subRgnName, rgnSelect, \
+                              obsParameterId, precipFlag, timeRegridOption, maskOption, seasonalCycleOption, metricOption, \
+                                                                                           plotTitle, plotFilenameStub)
+    """
+
+def generateModels(modelConfig):
+    """
+    This function will return a list of Model objects that can easily be used for 
+    metric computation and other processing tasks.
+    
+    Input::  
+        modelConfig - list of ('key', 'value') tuples.  Below is a list of valid keys
+            filenamepattern - string i.e. '/nas/run/model/output/MOD*precip*.nc'
+            latvariable - string i.e. 'latitude'
+            lonvariable - string i.e. 'longitude'
+            timevariable - string i.e. 't'
+            timestep - string 'monthly' | 'daily' | 'annual'
+            varname - string i.e. 'pr'
+
+    Output::
+        modelList - List of Model objects
+    """
+    # Setup the config Data Dictionary to make parsing easier later
+    configData = {}
+    for entry in modelConfig:
+        configData[entry[0]] = entry[1]
+
+    modelFileList = None
+    for keyValTuple in modelConfig:
+        if keyValTuple[0] == 'filenamePattern':
+            modelFileList = glob.glob(keyValTuple[1])
+    
+    # Remove the filenamePattern from the dict since it is no longer used
+    configData.pop('filenamePattern')
+    
+    models = []
+    for modelFile in modelFileList:
+        configData['filename'] = modelFile
+        model = Model(**configData)
+        models.append(model)
+    
+    return models
+
+def generateSettings(settingsConfig):
+    """
+    Helper function to decouple the argument parsing from the Settings object creation
+    
+    Input::  
+        settingsConfig - list of ('key', 'value') tuples.
+            workdir - string i.e. '/nas/run/rcmet/work/'
+            cachedir - string i.e. '/tmp/rcmet/cache/'
+    Output::
+        settings - Settings Object
+    """
+    # Setup the config Data Dictionary to make parsing easier later
+    configData = {}
+    for entry in settingsConfig:
+        configData[entry[0]] = entry[1]
+        
+    return Settings(**configData)
+
+def generateDatasets(rcmedConfig):
+    """
+    Helper function to decouple the argument parsing from the RCMEDDataset object creation
+
+    Input::  
+        rcmedConfig - list of ('key', 'value') tuples.
+            obsDatasetId=3,10
+            obsParamId=36,32
+            obsTimeStep=monthly,monthly
+
+    Output::
+        datasets - list of RCMEDDataset Objects
+    # Setup the config Data Dictionary to make parsing easier later
+    """
+    delimiter = ','
+    configData = {}
+    for entry in rcmedConfig:
+        if delimiter in entry[1]:
+            # print 'delim found - %s' % entry[1]
+            valueList = entry[1].split(delimiter)
+            configData[entry[0]] = valueList
+        else:
+            configData[entry[0]] = entry[1]
+
+    return configData
+
+def tempGetYears():
+    startYear = int(raw_input('Enter start year YYYY \n'))
+    endYear = int(raw_input('Enter end year YYYY \n'))
+    # CGOODALE - Updating the Static endTime to be 31-DEC
+    startTime = datetime.datetime(startYear, 1, 1, 0, 0)
+    endTime = datetime.datetime(endYear, 12, 31, 0, 0)
+    return (startTime, endTime)
+
+if __name__ == "__main__":
+    
+    if args.CONFIG:
+        print 'Running using config file: %s' % args.CONFIG
+        # Parse the Config file
+        userConfig = ConfigParser.SafeConfigParser()
+        userConfig.optionxform = str # This is so the case is preserved on the items in the config file
+        userConfig.read(args.CONFIG)
+        settings = generateSettings(userConfig.items('SETTINGS'))
+        models = generateModels(userConfig.items('MODEL'))
+        datasets = generateDatasets(userConfig.items('RCMED'))
+        
+        # Go get the parameter listing from the database
+        try:
+            params = db.getParams()
+        except Exception:
+            sys.exit()
+        
+        obsDatasetList = []
+        for param_id in datasets['obsParamId']:
+            for param in params:
+                if param['parameter_id'] == int(param_id):
+                    obsDatasetList.append(param)
+                else:
+                    pass
+
+        # TODO:  Find a home for the regrid parameters in the CONFIG file
+        # Setup the Regridding Options
+        regridOption = 'regular'
+        # dLon = 0.44 - Provided in the SETTINGS config section
+        # dLat = 0.44
+        lonMin = -24.64
+        lonMax = 60.28
+        latMin = -45.76
+        latMax = 42.24
+        # Create a Grid Box Object that extends the bounding box Object
+        gridBox = GridBox(latMin, lonMin, latMax, lonMax, settings.gridLonStep, settings.gridLatStep)
+       
+        """ These can now be accessed from the gridBox object using gridBox.latCount and gridBox.lonCount attributes
+        naLons = int((gridBox.lonMax - gridBox.lonMin + 1.e-5 * settings.gridLonStep) / settings.gridLonStep) + 1
+        print naLons
+        print int((gridBox.lonMax - gridBox.lonMin) / gridBox.lonStep) + 1 
+        naLats = int((gridBox.latMax - gridBox.latMin + 1.e-5 * settings.gridLatStep) / settings.gridLatStep) + 1
+        """
+        timeRegridOption = settings.temporalGrid
+        
+        # TODO:  How do we support n subregions as Jinwon has below?
+        
+        numSubRgn = 21
+#        subRgnLon0 = ma.zeros(numSubRgn)
+#        subRgnLon1 = ma.zeros(numSubRgn)
+#        subRgnLat0 = ma.zeros(numSubRgn)
+#        subRgnLat1 = ma.zeros(numSubRgn)
+        # 21 rgns: SMHI11 + W+C+E. Mediterrenean (JK) + 3 in UCT (Western Sahara, Somalia, Madagascar) + 4 in Mideast
+        subRgnLon0 = [-10.0, 0.0, 10.0, 20.0, -19.3, 15.0, -10.0, -10.0, 33.9, 44.2, 10.0, 10.0, 30.0, 13.6, 13.6, 20.0, 43.2, 33.0, 45.0, 43.0, 50.0]   # HYB 21 rgns
+        subRgnLon1 = [  0.0, 10.0, 20.0, 33.0, -10.2, 30.0, 10.0, 10.0, 40.0, 51.8, 25.0, 25.0, 40.0, 20.0, 20.0, 35.7, 50.3, 40.0, 50.0, 50.0, 58.0]   # HYB 21 rgns
+        subRgnLat0 = [ 29.0, 29.0, 25.0, 25.0, 12.0, 15.0, 7.3, 5.0, 6.9, 2.2, 0.0, -10.0, -15.0, -27.9, -35.0, -35.0, -25.8, 25.0, 28.0, 13.0, 20.0]   # HYB 21 rgns
+        subRgnLat1 = [ 36.5, 37.5, 32.5, 32.5, 20.0, 25.0, 15.0, 7.3, 15.0, 11.8, 10.0, 0.0, 0.0, -21.4, -27.9, -21.4, -11.7, 35.0, 35.0, 20.0, 27.5]   # HYB 21 rgns
+        subRgnName = ['R01', 'R02', 'R03', 'R04', 'R05', 'R06', 'R07', 'R08', 'R09', 'R10', 'R11', 'R12', 'R13', 'R14', 'R15', 'R16', 'R17', 'R18', 'R19', 'R20', 'R21']   # HYB 21 rgns
+        print subRgnName
+        
+        subRegionTuple = (numSubRgn, subRgnLon0, subRgnLon1, subRgnLat0, subRgnLat1, subRgnName)
+        
+        
+        rgnSelect = 3
+        maskOption = settings.maskOption
+        
+        bbox = BoundingBox(subRgnLat0[rgnSelect], 
+                           subRgnLon0[rgnSelect], 
+                           subRgnLat1[rgnSelect], 
+                           subRgnLon1[rgnSelect])
+        
+        regionMask = SubRegion(subRgnName[rgnSelect], bbox)
+        
+        # Using a 'mask' instance of the BoundingBox object
+#        maskLonMin = 0
+#        maskLonMax = 0
+#        maskLatMin = 0
+#        maskLatMax = 0
+        
+        choice = 'y'
+        
+        #  THIS JUST MEANS A USER DEFINED MASK IS BEING USED (basically from the hardcoded values listed above (line 819 ish)
+        maskInputChoice = 1
+
+        if maskInputChoice == 1:
+            for n in np.arange(numSubRgn):
+                print 'Subregion [', n, '] ', subRgnName[n], subRgnLon0[n], 'E - ', subRgnLon1[n], ' E: ', subRgnLat0[n], 'N - ', subRgnLat1[n], 'N'
+            rgnSelect = 3
+        
+        # Section 9: Select Peformance Metric
+        metricOption = 'bias'
+        FoutOption = 0
+        
+        # Section 11: Select Plot Options
+        # TODO: Using first model in models since Var name is the same across all
+        modifyPlotOptions = 'no'
+        plotTitle = models[0].varName + '_'
+        plotFilenameStub = models[0].varName + '_'
+        
+        print'------------------------------'
+        print'End of preprocessor: Run RCMET'
+        print'------------------------------'
+        
+        numOBS, numMDL, nT, ngrdY, ngrdX, Times, obsData, mdlData, obsRgn, mdlRgn, obsList, mdlList = toolkit.do_data_prep.prep_data(settings, obsDatasetList, gridBox, models, subRegionTuple)
+        
+        
+        print 'Input and regridding of both obs and model data are completed. now move to metrics calculations'
+        
+        """FROM THE UPPER SECTION OF CODE"""
+
+        mdlSelect = numMDL - 1                      # numMDL-1 corresponds to the model ensemble
+    
+        """ Disregard GUI block for now
+        if GUI:
+            n = 0
+            while n < len(mdlList):
+                print n, n_mos[n], mdlStartT[n], mdlEndT[n], FileList[n][35:]
+                n += 1
+            ask = 'Enter the model ID to be evaluated from above:  ', len(FileList), ' for the model-ensemble: \n'
+            mdlSelect = int(raw_input(ask))
+    
+        print '----------------------------------------------------------------------------------------------------------'
+        """
+        
+        if maskOption:
+            seasonalCycleOption = True
+        
+        # TODO:  This seems like we can just use numOBS to compute obsSelect (obsSelect = numbOBS -1)
+        if numOBS == 1:
+            obsSelect = 1
+        else:
+            #obsSelect = 1          #  1st obs (TRMM)
+            #obsSelect = 2          # 2nd obs (CRU3.1)
+            obsSelect = numOBS      # obs ensemble
+    
+        obsSelect = obsSelect - 1   # convert to fit the indexing that starts from 0
+    
+    
+    
+        # TODO:  Undo the following code when refactoring later
+        obsParameterId = [str(x['parameter_id']) for x in obsDatasetList]
+        precipFlag = models[0].precipFlag
+    
+        toolkit.do_metrics_20.metrics_plots(numOBS, numMDL, nT, ngrdY, ngrdX, Times, obsData, mdlData, obsRgn, mdlRgn, obsList, mdlList, \
+                                  settings.workDir, \
+                                  mdlSelect, obsSelect, \
+                                  numSubRgn, subRgnName, rgnSelect, \
+                                  obsParameterId, precipFlag, timeRegridOption, maskOption, seasonalCycleOption, metricOption, \
+                                                                                               plotTitle, plotFilenameStub)
+        
+
+        
+    else:
+        print 'Interactive mode has been enabled'
+        #getSettings(SETTINGS)
+        print "But isn't implemented.  Try using the -c option instead"
+
+    #rcmet_cordexAF()