<commit_before>(function ( $ ) {

    /**
     * Holds google map object and related utility entities.
     * @constructor
     */
    function GMapContext(domElement, options) {
        var _map = new google.maps.Map(domElement, options);
        var _marker = new google.maps.Marker({
            position: new google.maps.LatLng(54.19335, -3.92695),
            map: _map,
            title: "Drag Me",
            draggable: options.draggable
        });
        return {
            map: _map,
            marker: _marker,
            circle: null,
            location: _marker.position,
            radius: options.radius,
            locationName: options.locationName,
            addressComponents: {
                formatted_address: null,
                addressLine1: null,
                addressLine2: null,
                streetName: null,
                streetNumber: null,
                city: null,
                district: null,
                state: null,
                stateOrProvince: null
            },
            settings: options.settings,
            domContainer: domElement,
            geodecoder: new google.maps.Geocoder()
        }
    }

    // Utility functions for Google Map Manipulations
    var GmUtility = {
        /**
         * Draw a circle over the the map. Returns circle object.
         * Also writes new circle object in gmapContext.
         *
         * @param center - LatLng of the center of the circle
         * @param radius - radius in meters
         * @param gmapContext - context
         * @param options
         */
        drawCircle: function(gmapContext, center, radius, options) {
            if (gmapContext.circle != null) {
                gmapContext.circle.setMap(null);
            }
            if (radius > 0) {
                radius *= 1;
                options = $.extend({
                    strokeColor: "#0000FF",
                    strokeOpacity: 0.35,
                    strokeWeight: 2,
                    fillColor: "#0000FF",
                    fillOpacity: 0.20
                }, options);
                options.map = gmapContext.map;
                options.radius = radius;
                options.center = center;
                gmapContext.circle = new google.maps.Circle(options);
                return gmapContext.circle;
            }
            return null;
        },
        /**
         *
         * @param gMapContext
         * @param location
         * @param callback
         */
        setPosition: function(gMapContext, location, callback) {
            gMapContext.location = location;
            gMapContext.marker.setPosition(location);
            gMapContext.map.panTo(location);
            this.drawCircle(gMapContext, location, gMapContext.radius, {});
            if (gMapContext.settings.enableReverseGeocode) {
                gMapContext.geodecoder.geocode({latLng: gMapContext.location}, function(results, status){
                    if (status == google.maps.GeocoderStatus.OK && results.length > 0){
                        gMapContext.locationName = results[0].formatted_address;
                        gMapContext.addressComponents =
                            GmUtility.address_component_from_google_geocode(results[0].address_components);
                    }
                    if (callback) {
                        callback.call(this, gMapContext);
                    }
                });
            } else {
                if (callback) {
                    callback.call(this, gMapContext);
                }
            }

        },
        locationFromLatLng: function(lnlg) {
            return {latitude: lnlg.lat(), longitude: lnlg.lng()}
        },
        address_component_from_google_geocode: function(address_components) {
            var result = {};
            for (var i = address_components.length-1; i>=0; i--) {
                var component = address_components[i];
                // Postal code
                if (component.types.indexOf('postal_code') >= 0) {
                    result.postalCode = component.short_name;
                }
                // Street number
                else if (component.types.indexOf('street_number') >= 0) {
                    result.streetNumber = component.short_name;
                }
                // Street name
                else if (component.types.indexOf('route') >= 0) {
                    result.streetName = component.short_name;
                }
                // City
                else if (component.types.indexOf('locality') >= 0) {
                    result.city = component.short_name;
                }
                // District
                else if (component.types.indexOf('sublocality') >= 0) {
                    result.district = component.short_name;
                }
                // State \ Province
                else if (component.types.indexOf('administrative_area_level_1') >= 0) {
                    result.stateOrProvince = component.short_name;
                }
                // State \ Province
                else if (component.types.indexOf('country') >= 0) {
                    result.country = component.short_name;
                }
            }
            result.addressLine1 = [result.streetNumber, result.streetName].join(' ').trim();
            result.addressLine2 = '';
            return result;
        }
    };

    function isPluginApplied(domObj) {
        return getContextForElement(domObj) != undefined;
    }

    function getContextForElement(domObj) {
        return $(domObj).data("locationpicker");
    }

    function updateInputValues(inputBinding, gmapContext){
        if (!inputBinding) return;
        var currentLocation = GmUtility.locationFromLatLng(gmapContext.location);
        if (inputBinding.latitudeInput) {
            inputBinding.latitudeInput.val(currentLocation.latitude).change();
        }
        if (inputBinding.longitudeInput) {
            inputBinding.longitudeInput.val(currentLocation.longitude).change();
        }
        if (inputBinding.radiusInput) {
            inputBinding.radiusInput.val(gmapContext.radius).change();
        }
        if (inputBinding.locationNameInput) {
            inputBinding.locationNameInput.val(gmapContext.locationName).change();
        }
    }

    function setupInputListenersInput(inputBinding, gmapContext) {
        if (inputBinding) {
            if (inputBinding.radiusInput){
                inputBinding.radiusInput.on("change", function(e) {
                    if (!e.originalEvent) { return }
                    gmapContext.radius = $(this).val();
                    GmUtility.setPosition(gmapContext, gmapContext.location, function(context){
                        context.settings.onchanged.apply(gmapContext.domContainer,
                            [GmUtility.locationFromLatLng(context.location), context.radius, false]);
                    });
                });
            }
            if (inputBinding.locationNameInput && gmapContext.settings.enableAutocomplete) {
                gmapContext.autocomplete = new google.maps.places.Autocomplete(inputBinding.locationNameInput.get(0));
                google.maps.event.addListener(gmapContext.autocomplete, 'place_changed', function() {
                    var place = gmapContext.autocomplete.getPlace();
                    if (!place.geometry) {
                        gmapContext.settings.onlocationnotfound(place.name);
                        return;
                    }
                    GmUtility.setPosition(gmapContext, place.geometry.location, function(context) {
                        updateInputValues(inputBinding, context);
                        context.settings.onchanged.apply(gmapContext.domContainer,
                            [GmUtility.locationFromLatLng(context.location), context.radius, false]);
                    });
                });
            }
            if (inputBinding.latitudeInput) {
                inputBinding.latitudeInput.on("change", function(e) {
                    if (!e.originalEvent) { return }
                    GmUtility.setPosition(gmapContext, new google.maps.LatLng($(this).val(), gmapContext.location.lng()), function(context){
                        context.settings.onchanged.apply(gmapContext.domContainer,
                            [GmUtility.locationFromLatLng(context.location), context.radius, false]);
                    });
                });
            }
            if (inputBinding.longitudeInput) {
                inputBinding.longitudeInput.on("change", function(e) {
                    if (!e.originalEvent) { return }
                    GmUtility.setPosition(gmapContext, new google.maps.LatLng(gmapContext.location.lat(), $(this).val()), function(context){
                        context.settings.onchanged.apply(gmapContext.domContainer,
                            [GmUtility.locationFromLatLng(context.location), context.radius, false]);
                    });
                });
            }
        }
    }

    /**
     * Initialization:
     *  $("#myMap").locationpicker(options);
     * @param options
     * @param params
     * @returns {*}
     */
    $.fn.locationpicker = function( options, params ) {
        if (typeof options == 'string') { // Command provided
            var _targetDomElement = this.get(0);
            // Plug-in is not applied - nothing to do.
            if (!isPluginApplied(_targetDomElement)) return;
            var gmapContext = getContextForElement(_targetDomElement);
            switch (options) {
                case "location":
                    if (params == undefined) { // Getter
                        var location = GmUtility.locationFromLatLng(gmapContext.location);
                        location.radius = gmapContext.radius;
                        location.name = gmapContext.locationName;
                        return location;
                    } else { // Setter
                        if (params.radius) {
                            gmapContext.radius = params.radius;
                        }
                        GmUtility.setPosition(gmapContext, new google.maps.LatLng(params.latitude, params.longitude), function(gmapContext) {
                            updateInputValues(gmapContext.settings.inputBinding, gmapContext);
                        });
                    }
                    break;
                case "subscribe":
                    /**
                     * Provides interface for subscribing for GoogleMap events.
                     * See Google API documentation for details.
                     * Parameters:
                     * - event: string, name of the event
                     * - callback: function, callback function to be invoked
                     */
                    if (params == undefined) { // Getter is not available
                        return null;
                    } else {
                        var event = params.event;
                        var callback = params.callback;
                        if (!event || ! callback) {
                            console.error("LocationPicker: Invalid arguments for method \"subscribe\"")
                            return null;
                        }
                        google.maps.event.addListener(gmapContext.map, event, callback);
                    }
                    break;
                case "map":
                    /**
                     * Returns object which allows access actual google widget and marker paced on it.
                     * Structure: {
                     *  map: Instance of the google map widget
                     *  marker: marker placed on map
                     * }
                     */
                    if (params == undefined) { // Getter is not available
                        var locationObj = GmUtility.locationFromLatLng(gmapContext.location);
                        locationObj.formattedAddress = gmapContext.locationName;
                        locationObj.addressComponents = gmapContext.addressComponents;
                        return {
                            map: gmapContext.map,
                            marker: gmapContext.marker,
                            location: locationObj
                        }
                    } else {
                        return null;
                    }
            }
            return null;
        }
        return this.each(function() {
            var $target = $(this);
            // If plug-in hasn't been applied before - initialize, otherwise - skip
            if (isPluginApplied(this)) return;
            // Plug-in initialization is required
            // Defaults
            var settings = $.extend({}, $.fn.locationpicker.defaults, options );
            // Initialize
            var gmapContext = new GMapContext(this, {
                zoom: settings.zoom,
                center: new google.maps.LatLng(settings.location.latitude, settings.location.longitude),
                mapTypeId: google.maps.MapTypeId.ROADMAP,
                mapTypeControl: false,
                disableDoubleClickZoom: false,
                scrollwheel: settings.scrollwheel,
                streetViewControl: false,
                radius: settings.radius,
                locationName: settings.locationName,
                settings: settings,
                draggable: settings.draggable
            });
            $target.data("locationpicker", gmapContext);
            // Subscribe GMap events
            google.maps.event.addListener(gmapContext.marker, "dragend", function(event) {
                GmUtility.setPosition(gmapContext, gmapContext.marker.position, function(context){
                    var currentLocation = GmUtility.locationFromLatLng(gmapContext.location);
                    context.settings.onchanged.apply(gmapContext.domContainer, [currentLocation, context.radius, true]);
                    updateInputValues(gmapContext.settings.inputBinding, gmapContext);
                });
            });
            GmUtility.setPosition(gmapContext, new google.maps.LatLng(settings.location.latitude, settings.location.longitude), function(context){
                updateInputValues(settings.inputBinding, gmapContext);
                var currentLocation = GmUtility.locationFromLatLng(gmapContext.location);
                //settings.onchanged.apply(gmapContext.domContainer, [currentLocation, context.radius, false]);
                // Set up input bindings if needed
                setupInputListenersInput(settings.inputBinding, gmapContext);
                context.settings.oninitialized($target);
            });
        });
    };
    $.fn.locationpicker.defaults = {
        location: {latitude: 40.7324319, longitude: -73.82480799999996},
        locationName: "",
        radius: 500,
        zoom: 15,
        scrollwheel: true,
        inputBinding: {
            latitudeInput: null,
            longitudeInput: null,
            radiusInput: null,
            locationNameInput: null
        },
        enableAutocomplete: false,
        enableReverseGeocode: true,
        draggable: true,
        onchanged: function(currentLocation, radius, isMarkerDropped) {},
        onlocationnotfound: function(locationName) {},
        oninitialized: function (component) {}

    }

}( jQuery ));
<commit_msg>Added autosize method<commit_after>(function ( $ ) {

    /**
     * Holds google map object and related utility entities.
     * @constructor
     */
    function GMapContext(domElement, options) {
        var _map = new google.maps.Map(domElement, options);
        var _marker = new google.maps.Marker({
            position: new google.maps.LatLng(54.19335, -3.92695),
            map: _map,
            title: "Drag Me",
            draggable: options.draggable
        });
        return {
            map: _map,
            marker: _marker,
            circle: null,
            location: _marker.position,
            radius: options.radius,
            locationName: options.locationName,
            addressComponents: {
                formatted_address: null,
                addressLine1: null,
                addressLine2: null,
                streetName: null,
                streetNumber: null,
                city: null,
                district: null,
                state: null,
                stateOrProvince: null
            },
            settings: options.settings,
            domContainer: domElement,
            geodecoder: new google.maps.Geocoder()
        }
    }

    // Utility functions for Google Map Manipulations
    var GmUtility = {
        /**
         * Draw a circle over the the map. Returns circle object.
         * Also writes new circle object in gmapContext.
         *
         * @param center - LatLng of the center of the circle
         * @param radius - radius in meters
         * @param gmapContext - context
         * @param options
         */
        drawCircle: function(gmapContext, center, radius, options) {
            if (gmapContext.circle != null) {
                gmapContext.circle.setMap(null);
            }
            if (radius > 0) {
                radius *= 1;
                options = $.extend({
                    strokeColor: "#0000FF",
                    strokeOpacity: 0.35,
                    strokeWeight: 2,
                    fillColor: "#0000FF",
                    fillOpacity: 0.20
                }, options);
                options.map = gmapContext.map;
                options.radius = radius;
                options.center = center;
                gmapContext.circle = new google.maps.Circle(options);
                return gmapContext.circle;
            }
            return null;
        },
        /**
         *
         * @param gMapContext
         * @param location
         * @param callback
         */
        setPosition: function(gMapContext, location, callback) {
            gMapContext.location = location;
            gMapContext.marker.setPosition(location);
            gMapContext.map.panTo(location);
            this.drawCircle(gMapContext, location, gMapContext.radius, {});
            if (gMapContext.settings.enableReverseGeocode) {
                gMapContext.geodecoder.geocode({latLng: gMapContext.location}, function(results, status){
                    if (status == google.maps.GeocoderStatus.OK && results.length > 0){
                        gMapContext.locationName = results[0].formatted_address;
                        gMapContext.addressComponents =
                            GmUtility.address_component_from_google_geocode(results[0].address_components);
                    }
                    if (callback) {
                        callback.call(this, gMapContext);
                    }
                });
            } else {
                if (callback) {
                    callback.call(this, gMapContext);
                }
            }

        },
        locationFromLatLng: function(lnlg) {
            return {latitude: lnlg.lat(), longitude: lnlg.lng()}
        },
        address_component_from_google_geocode: function(address_components) {
            var result = {};
            for (var i = address_components.length-1; i>=0; i--) {
                var component = address_components[i];
                // Postal code
                if (component.types.indexOf('postal_code') >= 0) {
                    result.postalCode = component.short_name;
                }
                // Street number
                else if (component.types.indexOf('street_number') >= 0) {
                    result.streetNumber = component.short_name;
                }
                // Street name
                else if (component.types.indexOf('route') >= 0) {
                    result.streetName = component.short_name;
                }
                // City
                else if (component.types.indexOf('locality') >= 0) {
                    result.city = component.short_name;
                }
                // District
                else if (component.types.indexOf('sublocality') >= 0) {
                    result.district = component.short_name;
                }
                // State \ Province
                else if (component.types.indexOf('administrative_area_level_1') >= 0) {
                    result.stateOrProvince = component.short_name;
                }
                // State \ Province
                else if (component.types.indexOf('country') >= 0) {
                    result.country = component.short_name;
                }
            }
            result.addressLine1 = [result.streetNumber, result.streetName].join(' ').trim();
            result.addressLine2 = '';
            return result;
        }
    };

    function isPluginApplied(domObj) {
        return getContextForElement(domObj) != undefined;
    }

    function getContextForElement(domObj) {
        return $(domObj).data("locationpicker");
    }

    function updateInputValues(inputBinding, gmapContext){
        if (!inputBinding) return;
        var currentLocation = GmUtility.locationFromLatLng(gmapContext.location);
        if (inputBinding.latitudeInput) {
            inputBinding.latitudeInput.val(currentLocation.latitude).change();
        }
        if (inputBinding.longitudeInput) {
            inputBinding.longitudeInput.val(currentLocation.longitude).change();
        }
        if (inputBinding.radiusInput) {
            inputBinding.radiusInput.val(gmapContext.radius).change();
        }
        if (inputBinding.locationNameInput) {
            inputBinding.locationNameInput.val(gmapContext.locationName).change();
        }
    }

    function setupInputListenersInput(inputBinding, gmapContext) {
        if (inputBinding) {
            if (inputBinding.radiusInput){
                inputBinding.radiusInput.on("change", function(e) {
                    if (!e.originalEvent) { return }
                    gmapContext.radius = $(this).val();
                    GmUtility.setPosition(gmapContext, gmapContext.location, function(context){
                        context.settings.onchanged.apply(gmapContext.domContainer,
                            [GmUtility.locationFromLatLng(context.location), context.radius, false]);
                    });
                });
            }
            if (inputBinding.locationNameInput && gmapContext.settings.enableAutocomplete) {
                gmapContext.autocomplete = new google.maps.places.Autocomplete(inputBinding.locationNameInput.get(0));
                google.maps.event.addListener(gmapContext.autocomplete, 'place_changed', function() {
                    var place = gmapContext.autocomplete.getPlace();
                    if (!place.geometry) {
                        gmapContext.settings.onlocationnotfound(place.name);
                        return;
                    }
                    GmUtility.setPosition(gmapContext, place.geometry.location, function(context) {
                        updateInputValues(inputBinding, context);
                        context.settings.onchanged.apply(gmapContext.domContainer,
                            [GmUtility.locationFromLatLng(context.location), context.radius, false]);
                    });
                });
            }
            if (inputBinding.latitudeInput) {
                inputBinding.latitudeInput.on("change", function(e) {
                    if (!e.originalEvent) { return }
                    GmUtility.setPosition(gmapContext, new google.maps.LatLng($(this).val(), gmapContext.location.lng()), function(context){
                        context.settings.onchanged.apply(gmapContext.domContainer,
                            [GmUtility.locationFromLatLng(context.location), context.radius, false]);
                    });
                });
            }
            if (inputBinding.longitudeInput) {
                inputBinding.longitudeInput.on("change", function(e) {
                    if (!e.originalEvent) { return }
                    GmUtility.setPosition(gmapContext, new google.maps.LatLng(gmapContext.location.lat(), $(this).val()), function(context){
                        context.settings.onchanged.apply(gmapContext.domContainer,
                            [GmUtility.locationFromLatLng(context.location), context.radius, false]);
                    });
                });
            }
        }
    }

    function autosize(gmapContext) {
        google.maps.event.trigger(gmapContext.map, 'resize');
        setTimeout(function() {
            gmapContext.map.setCenter(gmapContext.marker.position);
        }, 300);
    }

    /**
     * Initialization:
     *  $("#myMap").locationpicker(options);
     * @param options
     * @param params
     * @returns {*}
     */
    $.fn.locationpicker = function( options, params ) {
        if (typeof options == 'string') { // Command provided
            var _targetDomElement = this.get(0);
            // Plug-in is not applied - nothing to do.
            if (!isPluginApplied(_targetDomElement)) return;
            var gmapContext = getContextForElement(_targetDomElement);
            switch (options) {
                case "location":
                    if (params == undefined) { // Getter
                        var location = GmUtility.locationFromLatLng(gmapContext.location);
                        location.radius = gmapContext.radius;
                        location.name = gmapContext.locationName;
                        return location;
                    } else { // Setter
                        if (params.radius) {
                            gmapContext.radius = params.radius;
                        }
                        GmUtility.setPosition(gmapContext, new google.maps.LatLng(params.latitude, params.longitude), function(gmapContext) {
                            updateInputValues(gmapContext.settings.inputBinding, gmapContext);
                        });
                    }
                    break;
                case "subscribe":
                    /**
                     * Provides interface for subscribing for GoogleMap events.
                     * See Google API documentation for details.
                     * Parameters:
                     * - event: string, name of the event
                     * - callback: function, callback function to be invoked
                     */
                    if (params == undefined) { // Getter is not available
                        return null;
                    } else {
                        var event = params.event;
                        var callback = params.callback;
                        if (!event || ! callback) {
                            console.error("LocationPicker: Invalid arguments for method \"subscribe\"")
                            return null;
                        }
                        google.maps.event.addListener(gmapContext.map, event, callback);
                    }
                    break;
                case "map":
                    /**
                     * Returns object which allows access actual google widget and marker paced on it.
                     * Structure: {
                     *  map: Instance of the google map widget
                     *  marker: marker placed on map
                     * }
                     */
                    if (params == undefined) { // Getter
                        var locationObj = GmUtility.locationFromLatLng(gmapContext.location);
                        locationObj.formattedAddress = gmapContext.locationName;
                        locationObj.addressComponents = gmapContext.addressComponents;
                        return {
                            map: gmapContext.map,
                            marker: gmapContext.marker,
                            location: locationObj
                        }
                    } else { // Setter is not available
                        return null;
                    }
                case "autosize":
                    autosize(gmapContext);
                    return this;
            }
            return null;
        }
        return this.each(function() {
            var $target = $(this);
            // If plug-in hasn't been applied before - initialize, otherwise - skip
            if (isPluginApplied(this)) return;
            // Plug-in initialization is required
            // Defaults
            var settings = $.extend({}, $.fn.locationpicker.defaults, options );
            // Initialize
            var gmapContext = new GMapContext(this, {
                zoom: settings.zoom,
                center: new google.maps.LatLng(settings.location.latitude, settings.location.longitude),
                mapTypeId: google.maps.MapTypeId.ROADMAP,
                mapTypeControl: false,
                disableDoubleClickZoom: false,
                scrollwheel: settings.scrollwheel,
                streetViewControl: false,
                radius: settings.radius,
                locationName: settings.locationName,
                settings: settings,
                draggable: settings.draggable
            });
            $target.data("locationpicker", gmapContext);
            // Subscribe GMap events
            google.maps.event.addListener(gmapContext.marker, "dragend", function(event) {
                GmUtility.setPosition(gmapContext, gmapContext.marker.position, function(context){
                    var currentLocation = GmUtility.locationFromLatLng(gmapContext.location);
                    context.settings.onchanged.apply(gmapContext.domContainer, [currentLocation, context.radius, true]);
                    updateInputValues(gmapContext.settings.inputBinding, gmapContext);
                });
            });
            GmUtility.setPosition(gmapContext, new google.maps.LatLng(settings.location.latitude, settings.location.longitude), function(context){
                updateInputValues(settings.inputBinding, gmapContext);
                // Set up input bindings if needed
                setupInputListenersInput(settings.inputBinding, gmapContext);
                context.settings.oninitialized($target);
            });
        });
    };
    $.fn.locationpicker.defaults = {
        location: {latitude: 40.7324319, longitude: -73.82480799999996},
        locationName: "",
        radius: 500,
        zoom: 15,
        scrollwheel: true,
        inputBinding: {
            latitudeInput: null,
            longitudeInput: null,
            radiusInput: null,
            locationNameInput: null
        },
        enableAutocomplete: false,
        enableReverseGeocode: true,
        draggable: true,
        onchanged: function(currentLocation, radius, isMarkerDropped) {},
        onlocationnotfound: function(locationName) {},
        oninitialized: function (component) {}

    }

}( jQuery ));
<|endoftext|>


