http://git-wip-us.apache.org/repos/asf/incubator-samoa/blob/7acb1c47/assets/js/bootstrap.min.js ---------------------------------------------------------------------- diff --git a/assets/js/bootstrap.min.js b/assets/js/bootstrap.min.js new file mode 100644 index 0000000..d839865 --- /dev/null +++ b/assets/js/bootstrap.min.js @@ -0,0 +1,7 @@ +/*! + * Bootstrap v3.3.1 (http://getbootstrap.com) + * Copyright 2011-2014 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + */ +if("undefined"==typeof jQuery)throw new Error("Bootstrap's JavaScript requires jQuery");+function(a){var b=a.fn.jquery.split(" ")[0].split(".");if(b[0]<2&&b[1]<9||1==b[0]&&9==b[1]&&b[2]<1)throw new Error("Bootstrap's JavaScript requires jQuery version 1.9.1 or higher")}(jQuery),+function(a){"use strict";function b(){var a=document.createElement("bootstrap"),b={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd otransitionend",transition:"transitionend"};for(var c in b)if(void 0!==a.style[c])return{end:b[c]};return!1}a.fn.emulateTransitionEnd=function(b){var c=!1,d=this;a(this).one("bsTransitionEnd",function(){c=!0});var e=function(){c||a(d).trigger(a.support.transition.end)};return setTimeout(e,b),this},a(function(){a.support.transition=b(),a.support.transition&&(a.event.special.bsTransitionEnd={bindType:a.support.transition.end,delegateType:a.support.transition.end,handle:function(b){return a(b.target).is(this)?b.handleObj.handler.apply (this,arguments):void 0}})})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var c=a(this),e=c.data("bs.alert");e||c.data("bs.alert",e=new d(this)),"string"==typeof b&&e[b].call(c)})}var c='[data-dismiss="alert"]',d=function(b){a(b).on("click",c,this.close)};d.VERSION="3.3.1",d.TRANSITION_DURATION=150,d.prototype.close=function(b){function c(){g.detach().trigger("closed.bs.alert").remove()}var e=a(this),f=e.attr("data-target");f||(f=e.attr("href"),f=f&&f.replace(/.*(?=#[^\s]*$)/,""));var g=a(f);b&&b.preventDefault(),g.length||(g=e.closest(".alert")),g.trigger(b=a.Event("close.bs.alert")),b.isDefaultPrevented()||(g.removeClass("in"),a.support.transition&&g.hasClass("fade")?g.one("bsTransitionEnd",c).emulateTransitionEnd(d.TRANSITION_DURATION):c())};var e=a.fn.alert;a.fn.alert=b,a.fn.alert.Constructor=d,a.fn.alert.noConflict=function(){return a.fn.alert=e,this},a(document).on("click.bs.alert.data-api",c,d.prototype.close)}(jQuery),+function(a){"use strict" ;function b(b){return this.each(function(){var d=a(this),e=d.data("bs.button"),f="object"==typeof b&&b;e||d.data("bs.button",e=new c(this,f)),"toggle"==b?e.toggle():b&&e.setState(b)})}var c=function(b,d){this.$element=a(b),this.options=a.extend({},c.DEFAULTS,d),this.isLoading=!1};c.VERSION="3.3.1",c.DEFAULTS={loadingText:"loading..."},c.prototype.setState=function(b){var c="disabled",d=this.$element,e=d.is("input")?"val":"html",f=d.data();b+="Text",null==f.resetText&&d.data("resetText",d[e]()),setTimeout(a.proxy(function(){d[e](null==f[b]?this.options[b]:f[b]),"loadingText"==b?(this.isLoading=!0,d.addClass(c).attr(c,c)):this.isLoading&&(this.isLoading=!1,d.removeClass(c).removeAttr(c))},this),0)},c.prototype.toggle=function(){var a=!0,b=this.$element.closest('[data-toggle="buttons"]');if(b.length){var c=this.$element.find("input");"radio"==c.prop("type")&&(c.prop("checked")&&this.$element.hasClass("active")?a=!1:b.find(".active").removeClass("active")),a&&c.prop("checked",!this.$ele ment.hasClass("active")).trigger("change")}else this.$element.attr("aria-pressed",!this.$element.hasClass("active"));a&&this.$element.toggleClass("active")};var d=a.fn.button;a.fn.button=b,a.fn.button.Constructor=c,a.fn.button.noConflict=function(){return a.fn.button=d,this},a(document).on("click.bs.button.data-api",'[data-toggle^="button"]',function(c){var d=a(c.target);d.hasClass("btn")||(d=d.closest(".btn")),b.call(d,"toggle"),c.preventDefault()}).on("focus.bs.button.data-api blur.bs.button.data-api",'[data-toggle^="button"]',function(b){a(b.target).closest(".btn").toggleClass("focus",/^focus(in)?$/.test(b.type))})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.carousel"),f=a.extend({},c.DEFAULTS,d.data(),"object"==typeof b&&b),g="string"==typeof b?b:f.slide;e||d.data("bs.carousel",e=new c(this,f)),"number"==typeof b?e.to(b):g?e[g]():f.interval&&e.pause().cycle()})}var c=function(b,c){this.$element=a(b),this.$indicators=thi s.$element.find(".carousel-indicators"),this.options=c,this.paused=this.sliding=this.interval=this.$active=this.$items=null,this.options.keyboard&&this.$element.on("keydown.bs.carousel",a.proxy(this.keydown,this)),"hover"==this.options.pause&&!("ontouchstart"in document.documentElement)&&this.$element.on("mouseenter.bs.carousel",a.proxy(this.pause,this)).on("mouseleave.bs.carousel",a.proxy(this.cycle,this))};c.VERSION="3.3.1",c.TRANSITION_DURATION=600,c.DEFAULTS={interval:5e3,pause:"hover",wrap:!0,keyboard:!0},c.prototype.keydown=function(a){if(!/input|textarea/i.test(a.target.tagName)){switch(a.which){case 37:this.prev();break;case 39:this.next();break;default:return}a.preventDefault()}},c.prototype.cycle=function(b){return b||(this.paused=!1),this.interval&&clearInterval(this.interval),this.options.interval&&!this.paused&&(this.interval=setInterval(a.proxy(this.next,this),this.options.interval)),this},c.prototype.getItemIndex=function(a){return this.$items=a.parent().children(".it em"),this.$items.index(a||this.$active)},c.prototype.getItemForDirection=function(a,b){var c="prev"==a?-1:1,d=this.getItemIndex(b),e=(d+c)%this.$items.length;return this.$items.eq(e)},c.prototype.to=function(a){var b=this,c=this.getItemIndex(this.$active=this.$element.find(".item.active"));return a>this.$items.length-1||0>a?void 0:this.sliding?this.$element.one("slid.bs.carousel",function(){b.to(a)}):c==a?this.pause().cycle():this.slide(a>c?"next":"prev",this.$items.eq(a))},c.prototype.pause=function(b){return b||(this.paused=!0),this.$element.find(".next, .prev").length&&a.support.transition&&(this.$element.trigger(a.support.transition.end),this.cycle(!0)),this.interval=clearInterval(this.interval),this},c.prototype.next=function(){return this.sliding?void 0:this.slide("next")},c.prototype.prev=function(){return this.sliding?void 0:this.slide("prev")},c.prototype.slide=function(b,d){var e=this.$element.find(".item.active"),f=d||this.getItemForDirection(b,e),g=this.interval,h="next" ==b?"left":"right",i="next"==b?"first":"last",j=this;if(!f.length){if(!this.options.wrap)return;f=this.$element.find(".item")[i]()}if(f.hasClass("active"))return this.sliding=!1;var k=f[0],l=a.Event("slide.bs.carousel",{relatedTarget:k,direction:h});if(this.$element.trigger(l),!l.isDefaultPrevented()){if(this.sliding=!0,g&&this.pause(),this.$indicators.length){this.$indicators.find(".active").removeClass("active");var m=a(this.$indicators.children()[this.getItemIndex(f)]);m&&m.addClass("active")}var n=a.Event("slid.bs.carousel",{relatedTarget:k,direction:h});return a.support.transition&&this.$element.hasClass("slide")?(f.addClass(b),f[0].offsetWidth,e.addClass(h),f.addClass(h),e.one("bsTransitionEnd",function(){f.removeClass([b,h].join(" ")).addClass("active"),e.removeClass(["active",h].join(" ")),j.sliding=!1,setTimeout(function(){j.$element.trigger(n)},0)}).emulateTransitionEnd(c.TRANSITION_DURATION)):(e.removeClass("active"),f.addClass("active"),this.sliding=!1,this.$element.trig ger(n)),g&&this.cycle(),this}};var d=a.fn.carousel;a.fn.carousel=b,a.fn.carousel.Constructor=c,a.fn.carousel.noConflict=function(){return a.fn.carousel=d,this};var e=function(c){var d,e=a(this),f=a(e.attr("data-target")||(d=e.attr("href"))&&d.replace(/.*(?=#[^\s]+$)/,""));if(f.hasClass("carousel")){var g=a.extend({},f.data(),e.data()),h=e.attr("data-slide-to");h&&(g.interval=!1),b.call(f,g),h&&f.data("bs.carousel").to(h),c.preventDefault()}};a(document).on("click.bs.carousel.data-api","[data-slide]",e).on("click.bs.carousel.data-api","[data-slide-to]",e),a(window).on("load",function(){a('[data-ride="carousel"]').each(function(){var c=a(this);b.call(c,c.data())})})}(jQuery),+function(a){"use strict";function b(b){var c,d=b.attr("data-target")||(c=b.attr("href"))&&c.replace(/.*(?=#[^\s]+$)/,"");return a(d)}function c(b){return this.each(function(){var c=a(this),e=c.data("bs.collapse"),f=a.extend({},d.DEFAULTS,c.data(),"object"==typeof b&&b);!e&&f.toggle&&"show"==b&&(f.toggle=!1),e||c. data("bs.collapse",e=new d(this,f)),"string"==typeof b&&e[b]()})}var d=function(b,c){this.$element=a(b),this.options=a.extend({},d.DEFAULTS,c),this.$trigger=a(this.options.trigger).filter('[href="#'+b.id+'"], [data-target="#'+b.id+'"]'),this.transitioning=null,this.options.parent?this.$parent=this.getParent():this.addAriaAndCollapsedClass(this.$element,this.$trigger),this.options.toggle&&this.toggle()};d.VERSION="3.3.1",d.TRANSITION_DURATION=350,d.DEFAULTS={toggle:!0,trigger:'[data-toggle="collapse"]'},d.prototype.dimension=function(){var a=this.$element.hasClass("width");return a?"width":"height"},d.prototype.show=function(){if(!this.transitioning&&!this.$element.hasClass("in")){var b,e=this.$parent&&this.$parent.find("> .panel").children(".in, .collapsing");if(!(e&&e.length&&(b=e.data("bs.collapse"),b&&b.transitioning))){var f=a.Event("show.bs.collapse");if(this.$element.trigger(f),!f.isDefaultPrevented()){e&&e.length&&(c.call(e,"hide"),b||e.data("bs.collapse",null));var g=this.di mension();this.$element.removeClass("collapse").addClass("collapsing")[g](0).attr("aria-expanded",!0),this.$trigger.removeClass("collapsed").attr("aria-expanded",!0),this.transitioning=1;var h=function(){this.$element.removeClass("collapsing").addClass("collapse in")[g](""),this.transitioning=0,this.$element.trigger("shown.bs.collapse")};if(!a.support.transition)return h.call(this);var i=a.camelCase(["scroll",g].join("-"));this.$element.one("bsTransitionEnd",a.proxy(h,this)).emulateTransitionEnd(d.TRANSITION_DURATION)[g](this.$element[0][i])}}}},d.prototype.hide=function(){if(!this.transitioning&&this.$element.hasClass("in")){var b=a.Event("hide.bs.collapse");if(this.$element.trigger(b),!b.isDefaultPrevented()){var c=this.dimension();this.$element[c](this.$element[c]())[0].offsetHeight,this.$element.addClass("collapsing").removeClass("collapse in").attr("aria-expanded",!1),this.$trigger.addClass("collapsed").attr("aria-expanded",!1),this.transitioning=1;var e=function(){this.transit ioning=0,this.$element.removeClass("collapsing").addClass("collapse").trigger("hidden.bs.collapse")};return a.support.transition?void this.$element[c](0).one("bsTransitionEnd",a.proxy(e,this)).emulateTransitionEnd(d.TRANSITION_DURATION):e.call(this)}}},d.prototype.toggle=function(){this[this.$element.hasClass("in")?"hide":"show"]()},d.prototype.getParent=function(){return a(this.options.parent).find('[data-toggle="collapse"][data-parent="'+this.options.parent+'"]').each(a.proxy(function(c,d){var e=a(d);this.addAriaAndCollapsedClass(b(e),e)},this)).end()},d.prototype.addAriaAndCollapsedClass=function(a,b){var c=a.hasClass("in");a.attr("aria-expanded",c),b.toggleClass("collapsed",!c).attr("aria-expanded",c)};var e=a.fn.collapse;a.fn.collapse=c,a.fn.collapse.Constructor=d,a.fn.collapse.noConflict=function(){return a.fn.collapse=e,this},a(document).on("click.bs.collapse.data-api",'[data-toggle="collapse"]',function(d){var e=a(this);e.attr("data-target")||d.preventDefault();var f=b(e),g= f.data("bs.collapse"),h=g?"toggle":a.extend({},e.data(),{trigger:this});c.call(f,h)})}(jQuery),+function(a){"use strict";function b(b){b&&3===b.which||(a(e).remove(),a(f).each(function(){var d=a(this),e=c(d),f={relatedTarget:this};e.hasClass("open")&&(e.trigger(b=a.Event("hide.bs.dropdown",f)),b.isDefaultPrevented()||(d.attr("aria-expanded","false"),e.removeClass("open").trigger("hidden.bs.dropdown",f)))}))}function c(b){var c=b.attr("data-target");c||(c=b.attr("href"),c=c&&/#[A-Za-z]/.test(c)&&c.replace(/.*(?=#[^\s]*$)/,""));var d=c&&a(c);return d&&d.length?d:b.parent()}function d(b){return this.each(function(){var c=a(this),d=c.data("bs.dropdown");d||c.data("bs.dropdown",d=new g(this)),"string"==typeof b&&d[b].call(c)})}var e=".dropdown-backdrop",f='[data-toggle="dropdown"]',g=function(b){a(b).on("click.bs.dropdown",this.toggle)};g.VERSION="3.3.1",g.prototype.toggle=function(d){var e=a(this);if(!e.is(".disabled, :disabled")){var f=c(e),g=f.hasClass("open");if(b(),!g){"ontouchstart "in document.documentElement&&!f.closest(".navbar-nav").length&&a('<div class="dropdown-backdrop"/>').insertAfter(a(this)).on("click",b);var h={relatedTarget:this};if(f.trigger(d=a.Event("show.bs.dropdown",h)),d.isDefaultPrevented())return;e.trigger("focus").attr("aria-expanded","true"),f.toggleClass("open").trigger("shown.bs.dropdown",h)}return!1}},g.prototype.keydown=function(b){if(/(38|40|27|32)/.test(b.which)&&!/input|textarea/i.test(b.target.tagName)){var d=a(this);if(b.preventDefault(),b.stopPropagation(),!d.is(".disabled, :disabled")){var e=c(d),g=e.hasClass("open");if(!g&&27!=b.which||g&&27==b.which)return 27==b.which&&e.find(f).trigger("focus"),d.trigger("click");var h=" li:not(.divider):visible a",i=e.find('[role="menu"]'+h+', [role="listbox"]'+h);if(i.length){var j=i.index(b.target);38==b.which&&j>0&&j--,40==b.which&&j<i.length-1&&j++,~j||(j=0),i.eq(j).trigger("focus")}}}};var h=a.fn.dropdown;a.fn.dropdown=d,a.fn.dropdown.Constructor=g,a.fn.dropdown.noConflict=function(){ return a.fn.dropdown=h,this},a(document).on("click.bs.dropdown.data-api",b).on("click.bs.dropdown.data-api",".dropdown form",function(a){a.stopPropagation()}).on("click.bs.dropdown.data-api",f,g.prototype.toggle).on("keydown.bs.dropdown.data-api",f,g.prototype.keydown).on("keydown.bs.dropdown.data-api",'[role="menu"]',g.prototype.keydown).on("keydown.bs.dropdown.data-api",'[role="listbox"]',g.prototype.keydown)}(jQuery),+function(a){"use strict";function b(b,d){return this.each(function(){var e=a(this),f=e.data("bs.modal"),g=a.extend({},c.DEFAULTS,e.data(),"object"==typeof b&&b);f||e.data("bs.modal",f=new c(this,g)),"string"==typeof b?f[b](d):g.show&&f.show(d)})}var c=function(b,c){this.options=c,this.$body=a(document.body),this.$element=a(b),this.$backdrop=this.isShown=null,this.scrollbarWidth=0,this.options.remote&&this.$element.find(".modal-content").load(this.options.remote,a.proxy(function(){this.$element.trigger("loaded.bs.modal")},this))};c.VERSION="3.3.1",c.TRANSITION_DURATI ON=300,c.BACKDROP_TRANSITION_DURATION=150,c.DEFAULTS={backdrop:!0,keyboard:!0,show:!0},c.prototype.toggle=function(a){return this.isShown?this.hide():this.show(a)},c.prototype.show=function(b){var d=this,e=a.Event("show.bs.modal",{relatedTarget:b});this.$element.trigger(e),this.isShown||e.isDefaultPrevented()||(this.isShown=!0,this.checkScrollbar(),this.setScrollbar(),this.$body.addClass("modal-open"),this.escape(),this.resize(),this.$element.on("click.dismiss.bs.modal",'[data-dismiss="modal"]',a.proxy(this.hide,this)),this.backdrop(function(){var e=a.support.transition&&d.$element.hasClass("fade");d.$element.parent().length||d.$element.appendTo(d.$body),d.$element.show().scrollTop(0),d.options.backdrop&&d.adjustBackdrop(),d.adjustDialog(),e&&d.$element[0].offsetWidth,d.$element.addClass("in").attr("aria-hidden",!1),d.enforceFocus();var f=a.Event("shown.bs.modal",{relatedTarget:b});e?d.$element.find(".modal-dialog").one("bsTransitionEnd",function(){d.$element.trigger("focus").trigge r(f)}).emulateTransitionEnd(c.TRANSITION_DURATION):d.$element.trigger("focus").trigger(f)}))},c.prototype.hide=function(b){b&&b.preventDefault(),b=a.Event("hide.bs.modal"),this.$element.trigger(b),this.isShown&&!b.isDefaultPrevented()&&(this.isShown=!1,this.escape(),this.resize(),a(document).off("focusin.bs.modal"),this.$element.removeClass("in").attr("aria-hidden",!0).off("click.dismiss.bs.modal"),a.support.transition&&this.$element.hasClass("fade")?this.$element.one("bsTransitionEnd",a.proxy(this.hideModal,this)).emulateTransitionEnd(c.TRANSITION_DURATION):this.hideModal())},c.prototype.enforceFocus=function(){a(document).off("focusin.bs.modal").on("focusin.bs.modal",a.proxy(function(a){this.$element[0]===a.target||this.$element.has(a.target).length||this.$element.trigger("focus")},this))},c.prototype.escape=function(){this.isShown&&this.options.keyboard?this.$element.on("keydown.dismiss.bs.modal",a.proxy(function(a){27==a.which&&this.hide()},this)):this.isShown||this.$element.off ("keydown.dismiss.bs.modal")},c.prototype.resize=function(){this.isShown?a(window).on("resize.bs.modal",a.proxy(this.handleUpdate,this)):a(window).off("resize.bs.modal")},c.prototype.hideModal=function(){var a=this;this.$element.hide(),this.backdrop(function(){a.$body.removeClass("modal-open"),a.resetAdjustments(),a.resetScrollbar(),a.$element.trigger("hidden.bs.modal")})},c.prototype.removeBackdrop=function(){this.$backdrop&&this.$backdrop.remove(),this.$backdrop=null},c.prototype.backdrop=function(b){var d=this,e=this.$element.hasClass("fade")?"fade":"";if(this.isShown&&this.options.backdrop){var f=a.support.transition&&e;if(this.$backdrop=a('<div class="modal-backdrop '+e+'" />').prependTo(this.$element).on("click.dismiss.bs.modal",a.proxy(function(a){a.target===a.currentTarget&&("static"==this.options.backdrop?this.$element[0].focus.call(this.$element[0]):this.hide.call(this))},this)),f&&this.$backdrop[0].offsetWidth,this.$backdrop.addClass("in"),!b)return;f?this.$backdrop.one(" bsTransitionEnd",b).emulateTransitionEnd(c.BACKDROP_TRANSITION_DURATION):b()}else if(!this.isShown&&this.$backdrop){this.$backdrop.removeClass("in");var g=function(){d.removeBackdrop(),b&&b()};a.support.transition&&this.$element.hasClass("fade")?this.$backdrop.one("bsTransitionEnd",g).emulateTransitionEnd(c.BACKDROP_TRANSITION_DURATION):g()}else b&&b()},c.prototype.handleUpdate=function(){this.options.backdrop&&this.adjustBackdrop(),this.adjustDialog()},c.prototype.adjustBackdrop=function(){this.$backdrop.css("height",0).css("height",this.$element[0].scrollHeight)},c.prototype.adjustDialog=function(){var a=this.$element[0].scrollHeight>document.documentElement.clientHeight;this.$element.css({paddingLeft:!this.bodyIsOverflowing&&a?this.scrollbarWidth:"",paddingRight:this.bodyIsOverflowing&&!a?this.scrollbarWidth:""})},c.prototype.resetAdjustments=function(){this.$element.css({paddingLeft:"",paddingRight:""})},c.prototype.checkScrollbar=function(){this.bodyIsOverflowing=document.body. scrollHeight>document.documentElement.clientHeight,this.scrollbarWidth=this.measureScrollbar()},c.prototype.setScrollbar=function(){var a=parseInt(this.$body.css("padding-right")||0,10);this.bodyIsOverflowing&&this.$body.css("padding-right",a+this.scrollbarWidth)},c.prototype.resetScrollbar=function(){this.$body.css("padding-right","")},c.prototype.measureScrollbar=function(){var a=document.createElement("div");a.className="modal-scrollbar-measure",this.$body.append(a);var b=a.offsetWidth-a.clientWidth;return this.$body[0].removeChild(a),b};var d=a.fn.modal;a.fn.modal=b,a.fn.modal.Constructor=c,a.fn.modal.noConflict=function(){return a.fn.modal=d,this},a(document).on("click.bs.modal.data-api",'[data-toggle="modal"]',function(c){var d=a(this),e=d.attr("href"),f=a(d.attr("data-target")||e&&e.replace(/.*(?=#[^\s]+$)/,"")),g=f.data("bs.modal")?"toggle":a.extend({remote:!/#/.test(e)&&e},f.data(),d.data());d.is("a")&&c.preventDefault(),f.one("show.bs.modal",function(a){a.isDefaultPrevente d()||f.one("hidden.bs.modal",function(){d.is(":visible")&&d.trigger("focus")})}),b.call(f,g,this)})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.tooltip"),f="object"==typeof b&&b,g=f&&f.selector;(e||"destroy"!=b)&&(g?(e||d.data("bs.tooltip",e={}),e[g]||(e[g]=new c(this,f))):e||d.data("bs.tooltip",e=new c(this,f)),"string"==typeof b&&e[b]())})}var c=function(a,b){this.type=this.options=this.enabled=this.timeout=this.hoverState=this.$element=null,this.init("tooltip",a,b)};c.VERSION="3.3.1",c.TRANSITION_DURATION=150,c.DEFAULTS={animation:!0,placement:"top",selector:!1,template:'<div class="tooltip" role="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>',trigger:"hover focus",title:"",delay:0,html:!1,container:!1,viewport:{selector:"body",padding:0}},c.prototype.init=function(b,c,d){this.enabled=!0,this.type=b,this.$element=a(c),this.options=this.getOptions(d),this.$viewport=this.options.viewport &&a(this.options.viewport.selector||this.options.viewport);for(var e=this.options.trigger.split(" "),f=e.length;f--;){var g=e[f];if("click"==g)this.$element.on("click."+this.type,this.options.selector,a.proxy(this.toggle,this));else if("manual"!=g){var h="hover"==g?"mouseenter":"focusin",i="hover"==g?"mouseleave":"focusout";this.$element.on(h+"."+this.type,this.options.selector,a.proxy(this.enter,this)),this.$element.on(i+"."+this.type,this.options.selector,a.proxy(this.leave,this))}}this.options.selector?this._options=a.extend({},this.options,{trigger:"manual",selector:""}):this.fixTitle()},c.prototype.getDefaults=function(){return c.DEFAULTS},c.prototype.getOptions=function(b){return b=a.extend({},this.getDefaults(),this.$element.data(),b),b.delay&&"number"==typeof b.delay&&(b.delay={show:b.delay,hide:b.delay}),b},c.prototype.getDelegateOptions=function(){var b={},c=this.getDefaults();return this._options&&a.each(this._options,function(a,d){c[a]!=d&&(b[a]=d)}),b},c.prototype.enter =function(b){var c=b instanceof this.constructor?b:a(b.currentTarget).data("bs."+this.type);return c&&c.$tip&&c.$tip.is(":visible")?void(c.hoverState="in"):(c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data("bs."+this.type,c)),clearTimeout(c.timeout),c.hoverState="in",c.options.delay&&c.options.delay.show?void(c.timeout=setTimeout(function(){"in"==c.hoverState&&c.show()},c.options.delay.show)):c.show())},c.prototype.leave=function(b){var c=b instanceof this.constructor?b:a(b.currentTarget).data("bs."+this.type);return c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data("bs."+this.type,c)),clearTimeout(c.timeout),c.hoverState="out",c.options.delay&&c.options.delay.hide?void(c.timeout=setTimeout(function(){"out"==c.hoverState&&c.hide()},c.options.delay.hide)):c.hide()},c.prototype.show=function(){var b=a.Event("show.bs."+this.type);if(this.hasContent()&&this.enabled){this.$element.trigger(b);var d=a. contains(this.$element[0].ownerDocument.documentElement,this.$element[0]);if(b.isDefaultPrevented()||!d)return;var e=this,f=this.tip(),g=this.getUID(this.type);this.setContent(),f.attr("id",g),this.$element.attr("aria-describedby",g),this.options.animation&&f.addClass("fade");var h="function"==typeof this.options.placement?this.options.placement.call(this,f[0],this.$element[0]):this.options.placement,i=/\s?auto?\s?/i,j=i.test(h);j&&(h=h.replace(i,"")||"top"),f.detach().css({top:0,left:0,display:"block"}).addClass(h).data("bs."+this.type,this),this.options.container?f.appendTo(this.options.container):f.insertAfter(this.$element);var k=this.getPosition(),l=f[0].offsetWidth,m=f[0].offsetHeight;if(j){var n=h,o=this.options.container?a(this.options.container):this.$element.parent(),p=this.getPosition(o);h="bottom"==h&&k.bottom+m>p.bottom?"top":"top"==h&&k.top-m<p.top?"bottom":"right"==h&&k.right+l>p.width?"left":"left"==h&&k.left-l<p.left?"right":h,f.removeClass(n).addClass(h)}var q=this .getCalculatedOffset(h,k,l,m);this.applyPlacement(q,h);var r=function(){var a=e.hoverState;e.$element.trigger("shown.bs."+e.type),e.hoverState=null,"out"==a&&e.leave(e)};a.support.transition&&this.$tip.hasClass("fade")?f.one("bsTransitionEnd",r).emulateTransitionEnd(c.TRANSITION_DURATION):r()}},c.prototype.applyPlacement=function(b,c){var d=this.tip(),e=d[0].offsetWidth,f=d[0].offsetHeight,g=parseInt(d.css("margin-top"),10),h=parseInt(d.css("margin-left"),10);isNaN(g)&&(g=0),isNaN(h)&&(h=0),b.top=b.top+g,b.left=b.left+h,a.offset.setOffset(d[0],a.extend({using:function(a){d.css({top:Math.round(a.top),left:Math.round(a.left)})}},b),0),d.addClass("in");var i=d[0].offsetWidth,j=d[0].offsetHeight;"top"==c&&j!=f&&(b.top=b.top+f-j);var k=this.getViewportAdjustedDelta(c,b,i,j);k.left?b.left+=k.left:b.top+=k.top;var l=/top|bottom/.test(c),m=l?2*k.left-e+i:2*k.top-f+j,n=l?"offsetWidth":"offsetHeight";d.offset(b),this.replaceArrow(m,d[0][n],l)},c.prototype.replaceArrow=function(a,b,c){this.arr ow().css(c?"left":"top",50*(1-a/b)+"%").css(c?"top":"left","")},c.prototype.setContent=function(){var a=this.tip(),b=this.getTitle();a.find(".tooltip-inner")[this.options.html?"html":"text"](b),a.removeClass("fade in top bottom left right")},c.prototype.hide=function(b){function d(){"in"!=e.hoverState&&f.detach(),e.$element.removeAttr("aria-describedby").trigger("hidden.bs."+e.type),b&&b()}var e=this,f=this.tip(),g=a.Event("hide.bs."+this.type);return this.$element.trigger(g),g.isDefaultPrevented()?void 0:(f.removeClass("in"),a.support.transition&&this.$tip.hasClass("fade")?f.one("bsTransitionEnd",d).emulateTransitionEnd(c.TRANSITION_DURATION):d(),this.hoverState=null,this)},c.prototype.fixTitle=function(){var a=this.$element;(a.attr("title")||"string"!=typeof a.attr("data-original-title"))&&a.attr("data-original-title",a.attr("title")||"").attr("title","")},c.prototype.hasContent=function(){return this.getTitle()},c.prototype.getPosition=function(b){b=b||this.$element;var c=b[0],d= "BODY"==c.tagName,e=c.getBoundingClientRect();null==e.width&&(e=a.extend({},e,{width:e.right-e.left,height:e.bottom-e.top}));var f=d?{top:0,left:0}:b.offset(),g={scroll:d?document.documentElement.scrollTop||document.body.scrollTop:b.scrollTop()},h=d?{width:a(window).width(),height:a(window).height()}:null;return a.extend({},e,g,h,f)},c.prototype.getCalculatedOffset=function(a,b,c,d){return"bottom"==a?{top:b.top+b.height,left:b.left+b.width/2-c/2}:"top"==a?{top:b.top-d,left:b.left+b.width/2-c/2}:"left"==a?{top:b.top+b.height/2-d/2,left:b.left-c}:{top:b.top+b.height/2-d/2,left:b.left+b.width}},c.prototype.getViewportAdjustedDelta=function(a,b,c,d){var e={top:0,left:0};if(!this.$viewport)return e;var f=this.options.viewport&&this.options.viewport.padding||0,g=this.getPosition(this.$viewport);if(/right|left/.test(a)){var h=b.top-f-g.scroll,i=b.top+f-g.scroll+d;h<g.top?e.top=g.top-h:i>g.top+g.height&&(e.top=g.top+g.height-i)}else{var j=b.left-f,k=b.left+f+c;j<g.left?e.left=g.left-j:k>g.w idth&&(e.left=g.left+g.width-k)}return e},c.prototype.getTitle=function(){var a,b=this.$element,c=this.options;return a=b.attr("data-original-title")||("function"==typeof c.title?c.title.call(b[0]):c.title)},c.prototype.getUID=function(a){do a+=~~(1e6*Math.random());while(document.getElementById(a));return a},c.prototype.tip=function(){return this.$tip=this.$tip||a(this.options.template)},c.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".tooltip-arrow")},c.prototype.enable=function(){this.enabled=!0},c.prototype.disable=function(){this.enabled=!1},c.prototype.toggleEnabled=function(){this.enabled=!this.enabled},c.prototype.toggle=function(b){var c=this;b&&(c=a(b.currentTarget).data("bs."+this.type),c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data("bs."+this.type,c))),c.tip().hasClass("in")?c.leave(c):c.enter(c)},c.prototype.destroy=function(){var a=this;clearTimeout(this.timeout),this.hide(function(){a.$elemen t.off("."+a.type).removeData("bs."+a.type)})};var d=a.fn.tooltip;a.fn.tooltip=b,a.fn.tooltip.Constructor=c,a.fn.tooltip.noConflict=function(){return a.fn.tooltip=d,this}}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.popover"),f="object"==typeof b&&b,g=f&&f.selector;(e||"destroy"!=b)&&(g?(e||d.data("bs.popover",e={}),e[g]||(e[g]=new c(this,f))):e||d.data("bs.popover",e=new c(this,f)),"string"==typeof b&&e[b]())})}var c=function(a,b){this.init("popover",a,b)};if(!a.fn.tooltip)throw new Error("Popover requires tooltip.js");c.VERSION="3.3.1",c.DEFAULTS=a.extend({},a.fn.tooltip.Constructor.DEFAULTS,{placement:"right",trigger:"click",content:"",template:'<div class="popover" role="tooltip"><div class="arrow"></div><h3 class="popover-title"></h3><div class="popover-content"></div></div>'}),c.prototype=a.extend({},a.fn.tooltip.Constructor.prototype),c.prototype.constructor=c,c.prototype.getDefaults=function(){return c.DEFAULTS},c.pro totype.setContent=function(){var a=this.tip(),b=this.getTitle(),c=this.getContent();a.find(".popover-title")[this.options.html?"html":"text"](b),a.find(".popover-content").children().detach().end()[this.options.html?"string"==typeof c?"html":"append":"text"](c),a.removeClass("fade top bottom left right in"),a.find(".popover-title").html()||a.find(".popover-title").hide()},c.prototype.hasContent=function(){return this.getTitle()||this.getContent()},c.prototype.getContent=function(){var a=this.$element,b=this.options;return a.attr("data-content")||("function"==typeof b.content?b.content.call(a[0]):b.content)},c.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".arrow")},c.prototype.tip=function(){return this.$tip||(this.$tip=a(this.options.template)),this.$tip};var d=a.fn.popover;a.fn.popover=b,a.fn.popover.Constructor=c,a.fn.popover.noConflict=function(){return a.fn.popover=d,this}}(jQuery),+function(a){"use strict";function b(c,d){var e=a.proxy(this.process ,this);this.$body=a("body"),this.$scrollElement=a(a(c).is("body")?window:c),this.options=a.extend({},b.DEFAULTS,d),this.selector=(this.options.target||"")+" .nav li > a",this.offsets=[],this.targets=[],this.activeTarget=null,this.scrollHeight=0,this.$scrollElement.on("scroll.bs.scrollspy",e),this.refresh(),this.process()}function c(c){return this.each(function(){var d=a(this),e=d.data("bs.scrollspy"),f="object"==typeof c&&c;e||d.data("bs.scrollspy",e=new b(this,f)),"string"==typeof c&&e[c]()})}b.VERSION="3.3.1",b.DEFAULTS={offset:10},b.prototype.getScrollHeight=function(){return this.$scrollElement[0].scrollHeight||Math.max(this.$body[0].scrollHeight,document.documentElement.scrollHeight)},b.prototype.refresh=function(){var b="offset",c=0;a.isWindow(this.$scrollElement[0])||(b="position",c=this.$scrollElement.scrollTop()),this.offsets=[],this.targets=[],this.scrollHeight=this.getScrollHeight();var d=this;this.$body.find(this.selector).map(function(){var d=a(this),e=d.data("target")| |d.attr("href"),f=/^#./.test(e)&&a(e);return f&&f.length&&f.is(":visible")&&[[f[b]().top+c,e]]||null}).sort(function(a,b){return a[0]-b[0]}).each(function(){d.offsets.push(this[0]),d.targets.push(this[1])})},b.prototype.process=function(){var a,b=this.$scrollElement.scrollTop()+this.options.offset,c=this.getScrollHeight(),d=this.options.offset+c-this.$scrollElement.height(),e=this.offsets,f=this.targets,g=this.activeTarget;if(this.scrollHeight!=c&&this.refresh(),b>=d)return g!=(a=f[f.length-1])&&this.activate(a);if(g&&b<e[0])return this.activeTarget=null,this.clear();for(a=e.length;a--;)g!=f[a]&&b>=e[a]&&(!e[a+1]||b<=e[a+1])&&this.activate(f[a])},b.prototype.activate=function(b){this.activeTarget=b,this.clear();var c=this.selector+'[data-target="'+b+'"],'+this.selector+'[href="'+b+'"]',d=a(c).parents("li").addClass("active");d.parent(".dropdown-menu").length&&(d=d.closest("li.dropdown").addClass("active")),d.trigger("activate.bs.scrollspy")},b.prototype.clear=function(){a(this.selec tor).parentsUntil(this.options.target,".active").removeClass("active")};var d=a.fn.scrollspy;a.fn.scrollspy=c,a.fn.scrollspy.Constructor=b,a.fn.scrollspy.noConflict=function(){return a.fn.scrollspy=d,this},a(window).on("load.bs.scrollspy.data-api",function(){a('[data-spy="scroll"]').each(function(){var b=a(this);c.call(b,b.data())})})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.tab");e||d.data("bs.tab",e=new c(this)),"string"==typeof b&&e[b]()})}var c=function(b){this.element=a(b)};c.VERSION="3.3.1",c.TRANSITION_DURATION=150,c.prototype.show=function(){var b=this.element,c=b.closest("ul:not(.dropdown-menu)"),d=b.data("target");if(d||(d=b.attr("href"),d=d&&d.replace(/.*(?=#[^\s]*$)/,"")),!b.parent("li").hasClass("active")){var e=c.find(".active:last a"),f=a.Event("hide.bs.tab",{relatedTarget:b[0]}),g=a.Event("show.bs.tab",{relatedTarget:e[0]});if(e.trigger(f),b.trigger(g),!g.isDefaultPrevented()&&!f.isDefaultPrevented()){var h=a(d);this.activate(b.closest("li"),c),this.activate(h,h.parent(),function(){e.trigger({type:"hidden.bs.tab",relatedTarget:b[0]}),b.trigger({type:"shown.bs.tab",relatedTarget:e[0]}) +})}}},c.prototype.activate=function(b,d,e){function f(){g.removeClass("active").find("> .dropdown-menu > .active").removeClass("active").end().find('[data-toggle="tab"]').attr("aria-expanded",!1),b.addClass("active").find('[data-toggle="tab"]').attr("aria-expanded",!0),h?(b[0].offsetWidth,b.addClass("in")):b.removeClass("fade"),b.parent(".dropdown-menu")&&b.closest("li.dropdown").addClass("active").end().find('[data-toggle="tab"]').attr("aria-expanded",!0),e&&e()}var g=d.find("> .active"),h=e&&a.support.transition&&(g.length&&g.hasClass("fade")||!!d.find("> .fade").length);g.length&&h?g.one("bsTransitionEnd",f).emulateTransitionEnd(c.TRANSITION_DURATION):f(),g.removeClass("in")};var d=a.fn.tab;a.fn.tab=b,a.fn.tab.Constructor=c,a.fn.tab.noConflict=function(){return a.fn.tab=d,this};var e=function(c){c.preventDefault(),b.call(a(this),"show")};a(document).on("click.bs.tab.data-api",'[data-toggle="tab"]',e).on("click.bs.tab.data-api",'[data-toggle="pill"]',e)}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.affix"),f="object"==typeof b&&b;e||d.data("bs.affix",e=new c(this,f)),"string"==typeof b&&e[b]()})}var c=function(b,d){this.options=a.extend({},c.DEFAULTS,d),this.$target=a(this.options.target).on("scroll.bs.affix.data-api",a.proxy(this.checkPosition,this)).on("click.bs.affix.data-api",a.proxy(this.checkPositionWithEventLoop,this)),this.$element=a(b),this.affixed=this.unpin=this.pinnedOffset=null,this.checkPosition()};c.VERSION="3.3.1",c.RESET="affix affix-top affix-bottom",c.DEFAULTS={offset:0,target:window},c.prototype.getState=function(a,b,c,d){var e=this.$target.scrollTop(),f=this.$element.offset(),g=this.$target.height();if(null!=c&&"top"==this.affixed)return c>e?"top":!1;if("bottom"==this.affixed)return null!=c?e+this.unpin<=f.top?!1:"bottom":a-d>=e+g?!1:"bottom";var h=null==this.affixed,i=h?e:f.top,j=h?g:b;return null!=c&&c>=i?"top":null!=d&&i+j>=a-d?"bottom":!1},c.prototype.getPinnedOffset=function( ){if(this.pinnedOffset)return this.pinnedOffset;this.$element.removeClass(c.RESET).addClass("affix");var a=this.$target.scrollTop(),b=this.$element.offset();return this.pinnedOffset=b.top-a},c.prototype.checkPositionWithEventLoop=function(){setTimeout(a.proxy(this.checkPosition,this),1)},c.prototype.checkPosition=function(){if(this.$element.is(":visible")){var b=this.$element.height(),d=this.options.offset,e=d.top,f=d.bottom,g=a("body").height();"object"!=typeof d&&(f=e=d),"function"==typeof e&&(e=d.top(this.$element)),"function"==typeof f&&(f=d.bottom(this.$element));var h=this.getState(g,b,e,f);if(this.affixed!=h){null!=this.unpin&&this.$element.css("top","");var i="affix"+(h?"-"+h:""),j=a.Event(i+".bs.affix");if(this.$element.trigger(j),j.isDefaultPrevented())return;this.affixed=h,this.unpin="bottom"==h?this.getPinnedOffset():null,this.$element.removeClass(c.RESET).addClass(i).trigger(i.replace("affix","affixed")+".bs.affix")}"bottom"==h&&this.$element.offset({top:g-b-f})}};var d =a.fn.affix;a.fn.affix=b,a.fn.affix.Constructor=c,a.fn.affix.noConflict=function(){return a.fn.affix=d,this},a(window).on("load",function(){a('[data-spy="affix"]').each(function(){var c=a(this),d=c.data();d.offset=d.offset||{},null!=d.offsetBottom&&(d.offset.bottom=d.offsetBottom),null!=d.offsetTop&&(d.offset.top=d.offsetTop),b.call(c,d)})})}(jQuery); \ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-samoa/blob/7acb1c47/assets/js/npm.js ---------------------------------------------------------------------- diff --git a/assets/js/npm.js b/assets/js/npm.js new file mode 100644 index 0000000..bf6aa80 --- /dev/null +++ b/assets/js/npm.js @@ -0,0 +1,13 @@ +// This file is autogenerated via the `commonjs` Grunt task. You can require() this file in a CommonJS environment. +require('../../js/transition.js') +require('../../js/alert.js') +require('../../js/button.js') +require('../../js/carousel.js') +require('../../js/collapse.js') +require('../../js/dropdown.js') +require('../../js/modal.js') +require('../../js/tooltip.js') +require('../../js/popover.js') +require('../../js/scrollspy.js') +require('../../js/tab.js') +require('../../js/affix.js') \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-samoa/blob/7acb1c47/contributors.html ---------------------------------------------------------------------- diff --git a/contributors.html b/contributors.html deleted file mode 100644 index 05dadca..0000000 --- a/contributors.html +++ /dev/null @@ -1,89 +0,0 @@ -<!doctype html> -<html> - <head> - <meta charset="utf-8"> - <meta http-equiv="X-UA-Compatible" content="chrome=1"> - <title>SAMOA by yahoo</title> - - <link rel="stylesheet" href="stylesheets/styles.css"> - <link rel="stylesheet" href="stylesheets/pygment_trac.css"> - <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no"> - <!--[if lt IE 9]> - <script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script> - <![endif]--> - </head> - <body> - <div class="wrapper"> - <header> - <h1>SAMOA</h1> - <p>Scalable Advanced Massive Online Analysis</p> - - <p class="view"><a href="https://github.com/yahoo/samoa">View the Project on GitHub <small>yahoo/samoa</small></a></p> - - - <ul> - <li><a href="https://github.com/yahoo/samoa/zipball/master">Download <strong>ZIP File</strong></a></li> - <li><a href="https://github.com/yahoo/samoa/tarball/master">Download <strong>TAR Ball</strong></a></li> - <li><a href="https://github.com/yahoo/samoa">View On <strong>GitHub</strong></a></li> - </ul> - </header> - <section> - <h1>The SAMOA Team</h1> - -<h2>Project lead</h2> -<ul> -<li><a href="http://gdfm.me/">Gianmarco De Francisci Morales</a></li> -<li><a href="http://www.albertbifet.com">Albert Bifet</a></li> -</ul> - -<h2>Committers</h2> -<ul> -<li><a href="http://www.cse.usf.edu/~nkourtel/">Nicolas Kourtellis</a></li> -<li><a href="http://www.linkedin.com/pub/faisal-moeen/40/17/512">Faisal Moeen</a></li> -<li><a href="http://www.linkedin.com/in/mmorel">Matthieu Morel</a></li> -<li><a href="http://www.otnira.com">Arinto Murdopo</a></li> -<li><a href="http://cs.brown.edu/~matteo/">Matteo Riondato</a></li> -<li><a href="https://twitter.com/AntonioSeverien">Antonio Severien</a></li> -<li><a href="http://www.van-laere.net">Olivier Van Laere</a></li> -<li><a href="http://www.linkedin.com/in/caseyvu">Anh Thu Vu</a></li> - - -</ul> - -<h2>Contributors</h2> -<ul> -<li><a href="http://www.lsi.upc.edu/~marias/">Marta Arias</a></li> -<li><a href="http://www.lsi.upc.edu/~gavalda/">Ricard Gavaldà </a></li> -<li><a href="http://dme.rwth-aachen.de/de/team/hassani">Marwan Hassani</a></li> -<li><a href="http://www.scms.waikato.ac.nz/genquery.php?linklist=SCMS&linktype=folder&linkname=The_Dean-0">Geoff Holmes</a></li> -<li><a href="http://dme.rwth-aachen.de/de/team/jansen">Timm Jansen</a></li> -<li>Richard Kirkby</li> -<li><a href="http://dme.rwth-aachen.de/de/team/kranen">Philipp Kranen</a></li> -<li><a href="http://dme.rwth-aachen.de/de/team/kremer">Hardy Kremer</a></li> -<li><a href="http://www.cs.waikato.ac.nz/~bernhard">Bernhard Pfahringer</a></li> -<li><a href="http://users.ics.aalto.fi/jesse/">Jesse Read</a></li> -<li><a href="http://www.cs.waikato.ac.nz/~fracpete">Peter Reutemann</a></li> -<li><a href="http://dme.rwth-aachen.de/de/team/seidl">Thomas Seidl</a></li> - -</ul> - - - </section> - <footer> - <p>This project is maintained by <a href="https://github.com/yahoo">yahoo</a></p> - <p><small>Hosted on GitHub Pages — Theme by <a href="https://github.com/orderedlist">orderedlist</a></small></p> - </footer> - </div> - <script src="javascripts/scale.fix.js"></script> -<script> - (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){ - (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o), - m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m) - })(window,document,'script','//www.google-analytics.com/analytics.js','ga'); - - ga('create', 'UA-586895-6', 'yahoo.github.io'); - ga('send', 'pageview'); - -</script> - </body> -</html> http://git-wip-us.apache.org/repos/asf/incubator-samoa/blob/7acb1c47/css/main.scss ---------------------------------------------------------------------- diff --git a/css/main.scss b/css/main.scss new file mode 100755 index 0000000..948735e --- /dev/null +++ b/css/main.scss @@ -0,0 +1,47 @@ +--- +# Only the main Sass file needs front matter (the dashes are enough) +--- +@charset "utf-8"; + + +$spacing-unit: 30px; + +@import + "syntax-highlighting" +; + +#sidebar { + float: left; + background: #F6F9FB; + border: 1px solid #E1E1E1; + padding: 0px 10px 10px 0px; + margin-left: 0px; + +} + +#sidebar a.current { + color: #E00000; +} + +#sidebar ul { + list-style: none; + font-size: 0.83em; + padding-left: 20px; +} + +#sidebar ul li { + margin-top: 3px; +} + + +#aboutcontent { + width: 70%; + margin-top:0px; + margin-left: 220px; +} + +#footer { + //margin: 100px; + //padding: 0; + font-size: 0.7em; +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-samoa/blob/7acb1c47/documentation/Adaptive-Model-Rules-Regressor.md ---------------------------------------------------------------------- diff --git a/documentation/Adaptive-Model-Rules-Regressor.md b/documentation/Adaptive-Model-Rules-Regressor.md new file mode 100644 index 0000000..ff6dc01 --- /dev/null +++ b/documentation/Adaptive-Model-Rules-Regressor.md @@ -0,0 +1,40 @@ +--- +title: Adaptive Model Rules Regressor +layout: documentation +documentation: true +--- +### Adaptive Model Rules Regressor +[Adaptive Model Rules (AMRules)](http://www.ecmlpkdd2013.org/wp-content/uploads/2013/07/251.pdf) is an innovative algorithm for learning regression rules with streaming data. In AMRules, the rule model consists of a set of normal rules and a default rule (a rule with no features). Hoeffding bound is used to define a confidence interval to decide whether to expand a rule. If the ratio of the 2 largest standard deviation reduction (SDR) measure among all potential features of a rule is is within this interval, the feature with the largest SDR will be added to the rule to expand it. If the default rule is expanded, it will become a normal rule and will be added to the model's rule set. A new default rule is initialized to replace the expanded one. A rule in the set might also be removed if the Page-Hinckley test indicates that its cumulative error exceed a threshold. + +### Vertical Adaptive Model Rules Regressor +Vertical Adaptive Model Rules Regressor (VAMR) is the vertical parallel implementation of AMRules in SAMOA. The diagram below shows the components of the implementation. + + +The _Source PI_ and _Evaluator PI_ are components of the [Prequential Evaluation task](Prequential-Evaluation-Task.html). The _Source PI_ produces the incoming instances while _Evaluator PI_ reads prediction results from VAMR and reports their accuracy and throughput. + +The core of VAMR implementation consists of one _Model Aggregator PI_ and multiple _Learner PIs_. Each _Learner PI_ is responsible for training a subset of rules. The _Model Aggregator PI_ manages the rule model (rule set and default rule) to compute the prediction results for incoming instances. It is also responsible for the training the default rule and creation of new rules. + +For each incoming instance from _Source PI_, _Model Aggregator PI_ appies the current rule set to compute the prediction. The instance is also forwarded from _Model Aggregator PI_ to the _Learner PI(s)_ to train those rules that cover this instance. If an instance is not covered by any rule in the set, the default rule will be used for prediction and will also be trained with this instance. When the default rule expands and create a new rule, the new rule will be sent from _Model aggregator PI_ to one of the _Learner PIs_. When the _Learner PIs_ expand or remove a rule, an update message is also sent back to the _Model Aggregator PI_. + +The number of _Learner PIs_ can be set with the `-p` option: + +``` +PrequentialEvaluationTask -l (com.yahoo.labs.samoa.learners.classifiers.rules.VerticalAMRulesRegressor -p 4) +``` + +### Horizontal Adaptive Model Rules Regressor +Horizontal Adaptive Model Rules Regressor (HAMR) is an extended implementation of VAMR. The components of a [[Prequential Evaluation task|Prequential Evaluation Task]] with HAMR are shown in the diagram below. + + +In HAMR, the _Model Aggregator PI_ is replicated, each processes only a partition of the incoming stream from _Source PI_. The default rule is moved from the _Model Aggregator PI_ to a special _Learner PI_, called _Default Rule Learner PI_. This new PI is reposible for both the training and predicting steps for default rule. + +For each incoming instance from _Source PI_, _Model Aggregator PIs_ apply the current rule set to compute the prediction. If the instance is covered by a rule in the set, its prediction is computed by the _Model Aggregator PI_ and, then, it is forwarded to the _Learner PI(s)_ for training. Otherwise, the instance is forwarded to _Default Rule Learner PI_ for both prediction and training. + +Newly created rules are sent from _Default Rule Learner PI_ to all _Model Aggregator PIs_ and one of the _Learner PIs_. Update messages are also sent from _Learner PIs_ to all _Model Aggregator PIs_ when a rule is expanded or removed. + +The number of _Learner PIs_ can be set with the `-p` option and the number of _Model Aggregator PIs_ can be set with the `-r` option: + +``` +PrequentialEvaluationTask -l (com.yahoo.labs.samoa.learners.classifiers.rules.HorizontalAMRulesRegressor -r 4 -p 2) +``` + http://git-wip-us.apache.org/repos/asf/incubator-samoa/blob/7acb1c47/documentation/Bagging-and-Boosting.md ---------------------------------------------------------------------- diff --git a/documentation/Bagging-and-Boosting.md b/documentation/Bagging-and-Boosting.md new file mode 100644 index 0000000..09572b6 --- /dev/null +++ b/documentation/Bagging-and-Boosting.md @@ -0,0 +1,33 @@ +--- +title: Bagging and Boosting +layout: documentation +documentation: true +--- +Ensemble methods are combinations of several models whose individual predictions are combined in some manner (e.g., averaging or voting) to form a final prediction. When tackling non-stationary concepts, ensembles of classifiers have several advantages over single classifier methods: they are easy to scale and parallelize, they can adapt to change quickly by pruning under-performing parts of the ensemble, and they therefore usually also generate more accurate concept descriptions. + +Bagging and boosting are traditional ensemble methods for streaming environments. +It is possible to use the classifiers available in [MOA](http://moa.cms.waikato.ac.nz) by using the [SAMOA-MOA](https://github.com/samoa-moa/samoa-moa) adapter. + +### Bagging +You can use Bagging as a SAMOA learner, specifying the number of learners to use with parameter `-s` and the base learner to use with parameter `-l` + +`(classifiers.ensemble.Bagging -s 10 -l (classifiers.trees.VerticalHoeffdingTree))` + +###### Only with SAMOA-MOA adapter +`(classifiers.ensemble.Bagging -s 10 -l (classifiers.SingleClassifier -l (MOAClassifierAdapter -l moa.classifiers.trees.HoeffdingTree)))` + +### Adaptive Bagging +If data is evolving, it is better to use an adaptive version of bagging, where each base learner has a change detector that monitors its accuracy. When the accuracy of a base learner decreases, a new base learner is built to replace it. + +`(classifiers.ensemble.AdaptiveBagging -s 10 -l (classifiers.trees.VerticalHoeffdingTree))` + +###### Only with SAMOA-MOA adapter +`(classifiers.ensemble.AdaptiveBagging -s 10 -l (classifiers.SingleClassifier -l (com.yahoo.labs.samoa.learners.classifiers.MOAClassifierAdapter -l moa.classifiers.trees.HoeffdingTree)))` + +### Boosting +Boosting is a well known ensemble method, that has a very good performance in non-streaming setting. SAMOA implements the version of Oza and Russel (_Nikunj C. Oza, Stuart J. Russell: Experimental comparisons of online and batch versions of bagging and boosting. KDD 2001:359-364_) + +`(classifiers.ensemble.Boosting -s 10 -l (classifiers.trees.VerticalHoeffdingTree))` + +###### Only with SAMOA-MOA adapter +`(classifiers.ensemble.Boosting -s 10 -l (classifiers.SingleClassifier -l (MOAClassifierAdapter -l moa.classifiers.trees.HoeffdingTree)))` http://git-wip-us.apache.org/repos/asf/incubator-samoa/blob/7acb1c47/documentation/Building-SAMOA.md ---------------------------------------------------------------------- diff --git a/documentation/Building-SAMOA.md b/documentation/Building-SAMOA.md new file mode 100644 index 0000000..a0ebb9b --- /dev/null +++ b/documentation/Building-SAMOA.md @@ -0,0 +1,44 @@ +--- +title: Building Apache SAMOA +layout: documentation +documentation: true +--- +To build SAMOA to run on local mode, on your own computer without a cluster, is simple as cloning the repository and installing it. + +```bash +git clone http://git.apache.org/incubator-samoa.git +cd incubator-samoa +mvn package +``` +The deployable jar for SAMOA will be in `target/SAMOA-Local-0.3.0-SNAPSHOT.jar`. + +### Storm +Simply clone the repository and install SAMOA. + +```bash +git clone http://git.apache.org/incubator-samoa.git +cd incubator-samoa +mvn -Pstorm package +``` + +The deployable jar for SAMOA will be in `target/SAMOA-Storm-0.3.0-SNAPSHOT.jar`. + +* [1.1 Executing SAMOA with Apache Storm](Executing-SAMOA-with-Apache-Storm.html) + +### S4 + +If you want to compile SAMOA for Apache S4, you will need to install the S4 dependencies manually as explained in [Executing SAMOA with Apache S4](Executing-SAMOA-with-Apache-S4.html). + +Once the dependencies are installed, you can simply clone the repository and install SAMOA. + +```bash +git clone http://git.apache.org/incubator-samoa.git +cd incubator-samoa +mvn -P<variant> package # where variant is "storm" or "s4" + +mvn -Pstorm,s4 package # e.g., to get both versions +``` + +The deployable jars for SAMOA will be in `target/SAMOA-<variant>-<version>-SNAPSHOT.jar`. For example, for S4 `target/SAMOA-S4-0.3.0-SNAPSHOT.jar`. + +* [1.2 Executing SAMOA with Apache S4](Executing-SAMOA-with-Apache-S4.html) http://git-wip-us.apache.org/repos/asf/incubator-samoa/blob/7acb1c47/documentation/Bylaws.md ---------------------------------------------------------------------- diff --git a/documentation/Bylaws.md b/documentation/Bylaws.md new file mode 100644 index 0000000..6a9005f --- /dev/null +++ b/documentation/Bylaws.md @@ -0,0 +1,107 @@ +--- +title: Apache SAMOA Bylaws +layout: documentation +documentation: true +--- +# SAMOA Bylaws (Draft) + +This document defines the bylaws under which the Apache SAMOA project operates. + +Apache SAMOA is a project of the Apache Software Foundation (ASF). The foundation holds the copyright on the code in the Apache SAMOA codebase. The foundation [FAQ](http://www.apache.org/foundation/faq.html) explains the operation and background of the foundation. + +Apache SAMOA is typical of Apache projects in that it operates under a set of principles, known collectively as the *Apache Way*. If you are new to Apache development, please refer to the [Apache Incubator](http://incubator.apache.org) for more information on how Apache projects operate. + + +## Roles and Responsibilities + +Apache projects define a set of roles with associated rights and responsibilities. These roles govern which tasks an individual may perform within the project. The roles are defined in the following sections. + +### Users: + +The most important participants in the project are people who use our software. The majority of our developers start out as users and guide their development efforts from the user's perspective. + +Users contribute to Apache projects by providing feedback to developers in the form of bug reports and feature suggestions. In addition, users participate in the Apache community by helping other users on mailing lists and user support forums. + +### Contributors: + +All of the volunteers who are contributing time, code, documentation, or resources to the SAMOA project. A contributor that makes sustained, welcome contributions to the project may be invited to become a Committer, though the exact timing of such invitations depends on many factors. + +### Committers: + +The project's Committers are responsible for the project's technical management. Committers have access to all project source repositories. Committers may cast binding votes on any technical discussion regarding SAMOA. + +Committer access is by invitation only and must be approved by lazy consensus of the active PMC members. A Committer is considered emeritus by their own declaration or by not contributing in any form to the project for over six months. An emeritus Committer may request reinstatement of commit access from the PMC. Such reinstatement is subject to lazy consensus approval of active PMC members. + +All Apache Committers are required to have a signed [Contributor License Agreement (CLA)](http://www.apache.org/licenses/icla.txt) on file with the Apache Software Foundation. There is a [Committer FAQ](http://www.apache.org/dev/committers.html) which provides more details on the requirements for Committers + +A Committer who makes a sustained contribution to the project may be invited to become a member of the PMC. The form of contribution is not limited to code. It can also include other activities such as code review, helping out users on the mailing lists, documentation, and testing. + +### Project Management Committee (PMC): + +The PMC is responsible to the board and the ASF for the management and oversight of the Apache SAMOA codebase. The responsibilities of the PMC include + + * Deciding what is distributed as products of the Apache SAMOA project. In particular all releases must be approved by the PMC. + * Maintaining the project's shared resources, including the codebase repository, mailing lists, websites. + * Speaking on behalf of the project. + * Resolving license disputes regarding products of the project. + * Nominating new PMC members and Committers. + * Maintaining these bylaws and other guidelines of the project. + +Membership of the PMC is by invitation only and must be approved by consensus approval of the active PMC members. A PMC member is considered "emeritus" by their own declaration or by not contributing in any form to the project for over six months. An emeritus member may request reinstatement to the PMC. Such reinstatement is subject to consensus approval of the active PMC members. + +The chair of the PMC is appointed by the ASF board. The chair is an office holder of the Apache Software Foundation (Vice President, Apache SAMOA) and has primary responsibility to the board for the management of the projects within the scope of the SAMOA PMC. The chair reports to the board quarterly on developments within the SAMOA project. + +The chair of the PMC is rotated annually. When the chair is rotated, or if the current chair of the PMC resigns, the PMC votes to recommend a new chair using [Single Transferable Vote (STV)](http://wiki.apache.org/general/BoardVoting) voting. The decision must be ratified by the ASF board. + +## Voting + +Decisions regarding the project are made by votes on the primary project development mailing list ([email protected]). Where necessary, PMC voting may take place on the private SAMOA PMC mailing list. Votes are clearly indicated by subject line starting with [VOTE]. Votes may contain multiple items for approval and these should be clearly separated. Voting is carried out by replying to the vote mail. Voting may take four flavors. + +| Vote | Meaning | +|------|---------| +| +1 | 'Yes', 'Agree', or 'the action should be performed'. | +| +0 | Neutral about the proposed action (or mildly negative but not enough so to want to block it). | +| -1 | This is a negative vote. On issues where consensus is required, this vote counts as a veto. All vetoes must contain an explanation of why the veto is appropriate. Vetoes with no explanation are void. It may also be appropriate for a -1 vote to include an alternative course of action. | + +All participants in the SAMOA project are encouraged to show their agreement with or against a particular action by voting. For technical decisions, only the votes of active Committers are binding. Non-binding votes are still useful for those with binding votes to understand the perception of an action in the wider SAMOA community. For PMC decisions, only the votes of active PMC members are binding. + +Voting can also be applied to changes already made to the SAMOA codebase. These typically take the form of a veto (-1) in reply to the commit message sent when the commit is made. Note that this should be a rare occurrence. All efforts should be made to discuss issues when they are still patches before the code is committed. + +Only active (i.e., non-emeritus) Committers and PMC members have binding votes. + +## Approvals + +These are the types of approval that can be sought. Different actions require different types of approval. + +| Approval | Requirements | +|-------------------|--------------| +| Consensus | requires all binding-vote holders to cast +1 votes and no binding -1 vetoes (consensus votes are rarely required due to the impracticality of getting all eligible voters to cast a vote). | +| 2/3 Majority | requires at least 2/3 of binding-vote holders to cast +1 votes. (2/3 majority is typically used for actions that affect the foundation of the project, e.g., adopting a new codebase to replace an existing product). | +| Lazy Consensus | requires 2 binding +1 votes and no -1 votes ('silence gives assent'). | +| Lazy Majority | requires 3 binding +1 votes and more binding +1 votes than -1 vetoes. | +| Lazy 2/3 Majority | requires at least 3 votes and twice as many +1 votes as -1 vetoes. | + +### Vetoes + +A valid, binding veto cannot be overruled. If a veto is cast, it must be accompanied by a valid reason explaining the reasons for the veto. The validity of a veto, if challenged, can be confirmed by anyone who has a binding vote. This does not necessarily signify agreement with the veto - merely that the veto is valid. + +If you disagree with a valid veto, you must lobby the person casting the veto to withdraw their veto. If a veto is not withdrawn, any action that has been vetoed must be reversed in a timely manner. + +## Actions + +This section describes the various actions which are undertaken within the project, the corresponding approval required for that action and those who have binding votes over the action. + +| Action | Description | Approval | Binding Votes | Minimum Length | Mailing List | +|--------|-------------|----------|---------------|----------------|--------------| +| Code Change | A change made to a codebase of the project and committed by a committer. This includes source code, documentation, and website content. | Lazy Consensus (with at least one +1 vote from someone who has not authored the patch). The code can be committed as soon as the required number of binding votes is reached. | Active Committers | 1 day | JIRA or GitHub pull request (with notification sent to dev@) | +| Release Plan | Defines the timetable and actions for a release. The plan also nominates a Release Manager. | Lazy Majority | Active Committers | 3 days | dev@ | +| Product Release | Accepting the official release of a product of the project. | Lazy Majority | Active PMC members | 3 days | dev@ | +| Adoption of New Codebase | Replacing the codebase for an existing, released product with an alternative codebase. If such a vote fails to gain approval, the existing code base will continue. This action also covers the creation of new sub-projects and sub-modules within the project. | Lazy 2/3 Majority | Active PMC members | 7 days | dev@ | +| New Committer | Electing a new Committer for the project. | Lazy Consensus | Active PMC members | 7 days | private@ | +| New PMC Member | Promoting a Committer to the PMC of the project. | Consensus | Active PMC members | 7 days | private@ | +| Emeritus PMC Member re-instatement | When an emeritus PMC member requests to be re-instated as an active PMC member. | Consensus | Active PMC members | 7 days | private@ | +| Emeritus Committer re-instatement | When an emeritus Committer requests to be re-instated as an active committer. | Consensus | Active PMC members | 7 days | private@ | +| Committer Removal | When removal of commit privileges is sought. Note: Such actions will also be referred to the ASF board by the PMC chair. | Consensus | Active PMC members (excluding the committer in question if member of the PMC) | 7 Days | private@ | +| PMC Member Removal | When removal of a PMC member is sought. Note: Such actions will also be referred to the ASF board by the PMC chair. | Consensus | Active PMC members (excluding the member in question) | 7 Days | private@ | +| Modifying Bylaws | Modifying this document. | 2/3 Majority | Active PMC members | 7 Days | dev@ | + http://git-wip-us.apache.org/repos/asf/incubator-samoa/blob/7acb1c47/documentation/Content-Event.md ---------------------------------------------------------------------- diff --git a/documentation/Content-Event.md b/documentation/Content-Event.md new file mode 100644 index 0000000..0a8ae9f --- /dev/null +++ b/documentation/Content-Event.md @@ -0,0 +1,120 @@ +--- +title: Content Event +layout: documentation +documentation: true +--- +A message or an event is called Content Event in SAMOA. As the name suggests, it is an event which contains content which needs to be processed by the processors. + +###1. Implementation +ContentEvent has been implemented as an interface in SAMOA. Users need to implement `ContentEvent` interface to create their custom message classes. As it can be seen in the following code, key is the necessary part of a message. + +``` +package com.yahoo.labs.samoa.core; + +public interface ContentEvent extends java.io.Serializable { + + public String getKey(); + + public void setKey(String str); + + public boolean isLastEvent(); +} +``` +###2. Methods +Following is a brief description of methods. + +#####2.1 `String getKey()` +Each message is identified by a key in SAMOA. All user-defined message classes should have a key state variable. Each instance of the custom message should be assigned a key. This method should return the key of the respective message. + +#####2.2 `void setKey(String str)` +This method is used to assign a key to the message. + +#####2.3 `boolean isLastEvent()` +This method lets SAMOA know that this message is the last message. + +###3. Example +Following is the example of a `Message` class which implements `ContentEvent` interface. As `ContentEvent` is an interface, it can not hold variables. A user-defined message class should have its own data variables and its getter methods. In the following example, `value` variable of type `Object` is added to the class. Using a generic type `Object` is beneficial in the sense that any object can be passed to it and later it can be casted back to the original type. The following example also adds a `streamId` variable which stores the `id` of the stream the message belongs to. This is not a requirement but can be beneficial in certain applications. + +``` +import com.yahoo.labs.samoa.core.ContentEvent; + +/** + * A general key-value message class which adds a stream id in the class variables + * Stream id information helps in determining to which stream does the message belongs to. + */ +public class Message implements ContentEvent { + + /** + * To tell if the message is the last message of the stream. This may be required in some applications where + * a stream can cease to exist + */ + private boolean last=false; + /** + * Id of the stream to which the message belongs + */ + private String streamId; + /** + * The key of the message. Can be any sting value. Duplicates are allowed. + */ + private String key; + /** + * The value of the message. Can be any object. Casting may be necessary to the desired type. + */ + private Object value; + + public Message() + {} + + /** + * @param key + * @param value + * @param isLastEvent + * @param streamId + */ + public Message(String key, Object value, boolean isLastEvent, String streamId) + { + this.key=key; + this.value = value; + this.last = isLastEvent; + this.streamId=streamId; + } + + @Override + public String getKey() { + return key; + } + + @Override + public void setKey(String str) { + this.key = str; + } + + @Override + public boolean isLastEvent() { + return last; + } + + /** + * @return value of the message + */ + public String getValue() + { + return value.toString(); + } + + /** + * @return id of the stream to which the message belongs + */ + public String getStreamId() { + return streamId; + } + /** + * @param streamId + */ + public void setStreamId(String streamId) { + this.streamId = streamId; + } + +} + +``` http://git-wip-us.apache.org/repos/asf/incubator-samoa/blob/7acb1c47/documentation/Developing-New-Tasks-in-SAMOA.md ---------------------------------------------------------------------- diff --git a/documentation/Developing-New-Tasks-in-SAMOA.md b/documentation/Developing-New-Tasks-in-SAMOA.md new file mode 100644 index 0000000..b028bde --- /dev/null +++ b/documentation/Developing-New-Tasks-in-SAMOA.md @@ -0,0 +1,163 @@ +--- +title: Developing New Tasks in Apache SAMOA +layout: documentation +documentation: true +--- +A _task_ is a machine learning related activity such as a specific evaluation for a classifier. For instance the _prequential evaluation_ task is a task that uses each instance first for testing and then for training a model built using a specific classification algorithm. A task corresponds to a topology in SAMOA. + +In this tutorial, we will develop a simple Hello World task. + +### Hello World Task +The Hello World task consists of a source processor, a destination processor with a parallelism hint setting, and a stream that connects the two. The source processor will generate a random integer which will be sent to the destination processor. The figure below shows the layout of Hello World task. + + + +To develop the task, we create a new class that implements the interface `com.yahoo.labs.samoa.tasks.Task`. For convenience we also implement `com.github.javacliparser.Configurable` which allows to parse command-line options. + +The `init` method builds the topology by instantiating the necessary `Processors`, `Streams` and connecting the source processor with the destination processor. + +### Hello World Source Processor +We need a source processor which is an instance of `EntranceProcessor` to start a task in SAMOA. In this tutorial, the source processor is `HelloWorldSourceProcessor`. + +The SAMOA runtime invokes the `nextEvent` method of `EntranceProcessor` until its `hasNext` method returns false. Each call to `nextEvent` should return the next `ContentEvent` to be sent to the topology. In this tutorial, `HelloWorldSourceProcessor` sends events of type `HelloWorldContentEvent`. + +Here is the relevant code in `HelloWorldSourceProcessor`: + +``` + private Random rnd; + private final long maxInst; + private long count; + + @Override + public boolean hasNext() { + return count < maxInst; + } + + @Override + public ContentEvent nextEvent() { + count++; + return new HelloWorldContentEvent(rnd.nextInt(), false); + } +``` + +We also need to create a new type of `ContentEvent` to hold our data. In this tutorial we call it `HelloWorldContentEvent` and its content is simply an integer. + +``` +public class HelloWorldContentEvent implements ContentEvent { + + private static final long serialVersionUID = -2406968925730298156L; + private final boolean isLastEvent; + private final int helloWorldData; + + public HelloWorldContentEvent(int helloWorldData, boolean isLastEvent) { + this.isLastEvent = isLastEvent; + this.helloWorldData = helloWorldData; + } + + @Override + public String getKey() { + return null; + } + + @Override + public void setKey(String str) { + // do nothing, it's key-less content event + } + + @Override + public boolean isLastEvent() { + return isLastEvent; + } + + public int getHelloWorldData() { + return helloWorldData; + } + + @Override + public String toString() { + return "HelloWorldContentEvent [helloWorldData=" + helloWorldData + "]"; + } +} +``` + +### Hello World Destination Processor +The destination processor for SAMOA is pretty straightforward and it will print the data from the event. + +``` +public class HelloWorldDestinationProcessor implements Processor { + + private static final long serialVersionUID = -6042613438148776446L; + private int processorId; + + @Override + public boolean process(ContentEvent event) { + System.out.println(processorId + ": " + event); + return true; + } + + @Override + public void onCreate(int id) { + this.processorId = id; + } + + @Override + public Processor newProcessor(Processor p) { + return new HelloWorldDestinationProcessor(); + } +} +``` + +### Putting It All Together +To put all the components together, we need to go back to class `HelloWorldTask`. First, we need to implement the code for setting up the `TopologyBuilder`. This code is necessary to be able to run on multiple platforms. + +``` + @Override + public void setFactory(ComponentFactory factory) { + builder = new TopologyBuilder(factory); + logger.debug("Sucessfully instantiating TopologyBuilder"); + builder.initTopology(evaluationNameOption.getValue()); + logger.debug("Sucessfully initializing SAMOA topology with name {}", evaluationNameOption.getValue()); + } +``` + +After this method is called we have a functioning builder to get components for our topology. Next, the `init` method is called by SAMOA to start the task. +First we instantiate the source `EntranceProcessor`. +After adding the entrance processor to the topology, we create a stream originating from it. We use the create stream method of `TopologyBuilder`. +Next we create the destination processor and connect it to the stream by using shuffle grouping. +Once we have created all the components, we use the builder to build the topology. + +``` + @Override + public void init() { + // create source EntranceProcesor + sourceProcessor = new HelloWorldSourceProcessor(instanceLimitOption.getValue()); + builder.addEntranceProcessor(sourceProcessor); + + // create Stream + Stream stream = builder.createStream(sourceProcessor); + + // create destination Processor + destProcessor = new HelloWorldDestinationProcessor(); + builder.addProcessor(destProcessor, helloWorldParallelismOption.getValue()); + builder.connectInputShuffleStream(stream, destProcessor); + + // build the topology + helloWorldTopology = builder.build(); + logger.debug("Successfully built the topology"); + } +``` + +### Running It +To run the example in local mode: + +``` +bin/samoa local target/SAMOA-Local-0.0.1-SNAPSHOT.jar "com.yahoo.labs.samoa.examples.HelloWorldTask -p 4 -i 100" +``` + +To run the example in Storm local mode: + +``` +java -cp $STORM_HOME/lib/*:$STORM_HOME/storm-0.8.2.jar:target/SAMOA-Storm-0.0.1-SNAPSHOT.jar com.yahoo.labs.samoa.LocalStormDoTask "com.yahoo.labs.samoa.examples.HelloWorldTask -p 4 -i 1000" +``` + +All the code for the HelloWorldTask and its components can be found [here](https://github.com/yahoo/samoa/tree/master/samoa-api/src/main/java/com/yahoo/labs/samoa/examples). http://git-wip-us.apache.org/repos/asf/incubator-samoa/blob/7acb1c47/documentation/Distributed-Stream-Clustering.md ---------------------------------------------------------------------- diff --git a/documentation/Distributed-Stream-Clustering.md b/documentation/Distributed-Stream-Clustering.md new file mode 100644 index 0000000..2a04946 --- /dev/null +++ b/documentation/Distributed-Stream-Clustering.md @@ -0,0 +1,22 @@ +--- +title: Distributed Stream Clustering +layout: documentation +documentation: true +--- +## Apache SAMOA Clustering Algorithm ## +The SAMOA Clustering Algorithm is invoked by using the `ClusteringEvaluation` task. The clustering task can be executed with default values just by running: + +``` +bin/samoa storm target/SAMOA-Storm-0.0.1-SNAPSHOT.jar "ClusteringEvaluation" +``` + +Parameters: + +* `-l`: clusterer to train +* `-s`: stream to learn from +* `-i`: maximum number of instances to test/train on (-1 = no limit) +* `-f`: how many instances between samples of the learning performance +* `-n`: evaluation name (default: ClusteringEvaluation_TimeStamp) +* `-d`: file to append intermediate csv results to + +In terms of the SAMOA API, Clustering Evaluation consists of a `source` processor, a `clusterer`, and a `evaluator` processor. `Source` processor sends the instances to the classifier using `source` stream. The clusterer sends the clustering results to the `evaluator` processor via the `result` stream. The `source Processor` corresponds to the `-s` option of Clustering Evaluation, and the clusterer corresponds to the `-l` option. http://git-wip-us.apache.org/repos/asf/incubator-samoa/blob/7acb1c47/documentation/Distributed-Stream-Frequent-Itemset-Mining.md ---------------------------------------------------------------------- diff --git a/documentation/Distributed-Stream-Frequent-Itemset-Mining.md b/documentation/Distributed-Stream-Frequent-Itemset-Mining.md new file mode 100644 index 0000000..1730f6c --- /dev/null +++ b/documentation/Distributed-Stream-Frequent-Itemset-Mining.md @@ -0,0 +1,59 @@ +--- +title: Distributed Frequent Itemset Mining +layout: documentation +documentation: true +--- +## 1. Introduction +SAMOA takes a micro-batching approach to frequent itemset mining (FIM). It uses [PARMA](https://dl.acm.org/citation.cfm?id=2396776) as a base algorithm for distributed sample-based frequent itemset mining. PARMA provides the guaranty that all the frequent itemsets would be present in the result that it returns.It also returns some false positives. The problem with FIM in streams is that the stream has an evolving nature. The itemsets that were frequent last year may not be frequent this year. To handle this, SAMOA implements [Time Biased Sampling](https://dl.acm.org/citation.cfm?id=1164180) approach. This sampling method depends on a parameter _lambda_ which determines the size of the reservoir sample. This also tells us how much biased the sample would be towards newer itemsets. As PARMA has its own way of determining sample sizes, SAMOA does not allow users to choose _lambda_ and determines its value using the sample size determined by PARMA using the approximation `lambda = 1/sam pleSize`. +## 2. Concepts +SAMOA implements FIM for streams in three processors i.e. StreamSourceProcessor, SamplerProcessor and AggregatorProcessor. The tasks of each of these are explained below. + +1. StreamSourceP takes as input the input transaction file. StreamSourceProcessor (Entrance PI) starts sending the transactions randomly to SamplerProcessor instances. The number of SamplerProcessors to instantiate is taken as an argument from the user but is verified by PARMA. PARMA determines this number based on the `epsilon` and `phi` parameters provided by the user. StreamSourceProcessor sends an FPM='yes' command to all the instances of SamplerProcessor after 2M transactions where M=numSamples*sampleSize. After first FPM='yes' command, all later FPM='yes' commands are sent after `fpmGap` transactions which is one of the parameter SAMOA FIM task takes as input. + +2. All the instances of SamplerProcessor start building a Time Biased Reservoir Sample in which newer transactions have more weight. Time biased sampling is the default approach but user can provide his own sampler by implementing `samoa.samplers.SamplerInterface`. When a SamplerProcessor receives FPM='yes' command, it starts FIM/FPM on the reservoir irrespective of whether the reservoir is full or not. When it completes, it sends the result item-sets to the AggregatorProcessor with the epoch/batch id. At the end of the result, each SamplerProcessor sends the (âepoch_endâ,<epochNum>) message to the AggregatorProcessor. + +3. AggregatorProcessor receives the result item-sets from all SamplerProcessors. It maintains different queues for different batch ids and also maintains a count of the number of SamplerProcessors which have finished sending their results for a corresponding batch/epoch. Whenever the `epoch_end` message count becomes equal to the number of instances of SampleProcessor, AggregatorProcessor aggregates the results and stores it in the file system using the output path specified by the user. + +In this way, epochs never overlap.If `fpmGap` is small and the StreamSourceProcessor dispatches an FPM='yes' command before the slowest SamplerProcessor finishes FIM on the last epoch, the speed of the global FIM will be equal to the local FIM of the slowest SamplerProcessor. (or AggregatorProcessor if it is slower than the slowest SamplerProcessor) + + + +## 3. How to run +Following is an example of the command used to run the SAMOA FIM task. + +``` +bin/samoa storm target/SAMOA-Storm-0.0.1-SNAPSHOT.jar "FpmTask -t Myfpmtopology -r (com.yahoo.labs.samoa.fpm.processors.FileReaderProcessor -i /datasets/freqDataCombined.txt) -m (com.yahoo.labs.samoa.fpm.processors.ParmaStreamFpmMiner -e .1 -d .1 -f 10 -t 20 -n 23 -p 0.08 -b 100000 -s com.yahoo.labs.samoa.samplers.reservoir.TimeBiasedReservoirSampler) -w (com.yahoo.labs.samoa.fpm.processors.FileWriterProcessor -o /output/outPARMA) " +``` + +Parameters: +To run an FIM task, four parameters are required + +* `-t`: Topology name (Can be any name) +* `-r`: The reader class +* `-m`: The miner class +* `-w`: The writer class + +In the example above, `FileReaderProcessor` is used as a reader class. It takes only one parameter: + +* `-i`: Path to input file + +Similarly, `FileWriterProcessor` is used as a writer class. It takes only one parameter: + +* `-o`: Path to output file + +SAMOA comes with a built-in distributed frequent mining algorithm PARMA as described above but users can plug-in their custom miners by implementing the `FpmMinerInterface`. The built-in PARMA miner can be used with the following parameters: + +* `-e`: epsilon parameter for [PARMA](https://dl.acm.org/citation.cfm?id=2396776) +* `-d`: delta parameter for [PARMA](https://dl.acm.org/citation.cfm?id=2396776) +* `-f`: minimum frequency (percentage) of a frequent itemset +* `-t`: maximum length of a transaction +* `-n`: number of samples to maintain +* `-a`: number of aggregators to initiate +* `-p`: phi parameter for [PARMA](https://dl.acm.org/citation.cfm?id=2396776) +* `-i`: path to input file +* `-o`: path to output file +* `-b`: batch size or fpmGap (Number of transactions after which FIM should be performed) +* `-s`: Sampler Class to be used for sampling at each node + +## Note +This method is currently unavailable in the master branch of SAMOA due to licensing restriction. http://git-wip-us.apache.org/repos/asf/incubator-samoa/blob/7acb1c47/documentation/Executing-SAMOA-with-Apache-S4.md ---------------------------------------------------------------------- diff --git a/documentation/Executing-SAMOA-with-Apache-S4.md b/documentation/Executing-SAMOA-with-Apache-S4.md new file mode 100644 index 0000000..d14bb38 --- /dev/null +++ b/documentation/Executing-SAMOA-with-Apache-S4.md @@ -0,0 +1,101 @@ +--- +title: Executing Apache SAMOA with Apache S4 +layout: documentation +documentation: true +--- + +In this tutorial page we describe how to execute SAMOA on top of Apache S4. + +## Prerequisites ## +The following dependencies are needed to run SAMOA smoothly on Apache S4 + +* [Gradle](http://www.gradle.org/) +* [Apache S4](https://incubator.apache.org/s4/) + +## Gradle ## +Gradle is a build automation tool and is used to build Apache S4. The installation guide can be found [here.](http://www.gradle.org/docs/current/userguide/installation.html) The following instructions is a simplified installation guide. + +1. Download Gradle binaries from [downloads](http://services.gradle.org/distributions/gradle-1.6-bin.zip), or from the console type `wget http://services.gradle.org/distributions/gradle-1.6-bin.zip` +1. Unzip the file `unzip gradle-1.6-bin.zip` +1. Set the Gradle environment variable: `export GRADLE_HOME=/foo/bar/gradle-1.6` +1. Add to the systems path `export PATH=$PATH:$GRADLE_HOME/bin` +1. Install Gradle by running `gradle` + +Now you are all set to install Apache S4 + +## Apache S4 ## +S4 is a general-purpose, distributed, scalable, fault-tolerant, pluggable platform that allows programmers to easily develop applications for processing continuous unbounded streams of data. The installation process is as follows: + +1. Download the latest Apache S4 release from [Apache S4 0.6.0](http://www.apache.org/dist/incubator/s4/s4-0.6.0-incubating/apache-s4-0.6.0-incubating-src.zip) or from command line `wget http://www.apache.org/dist/incubator/s4/s4-0.6.0-incubating/apache-s4-0.6.0-incubating-src.zip` or clone from git. +`git clone https://git-wip-us.apache.org/repos/asf/incubator-s4.git`. +1. Unzip the file `unzip apache-s4-0.6.0-incubating-src.zip` or go in the cloned directory. +1. Set the Apache S4 environment variable `export S4_HOME=/foo/bar/apache-s4-0.6.0-incubating-src`. +1. Add the S4_HOME to the system PATH. `export PATH=$PATH:$S4_HOME`. +1. Once the previous steps are done we can proceed to build and install Apache S4. +1. You can have a look at the available build tasks by typing `gradle tasks`. +1. There are some dependencies issues, therefore you should run the wrapper task first by typing `gradle wrapper`. +1. Install the artifacts for Apache S4 by running `gradle install` in the S4_HOME directory. +1. Install the S4-TOOLS, `gradle s4-tools::installApp`. + +Done. Now you can configure and run your Apache S4 cluster. + +*** + +## Building SAMOA ## +Once the S4 dependencies are installed, you can simply clone the repository and install SAMOA. + +```bash +git clone http://git.apache.org/incubator-samoa.git +cd incubator-samoa +mvn -Ps4 package +``` + +The deployable jars for SAMOA will be in `target/SAMOA-<variant>-<version>-SNAPSHOT.jar`. For example, in our case for S4 `target/SAMOA-S4-0.3.0-SNAPSHOT.jar`. + +*** + +## SAMOA-S4 Configuration ## +This section will go through the `bin/samoa-s4.properties` file and how to configure it. +In order for SAMOA to run correctly in a distributed environment there are some variables that need to be defined. Since Apache S4 uses [ZooKeeper](https://zookeeper.apache.org/) for cluster management we need to define where it is running. + + # Zookeeper Server + zookeeper.server=localhost + zookeeper.port=2181 + +Apache S4 also distributes the application via HTTP, therefore the server and port which contains the S4 application must be provided. + + # Simple HTTP Server providing the packaged S4 jar + http.server.ip=localhost + http.server.port=8000 + +Apache S4 uses the concept of logical clusters to define a group of machines, which are identified by an ID and start serving on a specific port. + + # Name of the S4 cluster + cluster.name=cluster + cluster.port=12000 + +SAMOA can be deployed on a single machine using only one resource or in a cluster environments. The following property can be defined to deploy as a `local` application or on a `cluster`. + + # Deployment strategy + samoa.deploy.mode=local + +*** + +## SAMOA S4 Deployment ## + +In order to deploy SAMOA in a distributed environment you **MUST** configure the `bin/samoa-s4.properties` file correctly. If you are running locally it is optional to modify the properties file. + +The deployment is done by running the SAMOA execution script `bin/samoa` with some additional parameters. +The execution syntax is as follows: +`bin/samoa <platform> <jar-location> <task & options>` + +Example: + + bin/samoa S4 target/SAMOA-S4-0.0.1-SNAPSHOT.jar "ClusteringEvaluation" + +The \<platform\> can be s4 or storm. + +The \<jar-location\> must be the absolute path to the platform specific jar file. + +The \<task & options\> should be the name of a known task and the options belonging to that task. +
