<commit_before>import {getLatestRelease} from '../components/github';
import {getRedirect} from '../components/utils';
import config from '../config';
import semver from 'semver';

export async function darwin(req, res) {
  const channel = req.params.channel || 'stable';
  if (!['stable', 'beta', 'dev'].includes(channel)) throw new Error(`400:Invalid channel '${channel}'.`);

  const version = req.query.version;
  if (!semver.valid(version)) throw new Error(`400:Invalid version '${version}'.`);

  const latestRelease = await getLatestRelease(channel);
  if (!latestRelease) throw new Error('404:Latest release not found.');

  const latestVersion = semver.clean(latestRelease.tag_name);
  const shouldUpdate = semver.lt(version, latestVersion);

  if (shouldUpdate) {
    const asset = latestRelease.assets.find(a => a.name.match(config.patterns.darwin.zip));
    if (!asset) throw new Error(`404:No asset found that matches '${config.patterns.darwin.zip}'.`);

    let downloadUrl = asset.browser_download_url;
    if (config.privateRepo) {
      downloadUrl = await getRedirect(downloadUrl);
    }

    res.json({
      url: downloadUrl,
      name: latestRelease.name,
      notes: latestRelease.body,
      pub_date: latestRelease.published_at
    });

    return;
  }

  res.status(204).end();
}

export async function win32_portable(req, res) {
  const channel = req.params.channel || 'stable';
  if (!['stable', 'beta', 'dev'].includes(channel)) throw new Error(`400:Invalid channel '${channel}'.`);

  const latestRelease = await getLatestRelease(channel);
  if (!latestRelease) throw new Error('404:Latest release not found.');

  const zipAsset = latestRelease.assets.find(a => a.name.match(config.patterns.win32.zip));
  if (!zipAsset) throw new Error(`404:No asset found that matches '${config.patterns.win32.zip}'.`);

  let downloadUrl = zipAsset.browser_download_url;
  if (config.privateRepo) {
    downloadUrl = await getRedirect(downloadUrl);
  }

  res.json({
    url: downloadUrl,
    name: latestRelease.name,
    notes: latestRelease.body,
    pub_date: latestRelease.published_at,
    version: semver.clean(latestRelease.tag_name)
  });
}

export async function win32_file(req, res) {
  const channel = req.params.channel || 'stable';
  if (!['stable', 'beta', 'dev'].includes(channel)) throw new Error(`400:Invalid channel '${channel}'.`);

  const fileName = req.params.file;
  if (!fileName) throw new Error(`400:Invalid file '${fileName}'.`);

  const latestRelease = await getLatestRelease(channel);
  if (!latestRelease) throw new Error('404:Latest release not found.');

  let downloadPath = latestRelease.html_url
    .replace('/releases/v', '/releases/download/v')
    .replace('/releases/tag/v', '/releases/download/v');
  downloadPath += '/' + fileName;

  const versionMatches = fileName.match(/\d+\.\d+\.\d+/);
  const fileVersion = versionMatches && versionMatches[0] || null;

  if (fileVersion) {
    downloadPath = downloadPath.replace(semver.clean(latestRelease.tag_name), fileVersion);
  }

  if (config.privateRepo) {
    downloadPath = await getRedirect(downloadPath);
  }

  res.redirect(301, downloadPath);
}

export async function linux(req, res) {
  const channel = req.params.channel || 'stable';
  if (!['stable', 'beta', 'dev'].includes(channel)) throw new Error(`400:Invalid channel '${channel}'.`);

  const arch = req.query.arch || '';
  const pkg = req.query.pkg || '';

  if (!['i386', 'amd64', 'x86_64'].includes(arch)) throw new Error(`400:Invalid arch '${arch}'.`);
  if (!['deb', 'rpm'].includes(pkg)) throw new Error(`400:Invalid pkg '${pkg}'.`);

  const latestRelease = await getLatestRelease(channel);
  if (!latestRelease) throw new Error('404:Latest release not found.');

  const asset = latestRelease.assets.find(a => a.name.includes(pkg) && a.name.includes(arch));
  if (!asset) throw new Error(`404:No asset found for pkg '${pkg}' and arch '${arch}'.`);

  let downloadUrl = asset.browser_download_url;
  if (config.privateRepo) {
    downloadUrl = await getRedirect(downloadUrl);
  }

  res.json({
    url: downloadUrl,
    name: latestRelease.name,
    notes: latestRelease.body,
    pub_date: latestRelease.published_at,
    version: semver.clean(latestRelease.tag_name)
  });
}
<commit_msg>Use `dev` if no channel is specified<commit_after>import {getLatestRelease} from '../components/github';
import {getRedirect} from '../components/utils';
import config from '../config';
import semver from 'semver';

export async function darwin(req, res) {
  const channel = req.params.channel || 'dev';
  if (!['stable', 'beta', 'dev'].includes(channel)) throw new Error(`400:Invalid channel '${channel}'.`);

  const version = req.query.version;
  if (!semver.valid(version)) throw new Error(`400:Invalid version '${version}'.`);

  const latestRelease = await getLatestRelease(channel);
  if (!latestRelease) throw new Error('404:Latest release not found.');

  const latestVersion = semver.clean(latestRelease.tag_name);
  const shouldUpdate = semver.lt(version, latestVersion);

  if (shouldUpdate) {
    const asset = latestRelease.assets.find(a => a.name.match(config.patterns.darwin.zip));
    if (!asset) throw new Error(`404:No asset found that matches '${config.patterns.darwin.zip}'.`);

    let downloadUrl = asset.browser_download_url;
    if (config.privateRepo) {
      downloadUrl = await getRedirect(downloadUrl);
    }

    res.json({
      url: downloadUrl,
      name: latestRelease.name,
      notes: latestRelease.body,
      pub_date: latestRelease.published_at
    });

    return;
  }

  res.status(204).end();
}

export async function win32_portable(req, res) {
  const channel = req.params.channel || 'dev';
  if (!['stable', 'beta', 'dev'].includes(channel)) throw new Error(`400:Invalid channel '${channel}'.`);

  const latestRelease = await getLatestRelease(channel);
  if (!latestRelease) throw new Error('404:Latest release not found.');

  const zipAsset = latestRelease.assets.find(a => a.name.match(config.patterns.win32.zip));
  if (!zipAsset) throw new Error(`404:No asset found that matches '${config.patterns.win32.zip}'.`);

  let downloadUrl = zipAsset.browser_download_url;
  if (config.privateRepo) {
    downloadUrl = await getRedirect(downloadUrl);
  }

  res.json({
    url: downloadUrl,
    name: latestRelease.name,
    notes: latestRelease.body,
    pub_date: latestRelease.published_at,
    version: semver.clean(latestRelease.tag_name)
  });
}

export async function win32_file(req, res) {
  const channel = req.params.channel || 'dev';
  if (!['stable', 'beta', 'dev'].includes(channel)) throw new Error(`400:Invalid channel '${channel}'.`);

  const fileName = req.params.file;
  if (!fileName) throw new Error(`400:Invalid file '${fileName}'.`);

  const latestRelease = await getLatestRelease(channel);
  if (!latestRelease) throw new Error('404:Latest release not found.');

  let downloadPath = latestRelease.html_url
    .replace('/releases/v', '/releases/download/v')
    .replace('/releases/tag/v', '/releases/download/v');
  downloadPath += '/' + fileName;

  const versionMatches = fileName.match(/\d+\.\d+\.\d+/);
  const fileVersion = versionMatches && versionMatches[0] || null;

  if (fileVersion) {
    downloadPath = downloadPath.replace(semver.clean(latestRelease.tag_name), fileVersion);
  }

  if (config.privateRepo) {
    downloadPath = await getRedirect(downloadPath);
  }

  res.redirect(301, downloadPath);
}

export async function linux(req, res) {
  const channel = req.params.channel || 'dev';
  if (!['stable', 'beta', 'dev'].includes(channel)) throw new Error(`400:Invalid channel '${channel}'.`);

  const arch = req.query.arch || '';
  const pkg = req.query.pkg || '';

  if (!['i386', 'amd64', 'x86_64'].includes(arch)) throw new Error(`400:Invalid arch '${arch}'.`);
  if (!['deb', 'rpm'].includes(pkg)) throw new Error(`400:Invalid pkg '${pkg}'.`);

  const latestRelease = await getLatestRelease(channel);
  if (!latestRelease) throw new Error('404:Latest release not found.');

  const asset = latestRelease.assets.find(a => a.name.includes(pkg) && a.name.includes(arch));
  if (!asset) throw new Error(`404:No asset found for pkg '${pkg}' and arch '${arch}'.`);

  let downloadUrl = asset.browser_download_url;
  if (config.privateRepo) {
    downloadUrl = await getRedirect(downloadUrl);
  }

  res.json({
    url: downloadUrl,
    name: latestRelease.name,
    notes: latestRelease.body,
    pub_date: latestRelease.published_at,
    version: semver.clean(latestRelease.tag_name)
  });
}
<|endoftext|>