<commit_before>var Tooltip = function()
{
    var tooltip

    var _template = function(d)
    {
        return d.title
    }

    function _move()
    {
        tooltip
            .style('left', (d3.event.pageX) + 'px')
            .style('top', (d3.event.pageY - 28) + 'px')
    }

    var publicSpace = {
        init: function(custom_template)
        {
            tooltip = d3.select('body')
                .append('div')
                .attr('class', 'tooltip')
                .style('opacity', 0)
                .style('pointer-events', 'none')
            if(custom_template !== undefined)
            {
                _template = custom_template
            }
        },
        show: function(d)
        {
            tooltip.transition()
                .duration(50)
                .style('opacity', 1)
            tooltip.html(_template(d))
            _move()
        },
        hide: function()
        {
            tooltip.transition()
                .duration(200)
                .style('opacity', 0)
        },
        move: _move
    }

    return publicSpace
}

var NeedlePlot = function ()
{
    var svg, zoom, vis, vertical_scalable, unit
    var scale = 1
	var position = 0
    var height_unit

    var legend = {
        x:
        {
            obj: null
        },
        y:
        {
            obj: null
        }
    }

    var Axis = function()
    {
        return {
            scale: null,
            group: null,
            obj: null
        }
    }

    var axes = {
        x: new Axis(),
        y: new Axis()
    }

    var config = {
        site_height: 10,
        animations_speed: 200,
        // 90 is width of description
        paddings: {bottom: 30, top: 30, left: 89, right: 1},
        y_scale: 'auto',
        sequenceLength: null,
        element: null,
        mutations: null,
        sites: null,
        needles: null,
        legends: {x: 'Sequence', y: '# of mutations'},
        width: 600,
        height: null,
        zoom_callback: null,
        position_callback: null,
        ratio: 0.5,
        min_zoom: 1,
        max_zoom: 10,
        color_map: {
          'distant': 'yellow',
          'network-rewiring': 'red',
          'direct': 'darkred',
          'proximal': 'orange',
          'none': 'darkgray'
        }
    }

	function get_remote_if_needed(new_config, name)
	{
        if(typeof new_config[name] === 'string')
        {
			$.ajax({
				url: new_config[name],
				type: 'GET',
				async: false,
				success: function(data)
				{
					new_config[name] = data
				}
			})
        }
	}

    function _adjustPlotDimensions()
    {
        if(!config.width && !config.height)
        {
            config.width = config.sequenceLength
        }

        if(config.height && config.width)
        {
            config.ratio = config.height / config.width
        }
        else if(!config.height)
        {
            config.height = config.width * config.ratio
        }
        else if(!config.width)
        {
            config.height = config.width * config.ratio
        }
    }

    function configure(new_config)
    {
		var allowed_remote_data = ['mutations', 'sites']

		for(var i = 0; i < allowed_remote_data.length; i++)
		{
			var name = allowed_remote_data[i]
			get_remote_if_needed(new_config, name)
		}

        // Automatical configuration update:
        update_object(config, new_config)

        // Manual configuration patching:
        _adjustPlotDimensions()

    }

    function scaleToNeedles()
    {
		if (config.y_scale === 'auto')
		{
            max = 0
            muts = config.mutations
            for(var i = 0; i < muts.length; i++)
            {
                max = Math.max(max, muts[i].value)
            }
			config.y_scale = max * 5 / 4
		}
    }

    function _rescalePlot()
    {
        svg
            .attr('viewBox', '0 0 ' + config.width + ' ' + config.height)

		unit = (config.width - config.paddings.left - config.paddings.right) / config.sequenceLength

        axes.x.scale
            .range([0, config.width - config.paddings.left - config.paddings.right])

        axes.y.scale
            .range([config.height - config.paddings.top, config.paddings.bottom])

        height_unit = (config.height - config.paddings.bottom - config.paddings.top) / config.y_scale

        axes.y.obj.scale(axes.y.scale)
        axes.y.group.call(axes.y.obj)

		var bottom_axis_pos = config.height - config.paddings.bottom

        axes.x.obj.scale(axes.x.scale)
        axes.x.group
	        .attr('transform', 'translate(0, ' + bottom_axis_pos + ')')
            .call(axes.x.obj)

        sites
            .attr('transform', function(d)
                {
                    return 'translate(' + [posToX(d.start), bottom_axis_pos - config.site_height] + ')'
                }
            )

        site_boxes
			.attr('width', function(d){ return posToX(d.end - d.start) })

        needles
            .attr('transform', function(d)
                {
                    return 'translate(' + [posToX(d.coord), bottom_axis_pos] + ')'
                }
            )

        needles.selectAll('line')
            .attr('stroke-width', posToX(1) / 2 + 'px')
            .attr('y1', function(d){ return -d.value * height_unit + 'px' })

        needles.selectAll('circle')
            .attr('transform', function(d){ return 'translate('  + [0, -d.value * height_unit] + ')scale(1, '+ scale +') ' })
            .attr('r', posToX(1) / 2 + 'px')

        leftPadding.attr('height', config.height)

        if(legend.x.obj)
            legend.x.obj.attr('x', config.width / 2)
        if(legend.y.obj)
            legend.y.obj.attr('transform','translate(' + -40 + ' ' + config.height / 2 + ') rotate(-90)')
    }

    function createPlot()
    {
        zoom = d3.behavior.zoom()
            .scaleExtent([config.min_zoom, config.max_zoom])
            .on('zoom', zoomAndMove)

        svg = d3.select(config.element).append('svg')
            .attr('preserveAspectRatio', 'xMinYMin meet')
            .attr('class', 'svg-content-responsive')
            .call(zoom)

		paddings = svg.append('g')
			.attr('class', 'paddings')
			.attr('transform', 'translate(' + config.paddings.left + ' , 0)')

		vertical_scalable = paddings.append('g')
			.attr('class', 'vertical scalable')

        leftPadding = paddings.append('rect')
            .attr('fill', 'white')
            .attr('width', config.paddings.left)
			.attr('transform', 'translate(-' + config.paddings.left + ' , 0)')

        axes.y.scale = d3.scale.linear()
            .domain([0, config.y_scale])

        axes.y.obj = d3.svg.axis()
            .orient('left')
            .scale(axes.y.scale)
            // TODO
			.tickFormat(d3.format('d'))
            .tickSubdivide(0)

        axes.y.group = paddings.append('g')
			.attr('class', 'y axis')
            .call(axes.y.obj)

        axes.x.scale = d3.scale.linear()
            .domain([0, config.sequenceLength])

        axes.x.obj = d3.svg.axis()
            .orient('bottom')
            .scale(axes.x.scale)

        axes.x.group = paddings.append('g')
			.attr('class', 'x axis')
            .call(axes.x.obj)

        vis = vertical_scalable.append('g')

        if(config.legends.x)
        {
            legend.x.obj = paddings.append('text')
                .attr('class', 'label')
                .text(config.legends.x)
                .attr('x', config.width / 2)
                .attr('y', config.height - config.paddings.bottom)
                .attr('dy','2.4em')
                .style('text-anchor','middle')
        }

        if(config.legends.y)
        {
            legend.y.obj = paddings.append('text')
                .attr('class', 'label')
                .text(config.legends.y)
                .style('text-anchor','middle')
        }

        var needle_tooltip = Tooltip()
        needle_tooltip.init(function(d){
            return d.category + '
' + d.coord
        })

        needles = vis.selectAll('.needle')
            .data(config.mutations)
            .enter()
            .append('g')
            .attr('class', 'needle')
            .on('mouseover', needle_tooltip.show)
            .on('mousemove', needle_tooltip.move)
            .on('mouseout', needle_tooltip.hide)

        needles
            .append('line')
                .attr('x1', 0)
                .attr('x2', 0)
                .attr('y2', 0)

        needles
            .append('circle')
                .attr('fill', function(d)
                    {
                        return config.color_map[d.category]
                    }
                )

        var site_tooltip = Tooltip()
        site_tooltip.init(function(d){
            return d.type + '
' + (d.start + 7)
        })

        sites = vis.selectAll('.site')
            .data(config.sites)
            .enter()
            .append('g')
            .attr('class', 'site')
            .on('mouseover', site_tooltip.show)
            .on('mousemove', site_tooltip.move)
            .on('mouseout', site_tooltip.hide)

        site_boxes = sites
			.append('rect')
			.attr('height', config.site_height)
            .attr('class', function(d)
                {
                    if(d.type.indexOf(',') == -1)
                        return d.type
                    else
                        return 'multi_ptm'
                }
            )

        _rescalePlot()

    }

	function _setPosition(new_position, stop_callback)
	{
        var axis_coverage = xAxisCoverage()
		var boundary = posToX(axis_coverage - config.sequenceLength) * scale

		if(new_position > 0)
			position = 0
		else if(new_position < boundary)
			position = boundary
		else
			position = new_position

        // let d3 know that we changed the position
        zoom.translate([position, 0])

        if(!stop_callback && config.position_callback)
        {
            aa_position = xToPos(position)
            config.position_callback(aa_position, true)
        }
	}

    function canvasAnimated(animate)
    {
        if(animate)
        {
		    t = svg
			    .transition().ease('quad').duration(config.animations_speed)
        }
        else
        {
            t = svg
        }
        return t
    }

    function adjustContent(animate)
    {
        var canvas = canvasAnimated(animate)
		canvas.select('.vertical.scalable').attr('transform', 'translate(' + position + ', 0)scale(' + scale + ', 1)')

        needles.selectAll('circle')
            .attr('transform', function(d){ return 'translate('  + [0, -d.value * height_unit] + ')scale(1, '+ scale +') ' })

        site_boxes.
            attr('stroke-width', 1/scale + 'px')
    }

    function xAxisCoverage()
    {
        return config.sequenceLength / scale
    }

	function posToX(pos)
	{
		return pos * unit
	}

    function xToPos(coord)
    {
        return -(coord / unit) / scale
    }

    function adjustXAxis(animate)
    {
        var canvas = canvasAnimated(animate)
        var axis_coverage = xAxisCoverage()
        var start = xToPos(position)
		axes.x.scale.domain([start, start + axis_coverage])
		canvas.select('.x.axis').call(axes.x.obj)
    }

    function refresh(animate)
    {
        adjustXAxis(animate)
        adjustContent(animate)
    }

    function zoomAndMove()
    {
		_setZoomAndMove(d3.event.scale, d3.event.translate[0])
    }

    function _setZoomAndMove(new_scale, new_position, animate)
    {
		_setZoom(new_scale)
		_setPosition(new_position)

        refresh(animate)
    }

	function _setZoom(new_scale, stop_callback)
	{
        if(scale === new_scale)
            return

		scale = new_scale

        // if we have a callback, release it (unless explicitly asked to refrain)
        if(!stop_callback && config.zoom_callback)
        {
            config.zoom_callback(scale, true)
        }
        // if we are not issung a callback, that the function was called by callback,
        // then we want to assure that all related components are aware of zoom update
        else
        {
            // let d3 know that the zoom was changed
			zoom.scale(scale)

            // recalculate position so we do not exceed boundaries
            _setPosition(position)

            // adjust axes
            refresh(true)
        }

	}

    var publicSpace = {
        init: function(new_config)
        {
            configure(new_config)
			scaleToNeedles()
            createPlot()

        },
        setZoom: _setZoom,
		setPosition: _setPosition,
        setAAPosition: function(aa_position, stop_callback, animate)
        {
            var converted_position = posToX(-aa_position) * scale
            _setPosition(converted_position, stop_callback)
            refresh(animate)
        },
        setSize: function(width, height)
        {
            config.width = width
            config.height = height

            _adjustPlotDimensions()

            _rescalePlot()

            // refresh zoom and position with current values
            _setZoomAndMove(scale, position, true)
        }
    }

    return publicSpace
}
<commit_msg>Improve tooltip code quality<commit_after>var Tooltip = function()
{
    var tooltip

    var _template = function(d)
    {
        return d.title
    }

    var publicSpace = {
        init: function(custom_template)
        {
            tooltip = d3.select('body')
                .append('div')
                .attr('class', 'tooltip')
                .style('opacity', 0)
                .style('pointer-events', 'none')
            if(custom_template !== undefined)
            {
                _template = custom_template
            }
        },
        show: function(d)
        {
            tooltip.transition()
                .duration(50)
                .style('opacity', 1)
            tooltip.html(_template(d))
            publicSpace.move()
        },
        hide: function()
        {
            tooltip.transition()
                .duration(200)
                .style('opacity', 0)
        },
        move: function()
        {
            tooltip
                .style('left', (d3.event.pageX) + 'px')
                .style('top', (d3.event.pageY - 28) + 'px')
        },
        bind: function(selection)
        {
            selection
                .on('mouseover', publicSpace.show)
                .on('mousemove', publicSpace.move)
                .on('mouseout', publicSpace.hide)
        }
    }

    return publicSpace
}

