<commit_before>(function () {
    'use strict';
    var config,
        callbacks,
        divId = "cordova-plugin-map-mapDiv",
        pinLocation,
        initCenter,
        map,
        html,
        popupHtml;

    config = {
        'latitude': null,
        'longitude': null,
        'scale': 17,
        'bingMapKey': null
    };

    callbacks = {
        'confirmOnSuccess': function () {
        },
        'confirmOnError': function () {
        },
        'confirmOptions': {}
    };

    html = '<link rel="stylesheet" href="css/cordova-plugin-map.css" />';

    popupHtml = '

<button data-action="done"  class="cordova-plugin-map-nativePopUp__button">done</button><button data-action="cancel" class="cordova-plugin-map-nativePopUp__button">cancel</button>

';

    function appendVeapicoreJs() {
        var head = document.getElementsByTagName('head').item(0);
        var script = document.createElement('script');
        script.setAttribute('type', 'text/javascript');
        script.setAttribute('src', 'ms-appx:///Bing.Maps.JavaScript//js/veapicore.js');
        head.appendChild(script);
    }

    MSApp.execUnsafeLocalFunction(function () {
        document.head.insertAdjacentHTML('beforeend', html);
        appendVeapicoreJs();
    });

    function openPopup() {
        MSApp.execUnsafeLocalFunction(function () {
            document.body.insertAdjacentHTML('beforeend', popupHtml);
        });
        var popup = document.getElementById('cordova-plugin-map-popup');
        var done = popup.querySelector('button[data-action=done]');
        var cancel = popup.querySelector('button[data-action=cancel]');
        popup.classList.add('cordova-plugin-map-nativePopUp-open');
        window.addEventListener('resize', resizePopup, false);

        done.addEventListener('click', closePopup, false);
        cancel.addEventListener('click', cancelPopup, false);
    }

    function resizePopup() {
        deletePopup();
        confirmLocation(callbacks.confirmOnSuccess, callbacks.confirmOnError, callbacks.confirmOptions);
    }

    function closePopup() {
        callbacks.confirmOnSuccess({latitude: pinLocation.latitude, longitude: pinLocation.longitude});
        deletePopup();
    }

    function cancelPopup() {
        callbacks.confirmOnSuccess(null);
        deletePopup();
    }

    function deletePopup() {
        window.removeEventListener('resize', resizePopup, false);
        MSApp.execUnsafeLocalFunction(function () {
            var popup = document.getElementById("cordova-plugin-map-popup");
            popup.classList.remove('cordova-plugin-map-nativePopUp-open');
            popup.parentNode.removeChild(popup);
        });
    }

    map = function (options) {};

    map.setOptions = function (onSuccess, onError, options) {
        Object.keys(config).forEach(function(k) {
            if (options[k]) {
                config[k] = options[k];
            }
        });
    };

    map.confirmLocation = function (onSuccess, onError, options) {
        var initMap;

        //check to see if latitude is provided
        if (options && options.latitude) {
            config.latitude = options.latitude;
        } else if(!config.latitude) {
            onError("latitude must be provided");
        }
        //check to see longitude is provided
        if (options && options.longitude) {
            config.longitude = options.longitude;
        } else if(!config.longitude) {
            onError("longitude must be provided");
        }
        //check to see bingMapKey is available
        if (options && options.bingMapKey) {
            config.bingMapKey = options.bingMapKey;
        } else if (!config.bingMapKey) {
            onError("map key must be provided");
        }

        if (options && options.scale) {
            config.scale = options.scale;
        }

        callbacks.confirmOnSuccess = onSuccess;
        callbacks.confirmOnError = onError;
        callbacks.confirmOptions = options;

        openPopup();

        while (typeof Microsoft == 'undefined' || !Microsoft) {
            setTimeout('', 100);
        }

        initMap = function () {
            var bingMap, DisplayLoc;

            DisplayLoc = function (e) {
                if (e.targetType == 'pushpin') {
                    pinLocation = e.target.getLocation();
                }
            };

            if (!initCenter) {
                initCenter = new Microsoft.Maps.Location(config.latitude, config.longitude);
            }
            if (!pinLocation) {
                pinLocation = new Microsoft.Maps.Location(config.latitude, config.longitude);
            }

            var mapDiv = document.getElementById(divId);
            var rect = mapDiv.getBoundingClientRect();

            var mapOptions = {
                credentials: config.bingMapKey,
                center: pinLocation,
                zoom: config.scale,
                height: rect.height,
                width: rect.width
            };

            bingMap = new Microsoft.Maps.Map(mapDiv, mapOptions);

            // Add a pin to the center of the map
            var pin = new Microsoft.Maps.Pushpin(pinLocation, {draggable: true});

            // Add a handler to the pushpin drag
            Microsoft.Maps.Events.addHandler(pin, 'mouseup', DisplayLoc);

            bingMap.entities.push(pin);
        };

        Microsoft.Maps.loadModule('Microsoft.Maps.Map', {callback: initMap, culture: "en-us", homeRegion: "AU"});
    };

    navigator.map = map;

}());

cordova.commandProxy.add("MapPlugin", {
  setOptions: navigator.map.setOptions,
  confirmLocation: navigator.map.confirmLocation
});
<commit_msg>call error handler when the bing maps API is unavailable<commit_after>(function () {
    'use strict';
    var config,
        callbacks,
        divId = "cordova-plugin-map-mapDiv",
        pinLocation,
        initCenter,
        map,
        html,
        popupHtml;

    config = {
        'latitude': null,
        'longitude': null,
        'scale': 17,
        'bingMapKey': null
    };

    callbacks = {
        'confirmOnSuccess': function () {
        },
        'confirmOnError': function () {
        },
        'confirmOptions': {}
    };

    html = '<link rel="stylesheet" href="css/cordova-plugin-map.css" />';

    popupHtml = '

<button data-action="done"  class="cordova-plugin-map-nativePopUp__button">done</button><button data-action="cancel" class="cordova-plugin-map-nativePopUp__button">cancel</button>

';

    function appendVeapicoreJs() {
        var head = document.getElementsByTagName('head').item(0);
        var script = document.createElement('script');
        script.setAttribute('type', 'text/javascript');
        script.setAttribute('src', 'ms-appx:///Bing.Maps.JavaScript//js/veapicore.js');
        head.appendChild(script);
    }

    MSApp.execUnsafeLocalFunction(function () {
        document.head.insertAdjacentHTML('beforeend', html);
        appendVeapicoreJs();
    });

    function openPopup() {
        MSApp.execUnsafeLocalFunction(function () {
            document.body.insertAdjacentHTML('beforeend', popupHtml);
        });
        var popup = document.getElementById('cordova-plugin-map-popup');
        var done = popup.querySelector('button[data-action=done]');
        var cancel = popup.querySelector('button[data-action=cancel]');
        popup.classList.add('cordova-plugin-map-nativePopUp-open');
        window.addEventListener('resize', resizePopup, false);

        done.addEventListener('click', closePopup, false);
        cancel.addEventListener('click', cancelPopup, false);
    }

    function resizePopup() {
        deletePopup();
        confirmLocation(callbacks.confirmOnSuccess, callbacks.confirmOnError, callbacks.confirmOptions);
    }

    function closePopup() {
        callbacks.confirmOnSuccess({latitude: pinLocation.latitude, longitude: pinLocation.longitude});
        deletePopup();
    }

    function cancelPopup() {
        callbacks.confirmOnSuccess(null);
        deletePopup();
    }

    function deletePopup() {
        window.removeEventListener('resize', resizePopup, false);
        MSApp.execUnsafeLocalFunction(function () {
            var popup = document.getElementById("cordova-plugin-map-popup");
            popup.classList.remove('cordova-plugin-map-nativePopUp-open');
            popup.parentNode.removeChild(popup);
        });
    }

    map = function (options) {};

    map.setOptions = function (onSuccess, onError, options) {
        Object.keys(config).forEach(function(k) {
            if (options[k]) {
                config[k] = options[k];
            }
        });
    };

    map.confirmLocation = function (onSuccess, onError, options) {
        var initMap;

        //check to see if latitude is provided
        if (options && options.latitude) {
            config.latitude = options.latitude;
        } else if(!config.latitude) {
            onError("latitude must be provided");
        }
        //check to see longitude is provided
        if (options && options.longitude) {
            config.longitude = options.longitude;
        } else if(!config.longitude) {
            onError("longitude must be provided");
        }
        //check to see bingMapKey is available
        if (options && options.bingMapKey) {
            config.bingMapKey = options.bingMapKey;
        } else if (!config.bingMapKey) {
            onError("map key must be provided");
        }

        if (options && options.scale) {
            config.scale = options.scale;
        }

        callbacks.confirmOnSuccess = onSuccess;
        callbacks.confirmOnError = onError;
        callbacks.confirmOptions = options;

        if (typeof Microsoft === 'undefined' || !Microsoft) {
            onError('bing maps API unavailable');
            return;
        }

        openPopup();

        initMap = function () {
            var bingMap, DisplayLoc;

            DisplayLoc = function (e) {
                if (e.targetType == 'pushpin') {
                    pinLocation = e.target.getLocation();
                }
            };

            if (!initCenter) {
                initCenter = new Microsoft.Maps.Location(config.latitude, config.longitude);
            }
            if (!pinLocation) {
                pinLocation = new Microsoft.Maps.Location(config.latitude, config.longitude);
            }

            var mapDiv = document.getElementById(divId);
            var rect = mapDiv.getBoundingClientRect();

            var mapOptions = {
                credentials: config.bingMapKey,
                center: pinLocation,
                zoom: config.scale,
                height: rect.height,
                width: rect.width
            };

            bingMap = new Microsoft.Maps.Map(mapDiv, mapOptions);

            // Add a pin to the center of the map
            var pin = new Microsoft.Maps.Pushpin(pinLocation, {draggable: true});

            // Add a handler to the pushpin drag
            Microsoft.Maps.Events.addHandler(pin, 'mouseup', DisplayLoc);

            bingMap.entities.push(pin);
        };

        Microsoft.Maps.loadModule('Microsoft.Maps.Map', {callback: initMap, culture: "en-us", homeRegion: "AU"});
    };

    navigator.map = map;

}());

cordova.commandProxy.add("MapPlugin", {
  setOptions: navigator.map.setOptions,
  confirmLocation: navigator.map.confirmLocation
});
<|endoftext|>