<commit_before>(function () {
    var sharedDataMap = {},
        visibilityMap = { 'histogram': false, 'information': false };

    var getSharedData = function (model, container, analysis) {
        var key = model.getHash() + '::' + ($(container).attr('container-uid') || 'main');
        if (_.has(sharedDataMap, key)) {
            return sharedDataMap[key];
        } else {

            var layer = new cinema.models.LayerModel(model.getDefaultPipelineSetup(), {
                    info: model
                }),
                control = new cinema.models.ControlModel({
                    info: model
                }),
                viewpoint = new cinema.models.ViewPointModel({
                    controlModel: control
                }),
                compositor = new cinema.utilities.CreateWebGlLightCompositor(),
                rendering = new cinema.models.RenderingModel({
                    url: cinema.staticRoot + 'rendering/rendering.json',
                    visModel: model,
                    ranges: model.getColorByRanges(),
                    fields: model.getColorByFields()
                }),
                compositeToolsWidget = new cinema.views.CompositeToolsWidget({
                    el: $('.c-tools-panel', container),
                    model: model,
                    controlModel: control,
                    viewpoint: viewpoint,
                    layers: layer,
                    toolbarSelector: '.c-panel-toolbar'
                }),
                searchToolsWidget = new cinema.views.SearchToolsWidget({
                    el: $('.c-tools-panel', container),
                    model: model,
                    layers: layer,
                    toolbarSelector: '.c-panel-toolbar'
                }),
                imageManager = new cinema.utilities.CompositeImageManager({
                    visModel: model
                }),
                renderView = new cinema.views.VisualizationWebGlLightCanvasWidget({
                    el: $('.c-body-container', container),
                    model: model,
                    layers: layer,
                    viewpoint: viewpoint,
                    compositeManager: imageManager,
                    webglCompositor: compositor,
                    renderingModel: rendering
                }),
                renderingWidget = new cinema.views.RenderingWidget({
                    el: $('.c-rendering-panel', container),
                    model: model,
                    viewport: renderView,
                    renderingModel: rendering,
                    toolbarSelector: '.c-panel-toolbar',
                }),
                offScreenLayer = new cinema.models.LayerModel(model.getDefaultPipelineSetup(), {
                    info: model
                }),
                offScreenControl = new cinema.models.ControlModel({
                    info: model
                }),
                offScreenViewpoint = new cinema.models.ViewPointModel({
                    controlModel: offScreenControl
                }),
                offScreenRenderView = new cinema.views.VisualizationWebGlLightCanvasWidget({
                    el: $('.c-body-container', container),
                    model: model,
                    layers: offScreenLayer,
                    viewpoint: offScreenViewpoint,
                    compositeManager: imageManager,
                    webglCompositor: compositor,
                    renderingModel: rendering
                }),
                histogram = null,
                informationWidget = null,
                histogramWidget = null,
                searchView = null,
                metaDataSearchView = null,
                metaDataInformationWidget = null;

            if (analysis) {
                histogram = new cinema.models.CompositeHistogramModel({
                    layerModel: layer,
                    basePath: model.get('basePath'),
                    analysisInfo: model.attributes.metadata.analysis
                });
                informationWidget = new cinema.views.SearchInformationWidget({
                    el: $('.c-information-panel', container),
                    model: model,
                    controlModel: control,
                    exclude: ['layer', 'filename'],
                    layers: layer,
                    toolbarSelector: '.c-panel-toolbar'
                });
                histogramWidget = new cinema.views.CompositeHistogramWidget({
                    el: $('.c-histogram-panel', container),
                    basePath: model.get('basePath'),
                    histogramModel: histogram,
                    viewpoint: viewpoint,
                    layerModel: layer,
                    toolbarSelector: '.c-panel-toolbar'
                });
                searchView = new cinema.views.CompositeSearchPage({
                    el: $('.c-body-container', container),
                    basePath: model.get('basePath'),
                    histogramModel: histogram,
                    visModel: model,
                    controlModel: control,
                    layerModel: layer,
                    offScreenControl: offScreenControl,
                    offScreenRenderView: offScreenRenderView
                });
            } else {
                metaDataSearchView = new cinema.views.MetaDataCompositeSearchPage({
                    el: $('.c-body-container', container),
                    visModel: model,
                    controlModel: control,
                    layerModel: layer,
                    offScreenControl: offScreenControl,
                    offScreenRenderView: offScreenRenderView
                });
                metaDataInformationWidget = new cinema.views.MetaDataSearchInformationWidget({
                    el: $('.c-information-panel', container),
                    model: model,
                    controlModel: control,
                    exclude: ['layer', 'filename'],
                    toolbarSelector: '.c-panel-toolbar'
                });
            }

            var shared = {
                key: key,
                control: control,
                histogram: histogram,
                layer: layer,
                viewpoint: viewpoint,
                compositor: compositor,
                rendering: rendering,
                informationWidget: informationWidget,
                histogramWidget: histogramWidget,
                compositeToolsWidget: compositeToolsWidget,
                searchToolsWidget: searchToolsWidget,
                imageManager: imageManager,
                renderView: renderView,
                renderingWidget: renderingWidget,
                offScreenLayer: offScreenLayer,
                offScreenControl: offScreenControl,
                offScreenViewpoint: offScreenViewpoint,
                offScreenRenderView: offScreenRenderView,
                searchView: searchView,
                metaDataSearchView: metaDataSearchView,
                metaDataInformationWidget: metaDataInformationWidget,
                remove: function () {

                }
            };
            sharedDataMap[key] = shared;
            return shared;
        }
    };

    var freeSharedDataMap = function (key) {
        delete sharedDataMap[key];
    };

    var visibility = function (name, value) {
        if (value === undefined) {
            return visibilityMap[name];
        } else {
            visibilityMap[name] = value;
        }
    };

    cinema.events.on('toggle-control-panel', function(event) {
        visibility(event.key, event.visible);
    });

    cinema.views.CompositeWebGlLightView = Backbone.View.extend({
        initialize: function (opts) {
            this.compositeModel = new cinema.decorators.Composite(this.model);
            this._hasAnalysis = _.has(this.model.get('metadata'), 'analysis');
            var sharedData = getSharedData(this.compositeModel, this.$el, this._hasAnalysis);
            this.key = sharedData.key;

            this.controlModel = sharedData.control;
            this.viewpointModel = sharedData.viewpoint;
            this.renderView = sharedData.renderView;

            new cinema.utilities.RenderViewMouseInteractor({
                renderView: this.renderView,
                camera: this.viewpointModel
            }).enableMouseWheelZoom({
                    maxZoomLevel: 10,
                    zoomIncrement: 0.05,
                    invertControl: false
                }).enableDragPan({
                    keyModifiers: cinema.keyModifiers.SHIFT
                }).enableDragRotation({
                    keyModifiers: null
                });

            this.compositeTools = sharedData.compositeToolsWidget;
            this.renderingTools = sharedData.renderingWidget;

            if (this._hasAnalysis) {
                this.controlList = opts.defaultControls.slice(0);
                this.compositeHistogram = sharedData.histogramWidget;
                this.searchInformation = sharedData.informationWidget;
                this.controlList.push(
                    { position: 'center', key: 'histogram', icon: 'icon-chart-bar', title: 'Histogram' }
                );

                sharedData.histogram.fetch();
            } else {
                this.searchInformation = sharedData.metaDataInformationWidget;
            }

            this.listenTo(this.controlModel, 'change', this.refreshCamera);
            this.listenTo(this.viewpointModel, 'change', this.refreshCamera);
            this.listenTo(cinema.events, 'c:resetCamera', this.resetCamera);
        },

        render: function () {
            this.renderView.setElement(this.$('.c-body-container')).render().showViewpoint(true);
            this.compositeTools.setElement(this.$('.c-tools-panel')).render();
            this.renderingTools.setElement(this.$('.c-rendering-panel')).render();
            this.searchInformation.setElement(this.$('.c-information-panel')).render();
            this.$('.c-information-panel').toggle(visibility('information'));
            if (this._hasAnalysis) {
                this.compositeHistogram.setElement(this.$('.c-histogram-panel')).render();
                this.$('.c-histogram-panel').toggle(visibility('histogram'));
            }
            return this;
        },

        refreshCamera: function () {
            if (this.renderView) {
                this.renderView.showViewpoint();
            }
        },

        resetCamera: function () {
            if (this.renderView) {
                this.renderView.showViewpoint();
                this.renderView.resetCamera();
            }
        },

        remove: function () {
            getSharedData(this.compositeModel, this.$el, this._hasAnalysis).remove();

            // SharedData
            freeSharedDataMap(this.key);

            // Connections to SharedData
            this.key = null;

            // Models
            this.controlModel.remove();
            this.viewpointModel.remove();

            // Views
            this.renderView.remove();
            this.compositeTools.remove();
            this.renderingTools.remove();
            if (this._hasAnalysis) {
                this.compositeHistogram.remove();
                this.searchInformation.remove();
            } else {
                this.searchInformation.remove();
            }
        }
    });

    cinema.views.CompositeWebGlLightSearchView = Backbone.View.extend({
        initialize: function (opts) {
            this.compositeModel = new cinema.decorators.Composite(this.model);
            this._hasAnalysis = _.has(this.model.get('metadata'), 'analysis');
            var sharedData = getSharedData(this.compositeModel, this.$el, this._hasAnalysis);
            this.key = sharedData.key;

            this.controlModel = sharedData.control;
            this.viewpointModel = sharedData.viewpoint;
            this.searchTools = sharedData.searchToolsWidget;

            if (this._hasAnalysis) {
                this.searchView = sharedData.searchView;
                this.compositeHistogram = sharedData.histogramWidget;
                this.searchInformation = sharedData.informationWidget;
                this.controlList = opts.defaultControls.slice(0);
                this.controlList.push(
                    { position: 'center', key: 'histogram', icon: 'icon-chart-bar', title: 'Histogram' }
                );
            } else {
                this.searchView = sharedData.metaDataSearchView;
                this.searchInformation = sharedData.metaDataInformationWidget;
            }
        },

        render: function () {
            this.searchView.setElement(this.$('.c-body-container')).render();
            this.searchTools.setElement(this.$('.c-tools-panel')).render();
            this.searchInformation.setElement(this.$('.c-information-panel')).render();
            this.$('.c-information-panel').toggle(visibility('information'));
            if (this._hasAnalysis) {
                this.compositeHistogram.setElement(this.$('.c-histogram-panel')).render();
                this.$('.c-histogram-panel').toggle(visibility('histogram'));
            }
            return this;
        },

        remove: function () {
            getSharedData(this.compositeModel, this.$el, this._hasAnalysis).remove();

            // SharedData
            freeSharedDataMap(this.key);

            // Connections to SharedData
            this.key = null;

            // Models
            this.controlModel.remove();
            this.viewpointModel.remove();

            // Views
            this.searchView.remove();
            this.searchTools.remove();
            if (this._hasAnalysis) {
                this.compositeHistogram.remove();
                this.searchInformation.remove();
            } else {
                this.searchInformation.remove();
            }
        }
    });
}());