var NeedlePlot = function ()
{
    var svg, zoom, vis, vertical_scalable, unit
    var scale = 1
	var position = 0
    var height_unit

    var legend = {
        x:
        {
            obj: null
        },
        y:
        {
            obj: null
        }
    }

    var Axis = function()
    {
        return {
            scale: null,
            group: null,
            obj: null
        }
    }

    var axes = {
        x: new Axis(),
        y: new Axis()
    }

    var config = {
        site_height: 10,
        animations_speed: 200,
        // 90 is width of description
        paddings: {bottom: 30, top: 30, left: 89, right: 1},
        y_scale: 'auto',
        sequenceLength: null,
        element: null,
        mutations: null,
        sites: null,
        needles: null,
        legends: {x: 'Sequence', y: '# of mutations'},
        width: 600,
        height: null,
        zoom_callback: null,
        position_callback: null,
        ratio: 0.5,
        min_zoom: 1,
        max_zoom: 10,
        color_map: {
          'distant': 'yellow',
          'network-rewiring': 'red',
          'direct': 'darkred',
          'proximal': 'orange',
          'none': 'darkgray'
        }
    }

	function get_remote_if_needed(new_config, name)
	{
        if(typeof new_config[name] === 'string')
        {
			$.ajax({
				url: new_config[name],
				type: 'GET',
				async: false,
				success: function(data)
				{
					new_config[name] = data
				}
			})
        }
	}

    function _adjustPlotDimensions()
    {
        if(!config.width && !config.height)
        {
            config.width = config.sequenceLength
        }

        if(config.height && config.width)
        {
            config.ratio = config.height / config.width
        }
        else if(!config.height)
        {
            config.height = config.width * config.ratio
        }
        else if(!config.width)
        {
            config.height = config.width * config.ratio
        }
    }

    function configure(new_config)
    {
		var allowed_remote_data = ['mutations', 'sites']

		for(var i = 0; i < allowed_remote_data.length; i++)
		{
			var name = allowed_remote_data[i]
			get_remote_if_needed(new_config, name)
		}

        // Automatical configuration update:
        update_object(config, new_config)

        // Manual configuration patching:
        _adjustPlotDimensions()

    }

    function scaleToNeedles()
    {
		if (config.y_scale === 'auto')
		{
            max = 0
            muts = config.mutations
            for(var i = 0; i < muts.length; i++)
            {
                max = Math.max(max, muts[i].value)
            }
			config.y_scale = max * 5 / 4
		}
    }

    function _rescalePlot()
    {
        svg
            .attr('viewBox', '0 0 ' + config.width + ' ' + config.height)

		unit = (config.width - config.paddings.left - config.paddings.right) / config.sequenceLength

        axes.x.scale
            .range([0, config.width - config.paddings.left - config.paddings.right])

        axes.y.scale
            .range([config.height - config.paddings.top, config.paddings.bottom])

        height_unit = (config.height - config.paddings.bottom - config.paddings.top) / config.y_scale

        axes.y.obj.scale(axes.y.scale)
        axes.y.group.call(axes.y.obj)

		var bottom_axis_pos = config.height - config.paddings.bottom

        axes.x.obj.scale(axes.x.scale)
        axes.x.group
	        .attr('transform', 'translate(0, ' + bottom_axis_pos + ')')
            .call(axes.x.obj)

        sites
            .attr('transform', function(d)
                {
                    return 'translate(' + [posToX(d.start), bottom_axis_pos - config.site_height] + ')'
                }
            )

        site_boxes
			.attr('width', function(d){ return posToX(d.end - d.start) })

        needles
            .attr('transform', function(d)
                {
                    return 'translate(' + [posToX(d.coord), bottom_axis_pos] + ')'
                }
            )

        needles.selectAll('line')
            .attr('stroke-width', posToX(1) / 2 + 'px')
            .attr('y1', function(d){ return -d.value * height_unit + 'px' })

        needles.selectAll('circle')
            .attr('transform', function(d){ return 'translate('  + [0, -d.value * height_unit] + ')scale(1, '+ scale +') ' })
            .attr('r', posToX(1) / 2 + 'px')

        leftPadding.attr('height', config.height)

        if(legend.x.obj)
            legend.x.obj.attr('x', config.width / 2)
        if(legend.y.obj)
            legend.y.obj.attr('transform','translate(' + -40 + ' ' + config.height / 2 + ') rotate(-90)')
    }

    function append_group(selection, class_name)
    {
        selection
            .append('g')
            .attr('class', class_name)
    }

    function createPlot()
    {
        zoom = d3.behavior.zoom()
            .scaleExtent([config.min_zoom, config.max_zoom])
            .on('zoom', zoomAndMove)

        svg = d3.select(config.element).append('svg')
            .attr('preserveAspectRatio', 'xMinYMin meet')
            .attr('class', 'svg-content-responsive')
            .call(zoom)

		paddings = svg.append('g')
			.attr('class', 'paddings')
			.attr('transform', 'translate(' + config.paddings.left + ' , 0)')

		vertical_scalable = paddings.append('g')
			.attr('class', 'vertical scalable')

        leftPadding = paddings.append('rect')
            .attr('fill', 'white')
            .attr('width', config.paddings.left)
			.attr('transform', 'translate(-' + config.paddings.left + ' , 0)')

        axes.y.scale = d3.scale.linear()
            .domain([0, config.y_scale])

        axes.y.obj = d3.svg.axis()
            .orient('left')
            .scale(axes.y.scale)
            // TODO
			.tickFormat(d3.format('d'))
            .tickSubdivide(0)

        axes.y.group = paddings.append('g')
			.attr('class', 'y axis')
            .call(axes.y.obj)

        axes.x.scale = d3.scale.linear()
            .domain([0, config.sequenceLength])

        axes.x.obj = d3.svg.axis()
            .orient('bottom')
            .scale(axes.x.scale)

        axes.x.group = paddings.append('g')
			.attr('class', 'x axis')
            .call(axes.x.obj)

        vis = vertical_scalable.append('g')

        if(config.legends.x)
        {
            legend.x.obj = paddings.append('text')
                .attr('class', 'label')
                .text(config.legends.x)
                .attr('x', config.width / 2)
                .attr('y', config.height - config.paddings.bottom)
                .attr('dy','2.4em')
                .style('text-anchor','middle')
        }

        if(config.legends.y)
        {
            legend.y.obj = paddings.append('text')
                .attr('class', 'label')
                .text(config.legends.y)
                .style('text-anchor','middle')
        }

        var needle_tooltip = Tooltip()
        needle_tooltip.init(function(d){
            return d.category + '
' + d.coord
        })

        needles = vis.selectAll('.needle')
            .data(config.mutations)
            .enter()
            .append('g')
            .attr('class', 'needle')
            .call(needle_tooltip.bind)

        needles
            .append('line')
                .attr('x1', 0)
                .attr('x2', 0)
                .attr('y2', 0)

        needles
            .append('circle')
                .attr('fill', function(d)
                    {
                        return config.color_map[d.category]
                    }
                )

        var site_tooltip = Tooltip()
        site_tooltip.init(function(d){
            return d.type + '
' + (d.start + 7)
        })

        sites = vis.selectAll('.site')
            .data(config.sites)
            .enter()
            .append('g')
            .attr('class', 'site')
            .call(site_tooltip.bind)

        site_boxes = sites
			.append('rect')
			.attr('height', config.site_height)
            .attr('class', function(d)
                {
                    if(d.type.indexOf(',') === -1)
                        return d.type
                    else
                        return 'multi_ptm'
                }
            )

        _rescalePlot()

    }

	function _setPosition(new_position, stop_callback)
	{
        var axis_coverage = xAxisCoverage()
		var boundary = posToX(axis_coverage - config.sequenceLength) * scale

		if(new_position > 0)
			position = 0
		else if(new_position < boundary)
			position = boundary
		else
			position = new_position

        // let d3 know that we changed the position
        zoom.translate([position, 0])

        if(!stop_callback && config.position_callback)
        {
            aa_position = xToPos(position)
            config.position_callback(aa_position, true)
        }
	}

    function canvasAnimated(animate)
    {
        if(animate)
        {
		    t = svg
			    .transition().ease('quad').duration(config.animations_speed)
        }
        else
        {
            t = svg
        }
        return t
    }

    function adjustContent(animate)
    {
        var canvas = canvasAnimated(animate)
		canvas.select('.vertical.scalable').attr('transform', 'translate(' + position + ', 0)scale(' + scale + ', 1)')

        needles.selectAll('circle')
            .attr('transform', function(d){ return 'translate('  + [0, -d.value * height_unit] + ')scale(1, '+ scale +') ' })

        site_boxes.
            attr('stroke-width', 1/scale + 'px')
    }

    function xAxisCoverage()
    {
        return config.sequenceLength / scale
    }

	function posToX(pos)
	{
		return pos * unit
	}

    function xToPos(coord)
    {
        return -(coord / unit) / scale
    }

    function adjustXAxis(animate)
    {
        var canvas = canvasAnimated(animate)
        var axis_coverage = xAxisCoverage()
        var start = xToPos(position)
		axes.x.scale.domain([start, start + axis_coverage])
		canvas.select('.x.axis').call(axes.x.obj)
    }

    function refresh(animate)
    {
        adjustXAxis(animate)
        adjustContent(animate)
    }

    function zoomAndMove()
    {
		_setZoomAndMove(d3.event.scale, d3.event.translate[0])
    }

    function _setZoomAndMove(new_scale, new_position, animate)
    {
		_setZoom(new_scale)
		_setPosition(new_position)

        refresh(animate)
    }

	function _setZoom(new_scale, stop_callback)
	{
        if(scale === new_scale)
            return

		scale = new_scale

        // if we have a callback, release it (unless explicitly asked to refrain)
        if(!stop_callback && config.zoom_callback)
        {
            config.zoom_callback(scale, true)
        }
        // if we are not issung a callback, that the function was called by callback,
        // then we want to assure that all related components are aware of zoom update
        else
        {
            // let d3 know that the zoom was changed
			zoom.scale(scale)

            // recalculate position so we do not exceed boundaries
            _setPosition(position)

            // adjust axes
            refresh(true)
        }

	}

    var publicSpace = {
        init: function(new_config)
        {
            configure(new_config)
			scaleToNeedles()
            createPlot()

        },
        setZoom: _setZoom,
		setPosition: _setPosition,
        setAAPosition: function(aa_position, stop_callback, animate)
        {
            var converted_position = posToX(-aa_position) * scale
            _setPosition(converted_position, stop_callback)
            refresh(animate)
        },
        setSize: function(width, height)
        {
            config.width = width
            config.height = height

            _adjustPlotDimensions()

            _rescalePlot()

            // refresh zoom and position with current values
            _setZoomAndMove(scale, position, true)
        }
    }

    return publicSpace
}
<|endoftext|>


