<commit_before>/*! (C) Cookie Banner v1.2.2 - MIT License - http://cookiebanner.eu/ */
<commit_msg>Build dist/cookiebanner.min.js from latest master<commit_after>/*! (C) Cookie Banner v1.2.2 - MIT License - http://cookiebanner.eu/ */
!function(context){"use strict";function contentLoaded(e,t){var i=!1,o=!0,n=e.document,s=n.documentElement,a=n.addEventListener?"addEventListener":"attachEvent",r=n.addEventListener?"removeEventListener":"detachEvent",c=n.addEventListener?"":"on",l=function(o){"readystatechange"==o.type&&"complete"!=n.readyState||(("load"==o.type?e:n)[r](c+o.type,l,!1),!i&&(i=!0)&&t.call(e,o.type||o))},p=function(){try{s.doScroll("left")}catch(e){return void setTimeout(p,50)}l("poll")};if("complete"==n.readyState)t.call(e,"lazy");else{if(n.createEventObject&&s.doScroll){try{o=!e.frameElement}catch(e){}o&&p()}n[a](c+"DOMContentLoaded",l,!1),n[a](c+"readystatechange",l,!1),e[a](c+"load",l,!1)}}var win=context,doc=win.document,global_instance_name="cbinstance",Cookies={get:function(e){return decodeURIComponent(doc.cookie.replace(new RegExp("(?:(?:^|.*;)\\s*"+encodeURIComponent(e).replace(/[-.+*]/g,"\\$&")+"\\s*\\=\\s*([^;]*).*$)|^.*$"),"$1"))||null},set:function(e,t,i,o,n,s){if(!e||/^(?:expires|max-age|path|domain|secure)$/i.test(e))return!1;var a="";if(i)switch(i.constructor){case Number:a=i===1/0?"; expires=Fri, 31 Dec 9999 23:59:59 GMT":"; max-age="+i;break;case String:a="; expires="+i;break;case Date:a="; expires="+i.toUTCString()}return doc.cookie=encodeURIComponent(e)+"="+encodeURIComponent(t)+a+(n?"; domain="+n:"")+(o?"; path="+o:"")+(s?"; secure":""),!0},has:function(e){return new RegExp("(?:^|;\\s*)"+encodeURIComponent(e).replace(/[-.+*]/g,"\\$&")+"\\s*\\=").test(doc.cookie)},remove:function(e,t,i){return!(!e||!this.has(e))&&(doc.cookie=encodeURIComponent(e)+"=; expires=Thu, 01 Jan 1970 00:00:00 GMT"+(i?"; domain="+i:"")+(t?"; path="+t:""),!0)}},Utils={merge:function(){var e,t={},i=0,o=arguments.length;if(0===o)return t;for(;i<o;i++)for(e in arguments[i])Object.prototype.hasOwnProperty.call(arguments[i],e)&&(t[e]=arguments[i][e]);return t},str2bool:function(e){switch(e=String(e),e.toLowerCase()){case"false":case"no":case"0":case"":return!1;default:return!0}},fade_in:function(e){e.style.opacity<1&&(e.style.opacity=(parseFloat(e.style.opacity)+.05).toFixed(2),win.setTimeout(function(){Utils.fade_in(e)},50))},fade_out:function(e,t){if("undefined"!=typeof e){e.style.opacity=1;var i=t/1e3;e.style.transition="opacity "+i+"s ease",e.style.opacity=0,setTimeout(function(){e.parentNode.removeChild(e)},t)}},get_data_attribs:function(script){var data={};if(Object.prototype.hasOwnProperty.call(script,"dataset"))data=script.dataset;else{var attribs=script.attributes,key;for(key in attribs)if(Object.prototype.hasOwnProperty.call(attribs,key)){var attr=attribs[key];if(/^data-/.test(attr.name)){var camelized=Utils.camelize(attr.name.substr(5)),isFunction=0===camelized.lastIndexOf("on",0);data[camelized]=isFunction?eval(attr.value):attr.value}}}return data},normalize_keys:function(e){var t={};for(var i in e)if(Object.prototype.hasOwnProperty.call(e,i)){var o=Utils.camelize(i);t[o]=e[o]?e[o]:e[i]}return t},camelize:function(e){for(var t="-",i=e.indexOf(t);i!==-1;){var o=i===e.length-1,n=o?"":e[i+1],s=n.toUpperCase(),a=o?t:t+n;e=e.replace(a,s),i=e.indexOf(t)}return e},find_script_by_id:function(e){for(var t=doc.getElementsByTagName("script"),i=0,o=t.length;i<o;i++)if(e===t[i].id)return t[i];return null},is_numeric:function(e){return parseFloat(e)==e}},script_el_invoker=Utils.find_script_by_id("cookiebanner"),Cookiebanner=context.Cookiebanner=function(e){this.init(e)};Cookiebanner.prototype={cookiejar:Cookies,init:function(e){this.inserted=!1,this.closed=!1;var t="We use cookies to enhance your experience. By continuing to visit this site you agree to our use of cookies.",i="Learn more";if(this.default_options={cookie:"cookiebanner-accepted",closeText:"✖",closeStyle:"float:right;padding-left:5px;",closePrecedes:!0,cookiePath:"/",cookieDomain:null,cookieSecure:!1,debug:!1,expires:1/0,zindex:255,mask:!1,maskOpacity:.5,maskBackground:"#000",height:"auto",minHeight:"21px",bg:"#000",fg:"#ddd",link:"#aaa",position:"bottom",padding:"5px 16px",message:t,linkmsg:i,moreinfo:"http://aboutcookies.org",moreinfoTarget:"_blank",moreinfoRel:"noopener noreferrer",moreinfoDecoration:"none",moreinfoFontWeight:"normal",moreinfoFontSize:null,moreinfoClass:null,effect:null,fontSize:"14px",fontFamily:"arial, sans-serif",instance:global_instance_name,textAlign:"center",acceptOnScroll:!1,acceptOnClick:!1,acceptOnTimeout:null,acceptOnFirstVisit:!1,onInserted:null,onClosed:null,delayBeforeClose:null,fadeOutDurationMs:2e3},this.options=this.default_options,this.script_el=script_el_invoker,this.script_el){var o=Utils.get_data_attribs(this.script_el);this.options=Utils.merge(this.options,o)}e&&(e=Utils.normalize_keys(e),this.options=Utils.merge(this.options,e)),global_instance_name=this.options.instance,this.options.zindex=parseInt(this.options.zindex,10),this.options.mask=Utils.str2bool(this.options.mask),this.options.closePrecedes=Utils.str2bool(this.options.closePrecedes),"string"==typeof this.options.expires&&("function"==typeof context[this.options.expires]?this.options.expires=context[this.options.expires]:Utils.is_numeric(this.options.expires)&&(this.options.expires=Number(parseFloat(this.options.expires)))),"function"==typeof this.options.expires&&(this.options.expires=this.options.expires()),this.script_el&&this.run()},log:function(){"undefined"!=typeof console&&console.log.apply(console,arguments)},run:function(){if(!this.agreed()){var e=this;contentLoaded(win,function(){e.insert()})}},build_viewport_mask:function(){var e=null;if(!0===this.options.mask){var t=this.options.maskOpacity,i=this.options.maskBackground,o='

',n=doc.createElement("div");n.innerHTML=o,e=n.firstChild}return e},agree:function(){return this.cookiejar.set(this.options.cookie,1,this.options.expires,this.options.cookiePath,""!==this.options.cookieDomain?this.options.cookieDomain:"",!!this.options.cookieSecure),!0},agreed:function(){return this.cookiejar.has(this.options.cookie)},close:function(){if("fade"===this.options.effect)Utils.fade_out(this.element,this.options.fadeOutDurationMs),this.closed=!0;else if(this.inserted){this.closed||(this.element&&this.element.parentNode.removeChild(this.element),this.element_mask&&this.element_mask.parentNode.removeChild(this.element_mask),this.closed=!0),this.closed=!0;var e=this.options.onClosed;e&&"function"==typeof e&&e(this)}return this.closed},agree_and_close:function(){if(this.options.debug||this.agree(),!this.options.delayBeforeClose||isNaN(parseFloat(this.options.delayBeforeClose))||!isFinite(this.options.delayBeforeClose))return this.close();var e=this;setTimeout(function(){e.close()},this.options.delayBeforeClose)},cleanup:function(){return this.close(),this.unload()},unload:function(){return this.script_el&&this.script_el.parentNode.removeChild(this.script_el),context[global_instance_name]=void 0,!0},insert:function(){function e(e,t,i){var o=e.addEventListener?"addEventListener":"attachEvent",n=e.addEventListener?"":"on";e[o](n+t,i,!1)}this.element_mask=this.build_viewport_mask();var t=this.options.zindex;this.element_mask&&(t+=1);var i=doc.createElement("div");i.className="cookiebanner",i.style.position="fixed",i.style.left=0,i.style.right=0,i.style.height=this.options.height,i.style.minHeight=this.options.minHeight,i.style.zIndex=t,i.style.background=this.options.bg,i.style.color=this.options.fg,i.style.lineHeight=i.style.minHeight,i.style.padding=this.options.padding,i.style.fontFamily=this.options.fontFamily,i.style.fontSize=this.options.fontSize,i.style.textAlign=this.options.textAlign,"top"===this.options.position?i.style.top=0:i.style.bottom=0;var o='
'+this.options.closeText+"
",n="";null!==this.options.moreinfoClass&&(n=' class="'+this.options.moreinfoClass+'" ');var s=""+this.options.message+(this.options.linkmsg?" "+this.options.linkmsg+"":"")+"";this.options.closePrecedes?i.innerHTML=o+s:i.innerHTML=s+o,this.element=i;var a;a=null!==this.options.moreinfoClass?i.getElementsByClassName(this.options.moreinfoClass)[0]:i.getElementsByTagName("a")[0],a&&(a.href=this.options.moreinfo,a.target=this.options.moreinfoTarget,this.options.moreinfoRel&&""!==this.options.moreinfoRel&&(a.rel=this.options.moreinfoRel),a.style.textDecoration=this.options.moreinfoDecoration,a.style.color=this.options.link,a.style.fontWeight=this.options.moreinfoFontWeight,""!==this.options.moreinfoFontSize&&(a.style.fontSize=this.options.moreinfoFontSize));var r=i.getElementsByTagName("div")[0];r.style.cursor="pointer";var c=this;e(r,"click",function(){c.agree_and_close()}),this.element_mask&&(e(this.element_mask,"click",function(){c.agree_and_close()}),doc.body.appendChild(this.element_mask)),this.options.acceptOnScroll&&e(window,"scroll",function(){c.agree_and_close()}),this.options.acceptOnClick&&e(window,"click",function(){c.agree_and_close()}),this.options.acceptOnTimeout&&!isNaN(parseFloat(this.options.acceptOnTimeout))&&isFinite(this.options.acceptOnTimeout)&&setTimeout(function(){c.agree_and_close()},this.options.acceptOnTimeout),this.options.acceptOnFirstVisit&&c.agree(),doc.body.appendChild(this.element),this.inserted=!0;var l=this.options.onInserted;l&&"function"==typeof l&&l(this),"fade"===this.options.effect?(this.element.style.opacity=0,Utils.fade_in(this.element)):this.element.style.opacity=1}},script_el_invoker&&(context[global_instance_name]||(context[global_instance_name]=new Cookiebanner))}(window);
<|endoftext|>


<commit_before>/*! skrollr-menu 0.1.10 (2014-03-13) | Alexander Prinzhorn - https://github.com/Prinzhorn/skrollr-menu | Free to use under terms of MIT license */
!function(a,b){"use strict";var c=500,d="sqrt",e=1,f="data-menu-top",g="data-menu-offset",h=b.skrollr,i=b.history,j=!!i.pushState,k=function(b){return b.tagName&&"A"===b.tagName.toUpperCase()?b:b===a?!1:k(b.parentNode)},l=function(a){if(1===a.which||0===a.button){var b=k(a.target);b&&m(b)&&a.preventDefault()}},m=function(b,c){var d=b.getAttribute("href");if(!/^#/.test(d))return!1;var e,h;if(h=t?t(b):b.getAttribute(f),null!==h)e=/p$/.test(h)?h.slice(0,-1)/100*a.documentElement.clientHeight:+h*u;else{var k=a.getElementById(d.substr(1));if(!k)return!1;e=p.relativeToAbsolute(k,"top","top");var l=k.getAttribute(g);null!==l&&(e+=+l)}return j&&!c&&i.pushState({top:e},"",d),s&&!c?p.animateTo(e,{duration:r(p.getScrollTop(),e),easing:q}):o(function(){p.setScrollTop(e)}),!0},n=function(){if(b.location.hash&&a.querySelector){var c=a.querySelector('a[href="'+b.location.hash+'"]');c&&m(c,!0)}},o=function(a){b.setTimeout(a,1)};h.menu={},h.menu.init=function(f,g){p=f,g=g||{},q=g.easing||d,s=g.animate!==!1,r=g.duration||c,t=g.handleLink,u=g.scale||e,"number"==typeof r&&(r=function(a){return function(){return a}}(r)),h.addEvent(a,"click",l),j&&h.addEvent(b,"popstate",function(a){var b=a.state||{},c=b.top||0;o(function(){p.setScrollTop(c)})},!1),n()};var p,q,r,s,t,u;o(function(){b.location.hash&&b.scrollTo(0,0)})}(document,window);<commit_msg>Revert "Compiled code"<commit_after>/*! skrollr-menu 0.1.10 (2013-11-21) | Alexander Prinzhorn - https://github.com/Prinzhorn/skrollr-menu | Free to use under terms of MIT license */
(function(t,e){"use strict";var n=500,o="sqrt",r=1,i="data-menu-top",u="data-menu-offset",a=e.skrollr,c=e.history,l=!!c.pushState,s=function(e){return"A"===e.tagName?e:e===t?!1:s(e.parentNode)},f=function(t){if(1===t.which||0===t.button){var e=s(t.target);e&&p(e)&&t.preventDefault()}},p=function(e,n){var o=e.getAttribute("href");if(!/^#/.test(o))return!1;var r,a;if(a=S?S(e):e.getAttribute(i),null!==a)r=/p$/.test(a)?a.slice(0,-1)/100*t.documentElement.clientHeight:+a*T;else{var s=t.getElementById(o.substr(1));if(!s)return!1;r=m.relativeToAbsolute(s,"top","top");var f=s.getAttribute(u);null!==f&&(r+=+f)}return l&&!n&&c.pushState({top:r},"",o),b&&!n?m.animateTo(r,{duration:g(m.getScrollTop(),r),easing:v}):d(function(){m.setScrollTop(r)}),!0},h=function(){if(e.location.hash&&t.querySelector){var n=t.querySelector('a[href="'+e.location.hash+'"]');n&&p(n,!0)}},d=function(t){e.setTimeout(t,1)};a.menu={},a.menu.init=function(i,u){m=i,u=u||{},v=u.easing||o,b=u.animate!==!1,g=u.duration||n,S=u.handleLink,T=u.scale||r,"number"==typeof g&&(g=function(t){return function(){return t}}(g)),a.addEvent(t,"click",f),l&&a.addEvent(e,"popstate",function(t){var e=t.state||{},n=e.top||0;d(function(){m.setScrollTop(n)})},!1),h()};var m,v,g,b,S,T;d(function(){e.location.hash&&e.scrollTo(0,0)})})(document,window);<|endoftext|>


<commit_before>'use babel'

/** @jsx vanilla.jsx */
import {Emitter, CompositeDisposable} from 'atom'
import vanilla from 'vanilla-jsx'
import {PanelStatusElement} from './panel-status'

export const PanelIcons = {
  MIN: '🗕',
  MAX: '🗖'
}

export class PanelElement {
  constructor() {
    this.element = PanelElement.getElement()
    this.subscriptions = new CompositeDisposable()
    this.emitter = new Emitter()

    this.subscriptions.add(this.element.status)
    this.subscriptions.add(this.emitter)

    this.panel.refs.toggleContent.addEventListener('click', () => {
      this.toggleContent()
    })
    this.panel.refs.destroy.addEventListener('click', () => {
      this.destroy()
    })
  }
  toggleContent() {
    const content = this.panel.refs.content
    const button = this.panel.refs.toggleContent

    if (content.classList.contains('hide')) {
      // Maximize
      content.classList.remove('hide')
      button.title = 'Minimize'
      button.textContent = PanelIcons.MIN
    } else {
      // Minimize
      content.classList.add('hide')
      button.title = 'Maximize'
      button.textContent = PanelIcons.MAX
    }
  }
  get content() {
    return this.panel.refs.content
  }
  set count(count) {
    this.panel.status.count = count
  }
  onDidDestroy(callback) {
    return this.emitter.on('did-destroy', callback)
  }
  destroy() {
    this.emitter.emit('did-destroy')
    this.dispose()
  }
  dispose() {
    this.element = null
    this.subscriptions.dispose()
  }

  static getElement() {
    const panelStatus = new PanelStatusElement()

    const panel = vanilla.process(<linter-ui-default-panel tabindex="-1">

            Linter

          {panelStatus.element}

            {PanelIcons.MIN}
            ✖

    </linter-ui-default-panel>)

    panel.status = panelStatus

    return panel
  }
}
<commit_msg>:bug: Fix a typo in panel element<commit_after>'use babel'

/** @jsx vanilla.jsx */
import {Emitter, CompositeDisposable} from 'atom'
import vanilla from 'vanilla-jsx'
import {PanelStatusElement} from './panel-status'

export const PanelIcons = {
  MIN: '🗕',
  MAX: '🗖'
}

export class PanelElement {
  constructor() {
    this.element = PanelElement.getElement()
    this.subscriptions = new CompositeDisposable()
    this.emitter = new Emitter()

    this.subscriptions.add(this.element.status)
    this.subscriptions.add(this.emitter)

    this.element.refs.toggleContent.addEventListener('click', () => {
      this.toggleContent()
    })
    this.element.refs.destroy.addEventListener('click', () => {
      this.destroy()
    })
  }
  toggleContent() {
    const content = this.element.refs.content
    const button = this.element.refs.toggleContent

    if (content.classList.contains('hide')) {
      // Maximize
      content.classList.remove('hide')
      button.title = 'Minimize'
      button.textContent = PanelIcons.MIN
    } else {
      // Minimize
      content.classList.add('hide')
      button.title = 'Maximize'
      button.textContent = PanelIcons.MAX
    }
  }
  get content() {
    return this.element.refs.content
  }
  set count(count) {
    this.element.status.count = count
  }
  onDidDestroy(callback) {
    return this.emitter.on('did-destroy', callback)
  }
  destroy() {
    this.emitter.emit('did-destroy')
    this.dispose()
  }
  dispose() {
    this.element = null
    this.subscriptions.dispose()
  }

  static getElement() {
    const panelStatus = new PanelStatusElement()

    const panel = vanilla.process(<linter-ui-default-panel tabindex="-1">

            Linter

          {panelStatus.element}

            {PanelIcons.MIN}
            ✖

    </linter-ui-default-panel>)

    panel.status = panelStatus

    return panel
  }
}
<|endoftext|>


<commit_before>var extend = require('obj-extend');
var Lynx = require('lynx');

module.exports = function expressStatsdInit (options) {
  options = extend({
    requestKey: 'statsdKey',
    host: '127.0.0.1',
    port: 8125
  }, options);

  var client = options.client || new Lynx(options.host, options.port, options);

  return function expressStatsd (req, res, next) {
    var startTime = new Date().getTime();

    // Function called on response finish that sends stats to statsd
    function sendStats() {
      var keys = generateStatNames(req.route);

      keys.forEach(function(key) {
        // Status Code
        var statusCode = res.statusCode || 'unknown_status';
        client.increment([key, 'status_code', statusCode].join('.'));

        // Response Time
        var duration = new Date().getTime() - startTime;
        client.timing([key, 'response_time'].join('.'), duration);
      })

      cleanup();
    }

    // Function to clean up the listeners we've added
    function cleanup() {
      res.removeListener('finish', sendStats);
      res.removeListener('error', cleanup);
      res.removeListener('close', cleanup);
    }

    // Add response listeners
    res.once('finish', sendStats);
    res.once('error', cleanup);
    res.once('close', cleanup);

    if (next) {
      next();
    }
  };
};

/* Automatically generate the stat paths from express routing by accessing
*  req.route object.
*
*  {
*    path: '/users/:list/:subscribed',
*    method: 'get',
*    callbacks: [ [Function] ],
*    keys:
*    [ { name: 'list', optional: false },
*      { name: 'subscribed', optional: false },
*      regexp: /^\/users\/(?:([^\/]+?))\/(?:([^\/]+?))\/?$/i,
*    params: [ list: '666', subscribed: 'true' ]
*   }
*
*  We replace the ':' of the url params with a '~' because the following
*  characters are reserved by statsd or graphite: !#:@*[{?/
*
*  This will result in stats like so:
*
*  express.http.get.users
*    - status_code.[2xx,4xx].count
*    - response_time.upper_90
*  express.http.post.users
*  express.http.get.users.~id
*    - status_code.[2xx,4xx].count
*    - response_time.upper_90
*  express.http.post.users.~list
*  express.http.get.users.~list.~subscribed
*/
function generateStatNames(routeObject) {
  var path = routeObject.path;
  path = path.replace(/:/g, '~');
  var pathParts = path.split('/');

  var resource = pathParts[1];
  var resourcePath = pathParts.slice(2, pathParts.length).join('_');

  var requestMethod = routeObject.method || 'unknown_method';
  var baseStat = ['express.http', requestMethod.toLowerCase(), resource].join('.');

  return [
    baseStat,
    [baseStat, resourcePath].join('.')
  ];
};<commit_msg>Don't unnecessarily set same var twice<commit_after>var extend = require('obj-extend');
var Lynx = require('lynx');

module.exports = function expressStatsdInit (options) {
  options = extend({
    requestKey: 'statsdKey',
    host: '127.0.0.1',
    port: 8125
  }, options);

  var client = options.client || new Lynx(options.host, options.port, options);

  return function expressStatsd (req, res, next) {
    var startTime = new Date().getTime();

    // Function called on response finish that sends stats to statsd
    function sendStats() {
      // Status Code
      var statusCode = res.statusCode || 'unknown_status';
      // Response Time
      var duration = new Date().getTime() - startTime;

      var keys = generateStatNames(req.route);

      keys.forEach(function(key) {
        client.increment([key, 'status_code', statusCode].join('.'));
        client.timing([key, 'response_time'].join('.'), duration);
      })

      cleanup();
    }

    // Function to clean up the listeners we've added
    function cleanup() {
      res.removeListener('finish', sendStats);
      res.removeListener('error', cleanup);
      res.removeListener('close', cleanup);
    }

    // Add response listeners
    res.once('finish', sendStats);
    res.once('error', cleanup);
    res.once('close', cleanup);

    if (next) {
      next();
    }
  };
};

/* Automatically generate the stat paths from express routing by accessing
*  req.route object.
*
*  {
*    path: '/users/:list/:subscribed',
*    method: 'get',
*    callbacks: [ [Function] ],
*    keys:
*    [ { name: 'list', optional: false },
*      { name: 'subscribed', optional: false },
*      regexp: /^\/users\/(?:([^\/]+?))\/(?:([^\/]+?))\/?$/i,
*    params: [ list: '666', subscribed: 'true' ]
*   }
*
*  We replace the ':' of the url params with a '~' because the following
*  characters are reserved by statsd or graphite: !#:@*[{?/
*
*  This will result in stats like so:
*
*  express.http.get.users
*    - status_code.[2xx,4xx].count
*    - response_time.upper_90
*  express.http.post.users
*  express.http.get.users.~id
*    - status_code.[2xx,4xx].count
*    - response_time.upper_90
*  express.http.post.users.~list
*  express.http.get.users.~list.~subscribed
*/
function generateStatNames(routeObject) {
  var path = routeObject.path;
  path = path.replace(/:/g, '~');
  var pathParts = path.split('/');

  var resource = pathParts[1];
  var resourcePath = pathParts.slice(2, pathParts.length).join('_');

  var requestMethod = routeObject.method || 'unknown_method';
  var baseStat = ['express.http', requestMethod.toLowerCase(), resource].join('.');

  return [
    baseStat,
    [baseStat, resourcePath].join('.')
  ];
};<|endoftext|>


<commit_before>'use babel';

import { CompositeDisposable, File, Directory } from 'atom';
import subAtom from 'sub-atom';
import path from 'path';
import camelCase from 'camelcase'
import { fromJS } from "immutable";

export default {

  config: {
    semicolons: {
      type: 'boolean',
      default: true,
      title: 'Adds semicolons'
    },
    quote: {
      type: 'string',
      default: "\"",
      title: 'Quote character around imported path',
      enum: [
        {value: '\'', description: 'Single quote'},
        {value: '\"', description: 'Double quote'},
        {value: '\`', description: 'Back quote'}
      ]
    }
  },

  subscriptions: null,

  getLineToAdd(currentBufferPath, filePath, importSpecifier, importPath) {
    let semicolons = atom.config.get('fast-import-js.semicolons') ? ';' : '';
    let quote = atom.config.get('fast-import-js.quote');
    return `import ${importSpecifier} from ${quote}${importPath}${quote}${semicolons}\n`;
  },

  getSpecifierOfNewImport(selectedText, filePath) {
    if (selectedText)
      return selectedText;
    let isIndex = path.basename(filePath).startsWith('index.');
    let moduleName;
    if (isIndex)
      moduleName = path.dirname(filePath).split('/').pop();
    else
      moduleName = path.basename(filePath).split('.')[0];
    if (moduleName[0] == moduleName[0].toUpperCase()) {
      return moduleName[0] + camelCase(moduleName.slice(1));
    } else {
      return camelCase(moduleName);
    }
  },

  getPackageJsonPath(fileWhichRequires) {
      let parentFolders = [];
      let parentFolder = new File(fileWhichRequires).getParent();
      while (parentFolder.getBaseName() != "") {
        parentFolders.push(parentFolder);
        parentFolder = parentFolder.getParent();
      }
      let existsPromises = parentFolders.map((path) => new Promise((resolve, reject) => {
        path.getFile("package.json").exists().then((fileExists) => {
          resolve(fileExists);
        });
      }));
      return Promise.all(existsPromises).then((results) => {
        return parentFolders[results.indexOf(true)].getPath();
      });
  },

  getImportPath(requiredFilePath, fileWhichRequiresPath) {
    return this.getPackageJsonPath(fileWhichRequiresPath).then(packageConfigDirectoryPath => {
      let packageConfigFile = new File(path.join(packageConfigDirectoryPath, "package.json"));
      if (new Directory(packageConfigDirectoryPath).contains(requiredFilePath)) {
        console.log("file contained in the same module, using relative path");
        let importPath = path.relative(fileWhichRequiresPath, requiredFilePath).slice(1);
        importPath = path.normalize(importPath);
        if (importPath[0] != '.')
          importPath = './' + importPath;
        return importPath;
      } else {
        console.log("file in another module, reading package.json");
        return packageConfigFile.read(false).then(packageConfigAsString => {
          console.log(packageConfigAsString);
          let packageConfig = JSON.parse(packageConfigAsString);
          console.log(packageConfig);
          let entriesToModulesMapper = tuple => fromJS({moduleName: tuple[0], modulePath: tuple[1]});
          let dependencies = fromJS([])
                              .concat(fromJS(packageConfig).get('dependencies', fromJS({})).entrySeq().map(entriesToModulesMapper))
                              .concat(fromJS(packageConfig).get('devDependencies', fromJS({})).entrySeq().map(entriesToModulesMapper))
                              .concat(fromJS(packageConfig).get('peerDependencies', fromJS({})).entrySeq().map(entriesToModulesMapper))
                              .toJS();
          console.log("dependencies");
          console.log(dependencies);
          let relativeDependencies = dependencies.filter(dependency => dependency.modulePath.startsWith("file:"));
          console.log("relatives");
          console.log(relativeDependencies);
          let requiredDependencyOfFile = relativeDependencies.find(
            dependency => new Directory(path.resolve(packageConfigDirectoryPath, dependency.modulePath.slice(5)))
                                .contains(requiredFilePath)
          );
          console.log("dependency containing the file found");
          console.log(requiredDependencyOfFile, requiredFilePath, relativeDependencies);
          if (requiredDependencyOfFile) {
            return requiredDependencyOfFile.moduleName + '/' + path.relative(path.resolve(packageConfigDirectoryPath, requiredDependencyOfFile.modulePath.slice(5)), requiredFilePath);
          } else {
            return Promise.reject("not found");
          }
        });
      }
    }).catch(e => {
      return Promise.reject("not a module")
    }).then(importPath => {
      importPath = importPath.slice(0, importPath.length - path.extname(importPath).length);
      importPath =  importPath.slice(0, importPath.length - (importPath.endsWith('index') ? 6 : 0));
      return importPath;
    });
  },

  getIndexOfNewImport(buffer) {
    let index = buffer.lastIndexOf('import');
    if (index == -1)
      index = buffer.lastIndexOf('require');
    if (index == -1)
      index = 0;
    else {
      index = index + buffer.slice(index).indexOf(';') + 2;
    }
    return index;
  },

  addLineToBuffer(buffer, index, line) {
    return buffer.slice(0, index) + line + buffer.slice(index);
  },

  activate(state) {
    // Events subscribed to in atom's system can be easily cleaned up with a CompositeDisposable
    this.subscriptions = new subAtom();
    this.subscriptions.add(atom.workspace.observeTextEditors((editor) => {
      let editorView = atom.views.getView(editor);
      let lines = editorView.shadowRoot.querySelector('.lines');
      this.subscriptions.add(lines, 'drop', e => {
        let filePath = e.originalEvent.dataTransfer.getData('initialPath');
        if (filePath && editor.getPath()) {
          let buffer = editor.getText();
          let specifier = this.getSpecifierOfNewImport(editor.getSelectedText(), filePath);
          this.getImportPath(filePath, editor.getPath()).then(importPath => {
            let lineToAdd = this.getLineToAdd(editor.getPath(), filePath, specifier, importPath);
            let index = this.getIndexOfNewImport(buffer);
            buffer = this.addLineToBuffer(buffer, index, lineToAdd);
            editor.setText(buffer);
            atom.notifications.addSuccess(`Imported ${importPath} as ${specifier}`)
          }).catch(e => {
            atom.notifications.addWarning(`Cannot resolve import path : ${e}`);
          });
        }
      });
    }));
  },

  deactivate() {
    this.subscriptions.dispose();
  },

  serialize() {
    return {};
  },
};
<commit_msg>Improves finding of import's index in buffer<commit_after>'use babel';

import { CompositeDisposable, File, Directory } from 'atom';
import subAtom from 'sub-atom';
import path from 'path';
import camelCase from 'camelcase'
import { fromJS } from "immutable";

export default {

  config: {
    semicolons: {
      type: 'boolean',
      default: true,
      title: 'Adds semicolons'
    },
    quote: {
      type: 'string',
      default: "\"",
      title: 'Quote character around imported path',
      enum: [
        {value: '\'', description: 'Single quote'},
        {value: '\"', description: 'Double quote'},
        {value: '\`', description: 'Back quote'}
      ]
    }
  },

  subscriptions: null,

  getLineToAdd(currentBufferPath, filePath, importSpecifier, importPath) {
    let semicolons = atom.config.get('fast-import-js.semicolons') ? ';' : '';
    let quote = atom.config.get('fast-import-js.quote');
    return `import ${importSpecifier} from ${quote}${importPath}${quote}${semicolons}\n`;
  },

  getSpecifierOfNewImport(selectedText, filePath) {
    if (selectedText)
      return selectedText;
    let isIndex = path.basename(filePath).startsWith('index.');
    let moduleName;
    if (isIndex)
      moduleName = path.dirname(filePath).split('/').pop();
    else
      moduleName = path.basename(filePath).split('.')[0];
    if (moduleName[0] == moduleName[0].toUpperCase()) {
      return moduleName[0] + camelCase(moduleName.slice(1));
    } else {
      return camelCase(moduleName);
    }
  },

  getPackageJsonPath(fileWhichRequires) {
      let parentFolders = [];
      let parentFolder = new File(fileWhichRequires).getParent();
      while (parentFolder.getBaseName() != "") {
        parentFolders.push(parentFolder);
        parentFolder = parentFolder.getParent();
      }
      let existsPromises = parentFolders.map((path) => new Promise((resolve, reject) => {
        path.getFile("package.json").exists().then((fileExists) => {
          resolve(fileExists);
        });
      }));
      return Promise.all(existsPromises).then((results) => {
        return parentFolders[results.indexOf(true)].getPath();
      });
  },

  getImportPath(requiredFilePath, fileWhichRequiresPath) {
    return this.getPackageJsonPath(fileWhichRequiresPath).then(packageConfigDirectoryPath => {
      let packageConfigFile = new File(path.join(packageConfigDirectoryPath, "package.json"));
      if (new Directory(packageConfigDirectoryPath).contains(requiredFilePath)) {
        console.log("file contained in the same module, using relative path");
        let importPath = path.relative(fileWhichRequiresPath, requiredFilePath).slice(1);
        importPath = path.normalize(importPath);
        if (importPath[0] != '.')
          importPath = './' + importPath;
        return importPath;
      } else {
        console.log("file in another module, reading package.json");
        return packageConfigFile.read(false).then(packageConfigAsString => {
          console.log(packageConfigAsString);
          let packageConfig = JSON.parse(packageConfigAsString);
          console.log(packageConfig);
          let entriesToModulesMapper = tuple => fromJS({moduleName: tuple[0], modulePath: tuple[1]});
          let dependencies = fromJS([])
                              .concat(fromJS(packageConfig).get('dependencies', fromJS({})).entrySeq().map(entriesToModulesMapper))
                              .concat(fromJS(packageConfig).get('devDependencies', fromJS({})).entrySeq().map(entriesToModulesMapper))
                              .concat(fromJS(packageConfig).get('peerDependencies', fromJS({})).entrySeq().map(entriesToModulesMapper))
                              .toJS();
          console.log("dependencies");
          console.log(dependencies);
          let relativeDependencies = dependencies.filter(dependency => dependency.modulePath.startsWith("file:"));
          console.log("relatives");
          console.log(relativeDependencies);
          let requiredDependencyOfFile = relativeDependencies.find(
            dependency => new Directory(path.resolve(packageConfigDirectoryPath, dependency.modulePath.slice(5)))
                                .contains(requiredFilePath)
          );
          console.log("dependency containing the file found");
          console.log(requiredDependencyOfFile, requiredFilePath, relativeDependencies);
          if (requiredDependencyOfFile) {
            return requiredDependencyOfFile.moduleName + '/' + path.relative(path.resolve(packageConfigDirectoryPath, requiredDependencyOfFile.modulePath.slice(5)), requiredFilePath);
          } else {
            return Promise.reject("not found");
          }
        });
      }
    }).catch(e => {
      return Promise.reject("not a module")
    }).then(importPath => {
      importPath = importPath.slice(0, importPath.length - path.extname(importPath).length);
      importPath =  importPath.slice(0, importPath.length - (importPath.endsWith('index') ? 6 : 0));
      return importPath;
    });
  },

  getIndexOfNewImport(buffer) {
    let lastIndexOfRegexp = (str, regexp) => {
      let match = str.match(regexp);
      console.log(match[match.length - 1], match);
      return match ? (str.lastIndexOf(match[match.length - 1]) + match[match.length - 1].length) : -1;
    };
    let importRegexp = /\nimport\s.*\sfrom\s+[\'\"\`]\S*[\'\"\`]\ *\;?\n/g;
    let requireRegexp = /\n\w.*\=\s*require\s*\(\S*\)\ *\;?\n/g;
    let index = lastIndexOfRegexp(buffer, importRegexp);
    if (index == -1)
      index = lastIndexOfRegexp(buffer, requireRegexp);
    if (index == -1)
      index = 0;
    return index;
  },

  addLineToBuffer(buffer, index, line) {
    return buffer.slice(0, index) + line + buffer.slice(index);
  },

  activate(state) {
    // Events subscribed to in atom's system can be easily cleaned up with a CompositeDisposable
    this.subscriptions = new subAtom();
    this.subscriptions.add(atom.workspace.observeTextEditors((editor) => {
      let editorView = atom.views.getView(editor);
      let lines = editorView.shadowRoot.querySelector('.lines');
      this.subscriptions.add(lines, 'drop', e => {
        let filePath = e.originalEvent.dataTransfer.getData('initialPath');
        if (filePath && editor.getPath()) {
          let buffer = editor.getText();
          let specifier = this.getSpecifierOfNewImport(editor.getSelectedText(), filePath);
          this.getImportPath(filePath, editor.getPath()).then(importPath => {
            let lineToAdd = this.getLineToAdd(editor.getPath(), filePath, specifier, importPath);
            let index = this.getIndexOfNewImport(buffer);
            buffer = this.addLineToBuffer(buffer, index, lineToAdd);
            editor.setText(buffer);
            atom.notifications.addSuccess(`Imported ${importPath} as ${specifier}`)
          }).catch(e => {
            atom.notifications.addWarning(`Cannot resolve import path : ${e}`);
          });
        }
      });
    }));
  },

  deactivate() {
    this.subscriptions.dispose();
  },

  serialize() {
    return {};
  },
};
<|endoftext|>


<commit_before>/*jshint laxcomma: true, smarttabs: true, node: true*/
'use strict';
/**
 * A field for dealing with related resources
 * @module tastypie/fields/related
 * @author Eric Satterwhite
 * @since 0.5.0
 * requires path
 * @requires tastypie/lib/class
 * @requires tastypie/lib/fields/api
 */

var path     = require( 'path' )
  , Class    = require( '../class' )
  , ApiField = require( './api' )
  , RelatedField
  ;

/**
 * @constructor
 * @alias module:tastypie/fields/related
 * @extends module:tastypie/fields/api
 * @param {Object} options
 * @param {String} [options.root=os.tempDir()]
 * @param {String} [options.dir]
 */
RelatedField = new Class({
	inherits:ApiField
	,options:{
		to:null
	}
	,is_related: true
	,constructor: function(to, options){
		this.parent('constructor', options);
		this.options.to = to;
		this.instance = new this.cli();
	}
});

Object.defineProperties(RelatedField.prototype,{
	cls:{
		enumerable:false
		,writeable: false
		,get: function(){
			var bits  // require path string ( /path/to/module.Class )
			  , mod   // the required module
			  , cls   // the related class object
			  , _to = this.options.to
			  ;
			if( typeof _to === 'string' ){
				bits = _to.split('/');
				var lastBit = bits[bits.length-1];
				var dotPosition = lastBit.indexOf('.');
				var hasCls =  dotPosition !== -1;

				if( hasCls ){
					var module_bits = lastBit.split('.');
					bits[ bits.length-1 ] = module_bits[0];
					cls = module_bits[1];

					_to = path.resolve( bits.join('/') );

				}
				mod = require( _to );
				cls = mod[ cls ];
				this.options.to = cls;
			}

			return this.options.to;
		}
	}
});

module.exports = RelatedField;<commit_msg>fix typo in related field<commit_after>/*jshint laxcomma: true, smarttabs: true, node: true*/
'use strict';
/**
 * A field for dealing with related resources
 * @module tastypie/fields/related
 * @author Eric Satterwhite
 * @since 0.5.0
 * requires path
 * @requires tastypie/lib/class
 * @requires tastypie/lib/fields/api
 */

var path     = require( 'path' )
  , Class    = require( '../class' )
  , ApiField = require( './api' )
  , RelatedField
  ;

/**
 * @constructor
 * @alias module:tastypie/fields/related
 * @extends module:tastypie/fields/api
 * @param {Object} options
 * @param {String} [options.root=os.tempDir()]
 * @param {String} [options.dir]
 */
RelatedField = new Class({
	inherits:ApiField
	,options:{
		to:null
	}
	,is_related: true
	,constructor: function(to, options){
		this.parent('constructor', options);
		this.options.to = to;
		this.instance = new this.cls();
	}
});

Object.defineProperties(RelatedField.prototype,{
	cls:{
		enumerable:false
		,writeable: false
		,get: function(){
			var bits  // require path string ( /path/to/module.Class )
			  , mod   // the required module
			  , cls   // the related class object
			  , _to = this.options.to
			  ;
			if( typeof _to === 'string' ){
				bits = _to.split('/');
				var lastBit = bits[bits.length-1];
				var dotPosition = lastBit.indexOf('.');
				var hasCls =  dotPosition !== -1;

				if( hasCls ){
					var module_bits = lastBit.split('.');
					bits[ bits.length-1 ] = module_bits[0];
					cls = module_bits[1];

					_to = path.resolve( bits.join('/') );

				}
				mod = require( _to );
				cls = mod[ cls ];
				this.options.to = cls;
			}

			return this.options.to;
		}
	}
});

module.exports = RelatedField;<|endoftext|>


<commit_before>var Surface = require('../gamejs').Surface;

/**
 * @fileoverview Methods to create, access and manipulate the display Surface.
 *
 * @example
 * var display = gamejs.display.setMode([800, 600]);
 * // blit sunflower picture in top left corner of display
 * var sunflower = gamejs.image.load("images/sunflower");
 * display.blit(sunflower);
 *
 */

var CANVAS_ID = "gjs-canvas";
var LOADER_ID = "gjs-loader";
var SURFACE = null;

/**
 * Create the master Canvas plane.
 * @ignore
 */
exports.init = function() {
   // create canvas element if not yet present
   var jsGameCanvas = null;
   if ((jsGameCanvas = getCanvas()) === null) {
      jsGameCanvas = document.createElement("canvas");
      jsGameCanvas.setAttribute("id", CANVAS_ID);
      document.body.appendChild(jsGameCanvas);
   };
   // remove loader if any;
   var $loader = document.getElementById('gjs-loader');
   if ($loader) {
       $loader.parentNode.removeChild($loader);
   }
   //jsGameCanvas.setAttribute("style", "width:95%;height:85%");
   return;
};

/**
 * Set the width and height of the Display. Conviniently this will
 * return the actual display Surface - the same as calling [gamejs.display.getSurface()](#getSurface))
 * later on.
 * @param {Array} dimensions [width, height] of the display surface
 */
exports.setMode = function(dimensions) {
   var canvas = getCanvas();
   canvas.width = dimensions[0];
   canvas.height = dimensions[1];
   return getSurface();
};

/**
 * Set the Caption of the Display (document.title)
 * @param {String} title the title of the app
 * @param {gamejs.Image} icon FIXME implement favicon support
 */
exports.setCaption = function(title, icon) {
   document.title = title;
};

/**
 * The Display (the canvas element) is most likely not in the top left corner
 * of the browser due to CSS styling. To calculate the mouseposition within the
 * canvas we need this offset.
 * @see {gamejs.event}
 * @ignore
 *
 * @returns {Array} [x, y] offset of the canvas
 */

exports._getCanvasOffset = function() {
   var boundRect = getCanvas().getBoundingClientRect();
   return [boundRect.left, boundRect.top];
};

/**
 * Drawing on the Surface returned by `getSurface()` will draw on the screen.
 * @returns {gamejs.Surface} the display Surface
 */
var getSurface = exports.getSurface = function() {
   if (SURFACE == null) {
      var canvas = getCanvas();
      var SURFACE = new Surface([canvas.clientWidth, canvas.clientHeight]);
      SURFACE._canvas = canvas;
   }
   return SURFACE;
};

/**
 * @returns {document.Element} the canvas dom element
 */
var getCanvas = function() {
   var jsGameCanvas = null;
   var canvasList = Array.prototype.slice.call(document.getElementsByTagName("canvas"));
   canvasList.every(function(canvas) {
      if (canvas.getAttribute("id") == CANVAS_ID) {
         jsGameCanvas = canvas;
         return false;
      }
      return true;
   });
   return jsGameCanvas;
};
<commit_msg>fix display SURFACe being re-created on every access<commit_after>var Surface = require('../gamejs').Surface;

/**
 * @fileoverview Methods to create, access and manipulate the display Surface.
 *
 * @example
 * var display = gamejs.display.setMode([800, 600]);
 * // blit sunflower picture in top left corner of display
 * var sunflower = gamejs.image.load("images/sunflower");
 * display.blit(sunflower);
 *
 */

var CANVAS_ID = "gjs-canvas";
var LOADER_ID = "gjs-loader";
var SURFACE = null;

/**
 * Create the master Canvas plane.
 * @ignore
 */
exports.init = function() {
   // create canvas element if not yet present
   var jsGameCanvas = null;
   if ((jsGameCanvas = getCanvas()) === null) {
      jsGameCanvas = document.createElement("canvas");
      jsGameCanvas.setAttribute("id", CANVAS_ID);
      document.body.appendChild(jsGameCanvas);
   };
   // remove loader if any;
   var $loader = document.getElementById('gjs-loader');
   if ($loader) {
       $loader.parentNode.removeChild($loader);
   }
   //jsGameCanvas.setAttribute("style", "width:95%;height:85%");
   return;
};

/**
 * Set the width and height of the Display. Conviniently this will
 * return the actual display Surface - the same as calling [gamejs.display.getSurface()](#getSurface))
 * later on.
 * @param {Array} dimensions [width, height] of the display surface
 */
exports.setMode = function(dimensions) {
   var canvas = getCanvas();
   canvas.width = dimensions[0];
   canvas.height = dimensions[1];
   return getSurface();
};

/**
 * Set the Caption of the Display (document.title)
 * @param {String} title the title of the app
 * @param {gamejs.Image} icon FIXME implement favicon support
 */
exports.setCaption = function(title, icon) {
   document.title = title;
};

/**
 * The Display (the canvas element) is most likely not in the top left corner
 * of the browser due to CSS styling. To calculate the mouseposition within the
 * canvas we need this offset.
 * @see {gamejs.event}
 * @ignore
 *
 * @returns {Array} [x, y] offset of the canvas
 */

exports._getCanvasOffset = function() {
   var boundRect = getCanvas().getBoundingClientRect();
   return [boundRect.left, boundRect.top];
};

/**
 * Drawing on the Surface returned by `getSurface()` will draw on the screen.
 * @returns {gamejs.Surface} the display Surface
 */
var getSurface = exports.getSurface = function() {
   if (SURFACE == null) {
      var canvas = getCanvas();
      SURFACE = new Surface([canvas.clientWidth, canvas.clientHeight]);
      SURFACE._canvas = canvas;
   }
   return SURFACE;
};

/**
 * @returns {document.Element} the canvas dom element
 */
var getCanvas = function() {
   var jsGameCanvas = null;
   var canvasList = Array.prototype.slice.call(document.getElementsByTagName("canvas"));
   canvasList.every(function(canvas) {
      if (canvas.getAttribute("id") == CANVAS_ID) {
         jsGameCanvas = canvas;
         return false;
      }
      return true;
   });
   return jsGameCanvas;
};
<|endoftext|>


<commit_before>const Promise = require('bluebird')
const xmlBuilder = require('xmlbuilder')
const TurndownService = require('turndown')
const turndownService = new TurndownService()
const calculateScore = require('../calculateScore')
const calculateHintCost = require('../calculateHintCost')
const hmacSha1 = require('../hmac')
const options = require('../options')
const { readFileSync } = require('fs')
const path = require('path')
let rtbTemplate = {}

function createRtbExport (challenges, { insertHints, insertHintUrls, ctfKey }) {
  function checkHints (challenge) {
    return (challenge.hint && insertHints !== options.noTextHints)
  }

  function checkHintsURL (challenge) {
    return (challenge.hintUrl && insertHintUrls !== options.noHintUrls)
  }

  function getDescription (category) {
    if (!rtbTemplate.categories[category]) {
      return category
    }
    return rtbTemplate.categories[category].description
  }

  function getImage (category) {
    if (!rtbTemplate.categories[category]) {
      category = 'Miscellaneous'
    }
    return rtbTemplate.categories[category].image
  }

  function insertHint (challenge, flag) {
    const includeHint = checkHints(challenge)
    const includeHintUrl = checkHintsURL(challenge)

    if (includeHint || includeHintUrl) {
      const hints = flag.ele('hints')
      let count = 0
      if (includeHint) {
        const hint = hints.ele('hint')
        hint.ele('description', turndownService.turndown(challenge.hint))
        hint.ele('price', calculateHintCost(challenge, insertHints))
        count += 1
      }
      if (includeHintUrl) {
        const hint = hints.ele('hint')
        hint.ele('description', '[' + formatHintURL(challenge) +
          '](' + challenge.hintUrl + ')')
        hint.ele('price', calculateHintCost(challenge, insertHintUrls))
        count += 1
      }
      hints.att({ count: count })
    }
  }

  function formatHintURL (challenge) {
    let hintText = challenge.description
    if (challenge.hintUrl.includes('#')) {
      const hintUrl = challenge.hintUrl
      hintText = hintUrl.substring(hintUrl.lastIndexOf('#') + 1, hintUrl.length).replace(/-/g, ' ')
      hintText = hintText.replace(/\b[a-z]|['_][a-z]|\B[A-Z]/g, function (x) {
        return x[0] === "'" || x[0] === '_' ? x : String.fromCharCode(x.charCodeAt(0) ^ 32)
      })
    }
    return hintText
  }

  function insertBoxes (challenges, boxes, category) {
    const box = boxes.ele('box', { gamelevel: '0' })
    box.ele('name', category)
    box.ele('category', category)
    box.ele('description', getDescription(category))
    box.ele('avatar', getImage(category))
    const flags = box.ele('flags')
    let i = 0
    for (const key in challenges) {
      if (Object.prototype.hasOwnProperty.call(challenges, key)) {
        const challenge = challenges[key]
        if (category === challenge.category) {
          i += 1
          insertFlag(challenge, flags, i)
        }
      }
    }
    flags.att({ count: i.toString() })
  }

  function difficultyText (value) {
    let difficulty = ''
    for (let i = 0; i < value; i++) {
      difficulty += '⭐'
    }
    return difficulty
  }

  function insertFlag (challenge, flags, order) {
    const flag = flags.ele('flag', { type: 'static' })
    flag.ele('name', challenge.name)
    flag.ele('description', turndownService.turndown(challenge.description) +
      ' **Difficulty** ' + difficultyText(challenge.difficulty))
    flag.ele('token', hmacSha1(ctfKey, challenge.name))
    flag.ele('value', calculateScore(challenge.difficulty))
    flag.ele('order', order.toString())
    insertHint(challenge, flag)
  }

  function insertCategories (challenges, xmlRTB) {
    const categories = new Set()
    for (const key in challenges) {
      categories.add(challenges[key].category)
    }
    if (categories.size > 0) {
      const categoriesXml = xmlRTB.ele('categories', { count: categories.size })
      for (const category of categories) {
        categoriesXml.ele('category').ele('category', category)
      }
      categoriesXml.up()
    }
    return categories
  }

  function insertCorporation (categories, xmlRTB) {
    const corporation = xmlRTB.ele('corporations', { count: '1' }).ele('corporation')
    corporation.ele('name')
    return corporation.ele('boxes', { count: categories.size.toString() })
  }

  function insertConfiguration (xmlRTB) {
    const config = xmlRTB.ele('configuration')
    config.ele('game_name', rtbTemplate.configuration.game_name)
    config.ele('org_footer', rtbTemplate.configuration.org_footer)
    config.ele('ctf_tagline', rtbTemplate.configuration.ctf_tagline)
    config.ele('ctf_logo', rtbTemplate.configuration.ctf_logo)
    config.ele('scoreboard_right_image', rtbTemplate.configuration.scoreboard_right_image)
  }

  function sortByDifficulty (dict) {
    const sorted = []
    let maxdifficulty = 5
    for (let i = 0; i <= maxdifficulty; i++) {
      for (const key in challenges) {
        if (Object.prototype.hasOwnProperty.call(challenges, key)) {
          const challenge = challenges[key]
          if (challenge.difficulty === i) {
            sorted[sorted.length] = challenge
          }
          maxdifficulty = Math.max(challenge.difficulty, maxdifficulty)
        }
      }
    }
    return sorted
  }

  function loadTemplate () {
    const template = readFileSync(path.join(__dirname, '../../data/rtbImportTemplate.json'))
    return JSON.parse(template)
  }

  return new Promise((resolve, reject) => {
    try {
      rtbTemplate = loadTemplate()
      const xmlRTB = xmlBuilder.create('rootthebox', { version: '1.0', encoding: 'UTF-8' }).att('api', '1')
      insertConfiguration(xmlRTB)
      xmlRTB.ele('gamelevels', { count: '1' }).up()
      const categories = insertCategories(challenges, xmlRTB)
      const boxes = insertCorporation(categories, xmlRTB)
      const sortedChallenges = sortByDifficulty(challenges)
      for (const category of categories) {
        insertBoxes(sortedChallenges, boxes, category)
      }
      resolve(xmlRTB.end({ pretty: true }))
    } catch (error) {
      reject(new Error('Failed to generate challenge data! ' + error.message))
    }
  })
}

module.exports = createRtbExport
<commit_msg>Fix category name using the wrong XML tag<commit_after>const Promise = require('bluebird')
const xmlBuilder = require('xmlbuilder')
const TurndownService = require('turndown')
const turndownService = new TurndownService()
const calculateScore = require('../calculateScore')
const calculateHintCost = require('../calculateHintCost')
const hmacSha1 = require('../hmac')
const options = require('../options')
const { readFileSync } = require('fs')
const path = require('path')
let rtbTemplate = {}

function createRtbExport (challenges, { insertHints, insertHintUrls, ctfKey }) {
  function checkHints (challenge) {
    return (challenge.hint && insertHints !== options.noTextHints)
  }

  function checkHintsURL (challenge) {
    return (challenge.hintUrl && insertHintUrls !== options.noHintUrls)
  }

  function getDescription (category) {
    if (!rtbTemplate.categories[category]) {
      return category
    }
    return rtbTemplate.categories[category].description
  }

  function getImage (category) {
    if (!rtbTemplate.categories[category]) {
      category = 'Miscellaneous'
    }
    return rtbTemplate.categories[category].image
  }

  function insertHint (challenge, flag) {
    const includeHint = checkHints(challenge)
    const includeHintUrl = checkHintsURL(challenge)

    if (includeHint || includeHintUrl) {
      const hints = flag.ele('hints')
      let count = 0
      if (includeHint) {
        const hint = hints.ele('hint')
        hint.ele('description', turndownService.turndown(challenge.hint))
        hint.ele('price', calculateHintCost(challenge, insertHints))
        count += 1
      }
      if (includeHintUrl) {
        const hint = hints.ele('hint')
        hint.ele('description', '[' + formatHintURL(challenge) +
          '](' + challenge.hintUrl + ')')
        hint.ele('price', calculateHintCost(challenge, insertHintUrls))
        count += 1
      }
      hints.att({ count: count })
    }
  }

  function formatHintURL (challenge) {
    let hintText = challenge.description
    if (challenge.hintUrl.includes('#')) {
      const hintUrl = challenge.hintUrl
      hintText = hintUrl.substring(hintUrl.lastIndexOf('#') + 1, hintUrl.length).replace(/-/g, ' ')
      hintText = hintText.replace(/\b[a-z]|['_][a-z]|\B[A-Z]/g, function (x) {
        return x[0] === "'" || x[0] === '_' ? x : String.fromCharCode(x.charCodeAt(0) ^ 32)
      })
    }
    return hintText
  }

  function insertBoxes (challenges, boxes, category) {
    const box = boxes.ele('box', { gamelevel: '0' })
    box.ele('name', category)
    box.ele('category', category)
    box.ele('description', getDescription(category))
    box.ele('avatar', getImage(category))
    const flags = box.ele('flags')
    let i = 0
    for (const key in challenges) {
      if (Object.prototype.hasOwnProperty.call(challenges, key)) {
        const challenge = challenges[key]
        if (category === challenge.category) {
          i += 1
          insertFlag(challenge, flags, i)
        }
      }
    }
    flags.att({ count: i.toString() })
  }

  function difficultyText (value) {
    let difficulty = ''
    for (let i = 0; i < value; i++) {
      difficulty += '⭐'
    }
    return difficulty
  }

  function insertFlag (challenge, flags, order) {
    const flag = flags.ele('flag', { type: 'static' })
    flag.ele('name', challenge.name)
    flag.ele('description', turndownService.turndown(challenge.description) +
      ' **Difficulty** ' + difficultyText(challenge.difficulty))
    flag.ele('token', hmacSha1(ctfKey, challenge.name))
    flag.ele('value', calculateScore(challenge.difficulty))
    flag.ele('order', order.toString())
    insertHint(challenge, flag)
  }

  function insertCategories (challenges, xmlRTB) {
    const categories = new Set()
    for (const key in challenges) {
      categories.add(challenges[key].category)
    }
    if (categories.size > 0) {
      const categoriesXml = xmlRTB.ele('categories', { count: categories.size })
      for (const category of categories) {
        categoriesXml.ele('category').ele('name', category)
      }
      categoriesXml.up()
    }
    return categories
  }

  function insertCorporation (categories, xmlRTB) {
    const corporation = xmlRTB.ele('corporations', { count: '1' }).ele('corporation')
    corporation.ele('name')
    return corporation.ele('boxes', { count: categories.size.toString() })
  }

  function insertConfiguration (xmlRTB) {
    const config = xmlRTB.ele('configuration')
    config.ele('game_name', rtbTemplate.configuration.game_name)
    config.ele('org_footer', rtbTemplate.configuration.org_footer)
    config.ele('ctf_tagline', rtbTemplate.configuration.ctf_tagline)
    config.ele('ctf_logo', rtbTemplate.configuration.ctf_logo)
    config.ele('scoreboard_right_image', rtbTemplate.configuration.scoreboard_right_image)
  }

  function sortByDifficulty (dict) {
    const sorted = []
    let maxdifficulty = 5
    for (let i = 0; i <= maxdifficulty; i++) {
      for (const key in challenges) {
        if (Object.prototype.hasOwnProperty.call(challenges, key)) {
          const challenge = challenges[key]
          if (challenge.difficulty === i) {
            sorted[sorted.length] = challenge
          }
          maxdifficulty = Math.max(challenge.difficulty, maxdifficulty)
        }
      }
    }
    return sorted
  }

  function loadTemplate () {
    const template = readFileSync(path.join(__dirname, '../../data/rtbImportTemplate.json'))
    return JSON.parse(template)
  }

  return new Promise((resolve, reject) => {
    try {
      rtbTemplate = loadTemplate()
      const xmlRTB = xmlBuilder.create('rootthebox', { version: '1.0', encoding: 'UTF-8' }).att('api', '1')
      insertConfiguration(xmlRTB)
      xmlRTB.ele('gamelevels', { count: '1' }).up()
      const categories = insertCategories(challenges, xmlRTB)
      const boxes = insertCorporation(categories, xmlRTB)
      const sortedChallenges = sortByDifficulty(challenges)
      for (const category of categories) {
        insertBoxes(sortedChallenges, boxes, category)
      }
      resolve(xmlRTB.end({ pretty: true }))
    } catch (error) {
      reject(new Error('Failed to generate challenge data! ' + error.message))
    }
  })
}

module.exports = createRtbExport
<|endoftext|>


<commit_before>/*
  Author:bachvtuan@gmail.com
  Website:http://dethoima.com
  A directive that support sortable list via html5 for angularjs
  Read the readme.md and take a look at example code before using.
*/

var sortable_app = angular.module('html5.sortable', []);
sortable_app.directive('htmlSortable', function($parse,$timeout, $log) {

  return {
    restrict: 'A',
    require: '?ngModel',
    scope: {
      htmlSortable: '=',
      ngModel : '='
    },

    //scope: true,   // optionally create a child scope
    link: function(scope, element, attrs,ngModel) {
      var model = $parse(attrs.htmlSortable);
      /*attrs.html5Sortable*/

      var sortable = {};
      sortable.is_handle = false;
      sortable.in_use = false;

      sortable.handleDragStart = function(e) {

        sortable.drag_source = null;

        if ( sortable.options &&  !sortable.is_handle && sortable.options.handle ){
          e.preventDefault();
          return;
        }

        sortable.is_handle  = false;
        e.dataTransfer.effectAllowed = 'move';

        sortable.drag_source = this;

        // this/e.target is the source node.
        this.classList.add('moving');
      };

      sortable.handleDragOver = function(e) {
        if (e.preventDefault) {
          e.preventDefault(); // Allows us to drop.
        }

        e.dataTransfer.dropEffect = 'move';

        return false;
      };

      sortable.handleDragEnter = function(e) {
        this.classList.add('over');
      };

      sortable.handleDragLeave = function(e) {
        this.classList.remove('over');
      };

      sortable.handleDrop = function(e) {
        // this/e.target is current target element.
        if (e.stopPropagation) {
          // stops the browser from redirecting.
          e.stopPropagation();
        }
        this.classList.remove('over');

        // Don't do anything if we're dropping on the same column we're dragging.
        if (sortable.drag_source != this) {

          if (sortable.drag_source == null){
            $log.info("Invalid sortable");
            return;
          }

          var drop_index = this.index;
          var drag_index = sortable.drag_source.index;
          var temp = angular.copy(ngModel.$modelValue[drag_index]);

          sortable.unbind();

          ngModel.$modelValue.splice(drag_index,1);
          ngModel.$modelValue.splice(drop_index,0, temp);

          scope.$apply();

          if ( sortable.options &&  angular.isDefined(sortable.options.stop) ){
            $log.info('Make callback');
            sortable.options.stop(ngModel.$modelValue,ngModel.$modelValue[drop_index]);
          }
        }

        return false;
      };

      sortable.handleDragEnd = function(e) {
        // this/e.target is the source node.
        [].forEach.call(sortable.cols_, function (col) {
          col.classList.remove('over');
          col.classList.remove('moving');
        });

      };

      //Unbind all events are registed before
      sortable.unbind = function(){

        $log.info('Unbind sortable');
        [].forEach.call(sortable.cols_, function (col) {
          col.removeEventListener('dragstart', sortable.handleDragStart, false);
          col.removeEventListener('dragenter', sortable.handleDragEnter, false);
          col.removeEventListener('dragover', sortable.handleDragOver, false);
          col.removeEventListener('dragleave', sortable.handleDragLeave, false);
          col.removeEventListener('drop', sortable.handleDrop, false);
          col.removeEventListener('dragend', sortable.handleDragEnd, false);
        });
        sortable.in_use = false;
      }

      sortable.activehandle = function(){
        sortable.is_handle = true;
      }

      sortable.update = function(){
        $log.info("Update sortable");
        sortable.drag_source = null;
        var index = 0;
        this.cols_ =  element[0].children;
        [].forEach.call(this.cols_, function (col) {
          if ( sortable.options &&  sortable.options.handle){
            var handle = col.querySelectorAll(sortable.options.handle)[0];
            handle.addEventListener('mousedown', sortable.activehandle, false);
          }

          col.index = index++;
          col.setAttribute('draggable', 'true');  // Enable columns to be draggable.
          col.addEventListener('dragstart', sortable.handleDragStart, false);
          col.addEventListener('dragenter', sortable.handleDragEnter, false);
          col.addEventListener('dragover', sortable.handleDragOver, false);
          col.addEventListener('dragleave', sortable.handleDragLeave, false);
          col.addEventListener('drop', sortable.handleDrop, false);
          col.addEventListener('dragend', sortable.handleDragEnd, false);
        });

        sortable.in_use = true;
      }

      if (ngModel) {
        ngModel.$render = function() {
          $timeout(function(){
            //Init flag indicate the first load sortable is done or not
            sortable.first_load = false;

            scope.$watch('htmlSortable', function(value) {

              $log.info("The fist time load html5-sortable");
              sortable.options = value;

              if (value == "stop" ){
                $log.info("stop");
                if (sortable.in_use){
                  sortable.unbind();
                  sortable.in_use = false;
                }
                return;
              }

              if ( sortable.options && angular.isDefined(sortable.options.construct) ){
                sortable.options.construct(ngModel.$modelValue);
              }
              element[0].classList.add('html5-sortable');
              sortable.update();
              $timeout(function(){
                sortable.first_load = true;
              })
            }, true);

            //Watch ngModel and narrate it
            scope.$watch('ngModel', function(value) {
              if ( !sortable.first_load || sortable.options == 'stop' ){
                //Ignore on first load
                return;
              }
              $log.info("Model changed");

              $timeout(function(){
                sortable.update();
              });

            },true);

          });
        };
      }
      else{
        $log.info('Missing ng-model in template');
      }
    }
  };
});
<commit_msg>add cross dropping<commit_after>/*
  Author:bachvtuan@gmail.com
  https://github.com/bachvtuan/html5-sortable-angularjs
  A directive that support sortable list via html5 for angularjs
  Read the readme.md and take a look at example code before using.
*/

var sortable_app = angular.module('html5.sortable', []);
sortable_app.directive('htmlSortable', function($parse,$timeout, $log, $window) {

  return {
    restrict: 'A',
    require: '?ngModel',
    scope: {
      htmlSortable: '=',
      ngModel : '=',
      ngExtraSortable:'='
    },

    //scope: true,   // optionally create a child scope
    link: function(scope, element, attrs,ngModel) {
      //var model = $parse(attrs.htmlSortable);
      /*attrs.html5Sortable*/

      var sortable = {};
      sortable.is_handle = false;
      sortable.in_use = false;

      sortable.handleDragStart = function(e) {

         $window['drag_source'] = null;
         $window['drag_source_extra'] = null;

        if ( sortable.options &&  !sortable.is_handle && sortable.options.handle ){
          e.preventDefault();
          return;
        }

        sortable.is_handle  = false;
        e.dataTransfer.effectAllowed = 'move';

         $window['drag_source'] = this;
         $window['drag_source_extra'] = element.extra_data;

        // this/e.target is the source node.
        this.classList.add('moving');
      };

      sortable.handleDragOver = function(e) {
        if (e.preventDefault) {
          e.preventDefault(); // Allows us to drop.
        }

        e.dataTransfer.dropEffect = 'move';

        return false;
      };

      sortable.handleDragEnter = function(e) {
        this.classList.add('over');
      };

      sortable.handleDragLeave = function(e) {
        this.classList.remove('over');
      };

      sortable.handleDrop = function(e) {
        // this/e.target is current target element.
        if (e.stopPropagation) {
          // stops the browser from redirecting.
          e.stopPropagation();
        }
        this.classList.remove('over');

        // Don't do anything if we're dropping on the same column we're dragging.
        if ( $window['drag_source'] != this) {

          if ( $window['drag_source'] == null){
            $log.info("Invalid sortable");
            return;
          }

          var source_model = $window['drag_source'].model;
          var drop_index = this.index;

          if (ngModel.$modelValue.indexOf(source_model) != -1){

            var drag_index =  $window['drag_source'].index;
            var temp = angular.copy(ngModel.$modelValue[drag_index]);

            sortable.unbind();

            ngModel.$modelValue.splice(drag_index,1);
            ngModel.$modelValue.splice(drop_index,0, temp);

          }
          else if ( sortable.options.allow_cross ){
            ngModel.$modelValue.splice(drop_index,0, source_model);
          }
          else{
            $log.info("disabled cross dropping");
            return;
          }

          //return;
          scope.$apply();

          if ( sortable.options &&  angular.isDefined(sortable.options.stop) ){
            $log.info('Make callback');
            sortable.options.stop(ngModel.$modelValue,drop_index,
              element.extra_data,$window['drag_source_extra']);
          }
        }

        return false;
      };

      sortable.handleDragEnd = function(e) {
        // this/e.target is the source node.
        [].forEach.call(sortable.cols_, function (col) {
          col.classList.remove('over');
          col.classList.remove('moving');
        });

      };

      //Unbind all events are registed before
      sortable.unbind = function(){

        $log.info('Unbind sortable');
        [].forEach.call(sortable.cols_, function (col) {
          col.removeAttribute('draggable');
          col.removeEventListener('dragstart', sortable.handleDragStart, false);
          col.removeEventListener('dragenter', sortable.handleDragEnter, false);
          col.removeEventListener('dragover', sortable.handleDragOver, false);
          col.removeEventListener('dragleave', sortable.handleDragLeave, false);
          col.removeEventListener('drop', sortable.handleDrop, false);
          col.removeEventListener('dragend', sortable.handleDragEnd, false);
        });
        sortable.in_use = false;
      }

      sortable.activehandle = function(){
        sortable.is_handle = true;
      }

      sortable.update = function(){
        $log.info("Update sortable");
         $window['drag_source'] = null;
        var index = 0;
        this.cols_ =  element[0].children;

        [].forEach.call(this.cols_, function (col) {
          if ( sortable.options &&  sortable.options.handle){
            var handle = col.querySelectorAll(sortable.options.handle)[0];
            handle.addEventListener('mousedown', sortable.activehandle, false);
          }

          col.index = index;
          col.model = ngModel.$modelValue[index];

          index++;

          col.setAttribute('draggable', 'true');  // Enable columns to be draggable.
          col.addEventListener('dragstart', sortable.handleDragStart, false);
          col.addEventListener('dragenter', sortable.handleDragEnter, false);
          col.addEventListener('dragover', sortable.handleDragOver, false);
          col.addEventListener('dragleave', sortable.handleDragLeave, false);
          col.addEventListener('drop', sortable.handleDrop, false);
          col.addEventListener('dragend', sortable.handleDragEnd, false);
        });

        sortable.in_use = true;
      }

      if (ngModel) {
        ngModel.$render = function() {
          $timeout(function(){
            //Init flag indicate the first load sortable is done or not
            sortable.first_load = false;

            scope.$watch('ngExtraSortable',function(value){
              element.extra_data = value;
              //sortable.extra_data = value;
            })

            scope.$watch('htmlSortable', function(value) {

              $log.info("The fist time load html5-sortable");
              sortable.options = angular.copy(value) ;

              if (value == "destroy" ){
                $log.info("destroy");
                if (sortable.in_use){
                  sortable.unbind();
                  sortable.in_use = false;
                }
                return;
              }

              if ( !angular.isDefined(sortable.options)){
                sortable.options = {};
              }

              if ( !angular.isDefined(sortable.options.allow_cross)){
                sortable.options.allow_cross = false
              }

              if ( angular.isDefined(sortable.options.construct) ){
                sortable.options.construct(ngModel.$modelValue);
              }
              element[0].classList.add('html5-sortable');
              sortable.update();
              $timeout(function(){
                sortable.first_load = true;
              })
            }, true);

            //Watch ngModel and narrate it
            scope.$watch('ngModel', function(value) {
              if ( !sortable.first_load || sortable.options == 'destroy' ){
                //Ignore on first load
                return;
              }
              $log.info("Model changed");

              $timeout(function(){
                sortable.update();
              });

            },true);

          });
        };
      }
      else{
        $log.info('Missing ng-model in template');
      }
    }
  };
});
<|endoftext|>


<commit_before>/* SIMPLE MOVING AVERAGE INDICATOR AND ALGORITHM

To calculate an simple moving average, we simply need time-series data:
    1, 52
    2, 53.7
    3, 57.3
    4, 60.1
    5, 62.9
    ...
For every new point (Date, value) that is added, the moving average substracts
the oldest value, adds the new one, then divides the set by the specified
period again.

Our set up as of now creates an issue however -- we don't have historical data.
Therefore we can't calculate a SMA with a period longer than the time the
the strategy has been running...

To deal with this I suggest we call an exchanges API for historical data, then
append on new points as the strategy runs.

With this said, once we have a proper data set that we called from an API, we
can append that dataset to our own set:
Start:          [[1,2],[2,2.4],...]   +    [ empty ]
                    Poloniex data   --->  our data set

Next iteration: [[1,2],[2,2.4],...]   +    [ 3,2.9 ]
                    Our data        --->   new point

Now, how this will integrate into our TradingDesk is another question...

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
                          sma.js Specifications
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
All these indicators should calculate an answer given a universal input. That
means that the inputs need to be standardized.
In order for SMA to work, it needs time-series data and one more data point.

INPUTS:

*/

'use strict';
/*

currencyPair:   currency pair to return
period:         candlestick period in seconds; valid values are 300, 900, 1800, 7200, 14400, and 86400
start:          are given in UNIX timestamp format and used to specify the date range for the data returned
end:            "

Call: https://poloniex.com/public?command=returnChartData&currencyPair=BTC_XMR&start=1405699200&end=9999999999&period=14400

returns:
[{"date":   1405699200,
  "high":   0.0045388,
  "low":    0.00403001,
  "open":   0.00404545,
  "close":  0.00427592,
  "volume": 44.11655644,
  "quoteVolume":     10259.29079097,
  "weightedAverage": 0.00430015},
  ...]

*/

//var oneMonthFromNow = new Date((+new Date) + 2578400000);
//console.log(oneMonthFromNow);

// API Wrapper class
var Poloniex = require('poloniex.js');
var poloniex = new Poloniex();

// Create time frame for API call below
var d                 = new Date();
var endDate           = d.getTime();
var timeFrame         = 30;             // 30 days
var milisecsPerDay    = 85946666;
// need 2 multiplier to calculate SMA for first point
var startDate         = currentDate - (timeFrame * milisecondsPerDay * 2);

// Call historical data and add (date,closingPrice) pairs to timeData;
var timeData = [];
poloniex.returnChartData("USDT", "ETH", 86400, startDate, endDate, function(err, data) {
  if (err) {
    console.log("error!");
  }
  for (var i = 0; i < data.length; i++) {
    timeData.push([data[i].date, data[i].close]);
  }
});

var SMATimeSeries = [];

/*
// Can implement timeSeriesData as a Queue
var simpleMovingAverage = function (timeSeriesData, newDataPoint, timePeriod) {

  timeSeriesData.push(newDataPoint);
  timeSeriesData.pop();
  var MA = 0;
  for (point in timeSeriesData) {
    if (point.data < timePeriod) {
        MA += point.value;
    }
  }

  MA = MA / timePeriod;
  return MA;
}

module.exports = function(indicatorMixin, accessor_ohlc) {  // Injected dependencies
  return function() { // Closure function
    var p = {},  // Container for private, direct access mixed in variables
        samples,
        currentIndex,
        total;

    function indicator(data) {
      indicator.init();
      return data.map(ma).filter(function(d) { return d.value !== null; });
    }

    indicator.init = function() {
      total = 0;
      samples = [];
      currentIndex = 0;
      return indicator;
    };

    function ma(d, i) {
      var value = indicator.average(p.accessor(d));
      if (i+1 < p.period) value = null;
      return { date: p.accessor.d(d), value: value };
    }

    indicator.average = function(value) {
      total += value;

      if(samples.length+1 < p.period) {
        samples.push(value);
        return total/++currentIndex;
      }
      else {
        if(samples.length < p.period) {
          samples.push(value);
          total += value;
        }

        total -= samples[currentIndex];
        samples[currentIndex] = value;
        if(++currentIndex === p.period) {
          currentIndex = 0;
        }

        return total/p.period;
      }
    };

    // Mixin 'superclass' methods and variables
    indicatorMixin(indicator, p)
      .accessor(accessor_ohlc())
      .period(10);

    return indicator;
  };
};
*/
<commit_msg>SMA implementation<commit_after>/* SIMPLE MOVING AVERAGE INDICATOR AND ALGORITHM

To calculate an simple moving average, we simply need time-series data:
    1, 52
    2, 53.7
    3, 57.3
    4, 60.1
    5, 62.9
    ...
For every new point (Date, value) that is added, the moving average substracts
the oldest value, adds the new one, then divides the set by the specified
period again.

Our set up as of now creates an issue however -- we don't have historical data.
Therefore we can't calculate a SMA with a period longer than the time the
the strategy has been running...

To deal with this I suggest we call an exchanges API for historical data, then
append on new points as the strategy runs.

With this said, once we have a proper data set that we called from an API, we
can append that dataset to our own set:
Start:          [[1,2],[2,2.4],...]   +    [ empty ]
                    Poloniex data   --->  our data set

Next iteration: [[1,2],[2,2.4],...]   +    [ 3,2.9 ]
                    Our data        --->   new point

Now, how this will integrate into our TradingDesk is another question...

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
                          sma.js Specifications
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
All these indicators should calculate an answer given a universal input. That
means that the inputs need to be standardized.
In order for SMA to work, it needs time-series data and one more data point.

INPUTS:

*/

'use strict';
/*

currencyPair:   currency pair to return
period:         candlestick period in seconds; valid values are 300, 900, 1800, 7200, 14400, and 86400
start:          are given in UNIX timestamp format and used to specify the date range for the data returned
end:            "

Call: https://poloniex.com/public?command=returnChartData&currencyPair=BTC_XMR&start=1405699200&end=9999999999&period=14400

returns:
[{"date":   1405699200,
  "high":   0.0045388,
  "low":    0.00403001,
  "open":   0.00404545,
  "close":  0.00427592,
  "volume": 44.11655644,
  "quoteVolume":     10259.29079097,
  "weightedAverage": 0.00430015},
  ...]

*/

//var oneMonthFromNow = new Date((+new Date) + 2578400000);
//console.log(oneMonthFromNow);

var calcAvg = function(array) {

}

// API Wrapper class
var Poloniex = require('poloniex.js');
var poloniex = new Poloniex();

// Create time frame for API call below
var d                 = new Date();
var endDate           = Math.floor(d.getTime() / 1000);
var timeFrame         = 30;             // 30 days
var secsPerDay        = 86400;
// need 2 multiplier to calculate SMA for first point
var startDate         = endDate - (timeFrame * secsPerDay * 2);
console.log("endDate: " + endDate);
console.log("startDate: " + startDate);

// Call historical data and add (date,closingPrice) pairs to timeData;
var timeData = [];
var SMATimeSeries = [];

poloniex.returnChartData("USDT", "ETH", 86400, startDate, endDate, function(err, data) {
  if (err) {
    console.log("error!");
  }
  console.log(data);
  for (var i = 0; i < data.length; i++) {
    timeData.push([data[i].date, data[i].close]);
  }

  for (var i = 0; i < timeFrame; i++) {   // add elements to SMA
    var sum = 0;
    console.log('sum: '+sum);
    for (var j = 0; j < timeFrame; j++) {   // go through
      sum += timeData[j][1];
      console.log('tempsum: '+sum);
    }
    console.log('finalsum: '+sum);
    sum = sum / timeFrame;
    console.log('finalavg: '+sum);
    SMATimeSeries.push([timeData[i+timeFrame][0], sum]);
    console.log(SMATimeSeries[i]);
  }
  console.log(SMATimeSeries);
});

/*
// Can implement timeSeriesData as a Queue
var simpleMovingAverage = function (timeSeriesData, newDataPoint, timePeriod) {

  timeSeriesData.push(newDataPoint);
  timeSeriesData.pop();
  var MA = 0;
  for (point in timeSeriesData) {
    if (point.data < timePeriod) {
        MA += point.value;
    }
  }

  MA = MA / timePeriod;
  return MA;
}

module.exports = function(indicatorMixin, accessor_ohlc) {  // Injected dependencies
  return function() { // Closure function
    var p = {},  // Container for private, direct access mixed in variables
        samples,
        currentIndex,
        total;

    function indicator(data) {
      indicator.init();
      return data.map(ma).filter(function(d) { return d.value !== null; });
    }

    indicator.init = function() {
      total = 0;
      samples = [];
      currentIndex = 0;
      return indicator;
    };

    function ma(d, i) {
      var value = indicator.average(p.accessor(d));
      if (i+1 < p.period) value = null;
      return { date: p.accessor.d(d), value: value };
    }

    indicator.average = function(value) {
      total += value;

      if(samples.length+1 < p.period) {
        samples.push(value);
        return total/++currentIndex;
      }
      else {
        if(samples.length < p.period) {
          samples.push(value);
          total += value;
        }

        total -= samples[currentIndex];
        samples[currentIndex] = value;
        if(++currentIndex === p.period) {
          currentIndex = 0;
        }

        return total/p.period;
      }
    };

    // Mixin 'superclass' methods and variables
    indicatorMixin(indicator, p)
      .accessor(accessor_ohlc())
      .period(10);

    return indicator;
  };
};
*/
<|endoftext|>


<commit_before>
// This file sets up boxing of javascript native objects into squeak objects
// All relevant classes are enhanced by that functionality and there are
// Several global functions to box or unbox objects.

// Some objects are boxing primitive js-values. Unboxing these values is polymorphic.
// The real version of this method is below. This could alternatively throw an error,
// but we try to be tolerant.
_Object._addInstanceMethods({
	_unbox: function() {
		return this;
	},
	// This never gets called, we just need a true-ish slot in each box-instance
	_isBoxedObject: function() { throw "just access this slot without calling."; }
});

// Class, that will wrap native javascript-objects to implement the Object-interface.
// Additionally, it adds accessor-methods for all fields to provide a squeak-API to
// set slots on javascript-objects.
Class("_Box", { superclass: _Object }};

// Functions to bootstrap primitive values and wrap them into 'squeak'-objects
// Most functions are used in translated code directly, to avoid switch-statement in _boxObject()
// (Instead of bool(), compiled code uses _true/_false directly. bool() is used in kernel_primitives.js etc.)
var bool = function(aBool) { if (aBool) { return _true; } else { return _false; } }
var character = function(aString) { return Character._wrapping(aString); }
var string = function(aString) { return ByteString._wrapping(aString); }
var number = function(aNumber) { return Float._wrapping(number); }
var array = function(anArray) { return _Array._wrapping(anArray); }
var object = function(anArray) { return _Box._wrapping(anArray); }
// if we box a javascript function into a smalltalk block we must bind it on creation
// Non-local-return handling is not required here
var boundBlock = function(func, that) {
	var b = BlockClosure._newInstance();
	b.original$ = function() {
		var unboxedArguments = [];
		for (index in arguments) {
			unboxedArguments.push(arguments[index].unbox());
		}
		return _boxObject(func.apply(that, unboxedArguments));
	}
	return b;
}

// There are multiple js-'classes', that will be wrapped into a Squeak-Array
var arrayConstructors = [Array, NodeList];
var isArrayObject = function(anObject) {
	var constructor = anObject.constructor;
	for (index in arrayConstructors) {
		if (arrayConstructors[index] == constructor) {
			return true;
		}
	}
	return false;
};

// This static unboxing-function is added to avoid adding an _unbox method to native js-objects
var _unboxObject = function(anyObject) {
	if (_boxObject._isBoxedObject) {
		return _boxObject._unbox();
	}
	return anyObject;
};
var _boxObject = function(nativeObject, that) { // The 'that' parameter is optional and will be undefined otherwise
	if (nativeObject._isBoxedObject) {
		switch( typeof(nativeObject) ) {
			case "number": return number(nativeObject); break;
			case "string": return string(nativeObject); break;
			case "boolean": return bool(nativeObject); break;
			case "function": return boundBlock(nativeObject, that); break;
			case "undefined": return nil; break;
			case "object":
				if (nativeObject == null) {
					return nil;
				} else if (isArrayObject(nativeObject) {
					return array(nativeObject);
				} else {
					return object(nativeObject);
				}
				break;
			default:
				alert("Could not box creepy object: " + nativeObject);
		}
    }
	// nativeObject is already boxed!
	return nativeObject;
};

// These boxing classes box fixed, immutable values
False._addInstanceMethods( { _unbox: function() { return false; } } );
True._addInstanceMethods( { _unbox: function() { return true; } } );
UndefinedObject._addInstanceMethods( { _unbox: function() { return null; } } );

// These boxing classes box variable values and are all added the same functionality.
var boxingClasses = [_Box, ByteString, _Number, Character, BlockClosure, _Array, OrderedCollection];
var getAllPropertyNames = function(obj) {
	if (typeof(obj) == "object" && obj != null) {
		// recurse up the prototype chain until null
		return Object.getOwnPropertyNames(obj).concat(getAllPropertyNames(obj.__proto__));
	} else {
		return [];
	}
};
for (index in boxingClasses) {
	var aClass = boxingClasses[index];
	aClass.addClassMethods({
		_wrapping: function(originalObject) {
			var result = _Box._new();
			result.original$ = originalObject;
			result._generateAccessors();
			return result;
		}
	});
	aClass.addInstanceMethods({
		_unbox: {
			return this.original$;
		}
	});
}
<commit_msg>small bugfix<commit_after>
// This file sets up boxing of javascript native objects into squeak objects
// All relevant classes are enhanced by that functionality and there are
// Several global functions to box or unbox objects.

// Some objects are boxing primitive js-values. Unboxing these values is polymorphic.
// The real version of this method is below. This could alternatively throw an error,
// but we try to be tolerant.
_Object._addInstanceMethods({
	_unbox: function() {
		return this;
	},
	// This never gets called, we just need a true-ish slot in each box-instance
	_isBoxedObject: function() { throw "just access this slot without calling."; }
});

// Class, that will wrap native javascript-objects to implement the Object-interface.
// Additionally, it adds accessor-methods for all fields to provide a squeak-API to
// set slots on javascript-objects.
Class("_Box", { superclass: _Object });

// Functions to bootstrap primitive values and wrap them into 'squeak'-objects
// Most functions are used in translated code directly, to avoid switch-statement in _boxObject()
// (Instead of bool(), compiled code uses _true/_false directly. bool() is used in kernel_primitives.js etc.)
var bool = function(aBool) { if (aBool) { return _true; } else { return _false; } }
var character = function(aString) { return Character._wrapping(aString); }
var string = function(aString) { return ByteString._wrapping(aString); }
var number = function(aNumber) { return Float._wrapping(number); }
var array = function(anArray) { return _Array._wrapping(anArray); }
var object = function(anArray) { return _Box._wrapping(anArray); }
// if we box a javascript function into a smalltalk block we must bind it on creation
// Non-local-return handling is not required here
var boundBlock = function(func, that) {
	var b = BlockClosure._newInstance();
	b.original$ = function() {
		var unboxedArguments = [];
		for (index in arguments) {
			unboxedArguments.push(arguments[index].unbox());
		}
		return _boxObject(func.apply(that, unboxedArguments));
	}
	return b;
}

// There are multiple js-'classes', that will be wrapped into a Squeak-Array
var arrayConstructors = [Array, NodeList];
var isArrayObject = function(anObject) {
	var constructor = anObject.constructor;
	for (index in arrayConstructors) {
		if (arrayConstructors[index] == constructor) {
			return true;
		}
	}
	return false;
};

// This static unboxing-function is added to avoid adding an _unbox method to native js-objects
var _unboxObject = function(anyObject) {
	if (_boxObject._isBoxedObject) {
		return _boxObject._unbox();
	}
	return anyObject;
};
var _boxObject = function(nativeObject, that) { // The 'that' parameter is optional and will be undefined otherwise
	if (nativeObject._isBoxedObject) {
		switch( typeof(nativeObject) ) {
			case "number": return number(nativeObject); break;
			case "string": return string(nativeObject); break;
			case "boolean": return bool(nativeObject); break;
			case "function": return boundBlock(nativeObject, that); break;
			case "undefined": return nil; break;
			case "object":
				if (nativeObject == null) {
					return nil;
				} else if (isArrayObject(nativeObject)) {
					return array(nativeObject);
				} else {
					return object(nativeObject);
				}
				break;
			default:
				alert("Could not box creepy object: " + nativeObject);
		}
    }
	// nativeObject is already boxed!
	return nativeObject;
};

// These boxing classes box fixed, immutable values
False._addInstanceMethods( { _unbox: function() { return false; } } );
True._addInstanceMethods( { _unbox: function() { return true; } } );
UndefinedObject._addInstanceMethods( { _unbox: function() { return null; } } );

// These boxing classes box variable values and are all added the same functionality.
var boxingClasses = [_Box, ByteString, _Number, Character, BlockClosure, _Array, OrderedCollection];
var getAllPropertyNames = function(obj) {
	if (typeof(obj) == "object" && obj != null) {
		// recurse up the prototype chain until null
		return Object.getOwnPropertyNames(obj).concat(getAllPropertyNames(obj.__proto__));
	} else {
		return [];
	}
};
for (index in boxingClasses) {
	var aClass = boxingClasses[index];
	aClass._addClassMethods({
		_wrapping: function(originalObject) {
			var result = _Box._new();
			result.original$ = originalObject;
			return result;
		}
	});
	aClass._addInstanceMethods({
		_unbox: function() {
			return this.original$;
		}
	});
}
<|endoftext|>


<commit_before>// split a string to get text between before & after characters
//var i = 0;

function between(input, before, after) {
  i = input.indexOf(before);
  if (i >= 0) {
    input = input.substring(i + before.length);
  }
  else {
    return '';
  }
  if (after) {
    i = input.indexOf(after);
    if (i >= 0) {
      input = input.substring(0, i);
    }
    else {
      return '';
    }
  }
  return input;
}

//folderStructure object we want to get
var folderStructure = {
    files: null,
    subDirs: {
      dir1: {
        files: ['file1', 'file2'],
        subDirs: {
          'subDirA': {
            files: ['file3', 'file4'],
            subDirs: null
          },
          'subDirB': {
            files: ['file5'],
            subDirs: null
          }
        }
      },
      dir2: {
        files: null,
        subDirs: {
          'subdirC': {
            files: ['file6'],
            subDirs: null
          }
        }
      },
    dir3: {
      files: null,
      subDirs: {
        'subDirD': {
          files: ['file7'],
          subDirs: null
        }
      }
    }
  }
};

var depthCount = 0;

function readFiles(obj) {
  for( var item in obj ) {
    if( typeof obj[item] === 'object' ) { //its a subDir, keep going
      if ( item !== 'subDirs' && item !== 'files') {
        console.log('mkdir & cd into', item);
        depthCount++;
      }
      if( Array.isArray(obj[item]) ) { //if its an array, its the folders
        for (var i = 0; i < obj[item].length; i++) {
          console.log('touch ', obj[item][i]);
        }
        if( obj.subDirs == null ) { //you hit the end of the tree
          console.log('cd ../');
        }
        depthCount--;
      }
      readFiles(obj[item]); // recurse!
    }
    else {
      for (i=0; i<depthCount; i++) {
        console.log('cd ../');
      }
    }
  }
}

//console.log( readFiles( folderStructure ) );

readFiles(folderStructure);

<commit_msg>i think the depth count and everything is right. so im p excited<commit_after>// split a string to get text between before & after characters
//var i = 0;

function between(input, before, after) {
  i = input.indexOf(before);
  if (i >= 0) {
    input = input.substring(i + before.length);
  }
  else {
    return '';
  }
  if (after) {
    i = input.indexOf(after);
    if (i >= 0) {
      input = input.substring(0, i);
    }
    else {
      return '';
    }
  }
  return input;
}

//folderStructure object we want to get
var folderStructure = {
    files: null,
    subDirs: {
      dir1: {
        files: ['file1', 'file2'],
        subDirs: {
          'subDirA': {
            files: ['file3', 'file4'],
            subDirs: null
          },
          'subDirB': {
            files: ['file5'],
            subDirs: null
          }
        }
      },
      dir2: {
        files: ['hello'],
        subDirs: {
          'subdirC': {
            files: ['file6'],
            subDirs: {
              'moreA': {
                files: ['file3', 'file4'],
                subDirs: null
              },
              'moreB': {
                files: ['file5'],
                subDirs: null
              }
            }
          }
        }
      },
    dir3: {
      files: null,
      subDirs: {
        'subDirD': {
          files: ['file7'],
          subDirs: null
        }
      }
    }
  }
};

var depthCount = 0;
var thisItem, lastDir;

function readFiles(obj) {
  for( var item in obj ) {
    if( typeof obj[item] === 'object' ) { //its a subDir, keep going
      if ( item !== 'subDirs' && item !== 'files') {
        //if its the last prop, cd back again
        lastDir = Object.keys(obj)[Object.keys(obj).length - 1]; //this is the last directory in the cluster
        thisItem = item;
        console.log('mkdir & cd into', item);
        depthCount++;
      }
      if( Array.isArray(obj[item]) ) { //if its an array, its the files
        for (var i = 0; i < obj[item].length; i++) {
          console.log('touch ', obj[item][i]);
        }
        if( obj.subDirs == null ) { //you hit the end of the tree
          depthCount--;
          console.log('cd ../', depthCount);
          if(lastDir === thisItem) { //if its the last dir in the dir we're looping
            depthCount--;
            console.log('cd ../', depthCount);

            for(i=0; i<depthCount; i++) {
              depthCount--;
              console.log('cd ../', depthCount);
            }
          }
        }
      }
      readFiles(obj[item]); // recurse!
    }
    // else {
    //   for (i=0; i<depthCount; i++) {
    //     // console.log('other cd ../');
    //   }
    // }
  }
}

//console.log( readFiles( folderStructure ) );

readFiles(folderStructure);

<|endoftext|>


<commit_before>process.exit(
     0.00 // budget.js - keeping the books for @corridorjs
          // by @gordtanner and @alexkinsella

          // Ideas borrowed with love from https://github.com/brooklynjs/brooklynjs.github.io

          // Corridor 0.0.1, 2016-09-29T19:00Z

+  210.00 // ticket sales            @gtanner
+  146.98 // surprise sponsorship    @dozrhub

-  146.98 // bar tab                 @mccabes
-   17.44 // ticketing               @tito
-  192.56 // donation                @kwhumane
);
<commit_msg>updated budget<commit_after>process.exit(
     0.00 // budget.js - keeping the books for @corridorjs
          // by @gordtanner and @carlosperez

          // Ideas borrowed with love from https://github.com/brooklynjs/brooklynjs.github.io

          // Corridor 0.0.1, 2016-09-29T19:00Z

+  210.00 // ticket sales            @gtanner
+  146.98 // surprise sponsorship    @dozrhub

-  146.98 // bar tab                 @mccabes
-   17.44 // ticketing               @tito
-  192.56 // donation                @kwhumane

          // Corridor 0.0.2, 2016-10-27T19:00Z

+   70.00 // ticket sales            @gtanner
+   93.99 // sponsorship             @gtanner

-   93.99 // bar tab                 @mccabes
-   14.07 // ticketing               @tito
-   55.93 // donation                @kwhumane
);
<|endoftext|>