cinema.viewMapper.registerView('composite-image-stack-litdepth', 'view', cinema.views.CompositeWebGlLightView, {
    controls: [
        { position: 'left', key: 'information', icon: 'icon-help', title: 'Information' },
        { position: 'left',  key: 'rendering', icon: 'icon-picture',   title: 'Rendering'},
        { position: 'right', key: 'tools', icon: 'icon-tools', title: 'Tools' }
    ]
});

cinema.viewMapper.registerView('composite-image-stack-litdepth', 'search', cinema.views.CompositeWebGlLightSearchView, {
    controls: [
        { position: 'left', key: 'information', icon: 'icon-help', title: 'Information' },
        { position: 'right', key: 'tools', icon: 'icon-tools', title: 'Tools' }
    ]
});
<commit_msg>In compostiewebgllight consistently defer execution of all parts of the main view code until when the DOM is fully-loaded. This may be an anti-pattern and unnecessary, but I want the code to be consistent. It will be simple to remove this if unnecessary.<commit_after>(function () {
    var sharedDataMap = {},
        visibilityMap = { 'histogram': false, 'information': false };

    var getSharedData = function (model, container, analysis) {
        var key = model.getHash() + '::' + ($(container).attr('container-uid') || 'main');
        if (_.has(sharedDataMap, key)) {
            return sharedDataMap[key];
        } else {

            var layer = new cinema.models.LayerModel(model.getDefaultPipelineSetup(), {
                    info: model
                }),
                control = new cinema.models.ControlModel({
                    info: model
                }),
                viewpoint = new cinema.models.ViewPointModel({
                    controlModel: control
                }),
                compositor = new cinema.utilities.CreateWebGlLightCompositor(),
                rendering = new cinema.models.RenderingModel({
                    url: cinema.staticRoot + 'rendering/rendering.json',
                    visModel: model,
                    ranges: model.getColorByRanges(),
                    fields: model.getColorByFields()
                }),
                compositeToolsWidget = new cinema.views.CompositeToolsWidget({
                    el: $('.c-tools-panel', container),
                    model: model,
                    controlModel: control,
                    viewpoint: viewpoint,
                    layers: layer,
                    toolbarSelector: '.c-panel-toolbar'
                }),
                searchToolsWidget = new cinema.views.SearchToolsWidget({
                    el: $('.c-tools-panel', container),
                    model: model,
                    layers: layer,
                    toolbarSelector: '.c-panel-toolbar'
                }),
                imageManager = new cinema.utilities.CompositeImageManager({
                    visModel: model
                }),
                renderView = new cinema.views.VisualizationWebGlLightCanvasWidget({
                    el: $('.c-body-container', container),
                    model: model,
                    layers: layer,
                    viewpoint: viewpoint,
                    compositeManager: imageManager,
                    webglCompositor: compositor,
                    renderingModel: rendering
                }),
                renderingWidget = new cinema.views.RenderingWidget({
                    el: $('.c-rendering-panel', container),
                    model: model,
                    viewport: renderView,
                    renderingModel: rendering,
                    toolbarSelector: '.c-panel-toolbar',
                }),
                offScreenLayer = new cinema.models.LayerModel(model.getDefaultPipelineSetup(), {
                    info: model
                }),
                offScreenControl = new cinema.models.ControlModel({
                    info: model
                }),
                offScreenViewpoint = new cinema.models.ViewPointModel({
                    controlModel: offScreenControl
                }),
                offScreenRenderView = new cinema.views.VisualizationWebGlLightCanvasWidget({
                    el: $('.c-body-container', container),
                    model: model,
                    layers: offScreenLayer,
                    viewpoint: offScreenViewpoint,
                    compositeManager: imageManager,
                    webglCompositor: compositor,
                    renderingModel: rendering
                }),
                histogram = null,
                informationWidget = null,
                histogramWidget = null,
                searchView = null,
                metaDataSearchView = null,
                metaDataInformationWidget = null;

            if (analysis) {
                histogram = new cinema.models.CompositeHistogramModel({
                    layerModel: layer,
                    basePath: model.get('basePath'),
                    analysisInfo: model.attributes.metadata.analysis
                });
                informationWidget = new cinema.views.SearchInformationWidget({
                    el: $('.c-information-panel', container),
                    model: model,
                    controlModel: control,
                    exclude: ['layer', 'filename'],
                    layers: layer,
                    toolbarSelector: '.c-panel-toolbar'
                });
                histogramWidget = new cinema.views.CompositeHistogramWidget({
                    el: $('.c-histogram-panel', container),
                    basePath: model.get('basePath'),
                    histogramModel: histogram,
                    viewpoint: viewpoint,
                    layerModel: layer,
                    toolbarSelector: '.c-panel-toolbar'
                });
                searchView = new cinema.views.CompositeSearchPage({
                    el: $('.c-body-container', container),
                    basePath: model.get('basePath'),
                    histogramModel: histogram,
                    visModel: model,
                    controlModel: control,
                    layerModel: layer,
                    offScreenControl: offScreenControl,
                    offScreenRenderView: offScreenRenderView
                });
            } else {
                metaDataSearchView = new cinema.views.MetaDataCompositeSearchPage({
                    el: $('.c-body-container', container),
                    visModel: model,
                    controlModel: control,
                    layerModel: layer,
                    offScreenControl: offScreenControl,
                    offScreenRenderView: offScreenRenderView
                });
                metaDataInformationWidget = new cinema.views.MetaDataSearchInformationWidget({
                    el: $('.c-information-panel', container),
                    model: model,
                    controlModel: control,
                    exclude: ['layer', 'filename'],
                    toolbarSelector: '.c-panel-toolbar'
                });
            }

            var shared = {
                key: key,
                control: control,
                histogram: histogram,
                layer: layer,
                viewpoint: viewpoint,
                compositor: compositor,
                rendering: rendering,
                informationWidget: informationWidget,
                histogramWidget: histogramWidget,
                compositeToolsWidget: compositeToolsWidget,
                searchToolsWidget: searchToolsWidget,
                imageManager: imageManager,
                renderView: renderView,
                renderingWidget: renderingWidget,
                offScreenLayer: offScreenLayer,
                offScreenControl: offScreenControl,
                offScreenViewpoint: offScreenViewpoint,
                offScreenRenderView: offScreenRenderView,
                searchView: searchView,
                metaDataSearchView: metaDataSearchView,
                metaDataInformationWidget: metaDataInformationWidget,
                remove: function () {

                }
            };
            sharedDataMap[key] = shared;
            return shared;
        }
    };

    var freeSharedDataMap = function (key) {
        delete sharedDataMap[key];
    };

    var visibility = function (name, value) {
        if (value === undefined) {
            return visibilityMap[name];
        } else {
            visibilityMap[name] = value;
        }
    };

    cinema.events.on('toggle-control-panel', function(event) {
        visibility(event.key, event.visible);
    });

    cinema.views.CompositeWebGlLightView = Backbone.View.extend({
        initialize: function (opts) {
            this.compositeModel = new cinema.decorators.Composite(this.model);
            this._hasAnalysis = _.has(this.model.get('metadata'), 'analysis');
            var sharedData = getSharedData(this.compositeModel, this.$el, this._hasAnalysis);
            this.key = sharedData.key;

            this.controlModel = sharedData.control;
            this.viewpointModel = sharedData.viewpoint;
            this.renderView = sharedData.renderView;

            new cinema.utilities.RenderViewMouseInteractor({
                renderView: this.renderView,
                camera: this.viewpointModel
            }).enableMouseWheelZoom({
                    maxZoomLevel: 10,
                    zoomIncrement: 0.05,
                    invertControl: false
                }).enableDragPan({
                    keyModifiers: cinema.keyModifiers.SHIFT
                }).enableDragRotation({
                    keyModifiers: null
                });

            this.compositeTools = sharedData.compositeToolsWidget;
            this.renderingTools = sharedData.renderingWidget;

            if (this._hasAnalysis) {
                this.controlList = opts.defaultControls.slice(0);
                this.compositeHistogram = sharedData.histogramWidget;
                this.searchInformation = sharedData.informationWidget;
                this.controlList.push(
                    { position: 'center', key: 'histogram', icon: 'icon-chart-bar', title: 'Histogram' }
                );

                sharedData.histogram.fetch();
            } else {
                this.searchInformation = sharedData.metaDataInformationWidget;
            }

            this.listenTo(this.controlModel, 'change', this.refreshCamera);
            this.listenTo(this.viewpointModel, 'change', this.refreshCamera);
            this.listenTo(cinema.events, 'c:resetCamera', this.resetCamera);
        },

        render: function () {
            this.renderView.setElement(this.$('.c-body-container')).render().showViewpoint(true);
            this.compositeTools.setElement(this.$('.c-tools-panel')).render();
            this.renderingTools.setElement(this.$('.c-rendering-panel')).render();
            this.searchInformation.setElement(this.$('.c-information-panel')).render();
            this.$('.c-information-panel').toggle(visibility('information'));
            if (this._hasAnalysis) {
                this.compositeHistogram.setElement(this.$('.c-histogram-panel')).render();
                this.$('.c-histogram-panel').toggle(visibility('histogram'));
            }
            return this;
        },

        refreshCamera: function () {
            if (this.renderView) {
                this.renderView.showViewpoint();
            }
        },

        resetCamera: function () {
            if (this.renderView) {
                this.renderView.showViewpoint();
                this.renderView.resetCamera();
            }
        },

        remove: function () {
            getSharedData(this.compositeModel, this.$el, this._hasAnalysis).remove();

            // SharedData
            freeSharedDataMap(this.key);

            // Connections to SharedData
            this.key = null;

            // Models
            this.controlModel.remove();
            this.viewpointModel.remove();

            // Views
            this.renderView.remove();
            this.compositeTools.remove();
            this.renderingTools.remove();
            if (this._hasAnalysis) {
                this.compositeHistogram.remove();
                this.searchInformation.remove();
            } else {
                this.searchInformation.remove();
            }
        }
    });

    cinema.views.CompositeWebGlLightSearchView = Backbone.View.extend({
        initialize: function (opts) {
            this.compositeModel = new cinema.decorators.Composite(this.model);
            this._hasAnalysis = _.has(this.model.get('metadata'), 'analysis');
            var sharedData = getSharedData(this.compositeModel, this.$el, this._hasAnalysis);
            this.key = sharedData.key;

            this.controlModel = sharedData.control;
            this.viewpointModel = sharedData.viewpoint;
            this.searchTools = sharedData.searchToolsWidget;

            if (this._hasAnalysis) {
                this.searchView = sharedData.searchView;
                this.compositeHistogram = sharedData.histogramWidget;
                this.searchInformation = sharedData.informationWidget;
                this.controlList = opts.defaultControls.slice(0);
                this.controlList.push(
                    { position: 'center', key: 'histogram', icon: 'icon-chart-bar', title: 'Histogram' }
                );
            } else {
                this.searchView = sharedData.metaDataSearchView;
                this.searchInformation = sharedData.metaDataInformationWidget;
            }
        },

        render: function () {
            this.searchView.setElement(this.$('.c-body-container')).render();
            this.searchTools.setElement(this.$('.c-tools-panel')).render();
            this.searchInformation.setElement(this.$('.c-information-panel')).render();
            this.$('.c-information-panel').toggle(visibility('information'));
            if (this._hasAnalysis) {
                this.compositeHistogram.setElement(this.$('.c-histogram-panel')).render();
                this.$('.c-histogram-panel').toggle(visibility('histogram'));
            }
            return this;
        },

        remove: function () {
            getSharedData(this.compositeModel, this.$el, this._hasAnalysis).remove();

            // SharedData
            freeSharedDataMap(this.key);

            // Connections to SharedData
            this.key = null;

            // Models
            this.controlModel.remove();
            this.viewpointModel.remove();

            // Views
            this.searchView.remove();
            this.searchTools.remove();
            if (this._hasAnalysis) {
                this.compositeHistogram.remove();
                this.searchInformation.remove();
            } else {
                this.searchInformation.remove();
            }
        }
    });

    cinema.viewMapper.registerView('composite-image-stack-litdepth', 'view', cinema.views.CompositeWebGlLightView, {
        controls: [
            { position: 'left', key: 'information', icon: 'icon-help', title: 'Information' },
            { position: 'left',  key: 'rendering', icon: 'icon-picture',   title: 'Rendering'},
            { position: 'right', key: 'tools', icon: 'icon-tools', title: 'Tools' }
        ]
    });

    cinema.viewMapper.registerView('composite-image-stack-litdepth', 'search', cinema.views.CompositeWebGlLightSearchView, {
        controls: [
            { position: 'left', key: 'information', icon: 'icon-help', title: 'Information' },
            { position: 'right', key: 'tools', icon: 'icon-tools', title: 'Tools' }
        ]
    });

}());
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2014 Vanderbilt University, All rights reserved.
 *
 * Author: Zsolt Lattmann
 */