<commit_before>const fs = require('fs');
const moment = require('moment');
const sql = require('sql.js');

const slurp = fn => {
    return fs.readFileSync(fn, {
        encoding: 'utf8'
    });
};

const slurpJson = fn => {
    return JSON.parse(slurp(fn));
};

const toPersonId = (obj, nameToId) => {
    if (typeof obj === 'number' && Object.values(nameToId).includes(obj)) {
        return obj;
    }

    if (typeof obj === 'string' && typeof nameToId[obj] === 'number') {
        return nameToId[obj];
    }

    if (typeof obj === 'object') {
        if (typeof obj.id === 'number') {
            return toPersonId(obj.id);
        }

        if (typeof obj.name === 'string') {
            return toPersonId(obj.name);
        }
    }

    throw {
        'error': `Could not get person ID for ${obj}`,
    };
};

const getProductionId = (date, location, productions) => {
    let _ = (column) => {
        return productions[0]['columns'].indexOf(column);
    };

    let options = [];
    for (let i = 0; i < productions[0]['values'].length; i++) {
        const production = productions[0]['values'][i];

        if (location && production[_('LOCATION')] !== location) {
            continue;
        }

        let startDate = moment(production[_('START')], 'YYYY-MM-DD HH:mm:ss.SSS');
        const endDate = moment(production[_('END')], 'YYYY-MM-DD HH:mm:ss.SSS');

        if (location) {
            /* If we know the location, allow for preview / premiere */
            startDate = startDate.subtract(2, 'days');
        }

        if (!date.isBefore(startDate) && !date.isAfter(endDate)) {
            /* If a location was specified we have checked it, so return immediately. */
            if (location) {
                return production[_('ID')];
            }

            /* If no location was specified, let's first see how many matches we get. */
            options.push(production[_('ID')]);
        }
    }

    /* If no location was specified, only return a unique match and reject all other cases. */
    if (!location) {
        if (options.length !== 1) {
            throw {};
        }

        return options[0];
    }

    throw {};
};

