<commit_before>var wav_1_minute = 'RFPT-WW13-20111229213002-540-60-KR8.wav';
var wav_15_minute = "RFPT-WW10A-2013-02-14T02.00.10-KR5.wav";
var URL = wav_15_minute;

var COLOUR_LUT = {
    k: "#0ff",
    m: "#f00",
    f: "#0f0",
    r: "#ff0",
    n: "#f0f",
    e: "#000"
};

var audio_context;

function parse_wav(raw){
    /*   https://ccrma.stanford.edu/courses/422/projects/WaveFormat/ */
    var header = new DataView(raw, 0, 44);
    var data = raw.slice(44);
    if (header.getUint32(0, 0) != 0x52494646 || //'RIFF'
        header.getUint32(8, 0) != 0x57415645 || //'WAVE'
        header.getUint16(20, 1) != 1         || //format (pcm == 1)
        header.getUint32(40, 1) != data.byteLength  //length should match data
       ){
       message("I can't understand this file. Is it really a WAV?" +
               " (Continuing regardless...)");
       console.log(header.getUint32(0, 0), 0x52494646,
       header.getUint32(8, 0), 0x57415645,
       header.getUint16(16, 1), 1,
       header.getUint32(40, 1), data.byteLength);
    }
    var samplerate = header.getUint32(24, 1);
    /*if there are more than one channel, just silently grab the first one */
    var channels = header.getUint16(22, 1);
    var bits_per_sample = header.getUint16(34, 1);
    var samples, scale;
    if (bits_per_sample == 8){
        samples = new Int8Array(data);
        scale = 1.0 / 256;
    }
    else if (bits_per_sample == 16){
        samples = new Int16Array(data);
        scale = 1.0 / 32768;
    }
    var normalised_samples = new Float32Array(samples.length / channels);
    for (var i = 0; i < normalised_samples.length; i++){
        normalised_samples[i] = samples[i * channels] * scale;
    }
    return {
        audio: normalised_samples,
        samplerate: samplerate
    };
}

function hann_window(length){
    var i;
    var window = new Float32Array(length);
    var tau_norm = Math.PI * 2 / length;
    for (i = 0; i < length; i++){
        window[i] = 0.5 - 0.5 * Math.cos(tau_norm * i);
    }
    return window;
}

function paint_spectrogram(audio, window_size, samplerate, pixels, width, height,
                           row_height){
    var i;
    var left, col, row;
    var fft = new FFT(window_size, samplerate);
    var spacing = 120 * samplerate / (width); /* fit 2 minutes across */
    var mask_window = hann_window(window_size);
    var data_window = new Float32Array(window_size);
    var window_padding = 10;
    var spectrum_low = 20;
    var spectrum_high = 200;
    var pixwidth = width * 4;
    for (left = 0, col = 0, row = 0;
         left + window_size <= audio.length;
         left += spacing, col++){
        var square_window = audio.subarray(left, left + window_size);
        for (i = 0; i < window_size; i++){
            data_window[i] = square_window[i] * mask_window[i];
        }
        fft.forward(data_window);
        var s = fft.spectrum; /*power spectrum, normalised somehow*/
        if (col >= width){
            col -= width;
            row++;
            console.log(col, row);
        }
        var base_offset = (((row + 1) * row_height + window_padding) * width + col) * 4;
        for (i = spectrum_low; i < spectrum_high; i++){
            var o = base_offset - i * pixwidth;
            var v = s[i * 2] + s[i * 2 + 1];
            //console.log(i, o, v);
            pixels[o] = v * v * 6e8;
            pixels[o + 1] = v * 3e5;// + Math.sin(v * 1e3) * 50;
            pixels[o + 2] = Math.sqrt(v) * 6e3;
            pixels[o + 3] = 255;
        }
    }
}

function fill_canvas(audio, samplerate, native_audio){
    var canvas = document.getElementById('fft');
    var context = canvas.getContext('2d');
    var width = canvas.width;
    var pixel2sec = 120 / width;
    var row_height = 200;
    var height = Math.ceil(audio.length / samplerate / 120) * row_height;
    canvas.height = height;
    var audio_source;
    var window_size = 1024;
    var imgdata = context.createImageData(canvas.width, canvas.height);
    var pixels = imgdata.data;

    paint_spectrogram(audio, window_size, samplerate,
                      pixels, canvas.width, canvas.height, row_height);
    context.putImageData(imgdata, 0, 0);

    function refill_background(){
        var data = context.getImageData(0, 0, canvas.width, canvas.height);
        var pix = data.data;
        for (var i = 0; i < pix.length; i += 4){
            if (pix[i] == 0 && pix[i + 1] == 0 && pix[i + 2] == 0){
                pix[i] = pixels[i];
                pix[i + 1] = pixels[i + 1];
                pix[i + 2] = pixels[i + 2];
            }
        }
        context.putImageData(data, 0, 0);
    }
    var drawing = 0;
    var playing_column = 0;
    var playing_row = 0;
    var hidden_data;
    var playing_column_interval;
    var colour = COLOUR_LUT['m'];
    var colour_label = document.getElementById("colour-m");
    colour_label.style.background = "#fc0";
    function switch_colour(c){
        if (colour === '#000'){
            refill_background();
        }
        var new_colour = COLOUR_LUT[c];
        if (new_colour !== undefined){
            colour_label.style.background = "#fff";
            colour_label = document.getElementById("colour-" + c);
            colour_label.style.background = "#fc4";
            colour = new_colour;
        }
    }

    for (var c in COLOUR_LUT){
        var label = document.getElementById("colour-" + c);
        label.onclick = function(x){
            return function(){switch_colour(x);};
        }(c);
    }
    function advance_playing_line(){
        context.putImageData(hidden_data, playing_column, playing_row * row_height);
        playing_column++;
        if (playing_column >= canvas.width){
            playing_column = 0;
            playing_row++;
        }
        hidden_data = context.getImageData(playing_column, playing_row * row_height,
                                           1, row_height);
        context.fillRect(playing_column, playing_row * row_height, 1, row_height);
    }
    function stop_playing(){
        if (audio_source !== undefined){
            audio_source.stop(0);
        }
        audio_source = undefined;
    }

    function start_playing_at_point(x, y){
        stop_playing();
        audio_source = audio_context.createBufferSource();
        audio_source.buffer = native_audio;
        audio_source.connect(audio_context.destination);
        var row = parseInt(y / row_height);
        audio_source.start(0, x * pixel2sec + row * 120);
        if (hidden_data !== undefined && playing_column !== undefined){
            context.putImageData(hidden_data, playing_column, playing_row * row_height);
        }
        playing_column = x;
        playing_row = row;
        context.fillStyle = "#ff3";
        hidden_data = context.getImageData(x, row * row_height, 1, row_height);
        context.fillRect(x, row * row_height, 1, row_height);
        playing_column_interval = window.setInterval(advance_playing_line,
                                                     pixel2sec * 1000);
        audio_source.onended = function(id){
            return function(){
                window.clearInterval(id);
            };
        }(playing_column_interval);
    }

    canvas.onclick = function(e){
        if (e.shiftKey){
            var x = e.pageX - this.offsetLeft;
            var y = e.pageY - this.offsetTop;
            start_playing_at_point(x, y);
        }
    };

    function draw_to(x, y, colour){
        context.lineTo(x, y);
        context.stroke();
    }
    canvas.onmousedown = function(e){
        if (! e.shiftKey){
            drawing = 1;
            var x = e.pageX - this.offsetLeft;
            var y = e.pageY - this.offsetTop;
            context.beginPath();
            context.lineWidth = 5;
	    context.lineJoin = 'round';
            context.strokeStyle = colour;
            context.moveTo(x, y);
            draw_to(x, y);
        }
    };
    document.onmouseup = function(e){
        drawing = 0;
    };
    canvas.onmousemove = function(e){
        if (drawing){
            draw_to(e.pageX - this.offsetLeft,
                    e.pageY - this.offsetTop);
        }
    };
    document.onkeypress = function(e){
        var c = String.fromCharCode(e.charCode);
        if (COLOUR_LUT[c] !== undefined){
            switch_colour(c);
        }
        else if (c == ' ' || c == 'p'){
            if (audio_source === undefined){
                start_playing_at_point(playing_column, playing_row * row_height);
            }
            else {
                stop_playing();
            }
            e.preventDefault();
        }
    };
}

function message(m){
    var el = document.getElementById('message');
    el.innerHTML += "
" +  m + "
";
}

function load_audio(url) {
    var AudioContext = window.AudioContext || window.webkitAudioContext;
    if (! AudioContext){
        message("Web API seems to be missing from this browser.
" +
               "It could almost work like that, but I can't be bothered" +
               " maintaining it. Expect errors. Sorry!");
    }
    /*audio_context is global*/
    audio_context = new AudioContext();
    var request = new XMLHttpRequest();
    request.open('GET', url, true);
    request.responseType = 'arraybuffer';
    request.onload = function(){
        var wav = request.response;
        audio_context.decodeAudioData(wav,
            function(audio) {
                var norm = parse_wav(wav);
                fill_canvas(norm.audio, norm.samplerate, audio);
            });
    };
    request.send();
}