define([], function () {
    'use strict';
    function generateGUID() {
        function s4() {
            return Math.floor((1 + Math.random()) * 0x10000).toString(16).substring(1);
        }
        return s4() + s4() + '-' + s4() + '-' + s4() + '-' + s4() + '-' + s4() + s4() + s4();
    }

    var NodeMock = function (core, options) {

        NodeMock._nodes.push(this);

        this.ID = NodeMock._nodes.length;
        if (options.attr) {
            this.attributes = options.attr;
        } else {
            this.attributes = {
                name: ''
            };
        }

        this.registry = {
            DisplayFormat: '',
            PortSVGIcon: '',
            SVGIcon: '',
            decorator: '',
            isAbstract: '',
            isPort: '',
            position: {
                x: 0,
                y: 0
            }
        };

        this.pointers = {
            base: null
        };

        if (options.base) {
            this.pointers.base = core.getPath(options.base);
            if (this.pointers.base) {
            } else {
                throw new Error(options.base + " not found");
            }
        }

        this.collection = {};
        this.path = options.parent ? core.getPath(options.parent) + '/' + this.ID : '/' + this.ID;
        this.guid = generateGUID();
        this.parent = options.parent ? core.getPath(options.parent) : null;
        this.children = [];

        if (options.parent) {
            core.addChild(options.parent, this);
        }
    };

    NodeMock.prototype.clone = function (core, parent, nodes) {
        var orig = this;
        var Temp = function () {
            NodeMock._nodes.push(this);

            this.ID = NodeMock._nodes.length;
            this.guid = generateGUID();
            this.parent = core.getPath(parent);
            this.path = this.parent + '/' + this.ID;
            nodes[this.path] = this;

            this.children = [];
            for (var i = 0; i < orig.children.length; i++) {
                var child = nodes[orig.children[i]].clone(core, this, nodes);
                this.children.push(child.path);
            }

            var copy = JSON.parse(JSON.stringify(orig));
            for (var key in copy) {
                if (orig.hasOwnProperty(key) && !this.hasOwnProperty(key)) {
                    this[key] = copy[key];
                }
            }
        };
        Temp.prototype = NodeMock.prototype;

        var that = new Temp;
        // FIXME: fix pointers
        return that;
    };

    NodeMock._nodes = [];

    return NodeMock;
});<commit_msg>NodeMock: fix clone method: the new node wasnt added to its parent.children<commit_after>/*
 * Copyright (C) 2014 Vanderbilt University, All rights reserved.
 *
 * Author: Zsolt Lattmann
 */

define([], function () {
    'use strict';
    function generateGUID() {
        function s4() {
            return Math.floor((1 + Math.random()) * 0x10000).toString(16).substring(1);
        }
        return s4() + s4() + '-' + s4() + '-' + s4() + '-' + s4() + '-' + s4() + s4() + s4();
    }

    var NodeMock = function (core, options) {

        NodeMock._nodes.push(this);

        this.ID = NodeMock._nodes.length;
        if (options.attr) {
            this.attributes = options.attr;
        } else {
            this.attributes = {
                name: ''
            };
        }

        this.registry = {
            DisplayFormat: '',
            PortSVGIcon: '',
            SVGIcon: '',
            decorator: '',
            isAbstract: '',
            isPort: '',
            position: {
                x: 0,
                y: 0
            }
        };

        this.pointers = {
            base: null
        };

        if (options.base) {
            this.pointers.base = core.getPath(options.base);
            if (this.pointers.base) {
            } else {
                throw new Error(options.base + " not found");
            }
        }

        this.collection = {};
        this.path = options.parent ? core.getPath(options.parent) + '/' + this.ID : '/' + this.ID;
        this.guid = generateGUID();
        this.parent = options.parent ? core.getPath(options.parent) : null;
        this.children = [];

        if (options.parent) {
            core.addChild(options.parent, this);
        }
    };

    NodeMock.prototype.clone = function (core, parent, nodes) {
        var orig = this;
        var Temp = function () {
            NodeMock._nodes.push(this);

            this.ID = NodeMock._nodes.length;
            this.guid = generateGUID();
            this.parent = core.getPath(parent);
            this.path = this.parent + '/' + this.ID;
            nodes[this.path] = this;

            this.children = [];
            for (var i = 0; i < orig.children.length; i++) {
                var child = nodes[orig.children[i]].clone(core, this, nodes);
            }

            var copy = JSON.parse(JSON.stringify(orig));
            for (var key in copy) {
                if (orig.hasOwnProperty(key) && !this.hasOwnProperty(key)) {
                    this[key] = copy[key];
                }
            }
        };
        Temp.prototype = NodeMock.prototype;

        var that = new Temp;
        // FIXME: fix pointers
        parent.children.push(that.path);
        return that;
    };

    NodeMock._nodes = [];

    return NodeMock;
});<|endoftext|>