const db = new sql.Database();

/* Database setup */
(() => {
    db.run(`
        CREATE TABLE PRODUCTION (
            ID       INTEGER PRIMARY KEY AUTOINCREMENT,
            START    DATE DEFAULT NULL,
            END      DATE DEFAULT NULL,
            LOCATION TEXT         NOT NULL,
            THEATER  TEXT DEFAULT NULL
        );`);

    db.run(`
        CREATE TABLE PERSON (
            ID     INTEGER PRIMARY KEY AUTOINCREMENT,
            NAME   TEXT         NOT NULL,
            AVATAR TEXT DEFAULT NULL
        );`);

    db.run(`
        CREATE TABLE CAST (
            SHOW_ID   INTEGER NOT NULL,
            ROLE      TEXT    NOT NULL,
            PERSON_ID INTEGER NOT NULL
        );`);

    db.run(`
        CREATE TABLE SHOW (
            ID            INTEGER PRIMARY KEY AUTOINCREMENT,
            PRODUCTION_ID INTEGER NOT NULL,
            DAY           DATE    NOT NULL,
            TIME          TEXT    NOT NULL,
            TYPE          TEXT    NOT NULL
        );`);
})();

/* Store productions */
slurpJson('./productions.json').forEach(production => {
    db.run('INSERT INTO PRODUCTION (START, END, LOCATION, THEATER) VALUES (?, ?, ?, ?);', [
        production.start,
        production.end,
        production.location,
        production.theater
    ]);
});

/* Cache productions */
const productions = db.exec('SELECT * FROM PRODUCTION');

/* Store actors */
slurpJson('./names.json').forEach(name => {
    db.run('INSERT INTO PERSON (NAME) VALUES (?);', [name]);
});

/* Cache names. */
const nameToId = (() => {
    const query = db.exec('SELECT ID, NAME FROM PERSON');

    let out = {};
    query[0]['values'].forEach((entry) => {
        /* Name → ID */
        out[entry[1]] = +entry[0];
    });

    return out;
})();

/* Store shows */
const fnToDate = fn => moment(fn.replace(/\.json$/, ''), 'YYYY-MM-DD-HHmm');
fs.readdirSync('./data/')
    .map(location => fs.readdirSync(`./data/${location}/`).map(fn => { return { 'fn': fn, 'location': location }; }))
    .reduce((a,b) => [...a, ...b])
    .sort((a,b) => fnToDate(a.fn).diff(fnToDate(b.fn)))
    .forEach(show => {
        const data = slurpJson(`./data/${show.location}/${show.fn}`);
        const productionId = data.production || getProductionId(data.day, data.location, productions);
        const day = moment(data.day, 'DD.MM.YYYY').format('YYYY-MM-DD 00:00:00.0000');

        console.log(`Inserting show ${day} / ${data.time}.`);

        db.run('INSERT INTO SHOW (PRODUCTION_ID, DAY, TIME, TYPE) VALUES (?, ?, ?, ?);', [
            productionId,
            day,
            data.time,
            data.type,
        ]);

        const showId = db.exec('SELECT ID FROM SHOW ORDER BY ID DESC')[0]['values'][0][0];

        Object.keys(data['cast']).forEach(role => {
            data['cast'][role].forEach(element => {
                if (!element) {
                    return;
                }

                const personId = toPersonId(element, nameToId);
                db.run('INSERT INTO CAST (SHOW_ID, ROLE, PERSON_ID) VALUES (?, ?, ?);', [showId, role, personId ]);
            });
        });
    });