<commit_before>(function(){

//----------------------------------------------------------------------------------------------------------------------
// Xflow.SamplerConfig
//----------------------------------------------------------------------------------------------------------------------

/**
 * @constructor
 */
Xflow.SamplerConfig = function(){
    this.minFilter = 0;
    this.magFilter = 0;
    this.mipFilter = 0;
    this.wrapS = 0;
    this.wrapT = 0;
    this.wrapU = 0;
    this.textureType = 0;
    this.colorR = 0;
    this.colorG = 0;
    this.colorB = 0;
    this.generateMipMap = 0;
};
Xflow.SamplerConfig.prototype.setDefaults = function() {
    // FIXME Generate this from the spec ?
    this.minFilter = WebGLRenderingContext.LINEAR;
    this.magFilter = WebGLRenderingContext.LINEAR;
    this.mipFilter = WebGLRenderingContext.NEAREST;
    this.wrapS = WebGLRenderingContext.CLAMP_TO_EDGE;
    this.wrapT = WebGLRenderingContext.CLAMP_TO_EDGE;
    this.wrapU = WebGLRenderingContext.CLAMP_TO_EDGE;
    this.textureType = WebGLRenderingContext.TEXTURE_2D;
    this.colorR = 0;
    this.colorG = 0;
    this.colorB = 0;
    this.generateMipMap = 0;
};
Xflow.SamplerConfig.prototype.set = function(other) {
    this.minFilter = other.minFilter;
    this.magFilter = other.magFilter;
    this.mipFilter = other.mipFilter;
    this.wrapS = other.wrapS;
    this.wrapT = other.wrapT;
    this.wrapU = other.wrapU;
    this.textureType = other.textureType;
    this.colorR = other.colorR;
    this.colorG = other.colorG;
    this.colorB = other.colorB;
    this.generateMipMap = other.generateMipMap;
};
var SamplerConfig = Xflow.SamplerConfig;

//----------------------------------------------------------------------------------------------------------------------
// Xflow.DataEntry
//----------------------------------------------------------------------------------------------------------------------

/**
 * @constructor
 * @param {Xflow.DATA_TYPE} type Type of DataEntry
 */
Xflow.DataEntry = function(type){
    this._type = type;
    this._listeners = [];
    this.userData = {};
};
var DataEntry = Xflow.DataEntry;

Object.defineProperty(DataEntry.prototype, "type", {
    /** @param {Xflow.DATA_TYPE} v */
    set: function(v){
        throw new Error("type is read-only");
    },
    /** @return {Xflow.DATA_TYPE} */
    get: function(){ return this._type; }
});

/**
 * @param {function(Xflow.DataEntry, Xflow.DATA_ENTRY_STATE)} callback
 */
DataEntry.prototype.addListener = function(callback){
    this._listeners.push(callback);
};

/**
 * @param {function(Xflow.DataEntry, Xflow.DATA_ENTRY_STATE)} callback
 */
DataEntry.prototype.removeListener = function(callback){
    Array.erase(this._listeners, callback);
};

DataEntry.prototype.notifyChanged = function(){
    notifyListeners(this, Xflow.DATA_ENTRY_STATE.CHANGED_VALUE);
}

//----------------------------------------------------------------------------------------------------------------------
// Xflow.BufferEntry
//----------------------------------------------------------------------------------------------------------------------

/**
 * @constructor
 * @extends {Xflow.DataEntry}
 * @param {Xflow.DATA_TYPE} type
 * @param {Object} value
 */
Xflow.BufferEntry = function(type, value){
    Xflow.DataEntry.call(this, type);
    this._value = value;
    notifyListeners(this, Xflow.DATA_ENTRY_STATE.CHANGED_NEW);
};
XML3D.createClass(Xflow.BufferEntry, Xflow.DataEntry);
var BufferEntry = Xflow.BufferEntry;

/** @param {Object} v */
BufferEntry.prototype.setValue = function(v){
    var newSize = (this._value ? this._value.length : 0) != (v ? v.length : 0);
    this._value = v;
    notifyListeners(this, newSize ? Xflow.DATA_ENTRY_STATE.CHANGE_SIZE : Xflow.DATA_ENTRY_STATE.CHANGED_VALUE);
}

/** @return {Object} */
BufferEntry.prototype.getValue = function(){
    return this._value;
};

/** @return {Object} */
BufferEntry.prototype.getLength = function(){
    return this._value ? this._value.length : 0;
};

BufferEntry.prototype.getTupleSize = function() {
    if (!this._tupleSize) {
        this._tupleSize = Xflow.DATA_TYPE_TUPLE_SIZE[this._type];
    }
    return this._tupleSize;
};

/**
 * @return {number}
 */
BufferEntry.prototype.getIterateCount = function(){
    return this.getLength() / this.getTupleSize();
};

BufferEntry.prototype.isEmpty = function(){
    return !this._value;
};

//----------------------------------------------------------------------------------------------------------------------
// Xflow.TextureEntry
//----------------------------------------------------------------------------------------------------------------------

function isLoading(image) {
    if (!image)
        return false;
    var nodeName = image.nodeName.toLowerCase();
    if (nodeName == 'img')
        return !image.complete;
    if (nodeName == 'canvas')
        return false;
    if (nodeName == 'video')
        return image.readyState == 0; // 0 == HAVE_NOTHING
    return false;
}

/**
 * @constructor
 * @param {Xflow.TextureEntry} textureEntry
 */
Xflow.ImageManipulator = function(textureEntry) {
    this._textureEntry = textureEntry;
    this._image = textureEntry.getImage();
    if (this._image) {
        this.width = this._image.width;
        this.height = this._image.height;
        if (this._image.nodeName.toLowerCase() === 'canvas') {
            this._canvas = this._image;
            this._copyImageToCtx = false;
        } else {
            this._canvas = null;
            this._copyImageToCtx = true;
        }
    } else {
        this.width = 0;
        this.height = 0;
        this._canvas = null;
    }
    this._context = null;
};
Xflow.ImageManipulator.prototype.isLoading = function() {
    return isLoading(this._image);
};
Xflow.ImageManipulator.prototype.detach = function() {
    this._textureEntry = null;
    // FIXME if _canvas is shared between _textureEntry and this object, it must to be cloned
};
Xflow.ImageManipulator.prototype.getCanvas = function() {
    if (!this._canvas) {
        this._canvas = document.createElement('canvas');
        this._canvas.width = this.width;
        this._canvas.height = this.height;
        this._canvas.complete = false; // for compatibility with img element
    }
    return this._canvas;
};
Xflow.ImageManipulator.prototype.getContext2D = function() {
    if (!this._context) {
        var canvas = this.getCanvas();
        this._context = canvas.getContext("2d");
        if (!this._context)
            throw new Error("Could not create 2D context.");
        if (this._copyImageToCtx) {
            // FIXME What to do with video element ?
            this._context.drawImage(this._image, 0, 0);
        }
    }
    return this._context;
};

function createPlaceholder(w, h) {
    var img = document.createElement('img');
    img.setAttribute('style', 'width:'+w+'px;height:'+h+'px;border:none;display:block');
    img.src = 'data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==';
    return img;
}

/** Call this function when image editing is finished.
 *
 */
Xflow.ImageManipulator.prototype.finish = function() {
    if (this._textureEntry && this._canvas) {
        if (this._canvas) {
            this._canvas.complete = true; // for compatibility with img element
            this._textureEntry._image = this._canvas;
            // FIXME Do we need to call notifyChanged here ? Arrays in DataEntry are not calling callbacks.
            this._textureEntry.notifyChanged();
        } else if (!this._image) {

            // FIXME Do we need to call notifyChanged here ? Arrays in DataEntry are not calling callbacks.
            this._textureEntry.notifyChanged();
        }
    }
}

/**
 * @constructor
 * @extends {Xflow.DataEntry}
 * @param {Object} image
 */
Xflow.TextureEntry = function(image){
    Xflow.DataEntry.call(this, Xflow.DATA_TYPE.TEXTURE);
    this._image = image;
    this._samplerConfig = new SamplerConfig();
    this._imageManipulator = null;
    notifyListeners(this, Xflow.DATA_ENTRY_STATE.CHANGED_NEW);
};
XML3D.createClass(Xflow.TextureEntry, Xflow.DataEntry);
var TextureEntry = Xflow.TextureEntry;

TextureEntry.prototype.isEmpty = function(){
    return !this._image;
};

TextureEntry.prototype.isLoading = function() {
    return isLoading(this._image);
};

/** @param {Object} v */
TextureEntry.prototype.setImage = function(v){
    this._image = v;
    if (this._imageManipulator) {
        this._imageManipulator.detach();
        this._imageManipulator = null;
    }
    notifyListeners(this, Xflow.DATA_ENTRY_STATE.CHANGED_VALUE);
}

/** @return {Object} */
TextureEntry.prototype.getImage = function(){
    return this._image;
}

/** @return {Object} */
TextureEntry.prototype.getImageManipulator = function() {
    if (!this._imageManipulator) {
        this._imageManipulator = new Xflow.ImageManipulator(this);
    }
    return this._imageManipulator;
}

    /** @return {Object} */
TextureEntry.prototype.getSamplerConfig = function(){
    return this._samplerConfig;
};

/** @return {number} */
TextureEntry.prototype.getLength = function(){
    return 1;
};

/** @return {number} */
TextureEntry.prototype.getIterateCount = function() {
    return 1;
};

//----------------------------------------------------------------------------------------------------------------------
// Xflow.DataChangeNotifier
//----------------------------------------------------------------------------------------------------------------------

Xflow.DataChangeNotifier = {
    _listeners: []
}
var DataChangeNotifier = Xflow.DataChangeNotifier;

/**
 * @param {function(Xflow.DataEntry, Xflow.DATA_ENTRY_STATE)} callback
 */
DataChangeNotifier.addListener = function(callback){
    this._listeners.push(callback);
};

/**
 * @param {function(Xflow.DataEntry, Xflow.DATA_ENTRY_STATE)} callback
 */
DataChangeNotifier.removeListener = function(callback){
    Array.erase(this._listeners, callback);
};

/**
 * @param {Xflow.DataEntry} dataEntry
 * @param {Xflow.DATA_ENTRY_STATE} notification
 */
function notifyListeners(dataEntry, notification){
    for(var i = 0; i < DataChangeNotifier._listeners.length; ++i){
        DataChangeNotifier._listeners[i](dataEntry, notification);
    }
    for(var i = 0; i < dataEntry._listeners.length; ++i){
        dataEntry._listeners[i].notify(dataEntry, notification);
    }
};
})();
<commit_msg>Added support for video frame processing to Xflow.<commit_after>(function(){

//----------------------------------------------------------------------------------------------------------------------
// Xflow.SamplerConfig
//----------------------------------------------------------------------------------------------------------------------

/**
 * @constructor
 */
Xflow.SamplerConfig = function(){
    this.minFilter = 0;
    this.magFilter = 0;
    this.mipFilter = 0;
    this.wrapS = 0;
    this.wrapT = 0;
    this.wrapU = 0;
    this.textureType = 0;
    this.colorR = 0;
    this.colorG = 0;
    this.colorB = 0;
    this.generateMipMap = 0;
};
Xflow.SamplerConfig.prototype.setDefaults = function() {
    // FIXME Generate this from the spec ?
    this.minFilter = WebGLRenderingContext.LINEAR;
    this.magFilter = WebGLRenderingContext.LINEAR;
    this.mipFilter = WebGLRenderingContext.NEAREST;
    this.wrapS = WebGLRenderingContext.CLAMP_TO_EDGE;
    this.wrapT = WebGLRenderingContext.CLAMP_TO_EDGE;
    this.wrapU = WebGLRenderingContext.CLAMP_TO_EDGE;
    this.textureType = WebGLRenderingContext.TEXTURE_2D;
    this.colorR = 0;
    this.colorG = 0;
    this.colorB = 0;
    this.generateMipMap = 0;
};
Xflow.SamplerConfig.prototype.set = function(other) {
    this.minFilter = other.minFilter;
    this.magFilter = other.magFilter;
    this.mipFilter = other.mipFilter;
    this.wrapS = other.wrapS;
    this.wrapT = other.wrapT;
    this.wrapU = other.wrapU;
    this.textureType = other.textureType;
    this.colorR = other.colorR;
    this.colorG = other.colorG;
    this.colorB = other.colorB;
    this.generateMipMap = other.generateMipMap;
};
var SamplerConfig = Xflow.SamplerConfig;

//----------------------------------------------------------------------------------------------------------------------
// Xflow.DataEntry
//----------------------------------------------------------------------------------------------------------------------

/**
 * @constructor
 * @param {Xflow.DATA_TYPE} type Type of DataEntry
 */
Xflow.DataEntry = function(type){
    this._type = type;
    this._listeners = [];
    this.userData = {};
};
var DataEntry = Xflow.DataEntry;

Object.defineProperty(DataEntry.prototype, "type", {
    /** @param {Xflow.DATA_TYPE} v */
    set: function(v){
        throw new Error("type is read-only");
    },
    /** @return {Xflow.DATA_TYPE} */
    get: function(){ return this._type; }
});

/**
 * @param {function(Xflow.DataEntry, Xflow.DATA_ENTRY_STATE)} callback
 */
DataEntry.prototype.addListener = function(callback){
    this._listeners.push(callback);
};

/**
 * @param {function(Xflow.DataEntry, Xflow.DATA_ENTRY_STATE)} callback
 */
DataEntry.prototype.removeListener = function(callback){
    Array.erase(this._listeners, callback);
};

DataEntry.prototype.notifyChanged = function(){
    notifyListeners(this, Xflow.DATA_ENTRY_STATE.CHANGED_VALUE);
}

//----------------------------------------------------------------------------------------------------------------------
// Xflow.BufferEntry
//----------------------------------------------------------------------------------------------------------------------

/**
 * @constructor
 * @extends {Xflow.DataEntry}
 * @param {Xflow.DATA_TYPE} type
 * @param {Object} value
 */
Xflow.BufferEntry = function(type, value){
    Xflow.DataEntry.call(this, type);
    this._value = value;
    notifyListeners(this, Xflow.DATA_ENTRY_STATE.CHANGED_NEW);
};
XML3D.createClass(Xflow.BufferEntry, Xflow.DataEntry);
var BufferEntry = Xflow.BufferEntry;

/** @param {Object} v */
BufferEntry.prototype.setValue = function(v){
    var newSize = (this._value ? this._value.length : 0) != (v ? v.length : 0);
    this._value = v;
    notifyListeners(this, newSize ? Xflow.DATA_ENTRY_STATE.CHANGE_SIZE : Xflow.DATA_ENTRY_STATE.CHANGED_VALUE);
}

/** @return {Object} */
BufferEntry.prototype.getValue = function(){
    return this._value;
};

/** @return {Object} */
BufferEntry.prototype.getLength = function(){
    return this._value ? this._value.length : 0;
};

BufferEntry.prototype.getTupleSize = function() {
    if (!this._tupleSize) {
        this._tupleSize = Xflow.DATA_TYPE_TUPLE_SIZE[this._type];
    }
    return this._tupleSize;
};

/**
 * @return {number}
 */
BufferEntry.prototype.getIterateCount = function(){
    return this.getLength() / this.getTupleSize();
};

BufferEntry.prototype.isEmpty = function(){
    return !this._value;
};

//----------------------------------------------------------------------------------------------------------------------
// Xflow.TextureEntry
//----------------------------------------------------------------------------------------------------------------------

function isLoading(image) {
    if (!image)
        return false;
    var nodeName = image.nodeName.toLowerCase();
    if (nodeName == 'img')
        return !image.complete;
    if (nodeName == 'canvas')
        return false;
    if (nodeName == 'video')
        // readyState == 0 is HAVE_NOTHING
        return image.readyState == 0;
    return false;
}

/**
 * @constructor
 * @param {Xflow.TextureEntry} textureEntry
 */
Xflow.ImageManipulator = function(textureEntry) {
    this._textureEntry = textureEntry;
    this.update();
};
Xflow.ImageManipulator.prototype.update = function() {
    this._image = this._textureEntry.getImage();
    if (this._image) {
        var nodeName = this._image.nodeName.toLowerCase();
        if (nodeName == 'video') {
            this.width = this._image.videoWidth;
            this.height = this._image.videoHeight;
        } else {
            this.width = this._image.width;
            this.height = this._image.height;
        }
        if (nodeName == 'canvas') {
            this._canvas = this._image;
            this._copyImageToCtx = false;
        } else {
            this._canvas = null;
            this._copyImageToCtx = true;
        }
    } else {
        this.width = 0;
        this.height = 0;
        this._canvas = null;
    }
    this._context = null;
};
Xflow.ImageManipulator.prototype.isLoading = function() {
    return isLoading(this._image);
};
Xflow.ImageManipulator.prototype.detach = function() {
    this._textureEntry = null;
    // FIXME if _canvas is shared between _textureEntry and this object, it must to be cloned
};
Xflow.ImageManipulator.prototype.getCanvas = function() {
    if (!this._canvas) {
        this._canvas = document.createElement('canvas');
        this._canvas.width = this.width;
        this._canvas.height = this.height;
        this._canvas.complete = false; // for compatibility with img element
    }
    return this._canvas;
};
Xflow.ImageManipulator.prototype.getContext2D = function() {
    if (!this._context) {
        var canvas = this.getCanvas();
        this._context = canvas.getContext("2d");
        if (!this._context)
            throw new Error("Could not create 2D context.");
        if (this._copyImageToCtx) {
            // FIXME What to do with video element ?
            this._context.drawImage(this._image, 0, 0);
        }
    }
    return this._context;
};

function createPlaceholder(w, h) {
    var img = document.createElement('img');
    img.setAttribute('style', 'width:'+w+'px;height:'+h+'px;border:none;display:block');
    img.src = 'data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==';
    return img;
}

/** Call this function when image editing is finished.
 *
 */
Xflow.ImageManipulator.prototype.finish = function() {
    if (this._textureEntry && this._canvas) {
        if (this._canvas) {
            this._canvas.complete = true; // for compatibility with img element
            this._textureEntry._image = this._canvas;
            // FIXME Do we need to call notifyChanged here ? Arrays in DataEntry are not calling callbacks.
            this._textureEntry.notifyChanged();
        } else if (!this._image) {

            // FIXME Do we need to call notifyChanged here ? Arrays in DataEntry are not calling callbacks.
            this._textureEntry.notifyChanged();
        }
    }
}

/**
 * @constructor
 * @extends {Xflow.DataEntry}
 * @param {Object} image
 */
Xflow.TextureEntry = function(image){
    Xflow.DataEntry.call(this, Xflow.DATA_TYPE.TEXTURE);
    this._image = image;
    this._samplerConfig = new SamplerConfig();
    this._imageManipulator = null;
    notifyListeners(this, Xflow.DATA_ENTRY_STATE.CHANGED_NEW);
};
XML3D.createClass(Xflow.TextureEntry, Xflow.DataEntry);
var TextureEntry = Xflow.TextureEntry;

TextureEntry.prototype.isEmpty = function(){
    return !this._image;
};

TextureEntry.prototype.isLoading = function() {
    return isLoading(this._image);
};

/** @param {Object} v */
TextureEntry.prototype.setImage = function(v){
    this._image = v;
    if (this._imageManipulator) {
        if (this._image === this._imageManipulator._image) {
            this._imageManipulator.update();
        } else {
            this._imageManipulator.detach();
            this._imageManipulator = null;
        }
    }
    notifyListeners(this, Xflow.DATA_ENTRY_STATE.CHANGED_VALUE);
}

/** @return {Object} */
TextureEntry.prototype.getImage = function(){
    return this._image;
}

/** @return {Object} */
TextureEntry.prototype.getImageManipulator = function() {
    if (!this._imageManipulator) {
        this._imageManipulator = new Xflow.ImageManipulator(this);
    }
    return this._imageManipulator;
}

    /** @return {Object} */
TextureEntry.prototype.getSamplerConfig = function(){
    return this._samplerConfig;
};

/** @return {number} */
TextureEntry.prototype.getLength = function(){
    return 1;
};

/** @return {number} */
TextureEntry.prototype.getIterateCount = function() {
    return 1;
};

//----------------------------------------------------------------------------------------------------------------------
// Xflow.DataChangeNotifier
//----------------------------------------------------------------------------------------------------------------------

Xflow.DataChangeNotifier = {
    _listeners: []
}
var DataChangeNotifier = Xflow.DataChangeNotifier;

/**
 * @param {function(Xflow.DataEntry, Xflow.DATA_ENTRY_STATE)} callback
 */
DataChangeNotifier.addListener = function(callback){
    this._listeners.push(callback);
};

/**
 * @param {function(Xflow.DataEntry, Xflow.DATA_ENTRY_STATE)} callback
 */
DataChangeNotifier.removeListener = function(callback){
    Array.erase(this._listeners, callback);
};

/**
 * @param {Xflow.DataEntry} dataEntry
 * @param {Xflow.DATA_ENTRY_STATE} notification
 */
function notifyListeners(dataEntry, notification){
    for(var i = 0; i < DataChangeNotifier._listeners.length; ++i){
        DataChangeNotifier._listeners[i](dataEntry, notification);
    }
    for(var i = 0; i < dataEntry._listeners.length; ++i){
        dataEntry._listeners[i].notify(dataEntry, notification);
    }
};
})();
<|endoftext|>