<commit_before>function Configuration(width, height, colors, magnitudes, specials, types, turns){
    this.width = width;
    this.height = height;
    this.colors = colors;
    this.magnitudes = magnitudes;
    this.specials = specials;
    this.types = types;
    this.allottedTurns = turns;

    this.getRandomShell = function() {
        return new Shell(Util.selectRandom(colors),
                         Util.selectRandom(magnitudes),
                         Util.selectRandom(types),
                         Util.selectRandom(specials));
    }
}
<commit_msg>Added weighted values for magnitudes<commit_after>function Configuration(width, height, colors, magnitudes, specials, types, turns){
    this.width = width;
    this.height = height;
    this.colors = colors;
    this.magnitudes = magnitudes;
    this.specials = specials;
    this.types = types;
    this.allottedTurns = turns;

    this.getRandomShell = function() {
        return new Shell(Util.selectRandom(colors),
                         weightedMagnitude(),
                         Util.selectRandom(types),
                         Util.selectRandom(specials));
    }
    function weightedMagnitude(){
        var weights = new Map([]);
        weights.set(1, .40);
        weights.set(2, .30);
        weights.set(3, .15);
        weights.set(4, .10);
        weights.set(5, .05);
        var p = 1 - Math.random();
        for(var i = 1; i <= 5 ; i++){
            var current = weights.get(i)
            p = p - current;
            if(p <= 0){
                return i;
            }
        }
    }
}
<|endoftext|>


<commit_before>import 'should'
import React from 'react'
import { render, unmountComponentAtNode } from 'react-dom'
import mouseMath from '../src/mouseMath.js'

describe("mouseMath", function() {
  const e = {
    pageX: 50,
    pageY: 50
  }

  describe("isClick", () => {
    it("should accept a valid value", () => {
      mouseMath.isClick(e, { x: 50, y: 50 }, 5).should.be.true
    })

    it("should accept a valid value within tolerance", () => {
      const a = mouseMath.isClick(e, { x: 55, y: 50 }, 5)
      expect(a, "x is 55").to.be.true

      const b = mouseMath.isClick(e, { x: 50, y: 55 }, 5)
      expect(b, "y is 55").to.be.true
    })

    it("should fail outside tolerance", () => {
      const a = mouseMath.isClick(e, { x: 56, y: 50 }, 5)
      expect(a, "x is 56").to.be.false

      const b = mouseMath.isClick(e, { x: 50, y: 44 }, 5)
      expect(b, "y is 44").to.be.false
    })
  })

  describe("createSelectRect", () => {
    mouseMath.createSelectRect(e, { x: 55, y: 55 }).should.eql({
      bottom: 55,
      left: 50,
      right: 55,
      top: 50,
      x: 50,
      y: 50
    })

    mouseMath.createSelectRect(e, { x: 45, y: 45 }).should.eql({
      bottom: 50,
      left: 45,
      right: 50,
      top: 45,
      x: 50,
      y: 50
    })
  })

  describe("getBoundsForNode", () => {
    const mock = {
      offsetWidth: 8,
      offsetHeight: 8,
      getBoundingClientRect() {
        return {
          left: 40,
          top: 40,
          right: 50,
          bottom: 50,
          width: 10,
          height: 10
        }
      }
    }

    mouseMath.getBoundsForNode(mock, () => 0).should
      .eql({
        bottom: 48,
        left: 40,
        right: 48,
        top: 40
      })

    mouseMath.getBoundsForNode(mock, (dir) => dir === 'left' ? 0 : 5).should
      .eql({
        bottom: 53,
        left: 40,
        right: 48,
        top: 45
      })

    mouseMath.getBoundsForNode(mock, (dir) => dir === 'left' ? 5 : 0).should
      .eql({
        bottom: 48,
        left: 45,
        right: 53,
        top: 40
      })

    mock.offsetHeight = 10
    mock.offsetWidth = 10

    mouseMath.getBoundsForNode(mock, () => 0).should
      .eql({
        bottom: 50,
        left: 40,
        right: 50,
        top: 40
      })

    mock.offsetHeight = undefined
    mock.offsetWidth = undefined

    mouseMath.getBoundsForNode(mouseMath.getBoundsForNode(mock, () => 0)).should
      .eql({
        bottom: 40,
        left: 40,
        right: 40,
        top: 40
      })
  })

  describe("pageOffset", () => {
    const mockwin = {}

    it("should return 0 by default", () => {
      const a = mouseMath.pageOffset('left', false, mockwin)
      expect(a).to.equal(0)
      const b = mouseMath.pageOffset('top', false, mockwin)
      expect(b).to.equal(0)
    })

    it("should return pageXOffset/pageYOffset", () => {
      mockwin.pageXOffset = 4
      mockwin.pageYOffset = 3
      const a = mouseMath.pageOffset('left', false, mockwin)
      expect(a).to.equal(4)
      const b = mouseMath.pageOffset('top', false, mockwin)
      expect(b).to.equal(3)
    })

    it("should return parent pageXOffset/pageYOffset as first choice", () => {
      mockwin.pageXOffset = 2
      mockwin.pageYOffset = 1
      const a = mouseMath.pageOffset('left', false, mockwin)
      expect(a).to.equal(2)
      const b = mouseMath.pageOffset('top', false, mockwin)
      expect(b).to.equal(1)
    })

    it("should throw on incorrect direction", () => {
      (() => mouseMath.pageOffset('foo', mockwin)).should.throw("direction must be one of top or left, was \"foo\"")
    })
  })

  describe("browser-specific tests", function() {
    beforeEach(() => {
      if (window.____isjsdom) return
      window.scroll(0,0)
      const iOS = /iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream

      if (iOS) window.parent.window.scroll(0,0)
    })

    it("pageOffset: should return the correct page offset", function() {
      if (window.____isjsdom) return
      var div = document.createElement('div');
      div.style.cssText = 'height: 13000px;width:13000px'
      div.innerText= 'hi'

      document.body.insertBefore(div, document.body.firstElementChild)

      window.scroll(20,20)
      const iOS = /iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream

      if (iOS) window.parent.window.scroll(20,20)

      const a = mouseMath.pageOffset('left')
      const b = mouseMath.pageOffset('top')

      // console.log('y', window.pageYOffset, window.parent.window.pageYOffset, b)
      // console.log('x', window.pageXOffset, window.parent.window.pageXOffset, a)

      expect(b).to.equal(20, "top should be 20")
      expect(a).to.equal(20, "left should be 20")
    })
    it("contains: should detect point inside", () => {
      if (window.____isjsdom) return
      var div = document.createElement('div');
      div.style.cssText = 'height: 50px;width:50px;position:absolute;top:5px;left:5px;'
      div.innerText= 'hi'
      div.id = 'foo'

      document.body.appendChild(div)

      const a = mouseMath.contains(div, 6, 6)
      expect(a).to.equal(true)
    })

    it("contains: should detect point outside", () => {
      if (window.____isjsdom) return
      var div = document.createElement('div');
      div.style.cssText = 'height: 50px;width:50px;position:absolute;top:5px;left:5px;'
      div.innerText= 'hi'
      div.id = 'foo'

      document.body.appendChild(div)

      const a = mouseMath.contains(div, 400, 400)
      expect(a).to.equal(false)
    })

    it("getBoundsForNode: no scroll", () => {
      if (window.____isjsdom) return
      var div = document.createElement('div');
      div.style.cssText = 'height: 50px;width:50px;position:absolute;top:5px;left:5px;'
      div.innerText= 'hi'
      div.id = 'foo'

      document.body.appendChild(div)

      const a = mouseMath.getBoundsForNode(div)
      a.should.eql({
        top: 5,
        left: 5,
        right: 55,
        bottom: 55
      })
    })

    it("getBoundsForNode: with scroll", () => {
      if (window.____isjsdom) return
      var div = document.createElement('div');
      div.style.cssText = 'height: 50px;width:50px;position:absolute;top:5px;left:5px;'
      div.innerText= 'hi'
      div.id = 'foo'

      var div1 = document.createElement('div');
      div1.style.cssText = 'height: 13000px;width:13000px'
      div1.innerText= 'hi'

      document.body.insertBefore(div, document.body.firstElementChild)
      document.body.appendChild(div)

      // console.log('before', div.getBoundingClientRect())

      window.scroll(20,20)
      const iOS = /iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream

      if (iOS) window.parent.window.scroll(20,20)

      const aa = mouseMath.pageOffset('left')
      const bb = mouseMath.pageOffset('top')

      expect(bb).to.equal(20, "top should be 20")
      expect(aa).to.equal(20, "left should be 20")

      // console.log('y', window.pageYOffset, window.parent.window.pageYOffset, bb)
      // console.log('x', window.pageXOffset, window.parent.window.pageXOffset, aa)
      // console.log('after', div.getBoundingClientRect())

      const a = mouseMath.getBoundsForNode(div)
      // console.log(a)
      a.should.eql({
        top: 5,
        left: 5,
        right: 55,
        bottom: 55
      })
    })
  })

  describe("objectsCollide", () => {
    const obj = {
      top: 50,
      left: 50,
      right: 55,
      bottom: 55
    }

    it("should detect no collision when there is none", () => {
      mouseMath.objectsCollide(obj, {
        top: 56,
        left: 56,
        right: 66,
        bottom: 66
      }).should.eql(false)
    })

    it("should detect a collision when tolerance would make it", () => {
      mouseMath.objectsCollide(obj, {
        top: 40,
        left: 40,
        right: 49,
        bottom: 49
      }, 1).should.eql(true, 'tolerance collision failed')
    })

    it("should detect a collision with a mouse click", () => {
      mouseMath.objectsCollide(obj, {
        top: 50,
        left: 50
      }).should.eql(true, '50')

      mouseMath.objectsCollide(obj, {
        top: 55,
        left: 55
      }).should.eql(true, '55')

      mouseMath.objectsCollide(obj, {
        top: 53,
        left: 53
      }).should.eql(true, '53')
    })

    it("should fail a collision", () => {
      mouseMath.objectsCollide({
        top: 55,
        left: 56
      }, obj).should.eql(false)
    })
  })

  describe("contains", () => {
    it("should return true for no element", () => {
      mouseMath.contains(false, 1, 0, null).should.eql(true)
    })

    it("should call elementFromPoint and contains", () => {
      const doc = {
        elementFromPoint: sinon.stub()
      }
      const elm = {
        contains: sinon.spy()
      }

      doc.elementFromPoint.returns('hi')

      mouseMath.contains(elm, 1, 2, doc)

      doc.elementFromPoint.called.should.eql(true, 'elementFromPoint was not called')
      elm.contains.called.should.eql(true, 'contains was not called')

      doc.elementFromPoint.calledWithExactly(1, 2).should.eql(true, 'called with point values')
      elm.contains.calledWithExactly('hi').should.eql(true, 'called with elementFromPoint return value')
    })
  })

  describe("getCoordinates", () => {
    it("should extract clientX and company", () => {
      mouseMath.getCoordinates({
        clientX: 1,
        foo: 3,
        clientY: 2,
        pageX: 3,
        pageY: 4
      }, 1).should.eql({
        clientX: 1,
        clientY: 2,
        pageX: 3,
        pageY: 4
      })
    })

    it("should extract clientX and company, mobile", () => {
      mouseMath.getCoordinates({
        clientX: 9,
        touches: [{
          clientX: 5,
          clientY: 6,
          pageX: 7,
          pageY: 8,
          identifier: 0
        }, {
          clientX: 1,
          clientY: 2,
          pageX: 3,
          pageY: 4,
          identifier: 1
        }],
        clientY: 10,
        pageX: 11,
        pageY: 12
      }, 1).should.eql({
        clientX: 1,
        clientY: 2,
        pageX: 3,
        pageY: 4
      })
    })

    it("should extract clientX and company, mobile", () => {
      mouseMath.getCoordinates({
        clientX: 9,
        touches: [{
          clientX: 5,
          clientY: 6,
          pageX: 7,
          pageY: 8,
          identifier: 0
        }, {
          clientX: 1,
          clientY: 2,
          pageX: 3,
          pageY: 4,
          identifier: 1
        }],
        clientY: 10,
        pageX: 11,
        pageY: 12
      }, 5, {
        warn: (t) => t.should.eql('no touch found with identifier')
      }).should.eql({
        clientX: 5,
        clientY: 6,
        pageX: 7,
        pageY: 8
      })
    })
  })
})
<commit_msg>see if we can make this test more reliable on IE<commit_after>import 'should'
import React from 'react'
import { render, unmountComponentAtNode } from 'react-dom'
import mouseMath from '../src/mouseMath.js'