/* Export database */
(() => {
    const data = db.export();
    const buffer = new Buffer(data);

    fs.writeFileSync('generated.sqlite', buffer, (err) => {
        if (err) {
            throw err;
        }
    });
})();<commit_msg>Fix date pattern after name change<commit_after>const fs = require('fs');
const moment = require('moment');
const sql = require('sql.js');

const slurp = fn => {
    return fs.readFileSync(fn, {
        encoding: 'utf8'
    });
};

const slurpJson = fn => {
    return JSON.parse(slurp(fn));
};

const toPersonId = (obj, nameToId) => {
    if (typeof obj === 'number' && Object.values(nameToId).includes(obj)) {
        return obj;
    }

    if (typeof obj === 'string' && typeof nameToId[obj] === 'number') {
        return nameToId[obj];
    }

    if (typeof obj === 'object') {
        if (typeof obj.id === 'number') {
            return toPersonId(obj.id);
        }

        if (typeof obj.name === 'string') {
            return toPersonId(obj.name);
        }
    }

    throw {
        'error': `Could not get person ID for ${obj}`,
    };
};

const getProductionId = (date, location, productions) => {
    let _ = (column) => {
        return productions[0]['columns'].indexOf(column);
    };

    let options = [];
    for (let i = 0; i < productions[0]['values'].length; i++) {
        const production = productions[0]['values'][i];

        if (location && production[_('LOCATION')] !== location) {
            continue;
        }

        let startDate = moment(production[_('START')], 'YYYY-MM-DD HH:mm:ss.SSS');
        const endDate = moment(production[_('END')], 'YYYY-MM-DD HH:mm:ss.SSS');

        if (location) {
            /* If we know the location, allow for preview / premiere */
            startDate = startDate.subtract(2, 'days');
        }

        if (!date.isBefore(startDate) && !date.isAfter(endDate)) {
            /* If a location was specified we have checked it, so return immediately. */
            if (location) {
                return production[_('ID')];
            }

            /* If no location was specified, let's first see how many matches we get. */
            options.push(production[_('ID')]);
        }
    }

    /* If no location was specified, only return a unique match and reject all other cases. */
    if (!location) {
        if (options.length !== 1) {
            throw {};
        }

        return options[0];
    }

    throw {};
};

const db = new sql.Database();

/* Database setup */
(() => {
    db.run(`
        CREATE TABLE PRODUCTION (
            ID       INTEGER PRIMARY KEY AUTOINCREMENT,
            START    DATE DEFAULT NULL,
            END      DATE DEFAULT NULL,
            LOCATION TEXT         NOT NULL,
            THEATER  TEXT DEFAULT NULL
        );`);

    db.run(`
        CREATE TABLE PERSON (
            ID     INTEGER PRIMARY KEY AUTOINCREMENT,
            NAME   TEXT         NOT NULL,
            AVATAR TEXT DEFAULT NULL
        );`);

    db.run(`
        CREATE TABLE CAST (
            SHOW_ID   INTEGER NOT NULL,
            ROLE      TEXT    NOT NULL,
            PERSON_ID INTEGER NOT NULL
        );`);

    db.run(`
        CREATE TABLE SHOW (
            ID            INTEGER PRIMARY KEY AUTOINCREMENT,
            PRODUCTION_ID INTEGER NOT NULL,
            DAY           DATE    NOT NULL,
            TIME          TEXT    NOT NULL,
            TYPE          TEXT    NOT NULL
        );`);
})();

/* Store productions */
slurpJson('./productions.json').forEach(production => {
    db.run('INSERT INTO PRODUCTION (START, END, LOCATION, THEATER) VALUES (?, ?, ?, ?);', [
        production.start,
        production.end,
        production.location,
        production.theater
    ]);
});

/* Cache productions */
const productions = db.exec('SELECT * FROM PRODUCTION');

/* Store actors */
slurpJson('./names.json').forEach(name => {
    db.run('INSERT INTO PERSON (NAME) VALUES (?);', [name]);
});

/* Cache names. */
const nameToId = (() => {
    const query = db.exec('SELECT ID, NAME FROM PERSON');

    let out = {};
    query[0]['values'].forEach((entry) => {
        /* Name → ID */
        out[entry[1]] = +entry[0];
    });

    return out;
})();

/* Store shows */
const fnToDate = fn => moment(fn.replace(/\.json$/, ''), 'DD.MM.YYYY-HHmm');
fs.readdirSync('./data/')
    .map(location => fs.readdirSync(`./data/${location}/`).map(fn => { return { 'fn': fn, 'location': location }; }))
    .reduce((a,b) => [...a, ...b])
    .sort((a,b) => fnToDate(a.fn).diff(fnToDate(b.fn)))
    .forEach(show => {
        const data = slurpJson(`./data/${show.location}/${show.fn}`);
        const productionId = data.production || getProductionId(data.day, data.location, productions);
        const day = moment(data.day, 'DD.MM.YYYY').format('YYYY-MM-DD 00:00:00.0000');

        console.log(`Inserting show ${day} / ${data.time}.`);

        db.run('INSERT INTO SHOW (PRODUCTION_ID, DAY, TIME, TYPE) VALUES (?, ?, ?, ?);', [
            productionId,
            day,
            data.time,
            data.type,
        ]);

        const showId = db.exec('SELECT ID FROM SHOW ORDER BY ID DESC')[0]['values'][0][0];

        Object.keys(data['cast']).forEach(role => {
            data['cast'][role].forEach(element => {
                if (!element) {
                    return;
                }

                const personId = toPersonId(element, nameToId);
                db.run('INSERT INTO CAST (SHOW_ID, ROLE, PERSON_ID) VALUES (?, ?, ?);', [showId, role, personId ]);
            });
        });
    });

/* Export database */
(() => {
    const data = db.export();
    const buffer = new Buffer(data);

    fs.writeFileSync('generated.sqlite', buffer, (err) => {
        if (err) {
            throw err;
        }
    });
})();<|endoftext|>


<commit_before>'use strict';

const amino = require('../../main.js');

const gfx = new amino.AminoGfx();

gfx.start(function (err) {
    if (err) {
        console.log('Amino error: ' + err.message);
        return;
    }

    this.fill('#000000');

    //root
    const root = this.createGroup().originX(.5).originY(.5).w(500).h(500);

    this.setRoot(root);

    //add background
    const bgRect = this.createRect().w(500).h(500).fill('#FFFFFF');

    root.add(bgRect);

    //depth rect
    const depthRect = this.createGroup().originX(.5).originY(.5).w(500).h(500);;

    depthRect.depth(true);

    root.add(depthRect);

    //add two rect
    const rect1 = this.createRect().w(100).h(100).x(200).y(200).fill('#FF0000').originX(.5).originY(.5);
    const rect2 = this.createRect().w(100).h(100).x(200).y(200).fill('#0000FF').originX(.5).originY(.5);

    rect2.rx(90);

    depthRect.add(rect1, rect2);

    //animate
    depthRect.ry.anim().from(0).to(360).dur(5000).loop(-1).start();

    //overlay rect
    const overlayRect = this.createRect().w(500).h(500).fill('#00FF00').opacity(.1);

    root.add(overlayRect);
});
<commit_msg>use perspective projection<commit_after>'use strict';

const amino = require('../../main.js');

const gfx = new amino.AminoGfx({
    perspective: {
        orthographic: false
    }
});

gfx.start(function (err) {
    if (err) {
        console.log('Amino error: ' + err.message);
        return;
    }

    this.fill('#000000');

    //root
    const root = this.createGroup().originX(.5).originY(.5).w(500).h(500);

    this.setRoot(root);

    //add background
    const bgRect = this.createRect().w(500).h(500).fill('#FFFFFF');

    root.add(bgRect);

    //depth rect
    const depthRect = this.createGroup().originX(.5).originY(.5).w(500).h(500);;

    depthRect.depth(true);

    root.add(depthRect);

    //add two rect
    const rect1 = this.createRect().w(100).h(100).x(200).y(200).fill('#FF0000').originX(.5).originY(.5);
    const rect2 = this.createRect().w(100).h(100).x(200).y(200).fill('#0000FF').originX(.5).originY(.5);

    rect2.rx(90);

    depthRect.add(rect1, rect2);

    //animate
    depthRect.ry.anim().from(0).to(360).dur(5000).loop(-1).start();

    //overlay rect
    const overlayRect = this.createRect().w(500).h(500).fill('#00FF00').opacity(.1);

    root.add(overlayRect);
});
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2017 TypeFox and others.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
 */
// @ts-check
const fs = require('fs');
const paths = require('path');
const cp = require('child_process');

function generate(name, cwd, prefix, target) {
    if (fs.existsSync(paths.resolve(cwd, prefix + '.package.json'))) {
        const command = 'yo';
        const args = ['theia:' + target, '--force'];
        console.log(`${name}: ${command} ${args.join(' ')}`);
        const p = cp.spawn(command, args, { cwd });
        p.on('exit', code => {
            if (code !== 0) {
                process.exit(code)
            }
        });
        p.on('error', err =>
            console.error(`${name}: ${err.message}`)
        );
        p.stdout.on('data', data =>
            console.log(`${name}: ${data}`)
        );
        p.stderr.on('data', data =>
            console.error(`${name}: ${data}`)
        );
    }
}

function generateAll(path, prefix, target) {
    const children = fs.readdirSync(path);
    for (const child of children) {
        const cwd = paths.resolve(path, child);
        generate(child, cwd, prefix, target);
    }
}

generateAll(paths.resolve(__dirname, '../packages'), 'extension', 'extension');
generate('browser', paths.resolve(__dirname, '../examples/browser'), 'theia', 'browser');
generate('electron', paths.resolve(__dirname, '../examples/electron'), 'theia', 'electron');<commit_msg>#307: fixed ext generation by passing env variables to yo<commit_after>/*
 * Copyright (C) 2017 TypeFox and others.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
 */