function on_page_load() {
    if (document.location.protocol == 'file:'){
        message("Warning: this probably won't work from the local filesystem " +
                "(<tt>file://</tt> protocol), due to browser security settings. " +
                "
Use a local webserver, like webfsd.");
    }
    load_audio(URL);
}

window.addEventListener('load', on_page_load);
<commit_msg>Split paint_spectrogram into calculate and paint parts<commit_after>var wav_1_minute = 'RFPT-WW13-20111229213002-540-60-KR8.wav';
var wav_15_minute = "RFPT-WW10A-2013-02-14T02.00.10-KR5.wav";
var URL = wav_15_minute;

var COLOUR_LUT = {
    k: "#0ff",
    m: "#f00",
    f: "#0f0",
    r: "#ff0",
    n: "#f0f",
    e: "#000"
};

var audio_context;

function parse_wav(raw){
    /*   https://ccrma.stanford.edu/courses/422/projects/WaveFormat/ */
    var header = new DataView(raw, 0, 44);
    var data = raw.slice(44);
    if (header.getUint32(0, 0) != 0x52494646 || //'RIFF'
        header.getUint32(8, 0) != 0x57415645 || //'WAVE'
        header.getUint16(20, 1) != 1         || //format (pcm == 1)
        header.getUint32(40, 1) != data.byteLength  //length should match data
       ){
       message("I can't understand this file. Is it really a WAV?" +
               " (Continuing regardless...)");
       console.log(header.getUint32(0, 0), 0x52494646,
       header.getUint32(8, 0), 0x57415645,
       header.getUint16(16, 1), 1,
       header.getUint32(40, 1), data.byteLength);
    }
    var samplerate = header.getUint32(24, 1);
    /*if there are more than one channel, just silently grab the first one */
    var channels = header.getUint16(22, 1);
    var bits_per_sample = header.getUint16(34, 1);
    var samples, scale;
    if (bits_per_sample == 8){
        samples = new Int8Array(data);
        scale = 1.0 / 256;
    }
    else if (bits_per_sample == 16){
        samples = new Int16Array(data);
        scale = 1.0 / 32768;
    }
    var normalised_samples = new Float32Array(samples.length / channels);
    for (var i = 0; i < normalised_samples.length; i++){
        normalised_samples[i] = samples[i * channels] * scale;
    }
    return {
        audio: normalised_samples,
        samplerate: samplerate
    };
}

function hann_window(length){
    var i;
    var window = new Float32Array(length);
    var tau_norm = Math.PI * 2 / length;
    for (i = 0; i < length; i++){
        window[i] = 0.5 - 0.5 * Math.cos(tau_norm * i);
    }
    return window;
}

function calculate_spectrogram(audio, window_size, samplerate, spacing){
    var i, left, j;
    var fft = new FFT(window_size, samplerate);
    var mask_window = hann_window(window_size);
    var data_window = new Float32Array(window_size);
    var window_padding = 10;
    var spectrogram_height = parseInt(window_size / 2);
    var spectrogram_length = parseInt(audio.length / window_size);
    var spectrogram = new Float32Array(spectrogram_length * spectrogram_height);
    for (j = 0; j < spectrogram_length; j++){
        left = j * spacing;
        var square_window = audio.subarray(left, left + window_size);
        for (i = 0; i < window_size; i++){
            data_window[i] = square_window[i] * mask_window[i];
        }
        fft.forward(data_window);
        spectrogram.set(fft.spectrum, j * spectrogram_height);
    }
    return {
        width: spectrogram_length,
        height: spectrogram_height,
        data: spectrogram
    };
}

function paint_spectrogram(spectrogram, pixels, width, height,
                           row_height){
    var i;
    var left, col, row;
    var window_padding = 10;
    var spectrum_low = 20;
    var spectrum_high = 200;
    var pixwidth = width * 4;
    var s_data = spectrogram.data;
    var s_width = spectrogram.width;
    var s_height = spectrogram.height;
    for (j = 0, col = 0, row = 0;
         j < s_width;
         j++, col++){
        var x  = j * s_height;
        var s = s_data.subarray(x, x + s_height);
        var base_offset = (((row + 1) * row_height + window_padding) * width + col) * 4;
        for (i = spectrum_low; i < spectrum_high; i++){
            var o = base_offset - i * pixwidth;
            var v = s[i * 2] + s[i * 2 + 1];
            pixels[o] = v * v * 6e8;
            pixels[o + 1] = v * 3e5;// + Math.sin(v * 1e3) * 50;
            pixels[o + 2] = Math.sqrt(v) * 6e3;
            pixels[o + 3] = 255;
        }
        if (col >= width){
            col -= width;
            row++;
            console.log(col, row);
        }
    }
}

function fill_canvas(audio, samplerate, native_audio){
    var canvas = document.getElementById('fft');
    var context = canvas.getContext('2d');
    var width = canvas.width;
    var pixel2sec = 120 / width;
    var row_height = 200;
    var height = Math.ceil(audio.length / samplerate / 120) * row_height;
    canvas.height = height;
    var audio_source;
    var window_size = 1024;
    var spacing = 120 * samplerate / (width); /* fit 2 minutes across */

    console.time('calculate_spectrogram');
    var spectrogram = calculate_spectrogram(audio, window_size, samplerate, spacing);
    console.timeEnd('calculate_spectrogram');
    console.time('paint_spectrogram');
    var imgdata = context.createImageData(canvas.width, canvas.height);
    var pixels = imgdata.data;
    paint_spectrogram(spectrogram,
                      pixels, canvas.width, canvas.height, row_height);
    console.timeEnd('paint_spectrogram');
    console.time('putImageData');
    context.putImageData(imgdata, 0, 0);
    console.timeEnd('putImageData');

    function refill_background(){
        var data = context.getImageData(0, 0, canvas.width, canvas.height);
        var pix = data.data;
        for (var i = 0; i < pix.length; i += 4){
            if (pix[i] == 0 && pix[i + 1] == 0 && pix[i + 2] == 0){
                pix[i] = pixels[i];
                pix[i + 1] = pixels[i + 1];
                pix[i + 2] = pixels[i + 2];
            }
        }
        context.putImageData(data, 0, 0);
    }
    var drawing = 0;
    var playing_column = 0;
    var playing_row = 0;
    var hidden_data;
    var playing_column_interval;
    var colour = COLOUR_LUT['m'];
    var colour_label = document.getElementById("colour-m");
    colour_label.style.background = "#fc0";
    function switch_colour(c){
        if (colour === '#000'){
            refill_background();
        }
        var new_colour = COLOUR_LUT[c];
        if (new_colour !== undefined){
            colour_label.style.background = "#fff";
            colour_label = document.getElementById("colour-" + c);
            colour_label.style.background = "#fc4";
            colour = new_colour;
        }
    }

    for (var c in COLOUR_LUT){
        var label = document.getElementById("colour-" + c);
        label.onclick = function(x){
            return function(){switch_colour(x);};
        }(c);
    }
    function advance_playing_line(){
        context.putImageData(hidden_data, playing_column, playing_row * row_height);
        playing_column++;
        if (playing_column >= canvas.width){
            playing_column = 0;
            playing_row++;
        }
        hidden_data = context.getImageData(playing_column, playing_row * row_height,
                                           1, row_height);
        context.fillRect(playing_column, playing_row * row_height, 1, row_height);
    }
    function stop_playing(){
        if (audio_source !== undefined){
            audio_source.stop(0);
        }
        audio_source = undefined;
    }

    function start_playing_at_point(x, y){
        stop_playing();
        audio_source = audio_context.createBufferSource();
        audio_source.buffer = native_audio;
        audio_source.connect(audio_context.destination);
        var row = parseInt(y / row_height);
        audio_source.start(0, x * pixel2sec + row * 120);
        if (hidden_data !== undefined && playing_column !== undefined){
            context.putImageData(hidden_data, playing_column, playing_row * row_height);
        }
        playing_column = x;
        playing_row = row;
        context.fillStyle = "#ff3";
        hidden_data = context.getImageData(x, row * row_height, 1, row_height);
        context.fillRect(x, row * row_height, 1, row_height);
        playing_column_interval = window.setInterval(advance_playing_line,
                                                     pixel2sec * 1000);
        audio_source.onended = function(id){
            return function(){
                window.clearInterval(id);
            };
        }(playing_column_interval);
    }

    canvas.onclick = function(e){
        if (e.shiftKey){
            var x = e.pageX - this.offsetLeft;
            var y = e.pageY - this.offsetTop;
            start_playing_at_point(x, y);
        }
    };

    function draw_to(x, y, colour){
        context.lineTo(x, y);
        context.stroke();
    }
    canvas.onmousedown = function(e){
        if (! e.shiftKey){
            drawing = 1;
            var x = e.pageX - this.offsetLeft;
            var y = e.pageY - this.offsetTop;
            context.beginPath();
            context.lineWidth = 5;
	    context.lineJoin = 'round';
            context.strokeStyle = colour;
            context.moveTo(x, y);
            draw_to(x, y);
        }
    };
    document.onmouseup = function(e){
        drawing = 0;
    };
    canvas.onmousemove = function(e){
        if (drawing){
            draw_to(e.pageX - this.offsetLeft,
                    e.pageY - this.offsetTop);
        }
    };
    document.onkeypress = function(e){
        var c = String.fromCharCode(e.charCode);
        if (COLOUR_LUT[c] !== undefined){
            switch_colour(c);
        }
        else if (c == ' ' || c == 'p'){
            if (audio_source === undefined){
                start_playing_at_point(playing_column, playing_row * row_height);
            }
            else {
                stop_playing();
            }
            e.preventDefault();
        }
    };
}

function message(m){
    var el = document.getElementById('message');
    el.innerHTML += "
" +  m + "
";
}

function load_audio(url) {
    var AudioContext = window.AudioContext || window.webkitAudioContext;
    if (! AudioContext){
        message("Web API seems to be missing from this browser.");
    }
    /*audio_context is global*/
    audio_context = new AudioContext();
    var request = new XMLHttpRequest();
    request.open('GET', url, true);
    request.responseType = 'arraybuffer';
    request.onload = function(){
        var wav = request.response;
        audio_context.decodeAudioData(wav,
            function(audio) {
                var norm = parse_wav(wav);
                fill_canvas(norm.audio, norm.samplerate, audio);
            });
    };
    request.send();
}

function on_page_load() {
    if (document.location.protocol == 'file:'){
        message("Warning: this probably won't work from the local filesystem " +
                "(<tt>file://</tt> protocol), due to browser security settings. " +
                "
Use a local webserver, like webfsd.");
    }
    load_audio(URL);
}

window.addEventListener('load', on_page_load);
<|endoftext|>


<commit_before>var Activity = require('./activity');
var Readable = require('stream').Readable;
var util = require('util');

/**
 * Readable stream that emits event objects from the github events api for a
 * given user
 */
function ActivityStream() {
   this.eventsPromise = Activity.get();
   this.eventIndex = 0;
   Readable.call(this, {objectMode:true});
}
util.inherits(ActivityStream, Readable);

ActivityStream.prototype._read = function () {
   pushNextEvent(this);
};

function pushNextEvent(stream) {
   stream.eventsPromise.done(function(events) {
      if (!events) {
         return stream.push(null);
      }
      if (!events[stream.eventIndex]) {
         stream.eventsPromise = events.nextPage();
         stream.eventIndex = 0;
         pushNextEvent(stream);
      }
      stream.push(events[stream.eventIndex]);
      stream.eventIndex++;
   });
}

module.exports = ActivityStream;
<commit_msg>Fix bug with repeated events<commit_after>var Activity = require('./activity');
var Readable = require('stream').Readable;
var util = require('util');

/**
 * Readable stream that emits event objects from the github events api for a
 * given user
 */
function ActivityStream() {
   this.eventsPromise = Activity.get();
   this.eventIndex = 0;
   Readable.call(this, {objectMode:true});
}
util.inherits(ActivityStream, Readable);

ActivityStream.prototype._read = function () {
   pushNextEvent(this);
};

function pushNextEvent(stream) {
   stream.eventsPromise.done(function(events) {
      if (!events) {
         return stream.push(null);
      }
      // If we're at the end of the current page of events,
      // load some more.
      if (!events[stream.eventIndex]) {
         stream.eventsPromise = events.nextPage();
         stream.eventIndex = 0;
         pushNextEvent(stream);
      } else {
         stream.push(events[stream.eventIndex]);
         stream.eventIndex++;
      }
   });
}

module.exports = ActivityStream;
<|endoftext|>


<commit_before>import cleanObject from 'driveback-utils/cleanObject';
import { getProp } from 'driveback-utils/dotProp';
import {
  VIEWED_PAGE,
  VIEWED_PRODUCT_DETAIL,
  COMPLETED_TRANSACTION,
  REFUNDED_TRANSACTION,
  VIEWED_CART,
  ADDED_PRODUCT,
  REMOVED_PRODUCT,
  VIEWED_CHECKOUT_STEP,
  COMPLETED_CHECKOUT_STEP,
  SEARCHED_PRODUCTS,
  VIEWED_PRODUCT_LISTING,
  VIEWED_CAMPAIGN,
  CLICKED_CAMPAIGN,
} from './../../events/semanticEvents';

const userProps = [
  'isLoggedIn',
  'isReturning',
  'isSubscribed',
  'hasTransacted',
  'lastTransactionDate',
];

const pageProps = [
  'name',
  'category',
  'type',
  'breadcrumb',
  'url',
  'path',
  'queryString',
  'title',
  'hash',
];

const websiteProps = [
  'type',
  'region',
  'regionId',
  'language',
  'currency',
  'environment',
];

const productProps = [
  'id',
  'name',
  'currency',
  'unitSalePrice',
  'unitPrice',
  'category',
  'categoryId',
  'url',
  'imageUrl',
  'thumbnailUrl',
  'manufacturer',
  'skuCode',
  'stock',
  'voucher',
  'color',
  'size',
];

const listingProps = [
  'listId',
  'listName',
  'categoryId',
  'category',
  'query',
  'resultCount',
  'pagesCount',
  'currentPage',
  'sortBy',
  'layout',
];

const cartProps = [
  'id',
  'vouchers',
  'lineItems',
  'total',
  'subtotal',
  'currency',
  'voucherDiscount',
  'shippingCost',
  'paymentMethod',
];

const transactionProps = [
  'vouchers',
  'lineItems',
  'total',
  'subtotal',
  'currency',
  'voucherDiscount',
  'shippingCost',
  'paymentMethod',
  'orderId',
  'isFirst',
];

const campaignProps = [
  'id',
  'name',
  'category',
  'subcategory',
  'design',
  'position',
];

const filterObject = (obj, propSets, restrictedProps = []) => {
  const filteredObject = {};
  propSets.forEach((propsSet) => {
    propsSet.forEach((prop) => {
      if (obj[prop] !== undefined && restrictedProps.indexOf(prop) < 0) {
        filteredObject[prop] = obj[prop];
      }
    });
  });
  return filteredObject;
};

const fitlerObjectsArray = (objArray, propSets, restrictedProps) =>
  objArray.map(obj => filterObject(obj, propSets, restrictedProps));

class Filters {
  constructor(customUserProps = [], customProductProps = []) {
    this.customUserProps = customUserProps;
    this.customProductProps = customProductProps;
  }

  filterEventHit(event) {
    const mapping = {
      [VIEWED_PAGE]: this.filterViewedPage.bind(this),
      [VIEWED_PRODUCT_DETAIL]: this.filterViewedProductDetail.bind(this),
      [ADDED_PRODUCT]: this.filterAddedProduct.bind(this),
      [REMOVED_PRODUCT]: this.filterRemovedProduct.bind(this),
      [VIEWED_CART]: this.filterViewedCart.bind(this),
      [COMPLETED_TRANSACTION]: this.filterCompletedTransaction.bind(this),
      [REFUNDED_TRANSACTION]: this.filterRefundedTransaction.bind(this),
      [VIEWED_CHECKOUT_STEP]: this.filterViewedCheckoutStep.bind(this),
      [COMPLETED_CHECKOUT_STEP]: this.filterCompeltedCheckoutStep.bind(this),
      [VIEWED_PRODUCT_LISTING]: this.filterViewedProductListing.bind(this),
      [SEARCHED_PRODUCTS]: this.filterSearchedProducts.bind(this),
      [VIEWED_CAMPAIGN]: this.filterViewedCampaign.bind(this),
      [CLICKED_CAMPAIGN]: this.filterClickedCampaign.bind(this),
    };

    if (event.name && mapping[event.name]) {
      return mapping[event.name](event);
    }
    return this.filterCommonEvent(event);
  }

  filterUser(user) {
    const fitlered = filterObject(user, [userProps, this.customUserProps], [
      'anonymousId',
      'userId',
      'firstName',
      'lastName',
      'fullName',
      'phone',
      'email',
    ]);

    return fitlered;
  }

  filterProduct(product = {}) {
    return filterObject(
      {
        ...product,
        id: (product.id) ? String(product.id) : undefined,
        categoryId: (product.categoryId) ? String(product.categoryId) : undefined,
        category: (product.category && Array.isArray(product.category)) ?
          product.category.join('/') : product.category,
        unitPrice: (product.unitPrice) ? Number(product.unitPrice) : undefined,
        unitSalePrice: (product.unitSalePrice) ? Number(product.unitSalePrice) : undefined,
      },
      [productProps, this.customProductProps],
    );
  }

  filterListing(listing = {}) {
    return filterObject({
      ...listing,
      categoryId: (listing.categoryId) ? String(listing.categoryId) : undefined,
      category: (listing.category && Array.isArray(listing.category)) ?
        listing.category.join('/') : listing.category,
    }, [listingProps]);
  }

  filterLineItems(lineItems = []) {
    return lineItems.map(lineItem => cleanObject({
      product: this.filterProduct(lineItem.product),
      quantity: lineItem.quantity,
      subtotal: lineItem.subtotal,
    }));
  }

  filterTransaction(transaction = {}) {
    return filterObject({
      ...transaction,
      orderId: transaction.orderId ? String(transaction.orderId) : undefined,
    }, [transactionProps]);
  }

  filterPage(page = {}) {
    return filterObject({
      ...page,
      breadcrumb: (page.breadcrumb && Array.isArray(page.breadcrumb)) ?
        page.breadcrumb.join('/') : page.breadcrumb,
    }, [pageProps]);
  }

  filterWebsite(website = {}) {
    return filterObject(website, [websiteProps]);
  }

  filterViewedPage(event) {
    const filtered = this.filterCommonEvent(event);
    return {
      ...filtered,
      page: this.filterPage(event.page),
    };
  }

  filterViewedProductDetail(event) {
    const filtered = this.filterCommonEvent(event);
    const product = this.filterProduct(event.product);
    return { ...filtered, product };
  }

  filterAddedProduct(event) {
    const filtered = this.filterCommonEvent(event);
    return {
      ...filtered,
      product: this.filterProduct(event.product),
      quantity: event.quantity || 1,
    };
  }

  filterRemovedProduct(event) {
    return this.filterAddedProduct(event);
  }

  filterAddedProductToWishlist(event) {
    return this.filterAddedProduct(event);
  }

  filterRemovedProductFromWishlist(event) {
    return this.filterAddedProduct(event);
  }

  filterViewedCheckoutStep(event) {
    const filtered = this.filterCommonEvent(event);
    return {
      ...filtered,
      step: event.step,
    };
  }

  filterCompeltedCheckoutStep(event) {
    return this.filterViewedCheckoutStep(event);
  }

  filterViewedCart(event) {
    const filtered = this.filterCommonEvent(event);
    const cart = filterObject(event.cart, [cartProps]);
    cart.lineItems = this.filterLineItems(getProp(event, 'cart.lineItems'));
    return {
      ...filtered,
      cart,
    };
  }

  filterCompletedTransaction(event) {
    const filtered = this.filterCommonEvent(event);
    const transaction = this.filterTransaction(event.transaction);
    transaction.lineItems = this.filterLineItems(getProp(event, 'transaction.lineItems'));
    return {
      ...filtered,
      transaction,
    };
  }

  filterRefundedTransaction(event) {
    return this.filterCompletedTransaction(event);
  }

  filterViewedProductListing(event) {
    const filtered = this.filterCommonEvent(event);
    const listing = this.filterListing(event.listing);
    return {
      ...filtered,
      listing,
    };
  }

  filterSearchedProducts(event) {
    return this.filterViewedProductListing(event);
  }

  filterViewedCampaign(event) {
    const filtered = this.filterCommonEvent(event);
    let campaigns;
    if (event.campaign) {
      campaigns = [event.campaign];
    } else if (event.campaigns) {
      campaigns = event.campaigns;
    }

    if (campaigns) {
      return {
        ...filtered,
        campaigns: fitlerObjectsArray(campaigns, [campaignProps]),
      };
    }

    return filtered;
  }

  filterClickedCampaign(event) {
    return this.filterViewedCampaign(event);
  }

  filterCommonEvent(event) {
    return cleanObject({
      name: event.name,
      category: event.category,
      label: event.label,
    });
  }
}

export default Filters;
<commit_msg>regionId filter<commit_after>import cleanObject from 'driveback-utils/cleanObject';
import { getProp } from 'driveback-utils/dotProp';
import {
  VIEWED_PAGE,
  VIEWED_PRODUCT_DETAIL,
  COMPLETED_TRANSACTION,
  REFUNDED_TRANSACTION,
  VIEWED_CART,
  ADDED_PRODUCT,
  REMOVED_PRODUCT,
  VIEWED_CHECKOUT_STEP,
  COMPLETED_CHECKOUT_STEP,
  SEARCHED_PRODUCTS,
  VIEWED_PRODUCT_LISTING,
  VIEWED_CAMPAIGN,
  CLICKED_CAMPAIGN,
} from './../../events/semanticEvents';

const userProps = [
  'isLoggedIn',
  'isReturning',
  'isSubscribed',
  'hasTransacted',
  'lastTransactionDate',
];

const pageProps = [
  'name',
  'category',
  'type',
  'breadcrumb',
  'url',
  'path',
  'queryString',
  'title',
  'hash',
];

const websiteProps = [
  'type',
  'region',
  'regionId',
  'language',
  'currency',
  'environment',
];

const productProps = [
  'id',
  'name',
  'currency',
  'unitSalePrice',
  'unitPrice',
  'category',
  'categoryId',
  'url',
  'imageUrl',
  'thumbnailUrl',
  'manufacturer',
  'skuCode',
  'stock',
  'voucher',
  'color',
  'size',
];

const listingProps = [
  'listId',
  'listName',
  'categoryId',
  'category',
  'query',
  'resultCount',
  'pagesCount',
  'currentPage',
  'sortBy',
  'layout',
];

const cartProps = [
  'id',
  'vouchers',
  'lineItems',
  'total',
  'subtotal',
  'currency',
  'voucherDiscount',
  'shippingCost',
  'paymentMethod',
];

const transactionProps = [
  'vouchers',
  'lineItems',
  'total',
  'subtotal',
  'currency',
  'voucherDiscount',
  'shippingCost',
  'paymentMethod',
  'orderId',
  'isFirst',
];

const campaignProps = [
  'id',
  'name',
  'category',
  'subcategory',
  'design',
  'position',
];

const filterObject = (obj, propSets, restrictedProps = []) => {
  const filteredObject = {};
  propSets.forEach((propsSet) => {
    propsSet.forEach((prop) => {
      if (obj[prop] !== undefined && restrictedProps.indexOf(prop) < 0) {
        filteredObject[prop] = obj[prop];
      }
    });
  });
  return filteredObject;
};

const fitlerObjectsArray = (objArray, propSets, restrictedProps) =>
  objArray.map(obj => filterObject(obj, propSets, restrictedProps));

class Filters {
  constructor(customUserProps = [], customProductProps = []) {
    this.customUserProps = customUserProps;
    this.customProductProps = customProductProps;
  }

  filterEventHit(event) {
    const mapping = {
      [VIEWED_PAGE]: this.filterViewedPage.bind(this),
      [VIEWED_PRODUCT_DETAIL]: this.filterViewedProductDetail.bind(this),
      [ADDED_PRODUCT]: this.filterAddedProduct.bind(this),
      [REMOVED_PRODUCT]: this.filterRemovedProduct.bind(this),
      [VIEWED_CART]: this.filterViewedCart.bind(this),
      [COMPLETED_TRANSACTION]: this.filterCompletedTransaction.bind(this),
      [REFUNDED_TRANSACTION]: this.filterRefundedTransaction.bind(this),
      [VIEWED_CHECKOUT_STEP]: this.filterViewedCheckoutStep.bind(this),
      [COMPLETED_CHECKOUT_STEP]: this.filterCompeltedCheckoutStep.bind(this),
      [VIEWED_PRODUCT_LISTING]: this.filterViewedProductListing.bind(this),
      [SEARCHED_PRODUCTS]: this.filterSearchedProducts.bind(this),
      [VIEWED_CAMPAIGN]: this.filterViewedCampaign.bind(this),
      [CLICKED_CAMPAIGN]: this.filterClickedCampaign.bind(this),
    };

    if (event.name && mapping[event.name]) {
      return mapping[event.name](event);
    }
    return this.filterCommonEvent(event);
  }

  filterUser(user) {
    const fitlered = filterObject(user, [userProps, this.customUserProps], [
      'anonymousId',
      'userId',
      'firstName',
      'lastName',
      'fullName',
      'phone',
      'email',
    ]);

    return fitlered;
  }

  filterProduct(product = {}) {
    return filterObject(
      {
        ...product,
        id: (product.id) ? String(product.id) : undefined,
        categoryId: (product.categoryId) ? String(product.categoryId) : undefined,
        category: (product.category && Array.isArray(product.category)) ?
          product.category.join('/') : product.category,
        unitPrice: (product.unitPrice) ? Number(product.unitPrice) : undefined,
        unitSalePrice: (product.unitSalePrice) ? Number(product.unitSalePrice) : undefined,
      },
      [productProps, this.customProductProps],
    );
  }

  filterListing(listing = {}) {
    return filterObject({
      ...listing,
      categoryId: (listing.categoryId) ? String(listing.categoryId) : undefined,
      category: (listing.category && Array.isArray(listing.category)) ?
        listing.category.join('/') : listing.category,
    }, [listingProps]);
  }

  filterLineItems(lineItems = []) {
    return lineItems.map(lineItem => cleanObject({
      product: this.filterProduct(lineItem.product),
      quantity: lineItem.quantity,
      subtotal: lineItem.subtotal,
    }));
  }

  filterTransaction(transaction = {}) {
    return filterObject({
      ...transaction,
      orderId: transaction.orderId ? String(transaction.orderId) : undefined,
    }, [transactionProps]);
  }

  filterPage(page = {}) {
    return filterObject({
      ...page,
      breadcrumb: (page.breadcrumb && Array.isArray(page.breadcrumb)) ?
        page.breadcrumb.join('/') : page.breadcrumb,
    }, [pageProps]);
  }

  filterWebsite(website = {}) {
    return filterObject({
      ...website,
      regionId: website.regionId ? String(website.regionId) : undefined,
    }, [websiteProps]);
  }

  filterViewedPage(event) {
    const filtered = this.filterCommonEvent(event);
    return {
      ...filtered,
      page: this.filterPage(event.page),
    };
  }

  filterViewedProductDetail(event) {
    const filtered = this.filterCommonEvent(event);
    const product = this.filterProduct(event.product);
    return { ...filtered, product };
  }

  filterAddedProduct(event) {
    const filtered = this.filterCommonEvent(event);
    return {
      ...filtered,
      product: this.filterProduct(event.product),
      quantity: event.quantity || 1,
    };
  }

  filterRemovedProduct(event) {
    return this.filterAddedProduct(event);
  }

  filterAddedProductToWishlist(event) {
    return this.filterAddedProduct(event);
  }

  filterRemovedProductFromWishlist(event) {
    return this.filterAddedProduct(event);
  }

  filterViewedCheckoutStep(event) {
    const filtered = this.filterCommonEvent(event);
    return {
      ...filtered,
      step: event.step,
    };
  }

  filterCompeltedCheckoutStep(event) {
    return this.filterViewedCheckoutStep(event);
  }

  filterViewedCart(event) {
    const filtered = this.filterCommonEvent(event);
    const cart = filterObject(event.cart, [cartProps]);
    cart.lineItems = this.filterLineItems(getProp(event, 'cart.lineItems'));
    return {
      ...filtered,
      cart,
    };
  }

  filterCompletedTransaction(event) {
    const filtered = this.filterCommonEvent(event);
    const transaction = this.filterTransaction(event.transaction);
    transaction.lineItems = this.filterLineItems(getProp(event, 'transaction.lineItems'));
    return {
      ...filtered,
      transaction,
    };
  }

  filterRefundedTransaction(event) {
    return this.filterCompletedTransaction(event);
  }

  filterViewedProductListing(event) {
    const filtered = this.filterCommonEvent(event);
    const listing = this.filterListing(event.listing);
    return {
      ...filtered,
      listing,
    };
  }

  filterSearchedProducts(event) {
    return this.filterViewedProductListing(event);
  }

  filterViewedCampaign(event) {
    const filtered = this.filterCommonEvent(event);
    let campaigns;
    if (event.campaign) {
      campaigns = [event.campaign];
    } else if (event.campaigns) {
      campaigns = event.campaigns;
    }

    if (campaigns) {
      return {
        ...filtered,
        campaigns: fitlerObjectsArray(campaigns, [campaignProps]),
      };
    }

    return filtered;
  }

  filterClickedCampaign(event) {
    return this.filterViewedCampaign(event);
  }

  filterCommonEvent(event) {
    return cleanObject({
      name: event.name,
      category: event.category,
      label: event.label,
    });
  }
}

export default Filters;
<|endoftext|>


<commit_before>const propsToValidate = [
  'contact_name',
  'address_1',
  'postal_code',
  'city',
  'state',
  'country',
  'ship_date',
  'weight',
  'reference',
  'tnt',
];

const validate = {
  telephone: function (phone) {
    return phone.length < 10
      ? '1111111111'
      : phone.replace(/\W/g, ' ').replace(/\s+/g, '');
  },

  postal_code: function (zip) {
    return zip.length === 4
      ? `0${zip}`
      : zip;
  },

  tnt: function (tnt) {
    return +tnt;
  },
};

/**
 * Checks that all required properties are present and perfoms additional data
 * cleansing on a subset of those properties.
 * @param  {object} order The order object.
 * @return {object}       The validated and cleansed order object.
 */
function validateOrder(order) {
  // Remove any pre-existing errors (from previous execution)
  delete order.error;
  delete order.error_detail;

  // Validate each required property
  let orderErrors;
  propsToValidate.forEach(prop => {
    let error;
    if (!order[prop]) {
      error = true;
    }

    // Perform additional validation for the few fields that need it
    if (!error) {
      if (validate[prop]) order[prop] = validate[prop](order[prop]);
    } else {
      orderErrors = orderErrors instanceof Array
        ? orderErrors
        : [];
      orderErrors.push(` Missing ${prop}`);
    }
  });

  // Perform specific validation for telephone
  order.telephone = validate.telephone(order.telephone);

  // Regex for removing whitespace
  let trimWhiteSpace = /^[ \t]+|[ \t]+$/g;

  // Regex for removing commas and periods
  let findCommasAndPeriods = /[,.]/g

  // Remove commas and periods
  order.address_1 = order.address_1.replace(findCommasAndPeriods, '');

  // Check if address_1 contains address_2 components
  let addrTwoComponentsToRemove = /\s((apartment|apt|suite|ste|unit)\s|#).*/gi;
  let textToRemove = order.address_1.match(addrTwoComponentsToRemove);

  // If address_1 contains address_2 components, remove and reassign
  if (textToRemove) {
    order.address_1 = order.address_1.replace(textToRemove, '');
    order.address_2 = order.address_2
      ? order.address_2
      : textToRemove[0].replace(trimWhiteSpace, '');
  }

  // Valid strings for address_2
  let validAddrTwoComponents = /^((apartment|apt|suite|ste|unit)\s|#)\w{1,5}/gi;

  // Find if address_2 is valid
  let validAddressTwo = order.address_2.match(validAddrTwoComponents);

  // Create placeholder vars
  let specialDeliveryText = '', addressTwoString = '';

  if (validAddressTwo) {
    // Get the valid address string
    addressTwoString = validAddressTwo[0];
    // Check if there is anything after the valid string
    let extraText = order.address_2.split(addressTwoString)[1];

    if (extraText) {
      // Get the extra content
      specialDeliveryText = extraText.replace(trimWhiteSpace, '');
    }
  } else {
    // If address_2 is invalid, set it up to be the order.special_delivery_instructions instead
    specialDeliveryText = order.address_2;
  }

  // Check if there are special delivery instructions
  if (order.special_delivery_instructions) {
    // Prepend if there is specialDeliveryText and it is not the same as existing instructions
    if (specialDeliveryText && specialDeliveryText !== order.special_delivery_instructions) {
      order.special_delivery_instructions = `${specialDeliveryText} - ${order.special_delivery_instructions}`;
    }
  } else {
    // Otherwise replace the text
    order.special_delivery_instructions = specialDeliveryText;
  }

  // Replace address_2 with the correct string
  order.address_2 = addressTwoString;

  // Add any validation errors to the order
  if (orderErrors) {
    order.error = `Sales Order ${order.sales_order}: ${orderErrors}`;
  }

  return order;
}

module.exports = {
  validateOrder,
};
<commit_msg>Add address_2 recognition for numbers only<commit_after>const propsToValidate = [
  'contact_name',
  'address_1',
  'postal_code',
  'city',
  'state',
  'country',
  'ship_date',
  'weight',
  'reference',
  'tnt',
];

const validate = {
  telephone: function (phone) {
    return phone.length < 10
      ? '1111111111'
      : phone.replace(/\W/g, ' ').replace(/\s+/g, '');
  },

  postal_code: function (zip) {
    return zip.length === 4
      ? `0${zip}`
      : zip;
  },

  tnt: function (tnt) {
    return +tnt;
  },
};

/**
 * Checks that all required properties are present and perfoms additional data
 * cleansing on a subset of those properties.
 * @param  {object} order The order object.
 * @return {object}       The validated and cleansed order object.
 */
function validateOrder(order) {
  // Remove any pre-existing errors (from previous execution)
  delete order.error;
  delete order.error_detail;

  // Validate each required property
  let orderErrors;
  propsToValidate.forEach(prop => {
    let error;
    if (!order[prop]) {
      error = true;
    }

    // Perform additional validation for the few fields that need it
    if (!error) {
      if (validate[prop]) order[prop] = validate[prop](order[prop]);
    } else {
      orderErrors = orderErrors instanceof Array
        ? orderErrors
        : [];
      orderErrors.push(` Missing ${prop}`);
    }
  });

  // Perform specific validation for telephone
  order.telephone = validate.telephone(order.telephone);

  // Regex for removing whitespace
  let trimWhiteSpace = /^[ \t]+|[ \t]+$/g;

  // Remove commas and periods
  order.address_1 = order.address_1.replace(/[,.]/g, '');

  // Check if address_1 contains address_2 components
  let addrTwoComponentsToRemove = /\s((apartment|apt|suite|ste|unit)\s|#).*/gi;
  let textToRemove = order.address_1.match(addrTwoComponentsToRemove);

  // If address_1 contains address_2 components, remove and reassign
  if (textToRemove) {
    order.address_1 = order.address_1.replace(textToRemove, '');
    order.address_2 = order.address_2
      ? order.address_2
      : textToRemove[0].replace(trimWhiteSpace, '');
  }

  // Remove commas, periods, and the hash symbol
  order.address_2 = order.address_2.replace(/[,.#]/g, '');

  // Valid strings for address_2
  let validAddrTwoComponents = /^(((apartment|apt|suite|ste|unit)\s\w{1,5})|\d+\w{0,4})/gi;

  // Find if address_2 is valid
  let validAddressTwo = order.address_2.match(validAddrTwoComponents);

  // Create placeholder vars
  let specialDeliveryText = '', addressTwoString = '';

  if (validAddressTwo) {
    // Get the valid address string
    addressTwoString = validAddressTwo[0];
    // Check if there is anything after the valid string
    let extraText = order.address_2.split(addressTwoString)[1];

    if (extraText) {
      // Get the extra content
      specialDeliveryText = extraText.replace(trimWhiteSpace, '');
    }
  } else {
    // If address_2 is invalid, set it up to be the order.special_delivery_instructions instead
    specialDeliveryText = order.address_2;
  }

  // Check if there are special delivery instructions
  if (order.special_delivery_instructions) {
    // Prepend if there is specialDeliveryText and it is not the same as existing instructions
    if (specialDeliveryText && specialDeliveryText !== order.special_delivery_instructions) {
      order.special_delivery_instructions = `${specialDeliveryText} - ${order.special_delivery_instructions}`;
    }
  } else {
    // Otherwise replace the text
    order.special_delivery_instructions = specialDeliveryText;
  }

  // Replace address_2 with the correct string
  order.address_2 = addressTwoString;

  // Add any validation errors to the order
  if (orderErrors) {
    order.error = `Sales Order ${order.sales_order}: ${orderErrors}`;
  }

  return order;
}

module.exports = {
  validateOrder,
};
<|endoftext|>


<commit_before>
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

define(["app/dom", "app/i18n", "app/utils", "diff_match_patch"], function($, i18n, utils) {

    "use strict";

    var mode = "reading";
    var article = $("article");
    var original_article = utils.clean_html(article.innerHTML);
    var new_article = null;

    var original_button = $.htmlify("<button>" + i18n.translate("show-original") + "</button>");

    // make a diff_match_patch object once and for all
    var dmp = new diff_match_patch();

    var init = function(comment_field) {
        // let's curry!
        return function() {
            if (mode === "reading" && comment_field.innerHTML !== "") {
                mode = "commenting";
                article.setAttribute("contenteditable", true);
            }
            else if (mode === "commenting" && comment_field.innerHTML === ""
                                           && new_article === null) {
                mode = "reading";
                article.setAttribute("contenteditable", false);
            }
        };
    };

    var maybe_article_just_changed = function() {
        var current = utils.clean_html(article.innerHTML);
        if (current !== original_article) {
            new_article = current;
        }
        else {
            new_article = null;
        }
    };

    var cancel = function() {
        if (mode === "commenting") {
            article.setAttribute("contenteditable", false);
            if (new_article !== null) {
                article.innerHTML = original_article;
                new_article = null;
            }
            mode = "reading";
        }
    };

    var show = function(comment) {
        // let's curry!
        return function() {
            if (mode === "reading" || mode === "reading_modification") {
                var array = JSON.parse(utils.tags_from_text(comment.edit));
                var html = dmp.diff_prettyHtml(array);
                article.innerHTML = utils.tags_from_text(html);
		original_button.show();
                mode = "reading_modification";
            }
        };
    };

    var show_original = function() {
        if (mode === "reading_modification") {
            article.innerHTML = original_article;
            original_button.hide();
            mode = "reading";
        }
    };

    // define events
    original_button.on("click", show_original);
    article.on("keyup", maybe_article_just_changed);

    // add html elements
    original_button.hide();
    article.insertAfter(original_button);

    return {
        init: init,
        new_article: function() {
            var new_text = utils.tags_from_text(new_article);
            return JSON.stringify(dmp.diff_main(original_article,new_text));
        },
        cancel: cancel,
        show: show
    };
});

<commit_msg>gray out everything that is not modified text<commit_after>
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

define(["app/dom", "app/i18n", "app/utils", "diff_match_patch"], function($, i18n, utils) {

    "use strict";

    var mode = "reading";
    var article = $("article");
    var original_article = utils.clean_html(article.innerHTML);
    var new_article = null;

    var original_button = $.htmlify("<button>" + i18n.translate("show-original") + "</button>");

    // make a diff_match_patch object once and for all
    var dmp = new diff_match_patch();

    var init = function(comment_field) {
        // let's curry!
        return function() {
            if (mode === "reading" && comment_field.innerHTML !== "") {
                mode = "commenting";
                article.setAttribute("contenteditable", true);
            }
            else if (mode === "commenting" && comment_field.innerHTML === ""
                                           && new_article === null) {
                mode = "reading";
                article.setAttribute("contenteditable", false);
            }
        };
    };

    var maybe_article_just_changed = function() {
        var current = utils.clean_html(article.innerHTML);
        if (current !== original_article) {
            new_article = current;
        }
        else {
            new_article = null;
        }
    };

    var cancel = function() {
        if (mode === "commenting") {
            article.setAttribute("contenteditable", false);
            if (new_article !== null) {
                article.innerHTML = original_article;
                new_article = null;
            }
            mode = "reading";
        }
    };

    var show = function(comment) {
        // let's curry!
        return function() {
            if (mode === "reading" || mode === "reading_modification") {
                var array = JSON.parse(utils.tags_from_text(comment.edit));
                var html = dmp.diff_prettyHtml(array);
                article.innerHTML = utils.tags_from_text(html);

                // gray mask on everything other than current comment and article text
                $("body").style.background = "gray";
                article.style.background = "white";

		original_button.show();

                mode = "reading_modification";
            }
        };
    };

    var show_original = function() {
        if (mode === "reading_modification") {
            article.innerHTML = original_article;
            original_button.hide();
            mode = "reading";
        }
    };

    // define events
    original_button.on("click", show_original);
    article.on("keyup", maybe_article_just_changed);

    // add html elements
    original_button.hide();
    article.insertAfter(original_button);

    return {
        init: init,
        new_article: function() {
            var new_text = utils.tags_from_text(new_article);
            return JSON.stringify(dmp.diff_main(original_article,new_text));
        },
        cancel: cancel,
        show: show
    };
});

<|endoftext|>


<commit_before>var header =
  '\

\

Spec Home
\

\

Specification 0.1
\

\
  ';

var footer =
  '\

\

Copyright © 2015 Tomona Nanase
\
  ';

function _(format)
{
  var args = arguments;
  return format.replace(/\{(\d)\}/g, function(m, c) { return args[parseInt(c) + 1] });
}

function build_nav() {
  var nav = $('

');
  var navul = nav.children('ul.nav');

  $('.col-main>section').each(function() {
    var section = $('

').prepend(_('{1}', $(this).attr('id'), $(this).find(':header:first').text()));
    var subsection = $(_('.col-main section#{0} section', $(this).attr('id')));

    if (subsection.length > 0) {
      var subnavul = $('

');
      subsection.each(function() {
        $('

').prepend(_('{1}', $(this).attr('id'), $(this).find(':header:first').text()))
                      .appendTo(subnavul);
      });
      subnavul.appendTo(section);
    }
    section.appendTo(navul);
  });

  nav.prependTo('.col-navigator');

  // apply affix
  $('nav.affix-nav').affix({
    offset: {
      top: $('.container>.row:first').position().top,
      bottom: 50
    }
  }).on('affix.bs.affix', function() {
    $(this).css('top', 0);
  });

  // apply scrollspy
  $('body').scrollspy({ target: 'nav.affix-nav' });
}

function build_regexLink() {
  var service = 'http://regexper.com/#';
  $('a[regex]').each(function() {
    $(this).attr('href', service + encodeURIComponent($(this).attr('regex')))
           .attr('target', '_blank');
  });
}

function build_grammarAnchor() {
  $('a.grammar').each(function() {
    $(this).attr('name', $(this).text());
  });
}

$(function(){
  $('.container>.row:first').before(header).after(footer);
  $(".markdown").markdown();

  $('

').insertAfter('.col-main');
  $('.col-main').addClass('col-sm-9');
  $('.col-navigator').addClass('col-sm-3');

  build_nav();
  build_regexLink();
  build_grammarAnchor();
});<commit_msg>build_parmaLink関数を追加<commit_after>var header =
  '\

\

Spec Home
\

\

Specification 0.1
\

\
  ';

var footer =
  '\

\

Copyright © 2015 Tomona Nanase
\
  ';

function _(format)
{
  var args = arguments;
  return format.replace(/\{(\d)\}/g, function(m, c) { return args[parseInt(c) + 1] });
}

function build_nav() {
  var nav = $('

');
  var navul = nav.children('ul.nav');

  $('.col-main>section').each(function() {
    var section = $('

').prepend(_('{1}', $(this).attr('id'), $(this).find(':header:first').text()));
    var subsection = $(_('.col-main section#{0} section', $(this).attr('id')));

    if (subsection.length > 0) {
      var subnavul = $('

');
      subsection.each(function() {
        $('

').prepend(_('{1}', $(this).attr('id'), $(this).find(':header:first').text()))
                      .appendTo(subnavul);
      });
      subnavul.appendTo(section);
    }
    section.appendTo(navul);
  });

  nav.prependTo('.col-navigator');

  // apply affix
  $('nav.affix-nav').affix({
    offset: {
      top: $('.container>.row:first').position().top,
      bottom: 50
    }
  }).on('affix.bs.affix', function() {
    $(this).css('top', 0);
  });

  // apply scrollspy
  $('body').scrollspy({ target: 'nav.affix-nav' });
}

function build_regexLink() {
  var service = 'http://regexper.com/#';
  $('a[regex]').each(function() {
    $(this).attr('href', service + encodeURIComponent($(this).attr('regex')))
           .attr('target', '_blank');
  });
}

function build_grammarAnchor() {
  $('a.grammar').each(function() {
    $(this).attr('name', $(this).text());
  });
}

function build_parmaLink() {
  $(this).find(':header').each(function(){
    var id = $(this).parents('section:first').attr('id');

    if (typeof id === 'undefined')
      return;

    var parmalink = $(_('§', id));
    $(this).prepend(parmalink)
           .hover(function() { parmalink.css('opacity', 1); },
                  function() { parmalink.css('opacity', 0); });
  });
}

$(function(){
  $('.container>.row:first').before(header).after(footer);
  $(".markdown").markdown();

  $('

').insertAfter('.col-main');
  $('.col-main').addClass('col-sm-9');
  $('.col-navigator').addClass('col-sm-3');

  build_nav();
  build_regexLink();
  build_grammarAnchor();
  build_parmaLink();
});<|endoftext|>


<commit_before>/**
 * Created by loren on 05/11/2017.
 */
$(document).ready(function()
    {
        oggi=new Date();
        $("#giorno_fine").val(convertiInDataPhp(oggi));
        oggi.setDate(oggi.getDate()-30);
        $("#giorno_inizio").val(convertiInDataPhp(oggi));
    });

$("#via").click(function()
    {
    if($("#risultato")!==null) {$("#risultato").remove();}
    statistica= $("#scegli_statistica").val();
    inizio= $("#giorno_inizio").val();
    iniziojs=convertiInDataJs(inizio);
    fine= $("#giorno_fine").val();
    finejs=convertiInDataJs(fine);
    oggi= new Date();

    if(!inizio || !fine) alert ("Attenzione: inserire tutti i campi")
    else{
        if( iniziojs.getTime()>oggi.getTime() || finejs.getTime()>oggi.getTime()) alert("Attenzione: le date devono essere uguali o antecedenti ad oggi");
        else {
            if (iniziojs.getTime() >= finejs.getTime()) alert("Attenzione: la data di inizio deve essere precedente alla data di fine");
            else {
                var richiesta = {
                    controller: "CStatistiche",
                    metodo: statistica
                };

                var dati = {
                    dataInizio: inizio,
                    dataFine: fine
                };
                $.post(indirizzo,
                    JSON.stringify(
                        {
                            richiesta: richiesta,
                            dati: dati
                        }),
                    function (risultato) {
                        $(".result").html(risultato);
                        console.log(risultato);
                        visualizzaRis(risultato, richiesta.metodo, dati);
                    },
                    "json"
                );
            }
        }
    }

    function visualizzaRis(ris, metodo, giorni)
    {
        x=giorni.dataInizio.split("-");
        y=giorni.dataFine.split("-");

        dataInizio=x[2]+"-"+x[1]+"-"+x[0];
        dataFine=y[2]+"-"+y[1]+"-"+y[0];
        testo='
';
        if (metodo=="guadagno")
        {
            testo=testo+
            '
Dal '+dataInizio+' al '+dataFine+' il tuo ricavo è stato di:
'+
            '
'+ris+' €
';
        }
        if (metodo=="serviziApplicati")
        {
            /*testo=testo+
                '
 Lista dei servizi applicati dal '+dataInizio+' al '+dataFine+':
'+
                '
';
            for (i in ris)
            {   console.log(ris[i].servizio);
                testo=testo+'
 '+ris[i].servizio.nome+ ' è stato applicato il '+ris[i].percentuale+'% delle volte
'
            }
            testo=testo+'
';
            */
            testo=testo+'
 Lista dei servizi applicati dal '+dataInizio+' al '+dataFine+':
'+
                '

'
        }
        if (metodo=="maxSpesaUtente")
        {
            testo=testo+
                '
 Dal '+dataInizio+' al '+dataFine+" l'utente che ha speso di più è:
"+
                '
'+ris.nome+' '+ris.cognome+'
';
        }
        if (metodo=="appuntamentiMancati")
        {
            testo=testo+
                '
 Lista degli utenti che dal '+dataInizio+' al '+dataFine+' hanno saltato almeno un appuntamento :
'+
                '
';
                    for (i in ris)
                    {
                        testo=testo+'
 '+ris[i].utente.nome+ ' '+ris[i].utente.cognome+' è mancato '+ris[i].mancati+' volte
'
                    }
                    testo=testo+'
';
        }

        testo=testo+'
';
        $("#box").append(testo);
        if(metodo=="serviziApplicati") {creaPieChart(ris);}

    }

});

function convertiInDataPhp (dataJs)
{
    if(dataJs.getDate()<10) {giorno="0"+dataJs.getDate()} else {giorno=dataJs.getDate()}
    dataPhp=""+dataJs.getFullYear()+"-"+(dataJs.getMonth()+1)+"-"+giorno;
    return dataPhp;
}

function convertiInDataJs (dataPhp)
{
    var x =dataPhp.split("-");
    dataJs= new Date;
    dataJs.setFullYear(x[0]);
    dataJs.setMonth(x[1]-1);
    dataJs.setDate(x[2]);
    return dataJs;
}

function creaPieChart(dati) {

    percentuali= [];
    for (i in dati)
    {   console.log(dati[i].servizio);
        testo=testo+'
 '+dati[i].servizio.nome+ ' è stato applicato il '+dati[i].percentuale+'% delle volte
'

        percentuali.push({y: dati[i].percentuale, indexLabel: dati[i].servizio.nome});
        console.log(percentuali);
    }

        var chart = new CanvasJS.Chart("chartContainer",
            {   animationEnabled: true,
                theme: "theme2",
                data: [
                    {
                        type: "pie",
                        showInLegend: true,
                        toolTipContent: "#percent %",
                        yValueFormatString: "##0.00\"%\"",
                        legendText: "{indexLabel}",
                        dataPoints:
                            percentuali

                    }
                ]
            });
        chart.render();
}<commit_msg>Controllo in statistiche di risultati nulli<commit_after>/**
 * Created by loren on 05/11/2017.
 */
$(document).ready(function()
    {
        oggi=new Date();
        $("#giorno_fine").val(convertiInDataPhp(oggi));
        oggi.setDate(oggi.getDate()-30);
        $("#giorno_inizio").val(convertiInDataPhp(oggi));
    });

$("#via").click(function()
    {
    if($("#risultato")!==null) {$("#risultato").remove();}
    statistica= $("#scegli_statistica").val();
    inizio= $("#giorno_inizio").val();
    iniziojs=convertiInDataJs(inizio);
    fine= $("#giorno_fine").val();
    finejs=convertiInDataJs(fine);
    oggi= new Date();

    if(!inizio || !fine) alert ("Attenzione: inserire tutti i campi")
    else{
        if( iniziojs.getTime()>oggi.getTime() || finejs.getTime()>oggi.getTime()) alert("Attenzione: le date devono essere uguali o antecedenti ad oggi");
        else {
            if (iniziojs.getTime() >= finejs.getTime()) alert("Attenzione: la data di inizio deve essere precedente alla data di fine");
            else {
                var richiesta = {
                    controller: "CStatistiche",
                    metodo: statistica
                };

                var dati = {
                    dataInizio: inizio,
                    dataFine: fine
                };
                $.post(indirizzo,
                    JSON.stringify(
                        {
                            richiesta: richiesta,
                            dati: dati
                        }),
                    function (risultato) {
                        $(".result").html(risultato);
                        visualizzaRis(risultato, richiesta.metodo, dati);
                    },
                    "json"
                );
            }
        }
    }

    function visualizzaRis(ris, metodo, giorni)
    {
        x=giorni.dataInizio.split("-");
        y=giorni.dataFine.split("-");

        dataInizio=x[2]+"-"+x[1]+"-"+x[0];
        dataFine=y[2]+"-"+y[1]+"-"+y[0];
        testo='
';
        if (metodo=="guadagno")
        {
            testo=testo+
            '
Dal '+dataInizio+' al '+dataFine+' il tuo ricavo è stato di:
'+
            '
'+ris+' €
';
            testo=testo+'
';
            $("#box").append(testo);
        }
        else if (metodo=="serviziApplicati" && ris.length > 0)
        {

            testo=testo+'
 Lista dei servizi applicati dal '+dataInizio+' al '+dataFine+':
'+
                '

'
            testo=testo+'
';
            $("#box").append(testo);
            creaPieChart(ris);
        }
        else if (metodo=="maxSpesaUtente" && ris)
        {
            testo=testo+
                '
 Dal '+dataInizio+' al '+dataFine+" l'utente che ha speso di più è:
"+
                '
'+ris.nome+' '+ris.cognome+'
';
            testo=testo+'
';
            $("#box").append(testo);
        }
        else if (metodo=="appuntamentiMancati" && ris.length > 0)
        {
            testo=testo+
                '
 Lista degli utenti che dal '+dataInizio+' al '+dataFine+' hanno saltato almeno un appuntamento :
'+
                '
';
                    for (i in ris)
                    {
                        testo=testo+'
 '+ris[i].utente.nome+ ' '+ris[i].utente.cognome+': '+ris[i].mancati+'
'
                    }
                    testo=testo+'
';
            testo=testo+'
';
            $("#box").append(testo);
        }
        else alert("Non c'è alcun risultato relativo all'intervallo scelto");

    }

});

function convertiInDataPhp (dataJs)
{
    if(dataJs.getDate()<10) {giorno="0"+dataJs.getDate()} else {giorno=dataJs.getDate()}
    dataPhp=""+dataJs.getFullYear()+"-"+(dataJs.getMonth()+1)+"-"+giorno;
    return dataPhp;
}

function convertiInDataJs (dataPhp)
{
    var x =dataPhp.split("-");
    dataJs= new Date;
    dataJs.setFullYear(x[0]);
    dataJs.setMonth(x[1]-1);
    dataJs.setDate(x[2]);
    return dataJs;
}

function creaPieChart(dati) {

    percentuali= [];
    for (i in dati)
    {
        testo=testo+'
 '+dati[i].servizio.nome+ ' è stato applicato il '+dati[i].percentuale+'% delle volte
'

        percentuali.push({y: dati[i].percentuale, indexLabel: dati[i].servizio.nome});
    }

        var chart = new CanvasJS.Chart("chartContainer",
            {   animationEnabled: true,
                theme: "theme2",
                data: [
                    {
                        type: "pie",
                        showInLegend: true,
                        toolTipContent: "#percent %",
                        yValueFormatString: "##0.00\"%\"",
                        legendText: "{indexLabel}",
                        dataPoints: percentuali
                    }
                ]
            });
        chart.render();
}<|endoftext|>


<commit_before><commit_msg>Don't modify options hash, use local variable for showingSharing<commit_after><|endoftext|>


<commit_before>import React, { Component } from 'react'
import { ThemeProvider } from 'styled-components'
import theme from './Theme'
import Header from './components/Header';
import Footer from './components/Footer';
import Demo from './components/Demo';
import { Flex, Box } from 'grid-styled'
import { Div, Main, H3, P, Pre, Code, A } from 'styled-system-html'

class App extends Component {
  render() {
    return (

        <ThemeProvider theme={theme}>

Usage

npm i styled-system-html

              <Flex flexWrap="wrap" pb={[3,3,3,4]}>
                <Box width={[1,1,1,1/2]} pr={[0,0,0,4]}>

Create a theme with settings for colors, typography and spacing.

{`const theme = {
  colors : {'primary':'#071'},
  space : [0,4,8,16,32,64,128]
}`}

                </Box>
                <Box width={[1,1,1,1/2]} pl={[0,0,0,4]}>

Apply your theme to the element components.

{`<H2 pb={2} color="primary">Hello</H2>`}

For more info, see Styled System by Brent Jackson.

                </Box>
              </Flex>

Live Code Example

              <Demo />

        </ThemeProvider>

    )
  }
}

export default App
<commit_msg>replace grid-styled in docs with styled-system<commit_after>import React, { Component } from 'react'
import { ThemeProvider } from 'styled-components'
import theme from './Theme'
import Header from './components/Header';
import Footer from './components/Footer';
import Demo from './components/Demo';
import { Div, Main, H3, P, Pre, Code, A } from 'styled-system-html'

class App extends Component {
  render() {
    return (

        <ThemeProvider theme={theme}>

Usage

npm i styled-system-html

Create a theme with settings for colors, typography and spacing.

{`const theme = {
  colors : {'primary':'#071'},
  space : [0,4,8,16,32,64,128]
}`}

Apply your theme to the element components.

{`<H2 pb={2} color="primary">Hello</H2>`}

For more info, see Styled System by Brent Jackson.

Live Code Example

              <Demo />

        </ThemeProvider>

    )
  }
}

export default App
<|endoftext|>


<commit_before>/*global describe,before,it,cy,Cypress */

describe('Journey', function () {

  before(function () {
    cy.clearIndexDb()
    cy.unregisterServiceWorkers()
  })

  it('should all work fine', function () {
    cy.visit('/')

    shouldBeAbleToAddTrays(Cypress.env('TRAY_URL'), Cypress.env('TRAY_USERNAME'), Cypress.env('TRAY_PASSWORD'))
    shouldBeAbleToChangeMessages()
    shouldBeAbleToChangeSettings()
  })

  function shouldBeAbleToAddTrays(trayUrl, username, password) {
    cy.location('pathname').should('include', 'tracking')

    cy.locate('add-tray-url').type(trayUrl)
    if (username && password) {
      cy.locate('add-tray-username').type(username)
      cy.locate('add-tray-password').type(password)
    }
    cy.locate('add-tray').click()

    cy.locate('tray').should('exist')
    cy.locate('container-sub-title').should('have.text', trayUrl)
    cy.locate('exclude-all').click()
    cy.locate('include-all').click()
    cy.locate('tab-settings').click()
    cy.locate('generate-random').click()
    cy.locate('tray-name').clear().type('renamed tray').blur()
    cy.locate('container-title').should('have.text', 'renamed tray')
    cy.locate('tab-projects').click()
    cy.locate('available-projects-list').contains('failure building project')
    cy.locate('available-projects-list').contains('failure sleeping project')
    cy.locate('available-projects-list').contains('success building project')
    cy.locate('available-projects-list').contains('success sleeping project')
  }

  function shouldBeAbleToChangeMessages() {
    cy.locate('menu-success').click()
    cy.location('pathname').should('include', 'success')
    cy.locate('message').type('some message')
    cy.locate('add-message').click()
    cy.locate('success-message').contains('=(^.^)=')
    cy.locate('success-message').contains('some message')

    cy.locate('message')
      .type('https://raw.githubusercontent.com/build-canaries/nevergreen/master/doc/screenshot.png')
    cy.locate('add-message').click()
    cy.locate('success-image').should('be.visible')
  }

  function shouldBeAbleToChangeSettings() {
    cy.locate('menu-settings').click()
    cy.location('pathname').should('include', 'settings')

    cy.locate('play-sounds').click()
    cy.locate('refresh-time').select('60')
    cy.locate('click-to-show-menu').click()

    cy.locate('show-tray-names').check()
    cy.locate('show-build-times').check()
    cy.locate('show-broken-build-times').check()
    cy.locate('show-build-labels').check()
    cy.locate('max-projects-to-show').select('6')
    cy.locate('build-label').should('exist')
    cy.locate('tray-name').should('exist')
    cy.locate('duration').should('exist') // TODO: building vs broken time

    cy.locate('show-tray-names').uncheck()
    cy.locate('show-build-times').uncheck()
    cy.locate('show-broken-build-times').uncheck()
    cy.locate('show-build-labels').uncheck()
    cy.locate('max-projects-to-show').select('30')
    cy.locate('build-label').should('not.exist')
    cy.locate('tray-name').should('not.exist')
    cy.locate('duration').should('not.exist')
  }
})
<commit_msg>[#162] Feature parity with clojure functional tests<commit_after>/*global describe,before,it,cy,Cypress */

describe('Journey', function () {

  before(function () {
    cy.clearIndexDb()
    cy.unregisterServiceWorkers()
  })

  it('should all work fine', function () {
    cy.visit('/')

    shouldBeAbleToAddTrays(Cypress.env('TRAY_URL'), Cypress.env('TRAY_USERNAME'), Cypress.env('TRAY_PASSWORD'))
    shouldBeAbleToChangeMessages()
    shouldBeAbleToChangeSettings()
    shouldBeAbleToExportAndImportConfig()
    shouldMonitor()
  })

  function shouldBeAbleToAddTrays(trayUrl, username, password) {
    cy.location('pathname').should('include', 'tracking')

    cy.locate('add-tray-url').type(trayUrl)
    if (username && password) {
      cy.locate('add-tray-username').type(username)
      cy.locate('add-tray-password').type(password)
    }
    cy.locate('add-tray').click()

    cy.locate('tray').should('exist')
    cy.locate('container-sub-title').should('have.text', trayUrl)
    cy.locate('exclude-all').click()
    cy.locate('include-all').click()
    cy.locate('tab-settings').click()
    cy.locate('generate-random').click()
    cy.locate('tray-name').clear().type('renamed tray').blur()
    cy.locate('container-title').should('have.text', 'renamed tray')
    cy.locate('tab-projects').click()
    cy.locate('available-projects-list').contains('failure building project')
    cy.locate('available-projects-list').contains('failure sleeping project')
    cy.locate('available-projects-list').contains('success building project')
    cy.locate('available-projects-list').contains('success sleeping project')
  }

  function shouldBeAbleToChangeMessages() {
    cy.locate('menu-success').click()
    cy.location('pathname').should('include', 'success')
    cy.locate('message').type('some message')
    cy.locate('add-message').click()
    cy.locate('success-message').contains('=(^.^)=')
    cy.locate('success-message').contains('some message')

    cy.locate('message')
      .type('https://raw.githubusercontent.com/build-canaries/nevergreen/master/doc/screenshot.png')
    cy.locate('add-message').click()
    cy.locate('success-image').should('be.visible')
  }

  function shouldBeAbleToChangeSettings() {
    cy.locate('menu-settings').click()
    cy.location('pathname').should('include', 'settings')

    cy.locate('play-sounds').click()
    cy.locate('refresh-time').select('60')
    cy.locate('click-to-show-menu').click()

    cy.locate('show-tray-names').check()
    cy.locate('show-build-times').check()
    cy.locate('show-broken-build-times').check()
    cy.locate('show-build-labels').check()
    cy.locate('max-projects-to-show').select('6')
    cy.locate('build-label').should('exist')
    cy.locate('tray-name').should('exist')
    cy.locate('duration').should('exist') // TODO: building vs broken time

    cy.locate('show-tray-names').uncheck()
    cy.locate('show-build-times').uncheck()
    cy.locate('show-broken-build-times').uncheck()
    cy.locate('show-build-labels').uncheck()
    cy.locate('max-projects-to-show').select('30')
    cy.locate('build-label').should('not.exist')
    cy.locate('tray-name').should('not.exist')
    cy.locate('duration').should('not.exist')
  }

  function shouldBeAbleToExportAndImportConfig() {
    cy.locate('menu-backup').click()
    cy.location('pathname').should('include', 'backup')

    cy.locate('import-data').type('something invalid')
    cy.locate('import').click()
    cy.locate('error-messages').should('exist')

    cy.get('#export-data').then((textarea) => {
      cy.locate('import-data').invoke('val', textarea.val()) // not using type() for speed reasons
      cy.locate('import-data').type(' ') // trigger react updates
      cy.locate('import').click()
    })
    cy.locate('info-messages').should('exist')
  }

  function shouldMonitor() {
    cy.locate('menu-monitor').click()
    cy.location('pathname').should('include', 'monitor')

    cy.locate('interesting-project').contains('success building project').should('exist')
    cy.locate('interesting-project').contains('failure sleeping project').should('exist')
    cy.locate('interesting-project').contains('failure building project').should('exist')
    cy.locate('interesting-project').contains('success-sleeping-project').should('not.exist')
  }
})
<|endoftext|>


<commit_before>const pth    = require('path');
const Struct = require('./lib/Struct/Struct');

PairgenConfig = (function() {
  const _ = new Struct('id');
  const M = _.Modifiers;
  function PairgenConfig(obj) {
    _.construct(this, obj, {seal: true});
  }

  _.defineStruct(PairgenConfig, {
    is_worker: {
      modifier   : M.boolean,
      _default   : false,
      enumerable : false,
      immutable  : true
    },

    path : {
      required   : true,
      modifier   : M.file.bind({normalize : true}),
      enumerable : true,
      immutable  : true
    },

    rangebed : {
      modifier   : M.some(M.isNull, M.file.bind({normalize : true})),
      enumerable : true,
      immutable  : true
    },

    name : {
      modifier : M.string.quiet.bind({min: 1, max: 20}),
      defaultFunc : function() {
        return pth.basename(_(this).path);
      },
      enumerable: true,
      immutable: true
    },

    tlen : {
      modifier: M.integer.quiet,
      _default: 400,
      enumerable: true,
      immutable: true
    },

    readlen : {
      modifier: M.integer.bind({min: 10, max: 10000}).quiet,
      _default: 100,
      enumerable: true,
      immutable: true
    },

    dev : {
      modifier: M.number.bind({min: 0}).quiet,
      _default: 50,
      enumerable: true,
      immutable: true
    },

    depth : {
      modifier: M.number.bind({min: 0.01, max: 10000}).quiet,
      _default: 40,
      enumerable: true,
      immutable: true
    },

    ranges : {
      modifier: M.array.quiet,
      _default: [],
      enumerable: true,
      immutable: true
    },

    save_dir : {
      modifier: M.dir.bind({normalize: true}).quiet,
      _default: process.cwd(),
      enumerable: true,
      immutable: true
    },

    tmp_dir : {
      get: function() {
        if (! _(this).tmp_dir) {
          if (this.is_worker) return undefined;
          const save_dir = this.save_dir;
          var tmp = save_dir + '/.pairgen' + process.pid;
          while (_.Modifiers.dir.quiet(tmp)) {
            tmp += '.' + Math.random();
          }
          _(this).tmp_dir = tmp;
        }
        return _(this).tmp_dir;
      },

      set: function(v) {
        if (this.is_worker) {
          _(this).tmp_dir = _.Modifiers.dir(v);
        }
      },
      enumerable: false,
      required  : true,
      immutable: true
    },

    parallel : {
      modifier: M.integer.bind({min: 1, max: 100}).quiet,
      _default: 1,
      enumerable: true,
      immutable: true
    },

    pair_id : {
      modifier: function(v) {
        /* pair identifier */
        var left_id, right_id;
        if (v instanceof Array && v.length == 2) {
          return v;
        }

        switch (v) {
          case 'n':
          default:
            left_id  = '';
            right_id = '';
            break;
          case 'A':
          case 'B':
            left_id  = '_A';
            right_id = '_B';
            break;
          case '1':
          case '2':
          case  1 :
          case  2 :
            left_id  = '_1';
            right_id = '_2';
            break;
          case 'F':
          case 'R':
            left_id  = '_F';
            right_id = '_R';
            break;
          case 'F3':
          case 'R3':
            left_id  = '_F3';
            right_id = '_R3';
            break;
        }
        return [left_id, right_id];
      },
      _default: ['', ''],
      enumerable: true,
      immutable: true,
    },

    para_id : {
      modifier: M.integer,
      enumerable: true,
      immutable: true
    },

    callback : {
      modifier: M.func,
      _default: function(pairgen) {
        return {};
      },
      enumerable: true,
      immutable: true
    },

    modify_seq : {
      modifier: M.func,
      _default: function(seq, len) {
        return seq.slice(0, len);
      },
      enumerable: true,
      immutable: true
    },

    modify_qual : {
      modifier: M.func,
      _default: function(qual, seq) {
        return qual;
      },
      enumerable: true,
      immutable: true
    },

    get_fragment_id : {
      modifier: M.func,
      _default: function(rname, start, end, depth, pos, tlen,para_id, parallel,i, till) {
        return [
          'PAIRGEN',
          rname + ':' + start + '-' + end + ':' + depth,
          'Po' + pos + '-' + (pos + tlen -1) + ':' + tlen,
          'Pa' + (para_id + 1) + ':' + parallel,
          'It' + i + ':' + till
        ].join('_');
      },
      enumerable: true,
      immutable: true
    },

    p5 : {
      modifier   : M.string.quiet.bind({min : 10}),
      _default   : 'AATGATACGGCGACCACCGAGATCTACACTCTTTCCCTACACGACGCTCTTCCGATCT', // 5' -> 3'
      enumerable : true,
      immutable  : true
    },

    p7 : {
      modifier   : M.string.quiet.bind({min : 10}),
      _default   : 'ACACTCTTTCCCTACACGACGCTCTTCCGATCT', // 5' -> 3'
      enumerable : true,
      immutable  : true
    },

    adapter1 : {
      modifier   : M.string.quiet.bind({min : 10}),
      _default   : 'GATCGGAAGAGCTCGTATGCCGTCTTCTGCTTG', // 5' -> 3'
      enumerable : true,
      immutable  : true
    },

    adapter2 : {
      modifier   : M.string.quiet.bind({min : 10}),
      _default   : 'ACACTCTTTCCCTACACGACGCTCTTCCGATCT', // 5' -> 3'
      enumerable : true,
      immutable  : true
    }
  });
  return PairgenConfig;
})();

function test() {
  console.log(PairgenConfig.getDefault('depth'));
  var config = new PairgenConfig({path: "pairgen.js"});
  console.log(config.toObject());
  try {
    config.depth = "ABC";
  }
  catch (e) {
    console.log(e.message);
  }
}

if (process.argv[1] == __filename) { test(); }
module.exports = PairgenConfig;
<commit_msg>changed adapter sequences<commit_after>const pth    = require('path');
const Struct = require('./lib/Struct/Struct');

PairgenConfig = (function() {
  const _ = new Struct('id');
  const M = _.Modifiers;
  function PairgenConfig(obj) {
    _.construct(this, obj, {seal: true});
  }

  _.defineStruct(PairgenConfig, {
    is_worker: {
      modifier   : M.boolean,
      _default   : false,
      enumerable : false,
      immutable  : true
    },

    path : {
      required   : true,
      modifier   : M.file.bind({normalize : true}),
      enumerable : true,
      immutable  : true
    },

    rangebed : {
      modifier   : M.some(M.isNull, M.file.bind({normalize : true})),
      enumerable : true,
      immutable  : true
    },

    name : {
      modifier : M.string.quiet.bind({min: 1, max: 20}),
      defaultFunc : function() {
        return pth.basename(_(this).path);
      },
      enumerable: true,
      immutable: true
    },

    tlen : {
      modifier: M.integer.quiet,
      _default: 400,
      enumerable: true,
      immutable: true
    },

    readlen : {
      modifier: M.integer.bind({min: 10, max: 10000}).quiet,
      _default: 100,
      enumerable: true,
      immutable: true
    },

    dev : {
      modifier: M.number.bind({min: 0}).quiet,
      _default: 50,
      enumerable: true,
      immutable: true
    },

    depth : {
      modifier: M.number.bind({min: 0.01, max: 10000}).quiet,
      _default: 40,
      enumerable: true,
      immutable: true
    },

    ranges : {
      modifier: M.array.quiet,
      _default: [],
      enumerable: true,
      immutable: true
    },

    save_dir : {
      modifier: M.dir.bind({normalize: true}).quiet,
      _default: process.cwd(),
      enumerable: true,
      immutable: true
    },

    tmp_dir : {
      get: function() {
        if (! _(this).tmp_dir) {
          if (this.is_worker) return undefined;
          const save_dir = this.save_dir;
          var tmp = save_dir + '/.pairgen' + process.pid;
          while (_.Modifiers.dir.quiet(tmp)) {
            tmp += '.' + Math.random();
          }
          _(this).tmp_dir = tmp;
        }
        return _(this).tmp_dir;
      },

      set: function(v) {
        if (this.is_worker) {
          _(this).tmp_dir = _.Modifiers.dir(v);
        }
      },
      enumerable: false,
      required  : true,
      immutable: true
    },

    parallel : {
      modifier: M.integer.bind({min: 1, max: 100}).quiet,
      _default: 1,
      enumerable: true,
      immutable: true
    },

    pair_id : {
      modifier: function(v) {
        /* pair identifier */
        var left_id, right_id;
        if (v instanceof Array && v.length == 2) {
          return v;
        }

        switch (v) {
          case 'n':
          default:
            left_id  = '';
            right_id = '';
            break;
          case 'A':
          case 'B':
            left_id  = '_A';
            right_id = '_B';
            break;
          case '1':
          case '2':
          case  1 :
          case  2 :
            left_id  = '_1';
            right_id = '_2';
            break;
          case 'F':
          case 'R':
            left_id  = '_F';
            right_id = '_R';
            break;
          case 'F3':
          case 'R3':
            left_id  = '_F3';
            right_id = '_R3';
            break;
        }
        return [left_id, right_id];
      },
      _default: ['', ''],
      enumerable: true,
      immutable: true,
    },

    para_id : {
      modifier: M.integer,
      enumerable: true,
      immutable: true
    },

    callback : {
      modifier: M.func,
      _default: function(pairgen) {
        return {};
      },
      enumerable: true,
      immutable: true
    },

    modify_seq : {
      modifier: M.func,
      _default: function(seq, len) {
        return seq.slice(0, len);
      },
      enumerable: true,
      immutable: true
    },

    modify_qual : {
      modifier: M.func,
      _default: function(qual, seq) {
        return qual;
      },
      enumerable: true,
      immutable: true
    },

    get_fragment_id : {
      modifier: M.func,
      _default: function(rname, start, end, depth, pos, tlen,para_id, parallel,i, till) {
        return [
          'PAIRGEN',
          rname + ':' + start + '-' + end + ':' + depth,
          'Po' + pos + '-' + (pos + tlen -1) + ':' + tlen,
          'Pa' + (para_id + 1) + ':' + parallel,
          'It' + i + ':' + till
        ].join('_');
      },
      enumerable: true,
      immutable: true
    },

    p5 : {
      modifier   : M.string.quiet.bind({min : 10}),
      _default   : 'GATCGGAAGAGCGGTTCAGCAGGAATGCCGAG', // 5' -> 3'
      enumerable : true,
      immutable  : true
    },

    p7 : {
      modifier   : M.string.quiet.bind({min : 10}),
      _default   : 'ACACTCTTTCCCTACACGACGCTCTTCCGATCT', // 5' -> 3'
      enumerable : true,
      immutable  : true
    },

    adapter1 : {
      modifier   : M.string.quiet.bind({min : 10}),
      _default   : 'AATGATACGGCGACCACCGAGATCTACACTCTTTCCCTACACGACGCTCTTCCGATCT', // 5' -> 3'
      enumerable : true,
      immutable  : true
    },

    adapter2 : {
      modifier   : M.string.quiet.bind({min : 10}),
      _default   : 'CAAGCAGAAGACGGCATACGAGATCGGTCTCGGCATTCCTGCTGAACCGCTCTTCCGATCT', // 5' -> 3'
      enumerable : true,
      immutable  : true
    }
  });
  return PairgenConfig;
})();

function test() {
  console.log(PairgenConfig.getDefault('depth'));
  var config = new PairgenConfig({path: "pairgen.js"});
  console.log(config.toObject());
  try {
    config.depth = "ABC";
  }
  catch (e) {
    console.log(e.message);
  }
}

if (process.argv[1] == __filename) { test(); }
module.exports = PairgenConfig;
<|endoftext|>


<commit_before>module.exports = {

//---------------------------------------------------------------------
// Action Name
//
// This is the name of the action displayed in the editor.
//---------------------------------------------------------------------

name: "Create Animated Emoji",

//---------------------------------------------------------------------
// Action Section
//
// This is the section the action will fall into.
//---------------------------------------------------------------------

section: "Emoji Control",

//---------------------------------------------------------------------
// Action Subtitle
//
// This function generates the subtitle displayed next to the name.
//---------------------------------------------------------------------

subtitle: function(data) {
	return `${data.emojiName}`;
},

//---------------------------------------------------------------------
	 // DBM Mods Manager Variables (Optional but nice to have!)
	 //
	 // These are variables that DBM Mods Manager uses to show information
	 // about the mods for people to see in the list.
	 //---------------------------------------------------------------------

	 // Who made the mod (If not set, defaults to "DBM Mods")
	 author: "MrGold",

	 // The version of the mod (Defaults to 1.0.0)
	 version: "1.9.2", //Added in 1.9.2

	 // A short description to show on the mod line for this mod (Must be on a single line)
	 short_description: "Creates an Animated Emoji",

	 // If it depends on any other mods by name, ex: WrexMODS if the mod uses something from WrexMods

	 //---------------------------------------------------------------------

//---------------------------------------------------------------------
// Action Storage Function
//
// Stores the relevant variable info for the editor.
//---------------------------------------------------------------------

variableStorage: function(data, varType) {
	const type = parseInt(data.storage2);
	if(type !== varType) return;
	return ([data.varName2, 'Animated Emoji']);
},

//---------------------------------------------------------------------
// Action Fields
//
// These are the fields for the action. These fields are customized
// by creating elements with corresponding IDs in the HTML. These
// are also the names of the fields stored in the action's JSON data.
//---------------------------------------------------------------------

fields: ["emojiName", "storage", "varName", "storage2", "varName2"],

//---------------------------------------------------------------------
// Command HTML
//
// This function returns a string containing the HTML used for
// editting actions.
//
// The "isEvent" parameter will be true if this action is being used
// for an event. Due to their nature, events lack certain information,
// so edit the HTML to reflect this.
//
// The "data" parameter stores constants for select elements to use.
// Each is an array: index 0 for commands, index 1 for events.
// The names are: sendTargets, members, roles, channels,
//                messages, servers, variables
//---------------------------------------------------------------------

html: function(isEvent, data) {
	return `

        Mod Info:

	    Created by MrGold

	Animated Emoji Name:

	<input id="emojiName" class="round" type="text">

		Source GIF:

		<select id="storage" class="round" onchange="glob.refreshVariableList(this)">
			${data.variables[1]}
		</select>

		Variable Name:

		<input id="varName" class="round" type="text" list="variableList">

		Store In:

		<select id="storage2" class="round" onchange="glob.onChange1(this)">
			${data.variables[0]}
		</select>

		Variable Name:

		<input id="varName2" class="round" type="text">

`
},

//---------------------------------------------------------------------
// Action Editor Init Code
//
// When the HTML is first applied to the action editor, this code
// is also run. This helps add modifications or setup reactionary
// functions for the DOM elements.
//---------------------------------------------------------------------

init: function() {
	const {glob, document} = this;

	glob.onChange1 = function(event) {
		const value = parseInt(event.value);
		const varNameInput = document.getElementById("varNameContainer2");
		if(value === 0) {
			varNameInput.style.display = "none";
		} else {
			varNameInput.style.display = null;
		}
	};

	glob.refreshVariableList(document.getElementById('storage'));
	glob.onChange1(document.getElementById('storage2'));
},

//---------------------------------------------------------------------
// Action Bot Function
//
// This is the function for the action within the Bot's Action class.
// Keep in mind event calls won't have access to the "msg" parameter,
// so be sure to provide checks for variable existance.
//---------------------------------------------------------------------

action: function(cache) {
	const data = cache.actions[cache.index];
	const server = cache.server;
	if(server && server.createEmoji) {
		const type = parseInt(data.storage);
		const varName = this.evalMessage(data.varName, cache);
		const gif = this.getVariable(type, varName, cache);
		const name = this.evalMessage(data.emojiName, cache);
		server.createEmoji(gif, name).then(function(emoji) {
			const varName2 = this.evalMessage(data.varName2, cache);
			const storage = parseInt(data.storage2);
			this.storeValue(emoji, storage, varName2, cache);
			this.callNextAction(cache);
		}.bind(this)).catch(this.displayError.bind(this, data, cache));
	} else {
		this.callNextAction(cache);
	}
},

//---------------------------------------------------------------------
// Action Bot Mod
//
// Upon initialization of the bot, this code is run. Using the bot's
// DBM namespace, one can add/modify existing functions if necessary.
// In order to reduce conflictions between mods, be sure to alias
// functions you wish to overwrite.
//---------------------------------------------------------------------

mod: function(DBM) {
}

}; // End of module<commit_msg>Fixed version number<commit_after>module.exports = {

//---------------------------------------------------------------------
// Action Name
//
// This is the name of the action displayed in the editor.
//---------------------------------------------------------------------

name: "Create Animated Emoji",

//---------------------------------------------------------------------
// Action Section
//
// This is the section the action will fall into.
//---------------------------------------------------------------------

section: "Emoji Control",

//---------------------------------------------------------------------
// Action Subtitle
//
// This function generates the subtitle displayed next to the name.
//---------------------------------------------------------------------

subtitle: function(data) {
	return `${data.emojiName}`;
},

//---------------------------------------------------------------------
	 // DBM Mods Manager Variables (Optional but nice to have!)
	 //
	 // These are variables that DBM Mods Manager uses to show information
	 // about the mods for people to see in the list.
	 //---------------------------------------------------------------------

	 // Who made the mod (If not set, defaults to "DBM Mods")
	 author: "MrGold",

	 // The version of the mod (Defaults to 1.0.0)
	 version: "1.9.4", //Added in 1.9.4

	 // A short description to show on the mod line for this mod (Must be on a single line)
	 short_description: "Creates an Animated Emoji",

	 // If it depends on any other mods by name, ex: WrexMODS if the mod uses something from WrexMods

	 //---------------------------------------------------------------------

//---------------------------------------------------------------------
// Action Storage Function
//
// Stores the relevant variable info for the editor.
//---------------------------------------------------------------------

variableStorage: function(data, varType) {
	const type = parseInt(data.storage2);
	if(type !== varType) return;
	return ([data.varName2, 'Animated Emoji']);
},

//---------------------------------------------------------------------
// Action Fields
//
// These are the fields for the action. These fields are customized
// by creating elements with corresponding IDs in the HTML. These
// are also the names of the fields stored in the action's JSON data.
//---------------------------------------------------------------------

fields: ["emojiName", "storage", "varName", "storage2", "varName2"],

//---------------------------------------------------------------------
// Command HTML
//
// This function returns a string containing the HTML used for
// editting actions.
//
// The "isEvent" parameter will be true if this action is being used
// for an event. Due to their nature, events lack certain information,
// so edit the HTML to reflect this.
//
// The "data" parameter stores constants for select elements to use.
// Each is an array: index 0 for commands, index 1 for events.
// The names are: sendTargets, members, roles, channels,
//                messages, servers, variables
//---------------------------------------------------------------------

html: function(isEvent, data) {
	return `

        Mod Info:

	    Created by MrGold

	Animated Emoji Name:

	<input id="emojiName" class="round" type="text">

		Source GIF:

		<select id="storage" class="round" onchange="glob.refreshVariableList(this)">
			${data.variables[1]}
		</select>

		Variable Name:

		<input id="varName" class="round" type="text" list="variableList">

		Store In:

		<select id="storage2" class="round" onchange="glob.onChange1(this)">
			${data.variables[0]}
		</select>

		Variable Name:

		<input id="varName2" class="round" type="text">

`
},

//---------------------------------------------------------------------
// Action Editor Init Code
//
// When the HTML is first applied to the action editor, this code
// is also run. This helps add modifications or setup reactionary
// functions for the DOM elements.
//---------------------------------------------------------------------

init: function() {
	const {glob, document} = this;

	glob.onChange1 = function(event) {
		const value = parseInt(event.value);
		const varNameInput = document.getElementById("varNameContainer2");
		if(value === 0) {
			varNameInput.style.display = "none";
		} else {
			varNameInput.style.display = null;
		}
	};

	glob.refreshVariableList(document.getElementById('storage'));
	glob.onChange1(document.getElementById('storage2'));
},

//---------------------------------------------------------------------
// Action Bot Function
//
// This is the function for the action within the Bot's Action class.
// Keep in mind event calls won't have access to the "msg" parameter,
// so be sure to provide checks for variable existance.
//---------------------------------------------------------------------

action: function(cache) {
	const data = cache.actions[cache.index];
	const server = cache.server;
	if(server && server.createEmoji) {
		const type = parseInt(data.storage);
		const varName = this.evalMessage(data.varName, cache);
		const gif = this.getVariable(type, varName, cache);
		const name = this.evalMessage(data.emojiName, cache);
		server.createEmoji(gif, name).then(function(emoji) {
			const varName2 = this.evalMessage(data.varName2, cache);
			const storage = parseInt(data.storage2);
			this.storeValue(emoji, storage, varName2, cache);
			this.callNextAction(cache);
		}.bind(this)).catch(this.displayError.bind(this, data, cache));
	} else {
		this.callNextAction(cache);
	}
},

//---------------------------------------------------------------------
// Action Bot Mod
//
// Upon initialization of the bot, this code is run. Using the bot's
// DBM namespace, one can add/modify existing functions if necessary.
// In order to reduce conflictions between mods, be sure to alias
// functions you wish to overwrite.
//---------------------------------------------------------------------

mod: function(DBM) {
}

}; // End of module
<|endoftext|>