describe("mouseMath", function() {
  const e = {
    pageX: 50,
    pageY: 50
  }

  describe("isClick", () => {
    it("should accept a valid value", () => {
      mouseMath.isClick(e, { x: 50, y: 50 }, 5).should.be.true
    })

    it("should accept a valid value within tolerance", () => {
      const a = mouseMath.isClick(e, { x: 55, y: 50 }, 5)
      expect(a, "x is 55").to.be.true

      const b = mouseMath.isClick(e, { x: 50, y: 55 }, 5)
      expect(b, "y is 55").to.be.true
    })

    it("should fail outside tolerance", () => {
      const a = mouseMath.isClick(e, { x: 56, y: 50 }, 5)
      expect(a, "x is 56").to.be.false

      const b = mouseMath.isClick(e, { x: 50, y: 44 }, 5)
      expect(b, "y is 44").to.be.false
    })
  })

  describe("createSelectRect", () => {
    mouseMath.createSelectRect(e, { x: 55, y: 55 }).should.eql({
      bottom: 55,
      left: 50,
      right: 55,
      top: 50,
      x: 50,
      y: 50
    })

    mouseMath.createSelectRect(e, { x: 45, y: 45 }).should.eql({
      bottom: 50,
      left: 45,
      right: 50,
      top: 45,
      x: 50,
      y: 50
    })
  })

  describe("getBoundsForNode", () => {
    const mock = {
      offsetWidth: 8,
      offsetHeight: 8,
      getBoundingClientRect() {
        return {
          left: 40,
          top: 40,
          right: 50,
          bottom: 50,
          width: 10,
          height: 10
        }
      }
    }

    mouseMath.getBoundsForNode(mock, () => 0).should
      .eql({
        bottom: 48,
        left: 40,
        right: 48,
        top: 40
      })

    mouseMath.getBoundsForNode(mock, (dir) => dir === 'left' ? 0 : 5).should
      .eql({
        bottom: 53,
        left: 40,
        right: 48,
        top: 45
      })

    mouseMath.getBoundsForNode(mock, (dir) => dir === 'left' ? 5 : 0).should
      .eql({
        bottom: 48,
        left: 45,
        right: 53,
        top: 40
      })

    mock.offsetHeight = 10
    mock.offsetWidth = 10

    mouseMath.getBoundsForNode(mock, () => 0).should
      .eql({
        bottom: 50,
        left: 40,
        right: 50,
        top: 40
      })

    mock.offsetHeight = undefined
    mock.offsetWidth = undefined

    mouseMath.getBoundsForNode(mouseMath.getBoundsForNode(mock, () => 0)).should
      .eql({
        bottom: 40,
        left: 40,
        right: 40,
        top: 40
      })
  })

  describe("pageOffset", () => {
    const mockwin = {}

    it("should return 0 by default", () => {
      const a = mouseMath.pageOffset('left', false, mockwin)
      expect(a).to.equal(0)
      const b = mouseMath.pageOffset('top', false, mockwin)
      expect(b).to.equal(0)
    })

    it("should return pageXOffset/pageYOffset", () => {
      mockwin.pageXOffset = 4
      mockwin.pageYOffset = 3
      const a = mouseMath.pageOffset('left', false, mockwin)
      expect(a).to.equal(4)
      const b = mouseMath.pageOffset('top', false, mockwin)
      expect(b).to.equal(3)
    })

    it("should return parent pageXOffset/pageYOffset as first choice", () => {
      mockwin.pageXOffset = 2
      mockwin.pageYOffset = 1
      const a = mouseMath.pageOffset('left', false, mockwin)
      expect(a).to.equal(2)
      const b = mouseMath.pageOffset('top', false, mockwin)
      expect(b).to.equal(1)
    })

    it("should throw on incorrect direction", () => {
      (() => mouseMath.pageOffset('foo', mockwin)).should.throw("direction must be one of top or left, was \"foo\"")
    })
  })

  describe("browser-specific tests", function() {
    beforeEach(() => {
      if (window.____isjsdom) return
      window.scroll(0,0)
      const iOS = /iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream

      if (iOS) window.parent.window.scroll(0,0)
    })

    it("pageOffset: should return the correct page offset", function() {
      if (window.____isjsdom) return
      var div = document.createElement('div');
      div.style.cssText = 'height: 13000px;width:13000px'
      div.innerText= 'hi'

      document.body.insertBefore(div, document.body.firstElementChild)

      window.scroll(20,20)
      const iOS = /iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream

      if (iOS) window.parent.window.scroll(20,20)

      const a = mouseMath.pageOffset('left')
      const b = mouseMath.pageOffset('top')

      // console.log('y', window.pageYOffset, window.parent.window.pageYOffset, b)
      // console.log('x', window.pageXOffset, window.parent.window.pageXOffset, a)

      expect(b).to.equal(20, "top should be 20")
      expect(a).to.equal(20, "left should be 20")
    })
    it("contains: should detect point inside", () => {
      if (window.____isjsdom) return
      var div = document.createElement('div');
      div.style.cssText = 'height: 50px;width:50px;position:absolute;top:5px;left:5px;'
      div.innerText= 'hi'
      div.id = 'foo'

      document.body.appendChild(div)

      const a = mouseMath.contains(div, 25, 25)
      expect(a).to.equal(true)
    })

    it("contains: should detect point outside", () => {
      if (window.____isjsdom) return
      var div = document.createElement('div');
      div.style.cssText = 'height: 50px;width:50px;position:absolute;top:5px;left:5px;'
      div.innerText= 'hi'
      div.id = 'foo'

      document.body.appendChild(div)

      const a = mouseMath.contains(div, 400, 400)
      expect(a).to.equal(false)
    })

    it("getBoundsForNode: no scroll", () => {
      if (window.____isjsdom) return
      var div = document.createElement('div');
      div.style.cssText = 'height: 50px;width:50px;position:absolute;top:5px;left:5px;'
      div.innerText= 'hi'
      div.id = 'foo'

      document.body.appendChild(div)

      const a = mouseMath.getBoundsForNode(div)
      a.should.eql({
        top: 5,
        left: 5,
        right: 55,
        bottom: 55
      })
    })

    it("getBoundsForNode: with scroll", () => {
      if (window.____isjsdom) return
      var div = document.createElement('div');
      div.style.cssText = 'height: 50px;width:50px;position:absolute;top:5px;left:5px;'
      div.innerText= 'hi'
      div.id = 'foo'

      var div1 = document.createElement('div');
      div1.style.cssText = 'height: 13000px;width:13000px'
      div1.innerText= 'hi'

      document.body.insertBefore(div, document.body.firstElementChild)
      document.body.appendChild(div)

      // console.log('before', div.getBoundingClientRect())

      window.scroll(20,20)
      const iOS = /iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream

      if (iOS) window.parent.window.scroll(20,20)

      const aa = mouseMath.pageOffset('left')
      const bb = mouseMath.pageOffset('top')

      expect(bb).to.equal(20, "top should be 20")
      expect(aa).to.equal(20, "left should be 20")

      // console.log('y', window.pageYOffset, window.parent.window.pageYOffset, bb)
      // console.log('x', window.pageXOffset, window.parent.window.pageXOffset, aa)
      // console.log('after', div.getBoundingClientRect())

      const a = mouseMath.getBoundsForNode(div)
      // console.log(a)
      a.should.eql({
        top: 5,
        left: 5,
        right: 55,
        bottom: 55
      })
    })
  })

  describe("objectsCollide", () => {
    const obj = {
      top: 50,
      left: 50,
      right: 55,
      bottom: 55
    }

    it("should detect no collision when there is none", () => {
      mouseMath.objectsCollide(obj, {
        top: 56,
        left: 56,
        right: 66,
        bottom: 66
      }).should.eql(false)
    })

    it("should detect a collision when tolerance would make it", () => {
      mouseMath.objectsCollide(obj, {
        top: 40,
        left: 40,
        right: 49,
        bottom: 49
      }, 1).should.eql(true, 'tolerance collision failed')
    })

    it("should detect a collision with a mouse click", () => {
      mouseMath.objectsCollide(obj, {
        top: 50,
        left: 50
      }).should.eql(true, '50')

      mouseMath.objectsCollide(obj, {
        top: 55,
        left: 55
      }).should.eql(true, '55')

      mouseMath.objectsCollide(obj, {
        top: 53,
        left: 53
      }).should.eql(true, '53')
    })

    it("should fail a collision", () => {
      mouseMath.objectsCollide({
        top: 55,
        left: 56
      }, obj).should.eql(false)
    })
  })

  describe("contains", () => {
    it("should return true for no element", () => {
      mouseMath.contains(false, 1, 0, null).should.eql(true)
    })

    it("should call elementFromPoint and contains", () => {
      const doc = {
        elementFromPoint: sinon.stub()
      }
      const elm = {
        contains: sinon.spy()
      }

      doc.elementFromPoint.returns('hi')

      mouseMath.contains(elm, 1, 2, doc)

      doc.elementFromPoint.called.should.eql(true, 'elementFromPoint was not called')
      elm.contains.called.should.eql(true, 'contains was not called')

      doc.elementFromPoint.calledWithExactly(1, 2).should.eql(true, 'called with point values')
      elm.contains.calledWithExactly('hi').should.eql(true, 'called with elementFromPoint return value')
    })
  })

  describe("getCoordinates", () => {
    it("should extract clientX and company", () => {
      mouseMath.getCoordinates({
        clientX: 1,
        foo: 3,
        clientY: 2,
        pageX: 3,
        pageY: 4
      }, 1).should.eql({
        clientX: 1,
        clientY: 2,
        pageX: 3,
        pageY: 4
      })
    })

    it("should extract clientX and company, mobile", () => {
      mouseMath.getCoordinates({
        clientX: 9,
        touches: [{
          clientX: 5,
          clientY: 6,
          pageX: 7,
          pageY: 8,
          identifier: 0
        }, {
          clientX: 1,
          clientY: 2,
          pageX: 3,
          pageY: 4,
          identifier: 1
        }],
        clientY: 10,
        pageX: 11,
        pageY: 12
      }, 1).should.eql({
        clientX: 1,
        clientY: 2,
        pageX: 3,
        pageY: 4
      })
    })

    it("should extract clientX and company, mobile", () => {
      mouseMath.getCoordinates({
        clientX: 9,
        touches: [{
          clientX: 5,
          clientY: 6,
          pageX: 7,
          pageY: 8,
          identifier: 0
        }, {
          clientX: 1,
          clientY: 2,
          pageX: 3,
          pageY: 4,
          identifier: 1
        }],
        clientY: 10,
        pageX: 11,
        pageY: 12
      }, 5, {
        warn: (t) => t.should.eql('no touch found with identifier')
      }).should.eql({
        clientX: 5,
        clientY: 6,
        pageX: 7,
        pageY: 8
      })
    })
  })
})
<|endoftext|>