// @ts-check
const fs = require('fs');
const paths = require('path');
const cp = require('child_process');

function generate(name, cwd, prefix, target) {
    if (fs.existsSync(paths.resolve(cwd, prefix + '.package.json'))) {
        const command = 'yo';
        const args = ['theia:' + target, '--force'];
        console.log(`${name}: ${command} ${args.join(' ')}`);
        const p = cp.spawn(command, args, { cwd, env: process.env });
        p.on('exit', code => {
            if (code !== 0) {
                process.exit(code)
            }
        });
        p.on('error', err =>
            console.error(`${name}: ${err.message}`)
        );
        p.stdout.on('data', data =>
            console.log(`${name}: ${data}`)
        );
        p.stderr.on('data', data =>
            console.error(`${name}: ${data}`)
        );
    }
}

function generateAll(path, prefix, target) {
    const children = fs.readdirSync(path);
    for (const child of children) {
        const cwd = paths.resolve(path, child);
        generate(child, cwd, prefix, target);
    }
}

generateAll(paths.resolve(__dirname, '../packages'), 'extension', 'extension');
generate('browser', paths.resolve(__dirname, '../examples/browser'), 'theia', 'browser');
generate('electron', paths.resolve(__dirname, '../examples/electron'), 'theia', 'electron');<|endoftext|>


<commit_before>'use strict';

const nock = require('nock');
const watson = require('../../index');
const assert = require('assert');
const authHelper = require('./auth_helper.js');
const auth = authHelper.auth;
const describe = authHelper.describe; // this runs describe.skip if there is no auth.js file :)
const assign = require('object.assign'); // for node v0.12 compatibility
const ConversationV1 = require('../../conversation/v1');

const extend = require('extend');

const TEN_SECONDS = 10000;
const TWO_SECONDS = 2000;

const workspace = {
  name: 'integration test',
  language: 'fr',
  entities: [
    {
      entity: 'hello',
      values: [
        {
          value: 'hola',
          synonyms: ['yo', 'yoo']
        }
      ]
    }
  ]
};

const intents = {
  language: 'en',
  intents: [
    {
      intent: 'test',
      examples: [
        {
          text: 'I test'
        }
      ]
    }
  ]
};

const workspace1 = extend(true, {}, workspace, intents);

describe('conversation_integration', function() {
  this.timeout(TEN_SECONDS);
  this.slow(TWO_SECONDS); // this controls when the tests get a colored warning for taking too long
  // this.retries(1);

  let conversation;

  before(function() {
    conversation = watson.conversation(auth.conversation);
    nock.enableNetConnect();
  });

  after(function() {
    nock.disableNetConnect();
  });

  describe('message()', function() {
    it('alternate_intents', function(done) {
      const params = {
        input: {
          text: 'Turn on the lights'
        },
        alternate_intents: true,
        workspace_id: auth.conversation.workspace_id
      };

      conversation.message(params, function(err, result) {
        if (err) {
          return done(err);
        }
        assert.equal(result.alternate_intents, true);
        done();
      });
    });

    it('dialog_stack with 2017-02-03 version_date', function(done) {
      const constructorParams = assign({}, auth.conversation, {
        version_date: ConversationV1.VERSION_DATE_2017_02_03
      });
      const conversation = watson.conversation(constructorParams);

      const params = {
        input: {
          text: 'Turn on the lights'
        },
        workspace_id: auth.conversation.workspace_id
      };

      conversation.message(params, function(err, result) {
        if (err) {
          return done(err);
        }
        assert.deepEqual(result.context.system.dialog_stack, [{ dialog_node: 'root' }]);
        done();
      });
    });

    it('dialog_stack with 2016-09-20 version_date', function(done) {
      const constructorParams = assign({}, auth.conversation, {
        version_date: ConversationV1.VERSION_DATE_2016_09_20
      });
      const conversation = watson.conversation(constructorParams);

      const params = {
        input: {
          text: 'Turn on the lights'
        },
        workspace_id: auth.conversation.workspace_id
      };

      conversation.message(params, function(err, result) {
        if (err) {
          return done(err);
        }
        assert.deepEqual(result.context.system.dialog_stack, [{ dialog_node: 'root' }]);
        done();
      });
    });

    it('dialog_stack with 2016-07-11 version_date', function(done) {
      const constructorParams = assign({}, auth.conversation, {
        version_date: ConversationV1.VERSION_DATE_2016_07_11
      });
      const conversation = watson.conversation(constructorParams);

      const params = {
        input: {
          text: 'Turn on the lights'
        },
        workspace_id: auth.conversation.workspace_id
      };

      conversation.message(params, function(err, result) {
        if (err) {
          return done(err);
        }
        assert.deepEqual(result.context.system.dialog_stack, ['root']);
        done();
      });
    });
  });

  describe('listWorkspaces()', function() {
    it('result should contain workspaces key', function(done) {
      conversation.listWorkspaces(function(err, result) {
        if (err) {
          return done(err);
        }
        assert.equal(result.hasOwnProperty('workspaces'), true);
        done();
      });
    });

    it('result should contain an array of workspaces', function(done) {
      conversation.listWorkspaces(function(err, result) {
        if (err) {
          return done(err);
        }
        assert.equal(Object.prototype.toString.call(result.workspaces), '[object Array]');
        done();
      });
    });
  });

  describe('createWorkspace()', function() {
    it('should create a new workspace', function(done) {
      const params = workspace;

      conversation.createWorkspace(params, function(err, result) {
        if (err) {
          return done(err);
        }
        workspace1.workspace_id = result.workspace_id;
        assert.equal(result.name, params.name);
        assert.equal(result.language, 'fr');
        assert.equal(result.metadata, params.metadata);
        assert.equal(result.description, params.description);
        done();
      });
    });
  });

  describe('updateWorkspace()', function() {
    it('should update the workspace with intents and language', function(done) {
      const params = workspace1;

      conversation.updateWorkspace(params, function(err, result) {
        if (err) {
          return done(err);
        }
        assert.equal(result.name, params.name);
        assert.equal(result.language, 'en');
        assert.equal(result.metadata, params.metadata);
        assert.equal(result.description, params.description);
        done();
      });
    });
  });

  describe('getWorkspace()', function() {
    it('should get the workspace with the right intent', function(done) {
      const params = {
        export: true,
        workspace_id: workspace1.workspace_id
      };

      conversation.getWorkspace(params, function(err, result) {
        if (err) {
          return done(err);
        }
        assert.equal(result.intents[0].intent, 'test');
        done();
      });
    });
  });

  describe('workspaceStatus()', function() {
    it('should get the workspace status', function(done) {
      const params = {
        workspace_id: workspace1.workspace_id
      };

      conversation.workspaceStatus(params, function(err, result) {
        if (err) {
          return done(err);
        }
        assert.equal(result.workspace_id, workspace1.workspace_id);
        assert.equal(result.training, true);
        done();
      });
    });
  });

  describe('deleteWorkspace()', function() {
    it('should delete the workplace', function(done) {
      const params = {
        workspace_id: workspace1.workspace_id
      };

      conversation.deleteWorkspace(params, function(err, result) {
        if (err) {
          return done(err);
        }
        done();
      });
    });
  });

  describe('createIntent()', function() {
    it('should create an intent', function(done) {
      const params = {
        workspace_id: workspace1.workspace_id,
        intent: intents.intents[0].intent,
        examples: intents.intents[0].examples
      };

      conversation.createIntent(params, function(err, result) {
        if (err) {
          return done(err);
        }
        assert.equal(result.intent, intents.intents[0].intent);
        assert.equal(result.description, null);
        done();
      });
    });
  });
});
<commit_msg>[conversation] Add the test for getIntents<commit_after>'use strict';

const nock = require('nock');
const watson = require('../../index');
const assert = require('assert');
const authHelper = require('./auth_helper.js');
const auth = authHelper.auth;
const describe = authHelper.describe; // this runs describe.skip if there is no auth.js file :)
const assign = require('object.assign'); // for node v0.12 compatibility
const ConversationV1 = require('../../conversation/v1');

const extend = require('extend');

const TEN_SECONDS = 10000;
const TWO_SECONDS = 2000;

const workspace = {
  name: 'integration test',
  language: 'fr',
  entities: [
    {
      entity: 'hello',
      values: [
        {
          value: 'hola',
          synonyms: ['yo', 'yoo']
        }
      ]
    }
  ]
};

const intents = {
  language: 'en',
  intents: [
    {
      intent: 'test',
      examples: [
        {
          text: 'I test'
        }
      ]
    }
  ]
};

const workspace1 = extend(true, {}, workspace, intents);