<commit_before>import React, { Component } from 'react';
import {
	ReactiveBase,
	CategorySearch,
	ResultCard,
	MultiDropdownList,
	RangeSlider,
	DataSearch,
	SingleDropdownRange
} from '@appbaseio/reactivesearch';

import './Base.styl';

class Base extends Component {
	constructor() {
		super();
		this.state = {
			tags: [],
			showNav: false
		};
		this.toggleTag = this.toggleTag.bind(this);
		this.handleToggleFilters = this.handleToggleFilters.bind(this);
	}

	handleToggleFilters() {
		const showNav = !this.state.showNav;
		this.setState({
			showNav
		});
	}

	toggleTag(tag) {
		const tags = [ ...this.state.tags ];
		const index = tags.indexOf(tag);
		let nextTags = [];
		if (index === -1) {
			nextTags = [ ...tags, tag ];
		} else {
			nextTags = tags.slice(0, index).concat(tags.slice(index + 1));
		}
		this.setState({
			tags: nextTags
		});
	}

	onData(res, toggleTag) {
		const result = {
			desc: (

									{res.owner}/{res.owner.length + res.name.length > 27 ?
 : ''}{res.name}

								{res.description}

							{
								res.topics.length > 0 ?

										{res.topics.slice(0, 7).map(tag => <span className="card-tag" key={`${res.name}-${tag}`} onClick={() => toggleTag(tag)}>#{tag})}

 :
								null
							}

								{res.stars}

								{res.forks}

								{res.watchers}

			)
		};
		return result;
	}

	render() {
		return (
			<ReactiveBase
				app="gitxplore-live"
				credentials="mfcug4RXu:186efc11-dc28-44ab-8023-f98f0ab09bc4"
				theme="rbc-green"
			>
				<div className={`${this.state.showNav ? 'full-header' : ''}`}>

GitXplore

								Toggle Filters

								<MultiDropdownList
									componentId="language"
									appbaseField="language"
									title="Language"
									searchPlaceholder="Search"
									initialLoader="Loading Languages..."
									size={500}
									URLParams={true}
								/>
								<MultiDropdownList
									componentId="topics"
									appbaseField="topics"
									title="Repo Topics"
									searchPlaceholder="Search"
									initialLoader="Loading Topics..."
									defaultSelected={this.state.tags}
									size={800}
									URLParams={true}
								/>
								<SingleDropdownRange
									componentId="pushed"
									appbaseField="pushed"
									title="Last Active"
									URLParams={true}
									data={[
										{"start": "2017-05-30T00:00:13Z", "end": "2017-07-06T09:22:30Z", "label": "This month"},
										{"start": "2000-05-30T00:00:13Z", "end": "2017-05-29T05:41:13Z", "label": "Past"}
									]}
								/>
								<SingleDropdownRange
									componentId="created"
									appbaseField="created"
									title="Created"
									URLParams={true}
									data={[
										{"start": "2017-01-01T00:00:13Z", "end": "2017-07-06T09:22:30Z", "label": "This year"},
										{"start": "2016-01-01T00:00:13Z", "end": "2017-01-01T00:00:13Z", "label": "Last year"},
										{"start": "2000-05-30T00:00:13Z", "end": "2016-01-01T00:00:13Z", "label": "Past"},
									]}
								/>
								<RangeSlider
									title="Repo Stars"
									componentId="stars"
									appbaseField="stars"
									initialLoader="Loading data..."
									showHistogram={false}
									URLParams={true}
									range={{
										"start": 0,
										"end": 300000
									}}
									defaultSelected={{
										"start": 0,
										"end": 300000
									}}
									rangeLabels={{
										"start": "0 Stars",
										"end": "300K Stars"
									}}
									stepValue={100}
								/>
								<RangeSlider
									title="Repo Forks"
									componentId="forks"
									appbaseField="forks"
									initialLoader="Loading data..."
									showHistogram={false}
									URLParams={true}
									range={{
										"start": 0,
										"end": 300000
									}}
									defaultSelected={{
										"start": 0,
										"end": 300000
									}}
									rangeLabels={{
										"start": "0 Forks",
										"end": "300K Forks"
									}}
									stepValue={100}
								/>
								<RangeSlider
									title="Repo Watchers"
									componentId="watchers"
									appbaseField="watchers"
									initialLoader="Loading data..."
									showHistogram={false}
									URLParams={true}
									range={{
										"start": 0,
										"end": 300000
									}}
									defaultSelected={{
										"start": 0,
										"end": 300000
									}}
									rangeLabels={{
										"start": "0 Watchers",
										"end": "300K Watchers"
									}}
									stepValue={100}
								/>

					<CategorySearch
						componentId="repo"
						appbaseField={["name", "description"]}
						categoryField="language"
						placeholder="Search Repos"
						autocomplete={false}
						URLParams={true}
					/>
					<ResultCard
						componentId="SearchResult"
						appbaseField="name"
						initialLoader="Loading data..."
						noResults="Oops! Nothing found."
						pagination={true}
						size={6}
						onData={(res) => this.onData(res, this.toggleTag)}
						react={{
							and: ["repo", "topics", "stars", "description", "forks", "pushed", "watchers", "created"]
						}}
						sortOptions={[
							{
								label: "Highest rated",
								appbaseField: "stars",
								sortBy: "desc"
							},
							{
								label: "Lowest rated",
								appbaseField: "stars",
								sortBy: "asc"
							},
							{
								label: "Most forked",
								appbaseField: "forks",
								sortBy: "desc"
							},
							{
								label: "Least forked",
								appbaseField: "forks",
								sortBy: "asc"
							},
							{
								label: "Alphabetic",
								appbaseField: "owner",
								sortBy: "asc"
							},
							{
								label: "Reverse alphabetic",
								appbaseField: "owner",
								sortBy: "desc"
							},
							{
								label: "Most recent",
								appbaseField: "pushed",
								sortBy: "desc"
							},
							{
								label: "Least recent",
								appbaseField: "pushed",
								sortBy: "asc"
							}
						]}
					/>

			</ReactiveBase>
		);
	}
}

export default Base;
<commit_msg>:art: Improve suggestions and update dataset<commit_after>import React, { Component } from 'react';
import {
	ReactiveBase,
	CategorySearch,
	ResultCard,
	MultiDropdownList,
	RangeSlider,
	DataSearch,
	SingleDropdownRange
} from '@appbaseio/reactivesearch';

import './Base.styl';

class Base extends Component {
	constructor() {
		super();
		this.state = {
			tags: [],
			showNav: false
		};
		this.toggleTag = this.toggleTag.bind(this);
		this.handleToggleFilters = this.handleToggleFilters.bind(this);
	}

	handleToggleFilters() {
		const showNav = !this.state.showNav;
		this.setState({
			showNav
		});
	}

	toggleTag(tag) {
		const tags = [ ...this.state.tags ];
		const index = tags.indexOf(tag);
		let nextTags = [];
		if (index === -1) {
			nextTags = [ ...tags, tag ];
		} else {
			nextTags = tags.slice(0, index).concat(tags.slice(index + 1));
		}
		this.setState({
			tags: nextTags
		});
	}

	onData(res, toggleTag) {
		const result = {
			desc: (

									{res.owner}/{res.owner.length + res.name.length > 27 ?
 : ''}{res.name}

								{res.description}

							{
								res.topics.length > 0 ?

										{res.topics.slice(0, 7).map(tag => <span className="card-tag" key={`${res.name}-${tag}`} onClick={() => toggleTag(tag)}>#{tag})}

 :
								null
							}

								{res.stars}

								{res.forks}

								{res.watchers}

			)
		};
		return result;
	}

	render() {
		return (
			<ReactiveBase
				app="gitxplore-live"
				credentials="bYTSo47tj:d001826a-f4ef-42c5-b0aa-a94f29967ba0"
				theme="rbc-green"
			>
				<div className={`${this.state.showNav ? 'full-header' : ''}`}>

GitXplore

								Toggle Filters

								<MultiDropdownList
									componentId="language"
									appbaseField="language.raw"
									title="Language"
									searchPlaceholder="Search"
									initialLoader="Loading Languages..."
									size={500}
									URLParams={true}
								/>
								<MultiDropdownList
									componentId="topics"
									appbaseField="topics.raw"
									title="Repo Topics"
									searchPlaceholder="Search"
									initialLoader="Loading Topics..."
									defaultSelected={this.state.tags}
									size={800}
									URLParams={true}
								/>
								<SingleDropdownRange
									componentId="pushed"
									appbaseField="pushed"
									title="Last Active"
									URLParams={true}
									data={[
										{"start": "2017-05-30T00:00:13Z", "end": "2017-07-06T09:22:30Z", "label": "This month"},
										{"start": "2000-05-30T00:00:13Z", "end": "2017-05-29T05:41:13Z", "label": "Past"}
									]}
								/>
								<SingleDropdownRange
									componentId="created"
									appbaseField="created"
									title="Created"
									URLParams={true}
									data={[
										{"start": "2017-01-01T00:00:13Z", "end": "2017-07-06T09:22:30Z", "label": "This year"},
										{"start": "2016-01-01T00:00:13Z", "end": "2017-01-01T00:00:13Z", "label": "Last year"},
										{"start": "2000-05-30T00:00:13Z", "end": "2016-01-01T00:00:13Z", "label": "Past"},
									]}
								/>
								<RangeSlider
									title="Repo Stars"
									componentId="stars"
									appbaseField="stars"
									initialLoader="Loading data..."
									showHistogram={false}
									URLParams={true}
									range={{
										"start": 0,
										"end": 300000
									}}
									defaultSelected={{
										"start": 0,
										"end": 300000
									}}
									rangeLabels={{
										"start": "0 Stars",
										"end": "300K Stars"
									}}
									stepValue={100}
								/>
								<RangeSlider
									title="Repo Forks"
									componentId="forks"
									appbaseField="forks"
									initialLoader="Loading data..."
									showHistogram={false}
									URLParams={true}
									range={{
										"start": 0,
										"end": 300000
									}}
									defaultSelected={{
										"start": 0,
										"end": 300000
									}}
									rangeLabels={{
										"start": "0 Forks",
										"end": "300K Forks"
									}}
									stepValue={100}
								/>
								<RangeSlider
									title="Repo Watchers"
									componentId="watchers"
									appbaseField="watchers"
									initialLoader="Loading data..."
									showHistogram={false}
									URLParams={true}
									range={{
										"start": 0,
										"end": 300000
									}}
									defaultSelected={{
										"start": 0,
										"end": 300000
									}}
									rangeLabels={{
										"start": "0 Watchers",
										"end": "300K Watchers"
									}}
									stepValue={100}
								/>

					<CategorySearch
						componentId="repo"
						appbaseField={["name", "description"]}
						categoryField="language.raw"
						placeholder="Search Repos"
						autocomplete={false}
						URLParams={true}
					/>
					<ResultCard
						componentId="SearchResult"
						appbaseField="name"
						initialLoader="Loading data..."
						noResults="Oops! Nothing found."
						pagination={true}
						size={6}
						onData={(res) => this.onData(res, this.toggleTag)}
						react={{
							and: ["repo", "topics", "stars", "description", "forks", "pushed", "watchers", "created", "language"]
						}}
						sortOptions={[
							{
								label: "Highest rated",
								appbaseField: "stars",
								sortBy: "desc"
							},
							{
								label: "Lowest rated",
								appbaseField: "stars",
								sortBy: "asc"
							},
							{
								label: "Most forked",
								appbaseField: "forks",
								sortBy: "desc"
							},
							{
								label: "Least forked",
								appbaseField: "forks",
								sortBy: "asc"
							},
							{
								label: "Alphabetic",
								appbaseField: "owner",
								sortBy: "asc"
							},
							{
								label: "Reverse alphabetic",
								appbaseField: "owner",
								sortBy: "desc"
							},
							{
								label: "Most recent",
								appbaseField: "pushed",
								sortBy: "desc"
							},
							{
								label: "Least recent",
								appbaseField: "pushed",
								sortBy: "asc"
							}
						]}
					/>

			</ReactiveBase>
		);
	}
}

export default Base;
<|endoftext|>


<commit_before>// @flow
import React, { Component } from 'react';
import { Link } from 'react-router-dom';
import styles from './Home.css';
import Web3 from 'web3';

export default class Home extends Component {

  constructor(props)  {
    super(props)
    this.state = {
      web3: new Web3(new Web3.providers.HttpProvider("http://localhost:8545"))
    }
  }

  generateAddress() {
    console.log("Generating address")
    console.log('Web 3', Web3);
  }

  render() {
    return (

Ether Wallet

          {/* <Link to="/counter">to Counter</Link> */}
          Generate New Address

Accounts on Test Net

          { this.state.web3.eth.accounts.map(account =>{
            return (

{ account }

            )
          })}

    );
  }
}
<commit_msg>add key attr<commit_after>// @flow
import React, { Component } from 'react';
import { Link } from 'react-router-dom';
import styles from './Home.css';
import Web3 from 'web3';

export default class Home extends Component {

  constructor(props)  {
    super(props)
    this.state = {
      web3: new Web3(new Web3.providers.HttpProvider("http://localhost:8545"))
    }
  }

  generateAddress() {
    console.log("Generating address")
    console.log('Web 3', Web3);
  }

  render() {
    return (

Ether Wallet

          {/* <Link to="/counter">to Counter</Link> */}
          Generate New Address

Accounts on Test Net

          { this.state.web3.eth.accounts.map(account =>{
            return (

{ account }

            )
          })}

    );
  }
}
<|endoftext|>


<commit_before>'use strict';

var Provider = channel.Provider;
var Consumer = channel.Consumer;

angular.module('streamium.core', [])

.service('StreamiumProvider', function(bitcore) {

  function StreamiumProvider() {
    this.address = this.streamId = this.rate = null;
    this.clients = [];

    // TODO: this screams for a status object or add status into Provider
    this.mapClientIdToProvider = {};
    this.mapClientIdToStatus = {};

    this.config = config.peerJS;
  }

  StreamiumProvider.STATUS = {
    disconnected: 'disconnected',
    connecting: 'connecting',
    ready: 'ready',
    finished: 'finished'
  };

  StreamiumProvider.prototype.init = function(streamId, address, rate, callback) {
    if (!streamId || !address || !rate || !callback) return callback('Invalid arguments');

    address = new bitcore.Address(address);
    if (!address.isValid()) return callback('Invalid address');

    this.streamId = streamId;
    this.address = address;
    this.rate = rate;

    this.peer = new Peer(this.streamId, this.config);
    var self = this;
    this.peer.on('open', function onOpen() {
      console.log('Conected to peer:', self.peer);
      callback(null, true);
    });

    this.peer.on('close', function onClose() {
      self.status = StreamiumProvider.STATUS.finished;
    });

    this.peer.on('error', function onError(error) {
      self.status = StreamiumProvider.STATUS.disconnected;
      console.log('we have an error');
      callback(error);
    });

    this.peer.on('connection', function onConnection(connection) {
      console.log('New connection!', connection);

      connection.on('data', function(data) {
        console.log('New message', data);
        if (!data.type || !self.handlers[data.type]) throw 'Kernel panic'; // TODO!
        self.handlers[data.type].call(self, connection, data.payload);
      });

    });

    // Init Provider
    // Change status
  };

  StreamiumProvider.prototype.handlers = {};

  StreamiumProvider.prototype.handlers.hello = function(connection, data) {

    // TODO: Assert state

    var provider =  = new Provider({
      network: this.address.network(),
      paymentAddress: this.address
    });

    this.mapClientIdToProvider[connection.peer.id] = provider;
    this.mapClientIdToStatus[connection.peer.id] = StreamiumProvider.STATUS.disconnected;

    connection.send({
      type: 'hello',
      payload: {
        rate: this.rate,
        pubkey: provider.getPublicKey()
      }
    });
  };

  StreamiumProvider.prototype.handlers.sign = function(connection, data) {

    // TODO: Assert state

    var provider = this.mapClientIdToProvider[connection.peer.id];
    var status = this.mapClientIdToStatus[connection.peer.id];

    connection.send({
      type: 'refundAck',
      payload: provider.signRefund(data)
    });
  };

  StreamiumProvider.prototype.handlers.payment = function(connection, data) {

    // TODO: Assert state

    // TODO: this looks like duplicated code
    var provider = this.mapClientIdToProvider[connection.peer.id];
    var status = this.mapClientIdToStatus[connection.peer.id];

    assert(provider.validPayment(data));
    // TODO: Do some check with provider.currentAmount

    connection.send({
      type: 'paymentAck',
      payload: {
        success: true,
        nextTimeout: 0 // TODO: Signal when the next payment is due
      }
    });
  };

  StreamiumProvider.prototype.getLink = function() {
    if (this.status == StreamiumProvider.STATUS.disconnected) throw 'Invalid State';
    return 'https://streamium.io/join/' + this.streamId;
  };

  return new StreamiumProvider();
})

.service('StreamiumClient', function() {

  function StreamiumClient() {
    this.peer = this.connection = null;
    this.status = StreamiumClient.STATUS.disconnected;

    this.rate = this.providerKey = null;

    this.config = config.peerJS;
  };

  StreamiumClient.STATUS = {
    disconnected: 'disconnected',
    connecting: 'connecting',
    funding: 'funding',
    ready: 'ready',
    finished: 'finished'
  };

  StreamiumClient.prototype.connect = function(streamId, callback) {
    this.peer = new Peer(null, this.config);
    this.status = StreamiumClient.STATUS.connecting;
    this.fundingCallback = callback;

    var self = this;
    this.peer.on('open', function onOpen(connection) {
      console.log('Open is working, sending data', self.peer);

      self.connection = self.peer.connect(streamId);
      self.connection.on('open', function() {
        self.connection.send({
          type: 'hello',
          payload: 'client pubkey'
        });

        self.connection.on('data', function(data) {
          console.log('New message', data);
          if (!data.type || !self.handlers[data.type]) throw 'Kernel panic'; // TODO!
          self.handlers[data.type].call(self, data.payload);
        });

      });
    });

    this.peer.on('close', function onClose() {
      self.status = StreamiumClient.STATUS.finished;
    });

    this.peer.on('error', function onError(error) {
      self.status = StreamiumClient.STATUS.disconnected;
      console.log('we have an error');
      callback(error);
    });
  };

  StreamiumClient.prototype.handlers = {};
  StreamiumClient.prototype.handlers.hello = function(data) {
    this.rate = data.rate;
    this.providerKey = data.pubkey;

    this.fundingAddress = 'mkYY5NRvikVBY1EPtaq9fAFgquesdjqECw'; // TODO: GET FUNDIND ADDRESS
    this.status = StreamiumClient.STATUS.funding;
    this.fundingCallback(null, this.fundingAddress);
    this.fundingCallback = null;
  };

  return new StreamiumClient();
});
<commit_msg>Add fucntionality to StreamiumClient<commit_after>'use strict';

var Provider = channel.Provider;
var Consumer = channel.Consumer;

angular.module('streamium.core', [])

.service('StreamiumProvider', function(bitcore) {

  function StreamiumProvider() {
    this.address = this.streamId = this.rate = null;
    this.clients = [];

    // TODO: this screams for a status object or add status into Provider
    this.mapClientIdToProvider = {};
    this.mapClientIdToStatus = {};

    this.config = config.peerJS;
  }

  StreamiumProvider.STATUS = {
    disconnected: 'disconnected',
    connecting: 'connecting',
    ready: 'ready',
    finished: 'finished'
  };

  StreamiumProvider.prototype.init = function(streamId, address, rate, callback) {
    if (!streamId || !address || !rate || !callback) return callback('Invalid arguments');

    address = new bitcore.Address(address);
    if (!address.isValid()) return callback('Invalid address');

    this.streamId = streamId;
    this.address = address;
    this.rate = rate;

    this.peer = new Peer(this.streamId, this.config);
    var self = this;
    this.peer.on('open', function onOpen() {
      console.log('Conected to peer:', self.peer);
      callback(null, true);
    });

    this.peer.on('close', function onClose() {
      self.status = StreamiumProvider.STATUS.finished;
    });

    this.peer.on('error', function onError(error) {
      self.status = StreamiumProvider.STATUS.disconnected;
      console.log('we have an error');
      callback(error);
    });

    this.peer.on('connection', function onConnection(connection) {
      console.log('New connection!', connection);

      connection.on('data', function(data) {
        console.log('New message', data);
        if (!data.type || !self.handlers[data.type]) throw 'Kernel panic'; // TODO!
        self.handlers[data.type].call(self, connection, data.payload);
      });

    });

    // Init Provider
    // Change status
  };

  StreamiumProvider.prototype.handlers = {};

  StreamiumProvider.prototype.handlers.hello = function(connection, data) {

    // TODO: Assert state

    var provider =  = new Provider({
      network: this.address.network(),
      paymentAddress: this.address
    });

    this.mapClientIdToProvider[connection.peer.id] = provider;
    this.mapClientIdToStatus[connection.peer.id] = StreamiumProvider.STATUS.disconnected;

    connection.send({
      type: 'hello',
      payload: {
        type: 'hello',
        payload: {
          pubkey: provider.getPublicKey(),
          rate: this.rate
        }
      }
    });
  };

  StreamiumProvider.prototype.handlers.sign = function(connection, data) {

    // TODO: Assert state

    var provider = this.mapClientIdToProvider[connection.peer.id];
    var status = this.mapClientIdToStatus[connection.peer.id];

    connection.send({
      type: 'refundAck',
      payload: provider.signRefund(data)
    });
  };

  StreamiumProvider.prototype.handlers.payment = function(connection, data) {

    // TODO: Assert state

    // TODO: this looks like duplicated code
    var provider = this.mapClientIdToProvider[connection.peer.id];
    var status = this.mapClientIdToStatus[connection.peer.id];

    assert(provider.validPayment(data));
    // TODO: Do some check with provider.currentAmount

    connection.send({
      type: 'paymentAck',
      payload: {
        success: true,
        nextTimeout: 0 // TODO: Signal when the next payment is due
      }
    });
  };

  StreamiumProvider.prototype.getLink = function() {
    if (this.status == StreamiumProvider.STATUS.disconnected) throw 'Invalid State';
    return 'https://streamium.io/join/' + this.streamId;
  };

  return new StreamiumProvider();
})

.service('StreamiumClient', function() {

  function StreamiumClient() {
    this.peer = this.connection = null;
    this.status = StreamiumClient.STATUS.disconnected;

    this.rate = this.providerKey = null;

    this.config = config.peerJS;
  };

  StreamiumClient.STATUS = {
    disconnected: 'disconnected',
    connecting: 'connecting',
    funding: 'funding',
    ready: 'ready',
    finished: 'finished'
  };

  StreamiumClient.prototype.connect = function(streamId, callback) {
    this.peer = new Peer(null, this.config);
    this.status = StreamiumClient.STATUS.connecting;
    this.fundingCallback = callback;

    var self = this;
    this.peer.on('open', function onOpen(connection) {
      console.log('Open is working, sending data', self.peer);

      self.connection = self.peer.connect(streamId);
      self.connection.on('open', function() {
        self.connection.send({
          type: 'hello',
          payload: ''
        });

        self.connection.on('data', function(data) {
          console.log('New message', data);
          if (!data.type || !self.handlers[data.type]) throw 'Kernel panic'; // TODO!
          self.handlers[data.type].call(self, data.payload);
        });

      });
    });

    this.peer.on('close', function onClose() {
      self.status = StreamiumClient.STATUS.finished;
    });

    this.peer.on('error', function onError(error) {
      self.status = StreamiumClient.STATUS.disconnected;
      console.log('we have an error');
      callback(error);
    });
  };

  StreamiumClient.prototype.handlers = {};
  StreamiumClient.prototype.handlers.hello = function(data) {
    this.rate = data.rate;
    this.network = data.network;
    this.providerKey = data.pubkey;
    this.providerAddress = data.address;

    this.consumer = new Consumer({
      network: this.network,
      providerKey: this.providerKey,
      providerAddress: this.providerAddress
    });
    this.status = StreamiumClient.STATUS.funding;
    this.fundingCallback(null, this.consumer.fundingAddress.toString());
    this.fundingCallback = null;
  };

  StreamiumClient.prototype.handlers.refundAck = function(data) {
    assert(consumer.validateRefund(messageFromProvider));
    this.connection.send({
      type: 'payment',
      payload: this.consumer.getPayment()
    });
  };

  StreamiumClient.prototype.handlers.paymentAck = function(data) {
    // TODO: Pass
  };

  StreamiumClient.prototype.askForRefund = function() {
    this.connection.send({
      type: 'sign',
      payload: this.consumer.getRefundTxToSign()
    });
  };

  return new StreamiumClient();
});
<|endoftext|>


<commit_before>var dockerHubApi  = require('docker-hub-api'), // (supports promises)
    moment        = require('moment'),
    Promise       = require('bluebird');

var dockerHubAuth = require('./config/docker-hub-auth');

var config        = require('./config/config');
var dockerHubInfo = {
  username:   config.downstream.dockerhub.user,
  repository: config.downstream.dockerhub.repo
};

// test
var buildTagName  = 'build-1.6-nightly-5fea2ccc77eb50a9704fa04b7c61755fe34e1d95';

// from task.js
var nightlyVersionStr = function(version, sha) {
  return [ version, '-nightly-', sha ].join('');
};
var buildTagPrefix = 'build-';
var getBuildTagName = function(version) {
  return buildTagPrefix + version;
};

const BUILD_STATUS_SUCCEEDED       = 10;
const BUILD_STATUS_FAILED          = -1;
const BUILD_STATUS_QUEUED          =  0;
const BUILD_STATUS_BUILDING        =  3;

const BUILD_TAG_SOURCE_TYPE_TAG    = 'Tag';
const BUILD_TAG_SOURCE_TYPE_BRANCH = 'Branch';

var isPendingBuild = function(build) {
  return (build.status == BUILD_STATUS_QUEUED || build.status == BUILD_STATUS_BUILDING);
};

// passing build = either successful or pending, not failed
var isPassingBuild = function(build) {
  return (isPendingBuild(build) || build.status == BUILD_STATUS_SUCCEEDED);
};

var findBuildTagsByDetails = function(buildTags, details) {
  return buildTags.filter(function(buildTag) {
    return compareBuildTagDetails(buildTag, details);
  });
};
var normalizeBuildDetails = function(details) {
  var detailsNormalized = details;

   detailsNormalized.name = details.name || '{sourceref}';
   if(details.source_name == 'master' && details.source_type == BUILD_TAG_SOURCE_TYPE_BRANCH) {
     detailsNormalized.name = 'latest';
   }

   detailsNormalized.dockerfile_location = details.dockerfile_location || '/';

   return detailsNormalized;
};
var compareBuildTagDetails = function(buildTag, details) {
  var detailsNormalized    = normalizeBuildDetails(details);
  return (
    buildTag.name                == detailsNormalized.name                &&
    buildTag.dockerfile_location == detailsNormalized.dockerfile_location &&
    buildTag.source_name         == detailsNormalized.source_name         &&
    buildTag.source_type         == detailsNormalized.source_type
  );
};

var reuseTagBuild       = function(dockerHubApi, username, repository, details) {
  var existingBuildTags = {};

  return dockerHubApi.buildSettings(dockerHubInfo.username, dockerHubInfo.repository)
  .then(function(buildSettings) {

    // existing build tag, e.g. build failed or hadn't been triggered yet - but build tag setting already exists
    //existingBuildTags = buildSettings.build_tags.filter(onlyTaggedBuildTag);
    existingBuildTags   = findBuildTagsByDetails(buildSettings.build_tags, details);
    if(existingBuildTags.length > 0) {
      // reuse existing build tag (to preserve the Docker Hub build details)
      return;
    }

    return dockerHubApi.createBuildTag(dockerHubInfo.username, dockerHubInfo.repository, details);
  })
  .then(function(createdBuildTag) {

    var buildTag;
    if(existingBuildTags.length > 0) {
      buildTag = existingBuildTags.pop(); // pick out first build tag for reusing, the rest will be cleaned up afterwards
    } else {
      buildTag = createdBuildTag;
    }

    // adjust details/settings to new details/settings
    // method saveBuildTag(...) not implemented yet!)
    // master branch (for 'latest') never requires modification
    //return dockerHubApi.saveBuildTag(dockerHubInfo.username, dockerHubInfo.repository, buildTag.id, details);

    // trigger the build tag
    // as long as the build process is running, triggering is idempotent
    return dockerHubApi.triggerBuild(dockerHubInfo.username, dockerHubInfo.repository, details);
  })
  .then(function() {
    // clean up eventually existing duplicate build tags
    // one build tag had been removed from the array, so this is only the duplicated rest
    if(existingBuildTags && existingBuildTags.length > 0) {
      return Promise.map(existingBuildTags, function(existingBuildTag) {
        return dockerHubApi.deleteBuildTag(dockerHubInfo.username, dockerHubInfo.repository, existingBuildTag.id);
      });
    }
  })
};

/*
// not used until saveBuildTag had been implemented (see above)
  .then(function(ret) {
    // trigger the now adjusted build tag (this luckily won't disrupt already running builds in build history,
    // so we don't have to leave old build tags in build settings until the regexp issue would have been resolved!)
    console.log('Done');
  })
  .catch(function(err) {
    console.log(err);
  });
};
*/

var getCommitShaFromDockerfile = function(dockerfile) {
  return dockerfile.match(/ENV GOLANG_BUILD_SHA[ ]+(.*)/)[1];
};

var getVersionFromDockerfile = function(dockerfile) {
  return dockerfile.match(/ENV GOLANG_BASE_VERSION[ ]+(.*)/)[1];
};

var byCreatedDateAsc = function(tagA, tagB) {
  return dockerhubCompareDates(
    tagA.created_date,
    tagB.created_date
  );
};
var dockerhubCompareDates = function(dateStrA, dateStrB) {
  return moment(dateStrA).diff(dateStrB);
};

var findTagsByName = function(tags, tagName) {
  return tags.filter(function(tagChecked) {
    return tagChecked.name == tagName;
  });
};
var findBuildsByTagName = function(builds, tagName) {
  return builds.filter(function(buildChecked) {
    return buildChecked.dockertag_name == tagName;
  });
};

dockerHubApi.login(dockerHubAuth.username, dockerHubAuth.password)
.then(function() {

  // note that build history doesn't contain pending builds nor there being a way yet to list pending builds
  // this applies to both, tagged and 'latest' builds

  // for checking tagged builds alone, list of tags can be used
  // for checking 'latest' builds, only buildDetails can be used,
  //   which may be removed when the buildTag settings are removed for 'latest' (master)

  return dockerHubApi.buildHistory(dockerHubInfo.username, dockerHubInfo.repository);
})
.then(function(builds) {

  var checks = [];

  var buildsSortedDesc = builds.sort(byCreatedDateAsc).reverse(); // (desc)

  // - 'latest' build
  var passingBuildsSortedDesc = buildsSortedDesc.filter(isPassingBuild);

  // check only possible using the build history
  // also check whether the 'latest' build is still pending
  var latestBuilds    = findBuildsByTagName(passingBuildsSortedDesc, 'latest');
  var lastLatestBuild = latestBuilds[0];

  checks.push(dockerHubApi.buildDetails(dockerHubInfo.username, dockerHubInfo.repository, lastLatestBuild.build_code)
  .then(function(lastLatestBuildDetails) {
    var lastLatestBuildTagName = tagNameFromBuildDetails(lastLatestBuildDetails)
    if(lastLatestBuildTagName == buildTagName) {

      if(isPendingBuild(lastLatestBuild)) {
        console.log("Last 'latest' build had been already triggered + is pending, skipped.");
        return;
      }

      console.log("Last 'latest' build had been already build, skipped.");
      return;
    }

    // trigger with master branch for 'latest' build
    console.log("Last 'latest' build uses not recent enough build tag (latest: '" + buildTagNameLastLatestBuild + "', last tag: '" + buildTagName + "'.");
    return reuseTagBuild(dockerHubApi, dockerHubInfo.username, dockerHubInfo.repository, {
      name:        'latest',
      source_name: 'master',
      source_type: BUILD_TAG_SOURCE_TYPE_BRANCH
    })
    .then(function() {
      console.log("Triggered 'latest' build with master branch.");
    })
    .catch(function(err) {
      console.log("Error triggering 'latest' build with master branch, error: " + err);
    });
    console.log("Triggered 'latest' build.");

  })
  );

  // - tagged build
  // (check for tagged builds can use tags)

  // only pending builds for checking as tags from successful builds may have been deleted
  var pendingBuildsSortedDesc = buildsSortedDesc.filter(isPendingBuild);

  checks.push(dockerHubApi.tags(dockerHubInfo.username, dockerHubInfo.repository)
  .then(function(tags) {

    var taggedTags = findTagsByName(tags, buildTagName);
    var taggedTag  = taggedTags[0]; // (tags are unique)
    if(taggedTag) {
      console.log("Tagged build '" + buildTagName + "' had been already built, skipped.");
      return;
    }

    // also check whether the tagged build is still pending
    var taggedPendingBuilds    = findBuildsByTagName(pendingBuildsSortedDesc, buildTagName);
    var lastTaggedPendingBuild = taggedPendingBuilds[0];
    if(lastTaggedPendingBuild) {
      console.log("Tagged build '" + buildTagName + "' had been already triggered + is pending, skipped.");
      return;
    }

    // trigger tagged build
    console.log("Tagged build '" + buildTagName + "' hadn't been built yet.");
    return reuseTagBuild(dockerHubApi, dockerHubInfo.username, dockerHubInfo.repository, {
      source_name: buildTagName,
      source_type: BUILD_TAG_SOURCE_TYPE_TAG
     })
     .then(function() {
       console.log("Triggered tagged build with tag '" + buildTagName + "'.");
     })
     .catch(function(err) {
       console.log("Error triggering tagged build with tag '" + buildTagName + "', error: " + err);
     });

  })
  );

  return Promise.all(checks);
})
.then(function() {
  console.log('Done.');
})
.catch(function(err) {
  console.log('Error (g): ' + err);
});

// determines the build tagname from the build details
var tagNameFromBuildDetails = function(buildDetails) {

  var dockerfile = buildDetails.build_results.dockerfile_contents;
  var version    = getVersionFromDockerfile(dockerfile);
  var sha        = getCommitShaFromDockerfile(dockerfile);

  var nightlyVersion = nightlyVersionStr(version, sha);
  var buildTagName   = getBuildTagName(nightlyVersion);

  return buildTagName;
};
<commit_msg>Separate responsibilities (is build there, trigger build). Improve code.<commit_after>var dockerHubApi  = require('docker-hub-api'), // (supports promises)
    moment        = require('moment'),
    Promise       = require('bluebird');

var dockerHubAuth = require('./config/docker-hub-auth');

var config        = require('./config/config');
var dockerHubInfo = {
  username:   config.downstream.dockerhub.user,
  repository: config.downstream.dockerhub.repo
};

// test
var buildTagName  = 'build-1.6-nightly-5fea2ccc77eb50a9704fa04b7c61755fe34e1d95';

// from task.js
var nightlyVersionStr = function(version, sha) {
  return [ version, '-nightly-', sha ].join('');
};
var buildTagPrefix = 'build-';
var getBuildTagName = function(version) {
  return buildTagPrefix + version;
};
// ----

const BUILD_STATUS_SUCCEEDED       = 10;
const BUILD_STATUS_FAILED          = -1;
const BUILD_STATUS_QUEUED          =  0;
const BUILD_STATUS_BUILDING        =  3;

const BUILD_TAG_SOURCE_TYPE_TAG    = 'Tag';
const BUILD_TAG_SOURCE_TYPE_BRANCH = 'Branch';

var isPendingBuild = function(build) {
  return (build.status == BUILD_STATUS_QUEUED || build.status == BUILD_STATUS_BUILDING);
};

// passing build = either successful or pending, not failed
var isPassingBuild = function(build) {
  return (isPendingBuild(build) || build.status == BUILD_STATUS_SUCCEEDED);
};

var findBuildTagsByDetails = function(buildTags, details) {
  return buildTags.filter(function(buildTag) {
    return compareBuildTagDetails(buildTag, details);
  });
};
var normalizeBuildDetails = function(details) {
  var detailsNormalized = details;

   detailsNormalized.name = details.name || '{sourceref}';
   if(details.source_name == 'master' && details.source_type == BUILD_TAG_SOURCE_TYPE_BRANCH) {
     detailsNormalized.name = 'latest';
   }

   detailsNormalized.dockerfile_location = details.dockerfile_location || '/';

   return detailsNormalized;
};
var compareBuildTagDetails = function(buildTag, details) {
  var detailsNormalized    = normalizeBuildDetails(details);
  return (
    buildTag.name                == detailsNormalized.name                &&
    buildTag.dockerfile_location == detailsNormalized.dockerfile_location &&
    buildTag.source_name         == detailsNormalized.source_name         &&
    buildTag.source_type         == detailsNormalized.source_type
  );
};

var getCommitShaFromDockerfile = function(dockerfile) {
  return dockerfile.match(/ENV GOLANG_BUILD_SHA[ ]+(.*)/)[1];
};

var getVersionFromDockerfile = function(dockerfile) {
  return dockerfile.match(/ENV GOLANG_BASE_VERSION[ ]+(.*)/)[1];
};

var byCreatedDateAsc = function(tagA, tagB) {
  return dockerhubCompareDates(
    tagA.created_date,
    tagB.created_date
  );
};
var dockerhubCompareDates = function(dateStrA, dateStrB) {
  return moment(dateStrA).diff(dateStrB);
};

var findTagsByName = function(tags, tagName) {
  return tags.filter(function(tagChecked) {
    return tagChecked.name == tagName;
  });
};
var findBuildsByTagName = function(builds, tagName) {
  return builds.filter(function(buildChecked) {
    return buildChecked.dockertag_name == tagName;
  });
};

// determines the build tagname from the build details
var tagNameFromBuildDetails = function(buildDetails) {

  var dockerfile = buildDetails.build_results.dockerfile_contents;
  var version    = getVersionFromDockerfile(dockerfile);
  var sha        = getCommitShaFromDockerfile(dockerfile);

  var nightlyVersion = nightlyVersionStr(version, sha);
  var buildTagName   = getBuildTagName(nightlyVersion);

  return buildTagName;
};

var reuseTagBuild       = function(dockerHubApi, username, repository, details) {
  var existingBuildTags = {};

  return dockerHubApi.buildSettings(dockerHubInfo.username, dockerHubInfo.repository)
  .then(function(buildSettings) {

    // existing build tag, e.g. build failed or hadn't been triggered yet - but build tag setting already exists
    //existingBuildTags = buildSettings.build_tags.filter(onlyTaggedBuildTag);
    existingBuildTags   = findBuildTagsByDetails(buildSettings.build_tags, details);
    if(existingBuildTags.length > 0) {
      // reuse existing build tag (to preserve the Docker Hub build details)
      return;
    }

    return dockerHubApi.createBuildTag(dockerHubInfo.username, dockerHubInfo.repository, details);
  })
  .then(function(createdBuildTag) {

    var buildTag;
    if(existingBuildTags.length > 0) {
      buildTag = existingBuildTags.pop(); // pick out first build tag for reusing, the rest will be cleaned up afterwards
    } else {
      buildTag = createdBuildTag;
    }

    // adjust details/settings to new details/settings
    // method saveBuildTag(...) not implemented yet!)
    // master branch (for 'latest') never requires modification
    //return dockerHubApi.saveBuildTag(dockerHubInfo.username, dockerHubInfo.repository, buildTag.id, details);

    // trigger the build tag
    // as long as the build process is running, triggering is idempotent
    return dockerHubApi.triggerBuild(dockerHubInfo.username, dockerHubInfo.repository, details);
  })
  .then(function() {
    // clean up eventually existing duplicate build tags
    // one build tag had been removed from the array, so this is only the duplicated rest
    if(existingBuildTags && existingBuildTags.length > 0) {
      return Promise.map(existingBuildTags, function(existingBuildTag) {
        return dockerHubApi.deleteBuildTag(dockerHubInfo.username, dockerHubInfo.repository, existingBuildTag.id);
      });
    }
  })
};

/*
// not used until saveBuildTag had been implemented (see above)
  .then(function(ret) {
    // trigger the now adjusted build tag (this luckily won't disrupt already running builds in build history,
    // so we don't have to leave old build tags in build settings until the regexp issue would have been resolved!)
    console.log('Done');
  })
  .catch(function(err) {
    console.log(err);
  });
};
*/

const CHECK_BUILD_OK         =  10;
const CHECK_BUILD_OK_PENDING =   2;
const CHECK_BUILD_NOTFOUND   =  -1;
const CHECK_BUILD_OUTDATED   =  -2;

var checkLatestBuild = function(dockerHubApi, username, repository, buildsSortedDesc, buildTagName) {
  return isThereLatestBuild(dockerHubApi, username, repository, buildsSortedDesc, buildTagName)
  .then(function(result) {
    if(result == CHECK_BUILD_OK || result == CHECK_BUILD_OK_PENDING) {
      if(result == CHECK_BUILD_OK_PENDING) {
        console.log("Last 'latest' build had been already triggered + is pending, skipped.");
        return;
      }
      console.log("Last 'latest' build had been already build, skipped.");
      return;
    }
    // Trigger with master branch for 'latest' build
    console.log("Last 'latest' build uses not recent enough build tag (latest: '" + buildTagNameLastLatestBuild + "', last tag: '" + buildTagName + "'.");
    return triggerLatestBuild(dockerHubApi, username, repository);
  });
};

var triggerLatestBuild = function(dockerHubApi, username, repository) {
  return reuseTagBuild(dockerHubApi, username, repository, {
    name:        'latest',
    source_name: 'master',
    source_type: BUILD_TAG_SOURCE_TYPE_BRANCH
  })
  .then(function() {
    console.log("Triggered 'latest' build with master branch.");
  })
  .catch(function(err) {
    console.log("Error triggering 'latest' build with master branch, error: " + err);
  });
};

var checkTaggedBuild = function(dockerHubApi, username, repository, buildsSortedDesc, buildTagName) {
  return isThereTaggedBuild(dockerHubApi, username, repository, buildsSortedDesc, buildTagName)
  .then(function(result) {
    if(result == CHECK_BUILD_OK || result == CHECK_BUILD_OK_PENDING) {
      if(result == CHECK_BUILD_OK_PENDING) {
        //console.log("Tagged build '" + buildTagName + "' had been already triggered + is pending, skipped.");
        return;
      }
      console.log("Tagged build '" + buildTagName + "' had been already built, skipped.");
      return;
    }
    // Trigger tagged build
    console.log("Tagged build '" + buildTagName + "' hadn't been built yet.");
    return triggerTaggedBuild(dockerHubApi, username, repository, buildTagName);
  });
};

var triggerTaggedBuild = function(dockerHubApi, username, repository, buildTagName) {
  return reuseTagBuild(dockerHubApi, username, repository, {
    source_name: buildTagName,
    source_type: BUILD_TAG_SOURCE_TYPE_TAG
  })
  .then(function() {
    console.log("Triggered tagged build with tag '" + buildTagName + "'.");
  })
  .catch(function(err) {
    console.log("Error triggering tagged build with tag '" + buildTagName + "', error: " + err);
  });
};

var isThereLatestBuild = function(dockerHubApi, username, repository, buildsSortedDesc) {
  // - 'latest' build
  var passingBuildsSortedDesc = buildsSortedDesc.filter(isPassingBuild);

  // check only possible using the build history
  // also check whether the 'latest' build is still pending
  var latestBuilds    = findBuildsByTagName(passingBuildsSortedDesc, 'latest');
  var lastLatestBuild = latestBuilds[0];

  return dockerHubApi.buildDetails(dockerHubInfo.username, dockerHubInfo.repository, lastLatestBuild.build_code)
  .then(function(lastLatestBuildDetails) {
    var lastLatestBuildTagName = tagNameFromBuildDetails(lastLatestBuildDetails)
    if(lastLatestBuildTagName == buildTagName) {

      if(isPendingBuild(lastLatestBuild)) {
        return CHECK_BUILD_OK_PENDING;
      }

      return CHECK_BUILD_OK;
    }

    return CHECK_BUILD_OUTDATED;
  })
};

var isThereTaggedBuild = function(dockerHubApi, username, repository, buildsSortedDesc, buildTagName) {
  // - tagged build
  // (check for tagged builds can use tags)

  // only pending builds for checking as tags from successful builds may have been deleted
  var pendingBuildsSortedDesc = buildsSortedDesc.filter(isPendingBuild);

  return dockerHubApi.tags(dockerHubInfo.username, dockerHubInfo.repository)
  .then(function(tags) {

    var taggedTags = findTagsByName(tags, buildTagName);
    var taggedTag  = taggedTags[0]; // (tags are unique)
    if(taggedTag) {
      return CHECK_BUILD_OK;
    }

    // also check whether the tagged build is still pending
    var taggedPendingBuilds    = findBuildsByTagName(pendingBuildsSortedDesc, buildTagName);
    var lastTaggedPendingBuild = taggedPendingBuilds[0];
    if(lastTaggedPendingBuild) {
      return CHECK_BUILD_OK_PENDING;
    }

    return CHECK_BUILD_NOTFOUND;
  })
};

dockerHubApi.login(dockerHubAuth.username, dockerHubAuth.password)
.then(function() {

  // note that build history doesn't contain pending builds nor there being a way yet to list pending builds
  // this applies to both, tagged and 'latest' builds

  // for checking tagged builds alone, list of tags can be used
  // for checking 'latest' builds, only buildDetails can be used,
  //   which may be removed when the buildTag settings are removed for 'latest' (master)

  return dockerHubApi.buildHistory(dockerHubInfo.username, dockerHubInfo.repository);
})
.then(function(builds) {

  var buildsSortedDesc = builds.sort(byCreatedDateAsc).reverse(); // (desc)

  return Promise.join([
    checkLatestBuild(dockerHubApi, dockerHubInfo.username, dockerHubInfo.repository, buildsSortedDesc, buildTagName),
    checkTaggedBuild(dockerHubApi, dockerHubInfo.username, dockerHubInfo.repository, buildsSortedDesc, buildTagName)
  ]);
})
.then(function() {
  console.log('Done.');
})
.catch(function(err) {
  console.log('Error (g): ' + err);
});
<|endoftext|>


<commit_before>/**
 * Copyright (c) 2016, Tidepool Project
 *
 * This program is free software; you can redistribute it and/or modify it under
 * the terms of the associated License, which is identical to the BSD 2-Clause
 * License as published by the Open Source Initiative at opensource.org.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the License for more details.
 *
 * You should have received a copy of the License along with this program; if
 * not, you can obtain one from Tidepool Project at tidepool.org.
 */

import _ from 'lodash';

import sundial from 'sundial';

import i18next from './language';
import { capitalize, validateEmail } from './utils';
import * as errors from './validation/errors';

import config from '../config';

const t = i18next.t.bind(i18next);

// ensure config vars are defined
export const ABOUT_MAX_LENGTH = config.ABOUT_MAX_LENGTH || 256;
export const PASSWORD_MIN_LENGTH = config.PASSWORD_MIN_LENGTH || 8;
export const PASSWORD_MAX_LENGTH = config.PASSWORD_MAX_LENGTH  || 72;
export const CLINICIAN_NAME_MAX_LENGTH = config.CLINICIAN_NAME_MAX_LENGTH || 140;
export const CLINICIAN_PHONE_MAX_LENGTH = config.CLINICIAN_PHONE_MAX_LENGTH || 30;

/**
 * Validation response when a field passes the validation checks
 *
 * @return {Object}
 */
export const valid = () => ({
  valid: true,
  message: null
});

/**
 * Validation response when a field fails the validation checks
 *
 * @param  {String} message error message that will be displayed in the form
 *
 * @return {Object}
 */
export const invalid = (message) => ({
  valid: false,
  message: message
});

/**
 * The date type validator. N.B It is has been extracted from inline definition in type
 * validators due to it being used inside of another.
 *
 * @param  {String} fieldLabel
 * @param  {Object} fieldValue
 * @param  {Object} currentDateObj for testing purposes
 * @return {Object}
 */
const dateValidator = (fieldLabel, fieldValue, currentDateObj) => {
  let now = new Date();
  let dateMask = t('M-D-YYYY');
  let dateString;

  currentDateObj = currentDateObj || Date.UTC(now.getFullYear(), now.getMonth(), now.getDate());

  if (!fieldValue) {
    return invalid(errors.isRequired(fieldLabel));
  }

  if (!fieldValue.day || !fieldValue.month || !fieldValue.year) {
    return invalid(errors.incompleteDate(fieldLabel));
  }

  let month = parseInt(fieldValue.month, 10) + 1; // month is zero indexed

  dateString = `${month}-${fieldValue.day}-${fieldValue.year}`;
  if (!sundial.isValidDateForMask(dateString, dateMask)) {
    return invalid(errors.invalidDate());
  }

  if (currentDateObj < sundial.parseFromFormat(dateString, dateMask)) {
    return invalid(errors.futureDate(fieldLabel));
  }

  return valid();
};

/**
 * Map of type validators for use in validateField()
 *
 * @type {Object}
 */
export const typeValidators = {
  name: (fieldLabel, fieldValue) => {
    if (!fieldValue || fieldValue.length === 0) {
      return invalid(errors.isRequired(fieldLabel));
    }
    return valid();
  },
  about: (fieldLabel, fieldValue) => {
    if (fieldValue && fieldValue.length > ABOUT_MAX_LENGTH) {
      return invalid(errors.isTooLong(ABOUT_MAX_LENGTH, fieldLabel));
    }

    return valid();
  },
  email: (fieldLabel, fieldValue) => {
    if (!fieldValue || fieldValue.length === 0) {
      return invalid(errors.isRequired(fieldLabel));
    }

    if (!validateEmail(fieldValue)) {
      return invalid(errors.invalidEmail(fieldLabel));
    }

    return valid();
  },
  password: (fieldLabel, fieldValue) => {
    if (!fieldValue || fieldValue.length === 0) {
      return invalid(errors.isRequired(fieldLabel));
    }

    if (/\s/g.test(fieldValue)) { //check for white-space (spaces, tabs)
      return invalid(errors.containsWhiteSpaces(fieldLabel));
    }

    if (fieldValue.length < PASSWORD_MIN_LENGTH) {
      return invalid(errors.isTooShort(PASSWORD_MIN_LENGTH, fieldLabel));
    }

    if (fieldValue.length > PASSWORD_MAX_LENGTH) {
      return invalid(errors.isTooLong(PASSWORD_MAX_LENGTH, fieldLabel));
    }

    return valid();
  },
  confirmPassword: (fieldLabel, fieldValue, prerequisites) => {
    if (!prerequisites.password || prerequisites.password.length === 0) {
      return invalid(errors.noPassword());
    }

    if (prerequisites.password !== fieldValue) {
      return invalid(errors.passwordsDontMatch());
    }

    return valid();
  },
  date: dateValidator,
  diagnosisDate: (fieldLabel, fieldValue, prerequisites) => {
    let dateMask = t('M-D-YYYY');
    let validDateCheck = dateValidator(fieldLabel, fieldValue);
    let birthdayObj, birthdayDateString;
    let diagnosisDateObj, diagnosisDateString;
    if (!validDateCheck.valid) {
      return validDateCheck;
    }

    if (!prerequisites.birthday) {
      return invalid(errors.noBirthday());
    }

    if (!dateValidator('', prerequisites.birthday).valid) {
      return invalid(errors.invalidBirthday());
    }

    // checks to see if diagnosis date is earlier than birthdate (which is not allowed)
    var invalidYear = prerequisites.birthday.year > fieldValue.year;
    var invalidMonth = prerequisites.birthday.month > fieldValue.month;
    var invalidDay = prerequisites.birthday.day > fieldValue.day;

    if (invalidYear || invalidMonth || invalidDay) {
      return invalid(errors.mustBeAfterBirthday(fieldLabel));
    }

    return valid();
  },
  clinicName: (fieldLabel, fieldValue) => {
    if (!fieldValue || fieldValue.length === 0) {
      return invalid(errors.isRequired(fieldLabel));
    }

    if (fieldValue.length > CLINICIAN_NAME_MAX_LENGTH) {
      return invalid(errors.isTooLong(CLINICIAN_NAME_MAX_LENGTH, fieldLabel));
    }
    return valid();
  },
  clinicPhone: (fieldLabel, fieldValue) => {
    if (fieldValue && fieldValue.length > CLINICIAN_PHONE_MAX_LENGTH) {
      return invalid(errors.isTooLong(CLINICIAN_PHONE_MAX_LENGTH, fieldLabel));
    }
    return valid();
  },
  clinicalRole: (fieldLabel, fieldValue) => {
    if (!fieldValue || fieldValue.length === 0) {
      return invalid(errors.isRequired(fieldLabel));
    }
    return valid();
  }
};

/**
 * Validates a single form field
 *
 * @param  {String} type
 * @param  {String} fieldLabel
 * @param  {String|Number|Object} fieldValue
 * @param  {Object|null} prerequisites
 * @return {Object}               either the results of invalid(message) or valid()
 */
export const validateField = (type, fieldLabel, fieldValue, prerequisites) => {
  if(!typeValidators[type]) { // @TODO: Gordon Dent: at present we do not have generic validation, we may way to add this
    return valid();
  }
  return typeValidators[type](fieldLabel, fieldValue, prerequisites);
};

/**
 * Validates an array of fields
 *
 * @param  {Array} form
 *
 * @return {Object} an object which is either empty (valid form) or contains entries for field names with error messages
 */
export const validateForm = (form) => {
  if (!form) { // @TODO: Gordon Dent: may want to check if not object too
    return {};
  }

  return form
    .map((field) => {
      let result = validateField(field.type, field.label, field.value, field.prerequisites);
      result.name = field.name;

      return result;
    })
    .filter((result) => !result.valid)
    // add comment here about component expectation
    .reduce((reduction, result) => {
      reduction[result.name] = result.message;
      return reduction;
    }, {});
};
<commit_msg>Fixed Birthday and Diagnosed Day bug v2<commit_after>/**
 * Copyright (c) 2016, Tidepool Project
 *
 * This program is free software; you can redistribute it and/or modify it under
 * the terms of the associated License, which is identical to the BSD 2-Clause
 * License as published by the Open Source Initiative at opensource.org.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the License for more details.
 *
 * You should have received a copy of the License along with this program; if
 * not, you can obtain one from Tidepool Project at tidepool.org.
 */

import _ from 'lodash';

import sundial from 'sundial';

import i18next from './language';
import { capitalize, validateEmail } from './utils';
import * as errors from './validation/errors';

import config from '../config';

const t = i18next.t.bind(i18next);

// ensure config vars are defined
export const ABOUT_MAX_LENGTH = config.ABOUT_MAX_LENGTH || 256;
export const PASSWORD_MIN_LENGTH = config.PASSWORD_MIN_LENGTH || 8;
export const PASSWORD_MAX_LENGTH = config.PASSWORD_MAX_LENGTH  || 72;
export const CLINICIAN_NAME_MAX_LENGTH = config.CLINICIAN_NAME_MAX_LENGTH || 140;
export const CLINICIAN_PHONE_MAX_LENGTH = config.CLINICIAN_PHONE_MAX_LENGTH || 30;

/**
 * Validation response when a field passes the validation checks
 *
 * @return {Object}
 */
export const valid = () => ({
  valid: true,
  message: null
});

/**
 * Validation response when a field fails the validation checks
 *
 * @param  {String} message error message that will be displayed in the form
 *
 * @return {Object}
 */
export const invalid = (message) => ({
  valid: false,
  message: message
});

/**
 * The date type validator. N.B It is has been extracted from inline definition in type
 * validators due to it being used inside of another.
 *
 * @param  {String} fieldLabel
 * @param  {Object} fieldValue
 * @param  {Object} currentDateObj for testing purposes
 * @return {Object}
 */
const dateValidator = (fieldLabel, fieldValue, currentDateObj) => {
  let now = new Date();
  let dateMask = t('M-D-YYYY');
  let dateString;

  currentDateObj = currentDateObj || Date.UTC(now.getFullYear(), now.getMonth(), now.getDate());

  if (!fieldValue) {
    return invalid(errors.isRequired(fieldLabel));
  }

  if (!fieldValue.day || !fieldValue.month || !fieldValue.year) {
    return invalid(errors.incompleteDate(fieldLabel));
  }

  let month = parseInt(fieldValue.month, 10) + 1; // month is zero indexed

  dateString = `${month}-${fieldValue.day}-${fieldValue.year}`;
  if (!sundial.isValidDateForMask(dateString, dateMask)) {
    return invalid(errors.invalidDate());
  }

  if (currentDateObj < sundial.parseFromFormat(dateString, dateMask)) {
    return invalid(errors.futureDate(fieldLabel));
  }

  return valid();
};

/**
 * Map of type validators for use in validateField()
 *
 * @type {Object}
 */
export const typeValidators = {
  name: (fieldLabel, fieldValue) => {
    if (!fieldValue || fieldValue.length === 0) {
      return invalid(errors.isRequired(fieldLabel));
    }
    return valid();
  },
  about: (fieldLabel, fieldValue) => {
    if (fieldValue && fieldValue.length > ABOUT_MAX_LENGTH) {
      return invalid(errors.isTooLong(ABOUT_MAX_LENGTH, fieldLabel));
    }

    return valid();
  },
  email: (fieldLabel, fieldValue) => {
    if (!fieldValue || fieldValue.length === 0) {
      return invalid(errors.isRequired(fieldLabel));
    }

    if (!validateEmail(fieldValue)) {
      return invalid(errors.invalidEmail(fieldLabel));
    }

    return valid();
  },
  password: (fieldLabel, fieldValue) => {
    if (!fieldValue || fieldValue.length === 0) {
      return invalid(errors.isRequired(fieldLabel));
    }

    if (/\s/g.test(fieldValue)) { //check for white-space (spaces, tabs)
      return invalid(errors.containsWhiteSpaces(fieldLabel));
    }

    if (fieldValue.length < PASSWORD_MIN_LENGTH) {
      return invalid(errors.isTooShort(PASSWORD_MIN_LENGTH, fieldLabel));
    }

    if (fieldValue.length > PASSWORD_MAX_LENGTH) {
      return invalid(errors.isTooLong(PASSWORD_MAX_LENGTH, fieldLabel));
    }

    return valid();
  },
  confirmPassword: (fieldLabel, fieldValue, prerequisites) => {
    if (!prerequisites.password || prerequisites.password.length === 0) {
      return invalid(errors.noPassword());
    }

    if (prerequisites.password !== fieldValue) {
      return invalid(errors.passwordsDontMatch());
    }

    return valid();
  },
  date: dateValidator,
  diagnosisDate: (fieldLabel, fieldValue, prerequisites) => {
    let dateMask = t('M-D-YYYY');
    let validDateCheck = dateValidator(fieldLabel, fieldValue);
    let birthdayObj;
    let diagnosisDateObj;
    if (!validDateCheck.valid) {
      return validDateCheck;
    }

    if (!prerequisites.birthday) {
      return invalid(errors.noBirthday());
    }

    if (!dateValidator('', prerequisites.birthday).valid) {
      return invalid(errors.invalidBirthday());
    }

    // checks to see if diagnosis date is earlier than birthdate (which is not allowed)
    birthdayObj = new Date(prerequisites.birthday.year, prerequisites.birthday.month, prerequisites.birthday.day);
    diagnosisDateObj = new Date(fieldValue.year, fieldValue.month, fieldValue.day);

    if (diagnosisDateObj > birthdayObj) {
      return invalid(errors.mustBeAfterBirthday(fieldLabel));
    }

    return valid();
  },
  clinicName: (fieldLabel, fieldValue) => {
    if (!fieldValue || fieldValue.length === 0) {
      return invalid(errors.isRequired(fieldLabel));
    }

    if (fieldValue.length > CLINICIAN_NAME_MAX_LENGTH) {
      return invalid(errors.isTooLong(CLINICIAN_NAME_MAX_LENGTH, fieldLabel));
    }
    return valid();
  },
  clinicPhone: (fieldLabel, fieldValue) => {
    if (fieldValue && fieldValue.length > CLINICIAN_PHONE_MAX_LENGTH) {
      return invalid(errors.isTooLong(CLINICIAN_PHONE_MAX_LENGTH, fieldLabel));
    }
    return valid();
  },
  clinicalRole: (fieldLabel, fieldValue) => {
    if (!fieldValue || fieldValue.length === 0) {
      return invalid(errors.isRequired(fieldLabel));
    }
    return valid();
  }
};

/**
 * Validates a single form field
 *
 * @param  {String} type
 * @param  {String} fieldLabel
 * @param  {String|Number|Object} fieldValue
 * @param  {Object|null} prerequisites
 * @return {Object}               either the results of invalid(message) or valid()
 */
export const validateField = (type, fieldLabel, fieldValue, prerequisites) => {
  if(!typeValidators[type]) { // @TODO: Gordon Dent: at present we do not have generic validation, we may way to add this
    return valid();
  }
  return typeValidators[type](fieldLabel, fieldValue, prerequisites);
};

/**
 * Validates an array of fields
 *
 * @param  {Array} form
 *
 * @return {Object} an object which is either empty (valid form) or contains entries for field names with error messages
 */
export const validateForm = (form) => {
  if (!form) { // @TODO: Gordon Dent: may want to check if not object too
    return {};
  }

  return form
    .map((field) => {
      let result = validateField(field.type, field.label, field.value, field.prerequisites);
      result.name = field.name;

      return result;
    })
    .filter((result) => !result.valid)
    // add comment here about component expectation
    .reduce((reduction, result) => {
      reduction[result.name] = result.message;
      return reduction;
    }, {});
};
<|endoftext|>


<commit_before>'use strict';

import mongoose from 'mongoose';
import config from '../../config/config.json';

const mongopt = config.mongo.config.development;
const options = {
  db: {native_parser: true},
  server: {poolSize: 5},
  user: mongopt.user,
  pass: mongopt.pass
};

mongoose.connect(mongopt.db, options);
mongoose.models = {};

// Register models
import User from './model/User';
User.register(mongoose);
import Thing from './model/Thing'
Thing.register(mongoose);

export default mongoose;
<commit_msg>Update init.js<commit_after>'use strict';

import mongoose from 'mongoose';
import config from '../../config/config.json';

const mongopt = config.mongo.config.development;
const options = {
  db: {native_parser: true},
  server: {poolSize: 5},
  user: mongopt.user,
  pass: mongopt.pass
};

mongoose.connect(mongopt.db, options);
mongoose.models = {};

// Register models
import User from './model/User';
User.register(mongoose);
import Thing from './model/Thing';
Thing.register(mongoose);

export default mongoose;
<|endoftext|>


<commit_before>/**
 * @fileOverview 应用入口
 * @author 吴钦飞(wuqf@pkusoft.net)
 * @module module:main
 * @requires jquery
 * @requires module:common/launchpad
 * @requires module:common/template
 * @requires module:common/app
 */
define( function ( require ) {
    var
        $ = require( "jquery" ),
        Launchpad = require( "./common/launchpad" ),
        App = require( "./common/app" ),
        Template = require( "template" ),
        AppSearch = require( "./common/app-search" ),
        AppSidebar = require( "./common/app-sidebar" ),
        menuSource = require( "./common/menuSource" )
    ;

    // 载入系统功能URL配置文件
    require( "./config/systemUrl" );

    if ( window.isIE8 ) {
        seajs.use( "./css/page/ie8-hack.css" );
    }

    // DOM树构建完毕后执行
    $( document ).ready( function () {

        // 启动 Launchpad
        Launchpad.init();

        // 启动 应用（App）系统
        App.init();

        // 启动搜索功能
        new AppSearch( {
            targetSelector: "#topbar-toolbar-search"
        } );

        // 启动应用侧边栏
        new AppSidebar( {
            toggleSelector: "#topbar-history",
            sidebarSelector: "#daSidebar",
            sidebarBodySelecotr: "#da-sidebar-body",
            oftenUsedUrl: "__CTX__/admin/oftenUsedSysMenu",
            recentUsedUrl: "__CTX__/admin/recentUsedSysMenu",
            saveUsedMenuUrl: "__CTX__/admin/saveUsedMenu",

            maxOftenUsedItemNum: 6,
            maxRecentUsedItemNum: 10
        } );

    } );
} );
<commit_msg>【desktop】desktop/js/main.js：应用全局配置文件<commit_after>/**
 * @fileOverview 应用入口
 * @author 吴钦飞(wuqf@pkusoft.net)
 * @module module:main
 * @requires jquery
 * @requires module:common/launchpad
 * @requires module:common/template
 * @requires module:common/app
 */
define( function ( require ) {
    var
        $ = require( "jquery" ),
        Launchpad = require( "./common/launchpad" ),
        App = require( "./common/app" ),
        Template = require( "template" ),
        AppSearch = require( "./common/app-search" ),
        AppSidebar = require( "./common/app-sidebar" ),
        menuSource = require( "./common/menuSource" )
    ;

    // 载入系统功能URL配置文件
    require( "./config/systemUrl" );

    // 载入全局设置的配置文件
    require( "./config/globalSetting" );

    if ( window.isIE8 ) {
        seajs.use( "./css/page/ie8-hack.css" );
    }

    // DOM树构建完毕后执行
    $( document ).ready( function () {

        // 启动 Launchpad
        Launchpad.init();

        // 启动 应用（App）系统
        App.init();

        // 启动搜索功能
        new AppSearch( {
            targetSelector: "#topbar-toolbar-search"
        } );

        // 启动应用侧边栏
        new AppSidebar( {
            toggleSelector: "#topbar-history",
            sidebarSelector: "#daSidebar",
            sidebarBodySelecotr: "#da-sidebar-body",
            oftenUsedUrl: "__CTX__/admin/oftenUsedSysMenu",
            recentUsedUrl: "__CTX__/admin/recentUsedSysMenu",
            saveUsedMenuUrl: "__CTX__/admin/saveUsedMenu",

            maxOftenUsedItemNum: 6,
            maxRecentUsedItemNum: 10
        } );

    } );
} );
<|endoftext|>