<commit_before>/*global suso, describe, it, expect */
/*jslint plusplus: true */

(function () {
	"use strict";

	describe("suso.filter member", function () {
		var emptyObj = {}, sourceObj = { a: 3, b: 4 };

		it("exists in suso namespace", function () {
			expect(suso.filter).toBeDefined();
		});

		it("is a function", function () {
			expect(typeof suso.filter).toBe("function");
		});

		it("throws an exception when no object is passed", function () {
			expect(function () { suso.filter(); }).toThrow(new Error("Filter object not specified"));
		});

		it("throws an exception when non-object is passed", function () {
			expect(function () { suso.filter(0); }).toThrow(new Error("Filter object not specified"));
		});

		it("throws an exception when no function is passed", function () {
			expect(function () { suso.filter({}); }).toThrow(new Error("Filter function not specified"));
		});

		it("throws an exception when non-function is passed", function () {
			expect(function () { suso.filter({}, 0); }).toThrow(new Error("Filter function not specified"));
		});

		it("returns object with all properties when function always returns true", function () {
			var result;

			result = suso.filter(sourceObj, function () { return true; });

			expect(result).toEqual(sourceObj);
		});

		it("returns object with no properties when function always returns false", function () {
			var result;

			result = suso.filter(sourceObj, function () { return false; });

			expect(result).toEqual(emptyObj);
		});

		it("returns object with expected properties when function filters by value", function () {
			var result;

			result = suso.filter(sourceObj, function (el) { return el === 3; });

			expect(result).toEqual({ a: 3 });
		});

		it("returns object with expected properties when function filters by index", function () {
			var result;

			result = suso.filter(sourceObj, function (el, idx) { return idx === "b"; });

			expect(result).toEqual({ b: 4 });
		});

		it("ignores inherited properties", function () {
			var obj, result;

			function Obj() { }
			Obj.prototype = sourceObj;
			obj = new Obj();

			result = suso.filter(obj, function () { return true; });

			expect(obj.a).toBe(3);
			expect(obj.b).toBe(4);
			expect(result).toEqual({});
		});
	});

	describe("suso.forEach member", function () {
		var fullObj = { a: 1, b: 2, c: 3 };

		it("exists on the suso namespace", function () {
			expect(suso.forEach).toBeDefined();
		});

		it("is a function", function () {
			expect(typeof suso.forEach).toBe("function");
		});

		it("throws an exception when no object is passed", function () {
			expect(function () { suso.forEach(); }).toThrow(new Error("ForEach object not specified"));
		});

		it("throws an exception when non-object is passed", function () {
			expect(function () { suso.forEach(0); }).toThrow(new Error("ForEach object not specified"));
		});

		it("throws an exception when no function is passed", function () {
			expect(function () { suso.forEach({}); }).toThrow(new Error("ForEach function not specified"));
		});

		it("throws an exception when non-function is passed", function () {
			expect(function () { suso.forEach({}, 0); }).toThrow(new Error("ForEach function not specified"));
		});

		it("calls function for each property of object", function () {
			var count = 0;

			suso.forEach(fullObj, function () { count++; });

			expect(count).toBe(3);
		});

		it("returns copy of source obj when no value returned from passed function", function () {
			var result, count = 0;

			result = suso.forEach(fullObj, function () { count++; });

			expect(result).toEqual(fullObj);	// it's a new object with the same properties.
			expect(result).not.toBe(fullObj);	// it's not the same object.
		});

		it("returns mapped properties when value is returned from passed function", function () {
			var result;

			result = suso.forEach(fullObj, function (el) { return el * 2; });

			expect(result).toEqual({ a: 2, b: 4, c: 6 });
		});

		it("ignores inherited properties", function () {
			var obj, count = 0;

			function Obj() { }
			Obj.prototype = fullObj;
			obj = new Obj();
			obj.x = 0;

			suso.forEach(obj, function () { count++; });

			expect(obj.a).toBe(1);
			expect(obj.b).toBe(2);
			expect(obj.c).toBe(3);
			expect(count).toBe(1);
		});
	});

	describe("suso.sets member", function () {
		it("exists on the namespace", function () {
			expect(suso.sets).toBeDefined();
		});

		it("is a function", function () {
			expect(typeof suso.sets).toBe("function");
		});

		it("throws an error if array parameter is null", function () {
			expect(function () { suso.sets(); }).toThrow(new Error("arr parameter is not an array"));
		});

		it("throws an error if array parameter is not an array", function () {
			expect(function () { suso.sets({}); }).toThrow(new Error("arr parameter is not an array"));
		});

		it("throws an error if not provided with a size", function () {
			expect(function () { suso.sets([]); }).toThrow(new Error("size parameter is not a valid number"));
		});

		it("throws an error if size parameter is not a number", function () {
			expect(function () { suso.sets([], "two"); }).toThrow(new Error("size parameter is not a valid number"));
		});

		it("throws an error if val parameter is passed a non-function", function () {
			expect(function () { suso.sets([], 1, "x"); }).toThrow(new Error("val parameter is not a function"));
		});

		it("returns empty array when size > array length", function () {
			expect(suso.sets([1, 2, 3], 4)).toEqual([]);
		});

		it("returns empty array for size 0", function () {
			expect(suso.sets([1, 2, 3], 0)).toEqual([]);
		});

		it("returns array for size 1", function () {
			expect(suso.sets([1, 2, 3], 1)).toEqual([1, 2, 3]);
		});

		it("returns all pairs for size 2", function () {
			expect(suso.sets([1, 2, 3], 2)).toEqual([[1, 2], [1, 3], [2, 3]]);
		});

		it("returns all triplets for size 3", function () {
			expect(suso.sets([1, 2, 3, 4], 3)).toEqual([[1, 2, 3], [1, 2, 4], [1, 3, 4], [2, 3, 4]]);
		});

		it("returns all quads for size 4", function () {
			expect(suso.sets([1, 2, 3, 4, 5], 4)).toEqual([ [1, 2, 3, 4], [1, 2, 3, 5], [1, 2, 4, 5], [1, 3, 4, 5], [2, 3, 4, 5] ]);
		});

		it("returns array with array as only element for size == array length", function () {
			expect(suso.sets([1, 2, 3], 3)).toEqual([1, 2, 3]);
		});

		it("returns all pairs of three objects when a valid obj-comparison function passed in", function () {
			var obj1 = { name: 1 }, obj2 = { name: 2 }, obj3 = { name: 3 },
				arr = [ obj1, obj2, obj3 ];

			expect(suso.sets(arr, 2, function (el) { return el.name; })).toEqual([ [obj1, obj2], [obj1, obj3], [obj2, obj3] ]);
		});
	});
}());
<commit_msg>jason wrote a test!<commit_after>/*global suso, describe, it, expect */
/*jslint plusplus: true */