describe('conversation_integration', function() {
  this.timeout(TEN_SECONDS);
  this.slow(TWO_SECONDS); // this controls when the tests get a colored warning for taking too long
  // this.retries(1);

  let conversation;

  before(function() {
    conversation = watson.conversation(auth.conversation);
    nock.enableNetConnect();
  });

  after(function() {
    nock.disableNetConnect();
  });

  describe('message()', function() {
    it('alternate_intents', function(done) {
      const params = {
        input: {
          text: 'Turn on the lights'
        },
        alternate_intents: true,
        workspace_id: auth.conversation.workspace_id
      };

      conversation.message(params, function(err, result) {
        if (err) {
          return done(err);
        }
        assert.equal(result.alternate_intents, true);
        done();
      });
    });

    it('dialog_stack with 2017-02-03 version_date', function(done) {
      const constructorParams = assign({}, auth.conversation, {
        version_date: ConversationV1.VERSION_DATE_2017_02_03
      });
      const conversation = watson.conversation(constructorParams);

      const params = {
        input: {
          text: 'Turn on the lights'
        },
        workspace_id: auth.conversation.workspace_id
      };

      conversation.message(params, function(err, result) {
        if (err) {
          return done(err);
        }
        assert.deepEqual(result.context.system.dialog_stack, [{ dialog_node: 'root' }]);
        done();
      });
    });

    it('dialog_stack with 2016-09-20 version_date', function(done) {
      const constructorParams = assign({}, auth.conversation, {
        version_date: ConversationV1.VERSION_DATE_2016_09_20
      });
      const conversation = watson.conversation(constructorParams);

      const params = {
        input: {
          text: 'Turn on the lights'
        },
        workspace_id: auth.conversation.workspace_id
      };

      conversation.message(params, function(err, result) {
        if (err) {
          return done(err);
        }
        assert.deepEqual(result.context.system.dialog_stack, [{ dialog_node: 'root' }]);
        done();
      });
    });

    it('dialog_stack with 2016-07-11 version_date', function(done) {
      const constructorParams = assign({}, auth.conversation, {
        version_date: ConversationV1.VERSION_DATE_2016_07_11
      });
      const conversation = watson.conversation(constructorParams);

      const params = {
        input: {
          text: 'Turn on the lights'
        },
        workspace_id: auth.conversation.workspace_id
      };

      conversation.message(params, function(err, result) {
        if (err) {
          return done(err);
        }
        assert.deepEqual(result.context.system.dialog_stack, ['root']);
        done();
      });
    });
  });

  describe('listWorkspaces()', function() {
    it('result should contain workspaces key', function(done) {
      conversation.listWorkspaces(function(err, result) {
        if (err) {
          return done(err);
        }
        assert.equal(result.hasOwnProperty('workspaces'), true);
        done();
      });
    });

    it('result should contain an array of workspaces', function(done) {
      conversation.listWorkspaces(function(err, result) {
        if (err) {
          return done(err);
        }
        assert.equal(Object.prototype.toString.call(result.workspaces), '[object Array]');
        done();
      });
    });
  });

  describe('createWorkspace()', function() {
    it('should create a new workspace', function(done) {
      const params = workspace;

      conversation.createWorkspace(params, function(err, result) {
        if (err) {
          return done(err);
        }
        workspace1.workspace_id = result.workspace_id;
        assert.equal(result.name, params.name);
        assert.equal(result.language, 'fr');
        assert.equal(result.metadata, params.metadata);
        assert.equal(result.description, params.description);
        done();
      });
    });
  });

  describe('updateWorkspace()', function() {
    it('should update the workspace with intents and language', function(done) {
      const params = workspace1;

      conversation.updateWorkspace(params, function(err, result) {
        if (err) {
          return done(err);
        }
        assert.equal(result.name, params.name);
        assert.equal(result.language, 'en');
        assert.equal(result.metadata, params.metadata);
        assert.equal(result.description, params.description);
        done();
      });
    });
  });

  describe('getWorkspace()', function() {
    it('should get the workspace with the right intent', function(done) {
      const params = {
        export: true,
        workspace_id: workspace1.workspace_id
      };

      conversation.getWorkspace(params, function(err, result) {
        if (err) {
          return done(err);
        }
        assert.equal(result.intents[0].intent, 'test');
        done();
      });
    });
  });

  describe('workspaceStatus()', function() {
    it('should get the workspace status', function(done) {
      const params = {
        workspace_id: workspace1.workspace_id
      };

      conversation.workspaceStatus(params, function(err, result) {
        if (err) {
          return done(err);
        }
        assert.equal(result.workspace_id, workspace1.workspace_id);
        assert.equal(result.training, true);
        done();
      });
    });
  });

  describe('deleteWorkspace()', function() {
    it('should delete the workplace', function(done) {
      const params = {
        workspace_id: workspace1.workspace_id
      };

      conversation.deleteWorkspace(params, function(err, result) {
        if (err) {
          return done(err);
        }
        done();
      });
    });
  });

  describe('createIntent()', function() {
    it('should create an intent', function(done) {
      const params = {
        workspace_id: workspace1.workspace_id,
        intent: intents.intents[0].intent,
        examples: intents.intents[0].examples
      };

      conversation.createIntent(params, function(err, result) {
        if (err) {
          return done(err);
        }
        assert.equal(result.intent, intents.intents[0].intent);
        assert.equal(result.description, null);
        done();
      });
    });
  });

  describe('getIntents()', function() {
    it('should get intents of the workspace', function(done) {
      const params = {
        workspace_id: workspace1.workspace_id,
        export: true
      };

      conversation.getIntents(params, function(err, result) {
        if (err) {
          return done(err);
        }
        assert.equal(result.intents[0].intent, intents.intents[0].intent);
        assert.equal(result.intents[0].examples[0].text, intents.intents[0].examples[0].text);
        done();
      });
    });
  });
});
<|endoftext|>


<commit_before>const PanelsActionCreator = require('../actions/panels-action-creator');
const MoleGameActionCreator = require('../actions/mole-game-action-creator');

const TARGET_PANELS = [
  // [stripId, panelId],
  ['0', '0'],
  ['1', '1'],
  ['2', '2'],
  ['1', '2'],
  ['0', '3'],
  ['2', '5']
];

const TARGET_PANEL_INTENSITY = 100;
const PANEL_OFF_INTENSITY = 0;

const ANIMATION_NONE = false;

export default class MoleGameLogic {
  static ANIMATION_SUCCESS = "success";

  // These are automatically added to the sculpture store
  static trackedProperties = {
    targetPanelIndex: 0,
    animation: ANIMATION_NONE
  };

  constructor(store) {
    this.store = store;
  }

  get data() {
    return this.store.data.get('mole');
  }

  start() {
    this._enableCurrentTargetPanel();
  }

  handleActionPayload(payload) {
    const actionHandlers = {
      [PanelsActionCreator.PANEL_PRESSED]: this._actionPanelPressed.bind(this),
      [MoleGameActionCreator.ANIMATION_FINISH]: this._actionAnimationFinish.bind(this)
    };

    const actionHandler = actionHandlers[payload.actionType];
    if (actionHandler) {
      actionHandler(payload);
    }
  }

  _actionPanelPressed(payload) {
    let {stripId, panelId, pressed} = payload;

    const targetPanelIndex = this.data.get("targetPanelIndex");
    const [targetStripId, targetPanelId] = this._getTargetPanel(targetPanelIndex);

    if (stripId === targetStripId && panelId === targetPanelId && pressed) {
      this.data.set("targetPanelIndex", targetPanelIndex + 1);
      this._enableCurrentTargetPanel();
    }
  }

  _actionAnimationFinish() {
    this.store.restoreStatus();
    this.data.set("animation", ANIMATION_NONE);
  }

  _enableCurrentTargetPanel() {
    const targetPanelIndex = this.data.get("targetPanelIndex");
    if (targetPanelIndex > 0) {
      this._disablePanelIndex(targetPanelIndex - 1);
    }

    if (targetPanelIndex >= TARGET_PANELS.length) {
      //TODO: Refactor the contents of this if statement into multiple methods
      this.store.data.get('lights').deactivateAll();

      this.data.set("targetPanelIndex", 0);
      this._enableCurrentTargetPanel();

      this.store.lock();
      this.data.set("animation", MoleGameLogic.ANIMATION_SUCCESS);
      return;
    }

    const [targetStripId, targetPanelId] = this._getTargetPanel(targetPanelIndex);
    this._enablePanel(targetStripId, targetPanelId);
  }

  _enablePanel(stripId, panelId) {
    this.store.data.get('lights').setIntensity(stripId, panelId, TARGET_PANEL_INTENSITY);
  }

  _disablePanelIndex(index) {
    const [stripId, panelId] = this._getTargetPanel(index);
    this._disablePanel(stripId, panelId);
  }

  _disablePanel(stripId, panelId) {
    this.store.data.get('lights').setIntensity(stripId, panelId, PANEL_OFF_INTENSITY);
  }

  _getTargetPanel(index) {
    return TARGET_PANELS[index];
  }
}
<commit_msg>Updated mole game puzzle to match physical reality<commit_after>const PanelsActionCreator = require('../actions/panels-action-creator');
const MoleGameActionCreator = require('../actions/mole-game-action-creator');

const TARGET_PANELS = [
  // [stripId, panelId],
  ['0', '3'],
  ['1', '3'],
  ['2', '3'],
  ['1', '4'],
  ['0', '5'],
  ['2', '5']
];

const TARGET_PANEL_INTENSITY = 100;
const PANEL_OFF_INTENSITY = 0;

const ANIMATION_NONE = false;

export default class MoleGameLogic {
  static ANIMATION_SUCCESS = "success";

  // These are automatically added to the sculpture store
  static trackedProperties = {
    targetPanelIndex: 0,
    animation: ANIMATION_NONE
  };

  constructor(store) {
    this.store = store;
  }

  get data() {
    return this.store.data.get('mole');
  }

  start() {
    this._enableCurrentTargetPanel();
  }

  handleActionPayload(payload) {
    const actionHandlers = {
      [PanelsActionCreator.PANEL_PRESSED]: this._actionPanelPressed.bind(this),
      [MoleGameActionCreator.ANIMATION_FINISH]: this._actionAnimationFinish.bind(this)
    };

    const actionHandler = actionHandlers[payload.actionType];
    if (actionHandler) {
      actionHandler(payload);
    }
  }

  _actionPanelPressed(payload) {
    let {stripId, panelId, pressed} = payload;

    const targetPanelIndex = this.data.get("targetPanelIndex");
    const [targetStripId, targetPanelId] = this._getTargetPanel(targetPanelIndex);

    if (stripId === targetStripId && panelId === targetPanelId && pressed) {
      this.data.set("targetPanelIndex", targetPanelIndex + 1);
      this._enableCurrentTargetPanel();
    }
  }

  _actionAnimationFinish() {
    this.store.restoreStatus();
    this.data.set("animation", ANIMATION_NONE);
  }

  _enableCurrentTargetPanel() {
    const targetPanelIndex = this.data.get("targetPanelIndex");
    if (targetPanelIndex > 0) {
      this._disablePanelIndex(targetPanelIndex - 1);
    }

    if (targetPanelIndex >= TARGET_PANELS.length) {
      //TODO: Refactor the contents of this if statement into multiple methods
      this.store.data.get('lights').deactivateAll();

      this.data.set("targetPanelIndex", 0);
      this._enableCurrentTargetPanel();

      this.store.lock();
      this.data.set("animation", MoleGameLogic.ANIMATION_SUCCESS);
      return;
    }

    const [targetStripId, targetPanelId] = this._getTargetPanel(targetPanelIndex);
    this._enablePanel(targetStripId, targetPanelId);
  }

  _enablePanel(stripId, panelId) {
    this.store.data.get('lights').setIntensity(stripId, panelId, TARGET_PANEL_INTENSITY);
  }

  _disablePanelIndex(index) {
    const [stripId, panelId] = this._getTargetPanel(index);
    this._disablePanel(stripId, panelId);
  }

  _disablePanel(stripId, panelId) {
    this.store.data.get('lights').setIntensity(stripId, panelId, PANEL_OFF_INTENSITY);
  }

  _getTargetPanel(index) {
    return TARGET_PANELS[index];
  }
}
<|endoftext|>