(function () {
	"use strict";

	describe("suso.filter member", function () {
		var emptyObj = {}, sourceObj = { a: 3, b: 4 };

		it("exists in suso namespace", function () {
			expect(suso.filter).toBeDefined();
		});

		it("is a function", function () {
			expect(typeof suso.filter).toBe("function");
		});

		it("throws an exception when no object is passed", function () {
			expect(function () { suso.filter(); }).toThrow(new Error("Filter object not specified"));
		});

		it("throws an exception when non-object is passed", function () {
			expect(function () { suso.filter(0); }).toThrow(new Error("Filter object not specified"));
		});

		it("throws an exception when no function is passed", function () {
			expect(function () { suso.filter({}); }).toThrow(new Error("Filter function not specified"));
		});

		it("throws an exception when non-function is passed", function () {
			expect(function () { suso.filter({}, 0); }).toThrow(new Error("Filter function not specified"));
		});

		it("returns object with all properties when function always returns true", function () {
			var result;

			result = suso.filter(sourceObj, function () { return true; });

			expect(result).toEqual(sourceObj);
		});

		it("returns object with no properties when function always returns false", function () {
			var result;

			result = suso.filter(sourceObj, function () { return false; });

			expect(result).toEqual(emptyObj);
		});

		it("returns object with expected properties when function filters by value", function () {
			var result;

			result = suso.filter(sourceObj, function (el) { return el === 3; });

			expect(result).toEqual({ a: 3 });
		});

		it("returns object with expected properties when function filters by index", function () {
			var result;

			result = suso.filter(sourceObj, function (el, idx) { return idx === "b"; });

			expect(result).toEqual({ b: 4 });
		});

		it("ignores inherited properties", function () {
			var obj, result;

			function Obj() { }
			Obj.prototype = sourceObj;
			obj = new Obj();

			result = suso.filter(obj, function () { return true; });

			expect(obj.a).toBe(3);
			expect(obj.b).toBe(4);
			expect(result).toEqual({});
		});
	});

	describe("suso.forEach member", function () {
		var fullObj = { a: 1, b: 2, c: 3 };

		it("exists on the suso namespace", function () {
			expect(suso.forEach).toBeDefined();
		});

		it("is a function", function () {
			expect(typeof suso.forEach).toBe("function");
		});

		it("throws an exception when no object is passed", function () {
			expect(function () { suso.forEach(); }).toThrow(new Error("ForEach object not specified"));
		});

		it("throws an exception when non-object is passed", function () {
			expect(function () { suso.forEach(0); }).toThrow(new Error("ForEach object not specified"));
		});

		it("throws an exception when no function is passed", function () {
			expect(function () { suso.forEach({}); }).toThrow(new Error("ForEach function not specified"));
		});

		it("throws an exception when non-function is passed", function () {
			expect(function () { suso.forEach({}, 0); }).toThrow(new Error("ForEach function not specified"));
		});

		it("calls function for each property of object", function () {
			var count = 0;

			suso.forEach(fullObj, function () { count++; });

			expect(count).toBe(3);
		});

		it("returns copy of source obj when no value returned from passed function", function () {
			var result, count = 0;

			result = suso.forEach(fullObj, function () { count++; });

			expect(result).toEqual(fullObj);	// it's a new object with the same properties.
			expect(result).not.toBe(fullObj);	// it's not the same object.
		});

		it("returns mapped properties when value is returned from passed function", function () {
			var result;

			result = suso.forEach(fullObj, function (el) { return el * 2; });

			expect(result).toEqual({ a: 2, b: 4, c: 6 });
		});

		it("ignores inherited properties", function () {
			var obj, count = 0;

			function Obj() { }
			Obj.prototype = fullObj;
			obj = new Obj();
			obj.x = 0;

			suso.forEach(obj, function () { count++; });

			expect(obj.a).toBe(1);
			expect(obj.b).toBe(2);
			expect(obj.c).toBe(3);
			expect(count).toBe(1);
		});
	});

	describe("suso.sets member", function () {
		it("exists on the namespace", function () {
			expect(suso.sets).toBeDefined();
		});

		it("is a function", function () {
			expect(typeof suso.sets).toBe("function");
		});

		it("throws an error if array parameter is null", function () {
			expect(function () { suso.sets(); }).toThrow(new Error("arr parameter is not an array"));
		});

		it("throws an error if array parameter is not an array", function () {
			expect(function () { suso.sets({}); }).toThrow(new Error("arr parameter is not an array"));
		});

		it("throws an error if not provided with a size", function () {
			expect(function () { suso.sets([]); }).toThrow(new Error("size parameter is not a valid number"));
		});

		it("throws an error if size parameter is not a number", function () {
			expect(function () { suso.sets([], "two"); }).toThrow(new Error("size parameter is not a valid number"));
		});

		it("throws an error if val parameter is passed a non-function", function () {
			expect(function () { suso.sets([], 1, "x"); }).toThrow(new Error("val parameter is not a function"));
		});

		it("returns empty array when size > array length", function () {
			expect(suso.sets([1, 2, 3], 4)).toEqual([]);
		});

		it("returns empty array for size 0", function () {
			expect(suso.sets([1, 2, 3], 0)).toEqual([]);
		});

		it("returns array for size 1", function () {
			expect(suso.sets([1, 2, 3], 1)).toEqual([1, 2, 3]);
		});

		it("returns all pairs for size 2", function () {
			expect(suso.sets([1, 2, 3], 2)).toEqual([[1, 2], [1, 3], [2, 3]]);
		});

		it("returns all pairs for size 2 when array > n+1", function () {
			expect(suso.sets([1, 2, 3, 4, 5], 2)).toEqual([[1, 2], [1, 3], [1, 4], [1, 5], [2, 3], [2, 4], [2, 5], [3, 4], [3, 5], [4, 5]]);
		});

		it("returns all triplets for size 3", function () {
			expect(suso.sets([1, 2, 3, 4], 3)).toEqual([[1, 2, 3], [1, 2, 4], [1, 3, 4], [2, 3, 4]]);
		});

		it("returns all quads for size 4", function () {
			expect(suso.sets([1, 2, 3, 4, 5], 4)).toEqual([ [1, 2, 3, 4], [1, 2, 3, 5], [1, 2, 4, 5], [1, 3, 4, 5], [2, 3, 4, 5] ]);
		});

		it("returns array with array as only element for size == array length", function () {
			expect(suso.sets([1, 2, 3], 3)).toEqual([1, 2, 3]);
		});

		it("returns all pairs of three objects when a valid obj-comparison function passed in", function () {
			var obj1 = { name: 1 }, obj2 = { name: 2 }, obj3 = { name: 3 },
				arr = [ obj1, obj2, obj3 ];

			expect(suso.sets(arr, 2, function (el) { return el.name; })).toEqual([ [obj1, obj2], [obj1, obj3], [obj2, obj3] ]);
		});
	});
}());
<|endoftext|>