diff --git a/build/compassql.js b/build/compassql.js new file mode 100644 index 00000000..9abc6713 --- /dev/null +++ b/build/compassql.js @@ -0,0 +1,10156 @@ +(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.cql = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o= opt.minCardinalityForBin; + } + return true; + } + }, { + name: 'binAppliedForQuantitative', + description: 'bin should be applied to quantitative field only.', + properties: [property_1.Property.TYPE, property_1.Property.BIN], + allowWildcardForProperties: false, + strict: true, + satisfy: function (fieldQ, _, __, ___) { + if (fieldQ.bin) { + // If binned, the type must be quantitative + return fieldQ.type === type_1.Type.QUANTITATIVE; + } + return true; + } + }, { + name: 'channelFieldCompatible', + description: "encoding channel's range type be compatible with channel type.", + properties: [property_1.Property.CHANNEL, property_1.Property.TYPE, property_1.Property.BIN, property_1.Property.TIMEUNIT], + allowWildcardForProperties: false, + strict: true, + satisfy: function (fieldQ, _, encWildcardIndex, opt) { + var fieldDef = __assign({ field: 'f' }, encoding_1.toFieldDef(fieldQ, ['bin', 'timeUnit', 'type'])); + return fielddef_1.channelCompatibility(fieldDef, fieldQ.channel).compatible; + } + }, { + name: 'hasFn', + description: 'A field with as hasFn flag should have one of aggregate, timeUnit, or bin.', + properties: [property_1.Property.AGGREGATE, property_1.Property.BIN, property_1.Property.TIMEUNIT], + allowWildcardForProperties: true, + strict: true, + satisfy: function (fieldQ, _, __, ___) { + if (fieldQ.hasFn) { + return !!fieldQ.aggregate || !!fieldQ.bin || !!fieldQ.timeUnit; + } + return true; + } + }, { + name: 'omitScaleZeroWithBinnedField', + description: 'Do not use scale zero with binned field', + properties: [property_1.Property.SCALE, property_1.getEncodingNestedProp('scale', 'zero'), property_1.Property.BIN], + allowWildcardForProperties: false, + strict: true, + satisfy: function (fieldQ, _, __, ___) { + if (fieldQ.bin && fieldQ.scale) { + if (fieldQ.scale.zero === true) { + return false; + } + } + return true; + } + }, { + name: 'onlyOneTypeOfFunction', + description: 'Only of of aggregate, autoCount, timeUnit, or bin should be applied at the same time.', + properties: [property_1.Property.AGGREGATE, property_1.Property.AUTOCOUNT, property_1.Property.TIMEUNIT, property_1.Property.BIN], + allowWildcardForProperties: true, + strict: true, + satisfy: function (fieldQ, _, __, ___) { + if (encoding_1.isFieldQuery(fieldQ)) { + var numFn = (!wildcard_1.isWildcard(fieldQ.aggregate) && !!fieldQ.aggregate ? 1 : 0) + + (!wildcard_1.isWildcard(fieldQ.bin) && !!fieldQ.bin ? 1 : 0) + + (!wildcard_1.isWildcard(fieldQ.timeUnit) && !!fieldQ.timeUnit ? 1 : 0); + return numFn <= 1; + } + // For autoCount there is always only one type of function + return true; + } + }, { + name: 'timeUnitAppliedForTemporal', + description: 'Time unit should be applied to temporal field only.', + properties: [property_1.Property.TYPE, property_1.Property.TIMEUNIT], + allowWildcardForProperties: false, + strict: true, + satisfy: function (fieldQ, _, __, ___) { + if (fieldQ.timeUnit && fieldQ.type !== type_1.Type.TEMPORAL) { + return false; + } + return true; + } + }, { + name: 'timeUnitShouldHaveVariation', + description: 'A particular time unit should be applied only if they produce unique values.', + properties: [property_1.Property.TIMEUNIT, property_1.Property.TYPE], + allowWildcardForProperties: false, + strict: false, + satisfy: function (fieldQ, schema, encWildcardIndex, opt) { + if (fieldQ.timeUnit && fieldQ.type === type_1.Type.TEMPORAL) { + if (!encWildcardIndex.has('timeUnit') && !opt.constraintManuallySpecifiedValue) { + // Do not have to check this as this is manually specified by users. + return true; + } + return schema.timeUnitHasVariation(fieldQ); + } + return true; + } + }, { + name: 'scalePropertiesSupportedByScaleType', + description: 'Scale properties must be supported by correct scale type', + properties: [].concat(property_1.SCALE_PROPS, [property_1.Property.SCALE, property_1.Property.TYPE]), + allowWildcardForProperties: true, + strict: true, + satisfy: function (fieldQ, _, __, ___) { + if (fieldQ.scale) { + var scale = fieldQ.scale; + // If fieldQ.type is an Wildcard and scale.type is undefined, it is equivalent + // to scale type is Wildcard. If scale type is an Wildcard, we do not yet know + // what the scale type is, and thus can ignore the constraint. + var sType = encoding_1.scaleType(fieldQ); + if (sType === undefined || sType === null) { + // If still ambiguous, doesn't check the constraint + return true; + } + for (var scaleProp in scale) { + if (scaleProp === 'type' || scaleProp === 'name' || scaleProp === 'enum') { + // ignore type and properties of wildcards + continue; + } + var sProp = scaleProp; + if (sType === 'point') { + // HACK: our current implementation of scaleType() can return point + // when the scaleType is a band since we didn't pass all parameter to Vega-Lite's scale type method. + if (!scale_1.scaleTypeSupportProperty('point', sProp) && !scale_1.scaleTypeSupportProperty('band', sProp)) { + return false; + } + } + else if (!scale_1.scaleTypeSupportProperty(sType, sProp)) { + return false; + } + } + } + return true; + } + }, { + name: 'scalePropertiesSupportedByChannel', + description: 'Not all scale properties are supported by all encoding channels', + properties: [].concat(property_1.SCALE_PROPS, [property_1.Property.SCALE, property_1.Property.CHANNEL]), + allowWildcardForProperties: true, + strict: true, + satisfy: function (fieldQ, _, __, ___) { + if (fieldQ) { + var channel = fieldQ.channel; + var scale = fieldQ.scale; + if (channel && !wildcard_1.isWildcard(channel) && scale) { + if (channel === 'row' || channel === 'column') { + // row / column do not have scale + return false; + } + for (var scaleProp in scale) { + if (!scale.hasOwnProperty(scaleProp)) + continue; + if (scaleProp === 'type' || scaleProp === 'name' || scaleProp === 'enum') { + // ignore type and properties of wildcards + continue; + } + var isSupported = scale_1.channelScalePropertyIncompatability(channel, scaleProp) === undefined; + if (!isSupported) { + return false; + } + } + } + } + return true; + } + }, { + name: 'typeMatchesPrimitiveType', + description: 'Data type should be supported by field\'s primitive type.', + properties: [property_1.Property.FIELD, property_1.Property.TYPE], + allowWildcardForProperties: false, + strict: true, + satisfy: function (fieldQ, schema, encWildcardIndex, opt) { + if (fieldQ.field === '*') { + return true; + } + var primitiveType = schema.primitiveType(fieldQ.field); + var type = fieldQ.type; + if (!encWildcardIndex.has('field') && !encWildcardIndex.has('type') && !opt.constraintManuallySpecifiedValue) { + // Do not have to check this as this is manually specified by users. + return true; + } + switch (primitiveType) { + case schema_1.PrimitiveType.BOOLEAN: + case schema_1.PrimitiveType.STRING: + return type !== type_1.Type.QUANTITATIVE && type !== type_1.Type.TEMPORAL; + case schema_1.PrimitiveType.NUMBER: + case schema_1.PrimitiveType.INTEGER: + return type !== type_1.Type.TEMPORAL; + case schema_1.PrimitiveType.DATETIME: + // TODO: add NOMINAL, ORDINAL support after we support this in Vega-Lite + return type === type_1.Type.TEMPORAL; + case null: + // field does not exist in the schema + return false; + } + throw new Error('Not implemented'); + } + }, + { + name: 'typeMatchesSchemaType', + description: 'Enumerated data type of a field should match the field\'s type in the schema.', + properties: [property_1.Property.FIELD, property_1.Property.TYPE], + allowWildcardForProperties: false, + strict: false, + satisfy: function (fieldQ, schema, encWildcardIndex, opt) { + if (!encWildcardIndex.has('field') && !encWildcardIndex.has('type') && !opt.constraintManuallySpecifiedValue) { + // Do not have to check this as this is manually specified by users. + return true; + } + if (fieldQ.field === '*') { + return fieldQ.type === type_1.Type.QUANTITATIVE; + } + return schema.vlType(fieldQ.field) === fieldQ.type; + } + }, { + name: 'maxCardinalityForCategoricalColor', + description: 'Categorical channel should not have too high cardinality', + properties: [property_1.Property.CHANNEL, property_1.Property.FIELD], + allowWildcardForProperties: false, + strict: false, + satisfy: function (fieldQ, schema, _, opt) { + // TODO: missing case where ordinal / temporal use categorical color + // (once we do so, need to add Property.BIN, Property.TIMEUNIT) + if (fieldQ.channel === channel_1.Channel.COLOR && (fieldQ.type === type_1.Type.NOMINAL || fieldQ.type === expandedtype_1.ExpandedType.KEY)) { + return schema.cardinality(fieldQ) <= opt.maxCardinalityForCategoricalColor; + } + return true; // other channel is irrelevant to this constraint + } + }, { + name: 'maxCardinalityForFacet', + description: 'Row/column channel should not have too high cardinality', + properties: [property_1.Property.CHANNEL, property_1.Property.FIELD, property_1.Property.BIN, property_1.Property.TIMEUNIT], + allowWildcardForProperties: false, + strict: false, + satisfy: function (fieldQ, schema, _, opt) { + if (fieldQ.channel === channel_1.Channel.ROW || fieldQ.channel === channel_1.Channel.COLUMN) { + return schema.cardinality(fieldQ) <= opt.maxCardinalityForFacet; + } + return true; // other channel is irrelevant to this constraint + } + }, { + name: 'maxCardinalityForShape', + description: 'Shape channel should not have too high cardinality', + properties: [property_1.Property.CHANNEL, property_1.Property.FIELD, property_1.Property.BIN, property_1.Property.TIMEUNIT], + allowWildcardForProperties: false, + strict: false, + satisfy: function (fieldQ, schema, _, opt) { + if (fieldQ.channel === channel_1.Channel.SHAPE) { + return schema.cardinality(fieldQ) <= opt.maxCardinalityForShape; + } + return true; // other channel is irrelevant to this constraint + } + }, + { + name: 'dataTypeAndFunctionMatchScaleType', + description: 'Scale type must match data type', + properties: [property_1.Property.TYPE, property_1.Property.SCALE, property_1.getEncodingNestedProp('scale', 'type'), property_1.Property.TIMEUNIT, property_1.Property.BIN], + allowWildcardForProperties: false, + strict: true, + satisfy: function (fieldQ, _, __, ___) { + if (fieldQ.scale) { + var type = fieldQ.type; + var sType = encoding_1.scaleType(fieldQ); + if (expandedtype_1.isDiscrete(type)) { + return sType === undefined || scale_1.hasDiscreteDomain(sType); + } + else if (type === type_1.Type.TEMPORAL) { + if (!fieldQ.timeUnit) { + return util_1.contains([scale_1.ScaleType.TIME, scale_1.ScaleType.UTC, undefined], sType); + } + else { + return util_1.contains([scale_1.ScaleType.TIME, scale_1.ScaleType.UTC, undefined], sType) || scale_1.hasDiscreteDomain(sType); + } + } + else if (type === type_1.Type.QUANTITATIVE) { + if (fieldQ.bin) { + return util_1.contains([scale_1.ScaleType.LINEAR, undefined], sType); + } + else { + return util_1.contains([scale_1.ScaleType.LOG, scale_1.ScaleType.POW, scale_1.ScaleType.SQRT, scale_1.ScaleType.QUANTILE, scale_1.ScaleType.QUANTIZE, scale_1.ScaleType.LINEAR, undefined], sType); + } + } + } + return true; + } + } +].map(function (ec) { return new base_1.EncodingConstraintModel(ec); }); +exports.FIELD_CONSTRAINT_INDEX = exports.FIELD_CONSTRAINTS.reduce(function (m, ec) { + m[ec.name()] = ec; + return m; +}, {}); +exports.FIELD_CONSTRAINTS_BY_PROPERTY = exports.FIELD_CONSTRAINTS.reduce(function (index, c) { + for (var _i = 0, _a = c.properties(); _i < _a.length; _i++) { + var prop = _a[_i]; + // Initialize array and use it + index.set(prop, index.get(prop) || []); + index.get(prop).push(c); + } + return index; +}, new propindex_1.PropIndex()); + +},{"../property":13,"../propindex":14,"../query/encoding":15,"../query/expandedtype":16,"../schema":36,"../util":38,"../wildcard":39,"./base":2,"vega-lite/build/src/channel":57,"vega-lite/build/src/fielddef":60,"vega-lite/build/src/scale":65,"vega-lite/build/src/type":67}],5:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var encoding = require("./encoding"); +exports.encoding = encoding; +var spec = require("./spec"); +exports.spec = spec; + +},{"./encoding":3,"./spec":6}],6:[function(require,module,exports){ +"use strict"; +var __extends = (this && this.__extends) || (function () { + var extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +Object.defineProperty(exports, "__esModule", { value: true }); +var aggregate_1 = require("vega-lite/build/src/aggregate"); +var channel_1 = require("vega-lite/build/src/channel"); +var mark_1 = require("vega-lite/build/src/mark"); +var scale_1 = require("vega-lite/build/src/scale"); +var type_1 = require("vega-lite/build/src/type"); +var expandedtype_1 = require("../query/expandedtype"); +var base_1 = require("./base"); +var wildcard_1 = require("../wildcard"); +var property_1 = require("../property"); +var propindex_1 = require("../propindex"); +var util_1 = require("../util"); +var encoding_1 = require("../query/encoding"); +var NONSPATIAL_CHANNELS_INDEX = channel_1.NONSPATIAL_CHANNELS.reduce(function (m, channel) { + m[channel] = true; + return m; +}, {}); +var SpecConstraintModel = (function (_super) { + __extends(SpecConstraintModel, _super); + function SpecConstraintModel(specConstraint) { + return _super.call(this, specConstraint) || this; + } + SpecConstraintModel.prototype.hasAllRequiredPropertiesSpecific = function (specM) { + return util_1.every(this.constraint.properties, function (prop) { + if (prop === property_1.Property.MARK) { + return !wildcard_1.isWildcard(specM.getMark()); + } + // TODO: transform + if (property_1.isEncodingNestedProp(prop)) { + var parent_1 = prop.parent; + var child_1 = prop.child; + return util_1.every(specM.getEncodings(), function (encQ) { + if (!encQ[parent_1]) { + return true; + } + return !wildcard_1.isWildcard(encQ[parent_1][child_1]); + }); + } + if (!property_1.isEncodingProperty(prop)) { + throw new Error('UNIMPLEMENTED'); + } + return util_1.every(specM.getEncodings(), function (encQ) { + if (!encQ[prop]) { + return true; + } + return !wildcard_1.isWildcard(encQ[prop]); + }); + }); + }; + SpecConstraintModel.prototype.satisfy = function (specM, schema, opt) { + // TODO: Re-order logic to optimize the "allowWildcardForProperties" check + if (!this.constraint.allowWildcardForProperties) { + if (!this.hasAllRequiredPropertiesSpecific(specM)) { + return true; + } + } + return this.constraint.satisfy(specM, schema, opt); + }; + return SpecConstraintModel; +}(base_1.AbstractConstraintModel)); +exports.SpecConstraintModel = SpecConstraintModel; +exports.SPEC_CONSTRAINTS = [ + { + name: 'noRepeatedChannel', + description: 'Each encoding channel should only be used once.', + properties: [property_1.Property.CHANNEL], + allowWildcardForProperties: true, + strict: true, + satisfy: function (specM, _, __) { + var usedChannel = {}; + // channel for all encodings should be valid + return util_1.every(specM.getEncodings(), function (encQ) { + if (!wildcard_1.isWildcard(encQ.channel)) { + // If channel is specified, it should no be used already + if (usedChannel[encQ.channel]) { + return false; + } + usedChannel[encQ.channel] = true; + return true; + } + return true; // unspecified channel is valid + }); + } + }, + { + name: 'alwaysIncludeZeroInScaleWithBarMark', + description: 'Do not recommend bar mark if scale does not start at zero', + properties: [property_1.Property.MARK, property_1.Property.SCALE, property_1.getEncodingNestedProp('scale', 'zero'), property_1.Property.CHANNEL, property_1.Property.TYPE], + allowWildcardForProperties: false, + strict: true, + satisfy: function (specM, _, __) { + var mark = specM.getMark(); + var encodings = specM.getEncodings(); + if (mark === mark_1.Mark.BAR) { + for (var _i = 0, encodings_1 = encodings; _i < encodings_1.length; _i++) { + var encQ = encodings_1[_i]; + if (encoding_1.isFieldQuery(encQ) && + (encQ.channel === channel_1.Channel.X || encQ.channel === channel_1.Channel.Y) && + (encQ.type === type_1.Type.QUANTITATIVE) && + (encQ.scale && encQ.scale.zero === false)) { + // TODO: zero shouldn't be manually specified + return false; + } + } + } + return true; + } + }, + { + name: 'autoAddCount', + description: 'Automatically adding count only for plots with only ordinal, binned quantitative, or temporal with timeunit fields.', + properties: [property_1.Property.BIN, property_1.Property.TIMEUNIT, property_1.Property.TYPE, property_1.Property.AUTOCOUNT], + allowWildcardForProperties: true, + strict: false, + satisfy: function (specM, _, __) { + var hasAutoCount = util_1.some(specM.getEncodings(), function (encQ) { return encoding_1.isEnabledAutoCountQuery(encQ); }); + if (hasAutoCount) { + // Auto count should only be applied if all fields are nominal, ordinal, temporal with timeUnit, binned quantitative, or autoCount + return util_1.every(specM.getEncodings(), function (encQ) { + if (encoding_1.isValueQuery(encQ)) { + return false; + } + if (encoding_1.isAutoCountQuery(encQ)) { + return true; + } + switch (encQ.type) { + case type_1.Type.QUANTITATIVE: + return !!encQ.bin; + case type_1.Type.TEMPORAL: + return !!encQ.timeUnit; + case type_1.Type.ORDINAL: + case expandedtype_1.ExpandedType.KEY: + case type_1.Type.NOMINAL: + return true; + } + /* istanbul ignore next */ + throw new Error('Unsupported Type'); + }); + } + else { + var autoCountEncIndex = specM.wildcardIndex.encodingIndicesByProperty.get('autoCount') || []; + var neverHaveAutoCount = util_1.every(autoCountEncIndex, function (index) { + var encQ = specM.getEncodingQueryByIndex(index); + return encoding_1.isAutoCountQuery(encQ) && !wildcard_1.isWildcard(encQ.autoCount); + }); + if (neverHaveAutoCount) { + // If the query surely does not have autoCount + // then one of the field should be + // (1) unbinned quantitative + // (2) temporal without time unit + // (3) nominal or ordinal field + // or at least have potential to be (still ambiguous). + return util_1.some(specM.getEncodings(), function (encQ) { + if ((encoding_1.isFieldQuery(encQ) || encoding_1.isAutoCountQuery(encQ)) && encQ.type === type_1.Type.QUANTITATIVE) { + if (encoding_1.isDisabledAutoCountQuery(encQ)) { + return false; + } + else { + return encoding_1.isFieldQuery(encQ) && (!encQ.bin || wildcard_1.isWildcard(encQ.bin)); + } + } + else if (encoding_1.isFieldQuery(encQ) && encQ.type === type_1.Type.TEMPORAL) { + return !encQ.timeUnit || wildcard_1.isWildcard(encQ.timeUnit); + } + return false; // nominal or ordinal + }); + } + } + return true; // no auto count, no constraint + } + }, + { + name: 'channelPermittedByMarkType', + description: 'Each encoding channel should be supported by the mark type', + properties: [property_1.Property.CHANNEL, property_1.Property.MARK], + allowWildcardForProperties: true, + strict: true, + satisfy: function (specM, _, __) { + var mark = specM.getMark(); + // if mark is unspecified, no need to check + if (wildcard_1.isWildcard(mark)) + return true; + // TODO: can optimize this to detect only what's the changed property if needed. + return util_1.every(specM.getEncodings(), function (encQ) { + // channel unspecified, no need to check + if (wildcard_1.isWildcard(encQ.channel)) + return true; + return channel_1.supportMark(encQ.channel, mark); + }); + } + }, + { + name: 'hasAllRequiredChannelsForMark', + description: 'All required channels for the specified mark should be specified', + properties: [property_1.Property.CHANNEL, property_1.Property.MARK], + allowWildcardForProperties: false, + strict: true, + satisfy: function (specM, _, __) { + var mark = specM.getMark(); + switch (mark) { + case mark_1.Mark.AREA: + case mark_1.Mark.LINE: + return specM.channelUsed(channel_1.Channel.X) && specM.channelUsed(channel_1.Channel.Y); + case mark_1.Mark.TEXT: + return specM.channelUsed(channel_1.Channel.TEXT); + case mark_1.Mark.BAR: + case mark_1.Mark.CIRCLE: + case mark_1.Mark.SQUARE: + case mark_1.Mark.TICK: + case mark_1.Mark.RULE: + return specM.channelUsed(channel_1.Channel.X) || specM.channelUsed(channel_1.Channel.Y); + case mark_1.Mark.POINT: + // This allows generating a point plot if channel was not a wildcard. + return !specM.wildcardIndex.hasProperty(property_1.Property.CHANNEL) || + specM.channelUsed(channel_1.Channel.X) || specM.channelUsed(channel_1.Channel.Y); + } + /* istanbul ignore next */ + throw new Error('hasAllRequiredChannelsForMark not implemented for mark' + JSON.stringify(mark)); + } + }, + { + name: 'omitAggregate', + description: 'Omit aggregate plots.', + properties: [property_1.Property.AGGREGATE, property_1.Property.AUTOCOUNT], + allowWildcardForProperties: true, + strict: false, + satisfy: function (specM, _, __) { + if (specM.isAggregate()) { + return false; + } + return true; + } + }, + { + name: 'omitAggregatePlotWithDimensionOnlyOnFacet', + description: 'Omit aggregate plots with dimensions only on facets as that leads to inefficient use of space.', + properties: [property_1.Property.CHANNEL, property_1.Property.AGGREGATE, property_1.Property.AUTOCOUNT], + allowWildcardForProperties: false, + strict: false, + satisfy: function (specM, _, opt) { + if (specM.isAggregate()) { + var hasNonFacetDim_1 = false, hasDim_1 = false, hasEnumeratedFacetDim_1 = false; + specM.specQuery.encodings.forEach(function (encQ, index) { + if (encoding_1.isValueQuery(encQ) || (encoding_1.isDisabledAutoCountQuery(encQ))) + return; // skip unused field + // FieldQuery & !encQ.aggregate + if (encoding_1.isFieldQuery(encQ) && !encQ.aggregate) { + hasDim_1 = true; + if (util_1.contains([channel_1.Channel.ROW, channel_1.Channel.COLUMN], encQ.channel)) { + if (specM.wildcardIndex.hasEncodingProperty(index, property_1.Property.CHANNEL)) { + hasEnumeratedFacetDim_1 = true; + } + } + else { + hasNonFacetDim_1 = true; + } + } + }); + if (hasDim_1 && !hasNonFacetDim_1) { + if (hasEnumeratedFacetDim_1 || opt.constraintManuallySpecifiedValue) { + return false; + } + } + } + return true; + } + }, + { + name: 'omitAggregatePlotWithoutDimension', + description: 'Aggregate plots without dimension should be omitted', + properties: [property_1.Property.AGGREGATE, property_1.Property.AUTOCOUNT, property_1.Property.BIN, property_1.Property.TIMEUNIT, property_1.Property.TYPE], + allowWildcardForProperties: false, + strict: false, + satisfy: function (specM, _, __) { + if (specM.isAggregate()) { + // TODO relax + return util_1.some(specM.getEncodings(), function (encQ) { + if (encoding_1.isDiscrete(encQ)) { + return true; + } + return false; + }); + } + return true; + } + }, + { + // TODO: we can be smarter and check if bar has occlusion based on profiling statistics + name: 'omitBarLineAreaWithOcclusion', + description: 'Don\'t use bar, line or area to visualize raw plot as they often lead to occlusion.', + properties: [property_1.Property.MARK, property_1.Property.AGGREGATE, property_1.Property.AUTOCOUNT], + allowWildcardForProperties: false, + strict: false, + satisfy: function (specM, _, __) { + if (util_1.contains([mark_1.Mark.BAR, mark_1.Mark.LINE, mark_1.Mark.AREA], specM.getMark())) { + return specM.isAggregate(); + } + return true; + } + }, + { + name: 'omitBarTickWithSize', + description: 'Do not map field to size channel with bar and tick mark', + properties: [property_1.Property.CHANNEL, property_1.Property.MARK], + allowWildcardForProperties: true, + strict: false, + satisfy: function (specM, _, opt) { + var mark = specM.getMark(); + if (util_1.contains([mark_1.Mark.TICK, mark_1.Mark.BAR], mark)) { + if (specM.channelUsed(channel_1.Channel.SIZE)) { + if (opt.constraintManuallySpecifiedValue) { + // If size is used and we constraintManuallySpecifiedValue, + // then the spec violates this constraint. + return false; + } + else { + // Otherwise have to search for the size channel and check if it is enumerated + var encodings = specM.specQuery.encodings; + for (var i = 0; i < encodings.length; i++) { + var encQ = encodings[i]; + if (encQ.channel === channel_1.Channel.SIZE) { + if (specM.wildcardIndex.hasEncodingProperty(i, property_1.Property.CHANNEL)) { + // If enumerated, then this is bad + return false; + } + else { + // If it's manually specified, no need to continue searching, just return. + return true; + } + } + } + } + } + } + return true; // skip + } + }, + { + name: 'omitBarAreaForLogScale', + description: 'Do not use bar and area mark for x and y\'s log scale', + properties: [property_1.Property.MARK, property_1.Property.CHANNEL, property_1.Property.SCALE, property_1.getEncodingNestedProp('scale', 'type'), property_1.Property.TYPE], + allowWildcardForProperties: false, + strict: true, + satisfy: function (specM, _, __) { + var mark = specM.getMark(); + var encodings = specM.getEncodings(); + // TODO: mark or scale type should be enumerated + if (mark === mark_1.Mark.AREA || mark === mark_1.Mark.BAR) { + for (var _i = 0, encodings_2 = encodings; _i < encodings_2.length; _i++) { + var encQ = encodings_2[_i]; + if (encoding_1.isFieldQuery(encQ) && ((encQ.channel === channel_1.Channel.X || encQ.channel === channel_1.Channel.Y) && encQ.scale)) { + var sType = encoding_1.scaleType(encQ); + if (sType === scale_1.ScaleType.LOG) { + return false; + } + } + } + } + return true; + } + }, + { + name: 'omitMultipleNonPositionalChannels', + description: 'Unless manually specified, do not use multiple non-positional encoding channel to avoid over-encoding.', + properties: [property_1.Property.CHANNEL], + allowWildcardForProperties: true, + strict: false, + satisfy: function (specM, _, opt) { + // have to use specM.specQuery.encodings insetad of specM.getEncodings() + // since specM.getEncodings() remove encQ with autoCount===false from the array + // and thus might shift the index + var encodings = specM.specQuery.encodings; + var nonPositionChannelCount = 0; + var hasEnumeratedNonPositionChannel = false; + for (var i = 0; i < encodings.length; i++) { + var encQ = encodings[i]; + if (encoding_1.isValueQuery(encQ) || (encoding_1.isDisabledAutoCountQuery(encQ))) { + continue; // ignore skipped encoding + } + var channel = encQ.channel; + if (!wildcard_1.isWildcard(channel)) { + if (NONSPATIAL_CHANNELS_INDEX[channel + '']) { + nonPositionChannelCount += 1; + if (specM.wildcardIndex.hasEncodingProperty(i, property_1.Property.CHANNEL)) { + hasEnumeratedNonPositionChannel = true; + } + if (nonPositionChannelCount > 1 && + (hasEnumeratedNonPositionChannel || opt.constraintManuallySpecifiedValue)) { + return false; + } + } + } + } + return true; + } + }, + { + name: 'omitNonPositionalOrFacetOverPositionalChannels', + description: 'Do not use non-positional channels unless all positional channels are used', + properties: [property_1.Property.CHANNEL], + allowWildcardForProperties: false, + strict: false, + satisfy: function (specM, _, opt) { + var encodings = specM.specQuery.encodings; + var hasNonPositionalChannelOrFacet = false; + var hasEnumeratedNonPositionOrFacetChannel = false; + var hasX = false, hasY = false; + for (var i = 0; i < encodings.length; i++) { + var encQ = encodings[i]; + if (encoding_1.isValueQuery(encQ) || (encoding_1.isDisabledAutoCountQuery(encQ))) { + continue; // ignore skipped encoding + } + var channel = encQ.channel; + if (channel === channel_1.Channel.X) { + hasX = true; + } + else if (channel === channel_1.Channel.Y) { + hasY = true; + } + else if (!wildcard_1.isWildcard(channel)) { + // All non positional channel / Facet + hasNonPositionalChannelOrFacet = true; + if (specM.wildcardIndex.hasEncodingProperty(i, property_1.Property.CHANNEL)) { + hasEnumeratedNonPositionOrFacetChannel = true; + } + } + } + if (hasEnumeratedNonPositionOrFacetChannel || + (opt.constraintManuallySpecifiedValue && hasNonPositionalChannelOrFacet)) { + return hasX && hasY; + } + return true; + } + }, + { + name: 'omitRaw', + description: 'Omit raw plots.', + properties: [property_1.Property.AGGREGATE, property_1.Property.AUTOCOUNT], + allowWildcardForProperties: false, + strict: false, + satisfy: function (specM, _, __) { + if (!specM.isAggregate()) { + return false; + } + return true; + } + }, + { + name: 'omitRawContinuousFieldForAggregatePlot', + description: 'Aggregate plot should not use raw continuous field as group by values. ' + + '(Quantitative should be binned. Temporal should have time unit.)', + properties: [property_1.Property.AGGREGATE, property_1.Property.AUTOCOUNT, property_1.Property.TIMEUNIT, property_1.Property.BIN, property_1.Property.TYPE], + allowWildcardForProperties: true, + strict: false, + satisfy: function (specM, _, opt) { + if (specM.isAggregate()) { + var encodings = specM.specQuery.encodings; + for (var i = 0; i < encodings.length; i++) { + var encQ = encodings[i]; + if (encoding_1.isValueQuery(encQ) || (encoding_1.isDisabledAutoCountQuery(encQ))) + continue; // skip unused encoding + // TODO: aggregate for ordinal and temporal + if (encoding_1.isFieldQuery(encQ) && encQ.type === type_1.Type.TEMPORAL) { + // Temporal fields should have timeUnit or is still a wildcard + if (!encQ.timeUnit && (specM.wildcardIndex.hasEncodingProperty(i, property_1.Property.TIMEUNIT) || + opt.constraintManuallySpecifiedValue)) { + return false; + } + } + if (encQ.type === type_1.Type.QUANTITATIVE) { + if (encoding_1.isFieldQuery(encQ) && !encQ.bin && !encQ.aggregate) { + // If Raw Q + if (specM.wildcardIndex.hasEncodingProperty(i, property_1.Property.BIN) || + specM.wildcardIndex.hasEncodingProperty(i, property_1.Property.AGGREGATE) || + specM.wildcardIndex.hasEncodingProperty(i, property_1.Property.AUTOCOUNT)) { + // and it's raw from enumeration + return false; + } + if (opt.constraintManuallySpecifiedValue) { + // or if we constraintManuallySpecifiedValue + return false; + } + } + } + } + } + return true; + } + }, + { + name: 'omitRawDetail', + description: 'Do not use detail channel with raw plot.', + properties: [property_1.Property.CHANNEL, property_1.Property.AGGREGATE, property_1.Property.AUTOCOUNT], + allowWildcardForProperties: false, + strict: true, + satisfy: function (specM, _, opt) { + if (specM.isAggregate()) { + return true; + } + return util_1.every(specM.specQuery.encodings, function (encQ, index) { + if (encoding_1.isValueQuery(encQ) || (encoding_1.isDisabledAutoCountQuery(encQ))) + return true; // ignore autoCount field + if (encQ.channel === channel_1.Channel.DETAIL) { + // Detail channel for raw plot is not good, except when its enumerated + // or when it's manually specified but we constraintManuallySpecifiedValue. + if (specM.wildcardIndex.hasEncodingProperty(index, property_1.Property.CHANNEL) || + opt.constraintManuallySpecifiedValue) { + return false; + } + } + return true; + }); + } + }, + { + name: 'omitRepeatedField', + description: 'Each field should be mapped to only one channel', + properties: [property_1.Property.FIELD], + allowWildcardForProperties: true, + strict: false, + satisfy: function (specM, _, opt) { + var fieldUsed = {}; + var fieldEnumerated = {}; + var encodings = specM.specQuery.encodings; + for (var i = 0; i < encodings.length; i++) { + var encQ = encodings[i]; + if (encoding_1.isValueQuery(encQ) || encoding_1.isAutoCountQuery(encQ)) + continue; + var field = void 0; + if (encQ.field && !wildcard_1.isWildcard(encQ.field)) { + field = encQ.field; + } + if (encoding_1.isAutoCountQuery(encQ) && !wildcard_1.isWildcard(encQ.autoCount)) { + field = 'count_*'; + } + if (field) { + if (specM.wildcardIndex.hasEncodingProperty(i, property_1.Property.FIELD)) { + fieldEnumerated[field] = true; + } + // When the field is specified previously, + // if it is enumerated (either previously or in this encQ) + // or if the opt.constraintManuallySpecifiedValue is true, + // then it violates the constraint. + if (fieldUsed[field]) { + if (fieldEnumerated[field] || opt.constraintManuallySpecifiedValue) { + return false; + } + } + fieldUsed[field] = true; + } + } + return true; + } + }, + // TODO: omitShapeWithBin + { + name: 'omitVerticalDotPlot', + description: 'Do not output vertical dot plot.', + properties: [property_1.Property.CHANNEL], + allowWildcardForProperties: true, + strict: false, + satisfy: function (specM, _, __) { + var encodings = specM.getEncodings(); + if (encodings.length === 1 && encodings[0].channel === channel_1.Channel.Y) { + return false; + } + return true; + } + }, + // EXPENSIVE CONSTRAINTS -- check them later! + { + name: 'hasAppropriateGraphicTypeForMark', + description: 'Has appropriate graphic type for mark', + properties: [property_1.Property.CHANNEL, property_1.Property.MARK, property_1.Property.TYPE, property_1.Property.TIMEUNIT, property_1.Property.BIN, property_1.Property.AGGREGATE, property_1.Property.AUTOCOUNT], + allowWildcardForProperties: false, + strict: false, + satisfy: function (specM, _, __) { + var mark = specM.getMark(); + switch (mark) { + case mark_1.Mark.AREA: + case mark_1.Mark.LINE: + if (specM.isAggregate()) { + var xEncQ = specM.getEncodingQueryByChannel(channel_1.Channel.X); + var yEncQ = specM.getEncodingQueryByChannel(channel_1.Channel.Y); + var xIsMeasure = encoding_1.isContinuous(xEncQ); + var yIsMeasure = encoding_1.isContinuous(yEncQ); + // for aggregate line / area, we need at least one group-by axis and one measure axis. + return xEncQ && yEncQ && (xIsMeasure !== yIsMeasure) && + // and the dimension axis should not be nominal + // TODO: make this clause optional + !(encoding_1.isFieldQuery(xEncQ) && !xIsMeasure && util_1.contains(['nominal', 'key'], xEncQ.type)) && + !(encoding_1.isFieldQuery(yEncQ) && !yIsMeasure && util_1.contains(['nominal', 'key'], yEncQ.type)); + // TODO: allow connected scatterplot + } + return true; + case mark_1.Mark.TEXT: + // FIXME correctly when we add text + return true; + case mark_1.Mark.BAR: + case mark_1.Mark.TICK: + // Bar and tick should not use size. + if (specM.channelUsed(channel_1.Channel.SIZE)) { + return false; + } + else { + // Tick and Bar should have one and only one continuous axis + var xEncQ = specM.getEncodingQueryByChannel(channel_1.Channel.X); + var yEncQ = specM.getEncodingQueryByChannel(channel_1.Channel.Y); + var xIsContinuous = encoding_1.isContinuous(xEncQ); + var yIsContinuous = encoding_1.isContinuous(yEncQ); + if (xIsContinuous !== yIsContinuous) { + // TODO: Bar and tick's dimension should not be continuous (quant/time) scale + return true; + } + return false; + } + case mark_1.Mark.CIRCLE: + case mark_1.Mark.POINT: + case mark_1.Mark.SQUARE: + case mark_1.Mark.RULE: + return true; + } + /* istanbul ignore next */ + throw new Error('hasAllRequiredChannelsForMark not implemented for mark' + mark); + } + }, + { + name: 'omitNonLinearScaleTypeWithStack', + description: 'Stacked plot should only use linear scale', + properties: [property_1.Property.CHANNEL, property_1.Property.MARK, property_1.Property.AGGREGATE, property_1.Property.AUTOCOUNT, property_1.Property.SCALE, property_1.getEncodingNestedProp('scale', 'type'), property_1.Property.TYPE], + // TODO: Property.STACK + allowWildcardForProperties: false, + strict: true, + satisfy: function (specM, _, __) { + var stack = specM.stack(); + if (stack) { + for (var _i = 0, _a = specM.getEncodings(); _i < _a.length; _i++) { + var encQ = _a[_i]; + if (encoding_1.isValueQuery(encQ)) + continue; + if (((encoding_1.isFieldQuery(encQ) && !!encQ.aggregate) || encoding_1.isEnabledAutoCountQuery(encQ)) && + encQ.type === type_1.Type.QUANTITATIVE && + util_1.contains([channel_1.Channel.X, channel_1.Channel.Y], encQ.channel)) { + if (encoding_1.scaleType(encQ) !== scale_1.ScaleType.LINEAR) { + return false; + } + } + } + } + return true; + } + }, + { + name: 'omitNonSumStack', + description: 'Stacked plot should use summative aggregation such as sum, count, or distinct', + properties: [property_1.Property.CHANNEL, property_1.Property.MARK, property_1.Property.AGGREGATE, property_1.Property.AUTOCOUNT], + allowWildcardForProperties: false, + strict: false, + satisfy: function (specM, _, __) { + var stack = specM.stack(); + if (stack) { + var measureEncQ = specM.getEncodingQueryByChannel(stack.fieldChannel); + return (encoding_1.isFieldQuery(measureEncQ) && util_1.contains(aggregate_1.SUM_OPS, measureEncQ.aggregate)) || (encoding_1.isAutoCountQuery(measureEncQ) && !!measureEncQ.autoCount); + } + return true; + } + }, + { + name: 'omitTableWithOcclusionIfAutoAddCount', + description: 'Plots without aggregation or autocount where x and y are both discrete should be omitted if autoAddCount is enabled as they often lead to occlusion', + properties: [property_1.Property.CHANNEL, property_1.Property.TYPE, property_1.Property.TIMEUNIT, property_1.Property.BIN, property_1.Property.AGGREGATE, property_1.Property.AUTOCOUNT], + allowWildcardForProperties: false, + strict: false, + satisfy: function (specM, _, opt) { + if (opt.autoAddCount) { + var xEncQ = specM.getEncodingQueryByChannel('x'); + var yEncQ = specM.getEncodingQueryByChannel('y'); + if ((!encoding_1.isFieldQuery(xEncQ) || encoding_1.isDiscrete(xEncQ)) && + (!encoding_1.isFieldQuery(yEncQ) || encoding_1.isDiscrete(yEncQ))) { + if (!specM.isAggregate()) { + return false; + } + else { + return util_1.every(specM.getEncodings(), function (encQ) { + var channel = encQ.channel; + if (channel !== channel_1.Channel.X && channel !== channel_1.Channel.Y && + channel !== channel_1.Channel.ROW && channel !== channel_1.Channel.COLUMN) { + // Non-position fields should not be unaggreated fields + if (encoding_1.isFieldQuery(encQ) && !encQ.aggregate) { + return false; + } + } + return true; + }); + } + } + } + return true; + } + } +].map(function (sc) { return new SpecConstraintModel(sc); }); +// For testing +exports.SPEC_CONSTRAINT_INDEX = exports.SPEC_CONSTRAINTS.reduce(function (m, c) { + m[c.name()] = c; + return m; +}, {}); +var SPEC_CONSTRAINTS_BY_PROPERTY = exports.SPEC_CONSTRAINTS.reduce(function (index, c) { + for (var _i = 0, _a = c.properties(); _i < _a.length; _i++) { + var prop = _a[_i]; + // Initialize array and use it + index.set(prop, index.get(prop) || []); + index.get(prop).push(c); + } + return index; +}, new propindex_1.PropIndex()); +/** + * Check all encoding constraints for a particular property and index tuple + */ +function checkSpec(prop, wildcard, specM, schema, opt) { + // Check encoding constraint + var specConstraints = SPEC_CONSTRAINTS_BY_PROPERTY.get(prop) || []; + for (var _i = 0, specConstraints_1 = specConstraints; _i < specConstraints_1.length; _i++) { + var c = specConstraints_1[_i]; + // Check if the constraint is enabled + if (c.strict() || !!opt[c.name()]) { + // For strict constraint, or enabled non-strict, check the constraints + var satisfy = c.satisfy(specM, schema, opt); + if (!satisfy) { + var violatedConstraint = '(spec) ' + c.name(); + /* istanbul ignore if */ + if (opt.verbose) { + console.log(violatedConstraint + ' failed with ' + specM.toShorthand() + ' for ' + wildcard.name); + } + return violatedConstraint; + } + } + } + return null; +} +exports.checkSpec = checkSpec; + +},{"../property":13,"../propindex":14,"../query/encoding":15,"../query/expandedtype":16,"../util":38,"../wildcard":39,"./base":2,"vega-lite/build/src/aggregate":54,"vega-lite/build/src/channel":57,"vega-lite/build/src/mark":64,"vega-lite/build/src/scale":65,"vega-lite/build/src/type":67}],7:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var property_1 = require("../property"); +var propindex_1 = require("../propindex"); +var util_1 = require("../util"); +var base_1 = require("./base"); +exports.VALUE_CONSTRAINTS = [ + { + name: 'doesNotSupportConstantValue', + description: 'row, column, x, y, and detail should not work with constant values.', + properties: [property_1.Property.TYPE, property_1.Property.AGGREGATE], + allowWildcardForProperties: false, + strict: true, + satisfy: function (valueQ, _, __, ___) { + return !(util_1.contains(['row', 'column', 'x', 'y', 'detail'], valueQ.channel)); + } + } +].map(function (ec) { return new base_1.EncodingConstraintModel(ec); }); +exports.VALUE_CONSTRAINT_INDEX = exports.VALUE_CONSTRAINTS.reduce(function (m, ec) { + m[ec.name()] = ec; + return m; +}, {}); +exports.VALUE_CONSTRAINTS_BY_PROPERTY = exports.VALUE_CONSTRAINTS.reduce(function (index, c) { + for (var _i = 0, _a = c.properties(); _i < _a.length; _i++) { + var prop = _a[_i]; + index.set(prop, index.get(prop) || []); + index.get(prop).push(c); + } + return index; +}, new propindex_1.PropIndex()); + +},{"../property":13,"../propindex":14,"../util":38,"./base":2}],8:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.version = '0.19.1'; +exports.config = require("./config"); +exports.constraint = require("./constraint"); +exports.enumerate = require("./enumerator"); +exports.wildcard = require("./wildcard"); +var generate_1 = require("./generate"); +exports.generate = generate_1.generate; +exports.model = require("./model"); +exports.nest = require("./nest"); +exports.property = require("./property"); +exports.query = require("./query"); +exports.ranking = require("./ranking/ranking"); +var recommend_1 = require("./recommend"); +exports.recommend = recommend_1.recommend; +exports.schema = require("./schema"); +exports.util = require("./util"); + +},{"./config":1,"./constraint":5,"./enumerator":9,"./generate":10,"./model":11,"./nest":12,"./property":13,"./query":18,"./ranking/ranking":34,"./recommend":35,"./schema":36,"./util":38,"./wildcard":39}],9:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var encoding_1 = require("./constraint/encoding"); +var spec_1 = require("./constraint/spec"); +var property_1 = require("./property"); +var propindex_1 = require("./propindex"); +var encoding_2 = require("./query/encoding"); +var ENUMERATOR_INDEX = new propindex_1.PropIndex(); +function getEnumerator(prop) { + return ENUMERATOR_INDEX.get(prop); +} +exports.getEnumerator = getEnumerator; +ENUMERATOR_INDEX.set('mark', function (wildcardIndex, schema, opt) { + return function (answerSet, specM) { + var markWildcard = specM.getMark(); + // enumerate the value + markWildcard.enum.forEach(function (mark) { + specM.setMark(mark); + // Check spec constraint + var violatedSpecConstraint = spec_1.checkSpec('mark', wildcardIndex.mark, specM, schema, opt); + if (!violatedSpecConstraint) { + // emit + answerSet.push(specM.duplicate()); + } + }); + // Reset to avoid side effect + specM.resetMark(); + return answerSet; + }; +}); +property_1.ENCODING_TOPLEVEL_PROPS.forEach(function (prop) { + ENUMERATOR_INDEX.set(prop, EncodingPropertyGeneratorFactory(prop)); +}); +property_1.ENCODING_NESTED_PROPS.forEach(function (nestedProp) { + ENUMERATOR_INDEX.set(nestedProp, EncodingPropertyGeneratorFactory(nestedProp)); +}); +/** + * @param prop property type. + * @return an answer set reducer factory for the given prop. + */ +function EncodingPropertyGeneratorFactory(prop) { + /** + * @return as reducer that takes a specQueryModel as input and output an answer set array. + */ + return function (wildcardIndex, schema, opt) { + return function (answerSet, specM) { + // index of encoding mappings that require enumeration + var indices = wildcardIndex.encodingIndicesByProperty.get(prop); + function enumerate(jobIndex) { + if (jobIndex === indices.length) { + // emit and terminate + answerSet.push(specM.duplicate()); + return; + } + var index = indices[jobIndex]; + var wildcard = wildcardIndex.encodings[index].get(prop); + var encQ = specM.getEncodingQueryByIndex(index); + var propWildcard = specM.getEncodingProperty(index, prop); + if (encoding_2.isValueQuery(encQ) || ( + // TODO: encQ.exclude + // If this encoding query is an excluded autoCount, there is no point enumerating other properties + // for this encoding query because they will be excluded anyway. + // Thus, we can just move on to the next encoding to enumerate. + (encoding_2.isDisabledAutoCountQuery(encQ)) || + // nested encoding property might have its parent set to false + // therefore, we no longer have to enumerate them + !propWildcard)) { + enumerate(jobIndex + 1); + } + else { + wildcard.enum.forEach(function (propVal) { + if (propVal === null) { + // our duplicate() method use JSON.stringify, parse and thus can accidentally + // convert undefined in an array into null + propVal = undefined; + } + specM.setEncodingProperty(index, prop, propVal, wildcard); + // Check encoding constraint + var violatedEncodingConstraint = encoding_1.checkEncoding(prop, wildcard, index, specM, schema, opt); + if (violatedEncodingConstraint) { + return; // do not keep searching + } + // Check spec constraint + var violatedSpecConstraint = spec_1.checkSpec(prop, wildcard, specM, schema, opt); + if (violatedSpecConstraint) { + return; // do not keep searching + } + // If qualify all of the constraints, keep enumerating + enumerate(jobIndex + 1); + }); + // Reset to avoid side effect + specM.resetEncodingProperty(index, prop, wildcard); + } + } + // start enumerating from 0 + enumerate(0); + return answerSet; + }; + }; +} +exports.EncodingPropertyGeneratorFactory = EncodingPropertyGeneratorFactory; + +},{"./constraint/encoding":3,"./constraint/spec":6,"./property":13,"./propindex":14,"./query/encoding":15}],10:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var config_1 = require("./config"); +var enumerator_1 = require("./enumerator"); +var model_1 = require("./model"); +var property_1 = require("./property"); +var stylize_1 = require("./stylize"); +function generate(specQ, schema, opt) { + if (opt === void 0) { opt = config_1.DEFAULT_QUERY_CONFIG; } + // 1. Build a SpecQueryModel, which also contains wildcardIndex + var specM = model_1.SpecQueryModel.build(specQ, schema, opt); + var wildcardIndex = specM.wildcardIndex; + // 2. Enumerate each of the properties based on propPrecedence. + var answerSet = [specM]; // Initialize Answer Set with only the input spec query. + opt.propertyPrecedence.forEach(function (propKey) { + var prop = property_1.fromKey(propKey); + // If the original specQuery contains wildcard for this prop + if (wildcardIndex.hasProperty(prop)) { + // update answerset + var enumerator = enumerator_1.getEnumerator(prop); + var reducer = enumerator(wildcardIndex, schema, opt); + answerSet = answerSet.reduce(reducer, []); + } + }); + if (opt.stylize) { + if ((opt.nominalColorScaleForHighCardinality !== null) || + (opt.smallRangeStepForHighCardinalityOrFacet !== null) || + (opt.xAxisOnTopForHighYCardinalityWithoutColumn !== null)) { + return stylize_1.stylize(answerSet, schema, opt); + } + } + return answerSet; +} +exports.generate = generate; + +},{"./config":1,"./enumerator":9,"./model":11,"./property":13,"./stylize":37}],11:[function(require,module,exports){ +"use strict"; +var __assign = (this && this.__assign) || Object.assign || function(t) { + for (var s, i = 1, n = arguments.length; i < n; i++) { + s = arguments[i]; + for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) + t[p] = s[p]; + } + return t; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +var type_1 = require("vega-lite/build/src/type"); +var property_1 = require("./property"); +var wildcard_1 = require("./wildcard"); +var wildcardindex_1 = require("./wildcardindex"); +var spec_1 = require("./query/spec"); +var encoding_1 = require("./query/encoding"); +var groupby_1 = require("./query/groupby"); +var shorthand_1 = require("./query/shorthand"); +var util_1 = require("./util"); +/** + * Internal class for specQuery that provides helper for the enumeration process. + */ +var SpecQueryModel = (function () { + function SpecQueryModel(spec, wildcardIndex, schema, opt, wildcardAssignment) { + this._rankingScore = {}; + this._spec = spec; + this._channelFieldCount = spec.encodings.reduce(function (m, encQ) { + if (!wildcard_1.isWildcard(encQ.channel) && (!encoding_1.isAutoCountQuery(encQ) || encQ.autoCount !== false)) { + m[encQ.channel + ''] = 1; + } + return m; + }, {}); + this._wildcardIndex = wildcardIndex; + this._assignedWildcardIndex = wildcardAssignment; + this._opt = opt; + this._schema = schema; + } + /** + * Build an WildcardIndex by detecting enumeration specifiers + * in the input specQuery and replace short wildcards with + * full ones that includes both names and enumValues. + * + * @return a SpecQueryModel that wraps the specQuery and the WildcardIndex. + */ + SpecQueryModel.build = function (specQ, schema, opt) { + var wildcardIndex = new wildcardindex_1.WildcardIndex(); + // mark + if (wildcard_1.isWildcard(specQ.mark)) { + var name_1 = wildcard_1.getDefaultName(property_1.Property.MARK); + specQ.mark = wildcard_1.initWildcard(specQ.mark, name_1, opt.enum.mark); + wildcardIndex.setMark(specQ.mark); + } + // TODO: transform + // encodings + specQ.encodings.forEach(function (encQ, index) { + if (encoding_1.isAutoCountQuery(encQ)) { + // This is only for testing purpose + console.warn('A field with autoCount should not be included as autoCount meant to be an internal object.'); + encQ.type = type_1.Type.QUANTITATIVE; // autoCount is always quantitative + } + if (encoding_1.isFieldQuery(encQ) && encQ.type === undefined) { + // type is optional -- we automatically augment wildcard if not specified + encQ.type = wildcard_1.SHORT_WILDCARD; + } + // For each property of the encodingQuery, enumerate + property_1.ENCODING_TOPLEVEL_PROPS.forEach(function (prop) { + if (wildcard_1.isWildcard(encQ[prop])) { + // Assign default wildcard name and enum values. + var defaultWildcardName = wildcard_1.getDefaultName(prop) + index; + var defaultEnumValues = wildcard_1.getDefaultEnumValues(prop, schema, opt); + var wildcard = encQ[prop] = wildcard_1.initWildcard(encQ[prop], defaultWildcardName, defaultEnumValues); + // Add index of the encoding mapping to the property's wildcard index. + wildcardIndex.setEncodingProperty(index, prop, wildcard); + } + }); + // For each nested property of the encoding query (e.g., encQ.bin.maxbins) + property_1.ENCODING_NESTED_PROPS.forEach(function (prop) { + var propObj = encQ[prop.parent]; // the property object e.g., encQ.bin + if (propObj) { + var child = prop.child; + if (wildcard_1.isWildcard(propObj[child])) { + // Assign default wildcard name and enum values. + var defaultWildcardName = wildcard_1.getDefaultName(prop) + index; + var defaultEnumValues = wildcard_1.getDefaultEnumValues(prop, schema, opt); + var wildcard = propObj[child] = wildcard_1.initWildcard(propObj[child], defaultWildcardName, defaultEnumValues); + // Add index of the encoding mapping to the property's wildcard index. + wildcardIndex.setEncodingProperty(index, prop, wildcard); + } + } + }); + }); + // AUTO COUNT + // Add Auto Count Field + if (opt.autoAddCount) { + var countEncQ = { + channel: { + name: wildcard_1.getDefaultName(property_1.Property.CHANNEL) + specQ.encodings.length, + enum: wildcard_1.getDefaultEnumValues(property_1.Property.CHANNEL, schema, opt) + }, + autoCount: { + name: wildcard_1.getDefaultName(property_1.Property.AUTOCOUNT) + specQ.encodings.length, + enum: [false, true] + }, + type: type_1.Type.QUANTITATIVE + }; + specQ.encodings.push(countEncQ); + var index = specQ.encodings.length - 1; + // Add index of the encoding mapping to the property's wildcard index. + wildcardIndex.setEncodingProperty(index, property_1.Property.CHANNEL, countEncQ.channel); + wildcardIndex.setEncodingProperty(index, property_1.Property.AUTOCOUNT, countEncQ.autoCount); + } + return new SpecQueryModel(specQ, wildcardIndex, schema, opt, {}); + }; + Object.defineProperty(SpecQueryModel.prototype, "wildcardIndex", { + get: function () { + return this._wildcardIndex; + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(SpecQueryModel.prototype, "schema", { + get: function () { + return this._schema; + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(SpecQueryModel.prototype, "specQuery", { + get: function () { + return this._spec; + }, + enumerable: true, + configurable: true + }); + SpecQueryModel.prototype.duplicate = function () { + return new SpecQueryModel(util_1.duplicate(this._spec), this._wildcardIndex, this._schema, this._opt, util_1.duplicate(this._assignedWildcardIndex)); + }; + SpecQueryModel.prototype.setMark = function (mark) { + var name = this._spec.mark.name; + this._assignedWildcardIndex[name] = this._spec.mark = mark; + }; + SpecQueryModel.prototype.resetMark = function () { + var wildcard = this._spec.mark = this._wildcardIndex.mark; + delete this._assignedWildcardIndex[wildcard.name]; + }; + SpecQueryModel.prototype.getMark = function () { + return this._spec.mark; + }; + SpecQueryModel.prototype.getEncodingProperty = function (index, prop) { + var encQ = this._spec.encodings[index]; + if (property_1.isEncodingNestedProp(prop)) { + return encQ[prop.parent][prop.child]; + } + return encQ[prop]; // encoding property (non-nested) + }; + SpecQueryModel.prototype.setEncodingProperty = function (index, prop, value, wildcard) { + var encQ = this._spec.encodings[index]; + if (prop === property_1.Property.CHANNEL && encQ.channel && !wildcard_1.isWildcard(encQ.channel)) { + // If there is an old channel + this._channelFieldCount[encQ.channel]--; + } + if (property_1.isEncodingNestedProp(prop)) { + encQ[prop.parent][prop.child] = value; + } + else if (property_1.hasNestedProperty(prop) && value === true) { + encQ[prop] = util_1.extend({}, encQ[prop], // copy all existing properties + { enum: undefined, name: undefined } // except name and values to it no longer an wildcard + ); + } + else { + encQ[prop] = value; + } + this._assignedWildcardIndex[wildcard.name] = value; + if (prop === property_1.Property.CHANNEL) { + // If there is a new channel, make sure it exists and add it to the count. + this._channelFieldCount[value] = (this._channelFieldCount[value] || 0) + 1; + } + }; + SpecQueryModel.prototype.resetEncodingProperty = function (index, prop, wildcard) { + var encQ = this._spec.encodings[index]; + if (prop === property_1.Property.CHANNEL) { + this._channelFieldCount[encQ.channel]--; + } + // reset it to wildcard + if (property_1.isEncodingNestedProp(prop)) { + encQ[prop.parent][prop.child] = wildcard; + } + else { + encQ[prop] = wildcard; + } + // add remove value that is reset from the assignment map + delete this._assignedWildcardIndex[wildcard.name]; + }; + SpecQueryModel.prototype.channelUsed = function (channel) { + // do not include encoding that has autoCount = false because it is not a part of the output spec. + return this._channelFieldCount[channel] > 0; + }; + SpecQueryModel.prototype.stack = function () { + return spec_1.stack(this._spec); + }; + SpecQueryModel.prototype.getEncodings = function () { + // do not include encoding that has autoCount = false because it is not a part of the output spec. + return this._spec.encodings.filter(function (encQ) { return !encoding_1.isDisabledAutoCountQuery(encQ); }); + }; + SpecQueryModel.prototype.getEncodingQueryByChannel = function (channel) { + for (var _i = 0, _a = this._spec.encodings; _i < _a.length; _i++) { + var specEncoding = _a[_i]; + if (specEncoding.channel === channel) { + return specEncoding; + } + } + return undefined; + }; + SpecQueryModel.prototype.getEncodingQueryByIndex = function (i) { + return this._spec.encodings[i]; + }; + SpecQueryModel.prototype.isAggregate = function () { + return spec_1.isAggregate(this._spec); + }; + SpecQueryModel.prototype.toShorthand = function (groupBy) { + if (groupBy) { + var parsedGroupBy = groupby_1.parseGroupBy(groupBy); + return shorthand_1.spec(this._spec, parsedGroupBy.include, parsedGroupBy.replacer); + } + return shorthand_1.spec(this._spec); + }; + SpecQueryModel.prototype._encoding = function () { + var encoding = {}; + for (var _i = 0, _a = this._spec.encodings; _i < _a.length; _i++) { + var encQ = _a[_i]; + // Need to cast here so we can assign properties later + var fieldDef = {}; + // For count field that is automatically added, convert to correct vega-lite fieldDef + if (encoding_1.isEnabledAutoCountQuery(encQ)) { + fieldDef = { + aggregate: 'count', + field: '*', + type: 'quantitative' + }; + } + else if (encoding_1.isValueQuery(encQ) || encoding_1.isDisabledAutoCountQuery(encQ)) { + continue; // Do not include this in the output. + } + // if channel is a wildcard, return null + if (wildcard_1.isWildcard(encQ.channel)) + return null; + // assemble other property into a field def. + var PROPERTIES = [property_1.Property.AGGREGATE, property_1.Property.BIN, property_1.Property.TIMEUNIT, property_1.Property.FIELD, property_1.Property.TYPE, property_1.Property.SCALE, property_1.Property.SORT, property_1.Property.AXIS, property_1.Property.LEGEND]; + for (var _b = 0, PROPERTIES_1 = PROPERTIES; _b < PROPERTIES_1.length; _b++) { + var prop = PROPERTIES_1[_b]; + // if the property's a wildcard, return null + var encodingProperty = encQ[prop]; + if (wildcard_1.isWildcard(encodingProperty)) { + return null; + } + else { + // all channels support this prop + var isSupportedByChannel = (!shorthand_1.PROPERTY_SUPPORTED_CHANNELS[prop] || shorthand_1.PROPERTY_SUPPORTED_CHANNELS[prop][encQ.channel]); + if (isSupportedByChannel) { + if (encodingProperty !== undefined) { + if (property_1.ENCODING_NESTED_PROP_PARENT_INDEX[prop]) { + for (var childProp in encQ[prop]) { + // ensure nested properties are not wildcard before assigning to field def + if (wildcard_1.isWildcard(encQ[prop][childProp])) { + return null; + } + } + } + fieldDef[prop] = encodingProperty; + } + if (prop === property_1.Property.SCALE && encoding_1.isFieldQuery(encQ) && encQ.type === type_1.Type.ORDINAL) { + var scale = encQ.scale; + var ordinalDomain = this._schema.fieldSchema(encQ.field).ordinalDomain; + if (scale !== null && ordinalDomain) { + fieldDef[property_1.Property.SCALE] = __assign({ domain: ordinalDomain }, (util_1.isObject(scale) ? scale : {})); + } + } + } + } + } + if (fieldDef.bin === false) { + // exclude bin false + delete fieldDef.bin; + } + encoding[encQ.channel] = fieldDef; + } + return encoding; + }; + /** + * Convert a query to a Vega-Lite spec if it is completed. + * @return a Vega-Lite spec if completed, null otherwise. + */ + SpecQueryModel.prototype.toSpec = function (data) { + if (wildcard_1.isWildcard(this._spec.mark)) + return null; + var spec = {}; + data = data || this._spec.data; + if (data) { + spec.data = data; + } + if (this._spec.transform) { + spec.transform = this._spec.transform; + } + spec.mark = this._spec.mark; + spec.encoding = this._encoding(); + if (spec.encoding === null) { + return null; + } + if (this._spec.config || this._opt.defaultSpecConfig) + spec.config = util_1.extend({}, this._opt.defaultSpecConfig, this._spec.config); + return spec; + }; + SpecQueryModel.prototype.getRankingScore = function (rankingName) { + return this._rankingScore[rankingName]; + }; + SpecQueryModel.prototype.setRankingScore = function (rankingName, score) { + this._rankingScore[rankingName] = score; + }; + return SpecQueryModel; +}()); +exports.SpecQueryModel = SpecQueryModel; +function getTopSpecQueryItem(specQuery) { + var topItem = specQuery.items[0]; + while (topItem && isSpecQueryGroup(topItem)) { + topItem = topItem.items[0]; + } + return topItem; +} +exports.getTopSpecQueryItem = getTopSpecQueryItem; +function isSpecQueryGroup(item) { + return item.items !== undefined; +} +exports.isSpecQueryGroup = isSpecQueryGroup; + +},{"./property":13,"./query/encoding":15,"./query/groupby":17,"./query/shorthand":20,"./query/spec":21,"./util":38,"./wildcard":39,"./wildcardindex":40,"vega-lite/build/src/type":67}],12:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var channel_1 = require("vega-lite/build/src/channel"); +var util_1 = require("datalib/src/util"); +var property_1 = require("./property"); +var propindex_1 = require("./propindex"); +var groupby_1 = require("./query/groupby"); +var shorthand_1 = require("./query/shorthand"); +var spec_1 = require("./query/spec"); +/** + * Registry for all possible grouping key functions. + */ +var groupRegistry = {}; +/** + * Add a grouping function to the registry. + */ +function registerKeyFn(name, keyFn) { + groupRegistry[name] = keyFn; +} +exports.registerKeyFn = registerKeyFn; +exports.FIELD = 'field'; +exports.FIELD_TRANSFORM = 'fieldTransform'; +exports.ENCODING = 'encoding'; +exports.TRANSPOSE = 'transpose'; +exports.SPEC = 'spec'; +/** + * Group the input spec query model by a key function registered in the group registry + * @return + */ +function nest(specModels, queryNest) { + if (queryNest) { + var rootGroup_1 = { + name: '', + path: '', + items: [], + }; + var groupIndex_1 = {}; + // global `includes` and `replaces` will get augmented by each level's groupBy. + // Upper level's `groupBy` will get cascaded to lower-level groupBy. + // `replace` can be overriden in a lower-level to support different grouping. + var includes_1 = []; + var replaces = []; + var replacers_1 = []; + for (var l = 0; l < queryNest.length; l++) { + includes_1.push(l > 0 ? includes_1[l - 1].duplicate() : new propindex_1.PropIndex()); + replaces.push(l > 0 ? replaces[l - 1].duplicate() : new propindex_1.PropIndex()); + var groupBy = queryNest[l].groupBy; + if (util_1.isArray(groupBy)) { + // If group is array, it's an array of extended group by that need to be parsed + var parsedGroupBy = groupby_1.parseGroupBy(groupBy, includes_1[l], replaces[l]); + replacers_1.push(parsedGroupBy.replacer); + } + } + // With includes and replacers, now we can construct the nesting tree + specModels.forEach(function (specM) { + var path = ''; + var group = rootGroup_1; + for (var l = 0; l < queryNest.length; l++) { + var groupBy = group.groupBy = queryNest[l].groupBy; + group.orderGroupBy = queryNest[l].orderGroupBy; + var key = util_1.isArray(groupBy) ? + shorthand_1.spec(specM.specQuery, includes_1[l], replacers_1[l]) : + groupRegistry[groupBy](specM); + path += '/' + key; + if (!groupIndex_1[path]) { + groupIndex_1[path] = { + name: key, + path: path, + items: [], + }; + group.items.push(groupIndex_1[path]); + } + group = groupIndex_1[path]; + } + group.items.push(specM); + }); + return rootGroup_1; + } + else { + // no nesting, just return a flat group + return { + name: '', + path: '', + items: specModels, + }; + } +} +exports.nest = nest; +// TODO: move this to groupBy, rename properly, and export +var GROUP_BY_FIELD = [property_1.Property.FIELD]; +var PARSED_GROUP_BY_FIELD = groupby_1.parseGroupBy(GROUP_BY_FIELD); +registerKeyFn(exports.FIELD, function (specM) { + return shorthand_1.spec(specM.specQuery, PARSED_GROUP_BY_FIELD.include, PARSED_GROUP_BY_FIELD.replacer); +}); +exports.PARSED_GROUP_BY_FIELD_TRANSFORM = groupby_1.parseGroupBy(groupby_1.GROUP_BY_FIELD_TRANSFORM); +registerKeyFn(exports.FIELD_TRANSFORM, function (specM) { + return shorthand_1.spec(specM.specQuery, exports.PARSED_GROUP_BY_FIELD_TRANSFORM.include, exports.PARSED_GROUP_BY_FIELD_TRANSFORM.replacer); +}); +exports.PARSED_GROUP_BY_ENCODING = groupby_1.parseGroupBy(groupby_1.GROUP_BY_ENCODING); +registerKeyFn(exports.ENCODING, function (specM) { + return shorthand_1.spec(specM.specQuery, exports.PARSED_GROUP_BY_ENCODING.include, exports.PARSED_GROUP_BY_ENCODING.replacer); +}); +function stringifyStack(specM) { + var _stack = spec_1.stack(specM.specQuery); + return (!!_stack ? 'stack=' + _stack.offset + '|' : ''); +} +// TODO: rename, provide similar format +registerKeyFn(exports.TRANSPOSE, function (specM) { + return specM.getMark() + '|' + + stringifyStack(specM) + + specM.getEncodings().map(function (encQ) { + var fieldDef = shorthand_1.fieldDef(encQ); + var channel = (encQ.channel === channel_1.Channel.X || encQ.channel === channel_1.Channel.Y) ? 'xy' : + (encQ.channel === channel_1.Channel.ROW || encQ.channel === channel_1.Channel.COLUMN) ? 'facet' : + encQ.channel; + return channel + ':' + fieldDef; + }) + .sort() + .join('|'); +}); +registerKeyFn(exports.SPEC, function (specM) { return JSON.stringify(specM.specQuery); }); + +},{"./property":13,"./propindex":14,"./query/groupby":17,"./query/shorthand":20,"./query/spec":21,"datalib/src/util":48,"vega-lite/build/src/channel":57}],13:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var axis_1 = require("vega-lite/build/src/axis"); +var scale_1 = require("vega-lite/build/src/scale"); +var legend_1 = require("vega-lite/build/src/legend"); +var util_1 = require("./util"); +function isEncodingNestedProp(p) { + return !!p['parent']; +} +exports.isEncodingNestedProp = isEncodingNestedProp; +exports.ENCODING_TOPLEVEL_PROPS = [ + // channel + 'channel', + // fn + 'aggregate', 'autoCount', 'bin', 'timeUnit', 'hasFn', + // sort + 'sort', + // field / type + 'field', 'type', + // scale / axis / legend + 'scale', 'axis', 'legend' +]; +var ENCODING_TOPLEVEL_PROPERTY_INDEX = util_1.toMap(exports.ENCODING_TOPLEVEL_PROPS); +function isEncodingTopLevelProperty(p) { + return p in ENCODING_TOPLEVEL_PROPERTY_INDEX; +} +exports.isEncodingTopLevelProperty = isEncodingTopLevelProperty; +var ENCODING_NESTED_PROP_PARENTS = [ + 'bin', 'scale', 'sort', 'axis', 'legend' +]; +exports.ENCODING_NESTED_PROP_PARENT_INDEX = util_1.toMap(ENCODING_NESTED_PROP_PARENTS); +function hasNestedProperty(prop) { + return exports.ENCODING_NESTED_PROP_PARENT_INDEX[prop]; +} +exports.hasNestedProperty = hasNestedProperty; +exports.BIN_CHILD_PROPS = ['maxbins', 'divide', 'extent', 'base', 'step', 'steps', 'minstep']; +exports.SORT_CHILD_PROPS = ['field', 'op', 'order']; +exports.SCALE_CHILD_PROPS = ['clamp', 'domain', 'exponent', 'nice', 'range', 'rangeStep', 'round', 'type', 'zero']; +var BIN_PROPS = exports.BIN_CHILD_PROPS.map(function (c) { + return { parent: 'bin', child: c }; +}); +exports.SORT_PROPS = exports.SORT_CHILD_PROPS.map(function (c) { + return { parent: 'sort', child: c }; +}); +exports.SCALE_PROPS = scale_1.SCALE_PROPERTIES.map(function (c) { + return { parent: 'scale', child: c }; +}); +var AXIS_PROPS = axis_1.AXIS_PROPERTIES.map(function (c) { + return { parent: 'axis', child: c }; +}); +var LEGEND_PROPS = legend_1.LEGEND_PROPERTIES.map(function (c) { + return { parent: 'legend', child: c }; +}); +exports.ENCODING_NESTED_PROPS = [].concat(BIN_PROPS, exports.SORT_PROPS, exports.SCALE_PROPS, AXIS_PROPS, LEGEND_PROPS); +var PROP_KEY_DELIMITER = '.'; +function toKey(p) { + if (isEncodingNestedProp(p)) { + return p.parent + PROP_KEY_DELIMITER + p.child; + } + return p; +} +exports.toKey = toKey; +function fromKey(k) { + var split = k.split(PROP_KEY_DELIMITER); + /* istanbul ignore else */ + if (split.length === 1) { + return k; + } + else if (split.length === 2) { + return { + parent: split[0], + child: split[1] + }; + } + else { + throw 'Invalid property key with ' + split.length + ' dots: ' + k; + } +} +exports.fromKey = fromKey; +var ENCODING_NESTED_PROP_INDEX = exports.ENCODING_NESTED_PROPS.reduce(function (i, prop) { + i[prop.parent] = i[prop.parent] || []; + i[prop.parent][prop.child] = prop; + return i; +}, {}); +// FIXME consider using a more general method +function getEncodingNestedProp(parent, child) { + return (ENCODING_NESTED_PROP_INDEX[parent] || {})[child]; +} +exports.getEncodingNestedProp = getEncodingNestedProp; +function isEncodingProperty(prop) { + return isEncodingTopLevelProperty(prop) || isEncodingNestedProp(prop); +} +exports.isEncodingProperty = isEncodingProperty; +exports.ALL_ENCODING_PROPS = [].concat(exports.ENCODING_TOPLEVEL_PROPS, exports.ENCODING_NESTED_PROPS); +exports.DEFAULT_PROP_PRECEDENCE = [ + 'type', + 'field', + // Field Transform + 'bin', 'timeUnit', 'aggregate', 'autoCount', + // Encoding + 'channel', + // Mark + 'mark', + 'scale', 'sort', + 'axis', 'legend' +].concat(BIN_PROPS, exports.SCALE_PROPS, AXIS_PROPS, LEGEND_PROPS, exports.SORT_PROPS); +var Property; +(function (Property) { + Property.MARK = 'mark'; + Property.TRANSFORM = 'transform'; + // Layout + Property.STACK = 'stack'; + // TODO: sub parts of stack + // Encoding Properties + Property.CHANNEL = 'channel'; + Property.AGGREGATE = 'aggregate'; + Property.AUTOCOUNT = 'autoCount'; + Property.BIN = 'bin'; + Property.HAS_FN = 'hasFn'; + Property.TIMEUNIT = 'timeUnit'; + Property.FIELD = 'field'; + Property.TYPE = 'type'; + Property.SORT = 'sort'; + Property.SCALE = 'scale'; + Property.AXIS = 'axis'; + Property.LEGEND = 'legend'; +})(Property = exports.Property || (exports.Property = {})); + +},{"./util":38,"vega-lite/build/src/axis":55,"vega-lite/build/src/legend":61,"vega-lite/build/src/scale":65}],14:[function(require,module,exports){ +"use strict"; +var __assign = (this && this.__assign) || Object.assign || function(t) { + for (var s, i = 1, n = arguments.length; i < n; i++) { + s = arguments[i]; + for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) + t[p] = s[p]; + } + return t; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +var util_1 = require("./util"); +var property_1 = require("./property"); +/** + * Dictionary that takes property as a key. + */ +var PropIndex = (function () { + function PropIndex(i) { + if (i === void 0) { i = null; } + this.index = i ? __assign({}, i) : {}; + } + PropIndex.prototype.has = function (p) { + return property_1.toKey(p) in this.index; + }; + PropIndex.prototype.get = function (p) { + return this.index[property_1.toKey(p)]; + }; + PropIndex.prototype.set = function (p, value) { + this.index[property_1.toKey(p)] = value; + return this; + }; + PropIndex.prototype.setByKey = function (key, value) { + this.index[key] = value; + }; + PropIndex.prototype.map = function (f) { + var i = new PropIndex(); + for (var k in this.index) { + i.index[k] = f(this.index[k]); + } + return i; + }; + PropIndex.prototype.size = function () { + return util_1.keys(this.index).length; + }; + PropIndex.prototype.duplicate = function () { + return new PropIndex(this.index); + }; + return PropIndex; +}()); +exports.PropIndex = PropIndex; + +},{"./property":13,"./util":38}],15:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var vlFieldDef = require("vega-lite/build/src/fielddef"); +var expandedtype_1 = require("./expandedtype"); +var type_1 = require("vega-lite/build/src/compile/scale/type"); +var wildcard_1 = require("../wildcard"); +function isValueQuery(encQ) { + return encQ !== null && encQ !== undefined && encQ['value']; +} +exports.isValueQuery = isValueQuery; +function isFieldQuery(encQ) { + return encQ !== null && encQ !== undefined && encQ['field']; +} +exports.isFieldQuery = isFieldQuery; +function isAutoCountQuery(encQ) { + return encQ !== null && encQ !== undefined && 'autoCount' in encQ; +} +exports.isAutoCountQuery = isAutoCountQuery; +function isDisabledAutoCountQuery(encQ) { + return isAutoCountQuery(encQ) && encQ.autoCount === false; +} +exports.isDisabledAutoCountQuery = isDisabledAutoCountQuery; +function isEnabledAutoCountQuery(encQ) { + return isAutoCountQuery(encQ) && encQ.autoCount === true; +} +exports.isEnabledAutoCountQuery = isEnabledAutoCountQuery; +function toFieldDef(encQ, props) { + if (props === void 0) { props = ['aggregate', 'bin', 'timeUnit', 'field', 'type']; } + if (isFieldQuery(encQ)) { + return props.reduce(function (fieldDef, prop) { + if (wildcard_1.isWildcard(encQ[prop])) { + throw new Error("Cannot convert " + JSON.stringify(encQ) + " to fielddef: " + prop + " is wildcard"); + } + else if (encQ[prop] !== undefined) { + fieldDef[prop] = encQ[prop]; + } + return fieldDef; + }, {}); + } + else { + if (encQ.autoCount === false) { + throw new Error("Cannot convert {autoCount: false} into a field def"); + } + else { + return props.reduce(function (fieldDef, prop) { + if (wildcard_1.isWildcard(encQ[prop])) { + throw new Error("Cannot convert " + JSON.stringify(encQ) + " to fielddef: " + prop + " is wildcard"); + } + switch (prop) { + case 'type': + fieldDef.type = 'quantitative'; + break; + case 'aggregate': + fieldDef.aggregate = 'count'; + break; + } + return fieldDef; + }, {}); + } + } +} +exports.toFieldDef = toFieldDef; +/** + * Is a field query continuous field? + * This method is applicable only for fieldQuery without wildcard + */ +function isContinuous(encQ) { + return isFieldQuery(encQ) && vlFieldDef.isContinuous(toFieldDef(encQ, ['bin', 'timeUnit', 'field', 'type'])); +} +exports.isContinuous = isContinuous; +/** + * Is a field query discrete field? + * This method is applicable only for fieldQuery without wildcard + */ +function isDiscrete(encQ) { + return isFieldQuery(encQ) && vlFieldDef.isDiscrete(toFieldDef(encQ, ['bin', 'timeUnit', 'field', 'type'])); +} +exports.isDiscrete = isDiscrete; +/** + * Returns the true scale type of an encoding. + * @returns {ScaleType} If the scale type was not specified, it is inferred from the encoding's Type. + * @returns {undefined} If the scale type was not specified and Type (or TimeUnit if applicable) is a Wildcard, there is no clear scale type + */ +function scaleType(fieldQ) { + var scale = fieldQ.scale === true || fieldQ.scale === wildcard_1.SHORT_WILDCARD ? {} : fieldQ.scale || {}; + var type = fieldQ.type, channel = fieldQ.channel, timeUnit = fieldQ.timeUnit, bin = fieldQ.bin; + // HACK: All of markType, and scaleConfig only affect + // sub-type of ordinal to quantitative scales (point or band) + // Currently, most of scaleType usage in CompassQL doesn't care about this subtle difference. + // Thus, instead of making this method requiring the global mark, + // we will just call it with mark = undefined . + // Thus, currently, we will always get a point scale unless a CompassQuery specifies band. + var markType = undefined; + var scaleConfig = {}; + if (wildcard_1.isWildcard(scale.type) || wildcard_1.isWildcard(type) || wildcard_1.isWildcard(channel) || wildcard_1.isWildcard(bin)) { + return undefined; + } + // If scale type is specified, then use scale.type + if (scale.type) { + return scale.type; + } + var rangeStep = undefined; + // Note: Range step currently does not matter as we don't pass mark into compileScaleType anyway. + // However, if we pass mark, we could use a rule like the following. + // I also have few test cases listed in encoding.test.ts + // if (channel === 'x' || channel === 'y') { + // if (isWildcard(scale.rangeStep)) { + // if (isShortWildcard(scale.rangeStep)) { + // return undefined; + // } else if (scale.rangeStep.enum) { + // const e = scale.rangeStep.enum; + // // if enumerated value contains enum then we can't be sure + // if (contains(e, undefined) || contains(e, null)) { + // return undefined; + // } + // rangeStep = e[0]; + // } + // } + // } + // if type is fixed and it's not temporal, we can ignore time unit. + if (type === 'temporal' && wildcard_1.isWildcard(timeUnit)) { + return undefined; + } + // if type is fixed and it's not quantitative, we can ignore bin + if (type === 'quantitative' && wildcard_1.isWildcard(bin)) { + return undefined; + } + var vegaLiteType = type === expandedtype_1.ExpandedType.KEY ? 'nominal' : type; + var fieldDef = { type: vegaLiteType, timeUnit: timeUnit, bin: bin }; + return type_1.scaleType(scale.type, channel, fieldDef, markType, rangeStep, scaleConfig); +} +exports.scaleType = scaleType; + +},{"../wildcard":39,"./expandedtype":16,"vega-lite/build/src/compile/scale/type":58,"vega-lite/build/src/fielddef":60}],16:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var type_1 = require("vega-lite/build/src/type"); +var ExpandedType; +(function (ExpandedType) { + ExpandedType.QUANTITATIVE = type_1.Type.QUANTITATIVE; + ExpandedType.ORDINAL = type_1.Type.ORDINAL; + ExpandedType.TEMPORAL = type_1.Type.TEMPORAL; + ExpandedType.NOMINAL = type_1.Type.NOMINAL; + ExpandedType.KEY = 'key'; +})(ExpandedType = exports.ExpandedType || (exports.ExpandedType = {})); +function isDiscrete(fieldType) { + return fieldType === type_1.Type.ORDINAL || fieldType === type_1.Type.NOMINAL || fieldType === ExpandedType.KEY; +} +exports.isDiscrete = isDiscrete; + +},{"vega-lite/build/src/type":67}],17:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var util_1 = require("datalib/src/util"); +var shorthand_1 = require("./shorthand"); +var property_1 = require("../property"); +var propindex_1 = require("../propindex"); +var util_2 = require("../util"); +exports.REPLACE_BLANK_FIELDS = { '*': '' }; +exports.REPLACE_XY_CHANNELS = { x: 'xy', y: 'xy' }; +exports.REPLACE_FACET_CHANNELS = { row: 'facet', column: 'facet' }; +exports.REPLACE_MARK_STYLE_CHANNELS = { color: 'style', opacity: 'style', shape: 'style', size: 'style' }; +function isExtendedGroupBy(g) { + return util_1.isObject(g) && !!g['property']; +} +exports.isExtendedGroupBy = isExtendedGroupBy; +function parseGroupBy(groupBy, include, replaceIndex) { + include = include || new propindex_1.PropIndex(); + replaceIndex = replaceIndex || new propindex_1.PropIndex(); + groupBy.forEach(function (grpBy) { + if (isExtendedGroupBy(grpBy)) { + include.setByKey(grpBy.property, true); + replaceIndex.setByKey(grpBy.property, grpBy.replace); + } + else { + include.setByKey(grpBy, true); + } + }); + return { + include: include, + replaceIndex: replaceIndex, + replacer: shorthand_1.getReplacerIndex(replaceIndex) + }; +} +exports.parseGroupBy = parseGroupBy; +function toString(groupBy) { + if (util_1.isArray(groupBy)) { + return groupBy.map(function (g) { + if (isExtendedGroupBy(g)) { + if (g.replace) { + var replaceIndex_1 = util_2.keys(g.replace).reduce(function (index, valFrom) { + var valTo = g.replace[valFrom]; + (index[valTo] = index[valTo] || []).push(valFrom); + return index; + }, {}); + return g.property + '[' + util_2.keys(replaceIndex_1).map(function (valTo) { + var valsFrom = replaceIndex_1[valTo].sort(); + return valsFrom.join(',') + '=>' + valTo; + }).join(';') + ']'; + } + return g.property; + } + return g; + }).join(','); + } + else { + return groupBy; + } +} +exports.toString = toString; +exports.GROUP_BY_FIELD_TRANSFORM = [ + property_1.Property.FIELD, property_1.Property.TYPE, + property_1.Property.AGGREGATE, property_1.Property.BIN, property_1.Property.TIMEUNIT, property_1.Property.STACK +]; +exports.GROUP_BY_ENCODING = exports.GROUP_BY_FIELD_TRANSFORM.concat([ + { + property: property_1.Property.CHANNEL, + replace: { + 'x': 'xy', 'y': 'xy', + 'color': 'style', 'size': 'style', 'shape': 'style', 'opacity': 'style', + 'row': 'facet', 'column': 'facet' + } + } +]); + +},{"../property":13,"../propindex":14,"../util":38,"./shorthand":20,"datalib/src/util":48}],18:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.encoding = require("./encoding"); +var normalize_1 = require("./normalize"); +exports.normalize = normalize_1.normalize; +exports.groupBy = require("./groupby"); +exports.shorthand = require("./shorthand"); +exports.spec = require("./spec"); +exports.transform = require("./transform"); + +},{"./encoding":15,"./groupby":17,"./normalize":19,"./shorthand":20,"./spec":21,"./transform":22}],19:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var util_1 = require("../util"); +/** + * Normalize the non-nested version of the query to a standardize nested + */ +function normalize(q) { + if (q.groupBy) { + var nest = { + groupBy: q.groupBy + }; + if (q.orderBy) { + nest.orderGroupBy = q.orderBy; + } + var normalizedQ = { + spec: util_1.duplicate(q.spec), + nest: [nest], + }; + if (q.chooseBy) { + normalizedQ.chooseBy = q.chooseBy; + } + if (q.config) { + normalizedQ.config = q.config; + } + return normalizedQ; + } + return util_1.duplicate(q); // We will cause side effect to q.spec in SpecQueryModel.build +} +exports.normalize = normalize; + +},{"../util":38}],20:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var aggregate_1 = require("vega-lite/build/src/aggregate"); +var channel_1 = require("vega-lite/build/src/channel"); +var timeunit_1 = require("vega-lite/build/src/timeunit"); +var type_1 = require("vega-lite/build/src/type"); +var util_1 = require("datalib/src/util"); +var encoding_1 = require("./encoding"); +var spec_1 = require("./spec"); +var wildcard_1 = require("../wildcard"); +var property_1 = require("../property"); +var propindex_1 = require("../propindex"); +var util_2 = require("../util"); +function getReplacerIndex(replaceIndex) { + return replaceIndex.map(function (r) { return getReplacer(r); }); +} +exports.getReplacerIndex = getReplacerIndex; +function getReplacer(replace) { + return function (s) { + if (replace[s] !== undefined) { + return replace[s]; + } + return s; + }; +} +exports.getReplacer = getReplacer; +function value(v, replacer) { + if (wildcard_1.isWildcard(v)) { + // Return the enum array if it's a full wildcard, or just return SHORT_WILDCARD for short ones. + if (!wildcard_1.isShortWildcard(v) && v.enum) { + return wildcard_1.SHORT_WILDCARD + JSON.stringify(v.enum); + } + else { + return wildcard_1.SHORT_WILDCARD; + } + } + if (replacer) { + return replacer(v); + } + return v; +} +exports.value = value; +function replace(v, replacer) { + if (replacer) { + return replacer(v); + } + return v; +} +exports.replace = replace; +exports.REPLACE_NONE = new propindex_1.PropIndex(); +exports.INCLUDE_ALL = +// FIXME: remove manual TRANSFORM concat once we really support enumerating transform. +[].concat(property_1.DEFAULT_PROP_PRECEDENCE, property_1.SORT_PROPS, [property_1.Property.TRANSFORM, property_1.Property.STACK]) + .reduce(function (pi, prop) { return pi.set(prop, true); }, new propindex_1.PropIndex()); +function vlSpec(vlspec, include, replace) { + if (include === void 0) { include = exports.INCLUDE_ALL; } + if (replace === void 0) { replace = exports.REPLACE_NONE; } + var specQ = spec_1.fromSpec(vlspec); + return spec(specQ, include, replace); +} +exports.vlSpec = vlSpec; +exports.PROPERTY_SUPPORTED_CHANNELS = { + axis: { x: true, y: true, row: true, column: true }, + legend: { color: true, opacity: true, size: true, shape: true }, + scale: { x: true, y: true, color: true, opacity: true, row: true, column: true, size: true, shape: true }, + sort: { x: true, y: true, path: true, order: true } +}; +/** + * Returns a shorthand for a spec query + * @param specQ a spec query + * @param include Dict Set listing property types (key) to be included in the shorthand + * @param replace Dictionary of replace function for values of a particular property type (key) + */ +function spec(specQ, include, replace) { + if (include === void 0) { include = exports.INCLUDE_ALL; } + if (replace === void 0) { replace = exports.REPLACE_NONE; } + var parts = []; + if (include.get(property_1.Property.MARK)) { + parts.push(value(specQ.mark, replace.get(property_1.Property.MARK))); + } + if (specQ.transform && specQ.transform.length > 0) { + parts.push('transform:' + JSON.stringify(specQ.transform)); + } + // TODO: extract this to its own stack method + if (include.get(property_1.Property.STACK)) { + var _stack = spec_1.stack(specQ); + if (_stack) { + // TODO: Refactor this once we have child stack property. + // Exclude type since we don't care about type in stack + var includeExceptType = include.duplicate().set('type', false); + var field = fieldDef(_stack.fieldEncQ, includeExceptType, replace); + var groupby = fieldDef(_stack.groupByEncQ, includeExceptType, replace); + parts.push('stack={field:' + field + ',' + + (groupby ? 'by:' + groupby + ',' : '') + + 'offset:' + _stack.offset + '}'); + } + } + if (specQ.encodings) { + var encodings = specQ.encodings.reduce(function (encQs, encQ) { + // Exclude encoding mapping with autoCount=false as they are basically disabled. + if (!encoding_1.isDisabledAutoCountQuery(encQ)) { + var str = encoding(encQ, include, replace); + if (str) { + encQs.push(str); + } + } + return encQs; + }, []) + .sort() // sort at the end to ignore order + .join('|'); + if (encodings) { + parts.push(encodings); + } + } + return parts.join('|'); +} +exports.spec = spec; +/** + * Returns a shorthand for an encoding query + * @param encQ an encoding query + * @param include Dict Set listing property types (key) to be included in the shorthand + * @param replace Dictionary of replace function for values of a particular property type (key) + */ +function encoding(encQ, include, replace) { + if (include === void 0) { include = exports.INCLUDE_ALL; } + if (replace === void 0) { replace = exports.REPLACE_NONE; } + var parts = []; + if (include.get(property_1.Property.CHANNEL)) { + parts.push(value(encQ.channel, replace.get(property_1.Property.CHANNEL))); + } + if (encoding_1.isFieldQuery(encQ)) { + var fieldDefStr = fieldDef(encQ, include, replace); + if (fieldDefStr) { + parts.push(fieldDefStr); + } + } + else if (encoding_1.isValueQuery(encQ)) { + parts.push(encQ.value); + } + return parts.join(':'); +} +exports.encoding = encoding; +/** + * Returns a field definition shorthand for an encoding query + * @param encQ an encoding query + * @param include Dict Set listing property types (key) to be included in the shorthand + * @param replace Dictionary of replace function for values of a particular property type (key) + */ +function fieldDef(encQ, include, replacer) { + if (include === void 0) { include = exports.INCLUDE_ALL; } + if (replacer === void 0) { replacer = exports.REPLACE_NONE; } + if (include.get(property_1.Property.AGGREGATE) && encoding_1.isDisabledAutoCountQuery(encQ)) { + return '-'; + } + var fn = func(encQ, include, replacer); + var props = fieldDefProps(encQ, include, replacer); + var fieldAndParams; + if (encoding_1.isFieldQuery(encQ)) { + // field + fieldAndParams = include.get('field') ? value(encQ.field, replacer.get('field')) : '...'; + // type + if (include.get(property_1.Property.TYPE)) { + if (wildcard_1.isWildcard(encQ.type)) { + fieldAndParams += ',' + value(encQ.type, replacer.get(property_1.Property.TYPE)); + } + else { + var typeShort = ((encQ.type || type_1.Type.QUANTITATIVE) + '').substr(0, 1); + fieldAndParams += ',' + value(typeShort, replacer.get(property_1.Property.TYPE)); + } + } + // encoding properties + fieldAndParams += props.map(function (p) { + var val = p.value instanceof Array ? '[' + p.value + ']' : p.value; + return ',' + p.key + '=' + val; + }).join(''); + } + else if (encoding_1.isAutoCountQuery(encQ)) { + fieldAndParams = '*,q'; + } + if (!fieldAndParams) { + return null; + } + if (fn) { + var fnPrefix = util_1.isString(fn) ? fn : wildcard_1.SHORT_WILDCARD + + (util_2.keys(fn).length > 0 ? JSON.stringify(fn) : ''); + return fnPrefix + '(' + fieldAndParams + ')'; + } + return fieldAndParams; +} +exports.fieldDef = fieldDef; +/** + * Return function part of + */ +function func(fieldQ, include, replacer) { + if (include.get(property_1.Property.AGGREGATE) && fieldQ.aggregate && !wildcard_1.isWildcard(fieldQ.aggregate)) { + return replace(fieldQ.aggregate, replacer.get(property_1.Property.AGGREGATE)); + } + else if (include.get(property_1.Property.AGGREGATE) && encoding_1.isEnabledAutoCountQuery(fieldQ)) { + // autoCount is considered a part of aggregate + return replace('count', replacer.get(property_1.Property.AGGREGATE)); + ; + } + else if (include.get(property_1.Property.TIMEUNIT) && fieldQ.timeUnit && !wildcard_1.isWildcard(fieldQ.timeUnit)) { + return replace(fieldQ.timeUnit, replacer.get(property_1.Property.TIMEUNIT)); + } + else if (include.get(property_1.Property.BIN) && fieldQ.bin && !wildcard_1.isWildcard(fieldQ.bin)) { + return 'bin'; + } + else { + var fn = null; + for (var _i = 0, _a = [property_1.Property.AGGREGATE, property_1.Property.AUTOCOUNT, property_1.Property.TIMEUNIT, property_1.Property.BIN]; _i < _a.length; _i++) { + var prop = _a[_i]; + var val = fieldQ[prop]; + if (include.get(prop) && fieldQ[prop] && wildcard_1.isWildcard(val)) { + // assign fnEnumIndex[prop] = array of enum values or just "?" if it is SHORT_WILDCARD + fn = fn || {}; + fn[prop] = wildcard_1.isShortWildcard(val) ? val : val.enum; + } + } + if (fn && fieldQ.hasFn) { + fn.hasFn = true; + } + return fn; + } +} +/** + * Return key-value of parameters of field defs + */ +function fieldDefProps(fieldQ, include, replacer) { + /** Encoding properties e.g., Scale, Axis, Legend */ + var props = []; + // Parameters of function such as bin will be just top-level properties + if (!util_2.isBoolean(fieldQ.bin) && !wildcard_1.isShortWildcard(fieldQ.bin)) { + var bin = fieldQ.bin; + for (var child in bin) { + var prop = property_1.getEncodingNestedProp('bin', child); + if (prop && include.get(prop) && bin[child] !== undefined) { + props.push({ + key: child, + value: value(bin[child], replacer.get(prop)) + }); + } + } + // Sort to make sure that parameter are ordered consistently + props.sort(function (a, b) { return a.key.localeCompare(b.key); }); + } + for (var _i = 0, _a = [property_1.Property.SCALE, property_1.Property.SORT, property_1.Property.AXIS, property_1.Property.LEGEND]; _i < _a.length; _i++) { + var parent_1 = _a[_i]; + if (!wildcard_1.isWildcard(fieldQ.channel) && !exports.PROPERTY_SUPPORTED_CHANNELS[parent_1][fieldQ.channel]) { + continue; + } + if (include.get(parent_1) && fieldQ[parent_1] !== undefined) { + var parentValue = fieldQ[parent_1]; + if (util_2.isBoolean(parentValue) || parentValue === null) { + // `scale`, `axis`, `legend` can be false/null. + props.push({ + key: parent_1 + '', + value: parentValue || false // return true or false (false if null) + }); + } + else if (util_1.isString(parentValue)) { + // `sort` can be a string (ascending/descending). + props.push({ + key: parent_1 + '', + value: replace(JSON.stringify(parentValue), replacer.get(parent_1)) + }); + } + else { + var nestedPropChildren = []; + for (var child in parentValue) { + var nestedProp = property_1.getEncodingNestedProp(parent_1, child); + if (nestedProp && include.get(nestedProp) && parentValue[child] !== undefined) { + nestedPropChildren.push({ + key: child, + value: value(parentValue[child], replacer.get(nestedProp)) + }); + } + } + if (nestedPropChildren.length > 0) { + var nestedPropObject = nestedPropChildren.sort(function (a, b) { return a.key.localeCompare(b.key); }) + .reduce(function (o, item) { + o[item.key] = item.value; + return o; + }, {}); + // Sort to make sure that parameter are ordered consistently + props.push({ + key: parent_1 + '', + value: JSON.stringify(nestedPropObject) + }); + } + } + } + } + return props; +} +var CHANNEL_INDEX = util_1.toMap(channel_1.CHANNELS); +var AGGREGATE_OP_INDEX = util_1.toMap(aggregate_1.AGGREGATE_OPS); +var SINGLE_TIMEUNIT_INDEX = util_1.toMap(timeunit_1.SINGLE_TIMEUNITS); +var MULTI_TIMEUNIT_INDEX = util_1.toMap(timeunit_1.MULTI_TIMEUNITS); +function parse(shorthand) { + // TODO(https://github.com/uwdata/compassql/issues/259): + // Do not split directly, but use an upgraded version of `getClosingBraceIndex()` + var splitShorthand = shorthand.split('|'); + var specQ = { mark: splitShorthand[0], encodings: [] }; + for (var i = 1; i < splitShorthand.length; i++) { + var part = splitShorthand[i]; + var splitPart = splitWithTail(part, ':', 1); + var splitPartKey = splitPart[0]; + var splitPartValue = splitPart[1]; + if (CHANNEL_INDEX[splitPartKey] || splitPartKey === '?') { + var encQ = shorthandParser.encoding(splitPartKey, splitPartValue); + specQ.encodings.push(encQ); + continue; + } + if (splitPartKey === 'transform') { + specQ.transform = JSON.parse(splitPartValue); + continue; + } + } + return specQ; +} +exports.parse = parse; +/** + * Split a string n times into substrings with the specified delimiter and return them as an array. + * @param str The string to be split + * @param delim The delimiter string used to separate the string + * @param number The value used to determine how many times the string is split + */ +function splitWithTail(str, delim, count) { + var result = []; + var lastIndex = 0; + for (var i = 0; i < count; i++) { + var indexOfDelim = str.indexOf(delim, lastIndex); + if (indexOfDelim !== -1) { + result.push(str.substring(lastIndex, indexOfDelim)); + lastIndex = indexOfDelim + 1; + } + else { + break; + } + } + result.push(str.substr(lastIndex)); + // If the specified count is greater than the number of delimiters that exist in the string, + // an empty string will be pushed count minus number of delimiter occurence times. + if (result.length !== count + 1) { + while (result.length !== count + 1) { + result.push(''); + } + } + return result; +} +exports.splitWithTail = splitWithTail; +var shorthandParser; +(function (shorthandParser) { + function encoding(channel, fieldDefShorthand) { + var encQ = { channel: channel }; + if (fieldDefShorthand.indexOf('(') !== -1) { + encQ = fn(encQ, fieldDefShorthand); + } + else { + encQ = rawFieldDef(encQ, splitWithTail(fieldDefShorthand, ',', 2)); + } + return encQ; + } + shorthandParser.encoding = encoding; + function rawFieldDef(fieldQ, fieldDefPart) { + fieldQ.field = fieldDefPart[0]; + fieldQ.type = type_1.getFullName(fieldDefPart[1].toUpperCase()) || '?'; + var partParams = fieldDefPart[2]; + var closingBraceIndex = 0; + var i = 0; + while (i < partParams.length) { + var propEqualSignIndex = partParams.indexOf('=', i); + var parsedValue = void 0; + if (propEqualSignIndex !== -1) { + var prop = partParams.substring(i, propEqualSignIndex); + if (partParams[i + prop.length + 1] === '{') { + var openingBraceIndex = i + prop.length + 1; + closingBraceIndex = getClosingIndex(openingBraceIndex, partParams, '}'); + var value_1 = partParams.substring(openingBraceIndex, closingBraceIndex + 1); + parsedValue = JSON.parse(value_1); + // index after next comma + i = closingBraceIndex + 2; + } + else if (partParams[i + prop.length + 1] === '[') { + // find closing square bracket + var openingBracketIndex = i + prop.length + 1; + var closingBracketIndex = getClosingIndex(openingBracketIndex, partParams, ']'); + var value_2 = partParams.substring(openingBracketIndex, closingBracketIndex + 1); + parsedValue = JSON.parse(value_2); + // index after next comma + i = closingBracketIndex + 2; + } + else { + var propIndex = i; + // Substring until the next comma (or end of the string) + var nextCommaIndex = partParams.indexOf(',', i + prop.length); + if (nextCommaIndex === -1) { + nextCommaIndex = partParams.length; + } + // index after next comma + i = nextCommaIndex + 1; + parsedValue = JSON.parse(partParams.substring(propIndex + prop.length + 1, nextCommaIndex)); + } + if (property_1.hasNestedProperty(prop)) { + fieldQ[prop] = parsedValue; + } + else { + // prop is a property of the aggregation function such as bin + fieldQ.bin[prop] = parsedValue; + } + } + else { + // something is wrong with the format of the partParams + // exits loop if don't have then infintie loop + break; + } + } + return fieldQ; + } + shorthandParser.rawFieldDef = rawFieldDef; + function getClosingIndex(openingBraceIndex, str, closingChar) { + for (var i = openingBraceIndex; i < str.length; i++) { + if (str[i] === closingChar) { + return i; + } + } + } + shorthandParser.getClosingIndex = getClosingIndex; + function fn(fieldQ, fieldDefShorthand) { + // Aggregate, Bin, TimeUnit as wildcard case + if (fieldDefShorthand[0] === '?') { + var closingBraceIndex = getClosingIndex(1, fieldDefShorthand, '}'); + var fnEnumIndex = JSON.parse(fieldDefShorthand.substring(1, closingBraceIndex + 1)); + for (var encodingProperty in fnEnumIndex) { + if (util_2.isArray(fnEnumIndex[encodingProperty])) { + fieldQ[encodingProperty] = { enum: fnEnumIndex[encodingProperty] }; + } + else { + fieldQ[encodingProperty] = fnEnumIndex[encodingProperty]; + } + } + return rawFieldDef(fieldQ, splitWithTail(fieldDefShorthand.substring(closingBraceIndex + 2, fieldDefShorthand.length - 1), ',', 2)); + } + else { + var func_1 = fieldDefShorthand.substring(0, fieldDefShorthand.indexOf('(')); + var insideFn = fieldDefShorthand.substring(func_1.length + 1, fieldDefShorthand.length - 1); + var insideFnParts = splitWithTail(insideFn, ',', 2); + if (AGGREGATE_OP_INDEX[func_1]) { + fieldQ.aggregate = func_1; + return rawFieldDef(fieldQ, insideFnParts); + } + else if (MULTI_TIMEUNIT_INDEX[func_1] || SINGLE_TIMEUNIT_INDEX[func_1]) { + fieldQ.timeUnit = func_1; + return rawFieldDef(fieldQ, insideFnParts); + } + else if (func_1 === 'bin') { + fieldQ.bin = {}; + return rawFieldDef(fieldQ, insideFnParts); + } + } + } + shorthandParser.fn = fn; +})(shorthandParser = exports.shorthandParser || (exports.shorthandParser = {})); + +},{"../property":13,"../propindex":14,"../util":38,"../wildcard":39,"./encoding":15,"./spec":21,"datalib/src/util":48,"vega-lite/build/src/aggregate":54,"vega-lite/build/src/channel":57,"vega-lite/build/src/timeunit":66,"vega-lite/build/src/type":67}],21:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var channel_1 = require("vega-lite/build/src/channel"); +var wildcard_1 = require("../wildcard"); +var property_1 = require("../property"); +var util_1 = require("../util"); +var encoding_1 = require("./encoding"); +var util_2 = require("datalib/src/util"); +/** + * Convert a Vega-Lite's ExtendedUnitSpec into a CompassQL's SpecQuery + * @param {ExtendedUnitSpec} spec + * @returns + */ +function fromSpec(spec) { + return util_1.extend(spec.data ? { data: spec.data } : {}, spec.transform ? { transform: spec.transform } : {}, { + mark: spec.mark, + encodings: util_1.keys(spec.encoding).map(function (channel) { + var encQ = { channel: channel }; + var channelDef = spec.encoding[channel]; + for (var prop in channelDef) { + if (property_1.isEncodingTopLevelProperty(prop) && channelDef[prop] !== undefined) { + // Currently bin, scale, axis, legend only support boolean, but not null. + // Therefore convert null to false. + if (util_1.contains(['bin', 'scale', 'axis', 'legend'], prop) && channelDef[prop] === null) { + encQ[prop] = false; + } + else { + encQ[prop] = channelDef[prop]; + } + } + } + return encQ; + }) + }, spec.config ? { config: spec.config } : {}); +} +exports.fromSpec = fromSpec; +function isAggregate(specQ) { + return util_1.some(specQ.encodings, function (encQ) { + return (encoding_1.isFieldQuery(encQ) && !wildcard_1.isWildcard(encQ.aggregate) && !!encQ.aggregate) || encoding_1.isEnabledAutoCountQuery(encQ); + }); +} +exports.isAggregate = isAggregate; +/** + * @return the stack offset type for the specQuery + */ +function stack(specQ) { + var config = specQ.config; + var stacked = config ? config.stack : undefined; + // Should not have stack explicitly disabled + if (util_1.contains(['none', null, false], stacked)) { + return null; + } + // Should have stackable mark + if (!util_1.contains(['bar', 'area'], specQ.mark)) { + return null; + } + // Should be aggregate plot + if (!isAggregate(specQ)) { + return null; + } + var stackBy = specQ.encodings.reduce(function (sc, encQ) { + if (util_1.contains(channel_1.STACK_BY_CHANNELS, encQ.channel) && (encoding_1.isValueQuery(encQ) || (encoding_1.isFieldQuery(encQ) && !encQ.aggregate))) { + sc.push({ + channel: encQ.channel, + fieldDef: encQ + }); + } + return sc; + }, []); + if (stackBy.length === 0) { + return null; + } + // Has only one aggregate axis + var xEncQ = specQ.encodings.reduce(function (f, encQ) { + return f || (encQ.channel === channel_1.Channel.X ? encQ : null); + }, null); + var yEncQ = specQ.encodings.reduce(function (f, encQ) { + return f || (encQ.channel === channel_1.Channel.Y ? encQ : null); + }, null); + // TODO(akshatsh): Check if autoCount undef is ok + var xIsAggregate = (encoding_1.isFieldQuery(xEncQ) && !!xEncQ.aggregate) || (encoding_1.isAutoCountQuery(xEncQ) && !!xEncQ.autoCount); + var yIsAggregate = (encoding_1.isFieldQuery(yEncQ) && !!yEncQ.aggregate) || (encoding_1.isAutoCountQuery(yEncQ) && !!yEncQ.autoCount); + if (xIsAggregate !== yIsAggregate) { + return { + groupbyChannel: xIsAggregate ? (!!yEncQ ? channel_1.Y : null) : (!!xEncQ ? channel_1.X : null), + groupByEncQ: xIsAggregate ? yEncQ : xEncQ, + fieldChannel: xIsAggregate ? channel_1.X : channel_1.Y, + fieldEncQ: xIsAggregate ? xEncQ : yEncQ, + stackBy: stackBy, + offset: stacked || 'zero' + }; + } + return null; +} +exports.stack = stack; +function hasWildcard(specQ, opt) { + if (opt === void 0) { opt = {}; } + var exclude = opt.exclude ? util_2.toMap(opt.exclude.map(property_1.toKey)) : {}; + if (wildcard_1.isWildcard(specQ.mark) && !exclude['mark']) { + return true; + } + for (var _i = 0, _a = specQ.encodings; _i < _a.length; _i++) { + var encQ = _a[_i]; + // TODO: implement more efficiently, just check only properties of encQ + for (var key in encQ) { + var parentProp = key; + if (encQ.hasOwnProperty(parentProp) && property_1.isEncodingTopLevelProperty(parentProp)) { + if (wildcard_1.isWildcard(encQ[parentProp]) && !exclude[parentProp]) { + return true; + } + var propObj = encQ[parentProp]; + for (var childProp in propObj) { + if (propObj.hasOwnProperty(childProp) && !util_1.contains(['enum', 'name'], childProp)) { + var prop = { + parent: parentProp, + child: childProp + }; + if (wildcard_1.isWildcard(propObj[childProp]) && !exclude[property_1.toKey(prop)]) { + return true; + } + } + } + } + } + } + return false; +} +exports.hasWildcard = hasWildcard; + +},{"../property":13,"../util":38,"../wildcard":39,"./encoding":15,"datalib/src/util":48,"vega-lite/build/src/channel":57}],22:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); + +},{}],23:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var type_1 = require("vega-lite/build/src/type"); +var util_1 = require("../util"); +var encoding_1 = require("../query/encoding"); +exports.name = 'aggregationQuality'; +function score(specM, schema, opt) { + var feature = aggregationQualityFeature(specM, schema, opt); + return { + score: feature.score, + features: [feature] + }; +} +exports.score = score; +function isDimension(encQ) { + return encoding_1.isDiscrete(encQ) || !!encQ.timeUnit; +} +function aggregationQualityFeature(specM, _, __) { + var encodings = specM.getEncodings(); + if (specM.isAggregate()) { + var isRawContinuous = function (encQ) { + return encoding_1.isFieldQuery(encQ) && ((encQ.type === type_1.Type.QUANTITATIVE && !encQ.bin && !encQ.aggregate) || + (encQ.type === type_1.Type.TEMPORAL && !encQ.timeUnit)); + }; + if (util_1.some(encodings, isRawContinuous)) { + // These are plots that pollute continuous fields as dimension. + // They are often intermediate visualizations rather than what users actually want. + return { + type: exports.name, + score: 0.1, + feature: 'Aggregate with raw continuous' + }; + } + if (util_1.some(encodings, function (encQ) { return encoding_1.isFieldQuery(encQ) && isDimension(encQ); })) { + var hasCount = util_1.some(encodings, function (encQ) { + return (encoding_1.isFieldQuery(encQ) && encQ.aggregate === 'count') || encoding_1.isEnabledAutoCountQuery(encQ); + }); + var hasBin = util_1.some(encodings, function (encQ) { + return encoding_1.isFieldQuery(encQ) && !!encQ.bin; + }); + if (hasCount) { + // If there is count, we might add additional count field, making it a little less simple + // then when we just apply aggregate to Q field + return { + type: exports.name, + score: 0.8, + feature: 'Aggregate with count' + }; + } + else if (hasBin) { + // This is not as good as binning all the Q and show heatmap + return { + type: exports.name, + score: 0.7, + feature: 'Aggregate with bin but without count' + }; + } + else { + return { + type: exports.name, + score: 0.9, + feature: 'Aggregate without count and without bin' + }; + } + } + // no dimension -- often not very useful + return { + type: exports.name, + score: 0.3, + feature: 'Aggregate without dimension' + }; + } + else { + if (util_1.some(encodings, function (encQ) { return encoding_1.isFieldQuery(encQ) && !isDimension(encQ); })) { + // raw plots with measure -- simplest of all! + return { + type: exports.name, + score: 1, + feature: 'Raw with measure' + }; + } + // raw plots with no measure -- often a lot of occlusion + return { + type: exports.name, + score: 0.2, + feature: 'Raw without measure' + }; + } +} + +},{"../query/encoding":15,"../util":38,"vega-lite/build/src/type":67}],24:[function(require,module,exports){ +"use strict"; +/** + * Field Type (with Bin and TimeUnit) and Channel Score (Cleveland / Mackinlay based) + */ +var __extends = (this && this.__extends) || (function () { + var extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +var __assign = (this && this.__assign) || Object.assign || function(t) { + for (var s, i = 1, n = arguments.length; i < n; i++) { + s = arguments[i]; + for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) + t[p] = s[p]; + } + return t; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +var channel_1 = require("vega-lite/build/src/channel"); +var config_1 = require("../../config"); +var type_1 = require("./type"); +var base_1 = require("./base"); +/** + * Effectiveness Score for preferred axis. + */ +var AxisScorer = (function (_super) { + __extends(AxisScorer, _super); + function AxisScorer() { + return _super.call(this, 'Axis') || this; + } + AxisScorer.prototype.initScore = function (opt) { + if (opt === void 0) { opt = {}; } + opt = __assign({}, config_1.DEFAULT_QUERY_CONFIG, opt); + var score = {}; + var preferredAxes = [{ + feature: type_1.BIN_Q, + opt: 'preferredBinAxis' + }, { + feature: type_1.T, + opt: 'preferredTemporalAxis' + }, { + feature: type_1.TIMEUNIT_T, + opt: 'preferredTemporalAxis' + }, { + feature: type_1.TIMEUNIT_O, + opt: 'preferredTemporalAxis' + }, { + feature: type_1.O, + opt: 'preferredOrdinalAxis' + }, { + feature: type_1.N, + opt: 'preferredNominalAxis' + }]; + preferredAxes.forEach(function (pAxis) { + if (opt[pAxis.opt] === channel_1.Channel.X) { + // penalize the other axis + score[pAxis.feature + '_' + channel_1.Channel.Y] = -0.01; + } + else if (opt[pAxis.opt] === channel_1.Channel.Y) { + // penalize the other axis + score[pAxis.feature + '_' + channel_1.Channel.X] = -0.01; + } + }); + return score; + }; + AxisScorer.prototype.featurize = function (type, channel) { + return type + '_' + channel; + }; + AxisScorer.prototype.getScore = function (specM, _, __) { + var _this = this; + return specM.getEncodings().reduce(function (features, encQ) { + var type = type_1.getExtendedType(encQ); + var feature = _this.featurize(type, encQ.channel); + var featureScore = _this.getFeatureScore(feature); + if (featureScore) { + features.push(featureScore); + } + return features; + }, []); + }; + return AxisScorer; +}(base_1.Scorer)); +exports.AxisScorer = AxisScorer; + +},{"../../config":1,"./base":25,"./type":31,"vega-lite/build/src/channel":57}],25:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var Scorer = (function () { + function Scorer(type) { + this.type = type; + this.scoreIndex = this.initScore(); + } + Scorer.prototype.getFeatureScore = function (feature) { + var type = this.type; + var score = this.scoreIndex[feature]; + if (score !== undefined) { + return { type: type, feature: feature, score: score }; + } + return undefined; + }; + return Scorer; +}()); +exports.Scorer = Scorer; + +},{}],26:[function(require,module,exports){ +"use strict"; +var __extends = (this && this.__extends) || (function () { + var extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +Object.defineProperty(exports, "__esModule", { value: true }); +var base_1 = require("./base"); +var encoding_1 = require("../../query/encoding"); +/** + * Penalize if facet channels are the only dimensions + */ +var DimensionScorer = (function (_super) { + __extends(DimensionScorer, _super); + function DimensionScorer() { + return _super.call(this, 'Dimension') || this; + } + DimensionScorer.prototype.initScore = function () { + return { + row: -2, + column: -2, + color: 0, + opacity: 0, + size: 0, + shape: 0 + }; + }; + DimensionScorer.prototype.getScore = function (specM, _, __) { + var _this = this; + if (specM.isAggregate()) { + specM.getEncodings().reduce(function (maxFScore, encQ) { + if (encoding_1.isFieldQuery(encQ) && !encQ.aggregate) { + var featureScore = _this.getFeatureScore(encQ.channel + ''); + if (featureScore && featureScore.score > maxFScore.score) { + return featureScore; + } + } + return maxFScore; + }, { type: 'Dimension', feature: 'No Dimension', score: -5 }); + } + return []; + }; + return DimensionScorer; +}(base_1.Scorer)); +exports.DimensionScorer = DimensionScorer; + +},{"../../query/encoding":15,"./base":25}],27:[function(require,module,exports){ +"use strict"; +var __extends = (this && this.__extends) || (function () { + var extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +var __assign = (this && this.__assign) || Object.assign || function(t) { + for (var s, i = 1, n = arguments.length; i < n; i++) { + s = arguments[i]; + for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) + t[p] = s[p]; + } + return t; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +var base_1 = require("./base"); +var config_1 = require("../../config"); +var channel_1 = require("vega-lite/build/src/channel"); +/** + * Effective Score for preferred facet + */ +var FacetScorer = (function (_super) { + __extends(FacetScorer, _super); + function FacetScorer() { + return _super.call(this, 'Facet') || this; + } + FacetScorer.prototype.initScore = function (opt) { + opt = __assign({}, config_1.DEFAULT_QUERY_CONFIG, opt); + var score = {}; + if (opt.preferredFacet === channel_1.Channel.ROW) { + // penalize the other axis + score[channel_1.Channel.COLUMN] = -0.01; + } + else if (opt.preferredFacet === channel_1.Channel.COLUMN) { + // penalize the other axis + score[channel_1.Channel.ROW] = -0.01; + } + return score; + }; + FacetScorer.prototype.getScore = function (specM, _, __) { + var _this = this; + return specM.getEncodings().reduce(function (features, encQ) { + var featureScore = _this.getFeatureScore(encQ.channel); + if (featureScore) { + features.push(featureScore); + } + return features; + }, []); + }; + return FacetScorer; +}(base_1.Scorer)); +exports.FacetScorer = FacetScorer; +; + +},{"../../config":1,"./base":25,"vega-lite/build/src/channel":57}],28:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var axis_1 = require("./axis"); +var dimension_1 = require("./dimension"); +var facet_1 = require("./facet"); +var sizechannel_1 = require("./sizechannel"); +var typechannel_1 = require("./typechannel"); +var mark_1 = require("./mark"); +var SCORERS = [ + new axis_1.AxisScorer(), + new dimension_1.DimensionScorer(), + new facet_1.FacetScorer(), + new mark_1.MarkScorer(), + new sizechannel_1.SizeChannelScorer(), + new typechannel_1.TypeChannelScorer() +]; +// TODO: x/y, row/column preference +// TODO: stacking +// TODO: Channel, Cardinality +// TODO: Penalize over encoding +function effectiveness(specM, schema, opt) { + var features = SCORERS.reduce(function (f, scorer) { + var scores = scorer.getScore(specM, schema, opt); + return f.concat(scores); + }, []); + return { + score: features.reduce(function (s, f) { + return s + f.score; + }, 0), + features: features + }; +} +exports.effectiveness = effectiveness; + +},{"./axis":24,"./dimension":26,"./facet":27,"./mark":29,"./sizechannel":30,"./typechannel":32}],29:[function(require,module,exports){ +"use strict"; +var __extends = (this && this.__extends) || (function () { + var extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +Object.defineProperty(exports, "__esModule", { value: true }); +var channel_1 = require("vega-lite/build/src/channel"); +var mark_1 = require("vega-lite/build/src/mark"); +var util_1 = require("../../util"); +var type_1 = require("./type"); +var base_1 = require("./base"); +var MarkScorer = (function (_super) { + __extends(MarkScorer, _super); + function MarkScorer() { + return _super.call(this, 'Mark') || this; + } + MarkScorer.prototype.initScore = function () { + return init(); + }; + MarkScorer.prototype.getScore = function (specM, _, __) { + var mark = specM.getMark(); + if (mark === mark_1.Mark.CIRCLE || mark === mark_1.Mark.SQUARE) { + mark = mark_1.Mark.POINT; + } + var xEncQ = specM.getEncodingQueryByChannel(channel_1.Channel.X); + var xType = xEncQ ? type_1.getExtendedType(xEncQ) : type_1.NONE; + var yEncQ = specM.getEncodingQueryByChannel(channel_1.Channel.Y); + var yType = yEncQ ? type_1.getExtendedType(yEncQ) : type_1.NONE; + var isOccluded = !specM.isAggregate(); // FIXME + var feature = xType + '_' + yType + '_' + isOccluded + '_' + mark; + var featureScore = this.getFeatureScore(feature); + return [featureScore]; + }; + return MarkScorer; +}(base_1.Scorer)); +exports.MarkScorer = MarkScorer; +function featurize(xType, yType, hasOcclusion, mark) { + return xType + '_' + yType + '_' + hasOcclusion + '_' + mark; +} +exports.featurize = featurize; +function init() { + var MEASURES = [type_1.Q, type_1.T]; + var DISCRETE = [type_1.BIN_Q, type_1.TIMEUNIT_O, type_1.O, type_1.N]; + var DISCRETE_OR_NONE = DISCRETE.concat([type_1.NONE]); + var SCORE = {}; + // QxQ + MEASURES.forEach(function (xType) { + MEASURES.forEach(function (yType) { + // has occlusion + var occludedQQMark = { + point: 0, + text: -0.2, + tick: -0.5, + rect: -1, + bar: -2, + line: -2, + area: -2, + rule: -2.5 + }; + util_1.forEach(occludedQQMark, function (score, mark) { + var feature = featurize(xType, yType, true, mark); + SCORE[feature] = score; + }); + // no occlusion + // TODO: possible to use connected scatter plot + var noOccludedQQMark = { + point: 0, + text: -0.2, + tick: -0.5, + bar: -2, + line: -2, + area: -2, + rule: -2.5 + }; + util_1.forEach(noOccludedQQMark, function (score, mark) { + var feature = featurize(xType, yType, false, mark); + SCORE[feature] = score; + }); + }); + }); + // DxQ, QxD + MEASURES.forEach(function (xType) { + // HAS OCCLUSION + DISCRETE_OR_NONE.forEach(function (yType) { + var occludedDimensionMeasureMark = { + tick: 0, + point: -0.2, + text: -0.5, + bar: -2, + line: -2, + area: -2, + rule: -2.5 + }; + util_1.forEach(occludedDimensionMeasureMark, function (score, mark) { + var feature = featurize(xType, yType, true, mark); + SCORE[feature] = score; + // also do the inverse + var feature2 = featurize(yType, xType, true, mark); + SCORE[feature2] = score; + }); + }); + [type_1.TIMEUNIT_T].forEach(function (yType) { + var occludedDimensionMeasureMark = { + // For Time Dimension with time scale, tick is not good + point: 0, + text: -0.5, + tick: -1, + bar: -2, + line: -2, + area: -2, + rule: -2.5 + }; + util_1.forEach(occludedDimensionMeasureMark, function (score, mark) { + var feature = featurize(xType, yType, true, mark); + SCORE[feature] = score; + // also do the inverse + var feature2 = featurize(yType, xType, true, mark); + SCORE[feature2] = score; + }); + }); + // NO OCCLUSION + [type_1.NONE, type_1.N, type_1.O].forEach(function (yType) { + var noOccludedQxN = { + bar: 0, + point: -0.2, + tick: -0.25, + text: -0.3, + // Line / Area can mislead trend for N + line: -2, + area: -2, + // Non-sense to use rule here + rule: -2.5 + }; + util_1.forEach(noOccludedQxN, function (score, mark) { + var feature = featurize(xType, yType, false, mark); + SCORE[feature] = score; + // also do the inverse + var feature2 = featurize(yType, xType, false, mark); + SCORE[feature2] = score; + }); + }); + [type_1.BIN_Q].forEach(function (yType) { + var noOccludedQxBinQ = { + bar: 0, + point: -0.2, + tick: -0.25, + text: -0.3, + // Line / Area isn't the best fit for bin + line: -0.5, + area: -0.5, + // Non-sense to use rule here + rule: -2.5 + }; + util_1.forEach(noOccludedQxBinQ, function (score, mark) { + var feature = featurize(xType, yType, false, mark); + SCORE[feature] = score; + // also do the inverse + var feature2 = featurize(yType, xType, false, mark); + SCORE[feature2] = score; + }); + }); + [type_1.TIMEUNIT_T, type_1.TIMEUNIT_O].forEach(function (yType) { + // For aggregate / surely no occlusion plot, Temporal with time or ordinal + // are not that different. + var noOccludedQxBinQ = { + line: 0, + area: -0.1, + bar: -0.2, + point: -0.3, + tick: -0.35, + text: -0.4, + // Non-sense to use rule here + rule: -2.5 + }; + util_1.forEach(noOccludedQxBinQ, function (score, mark) { + var feature = featurize(xType, yType, false, mark); + SCORE[feature] = score; + // also do the inverse + var feature2 = featurize(yType, xType, false, mark); + SCORE[feature2] = score; + }); + }); + }); + [type_1.TIMEUNIT_T].forEach(function (xType) { + [type_1.TIMEUNIT_T].forEach(function (yType) { + // has occlusion + var ttMark = { + point: 0, + rect: -0.1, + text: -0.5, + tick: -1, + bar: -2, + line: -2, + area: -2, + rule: -2.5 + }; + // No difference between has occlusion and no occlusion + // as most of the time, it will be the occluded case. + util_1.forEach(ttMark, function (score, mark) { + var feature = featurize(xType, yType, true, mark); + SCORE[feature] = score; + }); + util_1.forEach(ttMark, function (score, mark) { + var feature = featurize(xType, yType, false, mark); + SCORE[feature] = score; + }); + }); + DISCRETE_OR_NONE.forEach(function (yType) { + // has occlusion + var tdMark = { + tick: 0, + point: -0.2, + text: -0.5, + rect: -1, + bar: -2, + line: -2, + area: -2, + rule: -2.5 + }; + // No difference between has occlusion and no occlusion + // as most of the time, it will be the occluded case. + util_1.forEach(tdMark, function (score, mark) { + var feature = featurize(xType, yType, true, mark); + SCORE[feature] = score; + }); + util_1.forEach(tdMark, function (score, mark) { + var feature = featurize(yType, xType, true, mark); + SCORE[feature] = score; + }); + util_1.forEach(tdMark, function (score, mark) { + var feature = featurize(xType, yType, false, mark); + SCORE[feature] = score; + }); + util_1.forEach(tdMark, function (score, mark) { + var feature = featurize(yType, xType, false, mark); + SCORE[feature] = score; + }); + }); + }); + // DxD + DISCRETE_OR_NONE.forEach(function (xType) { + DISCRETE_OR_NONE.forEach(function (yType) { + // has occlusion + var ddMark = { + point: 0, + rect: 0, + text: -0.1, + tick: -1, + bar: -2, + line: -2, + area: -2, + rule: -2.5 + }; + // No difference between has occlusion and no occlusion + util_1.forEach(ddMark, function (score, mark) { + var feature = featurize(xType, yType, true, mark); + SCORE[feature] = score; + }); + util_1.forEach(ddMark, function (score, mark) { + var feature = featurize(xType, yType, false, mark); + SCORE[feature] = score; + }); + }); + }); + return SCORE; +} + +},{"../../util":38,"./base":25,"./type":31,"vega-lite/build/src/channel":57,"vega-lite/build/src/mark":64}],30:[function(require,module,exports){ +"use strict"; +var __extends = (this && this.__extends) || (function () { + var extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +Object.defineProperty(exports, "__esModule", { value: true }); +var base_1 = require("./base"); +/** + * Effectivenss score that penalize size for bar and tick + */ +var SizeChannelScorer = (function (_super) { + __extends(SizeChannelScorer, _super); + function SizeChannelScorer() { + return _super.call(this, 'SizeChannel') || this; + } + SizeChannelScorer.prototype.initScore = function () { + return { + bar_size: -2, + tick_size: -2 + }; + }; + SizeChannelScorer.prototype.getScore = function (specM, _, __) { + var _this = this; + var mark = specM.getMark(); + return specM.getEncodings().reduce(function (featureScores, encQ) { + var feature = mark + '_' + encQ.channel; + var featureScore = _this.getFeatureScore(feature); + if (featureScore) { + featureScores.push(featureScore); + } + return featureScores; + }, []); + }; + return SizeChannelScorer; +}(base_1.Scorer)); +exports.SizeChannelScorer = SizeChannelScorer; + +},{"./base":25}],31:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var scale_1 = require("vega-lite/build/src/scale"); +var type_1 = require("vega-lite/build/src/type"); +var encoding_1 = require("../../query/encoding"); +var expandedtype_1 = require("../../query/expandedtype"); +/** + * Finer grained data types that takes binning and timeUnit into account. + */ +var ExtendedType; +(function (ExtendedType) { + ExtendedType[ExtendedType["Q"] = type_1.Type.QUANTITATIVE] = "Q"; + ExtendedType[ExtendedType["BIN_Q"] = 'bin_' + type_1.Type.QUANTITATIVE] = "BIN_Q"; + ExtendedType[ExtendedType["T"] = type_1.Type.TEMPORAL] = "T"; + /** + * Time Unit Temporal Field with time scale. + */ + ExtendedType[ExtendedType["TIMEUNIT_T"] = 'timeUnit_time'] = "TIMEUNIT_T"; + /** + * Time Unit Temporal Field with ordinal scale. + */ + ExtendedType[ExtendedType["TIMEUNIT_O"] = 'timeUnit_' + type_1.Type.ORDINAL] = "TIMEUNIT_O"; + ExtendedType[ExtendedType["O"] = type_1.Type.ORDINAL] = "O"; + ExtendedType[ExtendedType["N"] = type_1.Type.NOMINAL] = "N"; + ExtendedType[ExtendedType["K"] = expandedtype_1.ExpandedType.KEY] = "K"; + ExtendedType[ExtendedType["NONE"] = '-'] = "NONE"; +})(ExtendedType = exports.ExtendedType || (exports.ExtendedType = {})); +exports.Q = ExtendedType.Q; +exports.BIN_Q = ExtendedType.BIN_Q; +exports.T = ExtendedType.T; +exports.TIMEUNIT_T = ExtendedType.TIMEUNIT_T; +exports.TIMEUNIT_O = ExtendedType.TIMEUNIT_O; +exports.O = ExtendedType.O; +exports.N = ExtendedType.N; +exports.K = ExtendedType.K; +exports.NONE = ExtendedType.NONE; +function getExtendedType(fieldQ) { + if (fieldQ.bin) { + return ExtendedType.BIN_Q; + } + else if (fieldQ.timeUnit) { + var sType = encoding_1.scaleType(fieldQ); + return scale_1.hasDiscreteDomain(sType) ? ExtendedType.TIMEUNIT_O : ExtendedType.TIMEUNIT_T; + } + return fieldQ.type; +} +exports.getExtendedType = getExtendedType; + +},{"../../query/encoding":15,"../../query/expandedtype":16,"vega-lite/build/src/scale":65,"vega-lite/build/src/type":67}],32:[function(require,module,exports){ +"use strict"; +var __extends = (this && this.__extends) || (function () { + var extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +Object.defineProperty(exports, "__esModule", { value: true }); +var shorthand_1 = require("../../query/shorthand"); +var util_1 = require("../../util"); +var type_1 = require("./type"); +var base_1 = require("./base"); +exports.TERRIBLE = -10; +/** + * Effectiveness score for relationship between + * Field Type (with Bin and TimeUnit) and Channel Score (Cleveland / Mackinlay based) + */ +var TypeChannelScorer = (function (_super) { + __extends(TypeChannelScorer, _super); + function TypeChannelScorer() { + return _super.call(this, 'TypeChannel') || this; + } + TypeChannelScorer.prototype.initScore = function () { + var _this = this; + var SCORE = {}; + // Continuous Quantitative / Temporal Fields + var CONTINUOUS_TYPE_CHANNEL_SCORE = { + x: 0, + y: 0, + size: -0.575, + color: -0.725, + text: -2, + opacity: -3, + shape: exports.TERRIBLE, + row: exports.TERRIBLE, + column: exports.TERRIBLE, + detail: 2 * exports.TERRIBLE + }; + [type_1.Q, type_1.T, type_1.TIMEUNIT_T].forEach(function (type) { + util_1.keys(CONTINUOUS_TYPE_CHANNEL_SCORE).forEach(function (channel) { + SCORE[_this.featurize(type, channel)] = CONTINUOUS_TYPE_CHANNEL_SCORE[channel]; + }); + }); + // Discretized Quantitative / Temporal Fields / Ordinal + var ORDERED_TYPE_CHANNEL_SCORE = util_1.extend({}, CONTINUOUS_TYPE_CHANNEL_SCORE, { + row: -0.75, + column: -0.75, + shape: -3.1, + text: -3.2, + detail: -4 + }); + [type_1.BIN_Q, type_1.TIMEUNIT_O, type_1.O].forEach(function (type) { + util_1.keys(ORDERED_TYPE_CHANNEL_SCORE).forEach(function (channel) { + SCORE[_this.featurize(type, channel)] = ORDERED_TYPE_CHANNEL_SCORE[channel]; + }); + }); + var NOMINAL_TYPE_CHANNEL_SCORE = { + x: 0, + y: 0, + color: -0.6, + shape: -0.65, + row: -0.7, + column: -0.7, + text: -0.8, + detail: -2, + size: -3, + opacity: -3.1, + }; + util_1.keys(NOMINAL_TYPE_CHANNEL_SCORE).forEach(function (channel) { + SCORE[_this.featurize(type_1.N, channel)] = NOMINAL_TYPE_CHANNEL_SCORE[channel]; + }); + return SCORE; + }; + TypeChannelScorer.prototype.featurize = function (type, channel) { + return type + '_' + channel; + }; + TypeChannelScorer.prototype.getScore = function (specM, schema, opt) { + var _this = this; + var encodingQueryByField = specM.getEncodings().reduce(function (m, encQ) { + var fieldKey = shorthand_1.fieldDef(encQ); + (m[fieldKey] = m[fieldKey] || []).push(encQ); + return m; + }, {}); + var features = []; + util_1.forEach(encodingQueryByField, function (encQs) { + var bestFieldFeature = encQs.reduce(function (best, encQ) { + var type = type_1.getExtendedType(encQ); + var feature = _this.featurize(type, encQ.channel); + var featureScore = _this.getFeatureScore(feature); + if (best === null || featureScore.score > best.score) { + return featureScore; + } + return best; + }, null); + features.push(bestFieldFeature); + // TODO: add plus for over-encoding of one field + }); + return features; + }; + return TypeChannelScorer; +}(base_1.Scorer)); +exports.TypeChannelScorer = TypeChannelScorer; + +},{"../../query/shorthand":20,"../../util":38,"./base":25,"./type":31}],33:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var encoding_1 = require("../query/encoding"); +exports.name = 'fieldOrder'; +/** + * Return ranking score based on indices of encoded fields in the schema. + * If there are multiple fields, prioritize field on the lower indices of encodings. + * + * For example, to compare two specs with two encodings each, + * first we compare the field on the 0-th index + * and only compare the field on the 1-th index only if the fields on the 0-th index are the same. + */ +function score(specM, schema, _) { + var fieldWildcardIndices = specM.wildcardIndex.encodingIndicesByProperty.get('field'); + if (!fieldWildcardIndices) { + return { + score: 0, + features: [] + }; + } + var encodings = specM.specQuery.encodings; + var numFields = schema.fieldSchemas.length; + var features = []; + var totalScore = 0, base = 1; + for (var i = fieldWildcardIndices.length - 1; i >= 0; i--) { + var index = fieldWildcardIndices[i]; + var encoding = encodings[index]; + // Skip ValueQuery as we only care about order of fields. + var field = void 0; + if (encoding_1.isFieldQuery(encoding)) { + field = encoding.field; + } + else { + continue; + } + var fieldWildcard = specM.wildcardIndex.encodings[index].get('field'); + var fieldIndex = schema.fieldSchema(field).index; + // reverse order field with lower index should get higher score and come first + var score_1 = -fieldIndex * base; + totalScore += score_1; + features.push({ + score: score_1, + type: 'fieldOrder', + feature: "field " + fieldWildcard.name + " is " + field + " (#" + fieldIndex + " in the schema)" + }); + base *= numFields; + } + return { + score: totalScore, + features: features + }; +} +exports.score = score; + +},{"../query/encoding":15}],34:[function(require,module,exports){ +"use strict"; +function __export(m) { + for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; +} +Object.defineProperty(exports, "__esModule", { value: true }); +var model_1 = require("../model"); +var effectiveness_1 = require("./effectiveness"); +__export(require("./effectiveness")); +exports.aggregation = require("./aggregation"); +exports.fieldOrder = require("./fieldorder"); +/** + * Registry for all encoding ranking functions + */ +var rankingRegistry = {}; +/** + * Add an ordering function to the registry. + */ +function register(name, keyFn) { + rankingRegistry[name] = keyFn; +} +exports.register = register; +function get(name) { + return rankingRegistry[name]; +} +exports.get = get; +function rank(group, query, schema, level) { + if (!query.nest || level === query.nest.length) { + if (query.orderBy || query.chooseBy) { + group.items.sort(comparatorFactory(query.orderBy || query.chooseBy, schema, query.config)); + if (query.chooseBy) { + if (group.items.length > 0) { + // for chooseBy -- only keep the top-item + group.items.splice(1); + } + } + } + } + else { + // sort lower-level nodes first because our ranking takes top-item in the subgroup + group.items.forEach(function (subgroup) { + rank(subgroup, query, schema, level + 1); + }); + if (query.nest[level].orderGroupBy) { + group.items.sort(groupComparatorFactory(query.nest[level].orderGroupBy, schema, query.config)); + } + } + return group; +} +exports.rank = rank; +function comparatorFactory(name, schema, opt) { + return function (m1, m2) { + if (name instanceof Array) { + return getScoreDifference(name, m1, m2, schema, opt); + } + else { + return getScoreDifference([name], m1, m2, schema, opt); + } + }; +} +exports.comparatorFactory = comparatorFactory; +function groupComparatorFactory(name, schema, opt) { + return function (g1, g2) { + var m1 = model_1.getTopSpecQueryItem(g1); + var m2 = model_1.getTopSpecQueryItem(g2); + if (name instanceof Array) { + return getScoreDifference(name, m1, m2, schema, opt); + } + else { + return getScoreDifference([name], m1, m2, schema, opt); + } + }; +} +exports.groupComparatorFactory = groupComparatorFactory; +function getScoreDifference(name, m1, m2, schema, opt) { + for (var _i = 0, name_1 = name; _i < name_1.length; _i++) { + var rankingName = name_1[_i]; + var scoreDifference = getScore(m2, rankingName, schema, opt).score - getScore(m1, rankingName, schema, opt).score; + if (scoreDifference !== 0) { + return scoreDifference; + } + } + return 0; +} +function getScore(model, rankingName, schema, opt) { + if (model.getRankingScore(rankingName) !== undefined) { + return model.getRankingScore(rankingName); + } + var fn = get(rankingName); + var score = fn(model, schema, opt); + model.setRankingScore(rankingName, score); + return score; +} +exports.getScore = getScore; +exports.EFFECTIVENESS = 'effectiveness'; +register(exports.EFFECTIVENESS, effectiveness_1.effectiveness); +register(exports.aggregation.name, exports.aggregation.score); +register(exports.fieldOrder.name, exports.fieldOrder.score); + +},{"../model":11,"./aggregation":23,"./effectiveness":28,"./fieldorder":33}],35:[function(require,module,exports){ +"use strict"; +var __assign = (this && this.__assign) || Object.assign || function(t) { + for (var s, i = 1, n = arguments.length; i < n; i++) { + s = arguments[i]; + for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) + t[p] = s[p]; + } + return t; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +var config_1 = require("./config"); +var generate_1 = require("./generate"); +var nest_1 = require("./nest"); +var normalize_1 = require("./query/normalize"); +var ranking_1 = require("./ranking/ranking"); +function recommend(q, schema, config) { + // 1. Normalize non-nested `groupBy` to always have `groupBy` inside `nest` + // and merge config with the following precedence + // query.config > config > DEFAULT_QUERY_CONFIG + q = __assign({}, normalize_1.normalize(q), { config: __assign({}, config_1.DEFAULT_QUERY_CONFIG, config, q.config) }); + // 2. Generate + var answerSet = generate_1.generate(q.spec, schema, q.config); + var nestedAnswerSet = nest_1.nest(answerSet, q.nest); + var result = ranking_1.rank(nestedAnswerSet, q, schema, 0); + return { + query: q, + result: result + }; +} +exports.recommend = recommend; + +},{"./config":1,"./generate":10,"./nest":12,"./query/normalize":19,"./ranking/ranking":34}],36:[function(require,module,exports){ +"use strict"; +var __assign = (this && this.__assign) || Object.assign || function(t) { + for (var s, i = 1, n = arguments.length; i < n; i++) { + s = arguments[i]; + for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) + t[p] = s[p]; + } + return t; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +var type_1 = require("vega-lite/build/src/type"); +var bin_1 = require("vega-lite/build/src/bin"); +var timeunit_1 = require("vega-lite/build/src/timeunit"); +var stats_1 = require("datalib/src/stats"); +var type_2 = require("datalib/src/import/type"); +var dlBin = require("datalib/src/bins/bins"); +var encoding_1 = require("./query/encoding"); +var expandedtype_1 = require("./query/expandedtype"); +var config_1 = require("./config"); +var util_1 = require("./util"); +/** + * Build a Schema object. + * + * @param data - a set of raw data in the same format that Vega-Lite / Vega takes + * Basically, it's an array in the form of: + * + * [ + * {a: 1, b:2}, + * {a: 2, b:3}, + * ... + * ] + * + * @return a Schema object + */ +function build(data, tableSchema, opt) { + if (tableSchema === void 0) { tableSchema = { fields: [] }; } + if (opt === void 0) { opt = {}; } + opt = util_1.extend({}, config_1.DEFAULT_QUERY_CONFIG, opt); + // create profiles for each variable + var summaries = stats_1.summary(data); + var types = type_2.inferAll(data); // inferAll does stronger type inference than summary + var tableSchemaFieldIndex = tableSchema.fields.reduce(function (m, field) { + m[field.name] = field; + return m; + }, {}); + var fieldSchemas = summaries.map(function (fieldProfile, index) { + var name = fieldProfile.field; + // In Table schema, 'date' doesn't include time so use 'datetime' + var type = types[name] === 'date' ? PrimitiveType.DATETIME : types[name]; + var distinct = fieldProfile.distinct; + var vlType; + if (type === PrimitiveType.NUMBER) { + vlType = type_1.Type.QUANTITATIVE; + } + else if (type === PrimitiveType.INTEGER) { + // use ordinal or nominal when cardinality of integer type is relatively low and the distinct values are less than an amount specified in options + if ((distinct < opt.numberNominalLimit) && (distinct / fieldProfile.count < opt.numberNominalProportion)) { + vlType = type_1.Type.NOMINAL; + } + else { + vlType = type_1.Type.QUANTITATIVE; + } + } + else if (type === PrimitiveType.DATETIME) { + vlType = type_1.Type.TEMPORAL; + // need to get correct min/max of date data because datalib's summary method does not + // calculate this correctly for date types. + fieldProfile.min = new Date(data[0][name]); + fieldProfile.max = new Date(data[0][name]); + for (var _i = 0, data_1 = data; _i < data_1.length; _i++) { + var dataEntry = data_1[_i]; + var time = new Date(dataEntry[name]).getTime(); + if (time < fieldProfile.min.getTime()) { + fieldProfile.min = new Date(time); + } + if (time > fieldProfile.max.getTime()) { + fieldProfile.max = new Date(time); + } + } + } + else { + vlType = type_1.Type.NOMINAL; + } + if (vlType === type_1.Type.NOMINAL + && distinct / fieldProfile.count > opt.minPercentUniqueForKey + && fieldProfile.count > opt.minCardinalityForKey) { + vlType = expandedtype_1.ExpandedType.KEY; + } + var fieldSchema = { + name: name, + // Need to keep original index for re-exporting TableSchema + originalIndex: index, + vlType: vlType, + type: type, + stats: fieldProfile, + timeStats: {}, + binStats: {} + }; + // extend field schema with table schema field - if present + var orgFieldSchema = tableSchemaFieldIndex[fieldSchema.name]; + fieldSchema = util_1.extend(fieldSchema, orgFieldSchema); + return fieldSchema; + }); + // calculate preset bins for quantitative and temporal data + for (var _i = 0, fieldSchemas_1 = fieldSchemas; _i < fieldSchemas_1.length; _i++) { + var fieldSchema = fieldSchemas_1[_i]; + if (fieldSchema.vlType === type_1.Type.QUANTITATIVE) { + for (var _a = 0, _b = opt.enum.binProps.maxbins; _a < _b.length; _a++) { + var maxbins = _b[_a]; + fieldSchema.binStats[maxbins] = binSummary(maxbins, fieldSchema.stats); + } + } + else if (fieldSchema.vlType === type_1.Type.TEMPORAL) { + for (var _c = 0, _d = opt.enum.timeUnit; _c < _d.length; _c++) { + var unit = _d[_c]; + if (unit !== undefined) { + fieldSchema.timeStats[unit] = timeSummary(unit, fieldSchema.stats); + } + } + } + } + var derivedTableSchema = __assign({}, tableSchema, { fields: fieldSchemas }); + return new Schema(derivedTableSchema); +} +exports.build = build; +// order the field schema when we construct a new Schema +// this orders the fields in the UI +var order = { + 'nominal': 0, + 'key': 1, + 'ordinal': 2, + 'temporal': 3, + 'quantitative': 4 +}; +var Schema = (function () { + function Schema(tableSchema) { + this._tableSchema = tableSchema; + tableSchema.fields.sort(function (a, b) { + // first order by vlType: nominal < temporal < quantitative < ordinal + if (order[a.vlType] < order[b.vlType]) { + return -1; + } + else if (order[a.vlType] > order[b.vlType]) { + return 1; + } + else { + // then order by field (alphabetically) + return a.name.localeCompare(b.name); + } + }); + // Add index for sorting + tableSchema.fields.forEach(function (fieldSchema, index) { return fieldSchema.index = index; }); + this._fieldSchemaIndex = tableSchema.fields.reduce(function (m, fieldSchema) { + m[fieldSchema.name] = fieldSchema; + return m; + }, {}); + } + /** @return a list of the field names (for enumerating). */ + Schema.prototype.fieldNames = function () { + return this._tableSchema.fields.map(function (fieldSchema) { return fieldSchema.name; }); + }; + Object.defineProperty(Schema.prototype, "fieldSchemas", { + /** @return a list of FieldSchemas */ + get: function () { + return this._tableSchema.fields; + }, + enumerable: true, + configurable: true + }); + Schema.prototype.fieldSchema = function (fieldName) { + return this._fieldSchemaIndex[fieldName]; + }; + Schema.prototype.tableSchema = function () { + // the fieldschemas are re-arranged + // but this is not allowed in table schema. + // so we will re-order based on original index. + var tableSchema = util_1.duplicate(this._tableSchema); + tableSchema.fields.sort(function (a, b) { return a.originalIndex - b.originalIndex; }); + return tableSchema; + }; + /** + * @return primitive type of the field if exist, otherwise return null + */ + Schema.prototype.primitiveType = function (fieldName) { + return this._fieldSchemaIndex[fieldName] ? this._fieldSchemaIndex[fieldName].type : null; + }; + /** + * @return vlType of measturement of the field if exist, otherwise return null + */ + Schema.prototype.vlType = function (fieldName) { + return this._fieldSchemaIndex[fieldName] ? this._fieldSchemaIndex[fieldName].vlType : null; + }; + /** @return cardinality of the field associated with encQ, null if it doesn't exist. + * @param augmentTimeUnitDomain - TimeUnit field domains will not be augmented if explicitly set to false. + */ + Schema.prototype.cardinality = function (fieldQ, augmentTimeUnitDomain, excludeInvalid) { + if (augmentTimeUnitDomain === void 0) { augmentTimeUnitDomain = true; } + if (excludeInvalid === void 0) { excludeInvalid = false; } + var fieldSchema = this._fieldSchemaIndex[fieldQ.field]; + if (fieldQ.aggregate || (encoding_1.isAutoCountQuery(fieldQ) && fieldQ.autoCount)) { + return 1; + } + else if (fieldQ.bin) { + // encQ.bin will either be a boolean or a BinQuery + var bin = void 0; + if (typeof fieldQ.bin === 'boolean') { + // autoMaxBins defaults to 10 if channel is Wildcard + bin = { + maxbins: bin_1.autoMaxBins(fieldQ.channel) + }; + } + else { + bin = fieldQ.bin; + } + var maxbins = bin.maxbins; + if (!fieldSchema.binStats[maxbins]) { + // need to calculate + fieldSchema.binStats[maxbins] = binSummary(maxbins, fieldSchema.stats); + } + // don't need to worry about excludeInvalid here because invalid values don't affect linearly binned field's cardinality + return fieldSchema.binStats[maxbins].distinct; + } + else if (fieldQ.timeUnit) { + if (augmentTimeUnitDomain) { + switch (fieldQ.timeUnit) { + // TODO: this should not always be the case once Vega-Lite supports turning off domain augmenting (VL issue #1385) + case timeunit_1.TimeUnit.SECONDS: return 60; + case timeunit_1.TimeUnit.MINUTES: return 60; + case timeunit_1.TimeUnit.HOURS: return 24; + case timeunit_1.TimeUnit.DAY: return 7; + case timeunit_1.TimeUnit.DATE: return 31; + case timeunit_1.TimeUnit.MONTH: return 12; + case timeunit_1.TimeUnit.QUARTER: return 4; + case timeunit_1.TimeUnit.MILLISECONDS: return 1000; + } + } + var unit = fieldQ.timeUnit; + var timeStats = fieldSchema.timeStats; + // if the cardinality for the timeUnit is not cached, calculate it + if (!timeStats[unit]) { + timeStats[unit] = timeSummary(fieldQ.timeUnit, fieldSchema.stats); + } + if (excludeInvalid) { + return timeStats[unit].distinct - invalidCount(timeStats[unit].unique, ['Invalid Date', null]); + } + else { + return timeStats[unit].distinct; + } + } + else { + if (fieldSchema) { + if (excludeInvalid) { + return fieldSchema.stats.distinct - invalidCount(fieldSchema.stats.unique, [NaN, null]); + } + else { + return fieldSchema.stats.distinct; + } + } + else { + return null; + } + } + }; + /** + * Given an EncodingQuery with a timeUnit, returns true if the date field + * has multiple distinct values for all parts of the timeUnit. Returns undefined + * if the timeUnit is undefined. + * i.e. + * ('yearmonth', [Jan 1 2000, Feb 2 2000] returns false) + * ('yearmonth', [Jan 1 2000, Feb 2 2001] returns true) + */ + Schema.prototype.timeUnitHasVariation = function (fieldQ) { + if (!fieldQ.timeUnit) { + return; + } + // if there is no variation in `date`, there should not be variation in `day` + if (fieldQ.timeUnit === timeunit_1.TimeUnit.DAY) { + var dateEncQ = util_1.extend({}, fieldQ, { timeUnit: timeunit_1.TimeUnit.DATE }); + if (this.cardinality(dateEncQ, false, true) <= 1) { + return false; + } + } + var fullTimeUnit = fieldQ.timeUnit; + for (var _i = 0, SINGLE_TIMEUNITS_1 = timeunit_1.SINGLE_TIMEUNITS; _i < SINGLE_TIMEUNITS_1.length; _i++) { + var singleUnit = SINGLE_TIMEUNITS_1[_i]; + if (timeunit_1.containsTimeUnit(fullTimeUnit, singleUnit)) { + // Create a clone of encQ, but with singleTimeUnit + var singleUnitEncQ = util_1.extend({}, fieldQ, { timeUnit: singleUnit }); + if (this.cardinality(singleUnitEncQ, false, true) <= 1) { + return false; + } + } + } + return true; + }; + Schema.prototype.domain = function (fieldQueryParts) { + // TODO: differentiate for field with bin / timeUnit + var fieldSchema = this._fieldSchemaIndex[fieldQueryParts.field]; + var domain = util_1.keys(fieldSchema.stats.unique); + if (fieldSchema.vlType === type_1.Type.QUANTITATIVE) { + // return [min, max], coerced into number types + return [+fieldSchema.stats.min, +fieldSchema.stats.max]; + } + else if (fieldSchema.type === PrimitiveType.DATETIME) { + // return [min, max] dates + return [fieldSchema.stats.min, fieldSchema.stats.max]; + } + else if (fieldSchema.type === PrimitiveType.INTEGER || + fieldSchema.type === PrimitiveType.NUMBER) { + // coerce non-quantitative numerical data into number type + domain = domain.map(function (x) { return +x; }); + return domain.sort(util_1.cmp); + } + else if ((fieldSchema.vlType === type_1.Type.ORDINAL) && fieldSchema.ordinalDomain) { + return fieldSchema.ordinalDomain; + } + return domain.map(function (x) { + // Convert 'null' to null as it is encoded similarly in datalib. + // This is wrong when it is a string 'null' but that rarely happens. + return x === 'null' ? null : x; + }).sort(util_1.cmp); + }; + /** + * @return a Summary corresponding to the field of the given EncodingQuery + */ + Schema.prototype.stats = function (fieldQ) { + // TODO: differentiate for field with bin / timeUnit vs without + var fieldSchema = this._fieldSchemaIndex[fieldQ.field]; + return fieldSchema ? fieldSchema.stats : null; + }; + return Schema; +}()); +exports.Schema = Schema; +/** + * @return a summary of the binning scheme determined from the given max number of bins + */ +function binSummary(maxbins, summary) { + var bin = dlBin({ + min: summary.min, + max: summary.max, + maxbins: maxbins + }); + // start with summary, pre-binning + var result = util_1.extend({}, summary); + result.unique = binUnique(bin, summary.unique); + result.distinct = (bin.stop - bin.start) / bin.step; + result.min = bin.start; + result.max = bin.stop; + return result; +} +/** @return a modified version of the passed summary with unique and distinct set according to the timeunit. + * Maps 'null' (string) keys to the null value and invalid dates to 'Invalid Date' in the unique dictionary. + */ +function timeSummary(timeunit, summary) { + var result = util_1.extend({}, summary); + var unique = {}; + util_1.keys(summary.unique).forEach(function (dateString) { + // don't convert null value because the Date constructor will actually convert it to a date + var date = (dateString === 'null') ? null : new Date(dateString); + // at this point, `date` is either the null value, a valid Date object, or "Invalid Date" which is a Date + var key; + if (date === null) { + key = null; + } + else if (isNaN(date.getTime())) { + key = 'Invalid Date'; + } + else { + key = ((timeunit === timeunit_1.TimeUnit.DAY) ? date.getDay() : timeunit_1.convert(timeunit, date)).toString(); + } + unique[key] = (unique[key] || 0) + summary.unique[dateString]; + }); + result.unique = unique; + result.distinct = util_1.keys(unique).length; + return result; +} +/** + * @return a new unique object based off of the old unique count and a binning scheme + */ +function binUnique(bin, oldUnique) { + var newUnique = {}; + for (var value in oldUnique) { + var bucket = void 0; + if (value === null) { + bucket = null; + } + else if (isNaN(Number(value))) { + bucket = NaN; + } + else { + bucket = bin.value(Number(value)); + } + newUnique[bucket] = (newUnique[bucket] || 0) + oldUnique[value]; + } + return newUnique; +} +/** @return the number of items in list that occur as keys of unique */ +function invalidCount(unique, list) { + return list.reduce(function (prev, cur) { + return unique[cur] ? prev + 1 : prev; + }, 0); +} +var PrimitiveType; +(function (PrimitiveType) { + PrimitiveType[PrimitiveType["STRING"] = 'string'] = "STRING"; + PrimitiveType[PrimitiveType["NUMBER"] = 'number'] = "NUMBER"; + PrimitiveType[PrimitiveType["INTEGER"] = 'integer'] = "INTEGER"; + PrimitiveType[PrimitiveType["BOOLEAN"] = 'boolean'] = "BOOLEAN"; + PrimitiveType[PrimitiveType["DATETIME"] = 'datetime'] = "DATETIME"; +})(PrimitiveType = exports.PrimitiveType || (exports.PrimitiveType = {})); + +},{"./config":1,"./query/encoding":15,"./query/expandedtype":16,"./util":38,"datalib/src/bins/bins":43,"datalib/src/import/type":45,"datalib/src/stats":46,"vega-lite/build/src/bin":56,"vega-lite/build/src/timeunit":66,"vega-lite/build/src/type":67}],37:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var channel_1 = require("vega-lite/build/src/channel"); +var scale_1 = require("vega-lite/build/src/scale"); +var type_1 = require("vega-lite/build/src/type"); +var encoding_1 = require("./query/encoding"); +var expandedtype_1 = require("./query/expandedtype"); +function stylize(answerSet, schema, opt) { + var encQIndex = {}; + answerSet = answerSet.map(function (specM) { + if (opt.smallRangeStepForHighCardinalityOrFacet) { + specM = smallRangeStepForHighCardinalityOrFacet(specM, schema, encQIndex, opt); + } + if (opt.nominalColorScaleForHighCardinality) { + specM = nominalColorScaleForHighCardinality(specM, schema, encQIndex, opt); + } + if (opt.xAxisOnTopForHighYCardinalityWithoutColumn) { + specM = xAxisOnTopForHighYCardinalityWithoutColumn(specM, schema, encQIndex, opt); + } + return specM; + }); + return answerSet; +} +exports.stylize = stylize; +function smallRangeStepForHighCardinalityOrFacet(specM, schema, encQIndex, opt) { + [channel_1.Channel.ROW, channel_1.Channel.Y, channel_1.Channel.COLUMN, channel_1.Channel.X].forEach(function (channel) { + encQIndex[channel] = specM.getEncodingQueryByChannel(channel); + }); + var yEncQ = encQIndex[channel_1.Channel.Y]; + if (yEncQ !== undefined && encoding_1.isFieldQuery(yEncQ)) { + if (encQIndex[channel_1.Channel.ROW] || + schema.cardinality(yEncQ) > opt.smallRangeStepForHighCardinalityOrFacet.maxCardinality) { + // We check for undefined rather than + // yEncQ.scale = yEncQ.scale || {} to cover the case where + // yEncQ.scale has been set to false/null. + // This prevents us from incorrectly overriding scale and + // assigning a rangeStep when scale is set to false. + if (yEncQ.scale === undefined) { + yEncQ.scale = {}; + } + // We do not want to assign a rangeStep if scale is set to false + // and we only apply this if the scale is (or can be) an ordinal scale. + var yScaleType = encoding_1.scaleType(yEncQ); + if (yEncQ.scale && (yScaleType === undefined || scale_1.hasDiscreteDomain(yScaleType))) { + if (!yEncQ.scale.rangeStep) { + yEncQ.scale.rangeStep = 12; + } + } + } + } + var xEncQ = encQIndex[channel_1.Channel.X]; + if (encoding_1.isFieldQuery(xEncQ)) { + if (encQIndex[channel_1.Channel.COLUMN] || + schema.cardinality(xEncQ) > opt.smallRangeStepForHighCardinalityOrFacet.maxCardinality) { + // Just like y, we don't want to do this if scale is null/false + if (xEncQ.scale === undefined) { + xEncQ.scale = {}; + } + // We do not want to assign a rangeStep if scale is set to false + // and we only apply this if the scale is (or can be) an ordinal scale. + var xScaleType = encoding_1.scaleType(xEncQ); + if (xEncQ.scale && (xScaleType === undefined || scale_1.hasDiscreteDomain(xScaleType))) { + if (!xEncQ.scale.rangeStep) { + xEncQ.scale.rangeStep = 12; + } + } + } + } + return specM; +} +exports.smallRangeStepForHighCardinalityOrFacet = smallRangeStepForHighCardinalityOrFacet; +function nominalColorScaleForHighCardinality(specM, schema, encQIndex, opt) { + encQIndex[channel_1.Channel.COLOR] = specM.getEncodingQueryByChannel(channel_1.Channel.COLOR); + var colorEncQ = encQIndex[channel_1.Channel.COLOR]; + if (encoding_1.isFieldQuery(colorEncQ) && (colorEncQ !== undefined) && (colorEncQ.type === type_1.Type.NOMINAL || colorEncQ.type === expandedtype_1.ExpandedType.KEY) && + (schema.cardinality(colorEncQ) > opt.nominalColorScaleForHighCardinality.maxCardinality)) { + if (colorEncQ.scale === undefined) { + colorEncQ.scale = {}; + } + if (colorEncQ.scale) { + if (!colorEncQ.scale.range) { + colorEncQ.scale.range = opt.nominalColorScaleForHighCardinality.palette; + } + } + } + return specM; +} +exports.nominalColorScaleForHighCardinality = nominalColorScaleForHighCardinality; +function xAxisOnTopForHighYCardinalityWithoutColumn(specM, schema, encQIndex, opt) { + [channel_1.Channel.COLUMN, channel_1.Channel.X, channel_1.Channel.Y].forEach(function (channel) { + encQIndex[channel] = specM.getEncodingQueryByChannel(channel); + }); + if (encQIndex[channel_1.Channel.COLUMN] === undefined) { + var xEncQ = encQIndex[channel_1.Channel.X]; + var yEncQ = encQIndex[channel_1.Channel.Y]; + if (encoding_1.isFieldQuery(xEncQ) && encoding_1.isFieldQuery(yEncQ) && yEncQ !== undefined && yEncQ.field && scale_1.hasDiscreteDomain(encoding_1.scaleType(yEncQ))) { + if (xEncQ !== undefined) { + if (schema.cardinality(yEncQ) > opt.xAxisOnTopForHighYCardinalityWithoutColumn.maxCardinality) { + if (xEncQ.axis === undefined) { + xEncQ.axis = {}; + } + if (xEncQ.axis && !xEncQ.axis.orient) { + xEncQ.axis.orient = 'top'; + } + } + } + } + } + return specM; +} +exports.xAxisOnTopForHighYCardinalityWithoutColumn = xAxisOnTopForHighYCardinalityWithoutColumn; + +},{"./query/encoding":15,"./query/expandedtype":16,"vega-lite/build/src/channel":57,"vega-lite/build/src/scale":65,"vega-lite/build/src/type":67}],38:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var util_1 = require("datalib/src/util"); +var util_2 = require("datalib/src/util"); +exports.cmp = util_2.cmp; +exports.keys = util_2.keys; +exports.duplicate = util_2.duplicate; +exports.extend = util_2.extend; +exports.isObject = util_2.isObject; +exports.isArray = util_2.isArray; +exports.isBoolean = util_2.isBoolean; +exports.toMap = util_2.toMap; +function contains(array, item) { + return array.indexOf(item) !== -1; +} +exports.contains = contains; +; +function every(arr, f) { + for (var i = 0; i < arr.length; i++) { + if (!f(arr[i], i)) { + return false; + } + } + return true; +} +exports.every = every; +; +function forEach(obj, f, thisArg) { + if (obj.forEach) { + obj.forEach.call(thisArg, f); + } + else { + for (var k in obj) { + f.call(thisArg, obj[k], k, obj); + } + } +} +exports.forEach = forEach; +; +function some(arr, f) { + var i = 0, k; + for (k in arr) { + if (f(arr[k], k, i++)) { + return true; + } + } + return false; +} +exports.some = some; +; +function nestedMap(array, f) { + return array.map(function (a) { + if (util_1.isArray(a)) { + return nestedMap(a, f); + } + return f(a); + }); +} +exports.nestedMap = nestedMap; +/** Returns the array without the elements in item */ +function without(array, excludedItems) { + return array.filter(function (item) { + return !contains(excludedItems, item); + }); +} +exports.without = without; + +},{"datalib/src/util":48}],39:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var property_1 = require("./property"); +var util_1 = require("./util"); +var axis_1 = require("vega-lite/build/src/axis"); +var channel_1 = require("vega-lite/build/src/channel"); +var mark_1 = require("vega-lite/build/src/mark"); +var scale_1 = require("vega-lite/build/src/scale"); +var legend_1 = require("vega-lite/build/src/legend"); +var timeunit_1 = require("vega-lite/build/src/timeunit"); +var type_1 = require("vega-lite/build/src/type"); +exports.SHORT_WILDCARD = '?'; +function isWildcard(prop) { + return isShortWildcard(prop) || isWildcardDef(prop); +} +exports.isWildcard = isWildcard; +function isShortWildcard(prop) { + return prop === exports.SHORT_WILDCARD; +} +exports.isShortWildcard = isShortWildcard; +function isWildcardDef(prop) { + return prop !== undefined && (!!prop.enum || !!prop.name) && !util_1.isArray(prop); +} +exports.isWildcardDef = isWildcardDef; +function initWildcard(prop, defaultName, defaultEnumValues) { + return util_1.extend({}, { + name: defaultName, + enum: defaultEnumValues + }, prop === exports.SHORT_WILDCARD ? {} : prop); +} +exports.initWildcard = initWildcard; +/** + * Initial short names from list of full camelCaseNames. + * For each camelCaseNames, return unique short names based on initial (e.g., `ccn`) + */ +function initNestedPropName(fullNames) { + var index = {}; + var has = {}; + var _loop_1 = function (fullName) { + var initialIndices = [0]; + for (var i = 0; i < fullName.length; i++) { + if (fullName.charAt(i).toUpperCase() === fullName.charAt(i)) { + initialIndices.push(i); + } + } + var shortName = initialIndices.map(function (i) { return fullName.charAt(i); }).join('').toLowerCase(); + if (!has[shortName]) { + index[fullName] = shortName; + has[shortName] = true; + return "continue"; + } + // If duplicate, add last character and try again! + if (initialIndices[initialIndices.length - 1] !== fullName.length - 1) { + shortName = initialIndices.concat([fullName.length - 1]).map(function (i) { return fullName.charAt(i); }).join('').toLowerCase(); + if (!has[shortName]) { + index[fullName] = shortName; + has[shortName] = true; + return "continue"; + } + } + for (var i = 1; !index[fullName]; i++) { + var shortNameWithNo = shortName + '_' + i; + if (!has[shortNameWithNo]) { + index[fullName] = shortNameWithNo; + has[shortNameWithNo] = true; + break; + } + } + }; + for (var _i = 0, fullNames_1 = fullNames; _i < fullNames_1.length; _i++) { + var fullName = fullNames_1[_i]; + _loop_1(fullName); + } + return index; +} +exports.DEFAULT_NAME = { + mark: 'm', + channel: 'c', + aggregate: 'a', + autoCount: '#', + hasFn: 'h', + bin: 'b', + sort: 'so', + scale: 's', + axis: 'ax', + legend: 'l', + timeUnit: 'tu', + field: 'f', + type: 't', + binProps: { + maxbins: 'mb', + min: 'mi', + max: 'ma', + base: 'b', + step: 's', + steps: 'ss', + minstep: 'ms', + divide: 'd' + }, + sortProps: { + field: 'f', + op: 'o', + order: 'or' + }, + scaleProps: initNestedPropName(scale_1.SCALE_PROPERTIES), + axisProps: initNestedPropName(axis_1.AXIS_PROPERTIES), + legendProps: initNestedPropName(legend_1.LEGEND_PROPERTIES) +}; +function getDefaultName(prop) { + if (property_1.isEncodingNestedProp(prop)) { + return exports.DEFAULT_NAME[prop.parent] + '-' + exports.DEFAULT_NAME[prop.parent + 'Props'][prop.child]; + } + if (exports.DEFAULT_NAME[prop]) { + return exports.DEFAULT_NAME[prop]; + } + /* istanbul ignore next */ + throw new Error('Default name undefined for ' + prop); +} +exports.getDefaultName = getDefaultName; +var DEFAULT_BOOLEAN_ENUM = [false, true]; +var DEFAULT_BIN_PROPS_ENUM = { + maxbins: [5, 10, 20], + extent: [undefined], + base: [10], + step: [undefined], + steps: [undefined], + minstep: [undefined], + divide: [[5, 2]] +}; +var DEFAULT_SORT_PROPS = { + field: [undefined], + op: ['min', 'mean'], + order: ['ascending', 'descending'] +}; +var DEFAULT_SCALE_PROPS_ENUM = { + type: [undefined, scale_1.ScaleType.LOG], + domain: [undefined], + exponent: [1, 2], + clamp: DEFAULT_BOOLEAN_ENUM, + nice: DEFAULT_BOOLEAN_ENUM, + reverse: DEFAULT_BOOLEAN_ENUM, + round: DEFAULT_BOOLEAN_ENUM, + zero: DEFAULT_BOOLEAN_ENUM, + padding: [undefined], + paddingInner: [undefined], + paddingOuter: [undefined], + interpolate: [undefined], + range: [undefined], + rangeStep: [17, 21], + scheme: [undefined], +}; +var DEFAULT_AXIS_PROPS_ENUM = { + zindex: [1, 0], + offset: [undefined], + orient: [undefined], + values: [undefined], + domain: DEFAULT_BOOLEAN_ENUM, + grid: DEFAULT_BOOLEAN_ENUM, + format: [undefined], + labels: DEFAULT_BOOLEAN_ENUM, + labelAngle: [undefined], + labelOverlap: [undefined], + labelPadding: [undefined], + maxExtent: [undefined], + minExtent: [undefined], + position: [undefined], + ticks: DEFAULT_BOOLEAN_ENUM, + tickCount: [undefined], + tickExtra: [undefined], + tickSize: [undefined], + title: [undefined], + titleMaxLength: [undefined], + titlePadding: [undefined] +}; +var DEFAULT_LEGEND_PROPS_ENUM = { + entryPadding: [undefined], + orient: ['left', 'right'], + offset: [undefined], + format: [undefined], + values: [undefined], + tickCount: [undefined], + title: [undefined], + type: [undefined], + zindex: [undefined] +}; +// Use FullEnumIndex to make sure we have all properties specified here! +exports.DEFAULT_ENUM_INDEX = { + mark: [mark_1.Mark.POINT, mark_1.Mark.BAR, mark_1.Mark.LINE, mark_1.Mark.AREA, mark_1.Mark.TICK], + channel: [channel_1.X, channel_1.Y, channel_1.ROW, channel_1.COLUMN, channel_1.SIZE, channel_1.COLOR], + aggregate: [undefined, 'mean'], + autoCount: DEFAULT_BOOLEAN_ENUM, + bin: DEFAULT_BOOLEAN_ENUM, + hasFn: DEFAULT_BOOLEAN_ENUM, + timeUnit: [undefined, timeunit_1.TimeUnit.YEAR, timeunit_1.TimeUnit.MONTH, timeunit_1.TimeUnit.MINUTES, timeunit_1.TimeUnit.SECONDS], + field: [undefined], + type: [type_1.Type.NOMINAL, type_1.Type.ORDINAL, type_1.Type.QUANTITATIVE, type_1.Type.TEMPORAL], + sort: ['ascending', 'descending'], + scale: [true], + axis: DEFAULT_BOOLEAN_ENUM, + legend: DEFAULT_BOOLEAN_ENUM, + binProps: DEFAULT_BIN_PROPS_ENUM, + sortProps: DEFAULT_SORT_PROPS, + scaleProps: DEFAULT_SCALE_PROPS_ENUM, + axisProps: DEFAULT_AXIS_PROPS_ENUM, + legendProps: DEFAULT_LEGEND_PROPS_ENUM +}; +// TODO: rename this to getDefaultEnum +function getDefaultEnumValues(prop, schema, opt) { + if (prop === 'field' || (property_1.isEncodingNestedProp(prop) && prop.parent === 'sort' && prop.child === 'field')) { + // For field, by default enumerate all fields + return schema.fieldNames(); + } + var val; + if (property_1.isEncodingNestedProp(prop)) { + val = opt.enum[prop.parent + 'Props'][prop.child]; + } + else { + val = opt.enum[prop]; + } + if (val !== undefined) { + return val; + } + /* istanbul ignore next */ + throw new Error('No default enumValues for ' + JSON.stringify(prop)); +} +exports.getDefaultEnumValues = getDefaultEnumValues; + +},{"./property":13,"./util":38,"vega-lite/build/src/axis":55,"vega-lite/build/src/channel":57,"vega-lite/build/src/legend":61,"vega-lite/build/src/mark":64,"vega-lite/build/src/scale":65,"vega-lite/build/src/timeunit":66,"vega-lite/build/src/type":67}],40:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var property_1 = require("./property"); +var propindex_1 = require("./propindex"); +var WildcardIndex = (function () { + function WildcardIndex() { + this._mark = undefined; + this._encodings = {}; + this._encodingIndicesByProperty = new propindex_1.PropIndex(); + } + WildcardIndex.prototype.setEncodingProperty = function (index, prop, wildcard) { + var encodingsIndex = this._encodings; + // Init encoding index and set prop + var encIndex = encodingsIndex[index] = encodingsIndex[index] || new propindex_1.PropIndex(); + encIndex.set(prop, wildcard); + // Initialize indicesByProperty[prop] and add index + var indicesByProp = this._encodingIndicesByProperty; + indicesByProp.set(prop, (indicesByProp.get(prop) || [])); + indicesByProp.get(prop).push(index); + return this; + }; + WildcardIndex.prototype.hasEncodingProperty = function (index, prop) { + return !!this._encodings[index] && this._encodings[index].has(prop); + }; + WildcardIndex.prototype.hasProperty = function (prop) { + if (property_1.isEncodingProperty(prop)) { + return this.encodingIndicesByProperty.has(prop); + } + if (prop === 'mark') { + return !!this.mark; + } + /* istanbul ignore next */ + throw new Error('Unimplemented for property ' + prop); + }; + WildcardIndex.prototype.isEmpty = function () { + return !this.mark && this.encodingIndicesByProperty.size() === 0; + }; + WildcardIndex.prototype.setMark = function (mark) { + this._mark = mark; + return this; + }; + Object.defineProperty(WildcardIndex.prototype, "mark", { + get: function () { + return this._mark; + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(WildcardIndex.prototype, "encodings", { + get: function () { + return this._encodings; + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(WildcardIndex.prototype, "encodingIndicesByProperty", { + get: function () { + return this._encodingIndicesByProperty; + }, + enumerable: true, + configurable: true + }); + return WildcardIndex; +}()); +exports.WildcardIndex = WildcardIndex; + +},{"./property":13,"./propindex":14}],41:[function(require,module,exports){ + +},{}],42:[function(require,module,exports){ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : + typeof define === 'function' && define.amd ? define('d3-time', ['exports'], factory) : + factory((global.d3_time = {})); +}(this, function (exports) { 'use strict'; + + var t0 = new Date; + var t1 = new Date; + function newInterval(floori, offseti, count, field) { + + function interval(date) { + return floori(date = new Date(+date)), date; + } + + interval.floor = interval; + + interval.round = function(date) { + var d0 = new Date(+date), + d1 = new Date(date - 1); + floori(d0), floori(d1), offseti(d1, 1); + return date - d0 < d1 - date ? d0 : d1; + }; + + interval.ceil = function(date) { + return floori(date = new Date(date - 1)), offseti(date, 1), date; + }; + + interval.offset = function(date, step) { + return offseti(date = new Date(+date), step == null ? 1 : Math.floor(step)), date; + }; + + interval.range = function(start, stop, step) { + var range = []; + start = new Date(start - 1); + stop = new Date(+stop); + step = step == null ? 1 : Math.floor(step); + if (!(start < stop) || !(step > 0)) return range; // also handles Invalid Date + offseti(start, 1), floori(start); + if (start < stop) range.push(new Date(+start)); + while (offseti(start, step), floori(start), start < stop) range.push(new Date(+start)); + return range; + }; + + interval.filter = function(test) { + return newInterval(function(date) { + while (floori(date), !test(date)) date.setTime(date - 1); + }, function(date, step) { + while (--step >= 0) while (offseti(date, 1), !test(date)); + }); + }; + + if (count) { + interval.count = function(start, end) { + t0.setTime(+start), t1.setTime(+end); + floori(t0), floori(t1); + return Math.floor(count(t0, t1)); + }; + + interval.every = function(step) { + step = Math.floor(step); + return !isFinite(step) || !(step > 0) ? null + : !(step > 1) ? interval + : interval.filter(field + ? function(d) { return field(d) % step === 0; } + : function(d) { return interval.count(0, d) % step === 0; }); + }; + } + + return interval; + }; + + var millisecond = newInterval(function() { + // noop + }, function(date, step) { + date.setTime(+date + step); + }, function(start, end) { + return end - start; + }); + + // An optimized implementation for this simple case. + millisecond.every = function(k) { + k = Math.floor(k); + if (!isFinite(k) || !(k > 0)) return null; + if (!(k > 1)) return millisecond; + return newInterval(function(date) { + date.setTime(Math.floor(date / k) * k); + }, function(date, step) { + date.setTime(+date + step * k); + }, function(start, end) { + return (end - start) / k; + }); + }; + + var second = newInterval(function(date) { + date.setMilliseconds(0); + }, function(date, step) { + date.setTime(+date + step * 1e3); + }, function(start, end) { + return (end - start) / 1e3; + }, function(date) { + return date.getSeconds(); + }); + + var minute = newInterval(function(date) { + date.setSeconds(0, 0); + }, function(date, step) { + date.setTime(+date + step * 6e4); + }, function(start, end) { + return (end - start) / 6e4; + }, function(date) { + return date.getMinutes(); + }); + + var hour = newInterval(function(date) { + date.setMinutes(0, 0, 0); + }, function(date, step) { + date.setTime(+date + step * 36e5); + }, function(start, end) { + return (end - start) / 36e5; + }, function(date) { + return date.getHours(); + }); + + var day = newInterval(function(date) { + date.setHours(0, 0, 0, 0); + }, function(date, step) { + date.setDate(date.getDate() + step); + }, function(start, end) { + return (end - start - (end.getTimezoneOffset() - start.getTimezoneOffset()) * 6e4) / 864e5; + }, function(date) { + return date.getDate() - 1; + }); + + function weekday(i) { + return newInterval(function(date) { + date.setHours(0, 0, 0, 0); + date.setDate(date.getDate() - (date.getDay() + 7 - i) % 7); + }, function(date, step) { + date.setDate(date.getDate() + step * 7); + }, function(start, end) { + return (end - start - (end.getTimezoneOffset() - start.getTimezoneOffset()) * 6e4) / 6048e5; + }); + } + + var sunday = weekday(0); + var monday = weekday(1); + var tuesday = weekday(2); + var wednesday = weekday(3); + var thursday = weekday(4); + var friday = weekday(5); + var saturday = weekday(6); + + var month = newInterval(function(date) { + date.setHours(0, 0, 0, 0); + date.setDate(1); + }, function(date, step) { + date.setMonth(date.getMonth() + step); + }, function(start, end) { + return end.getMonth() - start.getMonth() + (end.getFullYear() - start.getFullYear()) * 12; + }, function(date) { + return date.getMonth(); + }); + + var year = newInterval(function(date) { + date.setHours(0, 0, 0, 0); + date.setMonth(0, 1); + }, function(date, step) { + date.setFullYear(date.getFullYear() + step); + }, function(start, end) { + return end.getFullYear() - start.getFullYear(); + }, function(date) { + return date.getFullYear(); + }); + + var utcSecond = newInterval(function(date) { + date.setUTCMilliseconds(0); + }, function(date, step) { + date.setTime(+date + step * 1e3); + }, function(start, end) { + return (end - start) / 1e3; + }, function(date) { + return date.getUTCSeconds(); + }); + + var utcMinute = newInterval(function(date) { + date.setUTCSeconds(0, 0); + }, function(date, step) { + date.setTime(+date + step * 6e4); + }, function(start, end) { + return (end - start) / 6e4; + }, function(date) { + return date.getUTCMinutes(); + }); + + var utcHour = newInterval(function(date) { + date.setUTCMinutes(0, 0, 0); + }, function(date, step) { + date.setTime(+date + step * 36e5); + }, function(start, end) { + return (end - start) / 36e5; + }, function(date) { + return date.getUTCHours(); + }); + + var utcDay = newInterval(function(date) { + date.setUTCHours(0, 0, 0, 0); + }, function(date, step) { + date.setUTCDate(date.getUTCDate() + step); + }, function(start, end) { + return (end - start) / 864e5; + }, function(date) { + return date.getUTCDate() - 1; + }); + + function utcWeekday(i) { + return newInterval(function(date) { + date.setUTCHours(0, 0, 0, 0); + date.setUTCDate(date.getUTCDate() - (date.getUTCDay() + 7 - i) % 7); + }, function(date, step) { + date.setUTCDate(date.getUTCDate() + step * 7); + }, function(start, end) { + return (end - start) / 6048e5; + }); + } + + var utcSunday = utcWeekday(0); + var utcMonday = utcWeekday(1); + var utcTuesday = utcWeekday(2); + var utcWednesday = utcWeekday(3); + var utcThursday = utcWeekday(4); + var utcFriday = utcWeekday(5); + var utcSaturday = utcWeekday(6); + + var utcMonth = newInterval(function(date) { + date.setUTCHours(0, 0, 0, 0); + date.setUTCDate(1); + }, function(date, step) { + date.setUTCMonth(date.getUTCMonth() + step); + }, function(start, end) { + return end.getUTCMonth() - start.getUTCMonth() + (end.getUTCFullYear() - start.getUTCFullYear()) * 12; + }, function(date) { + return date.getUTCMonth(); + }); + + var utcYear = newInterval(function(date) { + date.setUTCHours(0, 0, 0, 0); + date.setUTCMonth(0, 1); + }, function(date, step) { + date.setUTCFullYear(date.getUTCFullYear() + step); + }, function(start, end) { + return end.getUTCFullYear() - start.getUTCFullYear(); + }, function(date) { + return date.getUTCFullYear(); + }); + + var milliseconds = millisecond.range; + var seconds = second.range; + var minutes = minute.range; + var hours = hour.range; + var days = day.range; + var sundays = sunday.range; + var mondays = monday.range; + var tuesdays = tuesday.range; + var wednesdays = wednesday.range; + var thursdays = thursday.range; + var fridays = friday.range; + var saturdays = saturday.range; + var weeks = sunday.range; + var months = month.range; + var years = year.range; + + var utcMillisecond = millisecond; + var utcMilliseconds = milliseconds; + var utcSeconds = utcSecond.range; + var utcMinutes = utcMinute.range; + var utcHours = utcHour.range; + var utcDays = utcDay.range; + var utcSundays = utcSunday.range; + var utcMondays = utcMonday.range; + var utcTuesdays = utcTuesday.range; + var utcWednesdays = utcWednesday.range; + var utcThursdays = utcThursday.range; + var utcFridays = utcFriday.range; + var utcSaturdays = utcSaturday.range; + var utcWeeks = utcSunday.range; + var utcMonths = utcMonth.range; + var utcYears = utcYear.range; + + var version = "0.1.1"; + + exports.version = version; + exports.milliseconds = milliseconds; + exports.seconds = seconds; + exports.minutes = minutes; + exports.hours = hours; + exports.days = days; + exports.sundays = sundays; + exports.mondays = mondays; + exports.tuesdays = tuesdays; + exports.wednesdays = wednesdays; + exports.thursdays = thursdays; + exports.fridays = fridays; + exports.saturdays = saturdays; + exports.weeks = weeks; + exports.months = months; + exports.years = years; + exports.utcMillisecond = utcMillisecond; + exports.utcMilliseconds = utcMilliseconds; + exports.utcSeconds = utcSeconds; + exports.utcMinutes = utcMinutes; + exports.utcHours = utcHours; + exports.utcDays = utcDays; + exports.utcSundays = utcSundays; + exports.utcMondays = utcMondays; + exports.utcTuesdays = utcTuesdays; + exports.utcWednesdays = utcWednesdays; + exports.utcThursdays = utcThursdays; + exports.utcFridays = utcFridays; + exports.utcSaturdays = utcSaturdays; + exports.utcWeeks = utcWeeks; + exports.utcMonths = utcMonths; + exports.utcYears = utcYears; + exports.millisecond = millisecond; + exports.second = second; + exports.minute = minute; + exports.hour = hour; + exports.day = day; + exports.sunday = sunday; + exports.monday = monday; + exports.tuesday = tuesday; + exports.wednesday = wednesday; + exports.thursday = thursday; + exports.friday = friday; + exports.saturday = saturday; + exports.week = sunday; + exports.month = month; + exports.year = year; + exports.utcSecond = utcSecond; + exports.utcMinute = utcMinute; + exports.utcHour = utcHour; + exports.utcDay = utcDay; + exports.utcSunday = utcSunday; + exports.utcMonday = utcMonday; + exports.utcTuesday = utcTuesday; + exports.utcWednesday = utcWednesday; + exports.utcThursday = utcThursday; + exports.utcFriday = utcFriday; + exports.utcSaturday = utcSaturday; + exports.utcWeek = utcSunday; + exports.utcMonth = utcMonth; + exports.utcYear = utcYear; + exports.interval = newInterval; + +})); +},{}],43:[function(require,module,exports){ +var util = require('../util'), + time = require('../time'), + EPSILON = 1e-15; + +function bins(opt) { + if (!opt) { throw Error("Missing binning options."); } + + // determine range + var maxb = opt.maxbins || 15, + base = opt.base || 10, + logb = Math.log(base), + div = opt.div || [5, 2], + min = opt.min, + max = opt.max, + span = max - min, + step, level, minstep, precision, v, i, eps; + + if (opt.step) { + // if step size is explicitly given, use that + step = opt.step; + } else if (opt.steps) { + // if provided, limit choice to acceptable step sizes + step = opt.steps[Math.min( + opt.steps.length - 1, + bisect(opt.steps, span/maxb, 0, opt.steps.length) + )]; + } else { + // else use span to determine step size + level = Math.ceil(Math.log(maxb) / logb); + minstep = opt.minstep || 0; + step = Math.max( + minstep, + Math.pow(base, Math.round(Math.log(span) / logb) - level) + ); + + // increase step size if too many bins + while (Math.ceil(span/step) > maxb) { step *= base; } + + // decrease step size if allowed + for (i=0; i= minstep && span / v <= maxb) step = v; + } + } + + // update precision, min and max + v = Math.log(step); + precision = v >= 0 ? 0 : ~~(-v / logb) + 1; + eps = Math.pow(base, -precision - 1); + min = Math.min(min, Math.floor(min / step + eps) * step); + max = Math.ceil(max / step) * step; + + return { + start: min, + stop: max, + step: step, + unit: {precision: precision}, + value: value, + index: index + }; +} + +function bisect(a, x, lo, hi) { + while (lo < hi) { + var mid = lo + hi >>> 1; + if (util.cmp(a[mid], x) < 0) { lo = mid + 1; } + else { hi = mid; } + } + return lo; +} + +function value(v) { + return this.step * Math.floor(v / this.step + EPSILON); +} + +function index(v) { + return Math.floor((v - this.start) / this.step + EPSILON); +} + +function date_value(v) { + return this.unit.date(value.call(this, v)); +} + +function date_index(v) { + return index.call(this, this.unit.unit(v)); +} + +bins.date = function(opt) { + if (!opt) { throw Error("Missing date binning options."); } + + // find time step, then bin + var units = opt.utc ? time.utc : time, + dmin = opt.min, + dmax = opt.max, + maxb = opt.maxbins || 20, + minb = opt.minbins || 4, + span = (+dmax) - (+dmin), + unit = opt.unit ? units[opt.unit] : units.find(span, minb, maxb), + spec = bins({ + min: unit.min != null ? unit.min : unit.unit(dmin), + max: unit.max != null ? unit.max : unit.unit(dmax), + maxbins: maxb, + minstep: unit.minstep, + steps: unit.step + }); + + spec.unit = unit; + spec.index = date_index; + if (!opt.raw) spec.value = date_value; + return spec; +}; + +module.exports = bins; + +},{"../time":47,"../util":48}],44:[function(require,module,exports){ +var util = require('./util'), + gen = module.exports; + +gen.repeat = function(val, n) { + var a = Array(n), i; + for (i=0; i stop) range.push(j); + else while ((j = start + step * ++i) < stop) range.push(j); + return range; +}; + +gen.random = {}; + +gen.random.uniform = function(min, max) { + if (max === undefined) { + max = min === undefined ? 1 : min; + min = 0; + } + var d = max - min; + var f = function() { + return min + d * Math.random(); + }; + f.samples = function(n) { + return gen.zeros(n).map(f); + }; + f.pdf = function(x) { + return (x >= min && x <= max) ? 1/d : 0; + }; + f.cdf = function(x) { + return x < min ? 0 : x > max ? 1 : (x - min) / d; + }; + f.icdf = function(p) { + return (p >= 0 && p <= 1) ? min + p*d : NaN; + }; + return f; +}; + +gen.random.integer = function(a, b) { + if (b === undefined) { + b = a; + a = 0; + } + var d = b - a; + var f = function() { + return a + Math.floor(d * Math.random()); + }; + f.samples = function(n) { + return gen.zeros(n).map(f); + }; + f.pdf = function(x) { + return (x === Math.floor(x) && x >= a && x < b) ? 1/d : 0; + }; + f.cdf = function(x) { + var v = Math.floor(x); + return v < a ? 0 : v >= b ? 1 : (v - a + 1) / d; + }; + f.icdf = function(p) { + return (p >= 0 && p <= 1) ? a - 1 + Math.floor(p*d) : NaN; + }; + return f; +}; + +gen.random.normal = function(mean, stdev) { + mean = mean || 0; + stdev = stdev || 1; + var next; + var f = function() { + var x = 0, y = 0, rds, c; + if (next !== undefined) { + x = next; + next = undefined; + return x; + } + do { + x = Math.random()*2-1; + y = Math.random()*2-1; + rds = x*x + y*y; + } while (rds === 0 || rds > 1); + c = Math.sqrt(-2*Math.log(rds)/rds); // Box-Muller transform + next = mean + y*c*stdev; + return mean + x*c*stdev; + }; + f.samples = function(n) { + return gen.zeros(n).map(f); + }; + f.pdf = function(x) { + var exp = Math.exp(Math.pow(x-mean, 2) / (-2 * Math.pow(stdev, 2))); + return (1 / (stdev * Math.sqrt(2*Math.PI))) * exp; + }; + f.cdf = function(x) { + // Approximation from West (2009) + // Better Approximations to Cumulative Normal Functions + var cd, + z = (x - mean) / stdev, + Z = Math.abs(z); + if (Z > 37) { + cd = 0; + } else { + var sum, exp = Math.exp(-Z*Z/2); + if (Z < 7.07106781186547) { + sum = 3.52624965998911e-02 * Z + 0.700383064443688; + sum = sum * Z + 6.37396220353165; + sum = sum * Z + 33.912866078383; + sum = sum * Z + 112.079291497871; + sum = sum * Z + 221.213596169931; + sum = sum * Z + 220.206867912376; + cd = exp * sum; + sum = 8.83883476483184e-02 * Z + 1.75566716318264; + sum = sum * Z + 16.064177579207; + sum = sum * Z + 86.7807322029461; + sum = sum * Z + 296.564248779674; + sum = sum * Z + 637.333633378831; + sum = sum * Z + 793.826512519948; + sum = sum * Z + 440.413735824752; + cd = cd / sum; + } else { + sum = Z + 0.65; + sum = Z + 4 / sum; + sum = Z + 3 / sum; + sum = Z + 2 / sum; + sum = Z + 1 / sum; + cd = exp / sum / 2.506628274631; + } + } + return z > 0 ? 1 - cd : cd; + }; + f.icdf = function(p) { + // Approximation of Probit function using inverse error function. + if (p <= 0 || p >= 1) return NaN; + var x = 2*p - 1, + v = (8 * (Math.PI - 3)) / (3 * Math.PI * (4-Math.PI)), + a = (2 / (Math.PI*v)) + (Math.log(1 - Math.pow(x,2)) / 2), + b = Math.log(1 - (x*x)) / v, + s = (x > 0 ? 1 : -1) * Math.sqrt(Math.sqrt((a*a) - b) - a); + return mean + stdev * Math.SQRT2 * s; + }; + return f; +}; + +gen.random.bootstrap = function(domain, smooth) { + // Generates a bootstrap sample from a set of observations. + // Smooth bootstrapping adds random zero-centered noise to the samples. + var val = domain.filter(util.isValid), + len = val.length, + err = smooth ? gen.random.normal(0, smooth) : null; + var f = function() { + return val[~~(Math.random()*len)] + (err ? err() : 0); + }; + f.samples = function(n) { + return gen.zeros(n).map(f); + }; + return f; +}; +},{"./util":48}],45:[function(require,module,exports){ +var util = require('../util'); + +var TYPES = '__types__'; + +var PARSERS = { + boolean: util.boolean, + integer: util.number, + number: util.number, + date: util.date, + string: function(x) { return x == null || x === '' ? null : x + ''; } +}; + +var TESTS = { + boolean: function(x) { return x==='true' || x==='false' || util.isBoolean(x); }, + integer: function(x) { return TESTS.number(x) && (x=+x) === ~~x; }, + number: function(x) { return !isNaN(+x) && !util.isDate(x); }, + date: function(x) { return !isNaN(Date.parse(x)); } +}; + +function annotation(data, types) { + if (!types) return data && data[TYPES] || null; + data[TYPES] = types; +} + +function fieldNames(datum) { + return util.keys(datum); +} + +function bracket(fieldName) { + return '[' + fieldName + ']'; +} + +function type(values, f) { + values = util.array(values); + f = util.$(f); + var v, i, n; + + // if data array has type annotations, use them + if (values[TYPES]) { + v = f(values[TYPES]); + if (util.isString(v)) return v; + } + + for (i=0, n=values.length; !util.isValid(v) && i 0 ? Math.pow(mean, 1/c) : 0; + return mean; +}; + +// Compute the harmonic mean of an array of numbers. +stats.mean.harmonic = function(values, f) { + f = util.$(f); + var mean = 0, c, n, v, i; + for (i=0, c=0, n=values.length; i b) b = v; + } + } + return [a, b]; +}; + +// Find the integer indices of the minimum and maximum values. +stats.extent.index = function(values, f) { + f = util.$(f); + var x = -1, y = -1, a, b, v, i, n = values.length; + for (i=0; i b) { b = v; y = i; } + } + } + return [x, y]; +}; + +// Compute the dot product of two arrays of numbers. +stats.dot = function(values, a, b) { + var sum = 0, i, v; + if (!b) { + if (values.length !== a.length) { + throw Error('Array lengths must match.'); + } + for (i=0; i -1 && p !== v) { + mu = 1 + (i-1 + tie) / 2; + for (; tie -1) { + mu = 1 + (n-1 + tie) / 2; + for (; tie max) max = x; + delta = x - mean; + mean = mean + delta / (++valid); + M2 = M2 + delta * (x - mean); + vals.push(x); + } + } + M2 = M2 / (valid - 1); + sd = Math.sqrt(M2); + + // sort values for median and iqr + vals.sort(util.cmp); + + return { + type: type(values, f), + unique: u, + count: values.length, + valid: valid, + missing: missing, + distinct: distinct, + min: min, + max: max, + mean: mean, + stdev: sd, + median: (v = stats.quantile(vals, 0.5)), + q1: stats.quantile(vals, 0.25), + q3: stats.quantile(vals, 0.75), + modeskew: sd === 0 ? 0 : (mean - v) / sd + }; +}; + +// Compute profiles for all variables in a data set. +stats.summary = function(data, fields) { + fields = fields || util.keys(data[0]); + var s = fields.map(function(f) { + var p = stats.profile(data, util.$(f)); + return (p.field = f, p); + }); + return (s.__summary__ = true, s); +}; + +},{"./generate":44,"./import/type":45,"./util":48}],47:[function(require,module,exports){ +var d3_time = require('d3-time'); + +var tempDate = new Date(), + baseDate = new Date(0, 0, 1).setFullYear(0), // Jan 1, 0 AD + utcBaseDate = new Date(Date.UTC(0, 0, 1)).setUTCFullYear(0); + +function date(d) { + return (tempDate.setTime(+d), tempDate); +} + +// create a time unit entry +function entry(type, date, unit, step, min, max) { + var e = { + type: type, + date: date, + unit: unit + }; + if (step) { + e.step = step; + } else { + e.minstep = 1; + } + if (min != null) e.min = min; + if (max != null) e.max = max; + return e; +} + +function create(type, unit, base, step, min, max) { + return entry(type, + function(d) { return unit.offset(base, d); }, + function(d) { return unit.count(base, d); }, + step, min, max); +} + +var locale = [ + create('second', d3_time.second, baseDate), + create('minute', d3_time.minute, baseDate), + create('hour', d3_time.hour, baseDate), + create('day', d3_time.day, baseDate, [1, 7]), + create('month', d3_time.month, baseDate, [1, 3, 6]), + create('year', d3_time.year, baseDate), + + // periodic units + entry('seconds', + function(d) { return new Date(1970, 0, 1, 0, 0, d); }, + function(d) { return date(d).getSeconds(); }, + null, 0, 59 + ), + entry('minutes', + function(d) { return new Date(1970, 0, 1, 0, d); }, + function(d) { return date(d).getMinutes(); }, + null, 0, 59 + ), + entry('hours', + function(d) { return new Date(1970, 0, 1, d); }, + function(d) { return date(d).getHours(); }, + null, 0, 23 + ), + entry('weekdays', + function(d) { return new Date(1970, 0, 4+d); }, + function(d) { return date(d).getDay(); }, + [1], 0, 6 + ), + entry('dates', + function(d) { return new Date(1970, 0, d); }, + function(d) { return date(d).getDate(); }, + [1], 1, 31 + ), + entry('months', + function(d) { return new Date(1970, d % 12, 1); }, + function(d) { return date(d).getMonth(); }, + [1], 0, 11 + ) +]; + +var utc = [ + create('second', d3_time.utcSecond, utcBaseDate), + create('minute', d3_time.utcMinute, utcBaseDate), + create('hour', d3_time.utcHour, utcBaseDate), + create('day', d3_time.utcDay, utcBaseDate, [1, 7]), + create('month', d3_time.utcMonth, utcBaseDate, [1, 3, 6]), + create('year', d3_time.utcYear, utcBaseDate), + + // periodic units + entry('seconds', + function(d) { return new Date(Date.UTC(1970, 0, 1, 0, 0, d)); }, + function(d) { return date(d).getUTCSeconds(); }, + null, 0, 59 + ), + entry('minutes', + function(d) { return new Date(Date.UTC(1970, 0, 1, 0, d)); }, + function(d) { return date(d).getUTCMinutes(); }, + null, 0, 59 + ), + entry('hours', + function(d) { return new Date(Date.UTC(1970, 0, 1, d)); }, + function(d) { return date(d).getUTCHours(); }, + null, 0, 23 + ), + entry('weekdays', + function(d) { return new Date(Date.UTC(1970, 0, 4+d)); }, + function(d) { return date(d).getUTCDay(); }, + [1], 0, 6 + ), + entry('dates', + function(d) { return new Date(Date.UTC(1970, 0, d)); }, + function(d) { return date(d).getUTCDate(); }, + [1], 1, 31 + ), + entry('months', + function(d) { return new Date(Date.UTC(1970, d % 12, 1)); }, + function(d) { return date(d).getUTCMonth(); }, + [1], 0, 11 + ) +]; + +var STEPS = [ + [31536e6, 5], // 1-year + [7776e6, 4], // 3-month + [2592e6, 4], // 1-month + [12096e5, 3], // 2-week + [6048e5, 3], // 1-week + [1728e5, 3], // 2-day + [864e5, 3], // 1-day + [432e5, 2], // 12-hour + [216e5, 2], // 6-hour + [108e5, 2], // 3-hour + [36e5, 2], // 1-hour + [18e5, 1], // 30-minute + [9e5, 1], // 15-minute + [3e5, 1], // 5-minute + [6e4, 1], // 1-minute + [3e4, 0], // 30-second + [15e3, 0], // 15-second + [5e3, 0], // 5-second + [1e3, 0] // 1-second +]; + +function find(units, span, minb, maxb) { + var step = STEPS[0], i, n, bins; + + for (i=1, n=STEPS.length; i step[0]) { + bins = span / step[0]; + if (bins > maxb) { + return units[STEPS[i-1][1]]; + } + if (bins >= minb) { + return units[step[1]]; + } + } + } + return units[STEPS[n-1][1]]; +} + +function toUnitMap(units) { + var map = {}, i, n; + for (i=0, n=units.length; i 1 ? + function(x, v) { + for (var i=0; i b || b == null) && a != null ? 1 : + ((b = b instanceof Date ? +b : b), + (a = a instanceof Date ? +a : a)) !== a && b === b ? -1 : + b !== b && a === a ? 1 : 0; +}; + +u.numcmp = function(a, b) { return a - b; }; + +u.stablesort = function(array, sortBy, keyFn) { + var indices = array.reduce(function(idx, v, i) { + return (idx[keyFn(v)] = i, idx); + }, {}); + + array.sort(function(a, b) { + var sa = sortBy(a), + sb = sortBy(b); + return sa < sb ? -1 : sa > sb ? 1 + : (indices[keyFn(a)] - indices[keyFn(b)]); + }); + + return array; +}; + +// permutes an array using a Knuth shuffle +u.permute = function(a) { + var m = a.length, + swap, + i; + + while (m) { + i = Math.floor(Math.random() * m--); + swap = a[m]; + a[m] = a[i]; + a[i] = swap; + } +}; + +// string functions + +u.pad = function(s, length, pos, padchar) { + padchar = padchar || " "; + var d = length - s.length; + if (d <= 0) return s; + switch (pos) { + case 'left': + return strrep(d, padchar) + s; + case 'middle': + case 'center': + return strrep(Math.floor(d/2), padchar) + + s + strrep(Math.ceil(d/2), padchar); + default: + return s + strrep(d, padchar); + } +}; + +function strrep(n, str) { + var s = "", i; + for (i=0; i= '0' && ch <= '9') { + string += ch; + next(); + } + if (ch === '.') { + string += '.'; + while (next() && ch >= '0' && ch <= '9') { + string += ch; + } + } + if (ch === 'e' || ch === 'E') { + string += ch; + next(); + if (ch === '-' || ch === '+') { + string += ch; + next(); + } + while (ch >= '0' && ch <= '9') { + string += ch; + next(); + } + } + number = +string; + if (!isFinite(number)) { + error("Bad number"); + } else { + return number; + } + }, + + string = function () { + // Parse a string value. + var hex, + i, + string = '', + uffff; + + // When parsing for string values, we must look for " and \ characters. + if (ch === '"') { + while (next()) { + if (ch === '"') { + next(); + return string; + } else if (ch === '\\') { + next(); + if (ch === 'u') { + uffff = 0; + for (i = 0; i < 4; i += 1) { + hex = parseInt(next(), 16); + if (!isFinite(hex)) { + break; + } + uffff = uffff * 16 + hex; + } + string += String.fromCharCode(uffff); + } else if (typeof escapee[ch] === 'string') { + string += escapee[ch]; + } else { + break; + } + } else { + string += ch; + } + } + } + error("Bad string"); + }, + + white = function () { + +// Skip whitespace. + + while (ch && ch <= ' ') { + next(); + } + }, + + word = function () { + +// true, false, or null. + + switch (ch) { + case 't': + next('t'); + next('r'); + next('u'); + next('e'); + return true; + case 'f': + next('f'); + next('a'); + next('l'); + next('s'); + next('e'); + return false; + case 'n': + next('n'); + next('u'); + next('l'); + next('l'); + return null; + } + error("Unexpected '" + ch + "'"); + }, + + value, // Place holder for the value function. + + array = function () { + +// Parse an array value. + + var array = []; + + if (ch === '[') { + next('['); + white(); + if (ch === ']') { + next(']'); + return array; // empty array + } + while (ch) { + array.push(value()); + white(); + if (ch === ']') { + next(']'); + return array; + } + next(','); + white(); + } + } + error("Bad array"); + }, + + object = function () { + +// Parse an object value. + + var key, + object = {}; + + if (ch === '{') { + next('{'); + white(); + if (ch === '}') { + next('}'); + return object; // empty object + } + while (ch) { + key = string(); + white(); + next(':'); + if (Object.hasOwnProperty.call(object, key)) { + error('Duplicate key "' + key + '"'); + } + object[key] = value(); + white(); + if (ch === '}') { + next('}'); + return object; + } + next(','); + white(); + } + } + error("Bad object"); + }; + +value = function () { + +// Parse a JSON value. It could be an object, an array, a string, a number, +// or a word. + + white(); + switch (ch) { + case '{': + return object(); + case '[': + return array(); + case '"': + return string(); + case '-': + return number(); + default: + return ch >= '0' && ch <= '9' ? number() : word(); + } +}; + +// Return the json_parse function. It will have access to all of the above +// functions and variables. + +module.exports = function (source, reviver) { + var result; + + text = source; + at = 0; + ch = ' '; + result = value(); + white(); + if (ch) { + error("Syntax error"); + } + + // If there is a reviver function, we recursively walk the new structure, + // passing each name/value pair to the reviver function for possible + // transformation, starting with a temporary root object that holds the result + // in an empty key. If there is not a reviver function, we simply return the + // result. + + return typeof reviver === 'function' ? (function walk(holder, key) { + var k, v, value = holder[key]; + if (value && typeof value === 'object') { + for (k in value) { + if (Object.prototype.hasOwnProperty.call(value, k)) { + v = walk(value, k); + if (v !== undefined) { + value[k] = v; + } else { + delete value[k]; + } + } + } + } + return reviver.call(holder, key, value); + }({'': result}, '')) : result; +}; + +},{}],52:[function(require,module,exports){ +var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g, + escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g, + gap, + indent, + meta = { // table of character substitutions + '\b': '\\b', + '\t': '\\t', + '\n': '\\n', + '\f': '\\f', + '\r': '\\r', + '"' : '\\"', + '\\': '\\\\' + }, + rep; + +function quote(string) { + // If the string contains no control characters, no quote characters, and no + // backslash characters, then we can safely slap some quotes around it. + // Otherwise we must also replace the offending characters with safe escape + // sequences. + + escapable.lastIndex = 0; + return escapable.test(string) ? '"' + string.replace(escapable, function (a) { + var c = meta[a]; + return typeof c === 'string' ? c : + '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4); + }) + '"' : '"' + string + '"'; +} + +function str(key, holder) { + // Produce a string from holder[key]. + var i, // The loop counter. + k, // The member key. + v, // The member value. + length, + mind = gap, + partial, + value = holder[key]; + + // If the value has a toJSON method, call it to obtain a replacement value. + if (value && typeof value === 'object' && + typeof value.toJSON === 'function') { + value = value.toJSON(key); + } + + // If we were called with a replacer function, then call the replacer to + // obtain a replacement value. + if (typeof rep === 'function') { + value = rep.call(holder, key, value); + } + + // What happens next depends on the value's type. + switch (typeof value) { + case 'string': + return quote(value); + + case 'number': + // JSON numbers must be finite. Encode non-finite numbers as null. + return isFinite(value) ? String(value) : 'null'; + + case 'boolean': + case 'null': + // If the value is a boolean or null, convert it to a string. Note: + // typeof null does not produce 'null'. The case is included here in + // the remote chance that this gets fixed someday. + return String(value); + + case 'object': + if (!value) return 'null'; + gap += indent; + partial = []; + + // Array.isArray + if (Object.prototype.toString.apply(value) === '[object Array]') { + length = value.length; + for (i = 0; i < length; i += 1) { + partial[i] = str(i, value) || 'null'; + } + + // Join all of the elements together, separated with commas, and + // wrap them in brackets. + v = partial.length === 0 ? '[]' : gap ? + '[\n' + gap + partial.join(',\n' + gap) + '\n' + mind + ']' : + '[' + partial.join(',') + ']'; + gap = mind; + return v; + } + + // If the replacer is an array, use it to select the members to be + // stringified. + if (rep && typeof rep === 'object') { + length = rep.length; + for (i = 0; i < length; i += 1) { + k = rep[i]; + if (typeof k === 'string') { + v = str(k, value); + if (v) { + partial.push(quote(k) + (gap ? ': ' : ':') + v); + } + } + } + } + else { + // Otherwise, iterate through all of the keys in the object. + for (k in value) { + if (Object.prototype.hasOwnProperty.call(value, k)) { + v = str(k, value); + if (v) { + partial.push(quote(k) + (gap ? ': ' : ':') + v); + } + } + } + } + + // Join all of the member texts together, separated with commas, + // and wrap them in braces. + + v = partial.length === 0 ? '{}' : gap ? + '{\n' + gap + partial.join(',\n' + gap) + '\n' + mind + '}' : + '{' + partial.join(',') + '}'; + gap = mind; + return v; + } +} + +module.exports = function (value, replacer, space) { + var i; + gap = ''; + indent = ''; + + // If the space parameter is a number, make an indent string containing that + // many spaces. + if (typeof space === 'number') { + for (i = 0; i < space; i += 1) { + indent += ' '; + } + } + // If the space parameter is a string, it will be used as the indent string. + else if (typeof space === 'string') { + indent = space; + } + + // If there is a replacer, it must be a function or an array. + // Otherwise, throw an error. + rep = replacer; + if (replacer && typeof replacer !== 'function' + && (typeof replacer !== 'object' || typeof replacer.length !== 'number')) { + throw new Error('JSON.stringify'); + } + + // Make a fake root object containing our value under the key of ''. + // Return the result of stringifying the value. + return str('', {'': value}); +}; + +},{}],53:[function(require,module,exports){ +(function (global){ +/*! ***************************************************************************** +Copyright (c) Microsoft Corporation. All rights reserved. +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 + +THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED +WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, +MERCHANTABLITY OR NON-INFRINGEMENT. + +See the Apache Version 2.0 License for specific language governing permissions +and limitations under the License. +***************************************************************************** */ +/* global global, define, System, Reflect, Promise */ +var __extends; +var __assign; +var __rest; +var __decorate; +var __param; +var __metadata; +var __awaiter; +var __generator; +var __exportStar; +var __values; +var __read; +var __spread; +var __await; +var __asyncGenerator; +var __asyncDelegator; +var __asyncValues; +(function (factory) { + var root = typeof global === "object" ? global : typeof self === "object" ? self : typeof this === "object" ? this : {}; + if (typeof define === "function" && define.amd) { + define("tslib", ["exports"], function (exports) { factory(createExporter(root, createExporter(exports))); }); + } + else if (typeof module === "object" && typeof module.exports === "object") { + factory(createExporter(root, createExporter(module.exports))); + } + else { + factory(createExporter(root)); + } + function createExporter(exports, previous) { + return function (id, v) { return exports[id] = previous ? previous(id, v) : v; }; + } +}) +(function (exporter) { + var extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + + __extends = function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; + + __assign = Object.assign || function (t) { + for (var s, i = 1, n = arguments.length; i < n; i++) { + s = arguments[i]; + for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; + } + return t; + }; + + __rest = function (s, e) { + var t = {}; + for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) + t[p] = s[p]; + if (s != null && typeof Object.getOwnPropertySymbols === "function") + for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) if (e.indexOf(p[i]) < 0) + t[p[i]] = s[p[i]]; + return t; + }; + + __decorate = function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; + }; + + __param = function (paramIndex, decorator) { + return function (target, key) { decorator(target, key, paramIndex); } + }; + + __metadata = function (metadataKey, metadataValue) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(metadataKey, metadataValue); + }; + + __awaiter = function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); + }; + + __generator = function (thisArg, body) { + var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; + return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; + function verb(n) { return function (v) { return step([n, v]); }; } + function step(op) { + if (f) throw new TypeError("Generator is already executing."); + while (_) try { + if (f = 1, y && (t = y[op[0] & 2 ? "return" : op[0] ? "throw" : "next"]) && !(t = t.call(y, op[1])).done) return t; + if (y = 0, t) op = [0, t.value]; + switch (op[0]) { + case 0: case 1: t = op; break; + case 4: _.label++; return { value: op[1], done: false }; + case 5: _.label++; y = op[1]; op = [0]; continue; + case 7: op = _.ops.pop(); _.trys.pop(); continue; + default: + if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } + if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } + if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } + if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } + if (t[2]) _.ops.pop(); + _.trys.pop(); continue; + } + op = body.call(thisArg, _); + } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } + if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; + } + }; + + __exportStar = function (m, exports) { + for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; + }; + + __values = function (o) { + var m = typeof Symbol === "function" && o[Symbol.iterator], i = 0; + if (m) return m.call(o); + return { + next: function () { + if (o && i >= o.length) o = void 0; + return { value: o && o[i++], done: !o }; + } + }; + }; + + __read = function (o, n) { + var m = typeof Symbol === "function" && o[Symbol.iterator]; + if (!m) return o; + var i = m.call(o), r, ar = [], e; + try { + while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value); + } + catch (error) { e = { error: error }; } + finally { + try { + if (r && !r.done && (m = i["return"])) m.call(i); + } + finally { if (e) throw e.error; } + } + return ar; + }; + + __spread = function () { + for (var ar = [], i = 0; i < arguments.length; i++) + ar = ar.concat(__read(arguments[i])); + return ar; + }; + + __await = function (v) { + return this instanceof __await ? (this.v = v, this) : new __await(v); + }; + + __asyncGenerator = function (thisArg, _arguments, generator) { + if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined."); + var g = generator.apply(thisArg, _arguments || []), i, q = []; + return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; + function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } + function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } + function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } + function fulfill(value) { resume("next", value); } + function reject(value) { resume("throw", value); } + function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } + }; + + __asyncDelegator = function (o) { + var i, p; + return i = {}, verb("next"), verb("throw", function (e) { throw e; }), verb("return"), i[Symbol.iterator] = function () { return this; }, i; + function verb(n, f) { if (o[n]) i[n] = function (v) { return (p = !p) ? { value: __await(o[n](v)), done: n === "return" } : f ? f(v) : v; }; } + }; + + __asyncValues = function (o) { + if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined."); + var m = o[Symbol.asyncIterator]; + return m ? m.call(o) : typeof __values === "function" ? __values(o) : o[Symbol.iterator](); + }; + + exporter("__extends", __extends); + exporter("__assign", __assign); + exporter("__rest", __rest); + exporter("__decorate", __decorate); + exporter("__param", __param); + exporter("__metadata", __metadata); + exporter("__awaiter", __awaiter); + exporter("__generator", __generator); + exporter("__exportStar", __exportStar); + exporter("__values", __values); + exporter("__read", __read); + exporter("__spread", __spread); + exporter("__await", __await); + exporter("__asyncGenerator", __asyncGenerator); + exporter("__asyncDelegator", __asyncDelegator); + exporter("__asyncValues", __asyncValues); +}); +}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) + +},{}],54:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var util_1 = require("./util"); +exports.AGGREGATE_OPS = [ + 'values', + 'count', + 'valid', + 'missing', + 'distinct', + 'sum', + 'mean', + 'average', + 'variance', + 'variancep', + 'stdev', + 'stdevp', + 'median', + 'q1', + 'q3', + 'ci0', + 'ci1', + 'modeskew', + 'min', + 'max', + 'argmin', + 'argmax', +]; +exports.AGGREGATE_OP_INDEX = util_1.toSet(exports.AGGREGATE_OPS); +exports.COUNTING_OPS = ['count', 'valid', 'missing', 'distinct']; +function isCountingAggregateOp(aggregate) { + return aggregate && util_1.contains(exports.COUNTING_OPS, aggregate); +} +exports.isCountingAggregateOp = isCountingAggregateOp; +/** Additive-based aggregation operations. These can be applied to stack. */ +exports.SUM_OPS = [ + 'count', + 'sum', + 'distinct', + 'valid', + 'missing' +]; +/** + * Aggregation operators that always produce values within the range [domainMin, domainMax]. + */ +exports.SHARED_DOMAIN_OPS = [ + 'mean', + 'average', + 'median', + 'q1', + 'q3', + 'min', + 'max', +]; +exports.SHARED_DOMAIN_OP_INDEX = util_1.toSet(exports.SHARED_DOMAIN_OPS); + +},{"./util":68}],55:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.DEFAULT_AXIS_CONFIG = { + quantitativeExtent: 30 +}; +/** + * A dictionary listing whether a certain axis property is applicable for only main axes or only grid axes. + * (Properties not listed are applicable for both) + */ +exports.AXIS_PROPERTY_TYPE = { + grid: 'grid', + labelOverlap: 'main', + offset: 'main', + maxExtent: 'main', + minExtent: 'main', + title: 'main' +}; +exports.AXIS_PROPERTIES = [ + 'domain', 'format', 'grid', 'labelPadding', 'labels', 'labelOverlap', 'maxExtent', 'minExtent', 'offset', 'orient', 'position', 'tickCount', 'tickExtra', 'ticks', 'tickSize', 'title', 'titlePadding', 'values', 'zindex' +]; +exports.VG_AXIS_PROPERTIES = [].concat(exports.AXIS_PROPERTIES, ['gridScale']); + +},{}],56:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var channel_1 = require("./channel"); +var util_1 = require("./util"); +function binToString(bin) { + if (util_1.isBoolean(bin)) { + return 'bin'; + } + return 'bin' + util_1.keys(bin).map(function (p) { return "_" + p + "_" + bin[p]; }).join(''); +} +exports.binToString = binToString; +function autoMaxBins(channel) { + switch (channel) { + case channel_1.ROW: + case channel_1.COLUMN: + case channel_1.SIZE: + case channel_1.COLOR: + case channel_1.OPACITY: + // Facets and Size shouldn't have too many bins + // We choose 6 like shape to simplify the rule + case channel_1.SHAPE: + return 6; // Vega's "shape" has 6 distinct values + default: + return 10; + } +} +exports.autoMaxBins = autoMaxBins; + +},{"./channel":57,"./util":68}],57:[function(require,module,exports){ +"use strict"; +/* + * Constants and utilities for encoding channels (Visual variables) + * such as 'x', 'y', 'color'. + */ +Object.defineProperty(exports, "__esModule", { value: true }); +var scale_1 = require("./scale"); +var util_1 = require("./util"); +var Channel; +(function (Channel) { + // Facet + Channel.ROW = 'row'; + Channel.COLUMN = 'column'; + // Position + Channel.X = 'x'; + Channel.Y = 'y'; + Channel.X2 = 'x2'; + Channel.Y2 = 'y2'; + // Mark property with scale + Channel.COLOR = 'color'; + Channel.SHAPE = 'shape'; + Channel.SIZE = 'size'; + Channel.OPACITY = 'opacity'; + // Non-scale channel + Channel.TEXT = 'text'; + Channel.ORDER = 'order'; + Channel.DETAIL = 'detail'; + Channel.TOOLTIP = 'tooltip'; +})(Channel = exports.Channel || (exports.Channel = {})); +exports.X = Channel.X; +exports.Y = Channel.Y; +exports.X2 = Channel.X2; +exports.Y2 = Channel.Y2; +exports.ROW = Channel.ROW; +exports.COLUMN = Channel.COLUMN; +exports.SHAPE = Channel.SHAPE; +exports.SIZE = Channel.SIZE; +exports.COLOR = Channel.COLOR; +exports.TEXT = Channel.TEXT; +exports.DETAIL = Channel.DETAIL; +exports.ORDER = Channel.ORDER; +exports.OPACITY = Channel.OPACITY; +exports.TOOLTIP = Channel.TOOLTIP; +exports.CHANNELS = [exports.X, exports.Y, exports.X2, exports.Y2, exports.ROW, exports.COLUMN, exports.SIZE, exports.SHAPE, exports.COLOR, exports.ORDER, exports.OPACITY, exports.TEXT, exports.DETAIL, exports.TOOLTIP]; +var CHANNEL_INDEX = util_1.toSet(exports.CHANNELS); +/** + * Channels cannot have an array of channelDef. + * model.fieldDef, getFieldDef only work for these channels. + * + * (The only two channels that can have an array of channelDefs are "detail" and "order". + * Since there can be multiple fieldDefs for detail and order, getFieldDef/model.fieldDef + * are not applicable for them. Similarly, selection projecttion won't work with "detail" and "order".) + */ +exports.SINGLE_DEF_CHANNELS = [exports.X, exports.Y, exports.X2, exports.Y2, exports.ROW, exports.COLUMN, exports.SIZE, exports.SHAPE, exports.COLOR, exports.OPACITY, exports.TEXT, exports.TOOLTIP]; +function isChannel(str) { + return !!CHANNEL_INDEX[str]; +} +exports.isChannel = isChannel; +// CHANNELS without COLUMN, ROW +exports.UNIT_CHANNELS = [exports.X, exports.Y, exports.X2, exports.Y2, exports.SIZE, exports.SHAPE, exports.COLOR, exports.ORDER, exports.OPACITY, exports.TEXT, exports.DETAIL, exports.TOOLTIP]; +/** List of channels with scales */ +exports.SCALE_CHANNELS = [exports.X, exports.Y, exports.SIZE, exports.SHAPE, exports.COLOR, exports.OPACITY]; +var SCALE_CHANNEL_INDEX = util_1.toSet(exports.SCALE_CHANNELS); +function isScaleChannel(channel) { + return !!SCALE_CHANNEL_INDEX[channel]; +} +exports.isScaleChannel = isScaleChannel; +// UNIT_CHANNELS without X, Y, X2, Y2; +exports.NONSPATIAL_CHANNELS = [exports.SIZE, exports.SHAPE, exports.COLOR, exports.ORDER, exports.OPACITY, exports.TEXT, exports.DETAIL, exports.TOOLTIP]; +// X and Y; +exports.SPATIAL_SCALE_CHANNELS = [exports.X, exports.Y]; +// SCALE_CHANNELS without X, Y; +exports.NONSPATIAL_SCALE_CHANNELS = [exports.SIZE, exports.SHAPE, exports.COLOR, exports.OPACITY]; +exports.LEVEL_OF_DETAIL_CHANNELS = util_1.without(exports.NONSPATIAL_CHANNELS, ['order']); +/** Channels that can serve as groupings for stacked charts. */ +exports.STACK_BY_CHANNELS = [exports.COLOR, exports.DETAIL, exports.ORDER, exports.OPACITY, exports.SIZE]; +/** + * Return whether a channel supports a particular mark type. + * @param channel channel name + * @param mark the mark type + * @return whether the mark supports the channel + */ +function supportMark(channel, mark) { + return mark in getSupportedMark(channel); +} +exports.supportMark = supportMark; +/** + * Return a dictionary showing whether a channel supports mark type. + * @param channel + * @return A dictionary mapping mark types to boolean values. + */ +function getSupportedMark(channel) { + switch (channel) { + case exports.X: + case exports.Y: + case exports.COLOR: + case exports.DETAIL: + case exports.TOOLTIP: + case exports.ORDER: // TODO: revise (order might not support rect, which is not stackable?) + case exports.OPACITY: + case exports.ROW: + case exports.COLUMN: + return { + point: true, tick: true, rule: true, circle: true, square: true, + bar: true, rect: true, line: true, area: true, text: true + }; + case exports.X2: + case exports.Y2: + return { + rule: true, bar: true, rect: true, area: true + }; + case exports.SIZE: + return { + point: true, tick: true, rule: true, circle: true, square: true, + bar: true, text: true, line: true + }; + case exports.SHAPE: + return { point: true }; + case exports.TEXT: + return { text: true }; + } +} +exports.getSupportedMark = getSupportedMark; +function hasScale(channel) { + return !util_1.contains([exports.DETAIL, exports.TEXT, exports.ORDER, exports.TOOLTIP], channel); +} +exports.hasScale = hasScale; +// Position does not work with ordinal (lookup) scale and sequential (which is only for color) +var POSITION_SCALE_TYPE_INDEX = util_1.toSet(util_1.without(scale_1.SCALE_TYPES, ['ordinal', 'sequential'])); +function supportScaleType(channel, scaleType) { + switch (channel) { + case exports.ROW: + case exports.COLUMN: + return scaleType === 'band'; // row / column currently supports band only + case exports.X: + case exports.Y: + case exports.SIZE: // TODO: size and opacity can support ordinal with more modification + case exports.OPACITY: + // Although it generally doesn't make sense to use band with size and opacity, + // it can also work since we use band: 0.5 to get midpoint. + return scaleType in POSITION_SCALE_TYPE_INDEX; + case exports.COLOR: + return scaleType !== 'band'; // band does not make sense with color + case exports.SHAPE: + return scaleType === 'ordinal'; // shape = lookup only + } + /* istanbul ignore next: it should never reach here */ + return false; +} +exports.supportScaleType = supportScaleType; +function rangeType(channel) { + switch (channel) { + case exports.X: + case exports.Y: + case exports.SIZE: + case exports.OPACITY: + // X2 and Y2 use X and Y scales, so they similarly have continuous range. + case exports.X2: + case exports.Y2: + return 'continuous'; + case exports.ROW: + case exports.COLUMN: + case exports.SHAPE: + // TEXT and TOOLTIP have no scale but have discrete output + case exports.TEXT: + case exports.TOOLTIP: + return 'discrete'; + // Color can be either continuous or discrete, depending on scale type. + case exports.COLOR: + return 'flexible'; + // No scale, no range type. + case exports.DETAIL: + case exports.ORDER: + return undefined; + } + /* istanbul ignore next: should never reach here. */ + throw new Error('getSupportedRole not implemented for ' + channel); +} +exports.rangeType = rangeType; + +},{"./scale":65,"./util":68}],58:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var channel_1 = require("../../channel"); +var log = require("../../log"); +var scale_1 = require("../../scale"); +var scale_2 = require("../../scale"); +var timeunit_1 = require("../../timeunit"); +var type_1 = require("../../type"); +var util = require("../../util"); +var util_1 = require("../../util"); +/** + * Determine if there is a specified scale type and if it is appropriate, + * or determine default type if type is unspecified or inappropriate. + */ +// NOTE: CompassQL uses this method. +function scaleType(specifiedType, channel, fieldDef, mark, specifiedRangeStep, scaleConfig) { + var defaultScaleType = defaultType(channel, fieldDef, mark, specifiedRangeStep, scaleConfig); + if (!channel_1.hasScale(channel)) { + // There is no scale for these channels + return null; + } + if (specifiedType !== undefined) { + // Check if explicitly specified scale type is supported by the channel + if (!channel_1.supportScaleType(channel, specifiedType)) { + log.warn(log.message.scaleTypeNotWorkWithChannel(channel, specifiedType, defaultScaleType)); + return defaultScaleType; + } + // Check if explicitly specified scale type is supported by the data type + if (!fieldDefMatchScaleType(specifiedType, fieldDef)) { + log.warn(log.message.scaleTypeNotWorkWithFieldDef(specifiedType, defaultScaleType)); + return defaultScaleType; + } + return specifiedType; + } + return defaultScaleType; +} +exports.scaleType = scaleType; +/** + * Determine appropriate default scale type. + */ +function defaultType(channel, fieldDef, mark, specifiedRangeStep, scaleConfig) { + switch (fieldDef.type) { + case 'nominal': + if (channel === 'color' || channel_1.rangeType(channel) === 'discrete') { + return 'ordinal'; + } + return discreteToContinuousType(channel, mark, specifiedRangeStep, scaleConfig); + case 'ordinal': + if (channel === 'color') { + return 'ordinal'; + } + else if (channel_1.rangeType(channel) === 'discrete') { + if (channel !== 'text' && channel !== 'tooltip') { + log.warn(log.message.discreteChannelCannotEncode(channel, 'ordinal')); + } + return 'ordinal'; + } + return discreteToContinuousType(channel, mark, specifiedRangeStep, scaleConfig); + case 'temporal': + if (channel === 'color') { + if (timeunit_1.isDiscreteByDefault(fieldDef.timeUnit)) { + // For discrete timeUnit, use ordinal scale so that legend produces correct value. + // (See https://github.com/vega/vega-lite/issues/2045.) + return 'ordinal'; + } + return 'sequential'; + } + else if (channel_1.rangeType(channel) === 'discrete') { + log.warn(log.message.discreteChannelCannotEncode(channel, 'temporal')); + // TODO: consider using quantize (equivalent to binning) once we have it + return 'ordinal'; + } + if (timeunit_1.isDiscreteByDefault(fieldDef.timeUnit)) { + return discreteToContinuousType(channel, mark, specifiedRangeStep, scaleConfig); + } + return 'time'; + case 'quantitative': + if (channel === 'color') { + if (fieldDef.bin) { + return 'bin-ordinal'; + } + // Use `sequential` as the default color scale for continuous data + // since it supports both array range and scheme range. + return 'sequential'; + } + else if (channel_1.rangeType(channel) === 'discrete') { + log.warn(log.message.discreteChannelCannotEncode(channel, 'quantitative')); + // TODO: consider using quantize (equivalent to binning) once we have it + return 'ordinal'; + } + // x and y use a linear scale because selections don't work with bin scales + if (fieldDef.bin && channel !== 'x' && channel !== 'y') { + return 'bin-linear'; + } + return 'linear'; + } + /* istanbul ignore next: should never reach this */ + throw new Error(log.message.invalidFieldType(fieldDef.type)); +} +/** + * Determines default scale type for nominal/ordinal field. + * @returns BAND or POINT scale based on channel, mark, and rangeStep + */ +function discreteToContinuousType(channel, mark, specifiedRangeStep, scaleConfig) { + if (util.contains(['x', 'y'], channel)) { + if (mark === 'rect') { + // The rect mark should fit into a band. + return 'band'; + } + if (mark === 'bar') { + return 'band'; + } + } + // Otherwise, use ordinal point scale so we can easily get center positions of the marks. + return 'point'; +} +function fieldDefMatchScaleType(specifiedType, fieldDef) { + var type = fieldDef.type; + if (util_1.contains([type_1.Type.ORDINAL, type_1.Type.NOMINAL], type)) { + return specifiedType === undefined || scale_2.hasDiscreteDomain(specifiedType); + } + else if (type === type_1.Type.TEMPORAL) { + if (!fieldDef.timeUnit) { + return util_1.contains([scale_1.ScaleType.TIME, scale_1.ScaleType.UTC, undefined], specifiedType); + } + else { + return util_1.contains([scale_1.ScaleType.TIME, scale_1.ScaleType.UTC, undefined], specifiedType) || scale_2.hasDiscreteDomain(specifiedType); + } + } + else if (type === type_1.Type.QUANTITATIVE) { + if (fieldDef.bin) { + return specifiedType === scale_1.ScaleType.BIN_LINEAR || specifiedType === scale_1.ScaleType.BIN_ORDINAL; + } + return util_1.contains([scale_1.ScaleType.LOG, scale_1.ScaleType.POW, scale_1.ScaleType.SQRT, scale_1.ScaleType.QUANTILE, scale_1.ScaleType.QUANTIZE, scale_1.ScaleType.LINEAR, undefined], specifiedType); + } + return true; +} +exports.fieldDefMatchScaleType = fieldDefMatchScaleType; + +},{"../../channel":57,"../../log":62,"../../scale":65,"../../timeunit":66,"../../type":67,"../../util":68}],59:[function(require,module,exports){ +"use strict"; +// DateTime definition object +Object.defineProperty(exports, "__esModule", { value: true }); +var log = require("./log"); +var util_1 = require("./util"); +/* + * A designated year that starts on Sunday. + */ +var SUNDAY_YEAR = 2006; +function isDateTime(o) { + return !!o && (!!o.year || !!o.quarter || !!o.month || !!o.date || !!o.day || + !!o.hours || !!o.minutes || !!o.seconds || !!o.milliseconds); +} +exports.isDateTime = isDateTime; +exports.MONTHS = ['january', 'february', 'march', 'april', 'may', 'june', 'july', 'august', 'september', 'october', 'november', 'december']; +exports.SHORT_MONTHS = exports.MONTHS.map(function (m) { return m.substr(0, 3); }); +exports.DAYS = ['sunday', 'monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday']; +exports.SHORT_DAYS = exports.DAYS.map(function (d) { return d.substr(0, 3); }); +function normalizeQuarter(q) { + if (util_1.isNumber(q)) { + if (q > 4) { + log.warn(log.message.invalidTimeUnit('quarter', q)); + } + // We accept 1-based quarter, so need to readjust to 0-based quarter + return (q - 1) + ''; + } + else { + // Invalid quarter + throw new Error(log.message.invalidTimeUnit('quarter', q)); + } +} +function normalizeMonth(m) { + if (util_1.isNumber(m)) { + // We accept 1-based month, so need to readjust to 0-based month + return (m - 1) + ''; + } + else { + var lowerM = m.toLowerCase(); + var monthIndex = exports.MONTHS.indexOf(lowerM); + if (monthIndex !== -1) { + return monthIndex + ''; // 0 for january, ... + } + var shortM = lowerM.substr(0, 3); + var shortMonthIndex = exports.SHORT_MONTHS.indexOf(shortM); + if (shortMonthIndex !== -1) { + return shortMonthIndex + ''; + } + // Invalid month + throw new Error(log.message.invalidTimeUnit('month', m)); + } +} +function normalizeDay(d) { + if (util_1.isNumber(d)) { + // mod so that this can be both 0-based where 0 = sunday + // and 1-based where 7=sunday + return (d % 7) + ''; + } + else { + var lowerD = d.toLowerCase(); + var dayIndex = exports.DAYS.indexOf(lowerD); + if (dayIndex !== -1) { + return dayIndex + ''; // 0 for january, ... + } + var shortD = lowerD.substr(0, 3); + var shortDayIndex = exports.SHORT_DAYS.indexOf(shortD); + if (shortDayIndex !== -1) { + return shortDayIndex + ''; + } + // Invalid day + throw new Error(log.message.invalidTimeUnit('day', d)); + } +} +/** + * Return Vega Expression for a particular date time. + * @param d + * @param normalize whether to normalize quarter, month, day. + */ +function dateTimeExpr(d, normalize) { + if (normalize === void 0) { normalize = false; } + var units = []; + if (normalize && d.day !== undefined) { + if (util_1.keys(d).length > 1) { + log.warn(log.message.droppedDay(d)); + d = util_1.duplicate(d); + delete d.day; + } + } + if (d.year !== undefined) { + units.push(d.year); + } + else if (d.day !== undefined) { + // Set year to 2006 for working with day since January 1 2006 is a Sunday + units.push(SUNDAY_YEAR); + } + else { + units.push(0); + } + if (d.month !== undefined) { + var month = normalize ? normalizeMonth(d.month) : d.month; + units.push(month); + } + else if (d.quarter !== undefined) { + var quarter = normalize ? normalizeQuarter(d.quarter) : d.quarter; + units.push(quarter + '*3'); + } + else { + units.push(0); // months start at zero in JS + } + if (d.date !== undefined) { + units.push(d.date); + } + else if (d.day !== undefined) { + // HACK: Day only works as a standalone unit + // This is only correct because we always set year to 2006 for day + var day = normalize ? normalizeDay(d.day) : d.day; + units.push(day + '+1'); + } + else { + units.push(1); // Date starts at 1 in JS + } + // Note: can't use TimeUnit enum here as importing it will create + // circular dependency problem! + for (var _i = 0, _a = ['hours', 'minutes', 'seconds', 'milliseconds']; _i < _a.length; _i++) { + var timeUnit = _a[_i]; + if (d[timeUnit] !== undefined) { + units.push(d[timeUnit]); + } + else { + units.push(0); + } + } + if (d.utc) { + return "utc(" + units.join(', ') + ")"; + } + else { + return "datetime(" + units.join(', ') + ")"; + } +} +exports.dateTimeExpr = dateTimeExpr; + +},{"./log":62,"./util":68}],60:[function(require,module,exports){ +"use strict"; +// utility for a field definition object +Object.defineProperty(exports, "__esModule", { value: true }); +var tslib_1 = require("tslib"); +var aggregate_1 = require("./aggregate"); +var bin_1 = require("./bin"); +var channel_1 = require("./channel"); +var log = require("./log"); +var timeunit_1 = require("./timeunit"); +var type_1 = require("./type"); +var util_1 = require("./util"); +function isRepeatRef(field) { + return field && !util_1.isString(field) && 'repeat' in field; +} +exports.isRepeatRef = isRepeatRef; +function isConditionalDef(channelDef) { + return !!channelDef && !!channelDef.condition; +} +exports.isConditionalDef = isConditionalDef; +/** + * Return if a channelDef is a ConditionalValueDef with ConditionFieldDef + */ +function hasConditionFieldDef(channelDef) { + return !!channelDef && !!channelDef.condition && isFieldDef(channelDef.condition); +} +exports.hasConditionFieldDef = hasConditionFieldDef; +function isFieldDef(channelDef) { + return !!channelDef && (!!channelDef['field'] || channelDef['aggregate'] === 'count'); +} +exports.isFieldDef = isFieldDef; +function isValueDef(channelDef) { + return channelDef && 'value' in channelDef && channelDef['value'] !== undefined; +} +exports.isValueDef = isValueDef; +function isScaleFieldDef(channelDef) { + return !!channelDef && (!!channelDef['scale'] || !!channelDef['sort']); +} +exports.isScaleFieldDef = isScaleFieldDef; +function field(fieldDef, opt) { + if (opt === void 0) { opt = {}; } + var field = fieldDef.field; + var prefix = opt.prefix; + var suffix = opt.suffix; + if (isCount(fieldDef)) { + field = 'count_*'; + } + else { + var fn = undefined; + if (!opt.nofn) { + if (fieldDef.bin) { + fn = bin_1.binToString(fieldDef.bin); + suffix = opt.binSuffix; + } + else if (fieldDef.aggregate) { + fn = String(opt.aggregate || fieldDef.aggregate); + } + else if (fieldDef.timeUnit) { + fn = String(fieldDef.timeUnit); + } + } + if (fn) { + field = fn + "_" + field; + } + } + if (suffix) { + field = field + "_" + suffix; + } + if (prefix) { + field = prefix + "_" + field; + } + if (opt.expr) { + field = opt.expr + "[" + util_1.stringValue(field) + "]"; + } + return field; +} +exports.field = field; +function isDiscrete(fieldDef) { + switch (fieldDef.type) { + case 'nominal': + case 'ordinal': + return true; + case 'quantitative': + return !!fieldDef.bin; + case 'temporal': + // TODO: deal with custom scale type case. + return timeunit_1.isDiscreteByDefault(fieldDef.timeUnit); + } + throw new Error(log.message.invalidFieldType(fieldDef.type)); +} +exports.isDiscrete = isDiscrete; +function isContinuous(fieldDef) { + return !isDiscrete(fieldDef); +} +exports.isContinuous = isContinuous; +function isCount(fieldDef) { + return fieldDef.aggregate === 'count'; +} +exports.isCount = isCount; +function title(fieldDef, config) { + if (isCount(fieldDef)) { + return config.countTitle; + } + var fn = fieldDef.aggregate || fieldDef.timeUnit || (fieldDef.bin && 'bin'); + if (fn) { + return fn.toUpperCase() + '(' + fieldDef.field + ')'; + } + else { + return fieldDef.field; + } +} +exports.title = title; +function defaultType(fieldDef, channel) { + if (fieldDef.timeUnit) { + return 'temporal'; + } + if (fieldDef.bin) { + return 'quantitative'; + } + switch (channel_1.rangeType(channel)) { + case 'continuous': + return 'quantitative'; + case 'discrete': + return 'nominal'; + case 'flexible':// color + return 'nominal'; + default: + return 'quantitative'; + } +} +exports.defaultType = defaultType; +/** + * Returns the fieldDef -- either from the outer channelDef or from the condition of channelDef. + * @param channelDef + */ +function getFieldDef(channelDef) { + if (isFieldDef(channelDef)) { + return channelDef; + } + else if (hasConditionFieldDef(channelDef)) { + return channelDef.condition; + } + return undefined; +} +exports.getFieldDef = getFieldDef; +/** + * Convert type to full, lowercase type, or augment the fieldDef with a default type if missing. + */ +function normalize(channelDef, channel) { + // If a fieldDef contains a field, we need type. + if (isFieldDef(channelDef)) { + return normalizeFieldDef(channelDef, channel); + } + else if (hasConditionFieldDef(channelDef)) { + return tslib_1.__assign({}, channelDef, { + // Need to cast as normalizeFieldDef normally return FieldDef, but here we know that it is definitely Condition + condition: normalizeFieldDef(channelDef.condition, channel) }); + } + return channelDef; +} +exports.normalize = normalize; +function normalizeFieldDef(fieldDef, channel) { + // Drop invalid aggregate + if (fieldDef.aggregate && !aggregate_1.AGGREGATE_OP_INDEX[fieldDef.aggregate]) { + var aggregate = fieldDef.aggregate, fieldDefWithoutAggregate = tslib_1.__rest(fieldDef, ["aggregate"]); + log.warn(log.message.invalidAggregate(fieldDef.aggregate)); + fieldDef = fieldDefWithoutAggregate; + } + // Normalize bin + if (fieldDef.bin) { + fieldDef = tslib_1.__assign({}, fieldDef, { bin: normalizeBin(fieldDef.bin, channel) }); + } + // Normalize Type + if (fieldDef.type) { + var fullType = type_1.getFullName(fieldDef.type); + if (fieldDef.type !== fullType) { + // convert short type to full type + fieldDef = tslib_1.__assign({}, fieldDef, { type: fullType }); + } + if (aggregate_1.isCountingAggregateOp(fieldDef.aggregate) && fieldDef.type !== 'quantitative') { + log.warn(log.message.invalidFieldTypeForCountAggregate(fieldDef.type, fieldDef.aggregate)); + fieldDef = tslib_1.__assign({}, fieldDef, { type: 'quantitative' }); + } + } + else { + // If type is empty / invalid, then augment with default type + var newType = defaultType(fieldDef, channel); + log.warn(log.message.emptyOrInvalidFieldType(fieldDef.type, channel, newType)); + fieldDef = tslib_1.__assign({}, fieldDef, { type: newType }); + } + var _a = channelCompatibility(fieldDef, channel), compatible = _a.compatible, warning = _a.warning; + if (!compatible) { + log.warn(warning); + } + return fieldDef; +} +exports.normalizeFieldDef = normalizeFieldDef; +function normalizeBin(bin, channel) { + if (util_1.isBoolean(bin)) { + return { maxbins: bin_1.autoMaxBins(channel) }; + } + else if (!bin.maxbins && !bin.step) { + return tslib_1.__assign({}, bin, { maxbins: bin_1.autoMaxBins(channel) }); + } + else { + return bin; + } +} +exports.normalizeBin = normalizeBin; +var COMPATIBLE = { compatible: true }; +function channelCompatibility(fieldDef, channel) { + switch (channel) { + case 'row': + case 'column': + if (isContinuous(fieldDef) && !fieldDef.timeUnit) { + // TODO:(https://github.com/vega/vega-lite/issues/2011): + // with timeUnit it's not always strictly continuous + return { + compatible: false, + warning: log.message.facetChannelShouldBeDiscrete(channel) + }; + } + return COMPATIBLE; + case 'x': + case 'y': + case 'color': + case 'text': + case 'detail': + case 'tooltip': + return COMPATIBLE; + case 'opacity': + case 'size': + case 'x2': + case 'y2': + if (isDiscrete(fieldDef) && !fieldDef.bin) { + return { + compatible: false, + warning: "Channel " + channel + " should not be used with discrete field." + }; + } + return COMPATIBLE; + case 'shape': + if (fieldDef.type !== 'nominal') { + return { + compatible: false, + warning: 'Shape channel should be used with nominal data only' + }; + } + return COMPATIBLE; + case 'order': + if (fieldDef.type === 'nominal') { + return { + compatible: false, + warning: "Channel order is inappropriate for nominal field, which has no inherent order." + }; + } + return COMPATIBLE; + } + throw new Error('channelCompatability not implemented for channel ' + channel); +} +exports.channelCompatibility = channelCompatibility; + +},{"./aggregate":54,"./bin":56,"./channel":57,"./log":62,"./timeunit":66,"./type":67,"./util":68,"tslib":53}],61:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.defaultLegendConfig = { + orient: undefined, +}; +exports.LEGEND_PROPERTIES = ['entryPadding', 'format', 'offset', 'orient', 'tickCount', 'title', 'type', 'values', 'zindex']; +exports.VG_LEGEND_PROPERTIES = [].concat(['fill', 'stroke', 'shape', 'size', 'opacity', 'encode'], exports.LEGEND_PROPERTIES); + +},{}],62:[function(require,module,exports){ +"use strict"; +/** + * Vega-Lite's singleton logger utility. + */ +Object.defineProperty(exports, "__esModule", { value: true }); +var vega_util_1 = require("vega-util"); +/** + * Main (default) Vega Logger instance for Vega-Lite + */ +var main = vega_util_1.logger(vega_util_1.Warn); +var current = main; +/** + * Logger tool for checking if the code throws correct warning + */ +var LocalLogger = (function () { + function LocalLogger() { + this.warns = []; + this.infos = []; + this.debugs = []; + } + LocalLogger.prototype.level = function () { + return this; + }; + LocalLogger.prototype.warn = function () { + var args = []; + for (var _i = 0; _i < arguments.length; _i++) { + args[_i] = arguments[_i]; + } + (_a = this.warns).push.apply(_a, args); + return this; + var _a; + }; + LocalLogger.prototype.info = function () { + var args = []; + for (var _i = 0; _i < arguments.length; _i++) { + args[_i] = arguments[_i]; + } + (_a = this.infos).push.apply(_a, args); + return this; + var _a; + }; + LocalLogger.prototype.debug = function () { + var args = []; + for (var _i = 0; _i < arguments.length; _i++) { + args[_i] = arguments[_i]; + } + (_a = this.debugs).push.apply(_a, args); + return this; + var _a; + }; + return LocalLogger; +}()); +exports.LocalLogger = LocalLogger; +function runLocalLogger(f) { + var localLogger = current = new LocalLogger(); + f(localLogger); + reset(); +} +exports.runLocalLogger = runLocalLogger; +function wrap(f) { + return function () { + var logger = current = new LocalLogger(); + f(logger); + reset(); + }; +} +exports.wrap = wrap; +/** + * Set the singleton logger to be a custom logger + */ +function set(logger) { + current = logger; + return current; +} +exports.set = set; +/** + * Reset the main logger to use the default Vega Logger + */ +function reset() { + current = main; + return current; +} +exports.reset = reset; +function warn() { + var _ = []; + for (var _i = 0; _i < arguments.length; _i++) { + _[_i] = arguments[_i]; + } + current.warn.apply(current, arguments); +} +exports.warn = warn; +function info() { + var _ = []; + for (var _i = 0; _i < arguments.length; _i++) { + _[_i] = arguments[_i]; + } + current.info.apply(current, arguments); +} +exports.info = info; +function debug() { + var _ = []; + for (var _i = 0; _i < arguments.length; _i++) { + _[_i] = arguments[_i]; + } + current.debug.apply(current, arguments); +} +exports.debug = debug; +/** + * Collection of all Vega-Lite Error Messages + */ +var message; +(function (message) { + message.INVALID_SPEC = 'Invalid spec'; + // SELECTION + function cannotProjectOnChannelWithoutField(channel) { + return "Cannot project a selection on encoding channel " + channel + ", which has no field."; + } + message.cannotProjectOnChannelWithoutField = cannotProjectOnChannelWithoutField; + function selectionNotFound(name) { + return "Cannot find a selection named \"" + name + "\""; + } + message.selectionNotFound = selectionNotFound; + // REPEAT + function noSuchRepeatedValue(field) { + return "Unknown repeated value \"" + field + "\"."; + } + message.noSuchRepeatedValue = noSuchRepeatedValue; + // DATA + function unrecognizedParse(p) { + return "Unrecognized parse " + p + "."; + } + message.unrecognizedParse = unrecognizedParse; + function differentParse(field, local, ancestor) { + return "An ancestor parsed field " + field + " as " + ancestor + " but a child wants to parse the field as " + local + "."; + } + message.differentParse = differentParse; + // TRANSFORMS + function invalidTransformIgnored(transform) { + return "Ignoring an invalid transform: " + JSON.stringify(transform) + "."; + } + message.invalidTransformIgnored = invalidTransformIgnored; + message.NO_FIELDS_NEEDS_AS = 'If `from.fields` is not specified, `as` has to be a string that specifies the key to be used for the the data from the secondary source.'; + // ENCODING & FACET + function invalidFieldType(type) { + return "Invalid field type \"" + type + "\""; + } + message.invalidFieldType = invalidFieldType; + function invalidFieldTypeForCountAggregate(type, aggregate) { + return "Invalid field type \"" + type + "\" for aggregate: \"" + aggregate + "\", using \"quantitative\" instead."; + } + message.invalidFieldTypeForCountAggregate = invalidFieldTypeForCountAggregate; + function invalidAggregate(aggregate) { + return "Invalid aggregation operator \"" + aggregate + "\""; + } + message.invalidAggregate = invalidAggregate; + function emptyOrInvalidFieldType(type, channel, newType) { + return "Invalid field type (" + type + ") for channel " + channel + ", using " + newType + " instead."; + } + message.emptyOrInvalidFieldType = emptyOrInvalidFieldType; + function emptyFieldDef(fieldDef, channel) { + return "Dropping " + JSON.stringify(fieldDef) + " from channel " + channel + " since it does not contain data field or value."; + } + message.emptyFieldDef = emptyFieldDef; + function incompatibleChannel(channel, markOrFacet, when) { + return channel + " dropped as it is incompatible with " + markOrFacet + (when ? " when " + when : '') + "."; + } + message.incompatibleChannel = incompatibleChannel; + function facetChannelShouldBeDiscrete(channel) { + return channel + " encoding should be discrete (ordinal / nominal / binned)."; + } + message.facetChannelShouldBeDiscrete = facetChannelShouldBeDiscrete; + function discreteChannelCannotEncode(channel, type) { + return "Using discrete channel " + channel + " to encode " + type + " field can be misleading as it does not encode " + (type === 'ordinal' ? 'order' : 'magnitude') + "."; + } + message.discreteChannelCannotEncode = discreteChannelCannotEncode; + // Mark + message.BAR_WITH_POINT_SCALE_AND_RANGESTEP_NULL = 'Bar mark should not be used with point scale when rangeStep is null. Please use band scale instead.'; + function unclearOrientContinuous(mark) { + return "Cannot clearly determine orientation for " + mark + " since both x and y channel encode continous fields. In this case, we use vertical by default"; + } + message.unclearOrientContinuous = unclearOrientContinuous; + function unclearOrientDiscreteOrEmpty(mark) { + return "Cannot clearly determine orientation for " + mark + " since both x and y channel encode discrete or empty fields."; + } + message.unclearOrientDiscreteOrEmpty = unclearOrientDiscreteOrEmpty; + function orientOverridden(original, actual) { + return "Specified orient " + original + " overridden with " + actual; + } + message.orientOverridden = orientOverridden; + // SCALE + message.CANNOT_UNION_CUSTOM_DOMAIN_WITH_FIELD_DOMAIN = 'custom domain scale cannot be unioned with default field-based domain'; + function cannotUseScalePropertyWithNonColor(prop) { + return "Cannot use " + prop + " with non-color channel."; + } + message.cannotUseScalePropertyWithNonColor = cannotUseScalePropertyWithNonColor; + function unaggregateDomainHasNoEffectForRawField(fieldDef) { + return "Using unaggregated domain with raw field has no effect (" + JSON.stringify(fieldDef) + ")."; + } + message.unaggregateDomainHasNoEffectForRawField = unaggregateDomainHasNoEffectForRawField; + function unaggregateDomainWithNonSharedDomainOp(aggregate) { + return "Unaggregated domain not applicable for " + aggregate + " since it produces values outside the origin domain of the source data."; + } + message.unaggregateDomainWithNonSharedDomainOp = unaggregateDomainWithNonSharedDomainOp; + function unaggregatedDomainWithLogScale(fieldDef) { + return "Unaggregated domain is currently unsupported for log scale (" + JSON.stringify(fieldDef) + ")."; + } + message.unaggregatedDomainWithLogScale = unaggregatedDomainWithLogScale; + message.CANNOT_USE_RANGE_WITH_POSITION = 'Cannot use custom range with x or y channel. Please customize width, height, padding, or rangeStep instead.'; + function cannotUseSizeFieldWithBandSize(positionChannel) { + return "Using size field when " + positionChannel + "-channel has a band scale is not supported."; + } + message.cannotUseSizeFieldWithBandSize = cannotUseSizeFieldWithBandSize; + function cannotApplySizeToNonOrientedMark(mark) { + return "Cannot apply size to non-oriented mark " + mark + "."; + } + message.cannotApplySizeToNonOrientedMark = cannotApplySizeToNonOrientedMark; + function rangeStepDropped(channel) { + return "rangeStep for " + channel + " is dropped as top-level " + (channel === 'x' ? 'width' : 'height') + " is provided."; + } + message.rangeStepDropped = rangeStepDropped; + function scaleTypeNotWorkWithChannel(channel, scaleType, defaultScaleType) { + return "Channel " + channel + " does not work with " + scaleType + " scale. We are using " + defaultScaleType + " scale instead."; + } + message.scaleTypeNotWorkWithChannel = scaleTypeNotWorkWithChannel; + function scaleTypeNotWorkWithFieldDef(scaleType, defaultScaleType) { + return "FieldDef does not work with " + scaleType + " scale. We are using " + defaultScaleType + " scale instead."; + } + message.scaleTypeNotWorkWithFieldDef = scaleTypeNotWorkWithFieldDef; + function scalePropertyNotWorkWithScaleType(scaleType, propName, channel) { + return channel + "-scale's \"" + propName + "\" is dropped as it does not work with " + scaleType + " scale."; + } + message.scalePropertyNotWorkWithScaleType = scalePropertyNotWorkWithScaleType; + function scaleTypeNotWorkWithMark(mark, scaleType) { + return "Scale type \"" + scaleType + "\" does not work with mark " + mark + "."; + } + message.scaleTypeNotWorkWithMark = scaleTypeNotWorkWithMark; + function mergeConflictingProperty(property, propertyOf, v1, v2) { + return "Conflicting " + propertyOf + " property " + property + " (" + v1 + " and " + v2 + "). Using " + v1 + "."; + } + message.mergeConflictingProperty = mergeConflictingProperty; + function independentScaleMeansIndependentGuide(channel) { + return "Setting the scale to be independent for " + channel + " means we also have to set the guide (axis or legend) to be independent."; + } + message.independentScaleMeansIndependentGuide = independentScaleMeansIndependentGuide; + function conflictedDomain(channel) { + return "Cannot set " + channel + "-scale's \"domain\" as it is binned. Please use \"bin\"'s \"extent\" instead."; + } + message.conflictedDomain = conflictedDomain; + message.INVAID_DOMAIN = 'Invalid scale domain'; + message.UNABLE_TO_MERGE_DOMAINS = 'Unable to merge domains'; + // AXIS + message.INVALID_CHANNEL_FOR_AXIS = 'Invalid channel for axis.'; + // STACK + function cannotStackRangedMark(channel) { + return "Cannot stack " + channel + " if there is already " + channel + "2"; + } + message.cannotStackRangedMark = cannotStackRangedMark; + function cannotStackNonLinearScale(scaleType) { + return "Cannot stack non-linear scale (" + scaleType + ")"; + } + message.cannotStackNonLinearScale = cannotStackNonLinearScale; + function cannotStackNonSummativeAggregate(aggregate) { + return "Cannot stack when the aggregate function is non-summative (" + aggregate + ")"; + } + message.cannotStackNonSummativeAggregate = cannotStackNonSummativeAggregate; + // TIMEUNIT + function invalidTimeUnit(unitName, value) { + return "Invalid " + unitName + ": " + value; + } + message.invalidTimeUnit = invalidTimeUnit; + function dayReplacedWithDate(fullTimeUnit) { + return "Time unit \"" + fullTimeUnit + "\" is not supported. We are replacing it with " + fullTimeUnit.replace('day', 'date') + "."; + } + message.dayReplacedWithDate = dayReplacedWithDate; + function droppedDay(d) { + return "Dropping day from datetime " + JSON.stringify(d) + " as day cannot be combined with other units."; + } + message.droppedDay = droppedDay; +})(message = exports.message || (exports.message = {})); + +},{"vega-util":69}],63:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +function isLogicalOr(op) { + return !!op.or; +} +exports.isLogicalOr = isLogicalOr; +function isLogicalAnd(op) { + return !!op.and; +} +exports.isLogicalAnd = isLogicalAnd; +function isLogicalNot(op) { + return !!op.not; +} +exports.isLogicalNot = isLogicalNot; + +},{}],64:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var util_1 = require("./util"); +var Mark; +(function (Mark) { + Mark.AREA = 'area'; + Mark.BAR = 'bar'; + Mark.LINE = 'line'; + Mark.POINT = 'point'; + Mark.RECT = 'rect'; + Mark.RULE = 'rule'; + Mark.TEXT = 'text'; + Mark.TICK = 'tick'; + Mark.CIRCLE = 'circle'; + Mark.SQUARE = 'square'; +})(Mark = exports.Mark || (exports.Mark = {})); +exports.AREA = Mark.AREA; +exports.BAR = Mark.BAR; +exports.LINE = Mark.LINE; +exports.POINT = Mark.POINT; +exports.TEXT = Mark.TEXT; +exports.TICK = Mark.TICK; +exports.RECT = Mark.RECT; +exports.RULE = Mark.RULE; +exports.CIRCLE = Mark.CIRCLE; +exports.SQUARE = Mark.SQUARE; +exports.PRIMITIVE_MARKS = [exports.AREA, exports.BAR, exports.LINE, exports.POINT, exports.TEXT, exports.TICK, exports.RECT, exports.RULE, exports.CIRCLE, exports.SQUARE]; +function isMarkDef(mark) { + return mark['type']; +} +exports.isMarkDef = isMarkDef; +var PRIMITIVE_MARK_INDEX = util_1.toSet(exports.PRIMITIVE_MARKS); +function isPrimitiveMark(mark) { + var markType = isMarkDef(mark) ? mark.type : mark; + return markType in PRIMITIVE_MARK_INDEX; +} +exports.isPrimitiveMark = isPrimitiveMark; +exports.STROKE_CONFIG = ['stroke', 'strokeWidth', + 'strokeDash', 'strokeDashOffset', 'strokeOpacity']; +exports.FILL_CONFIG = ['fill', 'fillOpacity']; +exports.FILL_STROKE_CONFIG = [].concat(exports.STROKE_CONFIG, exports.FILL_CONFIG); +exports.VL_ONLY_MARK_CONFIG_PROPERTIES = ['filled', 'color']; +exports.VL_ONLY_MARK_SPECIFIC_CONFIG_PROPERTY_INDEX = { + bar: ['binSpacing', 'continuousBandSize', 'discreteBandSize'], + text: ['shortTimeLabels'], + tick: ['bandSize', 'thickness'] +}; +exports.defaultMarkConfig = { + color: '#4c78a8', +}; +exports.defaultBarConfig = { + binSpacing: 1, + continuousBandSize: 2 +}; +exports.defaultTickConfig = { + thickness: 1 +}; + +},{"./util":68}],65:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var log = require("./log"); +var util_1 = require("./util"); +var ScaleType; +(function (ScaleType) { + // Continuous - Quantitative + ScaleType.LINEAR = 'linear'; + ScaleType.BIN_LINEAR = 'bin-linear'; + ScaleType.LOG = 'log'; + ScaleType.POW = 'pow'; + ScaleType.SQRT = 'sqrt'; + // Continuous - Time + ScaleType.TIME = 'time'; + ScaleType.UTC = 'utc'; + // sequential + ScaleType.SEQUENTIAL = 'sequential'; + // Quantile, Quantize, threshold + ScaleType.QUANTILE = 'quantile'; + ScaleType.QUANTIZE = 'quantize'; + ScaleType.THRESHOLD = 'threshold'; + ScaleType.ORDINAL = 'ordinal'; + ScaleType.BIN_ORDINAL = 'bin-ordinal'; + ScaleType.POINT = 'point'; + ScaleType.BAND = 'band'; +})(ScaleType = exports.ScaleType || (exports.ScaleType = {})); +exports.SCALE_TYPES = [ + // Continuous - Quantitative + 'linear', 'bin-linear', 'log', 'pow', 'sqrt', + // Continuous - Time + 'time', 'utc', + // Sequential + 'sequential', + // Discrete + 'ordinal', 'bin-ordinal', 'point', 'band', +]; +/** + * Index for scale categories -- only scale of the same categories can be merged together. + * Current implementation is trying to be conservative and avoid merging scale type that might not work together + */ +var SCALE_CATEGORY_INDEX = { + linear: 'numeric', + log: 'numeric', + pow: 'numeric', + sqrt: 'numeric', + 'bin-linear': 'bin-linear', + time: 'time', + utc: 'time', + sequential: 'sequential', + ordinal: 'ordinal', + 'bin-ordinal': 'bin-ordinal', + point: 'ordinal-position', + band: 'ordinal-position' +}; +function getScaleCategory(scaleType) { + return SCALE_CATEGORY_INDEX[scaleType]; +} +exports.getScaleCategory = getScaleCategory; +/** + * Whether the two given scale types can be merged together. + */ +function scaleCompatible(scaleType1, scaleType2) { + return SCALE_CATEGORY_INDEX[scaleType1] === SCALE_CATEGORY_INDEX[scaleType2]; +} +exports.scaleCompatible = scaleCompatible; +/** + * Index for scale predecence -- high score = higher priority for merging. + */ +var SCALE_PRECEDENCE_INDEX = { + // numeric + linear: 0, + log: 1, + pow: 1, + sqrt: 1, + // time + time: 0, + utc: 0, + // ordinal-position + point: 0, + band: 1, + // non grouped types + 'bin-linear': 0, + sequential: 0, + ordinal: 0, + 'bin-ordinal': 0, +}; +/** + * Return scale categories -- only scale of the same categories can be merged together. + */ +function scaleTypePrecedence(scaleType) { + return SCALE_PRECEDENCE_INDEX[scaleType]; +} +exports.scaleTypePrecedence = scaleTypePrecedence; +exports.CONTINUOUS_TO_CONTINUOUS_SCALES = ['linear', 'bin-linear', 'log', 'pow', 'sqrt', 'time', 'utc']; +var CONTINUOUS_TO_CONTINUOUS_INDEX = util_1.toSet(exports.CONTINUOUS_TO_CONTINUOUS_SCALES); +exports.CONTINUOUS_DOMAIN_SCALES = exports.CONTINUOUS_TO_CONTINUOUS_SCALES.concat(['sequential' /* TODO add 'quantile', 'quantize', 'threshold'*/]); +var CONTINUOUS_DOMAIN_INDEX = util_1.toSet(exports.CONTINUOUS_DOMAIN_SCALES); +exports.DISCRETE_DOMAIN_SCALES = ['ordinal', 'bin-ordinal', 'point', 'band']; +var DISCRETE_DOMAIN_INDEX = util_1.toSet(exports.DISCRETE_DOMAIN_SCALES); +var BIN_SCALES_INDEX = util_1.toSet(['bin-linear', 'bin-ordinal']); +exports.TIME_SCALE_TYPES = ['time', 'utc']; +function hasDiscreteDomain(type) { + return type in DISCRETE_DOMAIN_INDEX; +} +exports.hasDiscreteDomain = hasDiscreteDomain; +function isBinScale(type) { + return type in BIN_SCALES_INDEX; +} +exports.isBinScale = isBinScale; +function hasContinuousDomain(type) { + return type in CONTINUOUS_DOMAIN_INDEX; +} +exports.hasContinuousDomain = hasContinuousDomain; +function isContinuousToContinuous(type) { + return type in CONTINUOUS_TO_CONTINUOUS_INDEX; +} +exports.isContinuousToContinuous = isContinuousToContinuous; +exports.defaultScaleConfig = { + round: true, + textXRangeStep: 90, + rangeStep: 21, + pointPadding: 0.5, + bandPaddingInner: 0.1, + facetSpacing: 16, + minFontSize: 8, + maxFontSize: 40, + minOpacity: 0.3, + maxOpacity: 0.8, + // FIXME: revise if these *can* become ratios of rangeStep + minSize: 9, + minStrokeWidth: 1, + maxStrokeWidth: 4, + shapes: ['circle', 'square', 'cross', 'diamond', 'triangle-up', 'triangle-down'] +}; +function isExtendedScheme(scheme) { + return scheme && !!scheme['name']; +} +exports.isExtendedScheme = isExtendedScheme; +function isSelectionDomain(domain) { + return domain && domain['selection']; +} +exports.isSelectionDomain = isSelectionDomain; +exports.NON_TYPE_DOMAIN_RANGE_VEGA_SCALE_PROPERTIES = [ + 'reverse', 'round', + // quantitative / time + 'clamp', 'nice', + // quantitative + 'exponent', 'interpolate', 'zero', + // ordinal + 'padding', 'paddingInner', 'paddingOuter', +]; +exports.SCALE_PROPERTIES = [].concat([ + 'type', 'domain', + 'range', 'rangeStep', 'scheme' +], exports.NON_TYPE_DOMAIN_RANGE_VEGA_SCALE_PROPERTIES); +function scaleTypeSupportProperty(scaleType, propName) { + switch (propName) { + case 'type': + case 'domain': + case 'reverse': + case 'range': + case 'scheme': + return true; + case 'interpolate': + return util_1.contains(['linear', 'bin-linear', 'pow', 'log', 'sqrt', 'utc', 'time'], scaleType); + case 'round': + return isContinuousToContinuous(scaleType) || scaleType === 'band' || scaleType === 'point'; + case 'rangeStep': + case 'padding': + case 'paddingOuter': + return util_1.contains(['point', 'band'], scaleType); + case 'paddingInner': + return scaleType === 'band'; + case 'clamp': + return isContinuousToContinuous(scaleType) || scaleType === 'sequential'; + case 'nice': + return isContinuousToContinuous(scaleType) || scaleType === 'sequential' || scaleType === 'quantize'; + case 'exponent': + return scaleType === 'pow' || scaleType === 'log'; + case 'zero': + // TODO: what about quantize, threshold? + return scaleType === 'bin-ordinal' || (!hasDiscreteDomain(scaleType) && !util_1.contains(['log', 'time', 'utc', 'bin-linear'], scaleType)); + } + /* istanbul ignore next: should never reach here*/ + throw new Error("Invalid scale property " + propName + "."); +} +exports.scaleTypeSupportProperty = scaleTypeSupportProperty; +/** + * Returns undefined if the input channel supports the input scale property name + */ +function channelScalePropertyIncompatability(channel, propName) { + switch (propName) { + case 'range': + // User should not customize range for position and facet channel directly. + if (channel === 'x' || channel === 'y') { + return log.message.CANNOT_USE_RANGE_WITH_POSITION; + } + return undefined; // GOOD! + case 'interpolate': + case 'scheme': + if (channel !== 'color') { + return log.message.cannotUseScalePropertyWithNonColor(channel); + } + return undefined; + case 'type': + case 'domain': + case 'exponent': + case 'nice': + case 'padding': + case 'paddingInner': + case 'paddingOuter': + case 'rangeStep': + case 'reverse': + case 'round': + case 'clamp': + case 'zero': + return undefined; // GOOD! + } + /* istanbul ignore next: it should never reach here */ + throw new Error('Invalid scale property "${propName}".'); +} +exports.channelScalePropertyIncompatability = channelScalePropertyIncompatability; + +},{"./log":62,"./util":68}],66:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var datetime_1 = require("./datetime"); +var log = require("./log"); +var util_1 = require("./util"); +var TimeUnit; +(function (TimeUnit) { + TimeUnit.YEAR = 'year'; + TimeUnit.MONTH = 'month'; + TimeUnit.DAY = 'day'; + TimeUnit.DATE = 'date'; + TimeUnit.HOURS = 'hours'; + TimeUnit.MINUTES = 'minutes'; + TimeUnit.SECONDS = 'seconds'; + TimeUnit.MILLISECONDS = 'milliseconds'; + TimeUnit.YEARMONTH = 'yearmonth'; + TimeUnit.YEARMONTHDATE = 'yearmonthdate'; + TimeUnit.YEARMONTHDATEHOURS = 'yearmonthdatehours'; + TimeUnit.YEARMONTHDATEHOURSMINUTES = 'yearmonthdatehoursminutes'; + TimeUnit.YEARMONTHDATEHOURSMINUTESSECONDS = 'yearmonthdatehoursminutesseconds'; + // MONTHDATE always include 29 February since we use year 0th (which is a leap year); + TimeUnit.MONTHDATE = 'monthdate'; + TimeUnit.HOURSMINUTES = 'hoursminutes'; + TimeUnit.HOURSMINUTESSECONDS = 'hoursminutesseconds'; + TimeUnit.MINUTESSECONDS = 'minutesseconds'; + TimeUnit.SECONDSMILLISECONDS = 'secondsmilliseconds'; + TimeUnit.QUARTER = 'quarter'; + TimeUnit.YEARQUARTER = 'yearquarter'; + TimeUnit.QUARTERMONTH = 'quartermonth'; + TimeUnit.YEARQUARTERMONTH = 'yearquartermonth'; + TimeUnit.UTCYEAR = 'utcyear'; + TimeUnit.UTCMONTH = 'utcmonth'; + TimeUnit.UTCDAY = 'utcday'; + TimeUnit.UTCDATE = 'utcdate'; + TimeUnit.UTCHOURS = 'utchours'; + TimeUnit.UTCMINUTES = 'utcminutes'; + TimeUnit.UTCSECONDS = 'utcseconds'; + TimeUnit.UTCMILLISECONDS = 'utcmilliseconds'; + TimeUnit.UTCYEARMONTH = 'utcyearmonth'; + TimeUnit.UTCYEARMONTHDATE = 'utcyearmonthdate'; + TimeUnit.UTCYEARMONTHDATEHOURS = 'utcyearmonthdatehours'; + TimeUnit.UTCYEARMONTHDATEHOURSMINUTES = 'utcyearmonthdatehoursminutes'; + TimeUnit.UTCYEARMONTHDATEHOURSMINUTESSECONDS = 'utcyearmonthdatehoursminutesseconds'; + // MONTHDATE always include 29 February since we use year 0th (which is a leap year); + TimeUnit.UTCMONTHDATE = 'utcmonthdate'; + TimeUnit.UTCHOURSMINUTES = 'utchoursminutes'; + TimeUnit.UTCHOURSMINUTESSECONDS = 'utchoursminutesseconds'; + TimeUnit.UTCMINUTESSECONDS = 'utcminutesseconds'; + TimeUnit.UTCSECONDSMILLISECONDS = 'utcsecondsmilliseconds'; + TimeUnit.UTCQUARTER = 'utcquarter'; + TimeUnit.UTCYEARQUARTER = 'utcyearquarter'; + TimeUnit.UTCQUARTERMONTH = 'utcquartermonth'; + TimeUnit.UTCYEARQUARTERMONTH = 'utcyearquartermonth'; +})(TimeUnit = exports.TimeUnit || (exports.TimeUnit = {})); +/** Time Unit that only corresponds to only one part of Date objects. */ +exports.SINGLE_TIMEUNITS = [ + TimeUnit.YEAR, + TimeUnit.QUARTER, + TimeUnit.MONTH, + TimeUnit.DAY, + TimeUnit.DATE, + TimeUnit.HOURS, + TimeUnit.MINUTES, + TimeUnit.SECONDS, + TimeUnit.MILLISECONDS +]; +var SINGLE_TIMEUNIT_INDEX = exports.SINGLE_TIMEUNITS.reduce(function (d, timeUnit) { + d[timeUnit] = true; + return d; +}, {}); +function isSingleTimeUnit(timeUnit) { + return !!SINGLE_TIMEUNIT_INDEX[timeUnit]; +} +exports.isSingleTimeUnit = isSingleTimeUnit; +/** + * Converts a date to only have the measurements relevant to the specified unit + * i.e. ('yearmonth', '2000-12-04 07:58:14') -> '2000-12-01 00:00:00' + * Note: the base date is Jan 01 1900 00:00:00 + */ +function convert(unit, date) { + var result = new Date(0, 0, 1, 0, 0, 0, 0); // start with uniform date + exports.SINGLE_TIMEUNITS.forEach(function (singleUnit) { + if (containsTimeUnit(unit, singleUnit)) { + switch (singleUnit) { + case TimeUnit.DAY: + throw new Error('Cannot convert to TimeUnits containing \'day\''); + case TimeUnit.YEAR: + result.setFullYear(date.getFullYear()); + break; + case TimeUnit.QUARTER: + // indicate quarter by setting month to be the first of the quarter i.e. may (4) -> april (3) + result.setMonth((Math.floor(date.getMonth() / 3)) * 3); + break; + case TimeUnit.MONTH: + result.setMonth(date.getMonth()); + break; + case TimeUnit.DATE: + result.setDate(date.getDate()); + break; + case TimeUnit.HOURS: + result.setHours(date.getHours()); + break; + case TimeUnit.MINUTES: + result.setMinutes(date.getMinutes()); + break; + case TimeUnit.SECONDS: + result.setSeconds(date.getSeconds()); + break; + case TimeUnit.MILLISECONDS: + result.setMilliseconds(date.getMilliseconds()); + break; + } + } + }); + return result; +} +exports.convert = convert; +exports.MULTI_TIMEUNITS = [ + TimeUnit.YEARQUARTER, + TimeUnit.YEARQUARTERMONTH, + TimeUnit.YEARMONTH, + TimeUnit.YEARMONTHDATE, + TimeUnit.YEARMONTHDATEHOURS, + TimeUnit.YEARMONTHDATEHOURSMINUTES, + TimeUnit.YEARMONTHDATEHOURSMINUTESSECONDS, + TimeUnit.QUARTERMONTH, + TimeUnit.HOURSMINUTES, + TimeUnit.HOURSMINUTESSECONDS, + TimeUnit.MINUTESSECONDS, + TimeUnit.SECONDSMILLISECONDS, +]; +var MULTI_TIMEUNIT_INDEX = exports.MULTI_TIMEUNITS.reduce(function (d, timeUnit) { + d[timeUnit] = true; + return d; +}, {}); +function isMultiTimeUnit(timeUnit) { + return !!MULTI_TIMEUNIT_INDEX[timeUnit]; +} +exports.isMultiTimeUnit = isMultiTimeUnit; +exports.TIMEUNITS = [ + TimeUnit.YEAR, + TimeUnit.QUARTER, + TimeUnit.MONTH, + TimeUnit.DAY, + TimeUnit.DATE, + TimeUnit.HOURS, + TimeUnit.MINUTES, + TimeUnit.SECONDS, + TimeUnit.MILLISECONDS, + TimeUnit.YEARQUARTER, + TimeUnit.YEARQUARTERMONTH, + TimeUnit.YEARMONTH, + TimeUnit.YEARMONTHDATE, + TimeUnit.YEARMONTHDATEHOURS, + TimeUnit.YEARMONTHDATEHOURSMINUTES, + TimeUnit.YEARMONTHDATEHOURSMINUTESSECONDS, + TimeUnit.QUARTERMONTH, + TimeUnit.HOURSMINUTES, + TimeUnit.HOURSMINUTESSECONDS, + TimeUnit.MINUTESSECONDS, + TimeUnit.SECONDSMILLISECONDS, +]; +/** Returns true if fullTimeUnit contains the timeUnit, false otherwise. */ +function containsTimeUnit(fullTimeUnit, timeUnit) { + var index = fullTimeUnit.indexOf(timeUnit); + return index > -1 && + (timeUnit !== TimeUnit.SECONDS || + index === 0 || + fullTimeUnit.charAt(index - 1) !== 'i' // exclude milliseconds + ); +} +exports.containsTimeUnit = containsTimeUnit; +/** + * Returns Vega expresssion for a given timeUnit and fieldRef + */ +function fieldExpr(fullTimeUnit, field) { + var fieldRef = "datum[" + util_1.stringValue(field) + "]"; + var utc = isUTCTimeUnit(fullTimeUnit) ? 'utc' : ''; + function func(timeUnit) { + if (timeUnit === TimeUnit.QUARTER) { + // quarter starting at 0 (0,3,6,9). + return "(" + utc + "quarter(" + fieldRef + ")-1)"; + } + else { + return "" + utc + timeUnit + "(" + fieldRef + ")"; + } + } + var d = exports.SINGLE_TIMEUNITS.reduce(function (dateExpr, tu) { + if (containsTimeUnit(fullTimeUnit, tu)) { + dateExpr[tu] = func(tu); + } + return dateExpr; + }, {}); + if (d.day && util_1.keys(d).length > 1) { + log.warn(log.message.dayReplacedWithDate(fullTimeUnit)); + delete d.day; + d.date = func(TimeUnit.DATE); + } + return datetime_1.dateTimeExpr(d); +} +exports.fieldExpr = fieldExpr; +/** returns the smallest nice unit for scale.nice */ +function smallestUnit(timeUnit) { + if (!timeUnit) { + return undefined; + } + if (containsTimeUnit(timeUnit, TimeUnit.SECONDS)) { + return 'second'; + } + if (containsTimeUnit(timeUnit, TimeUnit.MINUTES)) { + return 'minute'; + } + if (containsTimeUnit(timeUnit, TimeUnit.HOURS)) { + return 'hour'; + } + if (containsTimeUnit(timeUnit, TimeUnit.DAY) || + containsTimeUnit(timeUnit, TimeUnit.DATE)) { + return 'day'; + } + if (containsTimeUnit(timeUnit, TimeUnit.MONTH)) { + return 'month'; + } + if (containsTimeUnit(timeUnit, TimeUnit.YEAR)) { + return 'year'; + } + return undefined; +} +exports.smallestUnit = smallestUnit; +/** + * returns the signal expression used for axis labels for a time unit + */ +function formatExpression(timeUnit, field, shortTimeLabels, isUTCScale) { + if (!timeUnit) { + return undefined; + } + var dateComponents = []; + var expression = ''; + var hasYear = containsTimeUnit(timeUnit, TimeUnit.YEAR); + if (containsTimeUnit(timeUnit, TimeUnit.QUARTER)) { + // special expression for quarter as prefix + expression = "'Q' + quarter(" + field + ")"; + } + if (containsTimeUnit(timeUnit, TimeUnit.MONTH)) { + // By default use short month name + dateComponents.push(shortTimeLabels !== false ? '%b' : '%B'); + } + if (containsTimeUnit(timeUnit, TimeUnit.DAY)) { + dateComponents.push(shortTimeLabels ? '%a' : '%A'); + } + else if (containsTimeUnit(timeUnit, TimeUnit.DATE)) { + dateComponents.push('%d' + (hasYear ? ',' : '')); // add comma if there is year + } + if (hasYear) { + dateComponents.push(shortTimeLabels ? '%y' : '%Y'); + } + var timeComponents = []; + if (containsTimeUnit(timeUnit, TimeUnit.HOURS)) { + timeComponents.push('%H'); + } + if (containsTimeUnit(timeUnit, TimeUnit.MINUTES)) { + timeComponents.push('%M'); + } + if (containsTimeUnit(timeUnit, TimeUnit.SECONDS)) { + timeComponents.push('%S'); + } + if (containsTimeUnit(timeUnit, TimeUnit.MILLISECONDS)) { + timeComponents.push('%L'); + } + var dateTimeComponents = []; + if (dateComponents.length > 0) { + dateTimeComponents.push(dateComponents.join(' ')); + } + if (timeComponents.length > 0) { + dateTimeComponents.push(timeComponents.join(':')); + } + if (dateTimeComponents.length > 0) { + if (expression) { + // Add space between quarter and main time format + expression += " + ' ' + "; + } + if (isUTCScale) { + expression += "utcFormat(" + field + ", '" + dateTimeComponents.join(' ') + "')"; + } + else { + expression += "timeFormat(" + field + ", '" + dateTimeComponents.join(' ') + "')"; + } + } + // If expression is still an empty string, return undefined instead. + return expression || undefined; +} +exports.formatExpression = formatExpression; +function isDiscreteByDefault(timeUnit) { + switch (timeUnit) { + // These time unit use discrete scale by default + case 'hours': + case 'day': + case 'month': + case 'quarter': + return true; + } + return false; +} +exports.isDiscreteByDefault = isDiscreteByDefault; +function isUTCTimeUnit(timeUnit) { + return timeUnit.substr(0, 3) === 'utc'; +} + +},{"./datetime":59,"./log":62,"./util":68}],67:[function(require,module,exports){ +"use strict"; +/** Constants and utilities for data type */ +/** Data type based on level of measurement */ +Object.defineProperty(exports, "__esModule", { value: true }); +var Type; +(function (Type) { + Type.QUANTITATIVE = 'quantitative'; + Type.ORDINAL = 'ordinal'; + Type.TEMPORAL = 'temporal'; + Type.NOMINAL = 'nominal'; +})(Type = exports.Type || (exports.Type = {})); +exports.QUANTITATIVE = Type.QUANTITATIVE; +exports.ORDINAL = Type.ORDINAL; +exports.TEMPORAL = Type.TEMPORAL; +exports.NOMINAL = Type.NOMINAL; +/** + * Get full, lowercase type name for a given type. + * @param type + * @return Full type name. + */ +function getFullName(type) { + if (type) { + type = type.toLowerCase(); + switch (type) { + case 'q': + case exports.QUANTITATIVE: + return 'quantitative'; + case 't': + case exports.TEMPORAL: + return 'temporal'; + case 'o': + case exports.ORDINAL: + return 'ordinal'; + case 'n': + case exports.NOMINAL: + return 'nominal'; + } + } + // If we get invalid input, return undefined type. + return undefined; +} +exports.getFullName = getFullName; + +},{}],68:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var stringify = require("json-stable-stringify"); +var vega_util_1 = require("vega-util"); +var logical_1 = require("./logical"); +var vega_util_2 = require("vega-util"); +exports.extend = vega_util_2.extend; +exports.isArray = vega_util_2.isArray; +exports.isObject = vega_util_2.isObject; +exports.isNumber = vega_util_2.isNumber; +exports.isString = vega_util_2.isString; +exports.truncate = vega_util_2.truncate; +exports.toSet = vega_util_2.toSet; +exports.stringValue = vega_util_2.stringValue; +/** + * Creates an object composed of the picked object properties. + * + * Example: (from lodash) + * + * var object = {'a': 1, 'b': '2', 'c': 3}; + * pick(object, ['a', 'c']); + * // → {'a': 1, 'c': 3} + * + */ +function pick(obj, props) { + var copy = {}; + props.forEach(function (prop) { + if (obj.hasOwnProperty(prop)) { + copy[prop] = obj[prop]; + } + }); + return copy; +} +exports.pick = pick; +/** + * The opposite of _.pick; this method creates an object composed of the own + * and inherited enumerable string keyed properties of object that are not omitted. + */ +function omit(obj, props) { + var copy = duplicate(obj); + props.forEach(function (prop) { + delete copy[prop]; + }); + return copy; +} +exports.omit = omit; +function hash(a) { + if (vega_util_1.isString(a) || vega_util_1.isNumber(a) || isBoolean(a)) { + return String(a); + } + return stringify(a); +} +exports.hash = hash; +function contains(array, item) { + return array.indexOf(item) > -1; +} +exports.contains = contains; +/** Returns the array without the elements in item */ +function without(array, excludedItems) { + return array.filter(function (item) { return !contains(excludedItems, item); }); +} +exports.without = without; +function union(array, other) { + return array.concat(without(other, array)); +} +exports.union = union; +/** + * Returns true if any item returns true. + */ +function some(arr, f) { + var i = 0; + for (var k = 0; k < arr.length; k++) { + if (f(arr[k], k, i++)) { + return true; + } + } + return false; +} +exports.some = some; +/** + * Returns true if all items return true. + */ +function every(arr, f) { + var i = 0; + for (var k = 0; k < arr.length; k++) { + if (!f(arr[k], k, i++)) { + return false; + } + } + return true; +} +exports.every = every; +function flatten(arrays) { + return [].concat.apply([], arrays); +} +exports.flatten = flatten; +/** + * recursively merges src into dest + */ +function mergeDeep(dest) { + var src = []; + for (var _i = 1; _i < arguments.length; _i++) { + src[_i - 1] = arguments[_i]; + } + for (var _a = 0, src_1 = src; _a < src_1.length; _a++) { + var s = src_1[_a]; + dest = deepMerge_(dest, s); + } + return dest; +} +exports.mergeDeep = mergeDeep; +// recursively merges src into dest +function deepMerge_(dest, src) { + if (typeof src !== 'object' || src === null) { + return dest; + } + for (var p in src) { + if (!src.hasOwnProperty(p)) { + continue; + } + if (src[p] === undefined) { + continue; + } + if (typeof src[p] !== 'object' || vega_util_1.isArray(src[p]) || src[p] === null) { + dest[p] = src[p]; + } + else if (typeof dest[p] !== 'object' || dest[p] === null) { + dest[p] = mergeDeep(vega_util_1.isArray(src[p].constructor) ? [] : {}, src[p]); + } + else { + mergeDeep(dest[p], src[p]); + } + } + return dest; +} +function unique(values, f) { + var results = []; + var u = {}; + var v; + for (var _i = 0, values_1 = values; _i < values_1.length; _i++) { + var val = values_1[_i]; + v = f(val); + if (v in u) { + continue; + } + u[v] = 1; + results.push(val); + } + return results; +} +exports.unique = unique; +/** + * Returns true if the two dictionaries disagree. Applies only to defined values. + */ +function differ(dict, other) { + for (var key in dict) { + if (dict.hasOwnProperty(key)) { + if (other[key] && dict[key] && other[key] !== dict[key]) { + return true; + } + } + } + return false; +} +exports.differ = differ; +function hasIntersection(a, b) { + for (var key in a) { + if (key in b) { + return true; + } + } + return false; +} +exports.hasIntersection = hasIntersection; +function differArray(array, other) { + if (array.length !== other.length) { + return true; + } + array.sort(); + other.sort(); + for (var i = 0; i < array.length; i++) { + if (other[i] !== array[i]) { + return true; + } + } + return false; +} +exports.differArray = differArray; +exports.keys = Object.keys; +function vals(x) { + var _vals = []; + for (var k in x) { + if (x.hasOwnProperty(k)) { + _vals.push(x[k]); + } + } + return _vals; +} +exports.vals = vals; +function duplicate(obj) { + return JSON.parse(JSON.stringify(obj)); +} +exports.duplicate = duplicate; +function isBoolean(b) { + return b === true || b === false; +} +exports.isBoolean = isBoolean; +/** + * Convert a string into a valid variable name + */ +function varName(s) { + // Replace non-alphanumeric characters (anything besides a-zA-Z0-9_) with _ + var alphanumericS = s.replace(/\W/g, '_'); + // Add _ if the string has leading numbers. + return (s.match(/^\d+/) ? '_' : '') + alphanumericS; +} +exports.varName = varName; +function logicalExpr(op, cb) { + if (logical_1.isLogicalNot(op)) { + return '!(' + logicalExpr(op.not, cb) + ')'; + } + else if (logical_1.isLogicalAnd(op)) { + return '(' + op.and.map(function (and) { return logicalExpr(and, cb); }).join(') && (') + ')'; + } + else if (logical_1.isLogicalOr(op)) { + return '(' + op.or.map(function (or) { return logicalExpr(or, cb); }).join(') || (') + ')'; + } + else { + return cb(op); + } +} +exports.logicalExpr = logicalExpr; + +},{"./logical":63,"json-stable-stringify":49,"vega-util":69}],69:[function(require,module,exports){ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : + typeof define === 'function' && define.amd ? define(['exports'], factory) : + (factory((global.vega = global.vega || {}))); +}(this, (function (exports) { 'use strict'; + +var accessor = function(fn, fields, name) { + fn.fields = fields || []; + fn.fname = name; + return fn; +}; + +function accessorName(fn) { + return fn == null ? null : fn.fname; +} + +function accessorFields(fn) { + return fn == null ? null : fn.fields; +} + +var error = function(message) { + throw Error(message); +}; + +var splitAccessPath = function(p) { + var path = [], + q = null, + b = 0, + n = p.length, + s = '', + i, j, c; + + p = p + ''; + + function push() { + path.push(s + p.substring(i, j)); + s = ''; + i = j + 1; + } + + for (i=j=0; j i) { + push(); + } else { + i = j + 1; + } + } else if (c === '[') { + if (j > i) push(); + b = i = j + 1; + } else if (c === ']') { + if (!b) error('Access path missing open bracket: ' + p); + if (b > 0) push(); + b = 0; + i = j + 1; + } + } + + if (b) error('Access path missing closing bracket: ' + p); + if (q) error('Access path missing closing quote: ' + p); + + if (j > i) { + j++; + push(); + } + + return path; +}; + +var isArray = Array.isArray; + +var isObject = function(_) { + return _ === Object(_); +}; + +var isString = function(_) { + return typeof _ === 'string'; +}; + +function $(x) { + return isArray(x) ? '[' + x.map($) + ']' + : isObject(x) || isString(x) ? + // Output valid JSON and JS source strings. + // See http://timelessrepo.com/json-isnt-a-javascript-subset + JSON.stringify(x).replace('\u2028','\\u2028').replace('\u2029', '\\u2029') + : x; +} + +var field = function(field, name) { + var path = splitAccessPath(field), + code = 'return _[' + path.map($).join('][') + '];'; + + return accessor( + Function('_', code), + [(field = path.length===1 ? path[0] : field)], + name || field + ); +}; + +var empty = []; + +var id = field('id'); + +var identity = accessor(function(_) { return _; }, empty, 'identity'); + +var zero = accessor(function() { return 0; }, empty, 'zero'); + +var one = accessor(function() { return 1; }, empty, 'one'); + +var truthy = accessor(function() { return true; }, empty, 'true'); + +var falsy = accessor(function() { return false; }, empty, 'false'); + +function log(method, level, input) { + var args = [level].concat([].slice.call(input)); + console[method].apply(console, args); // eslint-disable-line no-console +} + +var None = 0; +var Error$1 = 1; +var Warn = 2; +var Info = 3; +var Debug = 4; + +var logger = function(_) { + var level = _ || None; + return { + level: function(_) { + if (arguments.length) { + level = +_; + return this; + } else { + return level; + } + }, + error: function() { + if (level >= Error$1) log('error', 'ERROR', arguments); + return this; + }, + warn: function() { + if (level >= Warn) log('warn', 'WARN', arguments); + return this; + }, + info: function() { + if (level >= Info) log('log', 'INFO', arguments); + return this; + }, + debug: function() { + if (level >= Debug) log('log', 'DEBUG', arguments); + return this; + } + } +}; + +var array = function(_) { + return _ != null ? (isArray(_) ? _ : [_]) : []; +}; + +var compare = function(fields, orders) { + var idx = [], + cmp = (fields = array(fields)).map(function(f, i) { + if (f == null) { + return null; + } else { + idx.push(i); + return splitAccessPath(f).map($).join(']['); + } + }), + n = idx.length - 1, + ord = array(orders), + code = 'var u,v;return ', + i, j, f, u, v, d, lt, gt; + + if (n < 0) return null; + + for (j=0; j<=n; ++j) { + i = idx[j]; + f = cmp[i]; + u = '(u=a['+f+'])'; + v = '(v=b['+f+'])'; + d = '((v=v instanceof Date?+v:v),(u=u instanceof Date?+u:u))'; + if (ord[i] !== 'descending') { + gt = 1; + lt = -1; + } else { + gt = -1; + lt = 1; + } + code += '(' + u+'<'+v+'||u==null)&&v!=null?' + lt + + ':(u>v||v==null)&&u!=null?' + gt + + ':'+d+'!==u&&v===v?' + lt + + ':v!==v&&u===u?' + gt + + (i < n ? ':' : ':0'); + } + + return accessor( + Function('a', 'b', code + ';'), + fields.filter(function(_) { return _ != null; }) + ); +}; + +var isFunction = function(_) { + return typeof _ === 'function'; +}; + +var constant = function(_) { + return isFunction(_) ? _ : function() { return _; }; +}; + +var debounce = function(delay, handler) { + var tid, evt; + + function callback() { + handler(evt); + tid = evt = null; + } + + return function(e) { + evt = e; + if (tid) clearTimeout(tid); + tid = setTimeout(callback, delay); + }; +}; + +var extend = function(_) { + for (var x, k, i=1, len=arguments.length; i= b) { + a = c = b; + break; + } + } + u = v = i; + while (++i < n) { + b = array[i]; + if (b != null) { + if (a > b) { + a = b; + u = i; + } + if (c < b) { + c = b; + v = i; + } + } + } + } else { + while (++i < n) { + b = f(array[i], i, array); + if (b != null && b >= b) { + a = c = b; + break; + } + } + u = v = i; + while (++i < n) { + b = f(array[i], i, array); + if (b != null) { + if (a > b) { + a = b; + u = i; + } + if (c < b) { + c = b; + v = i; + } + } + } + } + + return [u, v]; +}; + +var NULL = {}; + +var fastmap = function(input) { + var obj = {}, + map, + test; + + function has(key) { + return obj.hasOwnProperty(key) && obj[key] !== NULL; + } + + map = { + size: 0, + empty: 0, + object: obj, + has: has, + get: function(key) { + return has(key) ? obj[key] : undefined; + }, + set: function(key, value) { + if (!has(key)) { + ++map.size; + if (obj[key] === NULL) --map.empty; + } + obj[key] = value; + return this; + }, + delete: function(key) { + if (has(key)) { + --map.size; + ++map.empty; + obj[key] = NULL; + } + return this; + }, + clear: function() { + map.size = map.empty = 0; + map.object = obj = {}; + }, + test: function(_) { + if (arguments.length) { + test = _; + return map; + } else { + return test; + } + }, + clean: function() { + var next = {}, + size = 0, + key, value; + for (key in obj) { + value = obj[key]; + if (value !== NULL && (!test || !test(value))) { + next[key] = value; + ++size; + } + } + map.size = size; + map.empty = 0; + map.object = (obj = next); + } + }; + + if (input) Object.keys(input).forEach(function(key) { + map.set(key, input[key]); + }); + + return map; +}; + +var inherits = function(child, parent) { + var proto = (child.prototype = Object.create(parent.prototype)); + proto.constructor = child; + return proto; +}; + +var isBoolean = function(_) { + return typeof _ === 'boolean'; +}; + +var isDate = function(_) { + return Object.prototype.toString.call(_) === '[object Date]'; +}; + +var isNumber = function(_) { + return typeof _ === 'number'; +}; + +var isRegExp = function(_) { + return Object.prototype.toString.call(_) === '[object RegExp]'; +}; + +var key = function(fields) { + fields = fields ? array(fields) : fields; + var fn = !(fields && fields.length) + ? function() { return ''; } + : Function('_', 'return \'\'+' + + fields.map(function(f) { + return '_[' + splitAccessPath(f).map($).join('][') + ']'; + }).join('+\'|\'+') + ';'); + return accessor(fn, fields, 'key'); +}; + +var merge = function(compare, array0, array1, output) { + var n0 = array0.length, + n1 = array1.length; + + if (!n1) return array0; + if (!n0) return array1; + + var merged = output || new array0.constructor(n0 + n1), + i0 = 0, i1 = 0, i = 0; + + for (; i0 0 + ? array1[i1++] + : array0[i0++]; + } + + for (; i0= 0) s += str; + return s; +}; + +var pad = function(str, length, padchar, align) { + var c = padchar || ' ', + s = str + '', + n = length - s.length; + + return n <= 0 ? s + : align === 'left' ? repeat(c, n) + s + : align === 'center' ? repeat(c, ~~(n/2)) + s + repeat(c, Math.ceil(n/2)) + : s + repeat(c, n); +}; + +var peek = function(array) { + return array[array.length - 1]; +}; + +var toBoolean = function(_) { + return _ == null || _ === '' ? null : !_ || _ === 'false' || _ === '0' ? false : !!_; +}; + +function defaultParser(_) { + return isNumber(_) ? _ : isDate(_) ? _ : Date.parse(_); +} + +var toDate = function(_, parser) { + parser = parser || defaultParser; + return _ == null || _ === '' ? null : parser(_); +}; + +var toNumber = function(_) { + return _ == null || _ === '' ? null : +_; +}; + +var toString = function(_) { + return _ == null || _ === '' ? null : _ + ''; +}; + +var toSet = function(_) { + for (var s={}, i=0, n=_.length; i= opt.minCardinalityForBin;\n }\n return true;\n }\n }, {\n name: 'binAppliedForQuantitative',\n description: 'bin should be applied to quantitative field only.',\n properties: [property_1.Property.TYPE, property_1.Property.BIN],\n allowWildcardForProperties: false,\n strict: true,\n satisfy: function (fieldQ, _, __, ___) {\n if (fieldQ.bin) {\n // If binned, the type must be quantitative\n return fieldQ.type === type_1.Type.QUANTITATIVE;\n }\n return true;\n }\n }, {\n name: 'channelFieldCompatible',\n description: \"encoding channel's range type be compatible with channel type.\",\n properties: [property_1.Property.CHANNEL, property_1.Property.TYPE, property_1.Property.BIN, property_1.Property.TIMEUNIT],\n allowWildcardForProperties: false,\n strict: true,\n satisfy: function (fieldQ, _, encWildcardIndex, opt) {\n var fieldDef = __assign({ field: 'f' }, encoding_1.toFieldDef(fieldQ, ['bin', 'timeUnit', 'type']));\n return fielddef_1.channelCompatibility(fieldDef, fieldQ.channel).compatible;\n }\n }, {\n name: 'hasFn',\n description: 'A field with as hasFn flag should have one of aggregate, timeUnit, or bin.',\n properties: [property_1.Property.AGGREGATE, property_1.Property.BIN, property_1.Property.TIMEUNIT],\n allowWildcardForProperties: true,\n strict: true,\n satisfy: function (fieldQ, _, __, ___) {\n if (fieldQ.hasFn) {\n return !!fieldQ.aggregate || !!fieldQ.bin || !!fieldQ.timeUnit;\n }\n return true;\n }\n }, {\n name: 'omitScaleZeroWithBinnedField',\n description: 'Do not use scale zero with binned field',\n properties: [property_1.Property.SCALE, property_1.getEncodingNestedProp('scale', 'zero'), property_1.Property.BIN],\n allowWildcardForProperties: false,\n strict: true,\n satisfy: function (fieldQ, _, __, ___) {\n if (fieldQ.bin && fieldQ.scale) {\n if (fieldQ.scale.zero === true) {\n return false;\n }\n }\n return true;\n }\n }, {\n name: 'onlyOneTypeOfFunction',\n description: 'Only of of aggregate, autoCount, timeUnit, or bin should be applied at the same time.',\n properties: [property_1.Property.AGGREGATE, property_1.Property.AUTOCOUNT, property_1.Property.TIMEUNIT, property_1.Property.BIN],\n allowWildcardForProperties: true,\n strict: true,\n satisfy: function (fieldQ, _, __, ___) {\n if (encoding_1.isFieldQuery(fieldQ)) {\n var numFn = (!wildcard_1.isWildcard(fieldQ.aggregate) && !!fieldQ.aggregate ? 1 : 0) +\n (!wildcard_1.isWildcard(fieldQ.bin) && !!fieldQ.bin ? 1 : 0) +\n (!wildcard_1.isWildcard(fieldQ.timeUnit) && !!fieldQ.timeUnit ? 1 : 0);\n return numFn <= 1;\n }\n // For autoCount there is always only one type of function\n return true;\n }\n }, {\n name: 'timeUnitAppliedForTemporal',\n description: 'Time unit should be applied to temporal field only.',\n properties: [property_1.Property.TYPE, property_1.Property.TIMEUNIT],\n allowWildcardForProperties: false,\n strict: true,\n satisfy: function (fieldQ, _, __, ___) {\n if (fieldQ.timeUnit && fieldQ.type !== type_1.Type.TEMPORAL) {\n return false;\n }\n return true;\n }\n }, {\n name: 'timeUnitShouldHaveVariation',\n description: 'A particular time unit should be applied only if they produce unique values.',\n properties: [property_1.Property.TIMEUNIT, property_1.Property.TYPE],\n allowWildcardForProperties: false,\n strict: false,\n satisfy: function (fieldQ, schema, encWildcardIndex, opt) {\n if (fieldQ.timeUnit && fieldQ.type === type_1.Type.TEMPORAL) {\n if (!encWildcardIndex.has('timeUnit') && !opt.constraintManuallySpecifiedValue) {\n // Do not have to check this as this is manually specified by users.\n return true;\n }\n return schema.timeUnitHasVariation(fieldQ);\n }\n return true;\n }\n }, {\n name: 'scalePropertiesSupportedByScaleType',\n description: 'Scale properties must be supported by correct scale type',\n properties: [].concat(property_1.SCALE_PROPS, [property_1.Property.SCALE, property_1.Property.TYPE]),\n allowWildcardForProperties: true,\n strict: true,\n satisfy: function (fieldQ, _, __, ___) {\n if (fieldQ.scale) {\n var scale = fieldQ.scale;\n // If fieldQ.type is an Wildcard and scale.type is undefined, it is equivalent\n // to scale type is Wildcard. If scale type is an Wildcard, we do not yet know\n // what the scale type is, and thus can ignore the constraint.\n var sType = encoding_1.scaleType(fieldQ);\n if (sType === undefined || sType === null) {\n // If still ambiguous, doesn't check the constraint\n return true;\n }\n for (var scaleProp in scale) {\n if (scaleProp === 'type' || scaleProp === 'name' || scaleProp === 'enum') {\n // ignore type and properties of wildcards\n continue;\n }\n var sProp = scaleProp;\n if (sType === 'point') {\n // HACK: our current implementation of scaleType() can return point\n // when the scaleType is a band since we didn't pass all parameter to Vega-Lite's scale type method.\n if (!scale_1.scaleTypeSupportProperty('point', sProp) && !scale_1.scaleTypeSupportProperty('band', sProp)) {\n return false;\n }\n }\n else if (!scale_1.scaleTypeSupportProperty(sType, sProp)) {\n return false;\n }\n }\n }\n return true;\n }\n }, {\n name: 'scalePropertiesSupportedByChannel',\n description: 'Not all scale properties are supported by all encoding channels',\n properties: [].concat(property_1.SCALE_PROPS, [property_1.Property.SCALE, property_1.Property.CHANNEL]),\n allowWildcardForProperties: true,\n strict: true,\n satisfy: function (fieldQ, _, __, ___) {\n if (fieldQ) {\n var channel = fieldQ.channel;\n var scale = fieldQ.scale;\n if (channel && !wildcard_1.isWildcard(channel) && scale) {\n if (channel === 'row' || channel === 'column') {\n // row / column do not have scale\n return false;\n }\n for (var scaleProp in scale) {\n if (!scale.hasOwnProperty(scaleProp))\n continue;\n if (scaleProp === 'type' || scaleProp === 'name' || scaleProp === 'enum') {\n // ignore type and properties of wildcards\n continue;\n }\n var isSupported = scale_1.channelScalePropertyIncompatability(channel, scaleProp) === undefined;\n if (!isSupported) {\n return false;\n }\n }\n }\n }\n return true;\n }\n }, {\n name: 'typeMatchesPrimitiveType',\n description: 'Data type should be supported by field\\'s primitive type.',\n properties: [property_1.Property.FIELD, property_1.Property.TYPE],\n allowWildcardForProperties: false,\n strict: true,\n satisfy: function (fieldQ, schema, encWildcardIndex, opt) {\n if (fieldQ.field === '*') {\n return true;\n }\n var primitiveType = schema.primitiveType(fieldQ.field);\n var type = fieldQ.type;\n if (!encWildcardIndex.has('field') && !encWildcardIndex.has('type') && !opt.constraintManuallySpecifiedValue) {\n // Do not have to check this as this is manually specified by users.\n return true;\n }\n switch (primitiveType) {\n case schema_1.PrimitiveType.BOOLEAN:\n case schema_1.PrimitiveType.STRING:\n return type !== type_1.Type.QUANTITATIVE && type !== type_1.Type.TEMPORAL;\n case schema_1.PrimitiveType.NUMBER:\n case schema_1.PrimitiveType.INTEGER:\n return type !== type_1.Type.TEMPORAL;\n case schema_1.PrimitiveType.DATETIME:\n // TODO: add NOMINAL, ORDINAL support after we support this in Vega-Lite\n return type === type_1.Type.TEMPORAL;\n case null:\n // field does not exist in the schema\n return false;\n }\n throw new Error('Not implemented');\n }\n },\n {\n name: 'typeMatchesSchemaType',\n description: 'Enumerated data type of a field should match the field\\'s type in the schema.',\n properties: [property_1.Property.FIELD, property_1.Property.TYPE],\n allowWildcardForProperties: false,\n strict: false,\n satisfy: function (fieldQ, schema, encWildcardIndex, opt) {\n if (!encWildcardIndex.has('field') && !encWildcardIndex.has('type') && !opt.constraintManuallySpecifiedValue) {\n // Do not have to check this as this is manually specified by users.\n return true;\n }\n if (fieldQ.field === '*') {\n return fieldQ.type === type_1.Type.QUANTITATIVE;\n }\n return schema.vlType(fieldQ.field) === fieldQ.type;\n }\n }, {\n name: 'maxCardinalityForCategoricalColor',\n description: 'Categorical channel should not have too high cardinality',\n properties: [property_1.Property.CHANNEL, property_1.Property.FIELD],\n allowWildcardForProperties: false,\n strict: false,\n satisfy: function (fieldQ, schema, _, opt) {\n // TODO: missing case where ordinal / temporal use categorical color\n // (once we do so, need to add Property.BIN, Property.TIMEUNIT)\n if (fieldQ.channel === channel_1.Channel.COLOR && (fieldQ.type === type_1.Type.NOMINAL || fieldQ.type === expandedtype_1.ExpandedType.KEY)) {\n return schema.cardinality(fieldQ) <= opt.maxCardinalityForCategoricalColor;\n }\n return true; // other channel is irrelevant to this constraint\n }\n }, {\n name: 'maxCardinalityForFacet',\n description: 'Row/column channel should not have too high cardinality',\n properties: [property_1.Property.CHANNEL, property_1.Property.FIELD, property_1.Property.BIN, property_1.Property.TIMEUNIT],\n allowWildcardForProperties: false,\n strict: false,\n satisfy: function (fieldQ, schema, _, opt) {\n if (fieldQ.channel === channel_1.Channel.ROW || fieldQ.channel === channel_1.Channel.COLUMN) {\n return schema.cardinality(fieldQ) <= opt.maxCardinalityForFacet;\n }\n return true; // other channel is irrelevant to this constraint\n }\n }, {\n name: 'maxCardinalityForShape',\n description: 'Shape channel should not have too high cardinality',\n properties: [property_1.Property.CHANNEL, property_1.Property.FIELD, property_1.Property.BIN, property_1.Property.TIMEUNIT],\n allowWildcardForProperties: false,\n strict: false,\n satisfy: function (fieldQ, schema, _, opt) {\n if (fieldQ.channel === channel_1.Channel.SHAPE) {\n return schema.cardinality(fieldQ) <= opt.maxCardinalityForShape;\n }\n return true; // other channel is irrelevant to this constraint\n }\n },\n {\n name: 'dataTypeAndFunctionMatchScaleType',\n description: 'Scale type must match data type',\n properties: [property_1.Property.TYPE, property_1.Property.SCALE, property_1.getEncodingNestedProp('scale', 'type'), property_1.Property.TIMEUNIT, property_1.Property.BIN],\n allowWildcardForProperties: false,\n strict: true,\n satisfy: function (fieldQ, _, __, ___) {\n if (fieldQ.scale) {\n var type = fieldQ.type;\n var sType = encoding_1.scaleType(fieldQ);\n if (expandedtype_1.isDiscrete(type)) {\n return sType === undefined || scale_1.hasDiscreteDomain(sType);\n }\n else if (type === type_1.Type.TEMPORAL) {\n if (!fieldQ.timeUnit) {\n return util_1.contains([scale_1.ScaleType.TIME, scale_1.ScaleType.UTC, undefined], sType);\n }\n else {\n return util_1.contains([scale_1.ScaleType.TIME, scale_1.ScaleType.UTC, undefined], sType) || scale_1.hasDiscreteDomain(sType);\n }\n }\n else if (type === type_1.Type.QUANTITATIVE) {\n if (fieldQ.bin) {\n return util_1.contains([scale_1.ScaleType.LINEAR, undefined], sType);\n }\n else {\n return util_1.contains([scale_1.ScaleType.LOG, scale_1.ScaleType.POW, scale_1.ScaleType.SQRT, scale_1.ScaleType.QUANTILE, scale_1.ScaleType.QUANTIZE, scale_1.ScaleType.LINEAR, undefined], sType);\n }\n }\n }\n return true;\n }\n }\n].map(function (ec) { return new base_1.EncodingConstraintModel(ec); });\nexports.FIELD_CONSTRAINT_INDEX = exports.FIELD_CONSTRAINTS.reduce(function (m, ec) {\n m[ec.name()] = ec;\n return m;\n}, {});\nexports.FIELD_CONSTRAINTS_BY_PROPERTY = exports.FIELD_CONSTRAINTS.reduce(function (index, c) {\n for (var _i = 0, _a = c.properties(); _i < _a.length; _i++) {\n var prop = _a[_i];\n // Initialize array and use it\n index.set(prop, index.get(prop) || []);\n index.get(prop).push(c);\n }\n return index;\n}, new propindex_1.PropIndex());\n//# sourceMappingURL=field.js.map", + "\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nvar encoding = require(\"./encoding\");\nexports.encoding = encoding;\nvar spec = require(\"./spec\");\nexports.spec = spec;\n//# sourceMappingURL=index.js.map", + "\"use strict\";\nvar __extends = (this && this.__extends) || (function () {\n var extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nObject.defineProperty(exports, \"__esModule\", { value: true });\nvar aggregate_1 = require(\"vega-lite/build/src/aggregate\");\nvar channel_1 = require(\"vega-lite/build/src/channel\");\nvar mark_1 = require(\"vega-lite/build/src/mark\");\nvar scale_1 = require(\"vega-lite/build/src/scale\");\nvar type_1 = require(\"vega-lite/build/src/type\");\nvar expandedtype_1 = require(\"../query/expandedtype\");\nvar base_1 = require(\"./base\");\nvar wildcard_1 = require(\"../wildcard\");\nvar property_1 = require(\"../property\");\nvar propindex_1 = require(\"../propindex\");\nvar util_1 = require(\"../util\");\nvar encoding_1 = require(\"../query/encoding\");\nvar NONSPATIAL_CHANNELS_INDEX = channel_1.NONSPATIAL_CHANNELS.reduce(function (m, channel) {\n m[channel] = true;\n return m;\n}, {});\nvar SpecConstraintModel = (function (_super) {\n __extends(SpecConstraintModel, _super);\n function SpecConstraintModel(specConstraint) {\n return _super.call(this, specConstraint) || this;\n }\n SpecConstraintModel.prototype.hasAllRequiredPropertiesSpecific = function (specM) {\n return util_1.every(this.constraint.properties, function (prop) {\n if (prop === property_1.Property.MARK) {\n return !wildcard_1.isWildcard(specM.getMark());\n }\n // TODO: transform\n if (property_1.isEncodingNestedProp(prop)) {\n var parent_1 = prop.parent;\n var child_1 = prop.child;\n return util_1.every(specM.getEncodings(), function (encQ) {\n if (!encQ[parent_1]) {\n return true;\n }\n return !wildcard_1.isWildcard(encQ[parent_1][child_1]);\n });\n }\n if (!property_1.isEncodingProperty(prop)) {\n throw new Error('UNIMPLEMENTED');\n }\n return util_1.every(specM.getEncodings(), function (encQ) {\n if (!encQ[prop]) {\n return true;\n }\n return !wildcard_1.isWildcard(encQ[prop]);\n });\n });\n };\n SpecConstraintModel.prototype.satisfy = function (specM, schema, opt) {\n // TODO: Re-order logic to optimize the \"allowWildcardForProperties\" check\n if (!this.constraint.allowWildcardForProperties) {\n if (!this.hasAllRequiredPropertiesSpecific(specM)) {\n return true;\n }\n }\n return this.constraint.satisfy(specM, schema, opt);\n };\n return SpecConstraintModel;\n}(base_1.AbstractConstraintModel));\nexports.SpecConstraintModel = SpecConstraintModel;\nexports.SPEC_CONSTRAINTS = [\n {\n name: 'noRepeatedChannel',\n description: 'Each encoding channel should only be used once.',\n properties: [property_1.Property.CHANNEL],\n allowWildcardForProperties: true,\n strict: true,\n satisfy: function (specM, _, __) {\n var usedChannel = {};\n // channel for all encodings should be valid\n return util_1.every(specM.getEncodings(), function (encQ) {\n if (!wildcard_1.isWildcard(encQ.channel)) {\n // If channel is specified, it should no be used already\n if (usedChannel[encQ.channel]) {\n return false;\n }\n usedChannel[encQ.channel] = true;\n return true;\n }\n return true; // unspecified channel is valid\n });\n }\n },\n {\n name: 'alwaysIncludeZeroInScaleWithBarMark',\n description: 'Do not recommend bar mark if scale does not start at zero',\n properties: [property_1.Property.MARK, property_1.Property.SCALE, property_1.getEncodingNestedProp('scale', 'zero'), property_1.Property.CHANNEL, property_1.Property.TYPE],\n allowWildcardForProperties: false,\n strict: true,\n satisfy: function (specM, _, __) {\n var mark = specM.getMark();\n var encodings = specM.getEncodings();\n if (mark === mark_1.Mark.BAR) {\n for (var _i = 0, encodings_1 = encodings; _i < encodings_1.length; _i++) {\n var encQ = encodings_1[_i];\n if (encoding_1.isFieldQuery(encQ) &&\n (encQ.channel === channel_1.Channel.X || encQ.channel === channel_1.Channel.Y) &&\n (encQ.type === type_1.Type.QUANTITATIVE) &&\n (encQ.scale && encQ.scale.zero === false)) {\n // TODO: zero shouldn't be manually specified\n return false;\n }\n }\n }\n return true;\n }\n },\n {\n name: 'autoAddCount',\n description: 'Automatically adding count only for plots with only ordinal, binned quantitative, or temporal with timeunit fields.',\n properties: [property_1.Property.BIN, property_1.Property.TIMEUNIT, property_1.Property.TYPE, property_1.Property.AUTOCOUNT],\n allowWildcardForProperties: true,\n strict: false,\n satisfy: function (specM, _, __) {\n var hasAutoCount = util_1.some(specM.getEncodings(), function (encQ) { return encoding_1.isEnabledAutoCountQuery(encQ); });\n if (hasAutoCount) {\n // Auto count should only be applied if all fields are nominal, ordinal, temporal with timeUnit, binned quantitative, or autoCount\n return util_1.every(specM.getEncodings(), function (encQ) {\n if (encoding_1.isValueQuery(encQ)) {\n return false;\n }\n if (encoding_1.isAutoCountQuery(encQ)) {\n return true;\n }\n switch (encQ.type) {\n case type_1.Type.QUANTITATIVE:\n return !!encQ.bin;\n case type_1.Type.TEMPORAL:\n return !!encQ.timeUnit;\n case type_1.Type.ORDINAL:\n case expandedtype_1.ExpandedType.KEY:\n case type_1.Type.NOMINAL:\n return true;\n }\n /* istanbul ignore next */\n throw new Error('Unsupported Type');\n });\n }\n else {\n var autoCountEncIndex = specM.wildcardIndex.encodingIndicesByProperty.get('autoCount') || [];\n var neverHaveAutoCount = util_1.every(autoCountEncIndex, function (index) {\n var encQ = specM.getEncodingQueryByIndex(index);\n return encoding_1.isAutoCountQuery(encQ) && !wildcard_1.isWildcard(encQ.autoCount);\n });\n if (neverHaveAutoCount) {\n // If the query surely does not have autoCount\n // then one of the field should be\n // (1) unbinned quantitative\n // (2) temporal without time unit\n // (3) nominal or ordinal field\n // or at least have potential to be (still ambiguous).\n return util_1.some(specM.getEncodings(), function (encQ) {\n if ((encoding_1.isFieldQuery(encQ) || encoding_1.isAutoCountQuery(encQ)) && encQ.type === type_1.Type.QUANTITATIVE) {\n if (encoding_1.isDisabledAutoCountQuery(encQ)) {\n return false;\n }\n else {\n return encoding_1.isFieldQuery(encQ) && (!encQ.bin || wildcard_1.isWildcard(encQ.bin));\n }\n }\n else if (encoding_1.isFieldQuery(encQ) && encQ.type === type_1.Type.TEMPORAL) {\n return !encQ.timeUnit || wildcard_1.isWildcard(encQ.timeUnit);\n }\n return false; // nominal or ordinal\n });\n }\n }\n return true; // no auto count, no constraint\n }\n },\n {\n name: 'channelPermittedByMarkType',\n description: 'Each encoding channel should be supported by the mark type',\n properties: [property_1.Property.CHANNEL, property_1.Property.MARK],\n allowWildcardForProperties: true,\n strict: true,\n satisfy: function (specM, _, __) {\n var mark = specM.getMark();\n // if mark is unspecified, no need to check\n if (wildcard_1.isWildcard(mark))\n return true;\n // TODO: can optimize this to detect only what's the changed property if needed.\n return util_1.every(specM.getEncodings(), function (encQ) {\n // channel unspecified, no need to check\n if (wildcard_1.isWildcard(encQ.channel))\n return true;\n return channel_1.supportMark(encQ.channel, mark);\n });\n }\n },\n {\n name: 'hasAllRequiredChannelsForMark',\n description: 'All required channels for the specified mark should be specified',\n properties: [property_1.Property.CHANNEL, property_1.Property.MARK],\n allowWildcardForProperties: false,\n strict: true,\n satisfy: function (specM, _, __) {\n var mark = specM.getMark();\n switch (mark) {\n case mark_1.Mark.AREA:\n case mark_1.Mark.LINE:\n return specM.channelUsed(channel_1.Channel.X) && specM.channelUsed(channel_1.Channel.Y);\n case mark_1.Mark.TEXT:\n return specM.channelUsed(channel_1.Channel.TEXT);\n case mark_1.Mark.BAR:\n case mark_1.Mark.CIRCLE:\n case mark_1.Mark.SQUARE:\n case mark_1.Mark.TICK:\n case mark_1.Mark.RULE:\n return specM.channelUsed(channel_1.Channel.X) || specM.channelUsed(channel_1.Channel.Y);\n case mark_1.Mark.POINT:\n // This allows generating a point plot if channel was not a wildcard.\n return !specM.wildcardIndex.hasProperty(property_1.Property.CHANNEL) ||\n specM.channelUsed(channel_1.Channel.X) || specM.channelUsed(channel_1.Channel.Y);\n }\n /* istanbul ignore next */\n throw new Error('hasAllRequiredChannelsForMark not implemented for mark' + JSON.stringify(mark));\n }\n },\n {\n name: 'omitAggregate',\n description: 'Omit aggregate plots.',\n properties: [property_1.Property.AGGREGATE, property_1.Property.AUTOCOUNT],\n allowWildcardForProperties: true,\n strict: false,\n satisfy: function (specM, _, __) {\n if (specM.isAggregate()) {\n return false;\n }\n return true;\n }\n },\n {\n name: 'omitAggregatePlotWithDimensionOnlyOnFacet',\n description: 'Omit aggregate plots with dimensions only on facets as that leads to inefficient use of space.',\n properties: [property_1.Property.CHANNEL, property_1.Property.AGGREGATE, property_1.Property.AUTOCOUNT],\n allowWildcardForProperties: false,\n strict: false,\n satisfy: function (specM, _, opt) {\n if (specM.isAggregate()) {\n var hasNonFacetDim_1 = false, hasDim_1 = false, hasEnumeratedFacetDim_1 = false;\n specM.specQuery.encodings.forEach(function (encQ, index) {\n if (encoding_1.isValueQuery(encQ) || (encoding_1.isDisabledAutoCountQuery(encQ)))\n return; // skip unused field\n // FieldQuery & !encQ.aggregate\n if (encoding_1.isFieldQuery(encQ) && !encQ.aggregate) {\n hasDim_1 = true;\n if (util_1.contains([channel_1.Channel.ROW, channel_1.Channel.COLUMN], encQ.channel)) {\n if (specM.wildcardIndex.hasEncodingProperty(index, property_1.Property.CHANNEL)) {\n hasEnumeratedFacetDim_1 = true;\n }\n }\n else {\n hasNonFacetDim_1 = true;\n }\n }\n });\n if (hasDim_1 && !hasNonFacetDim_1) {\n if (hasEnumeratedFacetDim_1 || opt.constraintManuallySpecifiedValue) {\n return false;\n }\n }\n }\n return true;\n }\n },\n {\n name: 'omitAggregatePlotWithoutDimension',\n description: 'Aggregate plots without dimension should be omitted',\n properties: [property_1.Property.AGGREGATE, property_1.Property.AUTOCOUNT, property_1.Property.BIN, property_1.Property.TIMEUNIT, property_1.Property.TYPE],\n allowWildcardForProperties: false,\n strict: false,\n satisfy: function (specM, _, __) {\n if (specM.isAggregate()) {\n // TODO relax\n return util_1.some(specM.getEncodings(), function (encQ) {\n if (encoding_1.isDiscrete(encQ)) {\n return true;\n }\n return false;\n });\n }\n return true;\n }\n },\n {\n // TODO: we can be smarter and check if bar has occlusion based on profiling statistics\n name: 'omitBarLineAreaWithOcclusion',\n description: 'Don\\'t use bar, line or area to visualize raw plot as they often lead to occlusion.',\n properties: [property_1.Property.MARK, property_1.Property.AGGREGATE, property_1.Property.AUTOCOUNT],\n allowWildcardForProperties: false,\n strict: false,\n satisfy: function (specM, _, __) {\n if (util_1.contains([mark_1.Mark.BAR, mark_1.Mark.LINE, mark_1.Mark.AREA], specM.getMark())) {\n return specM.isAggregate();\n }\n return true;\n }\n },\n {\n name: 'omitBarTickWithSize',\n description: 'Do not map field to size channel with bar and tick mark',\n properties: [property_1.Property.CHANNEL, property_1.Property.MARK],\n allowWildcardForProperties: true,\n strict: false,\n satisfy: function (specM, _, opt) {\n var mark = specM.getMark();\n if (util_1.contains([mark_1.Mark.TICK, mark_1.Mark.BAR], mark)) {\n if (specM.channelUsed(channel_1.Channel.SIZE)) {\n if (opt.constraintManuallySpecifiedValue) {\n // If size is used and we constraintManuallySpecifiedValue,\n // then the spec violates this constraint.\n return false;\n }\n else {\n // Otherwise have to search for the size channel and check if it is enumerated\n var encodings = specM.specQuery.encodings;\n for (var i = 0; i < encodings.length; i++) {\n var encQ = encodings[i];\n if (encQ.channel === channel_1.Channel.SIZE) {\n if (specM.wildcardIndex.hasEncodingProperty(i, property_1.Property.CHANNEL)) {\n // If enumerated, then this is bad\n return false;\n }\n else {\n // If it's manually specified, no need to continue searching, just return.\n return true;\n }\n }\n }\n }\n }\n }\n return true; // skip\n }\n },\n {\n name: 'omitBarAreaForLogScale',\n description: 'Do not use bar and area mark for x and y\\'s log scale',\n properties: [property_1.Property.MARK, property_1.Property.CHANNEL, property_1.Property.SCALE, property_1.getEncodingNestedProp('scale', 'type'), property_1.Property.TYPE],\n allowWildcardForProperties: false,\n strict: true,\n satisfy: function (specM, _, __) {\n var mark = specM.getMark();\n var encodings = specM.getEncodings();\n // TODO: mark or scale type should be enumerated\n if (mark === mark_1.Mark.AREA || mark === mark_1.Mark.BAR) {\n for (var _i = 0, encodings_2 = encodings; _i < encodings_2.length; _i++) {\n var encQ = encodings_2[_i];\n if (encoding_1.isFieldQuery(encQ) && ((encQ.channel === channel_1.Channel.X || encQ.channel === channel_1.Channel.Y) && encQ.scale)) {\n var sType = encoding_1.scaleType(encQ);\n if (sType === scale_1.ScaleType.LOG) {\n return false;\n }\n }\n }\n }\n return true;\n }\n },\n {\n name: 'omitMultipleNonPositionalChannels',\n description: 'Unless manually specified, do not use multiple non-positional encoding channel to avoid over-encoding.',\n properties: [property_1.Property.CHANNEL],\n allowWildcardForProperties: true,\n strict: false,\n satisfy: function (specM, _, opt) {\n // have to use specM.specQuery.encodings insetad of specM.getEncodings()\n // since specM.getEncodings() remove encQ with autoCount===false from the array\n // and thus might shift the index\n var encodings = specM.specQuery.encodings;\n var nonPositionChannelCount = 0;\n var hasEnumeratedNonPositionChannel = false;\n for (var i = 0; i < encodings.length; i++) {\n var encQ = encodings[i];\n if (encoding_1.isValueQuery(encQ) || (encoding_1.isDisabledAutoCountQuery(encQ))) {\n continue; // ignore skipped encoding\n }\n var channel = encQ.channel;\n if (!wildcard_1.isWildcard(channel)) {\n if (NONSPATIAL_CHANNELS_INDEX[channel + '']) {\n nonPositionChannelCount += 1;\n if (specM.wildcardIndex.hasEncodingProperty(i, property_1.Property.CHANNEL)) {\n hasEnumeratedNonPositionChannel = true;\n }\n if (nonPositionChannelCount > 1 &&\n (hasEnumeratedNonPositionChannel || opt.constraintManuallySpecifiedValue)) {\n return false;\n }\n }\n }\n }\n return true;\n }\n },\n {\n name: 'omitNonPositionalOrFacetOverPositionalChannels',\n description: 'Do not use non-positional channels unless all positional channels are used',\n properties: [property_1.Property.CHANNEL],\n allowWildcardForProperties: false,\n strict: false,\n satisfy: function (specM, _, opt) {\n var encodings = specM.specQuery.encodings;\n var hasNonPositionalChannelOrFacet = false;\n var hasEnumeratedNonPositionOrFacetChannel = false;\n var hasX = false, hasY = false;\n for (var i = 0; i < encodings.length; i++) {\n var encQ = encodings[i];\n if (encoding_1.isValueQuery(encQ) || (encoding_1.isDisabledAutoCountQuery(encQ))) {\n continue; // ignore skipped encoding\n }\n var channel = encQ.channel;\n if (channel === channel_1.Channel.X) {\n hasX = true;\n }\n else if (channel === channel_1.Channel.Y) {\n hasY = true;\n }\n else if (!wildcard_1.isWildcard(channel)) {\n // All non positional channel / Facet\n hasNonPositionalChannelOrFacet = true;\n if (specM.wildcardIndex.hasEncodingProperty(i, property_1.Property.CHANNEL)) {\n hasEnumeratedNonPositionOrFacetChannel = true;\n }\n }\n }\n if (hasEnumeratedNonPositionOrFacetChannel ||\n (opt.constraintManuallySpecifiedValue && hasNonPositionalChannelOrFacet)) {\n return hasX && hasY;\n }\n return true;\n }\n },\n {\n name: 'omitRaw',\n description: 'Omit raw plots.',\n properties: [property_1.Property.AGGREGATE, property_1.Property.AUTOCOUNT],\n allowWildcardForProperties: false,\n strict: false,\n satisfy: function (specM, _, __) {\n if (!specM.isAggregate()) {\n return false;\n }\n return true;\n }\n },\n {\n name: 'omitRawContinuousFieldForAggregatePlot',\n description: 'Aggregate plot should not use raw continuous field as group by values. ' +\n '(Quantitative should be binned. Temporal should have time unit.)',\n properties: [property_1.Property.AGGREGATE, property_1.Property.AUTOCOUNT, property_1.Property.TIMEUNIT, property_1.Property.BIN, property_1.Property.TYPE],\n allowWildcardForProperties: true,\n strict: false,\n satisfy: function (specM, _, opt) {\n if (specM.isAggregate()) {\n var encodings = specM.specQuery.encodings;\n for (var i = 0; i < encodings.length; i++) {\n var encQ = encodings[i];\n if (encoding_1.isValueQuery(encQ) || (encoding_1.isDisabledAutoCountQuery(encQ)))\n continue; // skip unused encoding\n // TODO: aggregate for ordinal and temporal\n if (encoding_1.isFieldQuery(encQ) && encQ.type === type_1.Type.TEMPORAL) {\n // Temporal fields should have timeUnit or is still a wildcard\n if (!encQ.timeUnit && (specM.wildcardIndex.hasEncodingProperty(i, property_1.Property.TIMEUNIT) ||\n opt.constraintManuallySpecifiedValue)) {\n return false;\n }\n }\n if (encQ.type === type_1.Type.QUANTITATIVE) {\n if (encoding_1.isFieldQuery(encQ) && !encQ.bin && !encQ.aggregate) {\n // If Raw Q\n if (specM.wildcardIndex.hasEncodingProperty(i, property_1.Property.BIN) ||\n specM.wildcardIndex.hasEncodingProperty(i, property_1.Property.AGGREGATE) ||\n specM.wildcardIndex.hasEncodingProperty(i, property_1.Property.AUTOCOUNT)) {\n // and it's raw from enumeration\n return false;\n }\n if (opt.constraintManuallySpecifiedValue) {\n // or if we constraintManuallySpecifiedValue\n return false;\n }\n }\n }\n }\n }\n return true;\n }\n },\n {\n name: 'omitRawDetail',\n description: 'Do not use detail channel with raw plot.',\n properties: [property_1.Property.CHANNEL, property_1.Property.AGGREGATE, property_1.Property.AUTOCOUNT],\n allowWildcardForProperties: false,\n strict: true,\n satisfy: function (specM, _, opt) {\n if (specM.isAggregate()) {\n return true;\n }\n return util_1.every(specM.specQuery.encodings, function (encQ, index) {\n if (encoding_1.isValueQuery(encQ) || (encoding_1.isDisabledAutoCountQuery(encQ)))\n return true; // ignore autoCount field\n if (encQ.channel === channel_1.Channel.DETAIL) {\n // Detail channel for raw plot is not good, except when its enumerated\n // or when it's manually specified but we constraintManuallySpecifiedValue.\n if (specM.wildcardIndex.hasEncodingProperty(index, property_1.Property.CHANNEL) ||\n opt.constraintManuallySpecifiedValue) {\n return false;\n }\n }\n return true;\n });\n }\n },\n {\n name: 'omitRepeatedField',\n description: 'Each field should be mapped to only one channel',\n properties: [property_1.Property.FIELD],\n allowWildcardForProperties: true,\n strict: false,\n satisfy: function (specM, _, opt) {\n var fieldUsed = {};\n var fieldEnumerated = {};\n var encodings = specM.specQuery.encodings;\n for (var i = 0; i < encodings.length; i++) {\n var encQ = encodings[i];\n if (encoding_1.isValueQuery(encQ) || encoding_1.isAutoCountQuery(encQ))\n continue;\n var field = void 0;\n if (encQ.field && !wildcard_1.isWildcard(encQ.field)) {\n field = encQ.field;\n }\n if (encoding_1.isAutoCountQuery(encQ) && !wildcard_1.isWildcard(encQ.autoCount)) {\n field = 'count_*';\n }\n if (field) {\n if (specM.wildcardIndex.hasEncodingProperty(i, property_1.Property.FIELD)) {\n fieldEnumerated[field] = true;\n }\n // When the field is specified previously,\n // if it is enumerated (either previously or in this encQ)\n // or if the opt.constraintManuallySpecifiedValue is true,\n // then it violates the constraint.\n if (fieldUsed[field]) {\n if (fieldEnumerated[field] || opt.constraintManuallySpecifiedValue) {\n return false;\n }\n }\n fieldUsed[field] = true;\n }\n }\n return true;\n }\n },\n // TODO: omitShapeWithBin\n {\n name: 'omitVerticalDotPlot',\n description: 'Do not output vertical dot plot.',\n properties: [property_1.Property.CHANNEL],\n allowWildcardForProperties: true,\n strict: false,\n satisfy: function (specM, _, __) {\n var encodings = specM.getEncodings();\n if (encodings.length === 1 && encodings[0].channel === channel_1.Channel.Y) {\n return false;\n }\n return true;\n }\n },\n // EXPENSIVE CONSTRAINTS -- check them later!\n {\n name: 'hasAppropriateGraphicTypeForMark',\n description: 'Has appropriate graphic type for mark',\n properties: [property_1.Property.CHANNEL, property_1.Property.MARK, property_1.Property.TYPE, property_1.Property.TIMEUNIT, property_1.Property.BIN, property_1.Property.AGGREGATE, property_1.Property.AUTOCOUNT],\n allowWildcardForProperties: false,\n strict: false,\n satisfy: function (specM, _, __) {\n var mark = specM.getMark();\n switch (mark) {\n case mark_1.Mark.AREA:\n case mark_1.Mark.LINE:\n if (specM.isAggregate()) {\n var xEncQ = specM.getEncodingQueryByChannel(channel_1.Channel.X);\n var yEncQ = specM.getEncodingQueryByChannel(channel_1.Channel.Y);\n var xIsMeasure = encoding_1.isContinuous(xEncQ);\n var yIsMeasure = encoding_1.isContinuous(yEncQ);\n // for aggregate line / area, we need at least one group-by axis and one measure axis.\n return xEncQ && yEncQ && (xIsMeasure !== yIsMeasure) &&\n // and the dimension axis should not be nominal\n // TODO: make this clause optional\n !(encoding_1.isFieldQuery(xEncQ) && !xIsMeasure && util_1.contains(['nominal', 'key'], xEncQ.type)) &&\n !(encoding_1.isFieldQuery(yEncQ) && !yIsMeasure && util_1.contains(['nominal', 'key'], yEncQ.type));\n // TODO: allow connected scatterplot\n }\n return true;\n case mark_1.Mark.TEXT:\n // FIXME correctly when we add text\n return true;\n case mark_1.Mark.BAR:\n case mark_1.Mark.TICK:\n // Bar and tick should not use size.\n if (specM.channelUsed(channel_1.Channel.SIZE)) {\n return false;\n }\n else {\n // Tick and Bar should have one and only one continuous axis\n var xEncQ = specM.getEncodingQueryByChannel(channel_1.Channel.X);\n var yEncQ = specM.getEncodingQueryByChannel(channel_1.Channel.Y);\n var xIsContinuous = encoding_1.isContinuous(xEncQ);\n var yIsContinuous = encoding_1.isContinuous(yEncQ);\n if (xIsContinuous !== yIsContinuous) {\n // TODO: Bar and tick's dimension should not be continuous (quant/time) scale\n return true;\n }\n return false;\n }\n case mark_1.Mark.CIRCLE:\n case mark_1.Mark.POINT:\n case mark_1.Mark.SQUARE:\n case mark_1.Mark.RULE:\n return true;\n }\n /* istanbul ignore next */\n throw new Error('hasAllRequiredChannelsForMark not implemented for mark' + mark);\n }\n },\n {\n name: 'omitNonLinearScaleTypeWithStack',\n description: 'Stacked plot should only use linear scale',\n properties: [property_1.Property.CHANNEL, property_1.Property.MARK, property_1.Property.AGGREGATE, property_1.Property.AUTOCOUNT, property_1.Property.SCALE, property_1.getEncodingNestedProp('scale', 'type'), property_1.Property.TYPE],\n // TODO: Property.STACK\n allowWildcardForProperties: false,\n strict: true,\n satisfy: function (specM, _, __) {\n var stack = specM.stack();\n if (stack) {\n for (var _i = 0, _a = specM.getEncodings(); _i < _a.length; _i++) {\n var encQ = _a[_i];\n if (encoding_1.isValueQuery(encQ))\n continue;\n if (((encoding_1.isFieldQuery(encQ) && !!encQ.aggregate) || encoding_1.isEnabledAutoCountQuery(encQ)) &&\n encQ.type === type_1.Type.QUANTITATIVE &&\n util_1.contains([channel_1.Channel.X, channel_1.Channel.Y], encQ.channel)) {\n if (encoding_1.scaleType(encQ) !== scale_1.ScaleType.LINEAR) {\n return false;\n }\n }\n }\n }\n return true;\n }\n },\n {\n name: 'omitNonSumStack',\n description: 'Stacked plot should use summative aggregation such as sum, count, or distinct',\n properties: [property_1.Property.CHANNEL, property_1.Property.MARK, property_1.Property.AGGREGATE, property_1.Property.AUTOCOUNT],\n allowWildcardForProperties: false,\n strict: false,\n satisfy: function (specM, _, __) {\n var stack = specM.stack();\n if (stack) {\n var measureEncQ = specM.getEncodingQueryByChannel(stack.fieldChannel);\n return (encoding_1.isFieldQuery(measureEncQ) && util_1.contains(aggregate_1.SUM_OPS, measureEncQ.aggregate)) || (encoding_1.isAutoCountQuery(measureEncQ) && !!measureEncQ.autoCount);\n }\n return true;\n }\n },\n {\n name: 'omitTableWithOcclusionIfAutoAddCount',\n description: 'Plots without aggregation or autocount where x and y are both discrete should be omitted if autoAddCount is enabled as they often lead to occlusion',\n properties: [property_1.Property.CHANNEL, property_1.Property.TYPE, property_1.Property.TIMEUNIT, property_1.Property.BIN, property_1.Property.AGGREGATE, property_1.Property.AUTOCOUNT],\n allowWildcardForProperties: false,\n strict: false,\n satisfy: function (specM, _, opt) {\n if (opt.autoAddCount) {\n var xEncQ = specM.getEncodingQueryByChannel('x');\n var yEncQ = specM.getEncodingQueryByChannel('y');\n if ((!encoding_1.isFieldQuery(xEncQ) || encoding_1.isDiscrete(xEncQ)) &&\n (!encoding_1.isFieldQuery(yEncQ) || encoding_1.isDiscrete(yEncQ))) {\n if (!specM.isAggregate()) {\n return false;\n }\n else {\n return util_1.every(specM.getEncodings(), function (encQ) {\n var channel = encQ.channel;\n if (channel !== channel_1.Channel.X && channel !== channel_1.Channel.Y &&\n channel !== channel_1.Channel.ROW && channel !== channel_1.Channel.COLUMN) {\n // Non-position fields should not be unaggreated fields\n if (encoding_1.isFieldQuery(encQ) && !encQ.aggregate) {\n return false;\n }\n }\n return true;\n });\n }\n }\n }\n return true;\n }\n }\n].map(function (sc) { return new SpecConstraintModel(sc); });\n// For testing\nexports.SPEC_CONSTRAINT_INDEX = exports.SPEC_CONSTRAINTS.reduce(function (m, c) {\n m[c.name()] = c;\n return m;\n}, {});\nvar SPEC_CONSTRAINTS_BY_PROPERTY = exports.SPEC_CONSTRAINTS.reduce(function (index, c) {\n for (var _i = 0, _a = c.properties(); _i < _a.length; _i++) {\n var prop = _a[_i];\n // Initialize array and use it\n index.set(prop, index.get(prop) || []);\n index.get(prop).push(c);\n }\n return index;\n}, new propindex_1.PropIndex());\n/**\n * Check all encoding constraints for a particular property and index tuple\n */\nfunction checkSpec(prop, wildcard, specM, schema, opt) {\n // Check encoding constraint\n var specConstraints = SPEC_CONSTRAINTS_BY_PROPERTY.get(prop) || [];\n for (var _i = 0, specConstraints_1 = specConstraints; _i < specConstraints_1.length; _i++) {\n var c = specConstraints_1[_i];\n // Check if the constraint is enabled\n if (c.strict() || !!opt[c.name()]) {\n // For strict constraint, or enabled non-strict, check the constraints\n var satisfy = c.satisfy(specM, schema, opt);\n if (!satisfy) {\n var violatedConstraint = '(spec) ' + c.name();\n /* istanbul ignore if */\n if (opt.verbose) {\n console.log(violatedConstraint + ' failed with ' + specM.toShorthand() + ' for ' + wildcard.name);\n }\n return violatedConstraint;\n }\n }\n }\n return null;\n}\nexports.checkSpec = checkSpec;\n//# sourceMappingURL=spec.js.map", + "\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nvar property_1 = require(\"../property\");\nvar propindex_1 = require(\"../propindex\");\nvar util_1 = require(\"../util\");\nvar base_1 = require(\"./base\");\nexports.VALUE_CONSTRAINTS = [\n {\n name: 'doesNotSupportConstantValue',\n description: 'row, column, x, y, and detail should not work with constant values.',\n properties: [property_1.Property.TYPE, property_1.Property.AGGREGATE],\n allowWildcardForProperties: false,\n strict: true,\n satisfy: function (valueQ, _, __, ___) {\n return !(util_1.contains(['row', 'column', 'x', 'y', 'detail'], valueQ.channel));\n }\n }\n].map(function (ec) { return new base_1.EncodingConstraintModel(ec); });\nexports.VALUE_CONSTRAINT_INDEX = exports.VALUE_CONSTRAINTS.reduce(function (m, ec) {\n m[ec.name()] = ec;\n return m;\n}, {});\nexports.VALUE_CONSTRAINTS_BY_PROPERTY = exports.VALUE_CONSTRAINTS.reduce(function (index, c) {\n for (var _i = 0, _a = c.properties(); _i < _a.length; _i++) {\n var prop = _a[_i];\n index.set(prop, index.get(prop) || []);\n index.get(prop).push(c);\n }\n return index;\n}, new propindex_1.PropIndex());\n//# sourceMappingURL=value.js.map", + "\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.version = '0.19.1';\nexports.config = require(\"./config\");\nexports.constraint = require(\"./constraint\");\nexports.enumerate = require(\"./enumerator\");\nexports.wildcard = require(\"./wildcard\");\nvar generate_1 = require(\"./generate\");\nexports.generate = generate_1.generate;\nexports.model = require(\"./model\");\nexports.nest = require(\"./nest\");\nexports.property = require(\"./property\");\nexports.query = require(\"./query\");\nexports.ranking = require(\"./ranking/ranking\");\nvar recommend_1 = require(\"./recommend\");\nexports.recommend = recommend_1.recommend;\nexports.schema = require(\"./schema\");\nexports.util = require(\"./util\");\n//# sourceMappingURL=cql.js.map", + "\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nvar encoding_1 = require(\"./constraint/encoding\");\nvar spec_1 = require(\"./constraint/spec\");\nvar property_1 = require(\"./property\");\nvar propindex_1 = require(\"./propindex\");\nvar encoding_2 = require(\"./query/encoding\");\nvar ENUMERATOR_INDEX = new propindex_1.PropIndex();\nfunction getEnumerator(prop) {\n return ENUMERATOR_INDEX.get(prop);\n}\nexports.getEnumerator = getEnumerator;\nENUMERATOR_INDEX.set('mark', function (wildcardIndex, schema, opt) {\n return function (answerSet, specM) {\n var markWildcard = specM.getMark();\n // enumerate the value\n markWildcard.enum.forEach(function (mark) {\n specM.setMark(mark);\n // Check spec constraint\n var violatedSpecConstraint = spec_1.checkSpec('mark', wildcardIndex.mark, specM, schema, opt);\n if (!violatedSpecConstraint) {\n // emit\n answerSet.push(specM.duplicate());\n }\n });\n // Reset to avoid side effect\n specM.resetMark();\n return answerSet;\n };\n});\nproperty_1.ENCODING_TOPLEVEL_PROPS.forEach(function (prop) {\n ENUMERATOR_INDEX.set(prop, EncodingPropertyGeneratorFactory(prop));\n});\nproperty_1.ENCODING_NESTED_PROPS.forEach(function (nestedProp) {\n ENUMERATOR_INDEX.set(nestedProp, EncodingPropertyGeneratorFactory(nestedProp));\n});\n/**\n * @param prop property type.\n * @return an answer set reducer factory for the given prop.\n */\nfunction EncodingPropertyGeneratorFactory(prop) {\n /**\n * @return as reducer that takes a specQueryModel as input and output an answer set array.\n */\n return function (wildcardIndex, schema, opt) {\n return function (answerSet, specM) {\n // index of encoding mappings that require enumeration\n var indices = wildcardIndex.encodingIndicesByProperty.get(prop);\n function enumerate(jobIndex) {\n if (jobIndex === indices.length) {\n // emit and terminate\n answerSet.push(specM.duplicate());\n return;\n }\n var index = indices[jobIndex];\n var wildcard = wildcardIndex.encodings[index].get(prop);\n var encQ = specM.getEncodingQueryByIndex(index);\n var propWildcard = specM.getEncodingProperty(index, prop);\n if (encoding_2.isValueQuery(encQ) || (\n // TODO: encQ.exclude\n // If this encoding query is an excluded autoCount, there is no point enumerating other properties\n // for this encoding query because they will be excluded anyway.\n // Thus, we can just move on to the next encoding to enumerate.\n (encoding_2.isDisabledAutoCountQuery(encQ)) ||\n // nested encoding property might have its parent set to false\n // therefore, we no longer have to enumerate them\n !propWildcard)) {\n enumerate(jobIndex + 1);\n }\n else {\n wildcard.enum.forEach(function (propVal) {\n if (propVal === null) {\n // our duplicate() method use JSON.stringify, parse and thus can accidentally\n // convert undefined in an array into null\n propVal = undefined;\n }\n specM.setEncodingProperty(index, prop, propVal, wildcard);\n // Check encoding constraint\n var violatedEncodingConstraint = encoding_1.checkEncoding(prop, wildcard, index, specM, schema, opt);\n if (violatedEncodingConstraint) {\n return; // do not keep searching\n }\n // Check spec constraint\n var violatedSpecConstraint = spec_1.checkSpec(prop, wildcard, specM, schema, opt);\n if (violatedSpecConstraint) {\n return; // do not keep searching\n }\n // If qualify all of the constraints, keep enumerating\n enumerate(jobIndex + 1);\n });\n // Reset to avoid side effect\n specM.resetEncodingProperty(index, prop, wildcard);\n }\n }\n // start enumerating from 0\n enumerate(0);\n return answerSet;\n };\n };\n}\nexports.EncodingPropertyGeneratorFactory = EncodingPropertyGeneratorFactory;\n//# sourceMappingURL=enumerator.js.map", + "\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nvar config_1 = require(\"./config\");\nvar enumerator_1 = require(\"./enumerator\");\nvar model_1 = require(\"./model\");\nvar property_1 = require(\"./property\");\nvar stylize_1 = require(\"./stylize\");\nfunction generate(specQ, schema, opt) {\n if (opt === void 0) { opt = config_1.DEFAULT_QUERY_CONFIG; }\n // 1. Build a SpecQueryModel, which also contains wildcardIndex\n var specM = model_1.SpecQueryModel.build(specQ, schema, opt);\n var wildcardIndex = specM.wildcardIndex;\n // 2. Enumerate each of the properties based on propPrecedence.\n var answerSet = [specM]; // Initialize Answer Set with only the input spec query.\n opt.propertyPrecedence.forEach(function (propKey) {\n var prop = property_1.fromKey(propKey);\n // If the original specQuery contains wildcard for this prop\n if (wildcardIndex.hasProperty(prop)) {\n // update answerset\n var enumerator = enumerator_1.getEnumerator(prop);\n var reducer = enumerator(wildcardIndex, schema, opt);\n answerSet = answerSet.reduce(reducer, []);\n }\n });\n if (opt.stylize) {\n if ((opt.nominalColorScaleForHighCardinality !== null) ||\n (opt.smallRangeStepForHighCardinalityOrFacet !== null) ||\n (opt.xAxisOnTopForHighYCardinalityWithoutColumn !== null)) {\n return stylize_1.stylize(answerSet, schema, opt);\n }\n }\n return answerSet;\n}\nexports.generate = generate;\n//# sourceMappingURL=generate.js.map", + "\"use strict\";\nvar __assign = (this && this.__assign) || Object.assign || function(t) {\n for (var s, i = 1, n = arguments.length; i < n; i++) {\n s = arguments[i];\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))\n t[p] = s[p];\n }\n return t;\n};\nObject.defineProperty(exports, \"__esModule\", { value: true });\nvar type_1 = require(\"vega-lite/build/src/type\");\nvar property_1 = require(\"./property\");\nvar wildcard_1 = require(\"./wildcard\");\nvar wildcardindex_1 = require(\"./wildcardindex\");\nvar spec_1 = require(\"./query/spec\");\nvar encoding_1 = require(\"./query/encoding\");\nvar groupby_1 = require(\"./query/groupby\");\nvar shorthand_1 = require(\"./query/shorthand\");\nvar util_1 = require(\"./util\");\n/**\n * Internal class for specQuery that provides helper for the enumeration process.\n */\nvar SpecQueryModel = (function () {\n function SpecQueryModel(spec, wildcardIndex, schema, opt, wildcardAssignment) {\n this._rankingScore = {};\n this._spec = spec;\n this._channelFieldCount = spec.encodings.reduce(function (m, encQ) {\n if (!wildcard_1.isWildcard(encQ.channel) && (!encoding_1.isAutoCountQuery(encQ) || encQ.autoCount !== false)) {\n m[encQ.channel + ''] = 1;\n }\n return m;\n }, {});\n this._wildcardIndex = wildcardIndex;\n this._assignedWildcardIndex = wildcardAssignment;\n this._opt = opt;\n this._schema = schema;\n }\n /**\n * Build an WildcardIndex by detecting enumeration specifiers\n * in the input specQuery and replace short wildcards with\n * full ones that includes both names and enumValues.\n *\n * @return a SpecQueryModel that wraps the specQuery and the WildcardIndex.\n */\n SpecQueryModel.build = function (specQ, schema, opt) {\n var wildcardIndex = new wildcardindex_1.WildcardIndex();\n // mark\n if (wildcard_1.isWildcard(specQ.mark)) {\n var name_1 = wildcard_1.getDefaultName(property_1.Property.MARK);\n specQ.mark = wildcard_1.initWildcard(specQ.mark, name_1, opt.enum.mark);\n wildcardIndex.setMark(specQ.mark);\n }\n // TODO: transform\n // encodings\n specQ.encodings.forEach(function (encQ, index) {\n if (encoding_1.isAutoCountQuery(encQ)) {\n // This is only for testing purpose\n console.warn('A field with autoCount should not be included as autoCount meant to be an internal object.');\n encQ.type = type_1.Type.QUANTITATIVE; // autoCount is always quantitative\n }\n if (encoding_1.isFieldQuery(encQ) && encQ.type === undefined) {\n // type is optional -- we automatically augment wildcard if not specified\n encQ.type = wildcard_1.SHORT_WILDCARD;\n }\n // For each property of the encodingQuery, enumerate\n property_1.ENCODING_TOPLEVEL_PROPS.forEach(function (prop) {\n if (wildcard_1.isWildcard(encQ[prop])) {\n // Assign default wildcard name and enum values.\n var defaultWildcardName = wildcard_1.getDefaultName(prop) + index;\n var defaultEnumValues = wildcard_1.getDefaultEnumValues(prop, schema, opt);\n var wildcard = encQ[prop] = wildcard_1.initWildcard(encQ[prop], defaultWildcardName, defaultEnumValues);\n // Add index of the encoding mapping to the property's wildcard index.\n wildcardIndex.setEncodingProperty(index, prop, wildcard);\n }\n });\n // For each nested property of the encoding query (e.g., encQ.bin.maxbins)\n property_1.ENCODING_NESTED_PROPS.forEach(function (prop) {\n var propObj = encQ[prop.parent]; // the property object e.g., encQ.bin\n if (propObj) {\n var child = prop.child;\n if (wildcard_1.isWildcard(propObj[child])) {\n // Assign default wildcard name and enum values.\n var defaultWildcardName = wildcard_1.getDefaultName(prop) + index;\n var defaultEnumValues = wildcard_1.getDefaultEnumValues(prop, schema, opt);\n var wildcard = propObj[child] = wildcard_1.initWildcard(propObj[child], defaultWildcardName, defaultEnumValues);\n // Add index of the encoding mapping to the property's wildcard index.\n wildcardIndex.setEncodingProperty(index, prop, wildcard);\n }\n }\n });\n });\n // AUTO COUNT\n // Add Auto Count Field\n if (opt.autoAddCount) {\n var countEncQ = {\n channel: {\n name: wildcard_1.getDefaultName(property_1.Property.CHANNEL) + specQ.encodings.length,\n enum: wildcard_1.getDefaultEnumValues(property_1.Property.CHANNEL, schema, opt)\n },\n autoCount: {\n name: wildcard_1.getDefaultName(property_1.Property.AUTOCOUNT) + specQ.encodings.length,\n enum: [false, true]\n },\n type: type_1.Type.QUANTITATIVE\n };\n specQ.encodings.push(countEncQ);\n var index = specQ.encodings.length - 1;\n // Add index of the encoding mapping to the property's wildcard index.\n wildcardIndex.setEncodingProperty(index, property_1.Property.CHANNEL, countEncQ.channel);\n wildcardIndex.setEncodingProperty(index, property_1.Property.AUTOCOUNT, countEncQ.autoCount);\n }\n return new SpecQueryModel(specQ, wildcardIndex, schema, opt, {});\n };\n Object.defineProperty(SpecQueryModel.prototype, \"wildcardIndex\", {\n get: function () {\n return this._wildcardIndex;\n },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(SpecQueryModel.prototype, \"schema\", {\n get: function () {\n return this._schema;\n },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(SpecQueryModel.prototype, \"specQuery\", {\n get: function () {\n return this._spec;\n },\n enumerable: true,\n configurable: true\n });\n SpecQueryModel.prototype.duplicate = function () {\n return new SpecQueryModel(util_1.duplicate(this._spec), this._wildcardIndex, this._schema, this._opt, util_1.duplicate(this._assignedWildcardIndex));\n };\n SpecQueryModel.prototype.setMark = function (mark) {\n var name = this._spec.mark.name;\n this._assignedWildcardIndex[name] = this._spec.mark = mark;\n };\n SpecQueryModel.prototype.resetMark = function () {\n var wildcard = this._spec.mark = this._wildcardIndex.mark;\n delete this._assignedWildcardIndex[wildcard.name];\n };\n SpecQueryModel.prototype.getMark = function () {\n return this._spec.mark;\n };\n SpecQueryModel.prototype.getEncodingProperty = function (index, prop) {\n var encQ = this._spec.encodings[index];\n if (property_1.isEncodingNestedProp(prop)) {\n return encQ[prop.parent][prop.child];\n }\n return encQ[prop]; // encoding property (non-nested)\n };\n SpecQueryModel.prototype.setEncodingProperty = function (index, prop, value, wildcard) {\n var encQ = this._spec.encodings[index];\n if (prop === property_1.Property.CHANNEL && encQ.channel && !wildcard_1.isWildcard(encQ.channel)) {\n // If there is an old channel\n this._channelFieldCount[encQ.channel]--;\n }\n if (property_1.isEncodingNestedProp(prop)) {\n encQ[prop.parent][prop.child] = value;\n }\n else if (property_1.hasNestedProperty(prop) && value === true) {\n encQ[prop] = util_1.extend({}, encQ[prop], // copy all existing properties\n { enum: undefined, name: undefined } // except name and values to it no longer an wildcard\n );\n }\n else {\n encQ[prop] = value;\n }\n this._assignedWildcardIndex[wildcard.name] = value;\n if (prop === property_1.Property.CHANNEL) {\n // If there is a new channel, make sure it exists and add it to the count.\n this._channelFieldCount[value] = (this._channelFieldCount[value] || 0) + 1;\n }\n };\n SpecQueryModel.prototype.resetEncodingProperty = function (index, prop, wildcard) {\n var encQ = this._spec.encodings[index];\n if (prop === property_1.Property.CHANNEL) {\n this._channelFieldCount[encQ.channel]--;\n }\n // reset it to wildcard\n if (property_1.isEncodingNestedProp(prop)) {\n encQ[prop.parent][prop.child] = wildcard;\n }\n else {\n encQ[prop] = wildcard;\n }\n // add remove value that is reset from the assignment map\n delete this._assignedWildcardIndex[wildcard.name];\n };\n SpecQueryModel.prototype.channelUsed = function (channel) {\n // do not include encoding that has autoCount = false because it is not a part of the output spec.\n return this._channelFieldCount[channel] > 0;\n };\n SpecQueryModel.prototype.stack = function () {\n return spec_1.stack(this._spec);\n };\n SpecQueryModel.prototype.getEncodings = function () {\n // do not include encoding that has autoCount = false because it is not a part of the output spec.\n return this._spec.encodings.filter(function (encQ) { return !encoding_1.isDisabledAutoCountQuery(encQ); });\n };\n SpecQueryModel.prototype.getEncodingQueryByChannel = function (channel) {\n for (var _i = 0, _a = this._spec.encodings; _i < _a.length; _i++) {\n var specEncoding = _a[_i];\n if (specEncoding.channel === channel) {\n return specEncoding;\n }\n }\n return undefined;\n };\n SpecQueryModel.prototype.getEncodingQueryByIndex = function (i) {\n return this._spec.encodings[i];\n };\n SpecQueryModel.prototype.isAggregate = function () {\n return spec_1.isAggregate(this._spec);\n };\n SpecQueryModel.prototype.toShorthand = function (groupBy) {\n if (groupBy) {\n var parsedGroupBy = groupby_1.parseGroupBy(groupBy);\n return shorthand_1.spec(this._spec, parsedGroupBy.include, parsedGroupBy.replacer);\n }\n return shorthand_1.spec(this._spec);\n };\n SpecQueryModel.prototype._encoding = function () {\n var encoding = {};\n for (var _i = 0, _a = this._spec.encodings; _i < _a.length; _i++) {\n var encQ = _a[_i];\n // Need to cast here so we can assign properties later\n var fieldDef = {};\n // For count field that is automatically added, convert to correct vega-lite fieldDef\n if (encoding_1.isEnabledAutoCountQuery(encQ)) {\n fieldDef = {\n aggregate: 'count',\n field: '*',\n type: 'quantitative'\n };\n }\n else if (encoding_1.isValueQuery(encQ) || encoding_1.isDisabledAutoCountQuery(encQ)) {\n continue; // Do not include this in the output.\n }\n // if channel is a wildcard, return null\n if (wildcard_1.isWildcard(encQ.channel))\n return null;\n // assemble other property into a field def.\n var PROPERTIES = [property_1.Property.AGGREGATE, property_1.Property.BIN, property_1.Property.TIMEUNIT, property_1.Property.FIELD, property_1.Property.TYPE, property_1.Property.SCALE, property_1.Property.SORT, property_1.Property.AXIS, property_1.Property.LEGEND];\n for (var _b = 0, PROPERTIES_1 = PROPERTIES; _b < PROPERTIES_1.length; _b++) {\n var prop = PROPERTIES_1[_b];\n // if the property's a wildcard, return null\n var encodingProperty = encQ[prop];\n if (wildcard_1.isWildcard(encodingProperty)) {\n return null;\n }\n else {\n // all channels support this prop\n var isSupportedByChannel = (!shorthand_1.PROPERTY_SUPPORTED_CHANNELS[prop] || shorthand_1.PROPERTY_SUPPORTED_CHANNELS[prop][encQ.channel]);\n if (isSupportedByChannel) {\n if (encodingProperty !== undefined) {\n if (property_1.ENCODING_NESTED_PROP_PARENT_INDEX[prop]) {\n for (var childProp in encQ[prop]) {\n // ensure nested properties are not wildcard before assigning to field def\n if (wildcard_1.isWildcard(encQ[prop][childProp])) {\n return null;\n }\n }\n }\n fieldDef[prop] = encodingProperty;\n }\n if (prop === property_1.Property.SCALE && encoding_1.isFieldQuery(encQ) && encQ.type === type_1.Type.ORDINAL) {\n var scale = encQ.scale;\n var ordinalDomain = this._schema.fieldSchema(encQ.field).ordinalDomain;\n if (scale !== null && ordinalDomain) {\n fieldDef[property_1.Property.SCALE] = __assign({ domain: ordinalDomain }, (util_1.isObject(scale) ? scale : {}));\n }\n }\n }\n }\n }\n if (fieldDef.bin === false) {\n // exclude bin false\n delete fieldDef.bin;\n }\n encoding[encQ.channel] = fieldDef;\n }\n return encoding;\n };\n /**\n * Convert a query to a Vega-Lite spec if it is completed.\n * @return a Vega-Lite spec if completed, null otherwise.\n */\n SpecQueryModel.prototype.toSpec = function (data) {\n if (wildcard_1.isWildcard(this._spec.mark))\n return null;\n var spec = {};\n data = data || this._spec.data;\n if (data) {\n spec.data = data;\n }\n if (this._spec.transform) {\n spec.transform = this._spec.transform;\n }\n spec.mark = this._spec.mark;\n spec.encoding = this._encoding();\n if (spec.encoding === null) {\n return null;\n }\n if (this._spec.config || this._opt.defaultSpecConfig)\n spec.config = util_1.extend({}, this._opt.defaultSpecConfig, this._spec.config);\n return spec;\n };\n SpecQueryModel.prototype.getRankingScore = function (rankingName) {\n return this._rankingScore[rankingName];\n };\n SpecQueryModel.prototype.setRankingScore = function (rankingName, score) {\n this._rankingScore[rankingName] = score;\n };\n return SpecQueryModel;\n}());\nexports.SpecQueryModel = SpecQueryModel;\nfunction getTopSpecQueryItem(specQuery) {\n var topItem = specQuery.items[0];\n while (topItem && isSpecQueryGroup(topItem)) {\n topItem = topItem.items[0];\n }\n return topItem;\n}\nexports.getTopSpecQueryItem = getTopSpecQueryItem;\nfunction isSpecQueryGroup(item) {\n return item.items !== undefined;\n}\nexports.isSpecQueryGroup = isSpecQueryGroup;\n//# sourceMappingURL=model.js.map", + "\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nvar channel_1 = require(\"vega-lite/build/src/channel\");\nvar util_1 = require(\"datalib/src/util\");\nvar property_1 = require(\"./property\");\nvar propindex_1 = require(\"./propindex\");\nvar groupby_1 = require(\"./query/groupby\");\nvar shorthand_1 = require(\"./query/shorthand\");\nvar spec_1 = require(\"./query/spec\");\n/**\n * Registry for all possible grouping key functions.\n */\nvar groupRegistry = {};\n/**\n * Add a grouping function to the registry.\n */\nfunction registerKeyFn(name, keyFn) {\n groupRegistry[name] = keyFn;\n}\nexports.registerKeyFn = registerKeyFn;\nexports.FIELD = 'field';\nexports.FIELD_TRANSFORM = 'fieldTransform';\nexports.ENCODING = 'encoding';\nexports.TRANSPOSE = 'transpose';\nexports.SPEC = 'spec';\n/**\n * Group the input spec query model by a key function registered in the group registry\n * @return\n */\nfunction nest(specModels, queryNest) {\n if (queryNest) {\n var rootGroup_1 = {\n name: '',\n path: '',\n items: [],\n };\n var groupIndex_1 = {};\n // global `includes` and `replaces` will get augmented by each level's groupBy.\n // Upper level's `groupBy` will get cascaded to lower-level groupBy.\n // `replace` can be overriden in a lower-level to support different grouping.\n var includes_1 = [];\n var replaces = [];\n var replacers_1 = [];\n for (var l = 0; l < queryNest.length; l++) {\n includes_1.push(l > 0 ? includes_1[l - 1].duplicate() : new propindex_1.PropIndex());\n replaces.push(l > 0 ? replaces[l - 1].duplicate() : new propindex_1.PropIndex());\n var groupBy = queryNest[l].groupBy;\n if (util_1.isArray(groupBy)) {\n // If group is array, it's an array of extended group by that need to be parsed\n var parsedGroupBy = groupby_1.parseGroupBy(groupBy, includes_1[l], replaces[l]);\n replacers_1.push(parsedGroupBy.replacer);\n }\n }\n // With includes and replacers, now we can construct the nesting tree\n specModels.forEach(function (specM) {\n var path = '';\n var group = rootGroup_1;\n for (var l = 0; l < queryNest.length; l++) {\n var groupBy = group.groupBy = queryNest[l].groupBy;\n group.orderGroupBy = queryNest[l].orderGroupBy;\n var key = util_1.isArray(groupBy) ?\n shorthand_1.spec(specM.specQuery, includes_1[l], replacers_1[l]) :\n groupRegistry[groupBy](specM);\n path += '/' + key;\n if (!groupIndex_1[path]) {\n groupIndex_1[path] = {\n name: key,\n path: path,\n items: [],\n };\n group.items.push(groupIndex_1[path]);\n }\n group = groupIndex_1[path];\n }\n group.items.push(specM);\n });\n return rootGroup_1;\n }\n else {\n // no nesting, just return a flat group\n return {\n name: '',\n path: '',\n items: specModels,\n };\n }\n}\nexports.nest = nest;\n// TODO: move this to groupBy, rename properly, and export\nvar GROUP_BY_FIELD = [property_1.Property.FIELD];\nvar PARSED_GROUP_BY_FIELD = groupby_1.parseGroupBy(GROUP_BY_FIELD);\nregisterKeyFn(exports.FIELD, function (specM) {\n return shorthand_1.spec(specM.specQuery, PARSED_GROUP_BY_FIELD.include, PARSED_GROUP_BY_FIELD.replacer);\n});\nexports.PARSED_GROUP_BY_FIELD_TRANSFORM = groupby_1.parseGroupBy(groupby_1.GROUP_BY_FIELD_TRANSFORM);\nregisterKeyFn(exports.FIELD_TRANSFORM, function (specM) {\n return shorthand_1.spec(specM.specQuery, exports.PARSED_GROUP_BY_FIELD_TRANSFORM.include, exports.PARSED_GROUP_BY_FIELD_TRANSFORM.replacer);\n});\nexports.PARSED_GROUP_BY_ENCODING = groupby_1.parseGroupBy(groupby_1.GROUP_BY_ENCODING);\nregisterKeyFn(exports.ENCODING, function (specM) {\n return shorthand_1.spec(specM.specQuery, exports.PARSED_GROUP_BY_ENCODING.include, exports.PARSED_GROUP_BY_ENCODING.replacer);\n});\nfunction stringifyStack(specM) {\n var _stack = spec_1.stack(specM.specQuery);\n return (!!_stack ? 'stack=' + _stack.offset + '|' : '');\n}\n// TODO: rename, provide similar format\nregisterKeyFn(exports.TRANSPOSE, function (specM) {\n return specM.getMark() + '|' +\n stringifyStack(specM) +\n specM.getEncodings().map(function (encQ) {\n var fieldDef = shorthand_1.fieldDef(encQ);\n var channel = (encQ.channel === channel_1.Channel.X || encQ.channel === channel_1.Channel.Y) ? 'xy' :\n (encQ.channel === channel_1.Channel.ROW || encQ.channel === channel_1.Channel.COLUMN) ? 'facet' :\n encQ.channel;\n return channel + ':' + fieldDef;\n })\n .sort()\n .join('|');\n});\nregisterKeyFn(exports.SPEC, function (specM) { return JSON.stringify(specM.specQuery); });\n//# sourceMappingURL=nest.js.map", + "\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nvar axis_1 = require(\"vega-lite/build/src/axis\");\nvar scale_1 = require(\"vega-lite/build/src/scale\");\nvar legend_1 = require(\"vega-lite/build/src/legend\");\nvar util_1 = require(\"./util\");\nfunction isEncodingNestedProp(p) {\n return !!p['parent'];\n}\nexports.isEncodingNestedProp = isEncodingNestedProp;\nexports.ENCODING_TOPLEVEL_PROPS = [\n // channel\n 'channel',\n // fn\n 'aggregate', 'autoCount', 'bin', 'timeUnit', 'hasFn',\n // sort\n 'sort',\n // field / type\n 'field', 'type',\n // scale / axis / legend\n 'scale', 'axis', 'legend'\n];\nvar ENCODING_TOPLEVEL_PROPERTY_INDEX = util_1.toMap(exports.ENCODING_TOPLEVEL_PROPS);\nfunction isEncodingTopLevelProperty(p) {\n return p in ENCODING_TOPLEVEL_PROPERTY_INDEX;\n}\nexports.isEncodingTopLevelProperty = isEncodingTopLevelProperty;\nvar ENCODING_NESTED_PROP_PARENTS = [\n 'bin', 'scale', 'sort', 'axis', 'legend'\n];\nexports.ENCODING_NESTED_PROP_PARENT_INDEX = util_1.toMap(ENCODING_NESTED_PROP_PARENTS);\nfunction hasNestedProperty(prop) {\n return exports.ENCODING_NESTED_PROP_PARENT_INDEX[prop];\n}\nexports.hasNestedProperty = hasNestedProperty;\nexports.BIN_CHILD_PROPS = ['maxbins', 'divide', 'extent', 'base', 'step', 'steps', 'minstep'];\nexports.SORT_CHILD_PROPS = ['field', 'op', 'order'];\nexports.SCALE_CHILD_PROPS = ['clamp', 'domain', 'exponent', 'nice', 'range', 'rangeStep', 'round', 'type', 'zero'];\nvar BIN_PROPS = exports.BIN_CHILD_PROPS.map(function (c) {\n return { parent: 'bin', child: c };\n});\nexports.SORT_PROPS = exports.SORT_CHILD_PROPS.map(function (c) {\n return { parent: 'sort', child: c };\n});\nexports.SCALE_PROPS = scale_1.SCALE_PROPERTIES.map(function (c) {\n return { parent: 'scale', child: c };\n});\nvar AXIS_PROPS = axis_1.AXIS_PROPERTIES.map(function (c) {\n return { parent: 'axis', child: c };\n});\nvar LEGEND_PROPS = legend_1.LEGEND_PROPERTIES.map(function (c) {\n return { parent: 'legend', child: c };\n});\nexports.ENCODING_NESTED_PROPS = [].concat(BIN_PROPS, exports.SORT_PROPS, exports.SCALE_PROPS, AXIS_PROPS, LEGEND_PROPS);\nvar PROP_KEY_DELIMITER = '.';\nfunction toKey(p) {\n if (isEncodingNestedProp(p)) {\n return p.parent + PROP_KEY_DELIMITER + p.child;\n }\n return p;\n}\nexports.toKey = toKey;\nfunction fromKey(k) {\n var split = k.split(PROP_KEY_DELIMITER);\n /* istanbul ignore else */\n if (split.length === 1) {\n return k;\n }\n else if (split.length === 2) {\n return {\n parent: split[0],\n child: split[1]\n };\n }\n else {\n throw 'Invalid property key with ' + split.length + ' dots: ' + k;\n }\n}\nexports.fromKey = fromKey;\nvar ENCODING_NESTED_PROP_INDEX = exports.ENCODING_NESTED_PROPS.reduce(function (i, prop) {\n i[prop.parent] = i[prop.parent] || [];\n i[prop.parent][prop.child] = prop;\n return i;\n}, {});\n// FIXME consider using a more general method\nfunction getEncodingNestedProp(parent, child) {\n return (ENCODING_NESTED_PROP_INDEX[parent] || {})[child];\n}\nexports.getEncodingNestedProp = getEncodingNestedProp;\nfunction isEncodingProperty(prop) {\n return isEncodingTopLevelProperty(prop) || isEncodingNestedProp(prop);\n}\nexports.isEncodingProperty = isEncodingProperty;\nexports.ALL_ENCODING_PROPS = [].concat(exports.ENCODING_TOPLEVEL_PROPS, exports.ENCODING_NESTED_PROPS);\nexports.DEFAULT_PROP_PRECEDENCE = [\n 'type',\n 'field',\n // Field Transform\n 'bin', 'timeUnit', 'aggregate', 'autoCount',\n // Encoding\n 'channel',\n // Mark\n 'mark',\n 'scale', 'sort',\n 'axis', 'legend'\n].concat(BIN_PROPS, exports.SCALE_PROPS, AXIS_PROPS, LEGEND_PROPS, exports.SORT_PROPS);\nvar Property;\n(function (Property) {\n Property.MARK = 'mark';\n Property.TRANSFORM = 'transform';\n // Layout\n Property.STACK = 'stack';\n // TODO: sub parts of stack\n // Encoding Properties\n Property.CHANNEL = 'channel';\n Property.AGGREGATE = 'aggregate';\n Property.AUTOCOUNT = 'autoCount';\n Property.BIN = 'bin';\n Property.HAS_FN = 'hasFn';\n Property.TIMEUNIT = 'timeUnit';\n Property.FIELD = 'field';\n Property.TYPE = 'type';\n Property.SORT = 'sort';\n Property.SCALE = 'scale';\n Property.AXIS = 'axis';\n Property.LEGEND = 'legend';\n})(Property = exports.Property || (exports.Property = {}));\n//# sourceMappingURL=property.js.map", + "\"use strict\";\nvar __assign = (this && this.__assign) || Object.assign || function(t) {\n for (var s, i = 1, n = arguments.length; i < n; i++) {\n s = arguments[i];\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))\n t[p] = s[p];\n }\n return t;\n};\nObject.defineProperty(exports, \"__esModule\", { value: true });\nvar util_1 = require(\"./util\");\nvar property_1 = require(\"./property\");\n/**\n * Dictionary that takes property as a key.\n */\nvar PropIndex = (function () {\n function PropIndex(i) {\n if (i === void 0) { i = null; }\n this.index = i ? __assign({}, i) : {};\n }\n PropIndex.prototype.has = function (p) {\n return property_1.toKey(p) in this.index;\n };\n PropIndex.prototype.get = function (p) {\n return this.index[property_1.toKey(p)];\n };\n PropIndex.prototype.set = function (p, value) {\n this.index[property_1.toKey(p)] = value;\n return this;\n };\n PropIndex.prototype.setByKey = function (key, value) {\n this.index[key] = value;\n };\n PropIndex.prototype.map = function (f) {\n var i = new PropIndex();\n for (var k in this.index) {\n i.index[k] = f(this.index[k]);\n }\n return i;\n };\n PropIndex.prototype.size = function () {\n return util_1.keys(this.index).length;\n };\n PropIndex.prototype.duplicate = function () {\n return new PropIndex(this.index);\n };\n return PropIndex;\n}());\nexports.PropIndex = PropIndex;\n//# sourceMappingURL=propindex.js.map", + "\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nvar vlFieldDef = require(\"vega-lite/build/src/fielddef\");\nvar expandedtype_1 = require(\"./expandedtype\");\nvar type_1 = require(\"vega-lite/build/src/compile/scale/type\");\nvar wildcard_1 = require(\"../wildcard\");\nfunction isValueQuery(encQ) {\n return encQ !== null && encQ !== undefined && encQ['value'];\n}\nexports.isValueQuery = isValueQuery;\nfunction isFieldQuery(encQ) {\n return encQ !== null && encQ !== undefined && encQ['field'];\n}\nexports.isFieldQuery = isFieldQuery;\nfunction isAutoCountQuery(encQ) {\n return encQ !== null && encQ !== undefined && 'autoCount' in encQ;\n}\nexports.isAutoCountQuery = isAutoCountQuery;\nfunction isDisabledAutoCountQuery(encQ) {\n return isAutoCountQuery(encQ) && encQ.autoCount === false;\n}\nexports.isDisabledAutoCountQuery = isDisabledAutoCountQuery;\nfunction isEnabledAutoCountQuery(encQ) {\n return isAutoCountQuery(encQ) && encQ.autoCount === true;\n}\nexports.isEnabledAutoCountQuery = isEnabledAutoCountQuery;\nfunction toFieldDef(encQ, props) {\n if (props === void 0) { props = ['aggregate', 'bin', 'timeUnit', 'field', 'type']; }\n if (isFieldQuery(encQ)) {\n return props.reduce(function (fieldDef, prop) {\n if (wildcard_1.isWildcard(encQ[prop])) {\n throw new Error(\"Cannot convert \" + JSON.stringify(encQ) + \" to fielddef: \" + prop + \" is wildcard\");\n }\n else if (encQ[prop] !== undefined) {\n fieldDef[prop] = encQ[prop];\n }\n return fieldDef;\n }, {});\n }\n else {\n if (encQ.autoCount === false) {\n throw new Error(\"Cannot convert {autoCount: false} into a field def\");\n }\n else {\n return props.reduce(function (fieldDef, prop) {\n if (wildcard_1.isWildcard(encQ[prop])) {\n throw new Error(\"Cannot convert \" + JSON.stringify(encQ) + \" to fielddef: \" + prop + \" is wildcard\");\n }\n switch (prop) {\n case 'type':\n fieldDef.type = 'quantitative';\n break;\n case 'aggregate':\n fieldDef.aggregate = 'count';\n break;\n }\n return fieldDef;\n }, {});\n }\n }\n}\nexports.toFieldDef = toFieldDef;\n/**\n * Is a field query continuous field?\n * This method is applicable only for fieldQuery without wildcard\n */\nfunction isContinuous(encQ) {\n return isFieldQuery(encQ) && vlFieldDef.isContinuous(toFieldDef(encQ, ['bin', 'timeUnit', 'field', 'type']));\n}\nexports.isContinuous = isContinuous;\n/**\n * Is a field query discrete field?\n * This method is applicable only for fieldQuery without wildcard\n */\nfunction isDiscrete(encQ) {\n return isFieldQuery(encQ) && vlFieldDef.isDiscrete(toFieldDef(encQ, ['bin', 'timeUnit', 'field', 'type']));\n}\nexports.isDiscrete = isDiscrete;\n/**\n * Returns the true scale type of an encoding.\n * @returns {ScaleType} If the scale type was not specified, it is inferred from the encoding's Type.\n * @returns {undefined} If the scale type was not specified and Type (or TimeUnit if applicable) is a Wildcard, there is no clear scale type\n */\nfunction scaleType(fieldQ) {\n var scale = fieldQ.scale === true || fieldQ.scale === wildcard_1.SHORT_WILDCARD ? {} : fieldQ.scale || {};\n var type = fieldQ.type, channel = fieldQ.channel, timeUnit = fieldQ.timeUnit, bin = fieldQ.bin;\n // HACK: All of markType, and scaleConfig only affect\n // sub-type of ordinal to quantitative scales (point or band)\n // Currently, most of scaleType usage in CompassQL doesn't care about this subtle difference.\n // Thus, instead of making this method requiring the global mark,\n // we will just call it with mark = undefined .\n // Thus, currently, we will always get a point scale unless a CompassQuery specifies band.\n var markType = undefined;\n var scaleConfig = {};\n if (wildcard_1.isWildcard(scale.type) || wildcard_1.isWildcard(type) || wildcard_1.isWildcard(channel) || wildcard_1.isWildcard(bin)) {\n return undefined;\n }\n // If scale type is specified, then use scale.type\n if (scale.type) {\n return scale.type;\n }\n var rangeStep = undefined;\n // Note: Range step currently does not matter as we don't pass mark into compileScaleType anyway.\n // However, if we pass mark, we could use a rule like the following.\n // I also have few test cases listed in encoding.test.ts\n // if (channel === 'x' || channel === 'y') {\n // if (isWildcard(scale.rangeStep)) {\n // if (isShortWildcard(scale.rangeStep)) {\n // return undefined;\n // } else if (scale.rangeStep.enum) {\n // const e = scale.rangeStep.enum;\n // // if enumerated value contains enum then we can't be sure\n // if (contains(e, undefined) || contains(e, null)) {\n // return undefined;\n // }\n // rangeStep = e[0];\n // }\n // }\n // }\n // if type is fixed and it's not temporal, we can ignore time unit.\n if (type === 'temporal' && wildcard_1.isWildcard(timeUnit)) {\n return undefined;\n }\n // if type is fixed and it's not quantitative, we can ignore bin\n if (type === 'quantitative' && wildcard_1.isWildcard(bin)) {\n return undefined;\n }\n var vegaLiteType = type === expandedtype_1.ExpandedType.KEY ? 'nominal' : type;\n var fieldDef = { type: vegaLiteType, timeUnit: timeUnit, bin: bin };\n return type_1.scaleType(scale.type, channel, fieldDef, markType, rangeStep, scaleConfig);\n}\nexports.scaleType = scaleType;\n//# sourceMappingURL=encoding.js.map", + "\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nvar type_1 = require(\"vega-lite/build/src/type\");\nvar ExpandedType;\n(function (ExpandedType) {\n ExpandedType.QUANTITATIVE = type_1.Type.QUANTITATIVE;\n ExpandedType.ORDINAL = type_1.Type.ORDINAL;\n ExpandedType.TEMPORAL = type_1.Type.TEMPORAL;\n ExpandedType.NOMINAL = type_1.Type.NOMINAL;\n ExpandedType.KEY = 'key';\n})(ExpandedType = exports.ExpandedType || (exports.ExpandedType = {}));\nfunction isDiscrete(fieldType) {\n return fieldType === type_1.Type.ORDINAL || fieldType === type_1.Type.NOMINAL || fieldType === ExpandedType.KEY;\n}\nexports.isDiscrete = isDiscrete;\n//# sourceMappingURL=expandedtype.js.map", + "\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nvar util_1 = require(\"datalib/src/util\");\nvar shorthand_1 = require(\"./shorthand\");\nvar property_1 = require(\"../property\");\nvar propindex_1 = require(\"../propindex\");\nvar util_2 = require(\"../util\");\nexports.REPLACE_BLANK_FIELDS = { '*': '' };\nexports.REPLACE_XY_CHANNELS = { x: 'xy', y: 'xy' };\nexports.REPLACE_FACET_CHANNELS = { row: 'facet', column: 'facet' };\nexports.REPLACE_MARK_STYLE_CHANNELS = { color: 'style', opacity: 'style', shape: 'style', size: 'style' };\nfunction isExtendedGroupBy(g) {\n return util_1.isObject(g) && !!g['property'];\n}\nexports.isExtendedGroupBy = isExtendedGroupBy;\nfunction parseGroupBy(groupBy, include, replaceIndex) {\n include = include || new propindex_1.PropIndex();\n replaceIndex = replaceIndex || new propindex_1.PropIndex();\n groupBy.forEach(function (grpBy) {\n if (isExtendedGroupBy(grpBy)) {\n include.setByKey(grpBy.property, true);\n replaceIndex.setByKey(grpBy.property, grpBy.replace);\n }\n else {\n include.setByKey(grpBy, true);\n }\n });\n return {\n include: include,\n replaceIndex: replaceIndex,\n replacer: shorthand_1.getReplacerIndex(replaceIndex)\n };\n}\nexports.parseGroupBy = parseGroupBy;\nfunction toString(groupBy) {\n if (util_1.isArray(groupBy)) {\n return groupBy.map(function (g) {\n if (isExtendedGroupBy(g)) {\n if (g.replace) {\n var replaceIndex_1 = util_2.keys(g.replace).reduce(function (index, valFrom) {\n var valTo = g.replace[valFrom];\n (index[valTo] = index[valTo] || []).push(valFrom);\n return index;\n }, {});\n return g.property + '[' + util_2.keys(replaceIndex_1).map(function (valTo) {\n var valsFrom = replaceIndex_1[valTo].sort();\n return valsFrom.join(',') + '=>' + valTo;\n }).join(';') + ']';\n }\n return g.property;\n }\n return g;\n }).join(',');\n }\n else {\n return groupBy;\n }\n}\nexports.toString = toString;\nexports.GROUP_BY_FIELD_TRANSFORM = [\n property_1.Property.FIELD, property_1.Property.TYPE,\n property_1.Property.AGGREGATE, property_1.Property.BIN, property_1.Property.TIMEUNIT, property_1.Property.STACK\n];\nexports.GROUP_BY_ENCODING = exports.GROUP_BY_FIELD_TRANSFORM.concat([\n {\n property: property_1.Property.CHANNEL,\n replace: {\n 'x': 'xy', 'y': 'xy',\n 'color': 'style', 'size': 'style', 'shape': 'style', 'opacity': 'style',\n 'row': 'facet', 'column': 'facet'\n }\n }\n]);\n//# sourceMappingURL=groupby.js.map", + "\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.encoding = require(\"./encoding\");\nvar normalize_1 = require(\"./normalize\");\nexports.normalize = normalize_1.normalize;\nexports.groupBy = require(\"./groupby\");\nexports.shorthand = require(\"./shorthand\");\nexports.spec = require(\"./spec\");\nexports.transform = require(\"./transform\");\n//# sourceMappingURL=index.js.map", + "\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nvar util_1 = require(\"../util\");\n/**\n * Normalize the non-nested version of the query to a standardize nested\n */\nfunction normalize(q) {\n if (q.groupBy) {\n var nest = {\n groupBy: q.groupBy\n };\n if (q.orderBy) {\n nest.orderGroupBy = q.orderBy;\n }\n var normalizedQ = {\n spec: util_1.duplicate(q.spec),\n nest: [nest],\n };\n if (q.chooseBy) {\n normalizedQ.chooseBy = q.chooseBy;\n }\n if (q.config) {\n normalizedQ.config = q.config;\n }\n return normalizedQ;\n }\n return util_1.duplicate(q); // We will cause side effect to q.spec in SpecQueryModel.build\n}\nexports.normalize = normalize;\n//# sourceMappingURL=normalize.js.map", + "\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nvar aggregate_1 = require(\"vega-lite/build/src/aggregate\");\nvar channel_1 = require(\"vega-lite/build/src/channel\");\nvar timeunit_1 = require(\"vega-lite/build/src/timeunit\");\nvar type_1 = require(\"vega-lite/build/src/type\");\nvar util_1 = require(\"datalib/src/util\");\nvar encoding_1 = require(\"./encoding\");\nvar spec_1 = require(\"./spec\");\nvar wildcard_1 = require(\"../wildcard\");\nvar property_1 = require(\"../property\");\nvar propindex_1 = require(\"../propindex\");\nvar util_2 = require(\"../util\");\nfunction getReplacerIndex(replaceIndex) {\n return replaceIndex.map(function (r) { return getReplacer(r); });\n}\nexports.getReplacerIndex = getReplacerIndex;\nfunction getReplacer(replace) {\n return function (s) {\n if (replace[s] !== undefined) {\n return replace[s];\n }\n return s;\n };\n}\nexports.getReplacer = getReplacer;\nfunction value(v, replacer) {\n if (wildcard_1.isWildcard(v)) {\n // Return the enum array if it's a full wildcard, or just return SHORT_WILDCARD for short ones.\n if (!wildcard_1.isShortWildcard(v) && v.enum) {\n return wildcard_1.SHORT_WILDCARD + JSON.stringify(v.enum);\n }\n else {\n return wildcard_1.SHORT_WILDCARD;\n }\n }\n if (replacer) {\n return replacer(v);\n }\n return v;\n}\nexports.value = value;\nfunction replace(v, replacer) {\n if (replacer) {\n return replacer(v);\n }\n return v;\n}\nexports.replace = replace;\nexports.REPLACE_NONE = new propindex_1.PropIndex();\nexports.INCLUDE_ALL = \n// FIXME: remove manual TRANSFORM concat once we really support enumerating transform.\n[].concat(property_1.DEFAULT_PROP_PRECEDENCE, property_1.SORT_PROPS, [property_1.Property.TRANSFORM, property_1.Property.STACK])\n .reduce(function (pi, prop) { return pi.set(prop, true); }, new propindex_1.PropIndex());\nfunction vlSpec(vlspec, include, replace) {\n if (include === void 0) { include = exports.INCLUDE_ALL; }\n if (replace === void 0) { replace = exports.REPLACE_NONE; }\n var specQ = spec_1.fromSpec(vlspec);\n return spec(specQ, include, replace);\n}\nexports.vlSpec = vlSpec;\nexports.PROPERTY_SUPPORTED_CHANNELS = {\n axis: { x: true, y: true, row: true, column: true },\n legend: { color: true, opacity: true, size: true, shape: true },\n scale: { x: true, y: true, color: true, opacity: true, row: true, column: true, size: true, shape: true },\n sort: { x: true, y: true, path: true, order: true }\n};\n/**\n * Returns a shorthand for a spec query\n * @param specQ a spec query\n * @param include Dict Set listing property types (key) to be included in the shorthand\n * @param replace Dictionary of replace function for values of a particular property type (key)\n */\nfunction spec(specQ, include, replace) {\n if (include === void 0) { include = exports.INCLUDE_ALL; }\n if (replace === void 0) { replace = exports.REPLACE_NONE; }\n var parts = [];\n if (include.get(property_1.Property.MARK)) {\n parts.push(value(specQ.mark, replace.get(property_1.Property.MARK)));\n }\n if (specQ.transform && specQ.transform.length > 0) {\n parts.push('transform:' + JSON.stringify(specQ.transform));\n }\n // TODO: extract this to its own stack method\n if (include.get(property_1.Property.STACK)) {\n var _stack = spec_1.stack(specQ);\n if (_stack) {\n // TODO: Refactor this once we have child stack property.\n // Exclude type since we don't care about type in stack\n var includeExceptType = include.duplicate().set('type', false);\n var field = fieldDef(_stack.fieldEncQ, includeExceptType, replace);\n var groupby = fieldDef(_stack.groupByEncQ, includeExceptType, replace);\n parts.push('stack={field:' + field + ',' +\n (groupby ? 'by:' + groupby + ',' : '') +\n 'offset:' + _stack.offset + '}');\n }\n }\n if (specQ.encodings) {\n var encodings = specQ.encodings.reduce(function (encQs, encQ) {\n // Exclude encoding mapping with autoCount=false as they are basically disabled.\n if (!encoding_1.isDisabledAutoCountQuery(encQ)) {\n var str = encoding(encQ, include, replace);\n if (str) {\n encQs.push(str);\n }\n }\n return encQs;\n }, [])\n .sort() // sort at the end to ignore order\n .join('|');\n if (encodings) {\n parts.push(encodings);\n }\n }\n return parts.join('|');\n}\nexports.spec = spec;\n/**\n * Returns a shorthand for an encoding query\n * @param encQ an encoding query\n * @param include Dict Set listing property types (key) to be included in the shorthand\n * @param replace Dictionary of replace function for values of a particular property type (key)\n */\nfunction encoding(encQ, include, replace) {\n if (include === void 0) { include = exports.INCLUDE_ALL; }\n if (replace === void 0) { replace = exports.REPLACE_NONE; }\n var parts = [];\n if (include.get(property_1.Property.CHANNEL)) {\n parts.push(value(encQ.channel, replace.get(property_1.Property.CHANNEL)));\n }\n if (encoding_1.isFieldQuery(encQ)) {\n var fieldDefStr = fieldDef(encQ, include, replace);\n if (fieldDefStr) {\n parts.push(fieldDefStr);\n }\n }\n else if (encoding_1.isValueQuery(encQ)) {\n parts.push(encQ.value);\n }\n return parts.join(':');\n}\nexports.encoding = encoding;\n/**\n * Returns a field definition shorthand for an encoding query\n * @param encQ an encoding query\n * @param include Dict Set listing property types (key) to be included in the shorthand\n * @param replace Dictionary of replace function for values of a particular property type (key)\n */\nfunction fieldDef(encQ, include, replacer) {\n if (include === void 0) { include = exports.INCLUDE_ALL; }\n if (replacer === void 0) { replacer = exports.REPLACE_NONE; }\n if (include.get(property_1.Property.AGGREGATE) && encoding_1.isDisabledAutoCountQuery(encQ)) {\n return '-';\n }\n var fn = func(encQ, include, replacer);\n var props = fieldDefProps(encQ, include, replacer);\n var fieldAndParams;\n if (encoding_1.isFieldQuery(encQ)) {\n // field\n fieldAndParams = include.get('field') ? value(encQ.field, replacer.get('field')) : '...';\n // type\n if (include.get(property_1.Property.TYPE)) {\n if (wildcard_1.isWildcard(encQ.type)) {\n fieldAndParams += ',' + value(encQ.type, replacer.get(property_1.Property.TYPE));\n }\n else {\n var typeShort = ((encQ.type || type_1.Type.QUANTITATIVE) + '').substr(0, 1);\n fieldAndParams += ',' + value(typeShort, replacer.get(property_1.Property.TYPE));\n }\n }\n // encoding properties\n fieldAndParams += props.map(function (p) {\n var val = p.value instanceof Array ? '[' + p.value + ']' : p.value;\n return ',' + p.key + '=' + val;\n }).join('');\n }\n else if (encoding_1.isAutoCountQuery(encQ)) {\n fieldAndParams = '*,q';\n }\n if (!fieldAndParams) {\n return null;\n }\n if (fn) {\n var fnPrefix = util_1.isString(fn) ? fn : wildcard_1.SHORT_WILDCARD +\n (util_2.keys(fn).length > 0 ? JSON.stringify(fn) : '');\n return fnPrefix + '(' + fieldAndParams + ')';\n }\n return fieldAndParams;\n}\nexports.fieldDef = fieldDef;\n/**\n * Return function part of\n */\nfunction func(fieldQ, include, replacer) {\n if (include.get(property_1.Property.AGGREGATE) && fieldQ.aggregate && !wildcard_1.isWildcard(fieldQ.aggregate)) {\n return replace(fieldQ.aggregate, replacer.get(property_1.Property.AGGREGATE));\n }\n else if (include.get(property_1.Property.AGGREGATE) && encoding_1.isEnabledAutoCountQuery(fieldQ)) {\n // autoCount is considered a part of aggregate\n return replace('count', replacer.get(property_1.Property.AGGREGATE));\n ;\n }\n else if (include.get(property_1.Property.TIMEUNIT) && fieldQ.timeUnit && !wildcard_1.isWildcard(fieldQ.timeUnit)) {\n return replace(fieldQ.timeUnit, replacer.get(property_1.Property.TIMEUNIT));\n }\n else if (include.get(property_1.Property.BIN) && fieldQ.bin && !wildcard_1.isWildcard(fieldQ.bin)) {\n return 'bin';\n }\n else {\n var fn = null;\n for (var _i = 0, _a = [property_1.Property.AGGREGATE, property_1.Property.AUTOCOUNT, property_1.Property.TIMEUNIT, property_1.Property.BIN]; _i < _a.length; _i++) {\n var prop = _a[_i];\n var val = fieldQ[prop];\n if (include.get(prop) && fieldQ[prop] && wildcard_1.isWildcard(val)) {\n // assign fnEnumIndex[prop] = array of enum values or just \"?\" if it is SHORT_WILDCARD\n fn = fn || {};\n fn[prop] = wildcard_1.isShortWildcard(val) ? val : val.enum;\n }\n }\n if (fn && fieldQ.hasFn) {\n fn.hasFn = true;\n }\n return fn;\n }\n}\n/**\n * Return key-value of parameters of field defs\n */\nfunction fieldDefProps(fieldQ, include, replacer) {\n /** Encoding properties e.g., Scale, Axis, Legend */\n var props = [];\n // Parameters of function such as bin will be just top-level properties\n if (!util_2.isBoolean(fieldQ.bin) && !wildcard_1.isShortWildcard(fieldQ.bin)) {\n var bin = fieldQ.bin;\n for (var child in bin) {\n var prop = property_1.getEncodingNestedProp('bin', child);\n if (prop && include.get(prop) && bin[child] !== undefined) {\n props.push({\n key: child,\n value: value(bin[child], replacer.get(prop))\n });\n }\n }\n // Sort to make sure that parameter are ordered consistently\n props.sort(function (a, b) { return a.key.localeCompare(b.key); });\n }\n for (var _i = 0, _a = [property_1.Property.SCALE, property_1.Property.SORT, property_1.Property.AXIS, property_1.Property.LEGEND]; _i < _a.length; _i++) {\n var parent_1 = _a[_i];\n if (!wildcard_1.isWildcard(fieldQ.channel) && !exports.PROPERTY_SUPPORTED_CHANNELS[parent_1][fieldQ.channel]) {\n continue;\n }\n if (include.get(parent_1) && fieldQ[parent_1] !== undefined) {\n var parentValue = fieldQ[parent_1];\n if (util_2.isBoolean(parentValue) || parentValue === null) {\n // `scale`, `axis`, `legend` can be false/null.\n props.push({\n key: parent_1 + '',\n value: parentValue || false // return true or false (false if null)\n });\n }\n else if (util_1.isString(parentValue)) {\n // `sort` can be a string (ascending/descending).\n props.push({\n key: parent_1 + '',\n value: replace(JSON.stringify(parentValue), replacer.get(parent_1))\n });\n }\n else {\n var nestedPropChildren = [];\n for (var child in parentValue) {\n var nestedProp = property_1.getEncodingNestedProp(parent_1, child);\n if (nestedProp && include.get(nestedProp) && parentValue[child] !== undefined) {\n nestedPropChildren.push({\n key: child,\n value: value(parentValue[child], replacer.get(nestedProp))\n });\n }\n }\n if (nestedPropChildren.length > 0) {\n var nestedPropObject = nestedPropChildren.sort(function (a, b) { return a.key.localeCompare(b.key); })\n .reduce(function (o, item) {\n o[item.key] = item.value;\n return o;\n }, {});\n // Sort to make sure that parameter are ordered consistently\n props.push({\n key: parent_1 + '',\n value: JSON.stringify(nestedPropObject)\n });\n }\n }\n }\n }\n return props;\n}\nvar CHANNEL_INDEX = util_1.toMap(channel_1.CHANNELS);\nvar AGGREGATE_OP_INDEX = util_1.toMap(aggregate_1.AGGREGATE_OPS);\nvar SINGLE_TIMEUNIT_INDEX = util_1.toMap(timeunit_1.SINGLE_TIMEUNITS);\nvar MULTI_TIMEUNIT_INDEX = util_1.toMap(timeunit_1.MULTI_TIMEUNITS);\nfunction parse(shorthand) {\n // TODO(https://github.com/uwdata/compassql/issues/259):\n // Do not split directly, but use an upgraded version of `getClosingBraceIndex()`\n var splitShorthand = shorthand.split('|');\n var specQ = { mark: splitShorthand[0], encodings: [] };\n for (var i = 1; i < splitShorthand.length; i++) {\n var part = splitShorthand[i];\n var splitPart = splitWithTail(part, ':', 1);\n var splitPartKey = splitPart[0];\n var splitPartValue = splitPart[1];\n if (CHANNEL_INDEX[splitPartKey] || splitPartKey === '?') {\n var encQ = shorthandParser.encoding(splitPartKey, splitPartValue);\n specQ.encodings.push(encQ);\n continue;\n }\n if (splitPartKey === 'transform') {\n specQ.transform = JSON.parse(splitPartValue);\n continue;\n }\n }\n return specQ;\n}\nexports.parse = parse;\n/**\n * Split a string n times into substrings with the specified delimiter and return them as an array.\n * @param str The string to be split\n * @param delim The delimiter string used to separate the string\n * @param number The value used to determine how many times the string is split\n */\nfunction splitWithTail(str, delim, count) {\n var result = [];\n var lastIndex = 0;\n for (var i = 0; i < count; i++) {\n var indexOfDelim = str.indexOf(delim, lastIndex);\n if (indexOfDelim !== -1) {\n result.push(str.substring(lastIndex, indexOfDelim));\n lastIndex = indexOfDelim + 1;\n }\n else {\n break;\n }\n }\n result.push(str.substr(lastIndex));\n // If the specified count is greater than the number of delimiters that exist in the string,\n // an empty string will be pushed count minus number of delimiter occurence times.\n if (result.length !== count + 1) {\n while (result.length !== count + 1) {\n result.push('');\n }\n }\n return result;\n}\nexports.splitWithTail = splitWithTail;\nvar shorthandParser;\n(function (shorthandParser) {\n function encoding(channel, fieldDefShorthand) {\n var encQ = { channel: channel };\n if (fieldDefShorthand.indexOf('(') !== -1) {\n encQ = fn(encQ, fieldDefShorthand);\n }\n else {\n encQ = rawFieldDef(encQ, splitWithTail(fieldDefShorthand, ',', 2));\n }\n return encQ;\n }\n shorthandParser.encoding = encoding;\n function rawFieldDef(fieldQ, fieldDefPart) {\n fieldQ.field = fieldDefPart[0];\n fieldQ.type = type_1.getFullName(fieldDefPart[1].toUpperCase()) || '?';\n var partParams = fieldDefPart[2];\n var closingBraceIndex = 0;\n var i = 0;\n while (i < partParams.length) {\n var propEqualSignIndex = partParams.indexOf('=', i);\n var parsedValue = void 0;\n if (propEqualSignIndex !== -1) {\n var prop = partParams.substring(i, propEqualSignIndex);\n if (partParams[i + prop.length + 1] === '{') {\n var openingBraceIndex = i + prop.length + 1;\n closingBraceIndex = getClosingIndex(openingBraceIndex, partParams, '}');\n var value_1 = partParams.substring(openingBraceIndex, closingBraceIndex + 1);\n parsedValue = JSON.parse(value_1);\n // index after next comma\n i = closingBraceIndex + 2;\n }\n else if (partParams[i + prop.length + 1] === '[') {\n // find closing square bracket\n var openingBracketIndex = i + prop.length + 1;\n var closingBracketIndex = getClosingIndex(openingBracketIndex, partParams, ']');\n var value_2 = partParams.substring(openingBracketIndex, closingBracketIndex + 1);\n parsedValue = JSON.parse(value_2);\n // index after next comma\n i = closingBracketIndex + 2;\n }\n else {\n var propIndex = i;\n // Substring until the next comma (or end of the string)\n var nextCommaIndex = partParams.indexOf(',', i + prop.length);\n if (nextCommaIndex === -1) {\n nextCommaIndex = partParams.length;\n }\n // index after next comma\n i = nextCommaIndex + 1;\n parsedValue = JSON.parse(partParams.substring(propIndex + prop.length + 1, nextCommaIndex));\n }\n if (property_1.hasNestedProperty(prop)) {\n fieldQ[prop] = parsedValue;\n }\n else {\n // prop is a property of the aggregation function such as bin\n fieldQ.bin[prop] = parsedValue;\n }\n }\n else {\n // something is wrong with the format of the partParams\n // exits loop if don't have then infintie loop\n break;\n }\n }\n return fieldQ;\n }\n shorthandParser.rawFieldDef = rawFieldDef;\n function getClosingIndex(openingBraceIndex, str, closingChar) {\n for (var i = openingBraceIndex; i < str.length; i++) {\n if (str[i] === closingChar) {\n return i;\n }\n }\n }\n shorthandParser.getClosingIndex = getClosingIndex;\n function fn(fieldQ, fieldDefShorthand) {\n // Aggregate, Bin, TimeUnit as wildcard case\n if (fieldDefShorthand[0] === '?') {\n var closingBraceIndex = getClosingIndex(1, fieldDefShorthand, '}');\n var fnEnumIndex = JSON.parse(fieldDefShorthand.substring(1, closingBraceIndex + 1));\n for (var encodingProperty in fnEnumIndex) {\n if (util_2.isArray(fnEnumIndex[encodingProperty])) {\n fieldQ[encodingProperty] = { enum: fnEnumIndex[encodingProperty] };\n }\n else {\n fieldQ[encodingProperty] = fnEnumIndex[encodingProperty];\n }\n }\n return rawFieldDef(fieldQ, splitWithTail(fieldDefShorthand.substring(closingBraceIndex + 2, fieldDefShorthand.length - 1), ',', 2));\n }\n else {\n var func_1 = fieldDefShorthand.substring(0, fieldDefShorthand.indexOf('('));\n var insideFn = fieldDefShorthand.substring(func_1.length + 1, fieldDefShorthand.length - 1);\n var insideFnParts = splitWithTail(insideFn, ',', 2);\n if (AGGREGATE_OP_INDEX[func_1]) {\n fieldQ.aggregate = func_1;\n return rawFieldDef(fieldQ, insideFnParts);\n }\n else if (MULTI_TIMEUNIT_INDEX[func_1] || SINGLE_TIMEUNIT_INDEX[func_1]) {\n fieldQ.timeUnit = func_1;\n return rawFieldDef(fieldQ, insideFnParts);\n }\n else if (func_1 === 'bin') {\n fieldQ.bin = {};\n return rawFieldDef(fieldQ, insideFnParts);\n }\n }\n }\n shorthandParser.fn = fn;\n})(shorthandParser = exports.shorthandParser || (exports.shorthandParser = {}));\n//# sourceMappingURL=shorthand.js.map", + "\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nvar channel_1 = require(\"vega-lite/build/src/channel\");\nvar wildcard_1 = require(\"../wildcard\");\nvar property_1 = require(\"../property\");\nvar util_1 = require(\"../util\");\nvar encoding_1 = require(\"./encoding\");\nvar util_2 = require(\"datalib/src/util\");\n/**\n * Convert a Vega-Lite's ExtendedUnitSpec into a CompassQL's SpecQuery\n * @param {ExtendedUnitSpec} spec\n * @returns\n */\nfunction fromSpec(spec) {\n return util_1.extend(spec.data ? { data: spec.data } : {}, spec.transform ? { transform: spec.transform } : {}, {\n mark: spec.mark,\n encodings: util_1.keys(spec.encoding).map(function (channel) {\n var encQ = { channel: channel };\n var channelDef = spec.encoding[channel];\n for (var prop in channelDef) {\n if (property_1.isEncodingTopLevelProperty(prop) && channelDef[prop] !== undefined) {\n // Currently bin, scale, axis, legend only support boolean, but not null.\n // Therefore convert null to false.\n if (util_1.contains(['bin', 'scale', 'axis', 'legend'], prop) && channelDef[prop] === null) {\n encQ[prop] = false;\n }\n else {\n encQ[prop] = channelDef[prop];\n }\n }\n }\n return encQ;\n })\n }, spec.config ? { config: spec.config } : {});\n}\nexports.fromSpec = fromSpec;\nfunction isAggregate(specQ) {\n return util_1.some(specQ.encodings, function (encQ) {\n return (encoding_1.isFieldQuery(encQ) && !wildcard_1.isWildcard(encQ.aggregate) && !!encQ.aggregate) || encoding_1.isEnabledAutoCountQuery(encQ);\n });\n}\nexports.isAggregate = isAggregate;\n/**\n * @return the stack offset type for the specQuery\n */\nfunction stack(specQ) {\n var config = specQ.config;\n var stacked = config ? config.stack : undefined;\n // Should not have stack explicitly disabled\n if (util_1.contains(['none', null, false], stacked)) {\n return null;\n }\n // Should have stackable mark\n if (!util_1.contains(['bar', 'area'], specQ.mark)) {\n return null;\n }\n // Should be aggregate plot\n if (!isAggregate(specQ)) {\n return null;\n }\n var stackBy = specQ.encodings.reduce(function (sc, encQ) {\n if (util_1.contains(channel_1.STACK_BY_CHANNELS, encQ.channel) && (encoding_1.isValueQuery(encQ) || (encoding_1.isFieldQuery(encQ) && !encQ.aggregate))) {\n sc.push({\n channel: encQ.channel,\n fieldDef: encQ\n });\n }\n return sc;\n }, []);\n if (stackBy.length === 0) {\n return null;\n }\n // Has only one aggregate axis\n var xEncQ = specQ.encodings.reduce(function (f, encQ) {\n return f || (encQ.channel === channel_1.Channel.X ? encQ : null);\n }, null);\n var yEncQ = specQ.encodings.reduce(function (f, encQ) {\n return f || (encQ.channel === channel_1.Channel.Y ? encQ : null);\n }, null);\n // TODO(akshatsh): Check if autoCount undef is ok\n var xIsAggregate = (encoding_1.isFieldQuery(xEncQ) && !!xEncQ.aggregate) || (encoding_1.isAutoCountQuery(xEncQ) && !!xEncQ.autoCount);\n var yIsAggregate = (encoding_1.isFieldQuery(yEncQ) && !!yEncQ.aggregate) || (encoding_1.isAutoCountQuery(yEncQ) && !!yEncQ.autoCount);\n if (xIsAggregate !== yIsAggregate) {\n return {\n groupbyChannel: xIsAggregate ? (!!yEncQ ? channel_1.Y : null) : (!!xEncQ ? channel_1.X : null),\n groupByEncQ: xIsAggregate ? yEncQ : xEncQ,\n fieldChannel: xIsAggregate ? channel_1.X : channel_1.Y,\n fieldEncQ: xIsAggregate ? xEncQ : yEncQ,\n stackBy: stackBy,\n offset: stacked || 'zero'\n };\n }\n return null;\n}\nexports.stack = stack;\nfunction hasWildcard(specQ, opt) {\n if (opt === void 0) { opt = {}; }\n var exclude = opt.exclude ? util_2.toMap(opt.exclude.map(property_1.toKey)) : {};\n if (wildcard_1.isWildcard(specQ.mark) && !exclude['mark']) {\n return true;\n }\n for (var _i = 0, _a = specQ.encodings; _i < _a.length; _i++) {\n var encQ = _a[_i];\n // TODO: implement more efficiently, just check only properties of encQ\n for (var key in encQ) {\n var parentProp = key;\n if (encQ.hasOwnProperty(parentProp) && property_1.isEncodingTopLevelProperty(parentProp)) {\n if (wildcard_1.isWildcard(encQ[parentProp]) && !exclude[parentProp]) {\n return true;\n }\n var propObj = encQ[parentProp];\n for (var childProp in propObj) {\n if (propObj.hasOwnProperty(childProp) && !util_1.contains(['enum', 'name'], childProp)) {\n var prop = {\n parent: parentProp,\n child: childProp\n };\n if (wildcard_1.isWildcard(propObj[childProp]) && !exclude[property_1.toKey(prop)]) {\n return true;\n }\n }\n }\n }\n }\n }\n return false;\n}\nexports.hasWildcard = hasWildcard;\n//# sourceMappingURL=spec.js.map", + "\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\n//# sourceMappingURL=transform.js.map", + "\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nvar type_1 = require(\"vega-lite/build/src/type\");\nvar util_1 = require(\"../util\");\nvar encoding_1 = require(\"../query/encoding\");\nexports.name = 'aggregationQuality';\nfunction score(specM, schema, opt) {\n var feature = aggregationQualityFeature(specM, schema, opt);\n return {\n score: feature.score,\n features: [feature]\n };\n}\nexports.score = score;\nfunction isDimension(encQ) {\n return encoding_1.isDiscrete(encQ) || !!encQ.timeUnit;\n}\nfunction aggregationQualityFeature(specM, _, __) {\n var encodings = specM.getEncodings();\n if (specM.isAggregate()) {\n var isRawContinuous = function (encQ) {\n return encoding_1.isFieldQuery(encQ) && ((encQ.type === type_1.Type.QUANTITATIVE && !encQ.bin && !encQ.aggregate) ||\n (encQ.type === type_1.Type.TEMPORAL && !encQ.timeUnit));\n };\n if (util_1.some(encodings, isRawContinuous)) {\n // These are plots that pollute continuous fields as dimension.\n // They are often intermediate visualizations rather than what users actually want.\n return {\n type: exports.name,\n score: 0.1,\n feature: 'Aggregate with raw continuous'\n };\n }\n if (util_1.some(encodings, function (encQ) { return encoding_1.isFieldQuery(encQ) && isDimension(encQ); })) {\n var hasCount = util_1.some(encodings, function (encQ) {\n return (encoding_1.isFieldQuery(encQ) && encQ.aggregate === 'count') || encoding_1.isEnabledAutoCountQuery(encQ);\n });\n var hasBin = util_1.some(encodings, function (encQ) {\n return encoding_1.isFieldQuery(encQ) && !!encQ.bin;\n });\n if (hasCount) {\n // If there is count, we might add additional count field, making it a little less simple\n // then when we just apply aggregate to Q field\n return {\n type: exports.name,\n score: 0.8,\n feature: 'Aggregate with count'\n };\n }\n else if (hasBin) {\n // This is not as good as binning all the Q and show heatmap\n return {\n type: exports.name,\n score: 0.7,\n feature: 'Aggregate with bin but without count'\n };\n }\n else {\n return {\n type: exports.name,\n score: 0.9,\n feature: 'Aggregate without count and without bin'\n };\n }\n }\n // no dimension -- often not very useful\n return {\n type: exports.name,\n score: 0.3,\n feature: 'Aggregate without dimension'\n };\n }\n else {\n if (util_1.some(encodings, function (encQ) { return encoding_1.isFieldQuery(encQ) && !isDimension(encQ); })) {\n // raw plots with measure -- simplest of all!\n return {\n type: exports.name,\n score: 1,\n feature: 'Raw with measure'\n };\n }\n // raw plots with no measure -- often a lot of occlusion\n return {\n type: exports.name,\n score: 0.2,\n feature: 'Raw without measure'\n };\n }\n}\n//# sourceMappingURL=aggregation.js.map", + "\"use strict\";\n/**\n * Field Type (with Bin and TimeUnit) and Channel Score (Cleveland / Mackinlay based)\n */\nvar __extends = (this && this.__extends) || (function () {\n var extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __assign = (this && this.__assign) || Object.assign || function(t) {\n for (var s, i = 1, n = arguments.length; i < n; i++) {\n s = arguments[i];\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))\n t[p] = s[p];\n }\n return t;\n};\nObject.defineProperty(exports, \"__esModule\", { value: true });\nvar channel_1 = require(\"vega-lite/build/src/channel\");\nvar config_1 = require(\"../../config\");\nvar type_1 = require(\"./type\");\nvar base_1 = require(\"./base\");\n/**\n * Effectiveness Score for preferred axis.\n */\nvar AxisScorer = (function (_super) {\n __extends(AxisScorer, _super);\n function AxisScorer() {\n return _super.call(this, 'Axis') || this;\n }\n AxisScorer.prototype.initScore = function (opt) {\n if (opt === void 0) { opt = {}; }\n opt = __assign({}, config_1.DEFAULT_QUERY_CONFIG, opt);\n var score = {};\n var preferredAxes = [{\n feature: type_1.BIN_Q,\n opt: 'preferredBinAxis'\n }, {\n feature: type_1.T,\n opt: 'preferredTemporalAxis'\n }, {\n feature: type_1.TIMEUNIT_T,\n opt: 'preferredTemporalAxis'\n }, {\n feature: type_1.TIMEUNIT_O,\n opt: 'preferredTemporalAxis'\n }, {\n feature: type_1.O,\n opt: 'preferredOrdinalAxis'\n }, {\n feature: type_1.N,\n opt: 'preferredNominalAxis'\n }];\n preferredAxes.forEach(function (pAxis) {\n if (opt[pAxis.opt] === channel_1.Channel.X) {\n // penalize the other axis\n score[pAxis.feature + '_' + channel_1.Channel.Y] = -0.01;\n }\n else if (opt[pAxis.opt] === channel_1.Channel.Y) {\n // penalize the other axis\n score[pAxis.feature + '_' + channel_1.Channel.X] = -0.01;\n }\n });\n return score;\n };\n AxisScorer.prototype.featurize = function (type, channel) {\n return type + '_' + channel;\n };\n AxisScorer.prototype.getScore = function (specM, _, __) {\n var _this = this;\n return specM.getEncodings().reduce(function (features, encQ) {\n var type = type_1.getExtendedType(encQ);\n var feature = _this.featurize(type, encQ.channel);\n var featureScore = _this.getFeatureScore(feature);\n if (featureScore) {\n features.push(featureScore);\n }\n return features;\n }, []);\n };\n return AxisScorer;\n}(base_1.Scorer));\nexports.AxisScorer = AxisScorer;\n//# sourceMappingURL=axis.js.map", + "\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nvar Scorer = (function () {\n function Scorer(type) {\n this.type = type;\n this.scoreIndex = this.initScore();\n }\n Scorer.prototype.getFeatureScore = function (feature) {\n var type = this.type;\n var score = this.scoreIndex[feature];\n if (score !== undefined) {\n return { type: type, feature: feature, score: score };\n }\n return undefined;\n };\n return Scorer;\n}());\nexports.Scorer = Scorer;\n//# sourceMappingURL=base.js.map", + "\"use strict\";\nvar __extends = (this && this.__extends) || (function () {\n var extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nObject.defineProperty(exports, \"__esModule\", { value: true });\nvar base_1 = require(\"./base\");\nvar encoding_1 = require(\"../../query/encoding\");\n/**\n * Penalize if facet channels are the only dimensions\n */\nvar DimensionScorer = (function (_super) {\n __extends(DimensionScorer, _super);\n function DimensionScorer() {\n return _super.call(this, 'Dimension') || this;\n }\n DimensionScorer.prototype.initScore = function () {\n return {\n row: -2,\n column: -2,\n color: 0,\n opacity: 0,\n size: 0,\n shape: 0\n };\n };\n DimensionScorer.prototype.getScore = function (specM, _, __) {\n var _this = this;\n if (specM.isAggregate()) {\n specM.getEncodings().reduce(function (maxFScore, encQ) {\n if (encoding_1.isFieldQuery(encQ) && !encQ.aggregate) {\n var featureScore = _this.getFeatureScore(encQ.channel + '');\n if (featureScore && featureScore.score > maxFScore.score) {\n return featureScore;\n }\n }\n return maxFScore;\n }, { type: 'Dimension', feature: 'No Dimension', score: -5 });\n }\n return [];\n };\n return DimensionScorer;\n}(base_1.Scorer));\nexports.DimensionScorer = DimensionScorer;\n//# sourceMappingURL=dimension.js.map", + "\"use strict\";\nvar __extends = (this && this.__extends) || (function () {\n var extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nvar __assign = (this && this.__assign) || Object.assign || function(t) {\n for (var s, i = 1, n = arguments.length; i < n; i++) {\n s = arguments[i];\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))\n t[p] = s[p];\n }\n return t;\n};\nObject.defineProperty(exports, \"__esModule\", { value: true });\nvar base_1 = require(\"./base\");\nvar config_1 = require(\"../../config\");\nvar channel_1 = require(\"vega-lite/build/src/channel\");\n/**\n * Effective Score for preferred facet\n */\nvar FacetScorer = (function (_super) {\n __extends(FacetScorer, _super);\n function FacetScorer() {\n return _super.call(this, 'Facet') || this;\n }\n FacetScorer.prototype.initScore = function (opt) {\n opt = __assign({}, config_1.DEFAULT_QUERY_CONFIG, opt);\n var score = {};\n if (opt.preferredFacet === channel_1.Channel.ROW) {\n // penalize the other axis\n score[channel_1.Channel.COLUMN] = -0.01;\n }\n else if (opt.preferredFacet === channel_1.Channel.COLUMN) {\n // penalize the other axis\n score[channel_1.Channel.ROW] = -0.01;\n }\n return score;\n };\n FacetScorer.prototype.getScore = function (specM, _, __) {\n var _this = this;\n return specM.getEncodings().reduce(function (features, encQ) {\n var featureScore = _this.getFeatureScore(encQ.channel);\n if (featureScore) {\n features.push(featureScore);\n }\n return features;\n }, []);\n };\n return FacetScorer;\n}(base_1.Scorer));\nexports.FacetScorer = FacetScorer;\n;\n//# sourceMappingURL=facet.js.map", + "\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nvar axis_1 = require(\"./axis\");\nvar dimension_1 = require(\"./dimension\");\nvar facet_1 = require(\"./facet\");\nvar sizechannel_1 = require(\"./sizechannel\");\nvar typechannel_1 = require(\"./typechannel\");\nvar mark_1 = require(\"./mark\");\nvar SCORERS = [\n new axis_1.AxisScorer(),\n new dimension_1.DimensionScorer(),\n new facet_1.FacetScorer(),\n new mark_1.MarkScorer(),\n new sizechannel_1.SizeChannelScorer(),\n new typechannel_1.TypeChannelScorer()\n];\n// TODO: x/y, row/column preference\n// TODO: stacking\n// TODO: Channel, Cardinality\n// TODO: Penalize over encoding\nfunction effectiveness(specM, schema, opt) {\n var features = SCORERS.reduce(function (f, scorer) {\n var scores = scorer.getScore(specM, schema, opt);\n return f.concat(scores);\n }, []);\n return {\n score: features.reduce(function (s, f) {\n return s + f.score;\n }, 0),\n features: features\n };\n}\nexports.effectiveness = effectiveness;\n//# sourceMappingURL=index.js.map", + "\"use strict\";\nvar __extends = (this && this.__extends) || (function () {\n var extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nObject.defineProperty(exports, \"__esModule\", { value: true });\nvar channel_1 = require(\"vega-lite/build/src/channel\");\nvar mark_1 = require(\"vega-lite/build/src/mark\");\nvar util_1 = require(\"../../util\");\nvar type_1 = require(\"./type\");\nvar base_1 = require(\"./base\");\nvar MarkScorer = (function (_super) {\n __extends(MarkScorer, _super);\n function MarkScorer() {\n return _super.call(this, 'Mark') || this;\n }\n MarkScorer.prototype.initScore = function () {\n return init();\n };\n MarkScorer.prototype.getScore = function (specM, _, __) {\n var mark = specM.getMark();\n if (mark === mark_1.Mark.CIRCLE || mark === mark_1.Mark.SQUARE) {\n mark = mark_1.Mark.POINT;\n }\n var xEncQ = specM.getEncodingQueryByChannel(channel_1.Channel.X);\n var xType = xEncQ ? type_1.getExtendedType(xEncQ) : type_1.NONE;\n var yEncQ = specM.getEncodingQueryByChannel(channel_1.Channel.Y);\n var yType = yEncQ ? type_1.getExtendedType(yEncQ) : type_1.NONE;\n var isOccluded = !specM.isAggregate(); // FIXME\n var feature = xType + '_' + yType + '_' + isOccluded + '_' + mark;\n var featureScore = this.getFeatureScore(feature);\n return [featureScore];\n };\n return MarkScorer;\n}(base_1.Scorer));\nexports.MarkScorer = MarkScorer;\nfunction featurize(xType, yType, hasOcclusion, mark) {\n return xType + '_' + yType + '_' + hasOcclusion + '_' + mark;\n}\nexports.featurize = featurize;\nfunction init() {\n var MEASURES = [type_1.Q, type_1.T];\n var DISCRETE = [type_1.BIN_Q, type_1.TIMEUNIT_O, type_1.O, type_1.N];\n var DISCRETE_OR_NONE = DISCRETE.concat([type_1.NONE]);\n var SCORE = {};\n // QxQ\n MEASURES.forEach(function (xType) {\n MEASURES.forEach(function (yType) {\n // has occlusion\n var occludedQQMark = {\n point: 0,\n text: -0.2,\n tick: -0.5,\n rect: -1,\n bar: -2,\n line: -2,\n area: -2,\n rule: -2.5\n };\n util_1.forEach(occludedQQMark, function (score, mark) {\n var feature = featurize(xType, yType, true, mark);\n SCORE[feature] = score;\n });\n // no occlusion\n // TODO: possible to use connected scatter plot\n var noOccludedQQMark = {\n point: 0,\n text: -0.2,\n tick: -0.5,\n bar: -2,\n line: -2,\n area: -2,\n rule: -2.5\n };\n util_1.forEach(noOccludedQQMark, function (score, mark) {\n var feature = featurize(xType, yType, false, mark);\n SCORE[feature] = score;\n });\n });\n });\n // DxQ, QxD\n MEASURES.forEach(function (xType) {\n // HAS OCCLUSION\n DISCRETE_OR_NONE.forEach(function (yType) {\n var occludedDimensionMeasureMark = {\n tick: 0,\n point: -0.2,\n text: -0.5,\n bar: -2,\n line: -2,\n area: -2,\n rule: -2.5\n };\n util_1.forEach(occludedDimensionMeasureMark, function (score, mark) {\n var feature = featurize(xType, yType, true, mark);\n SCORE[feature] = score;\n // also do the inverse\n var feature2 = featurize(yType, xType, true, mark);\n SCORE[feature2] = score;\n });\n });\n [type_1.TIMEUNIT_T].forEach(function (yType) {\n var occludedDimensionMeasureMark = {\n // For Time Dimension with time scale, tick is not good\n point: 0,\n text: -0.5,\n tick: -1,\n bar: -2,\n line: -2,\n area: -2,\n rule: -2.5\n };\n util_1.forEach(occludedDimensionMeasureMark, function (score, mark) {\n var feature = featurize(xType, yType, true, mark);\n SCORE[feature] = score;\n // also do the inverse\n var feature2 = featurize(yType, xType, true, mark);\n SCORE[feature2] = score;\n });\n });\n // NO OCCLUSION\n [type_1.NONE, type_1.N, type_1.O].forEach(function (yType) {\n var noOccludedQxN = {\n bar: 0,\n point: -0.2,\n tick: -0.25,\n text: -0.3,\n // Line / Area can mislead trend for N\n line: -2,\n area: -2,\n // Non-sense to use rule here\n rule: -2.5\n };\n util_1.forEach(noOccludedQxN, function (score, mark) {\n var feature = featurize(xType, yType, false, mark);\n SCORE[feature] = score;\n // also do the inverse\n var feature2 = featurize(yType, xType, false, mark);\n SCORE[feature2] = score;\n });\n });\n [type_1.BIN_Q].forEach(function (yType) {\n var noOccludedQxBinQ = {\n bar: 0,\n point: -0.2,\n tick: -0.25,\n text: -0.3,\n // Line / Area isn't the best fit for bin\n line: -0.5,\n area: -0.5,\n // Non-sense to use rule here\n rule: -2.5\n };\n util_1.forEach(noOccludedQxBinQ, function (score, mark) {\n var feature = featurize(xType, yType, false, mark);\n SCORE[feature] = score;\n // also do the inverse\n var feature2 = featurize(yType, xType, false, mark);\n SCORE[feature2] = score;\n });\n });\n [type_1.TIMEUNIT_T, type_1.TIMEUNIT_O].forEach(function (yType) {\n // For aggregate / surely no occlusion plot, Temporal with time or ordinal\n // are not that different.\n var noOccludedQxBinQ = {\n line: 0,\n area: -0.1,\n bar: -0.2,\n point: -0.3,\n tick: -0.35,\n text: -0.4,\n // Non-sense to use rule here\n rule: -2.5\n };\n util_1.forEach(noOccludedQxBinQ, function (score, mark) {\n var feature = featurize(xType, yType, false, mark);\n SCORE[feature] = score;\n // also do the inverse\n var feature2 = featurize(yType, xType, false, mark);\n SCORE[feature2] = score;\n });\n });\n });\n [type_1.TIMEUNIT_T].forEach(function (xType) {\n [type_1.TIMEUNIT_T].forEach(function (yType) {\n // has occlusion\n var ttMark = {\n point: 0,\n rect: -0.1,\n text: -0.5,\n tick: -1,\n bar: -2,\n line: -2,\n area: -2,\n rule: -2.5\n };\n // No difference between has occlusion and no occlusion\n // as most of the time, it will be the occluded case.\n util_1.forEach(ttMark, function (score, mark) {\n var feature = featurize(xType, yType, true, mark);\n SCORE[feature] = score;\n });\n util_1.forEach(ttMark, function (score, mark) {\n var feature = featurize(xType, yType, false, mark);\n SCORE[feature] = score;\n });\n });\n DISCRETE_OR_NONE.forEach(function (yType) {\n // has occlusion\n var tdMark = {\n tick: 0,\n point: -0.2,\n text: -0.5,\n rect: -1,\n bar: -2,\n line: -2,\n area: -2,\n rule: -2.5\n };\n // No difference between has occlusion and no occlusion\n // as most of the time, it will be the occluded case.\n util_1.forEach(tdMark, function (score, mark) {\n var feature = featurize(xType, yType, true, mark);\n SCORE[feature] = score;\n });\n util_1.forEach(tdMark, function (score, mark) {\n var feature = featurize(yType, xType, true, mark);\n SCORE[feature] = score;\n });\n util_1.forEach(tdMark, function (score, mark) {\n var feature = featurize(xType, yType, false, mark);\n SCORE[feature] = score;\n });\n util_1.forEach(tdMark, function (score, mark) {\n var feature = featurize(yType, xType, false, mark);\n SCORE[feature] = score;\n });\n });\n });\n // DxD\n DISCRETE_OR_NONE.forEach(function (xType) {\n DISCRETE_OR_NONE.forEach(function (yType) {\n // has occlusion\n var ddMark = {\n point: 0,\n rect: 0,\n text: -0.1,\n tick: -1,\n bar: -2,\n line: -2,\n area: -2,\n rule: -2.5\n };\n // No difference between has occlusion and no occlusion\n util_1.forEach(ddMark, function (score, mark) {\n var feature = featurize(xType, yType, true, mark);\n SCORE[feature] = score;\n });\n util_1.forEach(ddMark, function (score, mark) {\n var feature = featurize(xType, yType, false, mark);\n SCORE[feature] = score;\n });\n });\n });\n return SCORE;\n}\n//# sourceMappingURL=mark.js.map", + "\"use strict\";\nvar __extends = (this && this.__extends) || (function () {\n var extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nObject.defineProperty(exports, \"__esModule\", { value: true });\nvar base_1 = require(\"./base\");\n/**\n * Effectivenss score that penalize size for bar and tick\n */\nvar SizeChannelScorer = (function (_super) {\n __extends(SizeChannelScorer, _super);\n function SizeChannelScorer() {\n return _super.call(this, 'SizeChannel') || this;\n }\n SizeChannelScorer.prototype.initScore = function () {\n return {\n bar_size: -2,\n tick_size: -2\n };\n };\n SizeChannelScorer.prototype.getScore = function (specM, _, __) {\n var _this = this;\n var mark = specM.getMark();\n return specM.getEncodings().reduce(function (featureScores, encQ) {\n var feature = mark + '_' + encQ.channel;\n var featureScore = _this.getFeatureScore(feature);\n if (featureScore) {\n featureScores.push(featureScore);\n }\n return featureScores;\n }, []);\n };\n return SizeChannelScorer;\n}(base_1.Scorer));\nexports.SizeChannelScorer = SizeChannelScorer;\n//# sourceMappingURL=sizechannel.js.map", + "\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nvar scale_1 = require(\"vega-lite/build/src/scale\");\nvar type_1 = require(\"vega-lite/build/src/type\");\nvar encoding_1 = require(\"../../query/encoding\");\nvar expandedtype_1 = require(\"../../query/expandedtype\");\n/**\n * Finer grained data types that takes binning and timeUnit into account.\n */\nvar ExtendedType;\n(function (ExtendedType) {\n ExtendedType[ExtendedType[\"Q\"] = type_1.Type.QUANTITATIVE] = \"Q\";\n ExtendedType[ExtendedType[\"BIN_Q\"] = 'bin_' + type_1.Type.QUANTITATIVE] = \"BIN_Q\";\n ExtendedType[ExtendedType[\"T\"] = type_1.Type.TEMPORAL] = \"T\";\n /**\n * Time Unit Temporal Field with time scale.\n */\n ExtendedType[ExtendedType[\"TIMEUNIT_T\"] = 'timeUnit_time'] = \"TIMEUNIT_T\";\n /**\n * Time Unit Temporal Field with ordinal scale.\n */\n ExtendedType[ExtendedType[\"TIMEUNIT_O\"] = 'timeUnit_' + type_1.Type.ORDINAL] = \"TIMEUNIT_O\";\n ExtendedType[ExtendedType[\"O\"] = type_1.Type.ORDINAL] = \"O\";\n ExtendedType[ExtendedType[\"N\"] = type_1.Type.NOMINAL] = \"N\";\n ExtendedType[ExtendedType[\"K\"] = expandedtype_1.ExpandedType.KEY] = \"K\";\n ExtendedType[ExtendedType[\"NONE\"] = '-'] = \"NONE\";\n})(ExtendedType = exports.ExtendedType || (exports.ExtendedType = {}));\nexports.Q = ExtendedType.Q;\nexports.BIN_Q = ExtendedType.BIN_Q;\nexports.T = ExtendedType.T;\nexports.TIMEUNIT_T = ExtendedType.TIMEUNIT_T;\nexports.TIMEUNIT_O = ExtendedType.TIMEUNIT_O;\nexports.O = ExtendedType.O;\nexports.N = ExtendedType.N;\nexports.K = ExtendedType.K;\nexports.NONE = ExtendedType.NONE;\nfunction getExtendedType(fieldQ) {\n if (fieldQ.bin) {\n return ExtendedType.BIN_Q;\n }\n else if (fieldQ.timeUnit) {\n var sType = encoding_1.scaleType(fieldQ);\n return scale_1.hasDiscreteDomain(sType) ? ExtendedType.TIMEUNIT_O : ExtendedType.TIMEUNIT_T;\n }\n return fieldQ.type;\n}\nexports.getExtendedType = getExtendedType;\n//# sourceMappingURL=type.js.map", + "\"use strict\";\nvar __extends = (this && this.__extends) || (function () {\n var extendStatics = Object.setPrototypeOf ||\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\n return function (d, b) {\n extendStatics(d, b);\n function __() { this.constructor = d; }\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n})();\nObject.defineProperty(exports, \"__esModule\", { value: true });\nvar shorthand_1 = require(\"../../query/shorthand\");\nvar util_1 = require(\"../../util\");\nvar type_1 = require(\"./type\");\nvar base_1 = require(\"./base\");\nexports.TERRIBLE = -10;\n/**\n * Effectiveness score for relationship between\n * Field Type (with Bin and TimeUnit) and Channel Score (Cleveland / Mackinlay based)\n */\nvar TypeChannelScorer = (function (_super) {\n __extends(TypeChannelScorer, _super);\n function TypeChannelScorer() {\n return _super.call(this, 'TypeChannel') || this;\n }\n TypeChannelScorer.prototype.initScore = function () {\n var _this = this;\n var SCORE = {};\n // Continuous Quantitative / Temporal Fields\n var CONTINUOUS_TYPE_CHANNEL_SCORE = {\n x: 0,\n y: 0,\n size: -0.575,\n color: -0.725,\n text: -2,\n opacity: -3,\n shape: exports.TERRIBLE,\n row: exports.TERRIBLE,\n column: exports.TERRIBLE,\n detail: 2 * exports.TERRIBLE\n };\n [type_1.Q, type_1.T, type_1.TIMEUNIT_T].forEach(function (type) {\n util_1.keys(CONTINUOUS_TYPE_CHANNEL_SCORE).forEach(function (channel) {\n SCORE[_this.featurize(type, channel)] = CONTINUOUS_TYPE_CHANNEL_SCORE[channel];\n });\n });\n // Discretized Quantitative / Temporal Fields / Ordinal\n var ORDERED_TYPE_CHANNEL_SCORE = util_1.extend({}, CONTINUOUS_TYPE_CHANNEL_SCORE, {\n row: -0.75,\n column: -0.75,\n shape: -3.1,\n text: -3.2,\n detail: -4\n });\n [type_1.BIN_Q, type_1.TIMEUNIT_O, type_1.O].forEach(function (type) {\n util_1.keys(ORDERED_TYPE_CHANNEL_SCORE).forEach(function (channel) {\n SCORE[_this.featurize(type, channel)] = ORDERED_TYPE_CHANNEL_SCORE[channel];\n });\n });\n var NOMINAL_TYPE_CHANNEL_SCORE = {\n x: 0,\n y: 0,\n color: -0.6,\n shape: -0.65,\n row: -0.7,\n column: -0.7,\n text: -0.8,\n detail: -2,\n size: -3,\n opacity: -3.1,\n };\n util_1.keys(NOMINAL_TYPE_CHANNEL_SCORE).forEach(function (channel) {\n SCORE[_this.featurize(type_1.N, channel)] = NOMINAL_TYPE_CHANNEL_SCORE[channel];\n });\n return SCORE;\n };\n TypeChannelScorer.prototype.featurize = function (type, channel) {\n return type + '_' + channel;\n };\n TypeChannelScorer.prototype.getScore = function (specM, schema, opt) {\n var _this = this;\n var encodingQueryByField = specM.getEncodings().reduce(function (m, encQ) {\n var fieldKey = shorthand_1.fieldDef(encQ);\n (m[fieldKey] = m[fieldKey] || []).push(encQ);\n return m;\n }, {});\n var features = [];\n util_1.forEach(encodingQueryByField, function (encQs) {\n var bestFieldFeature = encQs.reduce(function (best, encQ) {\n var type = type_1.getExtendedType(encQ);\n var feature = _this.featurize(type, encQ.channel);\n var featureScore = _this.getFeatureScore(feature);\n if (best === null || featureScore.score > best.score) {\n return featureScore;\n }\n return best;\n }, null);\n features.push(bestFieldFeature);\n // TODO: add plus for over-encoding of one field\n });\n return features;\n };\n return TypeChannelScorer;\n}(base_1.Scorer));\nexports.TypeChannelScorer = TypeChannelScorer;\n//# sourceMappingURL=typechannel.js.map", + "\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nvar encoding_1 = require(\"../query/encoding\");\nexports.name = 'fieldOrder';\n/**\n * Return ranking score based on indices of encoded fields in the schema.\n * If there are multiple fields, prioritize field on the lower indices of encodings.\n *\n * For example, to compare two specs with two encodings each,\n * first we compare the field on the 0-th index\n * and only compare the field on the 1-th index only if the fields on the 0-th index are the same.\n */\nfunction score(specM, schema, _) {\n var fieldWildcardIndices = specM.wildcardIndex.encodingIndicesByProperty.get('field');\n if (!fieldWildcardIndices) {\n return {\n score: 0,\n features: []\n };\n }\n var encodings = specM.specQuery.encodings;\n var numFields = schema.fieldSchemas.length;\n var features = [];\n var totalScore = 0, base = 1;\n for (var i = fieldWildcardIndices.length - 1; i >= 0; i--) {\n var index = fieldWildcardIndices[i];\n var encoding = encodings[index];\n // Skip ValueQuery as we only care about order of fields.\n var field = void 0;\n if (encoding_1.isFieldQuery(encoding)) {\n field = encoding.field;\n }\n else {\n continue;\n }\n var fieldWildcard = specM.wildcardIndex.encodings[index].get('field');\n var fieldIndex = schema.fieldSchema(field).index;\n // reverse order field with lower index should get higher score and come first\n var score_1 = -fieldIndex * base;\n totalScore += score_1;\n features.push({\n score: score_1,\n type: 'fieldOrder',\n feature: \"field \" + fieldWildcard.name + \" is \" + field + \" (#\" + fieldIndex + \" in the schema)\"\n });\n base *= numFields;\n }\n return {\n score: totalScore,\n features: features\n };\n}\nexports.score = score;\n//# sourceMappingURL=fieldorder.js.map", + "\"use strict\";\nfunction __export(m) {\n for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p];\n}\nObject.defineProperty(exports, \"__esModule\", { value: true });\nvar model_1 = require(\"../model\");\nvar effectiveness_1 = require(\"./effectiveness\");\n__export(require(\"./effectiveness\"));\nexports.aggregation = require(\"./aggregation\");\nexports.fieldOrder = require(\"./fieldorder\");\n/**\n * Registry for all encoding ranking functions\n */\nvar rankingRegistry = {};\n/**\n * Add an ordering function to the registry.\n */\nfunction register(name, keyFn) {\n rankingRegistry[name] = keyFn;\n}\nexports.register = register;\nfunction get(name) {\n return rankingRegistry[name];\n}\nexports.get = get;\nfunction rank(group, query, schema, level) {\n if (!query.nest || level === query.nest.length) {\n if (query.orderBy || query.chooseBy) {\n group.items.sort(comparatorFactory(query.orderBy || query.chooseBy, schema, query.config));\n if (query.chooseBy) {\n if (group.items.length > 0) {\n // for chooseBy -- only keep the top-item\n group.items.splice(1);\n }\n }\n }\n }\n else {\n // sort lower-level nodes first because our ranking takes top-item in the subgroup\n group.items.forEach(function (subgroup) {\n rank(subgroup, query, schema, level + 1);\n });\n if (query.nest[level].orderGroupBy) {\n group.items.sort(groupComparatorFactory(query.nest[level].orderGroupBy, schema, query.config));\n }\n }\n return group;\n}\nexports.rank = rank;\nfunction comparatorFactory(name, schema, opt) {\n return function (m1, m2) {\n if (name instanceof Array) {\n return getScoreDifference(name, m1, m2, schema, opt);\n }\n else {\n return getScoreDifference([name], m1, m2, schema, opt);\n }\n };\n}\nexports.comparatorFactory = comparatorFactory;\nfunction groupComparatorFactory(name, schema, opt) {\n return function (g1, g2) {\n var m1 = model_1.getTopSpecQueryItem(g1);\n var m2 = model_1.getTopSpecQueryItem(g2);\n if (name instanceof Array) {\n return getScoreDifference(name, m1, m2, schema, opt);\n }\n else {\n return getScoreDifference([name], m1, m2, schema, opt);\n }\n };\n}\nexports.groupComparatorFactory = groupComparatorFactory;\nfunction getScoreDifference(name, m1, m2, schema, opt) {\n for (var _i = 0, name_1 = name; _i < name_1.length; _i++) {\n var rankingName = name_1[_i];\n var scoreDifference = getScore(m2, rankingName, schema, opt).score - getScore(m1, rankingName, schema, opt).score;\n if (scoreDifference !== 0) {\n return scoreDifference;\n }\n }\n return 0;\n}\nfunction getScore(model, rankingName, schema, opt) {\n if (model.getRankingScore(rankingName) !== undefined) {\n return model.getRankingScore(rankingName);\n }\n var fn = get(rankingName);\n var score = fn(model, schema, opt);\n model.setRankingScore(rankingName, score);\n return score;\n}\nexports.getScore = getScore;\nexports.EFFECTIVENESS = 'effectiveness';\nregister(exports.EFFECTIVENESS, effectiveness_1.effectiveness);\nregister(exports.aggregation.name, exports.aggregation.score);\nregister(exports.fieldOrder.name, exports.fieldOrder.score);\n//# sourceMappingURL=ranking.js.map", + "\"use strict\";\nvar __assign = (this && this.__assign) || Object.assign || function(t) {\n for (var s, i = 1, n = arguments.length; i < n; i++) {\n s = arguments[i];\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))\n t[p] = s[p];\n }\n return t;\n};\nObject.defineProperty(exports, \"__esModule\", { value: true });\nvar config_1 = require(\"./config\");\nvar generate_1 = require(\"./generate\");\nvar nest_1 = require(\"./nest\");\nvar normalize_1 = require(\"./query/normalize\");\nvar ranking_1 = require(\"./ranking/ranking\");\nfunction recommend(q, schema, config) {\n // 1. Normalize non-nested `groupBy` to always have `groupBy` inside `nest`\n // and merge config with the following precedence\n // query.config > config > DEFAULT_QUERY_CONFIG\n q = __assign({}, normalize_1.normalize(q), { config: __assign({}, config_1.DEFAULT_QUERY_CONFIG, config, q.config) });\n // 2. Generate\n var answerSet = generate_1.generate(q.spec, schema, q.config);\n var nestedAnswerSet = nest_1.nest(answerSet, q.nest);\n var result = ranking_1.rank(nestedAnswerSet, q, schema, 0);\n return {\n query: q,\n result: result\n };\n}\nexports.recommend = recommend;\n//# sourceMappingURL=recommend.js.map", + "\"use strict\";\nvar __assign = (this && this.__assign) || Object.assign || function(t) {\n for (var s, i = 1, n = arguments.length; i < n; i++) {\n s = arguments[i];\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))\n t[p] = s[p];\n }\n return t;\n};\nObject.defineProperty(exports, \"__esModule\", { value: true });\nvar type_1 = require(\"vega-lite/build/src/type\");\nvar bin_1 = require(\"vega-lite/build/src/bin\");\nvar timeunit_1 = require(\"vega-lite/build/src/timeunit\");\nvar stats_1 = require(\"datalib/src/stats\");\nvar type_2 = require(\"datalib/src/import/type\");\nvar dlBin = require(\"datalib/src/bins/bins\");\nvar encoding_1 = require(\"./query/encoding\");\nvar expandedtype_1 = require(\"./query/expandedtype\");\nvar config_1 = require(\"./config\");\nvar util_1 = require(\"./util\");\n/**\n * Build a Schema object.\n *\n * @param data - a set of raw data in the same format that Vega-Lite / Vega takes\n * Basically, it's an array in the form of:\n *\n * [\n * {a: 1, b:2},\n * {a: 2, b:3},\n * ...\n * ]\n *\n * @return a Schema object\n */\nfunction build(data, tableSchema, opt) {\n if (tableSchema === void 0) { tableSchema = { fields: [] }; }\n if (opt === void 0) { opt = {}; }\n opt = util_1.extend({}, config_1.DEFAULT_QUERY_CONFIG, opt);\n // create profiles for each variable\n var summaries = stats_1.summary(data);\n var types = type_2.inferAll(data); // inferAll does stronger type inference than summary\n var tableSchemaFieldIndex = tableSchema.fields.reduce(function (m, field) {\n m[field.name] = field;\n return m;\n }, {});\n var fieldSchemas = summaries.map(function (fieldProfile, index) {\n var name = fieldProfile.field;\n // In Table schema, 'date' doesn't include time so use 'datetime'\n var type = types[name] === 'date' ? PrimitiveType.DATETIME : types[name];\n var distinct = fieldProfile.distinct;\n var vlType;\n if (type === PrimitiveType.NUMBER) {\n vlType = type_1.Type.QUANTITATIVE;\n }\n else if (type === PrimitiveType.INTEGER) {\n // use ordinal or nominal when cardinality of integer type is relatively low and the distinct values are less than an amount specified in options\n if ((distinct < opt.numberNominalLimit) && (distinct / fieldProfile.count < opt.numberNominalProportion)) {\n vlType = type_1.Type.NOMINAL;\n }\n else {\n vlType = type_1.Type.QUANTITATIVE;\n }\n }\n else if (type === PrimitiveType.DATETIME) {\n vlType = type_1.Type.TEMPORAL;\n // need to get correct min/max of date data because datalib's summary method does not\n // calculate this correctly for date types.\n fieldProfile.min = new Date(data[0][name]);\n fieldProfile.max = new Date(data[0][name]);\n for (var _i = 0, data_1 = data; _i < data_1.length; _i++) {\n var dataEntry = data_1[_i];\n var time = new Date(dataEntry[name]).getTime();\n if (time < fieldProfile.min.getTime()) {\n fieldProfile.min = new Date(time);\n }\n if (time > fieldProfile.max.getTime()) {\n fieldProfile.max = new Date(time);\n }\n }\n }\n else {\n vlType = type_1.Type.NOMINAL;\n }\n if (vlType === type_1.Type.NOMINAL\n && distinct / fieldProfile.count > opt.minPercentUniqueForKey\n && fieldProfile.count > opt.minCardinalityForKey) {\n vlType = expandedtype_1.ExpandedType.KEY;\n }\n var fieldSchema = {\n name: name,\n // Need to keep original index for re-exporting TableSchema\n originalIndex: index,\n vlType: vlType,\n type: type,\n stats: fieldProfile,\n timeStats: {},\n binStats: {}\n };\n // extend field schema with table schema field - if present\n var orgFieldSchema = tableSchemaFieldIndex[fieldSchema.name];\n fieldSchema = util_1.extend(fieldSchema, orgFieldSchema);\n return fieldSchema;\n });\n // calculate preset bins for quantitative and temporal data\n for (var _i = 0, fieldSchemas_1 = fieldSchemas; _i < fieldSchemas_1.length; _i++) {\n var fieldSchema = fieldSchemas_1[_i];\n if (fieldSchema.vlType === type_1.Type.QUANTITATIVE) {\n for (var _a = 0, _b = opt.enum.binProps.maxbins; _a < _b.length; _a++) {\n var maxbins = _b[_a];\n fieldSchema.binStats[maxbins] = binSummary(maxbins, fieldSchema.stats);\n }\n }\n else if (fieldSchema.vlType === type_1.Type.TEMPORAL) {\n for (var _c = 0, _d = opt.enum.timeUnit; _c < _d.length; _c++) {\n var unit = _d[_c];\n if (unit !== undefined) {\n fieldSchema.timeStats[unit] = timeSummary(unit, fieldSchema.stats);\n }\n }\n }\n }\n var derivedTableSchema = __assign({}, tableSchema, { fields: fieldSchemas });\n return new Schema(derivedTableSchema);\n}\nexports.build = build;\n// order the field schema when we construct a new Schema\n// this orders the fields in the UI\nvar order = {\n 'nominal': 0,\n 'key': 1,\n 'ordinal': 2,\n 'temporal': 3,\n 'quantitative': 4\n};\nvar Schema = (function () {\n function Schema(tableSchema) {\n this._tableSchema = tableSchema;\n tableSchema.fields.sort(function (a, b) {\n // first order by vlType: nominal < temporal < quantitative < ordinal\n if (order[a.vlType] < order[b.vlType]) {\n return -1;\n }\n else if (order[a.vlType] > order[b.vlType]) {\n return 1;\n }\n else {\n // then order by field (alphabetically)\n return a.name.localeCompare(b.name);\n }\n });\n // Add index for sorting\n tableSchema.fields.forEach(function (fieldSchema, index) { return fieldSchema.index = index; });\n this._fieldSchemaIndex = tableSchema.fields.reduce(function (m, fieldSchema) {\n m[fieldSchema.name] = fieldSchema;\n return m;\n }, {});\n }\n /** @return a list of the field names (for enumerating). */\n Schema.prototype.fieldNames = function () {\n return this._tableSchema.fields.map(function (fieldSchema) { return fieldSchema.name; });\n };\n Object.defineProperty(Schema.prototype, \"fieldSchemas\", {\n /** @return a list of FieldSchemas */\n get: function () {\n return this._tableSchema.fields;\n },\n enumerable: true,\n configurable: true\n });\n Schema.prototype.fieldSchema = function (fieldName) {\n return this._fieldSchemaIndex[fieldName];\n };\n Schema.prototype.tableSchema = function () {\n // the fieldschemas are re-arranged\n // but this is not allowed in table schema.\n // so we will re-order based on original index.\n var tableSchema = util_1.duplicate(this._tableSchema);\n tableSchema.fields.sort(function (a, b) { return a.originalIndex - b.originalIndex; });\n return tableSchema;\n };\n /**\n * @return primitive type of the field if exist, otherwise return null\n */\n Schema.prototype.primitiveType = function (fieldName) {\n return this._fieldSchemaIndex[fieldName] ? this._fieldSchemaIndex[fieldName].type : null;\n };\n /**\n * @return vlType of measturement of the field if exist, otherwise return null\n */\n Schema.prototype.vlType = function (fieldName) {\n return this._fieldSchemaIndex[fieldName] ? this._fieldSchemaIndex[fieldName].vlType : null;\n };\n /** @return cardinality of the field associated with encQ, null if it doesn't exist.\n * @param augmentTimeUnitDomain - TimeUnit field domains will not be augmented if explicitly set to false.\n */\n Schema.prototype.cardinality = function (fieldQ, augmentTimeUnitDomain, excludeInvalid) {\n if (augmentTimeUnitDomain === void 0) { augmentTimeUnitDomain = true; }\n if (excludeInvalid === void 0) { excludeInvalid = false; }\n var fieldSchema = this._fieldSchemaIndex[fieldQ.field];\n if (fieldQ.aggregate || (encoding_1.isAutoCountQuery(fieldQ) && fieldQ.autoCount)) {\n return 1;\n }\n else if (fieldQ.bin) {\n // encQ.bin will either be a boolean or a BinQuery\n var bin = void 0;\n if (typeof fieldQ.bin === 'boolean') {\n // autoMaxBins defaults to 10 if channel is Wildcard\n bin = {\n maxbins: bin_1.autoMaxBins(fieldQ.channel)\n };\n }\n else {\n bin = fieldQ.bin;\n }\n var maxbins = bin.maxbins;\n if (!fieldSchema.binStats[maxbins]) {\n // need to calculate\n fieldSchema.binStats[maxbins] = binSummary(maxbins, fieldSchema.stats);\n }\n // don't need to worry about excludeInvalid here because invalid values don't affect linearly binned field's cardinality\n return fieldSchema.binStats[maxbins].distinct;\n }\n else if (fieldQ.timeUnit) {\n if (augmentTimeUnitDomain) {\n switch (fieldQ.timeUnit) {\n // TODO: this should not always be the case once Vega-Lite supports turning off domain augmenting (VL issue #1385)\n case timeunit_1.TimeUnit.SECONDS: return 60;\n case timeunit_1.TimeUnit.MINUTES: return 60;\n case timeunit_1.TimeUnit.HOURS: return 24;\n case timeunit_1.TimeUnit.DAY: return 7;\n case timeunit_1.TimeUnit.DATE: return 31;\n case timeunit_1.TimeUnit.MONTH: return 12;\n case timeunit_1.TimeUnit.QUARTER: return 4;\n case timeunit_1.TimeUnit.MILLISECONDS: return 1000;\n }\n }\n var unit = fieldQ.timeUnit;\n var timeStats = fieldSchema.timeStats;\n // if the cardinality for the timeUnit is not cached, calculate it\n if (!timeStats[unit]) {\n timeStats[unit] = timeSummary(fieldQ.timeUnit, fieldSchema.stats);\n }\n if (excludeInvalid) {\n return timeStats[unit].distinct - invalidCount(timeStats[unit].unique, ['Invalid Date', null]);\n }\n else {\n return timeStats[unit].distinct;\n }\n }\n else {\n if (fieldSchema) {\n if (excludeInvalid) {\n return fieldSchema.stats.distinct - invalidCount(fieldSchema.stats.unique, [NaN, null]);\n }\n else {\n return fieldSchema.stats.distinct;\n }\n }\n else {\n return null;\n }\n }\n };\n /**\n * Given an EncodingQuery with a timeUnit, returns true if the date field\n * has multiple distinct values for all parts of the timeUnit. Returns undefined\n * if the timeUnit is undefined.\n * i.e.\n * ('yearmonth', [Jan 1 2000, Feb 2 2000] returns false)\n * ('yearmonth', [Jan 1 2000, Feb 2 2001] returns true)\n */\n Schema.prototype.timeUnitHasVariation = function (fieldQ) {\n if (!fieldQ.timeUnit) {\n return;\n }\n // if there is no variation in `date`, there should not be variation in `day`\n if (fieldQ.timeUnit === timeunit_1.TimeUnit.DAY) {\n var dateEncQ = util_1.extend({}, fieldQ, { timeUnit: timeunit_1.TimeUnit.DATE });\n if (this.cardinality(dateEncQ, false, true) <= 1) {\n return false;\n }\n }\n var fullTimeUnit = fieldQ.timeUnit;\n for (var _i = 0, SINGLE_TIMEUNITS_1 = timeunit_1.SINGLE_TIMEUNITS; _i < SINGLE_TIMEUNITS_1.length; _i++) {\n var singleUnit = SINGLE_TIMEUNITS_1[_i];\n if (timeunit_1.containsTimeUnit(fullTimeUnit, singleUnit)) {\n // Create a clone of encQ, but with singleTimeUnit\n var singleUnitEncQ = util_1.extend({}, fieldQ, { timeUnit: singleUnit });\n if (this.cardinality(singleUnitEncQ, false, true) <= 1) {\n return false;\n }\n }\n }\n return true;\n };\n Schema.prototype.domain = function (fieldQueryParts) {\n // TODO: differentiate for field with bin / timeUnit\n var fieldSchema = this._fieldSchemaIndex[fieldQueryParts.field];\n var domain = util_1.keys(fieldSchema.stats.unique);\n if (fieldSchema.vlType === type_1.Type.QUANTITATIVE) {\n // return [min, max], coerced into number types\n return [+fieldSchema.stats.min, +fieldSchema.stats.max];\n }\n else if (fieldSchema.type === PrimitiveType.DATETIME) {\n // return [min, max] dates\n return [fieldSchema.stats.min, fieldSchema.stats.max];\n }\n else if (fieldSchema.type === PrimitiveType.INTEGER ||\n fieldSchema.type === PrimitiveType.NUMBER) {\n // coerce non-quantitative numerical data into number type\n domain = domain.map(function (x) { return +x; });\n return domain.sort(util_1.cmp);\n }\n else if ((fieldSchema.vlType === type_1.Type.ORDINAL) && fieldSchema.ordinalDomain) {\n return fieldSchema.ordinalDomain;\n }\n return domain.map(function (x) {\n // Convert 'null' to null as it is encoded similarly in datalib.\n // This is wrong when it is a string 'null' but that rarely happens.\n return x === 'null' ? null : x;\n }).sort(util_1.cmp);\n };\n /**\n * @return a Summary corresponding to the field of the given EncodingQuery\n */\n Schema.prototype.stats = function (fieldQ) {\n // TODO: differentiate for field with bin / timeUnit vs without\n var fieldSchema = this._fieldSchemaIndex[fieldQ.field];\n return fieldSchema ? fieldSchema.stats : null;\n };\n return Schema;\n}());\nexports.Schema = Schema;\n/**\n * @return a summary of the binning scheme determined from the given max number of bins\n */\nfunction binSummary(maxbins, summary) {\n var bin = dlBin({\n min: summary.min,\n max: summary.max,\n maxbins: maxbins\n });\n // start with summary, pre-binning\n var result = util_1.extend({}, summary);\n result.unique = binUnique(bin, summary.unique);\n result.distinct = (bin.stop - bin.start) / bin.step;\n result.min = bin.start;\n result.max = bin.stop;\n return result;\n}\n/** @return a modified version of the passed summary with unique and distinct set according to the timeunit.\n * Maps 'null' (string) keys to the null value and invalid dates to 'Invalid Date' in the unique dictionary.\n */\nfunction timeSummary(timeunit, summary) {\n var result = util_1.extend({}, summary);\n var unique = {};\n util_1.keys(summary.unique).forEach(function (dateString) {\n // don't convert null value because the Date constructor will actually convert it to a date\n var date = (dateString === 'null') ? null : new Date(dateString);\n // at this point, `date` is either the null value, a valid Date object, or \"Invalid Date\" which is a Date\n var key;\n if (date === null) {\n key = null;\n }\n else if (isNaN(date.getTime())) {\n key = 'Invalid Date';\n }\n else {\n key = ((timeunit === timeunit_1.TimeUnit.DAY) ? date.getDay() : timeunit_1.convert(timeunit, date)).toString();\n }\n unique[key] = (unique[key] || 0) + summary.unique[dateString];\n });\n result.unique = unique;\n result.distinct = util_1.keys(unique).length;\n return result;\n}\n/**\n * @return a new unique object based off of the old unique count and a binning scheme\n */\nfunction binUnique(bin, oldUnique) {\n var newUnique = {};\n for (var value in oldUnique) {\n var bucket = void 0;\n if (value === null) {\n bucket = null;\n }\n else if (isNaN(Number(value))) {\n bucket = NaN;\n }\n else {\n bucket = bin.value(Number(value));\n }\n newUnique[bucket] = (newUnique[bucket] || 0) + oldUnique[value];\n }\n return newUnique;\n}\n/** @return the number of items in list that occur as keys of unique */\nfunction invalidCount(unique, list) {\n return list.reduce(function (prev, cur) {\n return unique[cur] ? prev + 1 : prev;\n }, 0);\n}\nvar PrimitiveType;\n(function (PrimitiveType) {\n PrimitiveType[PrimitiveType[\"STRING\"] = 'string'] = \"STRING\";\n PrimitiveType[PrimitiveType[\"NUMBER\"] = 'number'] = \"NUMBER\";\n PrimitiveType[PrimitiveType[\"INTEGER\"] = 'integer'] = \"INTEGER\";\n PrimitiveType[PrimitiveType[\"BOOLEAN\"] = 'boolean'] = \"BOOLEAN\";\n PrimitiveType[PrimitiveType[\"DATETIME\"] = 'datetime'] = \"DATETIME\";\n})(PrimitiveType = exports.PrimitiveType || (exports.PrimitiveType = {}));\n//# sourceMappingURL=schema.js.map", + "\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nvar channel_1 = require(\"vega-lite/build/src/channel\");\nvar scale_1 = require(\"vega-lite/build/src/scale\");\nvar type_1 = require(\"vega-lite/build/src/type\");\nvar encoding_1 = require(\"./query/encoding\");\nvar expandedtype_1 = require(\"./query/expandedtype\");\nfunction stylize(answerSet, schema, opt) {\n var encQIndex = {};\n answerSet = answerSet.map(function (specM) {\n if (opt.smallRangeStepForHighCardinalityOrFacet) {\n specM = smallRangeStepForHighCardinalityOrFacet(specM, schema, encQIndex, opt);\n }\n if (opt.nominalColorScaleForHighCardinality) {\n specM = nominalColorScaleForHighCardinality(specM, schema, encQIndex, opt);\n }\n if (opt.xAxisOnTopForHighYCardinalityWithoutColumn) {\n specM = xAxisOnTopForHighYCardinalityWithoutColumn(specM, schema, encQIndex, opt);\n }\n return specM;\n });\n return answerSet;\n}\nexports.stylize = stylize;\nfunction smallRangeStepForHighCardinalityOrFacet(specM, schema, encQIndex, opt) {\n [channel_1.Channel.ROW, channel_1.Channel.Y, channel_1.Channel.COLUMN, channel_1.Channel.X].forEach(function (channel) {\n encQIndex[channel] = specM.getEncodingQueryByChannel(channel);\n });\n var yEncQ = encQIndex[channel_1.Channel.Y];\n if (yEncQ !== undefined && encoding_1.isFieldQuery(yEncQ)) {\n if (encQIndex[channel_1.Channel.ROW] ||\n schema.cardinality(yEncQ) > opt.smallRangeStepForHighCardinalityOrFacet.maxCardinality) {\n // We check for undefined rather than\n // yEncQ.scale = yEncQ.scale || {} to cover the case where\n // yEncQ.scale has been set to false/null.\n // This prevents us from incorrectly overriding scale and\n // assigning a rangeStep when scale is set to false.\n if (yEncQ.scale === undefined) {\n yEncQ.scale = {};\n }\n // We do not want to assign a rangeStep if scale is set to false\n // and we only apply this if the scale is (or can be) an ordinal scale.\n var yScaleType = encoding_1.scaleType(yEncQ);\n if (yEncQ.scale && (yScaleType === undefined || scale_1.hasDiscreteDomain(yScaleType))) {\n if (!yEncQ.scale.rangeStep) {\n yEncQ.scale.rangeStep = 12;\n }\n }\n }\n }\n var xEncQ = encQIndex[channel_1.Channel.X];\n if (encoding_1.isFieldQuery(xEncQ)) {\n if (encQIndex[channel_1.Channel.COLUMN] ||\n schema.cardinality(xEncQ) > opt.smallRangeStepForHighCardinalityOrFacet.maxCardinality) {\n // Just like y, we don't want to do this if scale is null/false\n if (xEncQ.scale === undefined) {\n xEncQ.scale = {};\n }\n // We do not want to assign a rangeStep if scale is set to false\n // and we only apply this if the scale is (or can be) an ordinal scale.\n var xScaleType = encoding_1.scaleType(xEncQ);\n if (xEncQ.scale && (xScaleType === undefined || scale_1.hasDiscreteDomain(xScaleType))) {\n if (!xEncQ.scale.rangeStep) {\n xEncQ.scale.rangeStep = 12;\n }\n }\n }\n }\n return specM;\n}\nexports.smallRangeStepForHighCardinalityOrFacet = smallRangeStepForHighCardinalityOrFacet;\nfunction nominalColorScaleForHighCardinality(specM, schema, encQIndex, opt) {\n encQIndex[channel_1.Channel.COLOR] = specM.getEncodingQueryByChannel(channel_1.Channel.COLOR);\n var colorEncQ = encQIndex[channel_1.Channel.COLOR];\n if (encoding_1.isFieldQuery(colorEncQ) && (colorEncQ !== undefined) && (colorEncQ.type === type_1.Type.NOMINAL || colorEncQ.type === expandedtype_1.ExpandedType.KEY) &&\n (schema.cardinality(colorEncQ) > opt.nominalColorScaleForHighCardinality.maxCardinality)) {\n if (colorEncQ.scale === undefined) {\n colorEncQ.scale = {};\n }\n if (colorEncQ.scale) {\n if (!colorEncQ.scale.range) {\n colorEncQ.scale.range = opt.nominalColorScaleForHighCardinality.palette;\n }\n }\n }\n return specM;\n}\nexports.nominalColorScaleForHighCardinality = nominalColorScaleForHighCardinality;\nfunction xAxisOnTopForHighYCardinalityWithoutColumn(specM, schema, encQIndex, opt) {\n [channel_1.Channel.COLUMN, channel_1.Channel.X, channel_1.Channel.Y].forEach(function (channel) {\n encQIndex[channel] = specM.getEncodingQueryByChannel(channel);\n });\n if (encQIndex[channel_1.Channel.COLUMN] === undefined) {\n var xEncQ = encQIndex[channel_1.Channel.X];\n var yEncQ = encQIndex[channel_1.Channel.Y];\n if (encoding_1.isFieldQuery(xEncQ) && encoding_1.isFieldQuery(yEncQ) && yEncQ !== undefined && yEncQ.field && scale_1.hasDiscreteDomain(encoding_1.scaleType(yEncQ))) {\n if (xEncQ !== undefined) {\n if (schema.cardinality(yEncQ) > opt.xAxisOnTopForHighYCardinalityWithoutColumn.maxCardinality) {\n if (xEncQ.axis === undefined) {\n xEncQ.axis = {};\n }\n if (xEncQ.axis && !xEncQ.axis.orient) {\n xEncQ.axis.orient = 'top';\n }\n }\n }\n }\n }\n return specM;\n}\nexports.xAxisOnTopForHighYCardinalityWithoutColumn = xAxisOnTopForHighYCardinalityWithoutColumn;\n//# sourceMappingURL=stylize.js.map", + "\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nvar util_1 = require(\"datalib/src/util\");\nvar util_2 = require(\"datalib/src/util\");\nexports.cmp = util_2.cmp;\nexports.keys = util_2.keys;\nexports.duplicate = util_2.duplicate;\nexports.extend = util_2.extend;\nexports.isObject = util_2.isObject;\nexports.isArray = util_2.isArray;\nexports.isBoolean = util_2.isBoolean;\nexports.toMap = util_2.toMap;\nfunction contains(array, item) {\n return array.indexOf(item) !== -1;\n}\nexports.contains = contains;\n;\nfunction every(arr, f) {\n for (var i = 0; i < arr.length; i++) {\n if (!f(arr[i], i)) {\n return false;\n }\n }\n return true;\n}\nexports.every = every;\n;\nfunction forEach(obj, f, thisArg) {\n if (obj.forEach) {\n obj.forEach.call(thisArg, f);\n }\n else {\n for (var k in obj) {\n f.call(thisArg, obj[k], k, obj);\n }\n }\n}\nexports.forEach = forEach;\n;\nfunction some(arr, f) {\n var i = 0, k;\n for (k in arr) {\n if (f(arr[k], k, i++)) {\n return true;\n }\n }\n return false;\n}\nexports.some = some;\n;\nfunction nestedMap(array, f) {\n return array.map(function (a) {\n if (util_1.isArray(a)) {\n return nestedMap(a, f);\n }\n return f(a);\n });\n}\nexports.nestedMap = nestedMap;\n/** Returns the array without the elements in item */\nfunction without(array, excludedItems) {\n return array.filter(function (item) {\n return !contains(excludedItems, item);\n });\n}\nexports.without = without;\n//# sourceMappingURL=util.js.map", + "\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nvar property_1 = require(\"./property\");\nvar util_1 = require(\"./util\");\nvar axis_1 = require(\"vega-lite/build/src/axis\");\nvar channel_1 = require(\"vega-lite/build/src/channel\");\nvar mark_1 = require(\"vega-lite/build/src/mark\");\nvar scale_1 = require(\"vega-lite/build/src/scale\");\nvar legend_1 = require(\"vega-lite/build/src/legend\");\nvar timeunit_1 = require(\"vega-lite/build/src/timeunit\");\nvar type_1 = require(\"vega-lite/build/src/type\");\nexports.SHORT_WILDCARD = '?';\nfunction isWildcard(prop) {\n return isShortWildcard(prop) || isWildcardDef(prop);\n}\nexports.isWildcard = isWildcard;\nfunction isShortWildcard(prop) {\n return prop === exports.SHORT_WILDCARD;\n}\nexports.isShortWildcard = isShortWildcard;\nfunction isWildcardDef(prop) {\n return prop !== undefined && (!!prop.enum || !!prop.name) && !util_1.isArray(prop);\n}\nexports.isWildcardDef = isWildcardDef;\nfunction initWildcard(prop, defaultName, defaultEnumValues) {\n return util_1.extend({}, {\n name: defaultName,\n enum: defaultEnumValues\n }, prop === exports.SHORT_WILDCARD ? {} : prop);\n}\nexports.initWildcard = initWildcard;\n/**\n * Initial short names from list of full camelCaseNames.\n * For each camelCaseNames, return unique short names based on initial (e.g., `ccn`)\n */\nfunction initNestedPropName(fullNames) {\n var index = {};\n var has = {};\n var _loop_1 = function (fullName) {\n var initialIndices = [0];\n for (var i = 0; i < fullName.length; i++) {\n if (fullName.charAt(i).toUpperCase() === fullName.charAt(i)) {\n initialIndices.push(i);\n }\n }\n var shortName = initialIndices.map(function (i) { return fullName.charAt(i); }).join('').toLowerCase();\n if (!has[shortName]) {\n index[fullName] = shortName;\n has[shortName] = true;\n return \"continue\";\n }\n // If duplicate, add last character and try again!\n if (initialIndices[initialIndices.length - 1] !== fullName.length - 1) {\n shortName = initialIndices.concat([fullName.length - 1]).map(function (i) { return fullName.charAt(i); }).join('').toLowerCase();\n if (!has[shortName]) {\n index[fullName] = shortName;\n has[shortName] = true;\n return \"continue\";\n }\n }\n for (var i = 1; !index[fullName]; i++) {\n var shortNameWithNo = shortName + '_' + i;\n if (!has[shortNameWithNo]) {\n index[fullName] = shortNameWithNo;\n has[shortNameWithNo] = true;\n break;\n }\n }\n };\n for (var _i = 0, fullNames_1 = fullNames; _i < fullNames_1.length; _i++) {\n var fullName = fullNames_1[_i];\n _loop_1(fullName);\n }\n return index;\n}\nexports.DEFAULT_NAME = {\n mark: 'm',\n channel: 'c',\n aggregate: 'a',\n autoCount: '#',\n hasFn: 'h',\n bin: 'b',\n sort: 'so',\n scale: 's',\n axis: 'ax',\n legend: 'l',\n timeUnit: 'tu',\n field: 'f',\n type: 't',\n binProps: {\n maxbins: 'mb',\n min: 'mi',\n max: 'ma',\n base: 'b',\n step: 's',\n steps: 'ss',\n minstep: 'ms',\n divide: 'd'\n },\n sortProps: {\n field: 'f',\n op: 'o',\n order: 'or'\n },\n scaleProps: initNestedPropName(scale_1.SCALE_PROPERTIES),\n axisProps: initNestedPropName(axis_1.AXIS_PROPERTIES),\n legendProps: initNestedPropName(legend_1.LEGEND_PROPERTIES)\n};\nfunction getDefaultName(prop) {\n if (property_1.isEncodingNestedProp(prop)) {\n return exports.DEFAULT_NAME[prop.parent] + '-' + exports.DEFAULT_NAME[prop.parent + 'Props'][prop.child];\n }\n if (exports.DEFAULT_NAME[prop]) {\n return exports.DEFAULT_NAME[prop];\n }\n /* istanbul ignore next */\n throw new Error('Default name undefined for ' + prop);\n}\nexports.getDefaultName = getDefaultName;\nvar DEFAULT_BOOLEAN_ENUM = [false, true];\nvar DEFAULT_BIN_PROPS_ENUM = {\n maxbins: [5, 10, 20],\n extent: [undefined],\n base: [10],\n step: [undefined],\n steps: [undefined],\n minstep: [undefined],\n divide: [[5, 2]]\n};\nvar DEFAULT_SORT_PROPS = {\n field: [undefined],\n op: ['min', 'mean'],\n order: ['ascending', 'descending']\n};\nvar DEFAULT_SCALE_PROPS_ENUM = {\n type: [undefined, scale_1.ScaleType.LOG],\n domain: [undefined],\n exponent: [1, 2],\n clamp: DEFAULT_BOOLEAN_ENUM,\n nice: DEFAULT_BOOLEAN_ENUM,\n reverse: DEFAULT_BOOLEAN_ENUM,\n round: DEFAULT_BOOLEAN_ENUM,\n zero: DEFAULT_BOOLEAN_ENUM,\n padding: [undefined],\n paddingInner: [undefined],\n paddingOuter: [undefined],\n interpolate: [undefined],\n range: [undefined],\n rangeStep: [17, 21],\n scheme: [undefined],\n};\nvar DEFAULT_AXIS_PROPS_ENUM = {\n zindex: [1, 0],\n offset: [undefined],\n orient: [undefined],\n values: [undefined],\n domain: DEFAULT_BOOLEAN_ENUM,\n grid: DEFAULT_BOOLEAN_ENUM,\n format: [undefined],\n labels: DEFAULT_BOOLEAN_ENUM,\n labelAngle: [undefined],\n labelOverlap: [undefined],\n labelPadding: [undefined],\n maxExtent: [undefined],\n minExtent: [undefined],\n position: [undefined],\n ticks: DEFAULT_BOOLEAN_ENUM,\n tickCount: [undefined],\n tickExtra: [undefined],\n tickSize: [undefined],\n title: [undefined],\n titleMaxLength: [undefined],\n titlePadding: [undefined]\n};\nvar DEFAULT_LEGEND_PROPS_ENUM = {\n entryPadding: [undefined],\n orient: ['left', 'right'],\n offset: [undefined],\n format: [undefined],\n values: [undefined],\n tickCount: [undefined],\n title: [undefined],\n type: [undefined],\n zindex: [undefined]\n};\n// Use FullEnumIndex to make sure we have all properties specified here!\nexports.DEFAULT_ENUM_INDEX = {\n mark: [mark_1.Mark.POINT, mark_1.Mark.BAR, mark_1.Mark.LINE, mark_1.Mark.AREA, mark_1.Mark.TICK],\n channel: [channel_1.X, channel_1.Y, channel_1.ROW, channel_1.COLUMN, channel_1.SIZE, channel_1.COLOR],\n aggregate: [undefined, 'mean'],\n autoCount: DEFAULT_BOOLEAN_ENUM,\n bin: DEFAULT_BOOLEAN_ENUM,\n hasFn: DEFAULT_BOOLEAN_ENUM,\n timeUnit: [undefined, timeunit_1.TimeUnit.YEAR, timeunit_1.TimeUnit.MONTH, timeunit_1.TimeUnit.MINUTES, timeunit_1.TimeUnit.SECONDS],\n field: [undefined],\n type: [type_1.Type.NOMINAL, type_1.Type.ORDINAL, type_1.Type.QUANTITATIVE, type_1.Type.TEMPORAL],\n sort: ['ascending', 'descending'],\n scale: [true],\n axis: DEFAULT_BOOLEAN_ENUM,\n legend: DEFAULT_BOOLEAN_ENUM,\n binProps: DEFAULT_BIN_PROPS_ENUM,\n sortProps: DEFAULT_SORT_PROPS,\n scaleProps: DEFAULT_SCALE_PROPS_ENUM,\n axisProps: DEFAULT_AXIS_PROPS_ENUM,\n legendProps: DEFAULT_LEGEND_PROPS_ENUM\n};\n// TODO: rename this to getDefaultEnum\nfunction getDefaultEnumValues(prop, schema, opt) {\n if (prop === 'field' || (property_1.isEncodingNestedProp(prop) && prop.parent === 'sort' && prop.child === 'field')) {\n // For field, by default enumerate all fields\n return schema.fieldNames();\n }\n var val;\n if (property_1.isEncodingNestedProp(prop)) {\n val = opt.enum[prop.parent + 'Props'][prop.child];\n }\n else {\n val = opt.enum[prop];\n }\n if (val !== undefined) {\n return val;\n }\n /* istanbul ignore next */\n throw new Error('No default enumValues for ' + JSON.stringify(prop));\n}\nexports.getDefaultEnumValues = getDefaultEnumValues;\n//# sourceMappingURL=wildcard.js.map", + "\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nvar property_1 = require(\"./property\");\nvar propindex_1 = require(\"./propindex\");\nvar WildcardIndex = (function () {\n function WildcardIndex() {\n this._mark = undefined;\n this._encodings = {};\n this._encodingIndicesByProperty = new propindex_1.PropIndex();\n }\n WildcardIndex.prototype.setEncodingProperty = function (index, prop, wildcard) {\n var encodingsIndex = this._encodings;\n // Init encoding index and set prop\n var encIndex = encodingsIndex[index] = encodingsIndex[index] || new propindex_1.PropIndex();\n encIndex.set(prop, wildcard);\n // Initialize indicesByProperty[prop] and add index\n var indicesByProp = this._encodingIndicesByProperty;\n indicesByProp.set(prop, (indicesByProp.get(prop) || []));\n indicesByProp.get(prop).push(index);\n return this;\n };\n WildcardIndex.prototype.hasEncodingProperty = function (index, prop) {\n return !!this._encodings[index] && this._encodings[index].has(prop);\n };\n WildcardIndex.prototype.hasProperty = function (prop) {\n if (property_1.isEncodingProperty(prop)) {\n return this.encodingIndicesByProperty.has(prop);\n }\n if (prop === 'mark') {\n return !!this.mark;\n }\n /* istanbul ignore next */\n throw new Error('Unimplemented for property ' + prop);\n };\n WildcardIndex.prototype.isEmpty = function () {\n return !this.mark && this.encodingIndicesByProperty.size() === 0;\n };\n WildcardIndex.prototype.setMark = function (mark) {\n this._mark = mark;\n return this;\n };\n Object.defineProperty(WildcardIndex.prototype, \"mark\", {\n get: function () {\n return this._mark;\n },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(WildcardIndex.prototype, \"encodings\", {\n get: function () {\n return this._encodings;\n },\n enumerable: true,\n configurable: true\n });\n Object.defineProperty(WildcardIndex.prototype, \"encodingIndicesByProperty\", {\n get: function () {\n return this._encodingIndicesByProperty;\n },\n enumerable: true,\n configurable: true\n });\n return WildcardIndex;\n}());\nexports.WildcardIndex = WildcardIndex;\n//# sourceMappingURL=wildcardindex.js.map", + "", + "(function (global, factory) {\n typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :\n typeof define === 'function' && define.amd ? define('d3-time', ['exports'], factory) :\n factory((global.d3_time = {}));\n}(this, function (exports) { 'use strict';\n\n var t0 = new Date;\n var t1 = new Date;\n function newInterval(floori, offseti, count, field) {\n\n function interval(date) {\n return floori(date = new Date(+date)), date;\n }\n\n interval.floor = interval;\n\n interval.round = function(date) {\n var d0 = new Date(+date),\n d1 = new Date(date - 1);\n floori(d0), floori(d1), offseti(d1, 1);\n return date - d0 < d1 - date ? d0 : d1;\n };\n\n interval.ceil = function(date) {\n return floori(date = new Date(date - 1)), offseti(date, 1), date;\n };\n\n interval.offset = function(date, step) {\n return offseti(date = new Date(+date), step == null ? 1 : Math.floor(step)), date;\n };\n\n interval.range = function(start, stop, step) {\n var range = [];\n start = new Date(start - 1);\n stop = new Date(+stop);\n step = step == null ? 1 : Math.floor(step);\n if (!(start < stop) || !(step > 0)) return range; // also handles Invalid Date\n offseti(start, 1), floori(start);\n if (start < stop) range.push(new Date(+start));\n while (offseti(start, step), floori(start), start < stop) range.push(new Date(+start));\n return range;\n };\n\n interval.filter = function(test) {\n return newInterval(function(date) {\n while (floori(date), !test(date)) date.setTime(date - 1);\n }, function(date, step) {\n while (--step >= 0) while (offseti(date, 1), !test(date));\n });\n };\n\n if (count) {\n interval.count = function(start, end) {\n t0.setTime(+start), t1.setTime(+end);\n floori(t0), floori(t1);\n return Math.floor(count(t0, t1));\n };\n\n interval.every = function(step) {\n step = Math.floor(step);\n return !isFinite(step) || !(step > 0) ? null\n : !(step > 1) ? interval\n : interval.filter(field\n ? function(d) { return field(d) % step === 0; }\n : function(d) { return interval.count(0, d) % step === 0; });\n };\n }\n\n return interval;\n };\n\n var millisecond = newInterval(function() {\n // noop\n }, function(date, step) {\n date.setTime(+date + step);\n }, function(start, end) {\n return end - start;\n });\n\n // An optimized implementation for this simple case.\n millisecond.every = function(k) {\n k = Math.floor(k);\n if (!isFinite(k) || !(k > 0)) return null;\n if (!(k > 1)) return millisecond;\n return newInterval(function(date) {\n date.setTime(Math.floor(date / k) * k);\n }, function(date, step) {\n date.setTime(+date + step * k);\n }, function(start, end) {\n return (end - start) / k;\n });\n };\n\n var second = newInterval(function(date) {\n date.setMilliseconds(0);\n }, function(date, step) {\n date.setTime(+date + step * 1e3);\n }, function(start, end) {\n return (end - start) / 1e3;\n }, function(date) {\n return date.getSeconds();\n });\n\n var minute = newInterval(function(date) {\n date.setSeconds(0, 0);\n }, function(date, step) {\n date.setTime(+date + step * 6e4);\n }, function(start, end) {\n return (end - start) / 6e4;\n }, function(date) {\n return date.getMinutes();\n });\n\n var hour = newInterval(function(date) {\n date.setMinutes(0, 0, 0);\n }, function(date, step) {\n date.setTime(+date + step * 36e5);\n }, function(start, end) {\n return (end - start) / 36e5;\n }, function(date) {\n return date.getHours();\n });\n\n var day = newInterval(function(date) {\n date.setHours(0, 0, 0, 0);\n }, function(date, step) {\n date.setDate(date.getDate() + step);\n }, function(start, end) {\n return (end - start - (end.getTimezoneOffset() - start.getTimezoneOffset()) * 6e4) / 864e5;\n }, function(date) {\n return date.getDate() - 1;\n });\n\n function weekday(i) {\n return newInterval(function(date) {\n date.setHours(0, 0, 0, 0);\n date.setDate(date.getDate() - (date.getDay() + 7 - i) % 7);\n }, function(date, step) {\n date.setDate(date.getDate() + step * 7);\n }, function(start, end) {\n return (end - start - (end.getTimezoneOffset() - start.getTimezoneOffset()) * 6e4) / 6048e5;\n });\n }\n\n var sunday = weekday(0);\n var monday = weekday(1);\n var tuesday = weekday(2);\n var wednesday = weekday(3);\n var thursday = weekday(4);\n var friday = weekday(5);\n var saturday = weekday(6);\n\n var month = newInterval(function(date) {\n date.setHours(0, 0, 0, 0);\n date.setDate(1);\n }, function(date, step) {\n date.setMonth(date.getMonth() + step);\n }, function(start, end) {\n return end.getMonth() - start.getMonth() + (end.getFullYear() - start.getFullYear()) * 12;\n }, function(date) {\n return date.getMonth();\n });\n\n var year = newInterval(function(date) {\n date.setHours(0, 0, 0, 0);\n date.setMonth(0, 1);\n }, function(date, step) {\n date.setFullYear(date.getFullYear() + step);\n }, function(start, end) {\n return end.getFullYear() - start.getFullYear();\n }, function(date) {\n return date.getFullYear();\n });\n\n var utcSecond = newInterval(function(date) {\n date.setUTCMilliseconds(0);\n }, function(date, step) {\n date.setTime(+date + step * 1e3);\n }, function(start, end) {\n return (end - start) / 1e3;\n }, function(date) {\n return date.getUTCSeconds();\n });\n\n var utcMinute = newInterval(function(date) {\n date.setUTCSeconds(0, 0);\n }, function(date, step) {\n date.setTime(+date + step * 6e4);\n }, function(start, end) {\n return (end - start) / 6e4;\n }, function(date) {\n return date.getUTCMinutes();\n });\n\n var utcHour = newInterval(function(date) {\n date.setUTCMinutes(0, 0, 0);\n }, function(date, step) {\n date.setTime(+date + step * 36e5);\n }, function(start, end) {\n return (end - start) / 36e5;\n }, function(date) {\n return date.getUTCHours();\n });\n\n var utcDay = newInterval(function(date) {\n date.setUTCHours(0, 0, 0, 0);\n }, function(date, step) {\n date.setUTCDate(date.getUTCDate() + step);\n }, function(start, end) {\n return (end - start) / 864e5;\n }, function(date) {\n return date.getUTCDate() - 1;\n });\n\n function utcWeekday(i) {\n return newInterval(function(date) {\n date.setUTCHours(0, 0, 0, 0);\n date.setUTCDate(date.getUTCDate() - (date.getUTCDay() + 7 - i) % 7);\n }, function(date, step) {\n date.setUTCDate(date.getUTCDate() + step * 7);\n }, function(start, end) {\n return (end - start) / 6048e5;\n });\n }\n\n var utcSunday = utcWeekday(0);\n var utcMonday = utcWeekday(1);\n var utcTuesday = utcWeekday(2);\n var utcWednesday = utcWeekday(3);\n var utcThursday = utcWeekday(4);\n var utcFriday = utcWeekday(5);\n var utcSaturday = utcWeekday(6);\n\n var utcMonth = newInterval(function(date) {\n date.setUTCHours(0, 0, 0, 0);\n date.setUTCDate(1);\n }, function(date, step) {\n date.setUTCMonth(date.getUTCMonth() + step);\n }, function(start, end) {\n return end.getUTCMonth() - start.getUTCMonth() + (end.getUTCFullYear() - start.getUTCFullYear()) * 12;\n }, function(date) {\n return date.getUTCMonth();\n });\n\n var utcYear = newInterval(function(date) {\n date.setUTCHours(0, 0, 0, 0);\n date.setUTCMonth(0, 1);\n }, function(date, step) {\n date.setUTCFullYear(date.getUTCFullYear() + step);\n }, function(start, end) {\n return end.getUTCFullYear() - start.getUTCFullYear();\n }, function(date) {\n return date.getUTCFullYear();\n });\n\n var milliseconds = millisecond.range;\n var seconds = second.range;\n var minutes = minute.range;\n var hours = hour.range;\n var days = day.range;\n var sundays = sunday.range;\n var mondays = monday.range;\n var tuesdays = tuesday.range;\n var wednesdays = wednesday.range;\n var thursdays = thursday.range;\n var fridays = friday.range;\n var saturdays = saturday.range;\n var weeks = sunday.range;\n var months = month.range;\n var years = year.range;\n\n var utcMillisecond = millisecond;\n var utcMilliseconds = milliseconds;\n var utcSeconds = utcSecond.range;\n var utcMinutes = utcMinute.range;\n var utcHours = utcHour.range;\n var utcDays = utcDay.range;\n var utcSundays = utcSunday.range;\n var utcMondays = utcMonday.range;\n var utcTuesdays = utcTuesday.range;\n var utcWednesdays = utcWednesday.range;\n var utcThursdays = utcThursday.range;\n var utcFridays = utcFriday.range;\n var utcSaturdays = utcSaturday.range;\n var utcWeeks = utcSunday.range;\n var utcMonths = utcMonth.range;\n var utcYears = utcYear.range;\n\n var version = \"0.1.1\";\n\n exports.version = version;\n exports.milliseconds = milliseconds;\n exports.seconds = seconds;\n exports.minutes = minutes;\n exports.hours = hours;\n exports.days = days;\n exports.sundays = sundays;\n exports.mondays = mondays;\n exports.tuesdays = tuesdays;\n exports.wednesdays = wednesdays;\n exports.thursdays = thursdays;\n exports.fridays = fridays;\n exports.saturdays = saturdays;\n exports.weeks = weeks;\n exports.months = months;\n exports.years = years;\n exports.utcMillisecond = utcMillisecond;\n exports.utcMilliseconds = utcMilliseconds;\n exports.utcSeconds = utcSeconds;\n exports.utcMinutes = utcMinutes;\n exports.utcHours = utcHours;\n exports.utcDays = utcDays;\n exports.utcSundays = utcSundays;\n exports.utcMondays = utcMondays;\n exports.utcTuesdays = utcTuesdays;\n exports.utcWednesdays = utcWednesdays;\n exports.utcThursdays = utcThursdays;\n exports.utcFridays = utcFridays;\n exports.utcSaturdays = utcSaturdays;\n exports.utcWeeks = utcWeeks;\n exports.utcMonths = utcMonths;\n exports.utcYears = utcYears;\n exports.millisecond = millisecond;\n exports.second = second;\n exports.minute = minute;\n exports.hour = hour;\n exports.day = day;\n exports.sunday = sunday;\n exports.monday = monday;\n exports.tuesday = tuesday;\n exports.wednesday = wednesday;\n exports.thursday = thursday;\n exports.friday = friday;\n exports.saturday = saturday;\n exports.week = sunday;\n exports.month = month;\n exports.year = year;\n exports.utcSecond = utcSecond;\n exports.utcMinute = utcMinute;\n exports.utcHour = utcHour;\n exports.utcDay = utcDay;\n exports.utcSunday = utcSunday;\n exports.utcMonday = utcMonday;\n exports.utcTuesday = utcTuesday;\n exports.utcWednesday = utcWednesday;\n exports.utcThursday = utcThursday;\n exports.utcFriday = utcFriday;\n exports.utcSaturday = utcSaturday;\n exports.utcWeek = utcSunday;\n exports.utcMonth = utcMonth;\n exports.utcYear = utcYear;\n exports.interval = newInterval;\n\n}));", + "var util = require('../util'),\n time = require('../time'),\n EPSILON = 1e-15;\n\nfunction bins(opt) {\n if (!opt) { throw Error(\"Missing binning options.\"); }\n\n // determine range\n var maxb = opt.maxbins || 15,\n base = opt.base || 10,\n logb = Math.log(base),\n div = opt.div || [5, 2],\n min = opt.min,\n max = opt.max,\n span = max - min,\n step, level, minstep, precision, v, i, eps;\n\n if (opt.step) {\n // if step size is explicitly given, use that\n step = opt.step;\n } else if (opt.steps) {\n // if provided, limit choice to acceptable step sizes\n step = opt.steps[Math.min(\n opt.steps.length - 1,\n bisect(opt.steps, span/maxb, 0, opt.steps.length)\n )];\n } else {\n // else use span to determine step size\n level = Math.ceil(Math.log(maxb) / logb);\n minstep = opt.minstep || 0;\n step = Math.max(\n minstep,\n Math.pow(base, Math.round(Math.log(span) / logb) - level)\n );\n\n // increase step size if too many bins\n while (Math.ceil(span/step) > maxb) { step *= base; }\n\n // decrease step size if allowed\n for (i=0; i= minstep && span / v <= maxb) step = v;\n }\n }\n\n // update precision, min and max\n v = Math.log(step);\n precision = v >= 0 ? 0 : ~~(-v / logb) + 1;\n eps = Math.pow(base, -precision - 1);\n min = Math.min(min, Math.floor(min / step + eps) * step);\n max = Math.ceil(max / step) * step;\n\n return {\n start: min,\n stop: max,\n step: step,\n unit: {precision: precision},\n value: value,\n index: index\n };\n}\n\nfunction bisect(a, x, lo, hi) {\n while (lo < hi) {\n var mid = lo + hi >>> 1;\n if (util.cmp(a[mid], x) < 0) { lo = mid + 1; }\n else { hi = mid; }\n }\n return lo;\n}\n\nfunction value(v) {\n return this.step * Math.floor(v / this.step + EPSILON);\n}\n\nfunction index(v) {\n return Math.floor((v - this.start) / this.step + EPSILON);\n}\n\nfunction date_value(v) {\n return this.unit.date(value.call(this, v));\n}\n\nfunction date_index(v) {\n return index.call(this, this.unit.unit(v));\n}\n\nbins.date = function(opt) {\n if (!opt) { throw Error(\"Missing date binning options.\"); }\n\n // find time step, then bin\n var units = opt.utc ? time.utc : time,\n dmin = opt.min,\n dmax = opt.max,\n maxb = opt.maxbins || 20,\n minb = opt.minbins || 4,\n span = (+dmax) - (+dmin),\n unit = opt.unit ? units[opt.unit] : units.find(span, minb, maxb),\n spec = bins({\n min: unit.min != null ? unit.min : unit.unit(dmin),\n max: unit.max != null ? unit.max : unit.unit(dmax),\n maxbins: maxb,\n minstep: unit.minstep,\n steps: unit.step\n });\n\n spec.unit = unit;\n spec.index = date_index;\n if (!opt.raw) spec.value = date_value;\n return spec;\n};\n\nmodule.exports = bins;\n", + "var util = require('./util'),\n gen = module.exports;\n\ngen.repeat = function(val, n) {\n var a = Array(n), i;\n for (i=0; i stop) range.push(j);\n else while ((j = start + step * ++i) < stop) range.push(j);\n return range;\n};\n\ngen.random = {};\n\ngen.random.uniform = function(min, max) {\n if (max === undefined) {\n max = min === undefined ? 1 : min;\n min = 0;\n }\n var d = max - min;\n var f = function() {\n return min + d * Math.random();\n };\n f.samples = function(n) {\n return gen.zeros(n).map(f);\n };\n f.pdf = function(x) {\n return (x >= min && x <= max) ? 1/d : 0;\n };\n f.cdf = function(x) {\n return x < min ? 0 : x > max ? 1 : (x - min) / d;\n };\n f.icdf = function(p) {\n return (p >= 0 && p <= 1) ? min + p*d : NaN;\n };\n return f;\n};\n\ngen.random.integer = function(a, b) {\n if (b === undefined) {\n b = a;\n a = 0;\n }\n var d = b - a;\n var f = function() {\n return a + Math.floor(d * Math.random());\n };\n f.samples = function(n) {\n return gen.zeros(n).map(f);\n };\n f.pdf = function(x) {\n return (x === Math.floor(x) && x >= a && x < b) ? 1/d : 0;\n };\n f.cdf = function(x) {\n var v = Math.floor(x);\n return v < a ? 0 : v >= b ? 1 : (v - a + 1) / d;\n };\n f.icdf = function(p) {\n return (p >= 0 && p <= 1) ? a - 1 + Math.floor(p*d) : NaN;\n };\n return f;\n};\n\ngen.random.normal = function(mean, stdev) {\n mean = mean || 0;\n stdev = stdev || 1;\n var next;\n var f = function() {\n var x = 0, y = 0, rds, c;\n if (next !== undefined) {\n x = next;\n next = undefined;\n return x;\n }\n do {\n x = Math.random()*2-1;\n y = Math.random()*2-1;\n rds = x*x + y*y;\n } while (rds === 0 || rds > 1);\n c = Math.sqrt(-2*Math.log(rds)/rds); // Box-Muller transform\n next = mean + y*c*stdev;\n return mean + x*c*stdev;\n };\n f.samples = function(n) {\n return gen.zeros(n).map(f);\n };\n f.pdf = function(x) {\n var exp = Math.exp(Math.pow(x-mean, 2) / (-2 * Math.pow(stdev, 2)));\n return (1 / (stdev * Math.sqrt(2*Math.PI))) * exp;\n };\n f.cdf = function(x) {\n // Approximation from West (2009)\n // Better Approximations to Cumulative Normal Functions\n var cd,\n z = (x - mean) / stdev,\n Z = Math.abs(z);\n if (Z > 37) {\n cd = 0;\n } else {\n var sum, exp = Math.exp(-Z*Z/2);\n if (Z < 7.07106781186547) {\n sum = 3.52624965998911e-02 * Z + 0.700383064443688;\n sum = sum * Z + 6.37396220353165;\n sum = sum * Z + 33.912866078383;\n sum = sum * Z + 112.079291497871;\n sum = sum * Z + 221.213596169931;\n sum = sum * Z + 220.206867912376;\n cd = exp * sum;\n sum = 8.83883476483184e-02 * Z + 1.75566716318264;\n sum = sum * Z + 16.064177579207;\n sum = sum * Z + 86.7807322029461;\n sum = sum * Z + 296.564248779674;\n sum = sum * Z + 637.333633378831;\n sum = sum * Z + 793.826512519948;\n sum = sum * Z + 440.413735824752;\n cd = cd / sum;\n } else {\n sum = Z + 0.65;\n sum = Z + 4 / sum;\n sum = Z + 3 / sum;\n sum = Z + 2 / sum;\n sum = Z + 1 / sum;\n cd = exp / sum / 2.506628274631;\n }\n }\n return z > 0 ? 1 - cd : cd;\n };\n f.icdf = function(p) {\n // Approximation of Probit function using inverse error function.\n if (p <= 0 || p >= 1) return NaN;\n var x = 2*p - 1,\n v = (8 * (Math.PI - 3)) / (3 * Math.PI * (4-Math.PI)),\n a = (2 / (Math.PI*v)) + (Math.log(1 - Math.pow(x,2)) / 2),\n b = Math.log(1 - (x*x)) / v,\n s = (x > 0 ? 1 : -1) * Math.sqrt(Math.sqrt((a*a) - b) - a);\n return mean + stdev * Math.SQRT2 * s;\n };\n return f;\n};\n\ngen.random.bootstrap = function(domain, smooth) {\n // Generates a bootstrap sample from a set of observations.\n // Smooth bootstrapping adds random zero-centered noise to the samples.\n var val = domain.filter(util.isValid),\n len = val.length,\n err = smooth ? gen.random.normal(0, smooth) : null;\n var f = function() {\n return val[~~(Math.random()*len)] + (err ? err() : 0);\n };\n f.samples = function(n) {\n return gen.zeros(n).map(f);\n };\n return f;\n};", + "var util = require('../util');\n\nvar TYPES = '__types__';\n\nvar PARSERS = {\n boolean: util.boolean,\n integer: util.number,\n number: util.number,\n date: util.date,\n string: function(x) { return x == null || x === '' ? null : x + ''; }\n};\n\nvar TESTS = {\n boolean: function(x) { return x==='true' || x==='false' || util.isBoolean(x); },\n integer: function(x) { return TESTS.number(x) && (x=+x) === ~~x; },\n number: function(x) { return !isNaN(+x) && !util.isDate(x); },\n date: function(x) { return !isNaN(Date.parse(x)); }\n};\n\nfunction annotation(data, types) {\n if (!types) return data && data[TYPES] || null;\n data[TYPES] = types;\n}\n\nfunction fieldNames(datum) {\n return util.keys(datum);\n}\n\nfunction bracket(fieldName) {\n return '[' + fieldName + ']';\n}\n\nfunction type(values, f) {\n values = util.array(values);\n f = util.$(f);\n var v, i, n;\n\n // if data array has type annotations, use them\n if (values[TYPES]) {\n v = f(values[TYPES]);\n if (util.isString(v)) return v;\n }\n\n for (i=0, n=values.length; !util.isValid(v) && i 0 ? Math.pow(mean, 1/c) : 0;\n return mean;\n};\n\n// Compute the harmonic mean of an array of numbers.\nstats.mean.harmonic = function(values, f) {\n f = util.$(f);\n var mean = 0, c, n, v, i;\n for (i=0, c=0, n=values.length; i b) b = v;\n }\n }\n return [a, b];\n};\n\n// Find the integer indices of the minimum and maximum values.\nstats.extent.index = function(values, f) {\n f = util.$(f);\n var x = -1, y = -1, a, b, v, i, n = values.length;\n for (i=0; i b) { b = v; y = i; }\n }\n }\n return [x, y];\n};\n\n// Compute the dot product of two arrays of numbers.\nstats.dot = function(values, a, b) {\n var sum = 0, i, v;\n if (!b) {\n if (values.length !== a.length) {\n throw Error('Array lengths must match.');\n }\n for (i=0; i -1 && p !== v) {\n mu = 1 + (i-1 + tie) / 2;\n for (; tie -1) {\n mu = 1 + (n-1 + tie) / 2;\n for (; tie max) max = x;\n delta = x - mean;\n mean = mean + delta / (++valid);\n M2 = M2 + delta * (x - mean);\n vals.push(x);\n }\n }\n M2 = M2 / (valid - 1);\n sd = Math.sqrt(M2);\n\n // sort values for median and iqr\n vals.sort(util.cmp);\n\n return {\n type: type(values, f),\n unique: u,\n count: values.length,\n valid: valid,\n missing: missing,\n distinct: distinct,\n min: min,\n max: max,\n mean: mean,\n stdev: sd,\n median: (v = stats.quantile(vals, 0.5)),\n q1: stats.quantile(vals, 0.25),\n q3: stats.quantile(vals, 0.75),\n modeskew: sd === 0 ? 0 : (mean - v) / sd\n };\n};\n\n// Compute profiles for all variables in a data set.\nstats.summary = function(data, fields) {\n fields = fields || util.keys(data[0]);\n var s = fields.map(function(f) {\n var p = stats.profile(data, util.$(f));\n return (p.field = f, p);\n });\n return (s.__summary__ = true, s);\n};\n", + "var d3_time = require('d3-time');\n\nvar tempDate = new Date(),\n baseDate = new Date(0, 0, 1).setFullYear(0), // Jan 1, 0 AD\n utcBaseDate = new Date(Date.UTC(0, 0, 1)).setUTCFullYear(0);\n\nfunction date(d) {\n return (tempDate.setTime(+d), tempDate);\n}\n\n// create a time unit entry\nfunction entry(type, date, unit, step, min, max) {\n var e = {\n type: type,\n date: date,\n unit: unit\n };\n if (step) {\n e.step = step;\n } else {\n e.minstep = 1;\n }\n if (min != null) e.min = min;\n if (max != null) e.max = max;\n return e;\n}\n\nfunction create(type, unit, base, step, min, max) {\n return entry(type,\n function(d) { return unit.offset(base, d); },\n function(d) { return unit.count(base, d); },\n step, min, max);\n}\n\nvar locale = [\n create('second', d3_time.second, baseDate),\n create('minute', d3_time.minute, baseDate),\n create('hour', d3_time.hour, baseDate),\n create('day', d3_time.day, baseDate, [1, 7]),\n create('month', d3_time.month, baseDate, [1, 3, 6]),\n create('year', d3_time.year, baseDate),\n\n // periodic units\n entry('seconds',\n function(d) { return new Date(1970, 0, 1, 0, 0, d); },\n function(d) { return date(d).getSeconds(); },\n null, 0, 59\n ),\n entry('minutes',\n function(d) { return new Date(1970, 0, 1, 0, d); },\n function(d) { return date(d).getMinutes(); },\n null, 0, 59\n ),\n entry('hours',\n function(d) { return new Date(1970, 0, 1, d); },\n function(d) { return date(d).getHours(); },\n null, 0, 23\n ),\n entry('weekdays',\n function(d) { return new Date(1970, 0, 4+d); },\n function(d) { return date(d).getDay(); },\n [1], 0, 6\n ),\n entry('dates',\n function(d) { return new Date(1970, 0, d); },\n function(d) { return date(d).getDate(); },\n [1], 1, 31\n ),\n entry('months',\n function(d) { return new Date(1970, d % 12, 1); },\n function(d) { return date(d).getMonth(); },\n [1], 0, 11\n )\n];\n\nvar utc = [\n create('second', d3_time.utcSecond, utcBaseDate),\n create('minute', d3_time.utcMinute, utcBaseDate),\n create('hour', d3_time.utcHour, utcBaseDate),\n create('day', d3_time.utcDay, utcBaseDate, [1, 7]),\n create('month', d3_time.utcMonth, utcBaseDate, [1, 3, 6]),\n create('year', d3_time.utcYear, utcBaseDate),\n\n // periodic units\n entry('seconds',\n function(d) { return new Date(Date.UTC(1970, 0, 1, 0, 0, d)); },\n function(d) { return date(d).getUTCSeconds(); },\n null, 0, 59\n ),\n entry('minutes',\n function(d) { return new Date(Date.UTC(1970, 0, 1, 0, d)); },\n function(d) { return date(d).getUTCMinutes(); },\n null, 0, 59\n ),\n entry('hours',\n function(d) { return new Date(Date.UTC(1970, 0, 1, d)); },\n function(d) { return date(d).getUTCHours(); },\n null, 0, 23\n ),\n entry('weekdays',\n function(d) { return new Date(Date.UTC(1970, 0, 4+d)); },\n function(d) { return date(d).getUTCDay(); },\n [1], 0, 6\n ),\n entry('dates',\n function(d) { return new Date(Date.UTC(1970, 0, d)); },\n function(d) { return date(d).getUTCDate(); },\n [1], 1, 31\n ),\n entry('months',\n function(d) { return new Date(Date.UTC(1970, d % 12, 1)); },\n function(d) { return date(d).getUTCMonth(); },\n [1], 0, 11\n )\n];\n\nvar STEPS = [\n [31536e6, 5], // 1-year\n [7776e6, 4], // 3-month\n [2592e6, 4], // 1-month\n [12096e5, 3], // 2-week\n [6048e5, 3], // 1-week\n [1728e5, 3], // 2-day\n [864e5, 3], // 1-day\n [432e5, 2], // 12-hour\n [216e5, 2], // 6-hour\n [108e5, 2], // 3-hour\n [36e5, 2], // 1-hour\n [18e5, 1], // 30-minute\n [9e5, 1], // 15-minute\n [3e5, 1], // 5-minute\n [6e4, 1], // 1-minute\n [3e4, 0], // 30-second\n [15e3, 0], // 15-second\n [5e3, 0], // 5-second\n [1e3, 0] // 1-second\n];\n\nfunction find(units, span, minb, maxb) {\n var step = STEPS[0], i, n, bins;\n\n for (i=1, n=STEPS.length; i step[0]) {\n bins = span / step[0];\n if (bins > maxb) {\n return units[STEPS[i-1][1]];\n }\n if (bins >= minb) {\n return units[step[1]];\n }\n }\n }\n return units[STEPS[n-1][1]];\n}\n\nfunction toUnitMap(units) {\n var map = {}, i, n;\n for (i=0, n=units.length; i 1 ?\n function(x, v) {\n for (var i=0; i b || b == null) && a != null ? 1 :\n ((b = b instanceof Date ? +b : b),\n (a = a instanceof Date ? +a : a)) !== a && b === b ? -1 :\n b !== b && a === a ? 1 : 0;\n};\n\nu.numcmp = function(a, b) { return a - b; };\n\nu.stablesort = function(array, sortBy, keyFn) {\n var indices = array.reduce(function(idx, v, i) {\n return (idx[keyFn(v)] = i, idx);\n }, {});\n\n array.sort(function(a, b) {\n var sa = sortBy(a),\n sb = sortBy(b);\n return sa < sb ? -1 : sa > sb ? 1\n : (indices[keyFn(a)] - indices[keyFn(b)]);\n });\n\n return array;\n};\n\n// permutes an array using a Knuth shuffle\nu.permute = function(a) {\n var m = a.length,\n swap,\n i;\n\n while (m) {\n i = Math.floor(Math.random() * m--);\n swap = a[m];\n a[m] = a[i];\n a[i] = swap;\n }\n};\n\n// string functions\n\nu.pad = function(s, length, pos, padchar) {\n padchar = padchar || \" \";\n var d = length - s.length;\n if (d <= 0) return s;\n switch (pos) {\n case 'left':\n return strrep(d, padchar) + s;\n case 'middle':\n case 'center':\n return strrep(Math.floor(d/2), padchar) +\n s + strrep(Math.ceil(d/2), padchar);\n default:\n return s + strrep(d, padchar);\n }\n};\n\nfunction strrep(n, str) {\n var s = \"\", i;\n for (i=0; i= '0' && ch <= '9') {\n string += ch;\n next();\n }\n if (ch === '.') {\n string += '.';\n while (next() && ch >= '0' && ch <= '9') {\n string += ch;\n }\n }\n if (ch === 'e' || ch === 'E') {\n string += ch;\n next();\n if (ch === '-' || ch === '+') {\n string += ch;\n next();\n }\n while (ch >= '0' && ch <= '9') {\n string += ch;\n next();\n }\n }\n number = +string;\n if (!isFinite(number)) {\n error(\"Bad number\");\n } else {\n return number;\n }\n },\n \n string = function () {\n // Parse a string value.\n var hex,\n i,\n string = '',\n uffff;\n \n // When parsing for string values, we must look for \" and \\ characters.\n if (ch === '\"') {\n while (next()) {\n if (ch === '\"') {\n next();\n return string;\n } else if (ch === '\\\\') {\n next();\n if (ch === 'u') {\n uffff = 0;\n for (i = 0; i < 4; i += 1) {\n hex = parseInt(next(), 16);\n if (!isFinite(hex)) {\n break;\n }\n uffff = uffff * 16 + hex;\n }\n string += String.fromCharCode(uffff);\n } else if (typeof escapee[ch] === 'string') {\n string += escapee[ch];\n } else {\n break;\n }\n } else {\n string += ch;\n }\n }\n }\n error(\"Bad string\");\n },\n\n white = function () {\n\n// Skip whitespace.\n\n while (ch && ch <= ' ') {\n next();\n }\n },\n\n word = function () {\n\n// true, false, or null.\n\n switch (ch) {\n case 't':\n next('t');\n next('r');\n next('u');\n next('e');\n return true;\n case 'f':\n next('f');\n next('a');\n next('l');\n next('s');\n next('e');\n return false;\n case 'n':\n next('n');\n next('u');\n next('l');\n next('l');\n return null;\n }\n error(\"Unexpected '\" + ch + \"'\");\n },\n\n value, // Place holder for the value function.\n\n array = function () {\n\n// Parse an array value.\n\n var array = [];\n\n if (ch === '[') {\n next('[');\n white();\n if (ch === ']') {\n next(']');\n return array; // empty array\n }\n while (ch) {\n array.push(value());\n white();\n if (ch === ']') {\n next(']');\n return array;\n }\n next(',');\n white();\n }\n }\n error(\"Bad array\");\n },\n\n object = function () {\n\n// Parse an object value.\n\n var key,\n object = {};\n\n if (ch === '{') {\n next('{');\n white();\n if (ch === '}') {\n next('}');\n return object; // empty object\n }\n while (ch) {\n key = string();\n white();\n next(':');\n if (Object.hasOwnProperty.call(object, key)) {\n error('Duplicate key \"' + key + '\"');\n }\n object[key] = value();\n white();\n if (ch === '}') {\n next('}');\n return object;\n }\n next(',');\n white();\n }\n }\n error(\"Bad object\");\n };\n\nvalue = function () {\n\n// Parse a JSON value. It could be an object, an array, a string, a number,\n// or a word.\n\n white();\n switch (ch) {\n case '{':\n return object();\n case '[':\n return array();\n case '\"':\n return string();\n case '-':\n return number();\n default:\n return ch >= '0' && ch <= '9' ? number() : word();\n }\n};\n\n// Return the json_parse function. It will have access to all of the above\n// functions and variables.\n\nmodule.exports = function (source, reviver) {\n var result;\n \n text = source;\n at = 0;\n ch = ' ';\n result = value();\n white();\n if (ch) {\n error(\"Syntax error\");\n }\n\n // If there is a reviver function, we recursively walk the new structure,\n // passing each name/value pair to the reviver function for possible\n // transformation, starting with a temporary root object that holds the result\n // in an empty key. If there is not a reviver function, we simply return the\n // result.\n\n return typeof reviver === 'function' ? (function walk(holder, key) {\n var k, v, value = holder[key];\n if (value && typeof value === 'object') {\n for (k in value) {\n if (Object.prototype.hasOwnProperty.call(value, k)) {\n v = walk(value, k);\n if (v !== undefined) {\n value[k] = v;\n } else {\n delete value[k];\n }\n }\n }\n }\n return reviver.call(holder, key, value);\n }({'': result}, '')) : result;\n};\n", + "var cx = /[\\u0000\\u00ad\\u0600-\\u0604\\u070f\\u17b4\\u17b5\\u200c-\\u200f\\u2028-\\u202f\\u2060-\\u206f\\ufeff\\ufff0-\\uffff]/g,\n escapable = /[\\\\\\\"\\x00-\\x1f\\x7f-\\x9f\\u00ad\\u0600-\\u0604\\u070f\\u17b4\\u17b5\\u200c-\\u200f\\u2028-\\u202f\\u2060-\\u206f\\ufeff\\ufff0-\\uffff]/g,\n gap,\n indent,\n meta = { // table of character substitutions\n '\\b': '\\\\b',\n '\\t': '\\\\t',\n '\\n': '\\\\n',\n '\\f': '\\\\f',\n '\\r': '\\\\r',\n '\"' : '\\\\\"',\n '\\\\': '\\\\\\\\'\n },\n rep;\n\nfunction quote(string) {\n // If the string contains no control characters, no quote characters, and no\n // backslash characters, then we can safely slap some quotes around it.\n // Otherwise we must also replace the offending characters with safe escape\n // sequences.\n \n escapable.lastIndex = 0;\n return escapable.test(string) ? '\"' + string.replace(escapable, function (a) {\n var c = meta[a];\n return typeof c === 'string' ? c :\n '\\\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);\n }) + '\"' : '\"' + string + '\"';\n}\n\nfunction str(key, holder) {\n // Produce a string from holder[key].\n var i, // The loop counter.\n k, // The member key.\n v, // The member value.\n length,\n mind = gap,\n partial,\n value = holder[key];\n \n // If the value has a toJSON method, call it to obtain a replacement value.\n if (value && typeof value === 'object' &&\n typeof value.toJSON === 'function') {\n value = value.toJSON(key);\n }\n \n // If we were called with a replacer function, then call the replacer to\n // obtain a replacement value.\n if (typeof rep === 'function') {\n value = rep.call(holder, key, value);\n }\n \n // What happens next depends on the value's type.\n switch (typeof value) {\n case 'string':\n return quote(value);\n \n case 'number':\n // JSON numbers must be finite. Encode non-finite numbers as null.\n return isFinite(value) ? String(value) : 'null';\n \n case 'boolean':\n case 'null':\n // If the value is a boolean or null, convert it to a string. Note:\n // typeof null does not produce 'null'. The case is included here in\n // the remote chance that this gets fixed someday.\n return String(value);\n \n case 'object':\n if (!value) return 'null';\n gap += indent;\n partial = [];\n \n // Array.isArray\n if (Object.prototype.toString.apply(value) === '[object Array]') {\n length = value.length;\n for (i = 0; i < length; i += 1) {\n partial[i] = str(i, value) || 'null';\n }\n \n // Join all of the elements together, separated with commas, and\n // wrap them in brackets.\n v = partial.length === 0 ? '[]' : gap ?\n '[\\n' + gap + partial.join(',\\n' + gap) + '\\n' + mind + ']' :\n '[' + partial.join(',') + ']';\n gap = mind;\n return v;\n }\n \n // If the replacer is an array, use it to select the members to be\n // stringified.\n if (rep && typeof rep === 'object') {\n length = rep.length;\n for (i = 0; i < length; i += 1) {\n k = rep[i];\n if (typeof k === 'string') {\n v = str(k, value);\n if (v) {\n partial.push(quote(k) + (gap ? ': ' : ':') + v);\n }\n }\n }\n }\n else {\n // Otherwise, iterate through all of the keys in the object.\n for (k in value) {\n if (Object.prototype.hasOwnProperty.call(value, k)) {\n v = str(k, value);\n if (v) {\n partial.push(quote(k) + (gap ? ': ' : ':') + v);\n }\n }\n }\n }\n \n // Join all of the member texts together, separated with commas,\n // and wrap them in braces.\n\n v = partial.length === 0 ? '{}' : gap ?\n '{\\n' + gap + partial.join(',\\n' + gap) + '\\n' + mind + '}' :\n '{' + partial.join(',') + '}';\n gap = mind;\n return v;\n }\n}\n\nmodule.exports = function (value, replacer, space) {\n var i;\n gap = '';\n indent = '';\n \n // If the space parameter is a number, make an indent string containing that\n // many spaces.\n if (typeof space === 'number') {\n for (i = 0; i < space; i += 1) {\n indent += ' ';\n }\n }\n // If the space parameter is a string, it will be used as the indent string.\n else if (typeof space === 'string') {\n indent = space;\n }\n\n // If there is a replacer, it must be a function or an array.\n // Otherwise, throw an error.\n rep = replacer;\n if (replacer && typeof replacer !== 'function'\n && (typeof replacer !== 'object' || typeof replacer.length !== 'number')) {\n throw new Error('JSON.stringify');\n }\n \n // Make a fake root object containing our value under the key of ''.\n // Return the result of stringifying the value.\n return str('', {'': value});\n};\n", + "/*! *****************************************************************************\r\nCopyright (c) Microsoft Corporation. All rights reserved.\r\nLicensed under the Apache License, Version 2.0 (the \"License\"); you may not use\r\nthis file except in compliance with the License. You may obtain a copy of the\r\nLicense at http://www.apache.org/licenses/LICENSE-2.0\r\n\r\nTHIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\r\nKIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED\r\nWARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,\r\nMERCHANTABLITY OR NON-INFRINGEMENT.\r\n\r\nSee the Apache Version 2.0 License for specific language governing permissions\r\nand limitations under the License.\r\n***************************************************************************** */\r\n/* global global, define, System, Reflect, Promise */\r\nvar __extends;\r\nvar __assign;\r\nvar __rest;\r\nvar __decorate;\r\nvar __param;\r\nvar __metadata;\r\nvar __awaiter;\r\nvar __generator;\r\nvar __exportStar;\r\nvar __values;\r\nvar __read;\r\nvar __spread;\r\nvar __await;\r\nvar __asyncGenerator;\r\nvar __asyncDelegator;\r\nvar __asyncValues;\r\n(function (factory) {\r\n var root = typeof global === \"object\" ? global : typeof self === \"object\" ? self : typeof this === \"object\" ? this : {};\r\n if (typeof define === \"function\" && define.amd) {\r\n define(\"tslib\", [\"exports\"], function (exports) { factory(createExporter(root, createExporter(exports))); });\r\n }\r\n else if (typeof module === \"object\" && typeof module.exports === \"object\") {\r\n factory(createExporter(root, createExporter(module.exports)));\r\n }\r\n else {\r\n factory(createExporter(root));\r\n }\r\n function createExporter(exports, previous) {\r\n return function (id, v) { return exports[id] = previous ? previous(id, v) : v; };\r\n }\r\n})\r\n(function (exporter) {\r\n var extendStatics = Object.setPrototypeOf ||\r\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\r\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\r\n\r\n __extends = function (d, b) {\r\n extendStatics(d, b);\r\n function __() { this.constructor = d; }\r\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\r\n };\r\n\r\n __assign = Object.assign || function (t) {\r\n for (var s, i = 1, n = arguments.length; i < n; i++) {\r\n s = arguments[i];\r\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];\r\n }\r\n return t;\r\n };\r\n\r\n __rest = function (s, e) {\r\n var t = {};\r\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)\r\n t[p] = s[p];\r\n if (s != null && typeof Object.getOwnPropertySymbols === \"function\")\r\n for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) if (e.indexOf(p[i]) < 0)\r\n t[p[i]] = s[p[i]];\r\n return t;\r\n };\r\n\r\n __decorate = function (decorators, target, key, desc) {\r\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\r\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\r\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\r\n return c > 3 && r && Object.defineProperty(target, key, r), r;\r\n };\r\n\r\n __param = function (paramIndex, decorator) {\r\n return function (target, key) { decorator(target, key, paramIndex); }\r\n };\r\n\r\n __metadata = function (metadataKey, metadataValue) {\r\n if (typeof Reflect === \"object\" && typeof Reflect.metadata === \"function\") return Reflect.metadata(metadataKey, metadataValue);\r\n };\r\n\r\n __awaiter = function (thisArg, _arguments, P, generator) {\r\n return new (P || (P = Promise))(function (resolve, reject) {\r\n function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\r\n function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\r\n function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }\r\n step((generator = generator.apply(thisArg, _arguments || [])).next());\r\n });\r\n };\r\n\r\n __generator = function (thisArg, body) {\r\n var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;\r\n return g = { next: verb(0), \"throw\": verb(1), \"return\": verb(2) }, typeof Symbol === \"function\" && (g[Symbol.iterator] = function() { return this; }), g;\r\n function verb(n) { return function (v) { return step([n, v]); }; }\r\n function step(op) {\r\n if (f) throw new TypeError(\"Generator is already executing.\");\r\n while (_) try {\r\n if (f = 1, y && (t = y[op[0] & 2 ? \"return\" : op[0] ? \"throw\" : \"next\"]) && !(t = t.call(y, op[1])).done) return t;\r\n if (y = 0, t) op = [0, t.value];\r\n switch (op[0]) {\r\n case 0: case 1: t = op; break;\r\n case 4: _.label++; return { value: op[1], done: false };\r\n case 5: _.label++; y = op[1]; op = [0]; continue;\r\n case 7: op = _.ops.pop(); _.trys.pop(); continue;\r\n default:\r\n if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }\r\n if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }\r\n if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }\r\n if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }\r\n if (t[2]) _.ops.pop();\r\n _.trys.pop(); continue;\r\n }\r\n op = body.call(thisArg, _);\r\n } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }\r\n if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };\r\n }\r\n };\r\n\r\n __exportStar = function (m, exports) {\r\n for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p];\r\n };\r\n\r\n __values = function (o) {\r\n var m = typeof Symbol === \"function\" && o[Symbol.iterator], i = 0;\r\n if (m) return m.call(o);\r\n return {\r\n next: function () {\r\n if (o && i >= o.length) o = void 0;\r\n return { value: o && o[i++], done: !o };\r\n }\r\n };\r\n };\r\n\r\n __read = function (o, n) {\r\n var m = typeof Symbol === \"function\" && o[Symbol.iterator];\r\n if (!m) return o;\r\n var i = m.call(o), r, ar = [], e;\r\n try {\r\n while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);\r\n }\r\n catch (error) { e = { error: error }; }\r\n finally {\r\n try {\r\n if (r && !r.done && (m = i[\"return\"])) m.call(i);\r\n }\r\n finally { if (e) throw e.error; }\r\n }\r\n return ar;\r\n };\r\n\r\n __spread = function () {\r\n for (var ar = [], i = 0; i < arguments.length; i++)\r\n ar = ar.concat(__read(arguments[i]));\r\n return ar;\r\n };\r\n\r\n __await = function (v) {\r\n return this instanceof __await ? (this.v = v, this) : new __await(v);\r\n };\r\n\r\n __asyncGenerator = function (thisArg, _arguments, generator) {\r\n if (!Symbol.asyncIterator) throw new TypeError(\"Symbol.asyncIterator is not defined.\");\r\n var g = generator.apply(thisArg, _arguments || []), i, q = [];\r\n return i = {}, verb(\"next\"), verb(\"throw\"), verb(\"return\"), i[Symbol.asyncIterator] = function () { return this; }, i;\r\n function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; }\r\n function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } }\r\n function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); }\r\n function fulfill(value) { resume(\"next\", value); }\r\n function reject(value) { resume(\"throw\", value); }\r\n function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); }\r\n };\r\n\r\n __asyncDelegator = function (o) {\r\n var i, p;\r\n return i = {}, verb(\"next\"), verb(\"throw\", function (e) { throw e; }), verb(\"return\"), i[Symbol.iterator] = function () { return this; }, i;\r\n function verb(n, f) { if (o[n]) i[n] = function (v) { return (p = !p) ? { value: __await(o[n](v)), done: n === \"return\" } : f ? f(v) : v; }; }\r\n };\r\n\r\n __asyncValues = function (o) {\r\n if (!Symbol.asyncIterator) throw new TypeError(\"Symbol.asyncIterator is not defined.\");\r\n var m = o[Symbol.asyncIterator];\r\n return m ? m.call(o) : typeof __values === \"function\" ? __values(o) : o[Symbol.iterator]();\r\n };\r\n\r\n exporter(\"__extends\", __extends);\r\n exporter(\"__assign\", __assign);\r\n exporter(\"__rest\", __rest);\r\n exporter(\"__decorate\", __decorate);\r\n exporter(\"__param\", __param);\r\n exporter(\"__metadata\", __metadata);\r\n exporter(\"__awaiter\", __awaiter);\r\n exporter(\"__generator\", __generator);\r\n exporter(\"__exportStar\", __exportStar);\r\n exporter(\"__values\", __values);\r\n exporter(\"__read\", __read);\r\n exporter(\"__spread\", __spread);\r\n exporter(\"__await\", __await);\r\n exporter(\"__asyncGenerator\", __asyncGenerator);\r\n exporter(\"__asyncDelegator\", __asyncDelegator);\r\n exporter(\"__asyncValues\", __asyncValues);\r\n});", + "\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nvar util_1 = require(\"./util\");\nexports.AGGREGATE_OPS = [\n 'values',\n 'count',\n 'valid',\n 'missing',\n 'distinct',\n 'sum',\n 'mean',\n 'average',\n 'variance',\n 'variancep',\n 'stdev',\n 'stdevp',\n 'median',\n 'q1',\n 'q3',\n 'ci0',\n 'ci1',\n 'modeskew',\n 'min',\n 'max',\n 'argmin',\n 'argmax',\n];\nexports.AGGREGATE_OP_INDEX = util_1.toSet(exports.AGGREGATE_OPS);\nexports.COUNTING_OPS = ['count', 'valid', 'missing', 'distinct'];\nfunction isCountingAggregateOp(aggregate) {\n return aggregate && util_1.contains(exports.COUNTING_OPS, aggregate);\n}\nexports.isCountingAggregateOp = isCountingAggregateOp;\n/** Additive-based aggregation operations. These can be applied to stack. */\nexports.SUM_OPS = [\n 'count',\n 'sum',\n 'distinct',\n 'valid',\n 'missing'\n];\n/**\n * Aggregation operators that always produce values within the range [domainMin, domainMax].\n */\nexports.SHARED_DOMAIN_OPS = [\n 'mean',\n 'average',\n 'median',\n 'q1',\n 'q3',\n 'min',\n 'max',\n];\nexports.SHARED_DOMAIN_OP_INDEX = util_1.toSet(exports.SHARED_DOMAIN_OPS);\n//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYWdncmVnYXRlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2FnZ3JlZ2F0ZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQUFBLCtCQUF1QztBQVExQixRQUFBLGFBQWEsR0FBa0I7SUFDeEMsUUFBUTtJQUNSLE9BQU87SUFDUCxPQUFPO0lBQ1AsU0FBUztJQUNULFVBQVU7SUFDVixLQUFLO0lBQ0wsTUFBTTtJQUNOLFNBQVM7SUFDVCxVQUFVO0lBQ1YsV0FBVztJQUNYLE9BQU87SUFDUCxRQUFRO0lBQ1IsUUFBUTtJQUNSLElBQUk7SUFDSixJQUFJO0lBQ0osS0FBSztJQUNMLEtBQUs7SUFDTCxVQUFVO0lBQ1YsS0FBSztJQUNMLEtBQUs7SUFDTCxRQUFRO0lBQ1IsUUFBUTtDQUNYLENBQUM7QUFFVyxRQUFBLGtCQUFrQixHQUFHLFlBQUssQ0FBQyxxQkFBYSxDQUFDLENBQUM7QUFFMUMsUUFBQSxZQUFZLEdBQWtCLENBQUMsT0FBTyxFQUFFLE9BQU8sRUFBRSxTQUFTLEVBQUUsVUFBVSxDQUFDLENBQUM7QUFFckYsK0JBQXNDLFNBQWlCO0lBQ3JELE1BQU0sQ0FBQyxTQUFTLElBQUksZUFBUSxDQUFDLG9CQUFZLEVBQUUsU0FBUyxDQUFDLENBQUM7QUFDeEQsQ0FBQztBQUZELHNEQUVDO0FBRUQsNkVBQTZFO0FBQ2hFLFFBQUEsT0FBTyxHQUFrQjtJQUNsQyxPQUFPO0lBQ1AsS0FBSztJQUNMLFVBQVU7SUFDVixPQUFPO0lBQ1AsU0FBUztDQUNaLENBQUM7QUFFRjs7R0FFRztBQUNVLFFBQUEsaUJBQWlCLEdBQWtCO0lBQzVDLE1BQU07SUFDTixTQUFTO0lBQ1QsUUFBUTtJQUNSLElBQUk7SUFDSixJQUFJO0lBQ0osS0FBSztJQUNMLEtBQUs7Q0FDUixDQUFDO0FBRVcsUUFBQSxzQkFBc0IsR0FBRyxZQUFLLENBQUMseUJBQWlCLENBQUMsQ0FBQyJ9", + "\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.DEFAULT_AXIS_CONFIG = {\n quantitativeExtent: 30\n};\n/**\n * A dictionary listing whether a certain axis property is applicable for only main axes or only grid axes.\n * (Properties not listed are applicable for both)\n */\nexports.AXIS_PROPERTY_TYPE = {\n grid: 'grid',\n labelOverlap: 'main',\n offset: 'main',\n maxExtent: 'main',\n minExtent: 'main',\n title: 'main'\n};\nexports.AXIS_PROPERTIES = [\n 'domain', 'format', 'grid', 'labelPadding', 'labels', 'labelOverlap', 'maxExtent', 'minExtent', 'offset', 'orient', 'position', 'tickCount', 'tickExtra', 'ticks', 'tickSize', 'title', 'titlePadding', 'values', 'zindex'\n];\nexports.VG_AXIS_PROPERTIES = [].concat(exports.AXIS_PROPERTIES, ['gridScale']);\n//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXhpcy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9heGlzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7O0FBZWEsUUFBQSxtQkFBbUIsR0FBRztJQUNqQyxrQkFBa0IsRUFBRSxFQUFFO0NBQ3ZCLENBQUM7QUEyREY7OztHQUdHO0FBQ1UsUUFBQSxrQkFBa0IsR0FBeUM7SUFDdEUsSUFBSSxFQUFFLE1BQU07SUFDWixZQUFZLEVBQUUsTUFBTTtJQUNwQixNQUFNLEVBQUUsTUFBTTtJQUNkLFNBQVMsRUFBRSxNQUFNO0lBQ2pCLFNBQVMsRUFBRSxNQUFNO0lBQ2pCLEtBQUssRUFBRSxNQUFNO0NBQ2QsQ0FBQztBQWtDVyxRQUFBLGVBQWUsR0FBMkI7SUFDckQsUUFBUSxFQUFFLFFBQVEsRUFBRSxNQUFNLEVBQUUsY0FBYyxFQUFFLFFBQVEsRUFBRSxjQUFjLEVBQUUsV0FBVyxFQUFFLFdBQVcsRUFBRSxRQUFRLEVBQUUsUUFBUSxFQUFFLFVBQVUsRUFBRSxXQUFXLEVBQUUsV0FBVyxFQUFFLE9BQU8sRUFBRSxVQUFVLEVBQUUsT0FBTyxFQUFFLGNBQWMsRUFBRSxRQUFRLEVBQUUsUUFBUTtDQUMzTixDQUFDO0FBRVcsUUFBQSxrQkFBa0IsR0FBcUIsRUFBRSxDQUFDLE1BQU0sQ0FBQyx1QkFBZSxFQUFFLENBQUMsV0FBVyxDQUFDLENBQUMsQ0FBQyJ9", + "\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nvar channel_1 = require(\"./channel\");\nvar util_1 = require(\"./util\");\nfunction binToString(bin) {\n if (util_1.isBoolean(bin)) {\n return 'bin';\n }\n return 'bin' + util_1.keys(bin).map(function (p) { return \"_\" + p + \"_\" + bin[p]; }).join('');\n}\nexports.binToString = binToString;\nfunction autoMaxBins(channel) {\n switch (channel) {\n case channel_1.ROW:\n case channel_1.COLUMN:\n case channel_1.SIZE:\n case channel_1.COLOR:\n case channel_1.OPACITY:\n // Facets and Size shouldn't have too many bins\n // We choose 6 like shape to simplify the rule\n case channel_1.SHAPE:\n return 6; // Vega's \"shape\" has 6 distinct values\n default:\n return 10;\n }\n}\nexports.autoMaxBins = autoMaxBins;\n//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYmluLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2Jpbi50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQUFBLHFDQUE0RTtBQUM1RSwrQkFBdUM7QUE0RHZDLHFCQUE0QixHQUFrQjtJQUM1QyxFQUFFLENBQUMsQ0FBQyxnQkFBUyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUNuQixNQUFNLENBQUMsS0FBSyxDQUFDO0lBQ2YsQ0FBQztJQUNELE1BQU0sQ0FBQyxLQUFLLEdBQUcsV0FBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxVQUFBLENBQUMsSUFBSSxPQUFBLE1BQUksQ0FBQyxTQUFJLEdBQUcsQ0FBQyxDQUFDLENBQUcsRUFBakIsQ0FBaUIsQ0FBQyxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQztBQUNoRSxDQUFDO0FBTEQsa0NBS0M7QUFFRCxxQkFBNEIsT0FBZ0I7SUFDMUMsTUFBTSxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQztRQUNoQixLQUFLLGFBQUcsQ0FBQztRQUNULEtBQUssZ0JBQU0sQ0FBQztRQUNaLEtBQUssY0FBSSxDQUFDO1FBQ1YsS0FBSyxlQUFLLENBQUM7UUFDWCxLQUFLLGlCQUFPLENBQUM7UUFDWCwrQ0FBK0M7UUFDL0MsOENBQThDO1FBQ2hELEtBQUssZUFBSztZQUNSLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyx1Q0FBdUM7UUFDbkQ7WUFDRSxNQUFNLENBQUMsRUFBRSxDQUFDO0lBQ2QsQ0FBQztBQUNILENBQUM7QUFkRCxrQ0FjQyJ9", + "\"use strict\";\n/*\n * Constants and utilities for encoding channels (Visual variables)\n * such as 'x', 'y', 'color'.\n */\nObject.defineProperty(exports, \"__esModule\", { value: true });\nvar scale_1 = require(\"./scale\");\nvar util_1 = require(\"./util\");\nvar Channel;\n(function (Channel) {\n // Facet\n Channel.ROW = 'row';\n Channel.COLUMN = 'column';\n // Position\n Channel.X = 'x';\n Channel.Y = 'y';\n Channel.X2 = 'x2';\n Channel.Y2 = 'y2';\n // Mark property with scale\n Channel.COLOR = 'color';\n Channel.SHAPE = 'shape';\n Channel.SIZE = 'size';\n Channel.OPACITY = 'opacity';\n // Non-scale channel\n Channel.TEXT = 'text';\n Channel.ORDER = 'order';\n Channel.DETAIL = 'detail';\n Channel.TOOLTIP = 'tooltip';\n})(Channel = exports.Channel || (exports.Channel = {}));\nexports.X = Channel.X;\nexports.Y = Channel.Y;\nexports.X2 = Channel.X2;\nexports.Y2 = Channel.Y2;\nexports.ROW = Channel.ROW;\nexports.COLUMN = Channel.COLUMN;\nexports.SHAPE = Channel.SHAPE;\nexports.SIZE = Channel.SIZE;\nexports.COLOR = Channel.COLOR;\nexports.TEXT = Channel.TEXT;\nexports.DETAIL = Channel.DETAIL;\nexports.ORDER = Channel.ORDER;\nexports.OPACITY = Channel.OPACITY;\nexports.TOOLTIP = Channel.TOOLTIP;\nexports.CHANNELS = [exports.X, exports.Y, exports.X2, exports.Y2, exports.ROW, exports.COLUMN, exports.SIZE, exports.SHAPE, exports.COLOR, exports.ORDER, exports.OPACITY, exports.TEXT, exports.DETAIL, exports.TOOLTIP];\nvar CHANNEL_INDEX = util_1.toSet(exports.CHANNELS);\n/**\n * Channels cannot have an array of channelDef.\n * model.fieldDef, getFieldDef only work for these channels.\n *\n * (The only two channels that can have an array of channelDefs are \"detail\" and \"order\".\n * Since there can be multiple fieldDefs for detail and order, getFieldDef/model.fieldDef\n * are not applicable for them. Similarly, selection projecttion won't work with \"detail\" and \"order\".)\n */\nexports.SINGLE_DEF_CHANNELS = [exports.X, exports.Y, exports.X2, exports.Y2, exports.ROW, exports.COLUMN, exports.SIZE, exports.SHAPE, exports.COLOR, exports.OPACITY, exports.TEXT, exports.TOOLTIP];\nfunction isChannel(str) {\n return !!CHANNEL_INDEX[str];\n}\nexports.isChannel = isChannel;\n// CHANNELS without COLUMN, ROW\nexports.UNIT_CHANNELS = [exports.X, exports.Y, exports.X2, exports.Y2, exports.SIZE, exports.SHAPE, exports.COLOR, exports.ORDER, exports.OPACITY, exports.TEXT, exports.DETAIL, exports.TOOLTIP];\n/** List of channels with scales */\nexports.SCALE_CHANNELS = [exports.X, exports.Y, exports.SIZE, exports.SHAPE, exports.COLOR, exports.OPACITY];\nvar SCALE_CHANNEL_INDEX = util_1.toSet(exports.SCALE_CHANNELS);\nfunction isScaleChannel(channel) {\n return !!SCALE_CHANNEL_INDEX[channel];\n}\nexports.isScaleChannel = isScaleChannel;\n// UNIT_CHANNELS without X, Y, X2, Y2;\nexports.NONSPATIAL_CHANNELS = [exports.SIZE, exports.SHAPE, exports.COLOR, exports.ORDER, exports.OPACITY, exports.TEXT, exports.DETAIL, exports.TOOLTIP];\n// X and Y;\nexports.SPATIAL_SCALE_CHANNELS = [exports.X, exports.Y];\n// SCALE_CHANNELS without X, Y;\nexports.NONSPATIAL_SCALE_CHANNELS = [exports.SIZE, exports.SHAPE, exports.COLOR, exports.OPACITY];\nexports.LEVEL_OF_DETAIL_CHANNELS = util_1.without(exports.NONSPATIAL_CHANNELS, ['order']);\n/** Channels that can serve as groupings for stacked charts. */\nexports.STACK_BY_CHANNELS = [exports.COLOR, exports.DETAIL, exports.ORDER, exports.OPACITY, exports.SIZE];\n/**\n * Return whether a channel supports a particular mark type.\n * @param channel channel name\n * @param mark the mark type\n * @return whether the mark supports the channel\n */\nfunction supportMark(channel, mark) {\n return mark in getSupportedMark(channel);\n}\nexports.supportMark = supportMark;\n/**\n * Return a dictionary showing whether a channel supports mark type.\n * @param channel\n * @return A dictionary mapping mark types to boolean values.\n */\nfunction getSupportedMark(channel) {\n switch (channel) {\n case exports.X:\n case exports.Y:\n case exports.COLOR:\n case exports.DETAIL:\n case exports.TOOLTIP:\n case exports.ORDER: // TODO: revise (order might not support rect, which is not stackable?)\n case exports.OPACITY:\n case exports.ROW:\n case exports.COLUMN:\n return {\n point: true, tick: true, rule: true, circle: true, square: true,\n bar: true, rect: true, line: true, area: true, text: true\n };\n case exports.X2:\n case exports.Y2:\n return {\n rule: true, bar: true, rect: true, area: true\n };\n case exports.SIZE:\n return {\n point: true, tick: true, rule: true, circle: true, square: true,\n bar: true, text: true, line: true\n };\n case exports.SHAPE:\n return { point: true };\n case exports.TEXT:\n return { text: true };\n }\n}\nexports.getSupportedMark = getSupportedMark;\nfunction hasScale(channel) {\n return !util_1.contains([exports.DETAIL, exports.TEXT, exports.ORDER, exports.TOOLTIP], channel);\n}\nexports.hasScale = hasScale;\n// Position does not work with ordinal (lookup) scale and sequential (which is only for color)\nvar POSITION_SCALE_TYPE_INDEX = util_1.toSet(util_1.without(scale_1.SCALE_TYPES, ['ordinal', 'sequential']));\nfunction supportScaleType(channel, scaleType) {\n switch (channel) {\n case exports.ROW:\n case exports.COLUMN:\n return scaleType === 'band'; // row / column currently supports band only\n case exports.X:\n case exports.Y:\n case exports.SIZE: // TODO: size and opacity can support ordinal with more modification\n case exports.OPACITY:\n // Although it generally doesn't make sense to use band with size and opacity,\n // it can also work since we use band: 0.5 to get midpoint.\n return scaleType in POSITION_SCALE_TYPE_INDEX;\n case exports.COLOR:\n return scaleType !== 'band'; // band does not make sense with color\n case exports.SHAPE:\n return scaleType === 'ordinal'; // shape = lookup only\n }\n /* istanbul ignore next: it should never reach here */\n return false;\n}\nexports.supportScaleType = supportScaleType;\nfunction rangeType(channel) {\n switch (channel) {\n case exports.X:\n case exports.Y:\n case exports.SIZE:\n case exports.OPACITY:\n // X2 and Y2 use X and Y scales, so they similarly have continuous range.\n case exports.X2:\n case exports.Y2:\n return 'continuous';\n case exports.ROW:\n case exports.COLUMN:\n case exports.SHAPE:\n // TEXT and TOOLTIP have no scale but have discrete output\n case exports.TEXT:\n case exports.TOOLTIP:\n return 'discrete';\n // Color can be either continuous or discrete, depending on scale type.\n case exports.COLOR:\n return 'flexible';\n // No scale, no range type.\n case exports.DETAIL:\n case exports.ORDER:\n return undefined;\n }\n /* istanbul ignore next: should never reach here. */\n throw new Error('getSupportedRole not implemented for ' + channel);\n}\nexports.rangeType = rangeType;\n//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2hhbm5lbC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9jaGFubmVsLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQTs7O0dBR0c7O0FBTUgsaUNBQStDO0FBQy9DLCtCQUFnRDtBQUdoRCxJQUFpQixPQUFPLENBc0J2QjtBQXRCRCxXQUFpQixPQUFPO0lBQ3RCLFFBQVE7SUFDSyxXQUFHLEdBQVUsS0FBSyxDQUFDO0lBQ25CLGNBQU0sR0FBYSxRQUFRLENBQUM7SUFFekMsV0FBVztJQUNFLFNBQUMsR0FBUSxHQUFHLENBQUM7SUFDYixTQUFDLEdBQVEsR0FBRyxDQUFDO0lBQ2IsVUFBRSxHQUFTLElBQUksQ0FBQztJQUNoQixVQUFFLEdBQVMsSUFBSSxDQUFDO0lBRTdCLDJCQUEyQjtJQUNkLGFBQUssR0FBWSxPQUFPLENBQUM7SUFDekIsYUFBSyxHQUFZLE9BQU8sQ0FBQztJQUN6QixZQUFJLEdBQVcsTUFBTSxDQUFDO0lBQ3RCLGVBQU8sR0FBYyxTQUFTLENBQUM7SUFFNUMsb0JBQW9CO0lBQ1AsWUFBSSxHQUFXLE1BQU0sQ0FBQztJQUN0QixhQUFLLEdBQVksT0FBTyxDQUFDO0lBQ3pCLGNBQU0sR0FBYSxRQUFRLENBQUM7SUFDNUIsZUFBTyxHQUFjLFNBQVMsQ0FBQztBQUM5QyxDQUFDLEVBdEJnQixPQUFPLEdBQVAsZUFBTyxLQUFQLGVBQU8sUUFzQnZCO0FBSVksUUFBQSxDQUFDLEdBQUcsT0FBTyxDQUFDLENBQUMsQ0FBQztBQUNkLFFBQUEsQ0FBQyxHQUFHLE9BQU8sQ0FBQyxDQUFDLENBQUM7QUFDZCxRQUFBLEVBQUUsR0FBRyxPQUFPLENBQUMsRUFBRSxDQUFDO0FBQ2hCLFFBQUEsRUFBRSxHQUFHLE9BQU8sQ0FBQyxFQUFFLENBQUM7QUFDaEIsUUFBQSxHQUFHLEdBQUcsT0FBTyxDQUFDLEdBQUcsQ0FBQztBQUNsQixRQUFBLE1BQU0sR0FBRyxPQUFPLENBQUMsTUFBTSxDQUFDO0FBQ3hCLFFBQUEsS0FB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", + "\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nvar channel_1 = require(\"../../channel\");\nvar log = require(\"../../log\");\nvar scale_1 = require(\"../../scale\");\nvar scale_2 = require(\"../../scale\");\nvar timeunit_1 = require(\"../../timeunit\");\nvar type_1 = require(\"../../type\");\nvar util = require(\"../../util\");\nvar util_1 = require(\"../../util\");\n/**\n * Determine if there is a specified scale type and if it is appropriate,\n * or determine default type if type is unspecified or inappropriate.\n */\n// NOTE: CompassQL uses this method.\nfunction scaleType(specifiedType, channel, fieldDef, mark, specifiedRangeStep, scaleConfig) {\n var defaultScaleType = defaultType(channel, fieldDef, mark, specifiedRangeStep, scaleConfig);\n if (!channel_1.hasScale(channel)) {\n // There is no scale for these channels\n return null;\n }\n if (specifiedType !== undefined) {\n // Check if explicitly specified scale type is supported by the channel\n if (!channel_1.supportScaleType(channel, specifiedType)) {\n log.warn(log.message.scaleTypeNotWorkWithChannel(channel, specifiedType, defaultScaleType));\n return defaultScaleType;\n }\n // Check if explicitly specified scale type is supported by the data type\n if (!fieldDefMatchScaleType(specifiedType, fieldDef)) {\n log.warn(log.message.scaleTypeNotWorkWithFieldDef(specifiedType, defaultScaleType));\n return defaultScaleType;\n }\n return specifiedType;\n }\n return defaultScaleType;\n}\nexports.scaleType = scaleType;\n/**\n * Determine appropriate default scale type.\n */\nfunction defaultType(channel, fieldDef, mark, specifiedRangeStep, scaleConfig) {\n switch (fieldDef.type) {\n case 'nominal':\n if (channel === 'color' || channel_1.rangeType(channel) === 'discrete') {\n return 'ordinal';\n }\n return discreteToContinuousType(channel, mark, specifiedRangeStep, scaleConfig);\n case 'ordinal':\n if (channel === 'color') {\n return 'ordinal';\n }\n else if (channel_1.rangeType(channel) === 'discrete') {\n if (channel !== 'text' && channel !== 'tooltip') {\n log.warn(log.message.discreteChannelCannotEncode(channel, 'ordinal'));\n }\n return 'ordinal';\n }\n return discreteToContinuousType(channel, mark, specifiedRangeStep, scaleConfig);\n case 'temporal':\n if (channel === 'color') {\n if (timeunit_1.isDiscreteByDefault(fieldDef.timeUnit)) {\n // For discrete timeUnit, use ordinal scale so that legend produces correct value.\n // (See https://github.com/vega/vega-lite/issues/2045.)\n return 'ordinal';\n }\n return 'sequential';\n }\n else if (channel_1.rangeType(channel) === 'discrete') {\n log.warn(log.message.discreteChannelCannotEncode(channel, 'temporal'));\n // TODO: consider using quantize (equivalent to binning) once we have it\n return 'ordinal';\n }\n if (timeunit_1.isDiscreteByDefault(fieldDef.timeUnit)) {\n return discreteToContinuousType(channel, mark, specifiedRangeStep, scaleConfig);\n }\n return 'time';\n case 'quantitative':\n if (channel === 'color') {\n if (fieldDef.bin) {\n return 'bin-ordinal';\n }\n // Use `sequential` as the default color scale for continuous data\n // since it supports both array range and scheme range.\n return 'sequential';\n }\n else if (channel_1.rangeType(channel) === 'discrete') {\n log.warn(log.message.discreteChannelCannotEncode(channel, 'quantitative'));\n // TODO: consider using quantize (equivalent to binning) once we have it\n return 'ordinal';\n }\n // x and y use a linear scale because selections don't work with bin scales\n if (fieldDef.bin && channel !== 'x' && channel !== 'y') {\n return 'bin-linear';\n }\n return 'linear';\n }\n /* istanbul ignore next: should never reach this */\n throw new Error(log.message.invalidFieldType(fieldDef.type));\n}\n/**\n * Determines default scale type for nominal/ordinal field.\n * @returns BAND or POINT scale based on channel, mark, and rangeStep\n */\nfunction discreteToContinuousType(channel, mark, specifiedRangeStep, scaleConfig) {\n if (util.contains(['x', 'y'], channel)) {\n if (mark === 'rect') {\n // The rect mark should fit into a band.\n return 'band';\n }\n if (mark === 'bar') {\n return 'band';\n }\n }\n // Otherwise, use ordinal point scale so we can easily get center positions of the marks.\n return 'point';\n}\nfunction fieldDefMatchScaleType(specifiedType, fieldDef) {\n var type = fieldDef.type;\n if (util_1.contains([type_1.Type.ORDINAL, type_1.Type.NOMINAL], type)) {\n return specifiedType === undefined || scale_2.hasDiscreteDomain(specifiedType);\n }\n else if (type === type_1.Type.TEMPORAL) {\n if (!fieldDef.timeUnit) {\n return util_1.contains([scale_1.ScaleType.TIME, scale_1.ScaleType.UTC, undefined], specifiedType);\n }\n else {\n return util_1.contains([scale_1.ScaleType.TIME, scale_1.ScaleType.UTC, undefined], specifiedType) || scale_2.hasDiscreteDomain(specifiedType);\n }\n }\n else if (type === type_1.Type.QUANTITATIVE) {\n if (fieldDef.bin) {\n return specifiedType === scale_1.ScaleType.BIN_LINEAR || specifiedType === scale_1.ScaleType.BIN_ORDINAL;\n }\n return util_1.contains([scale_1.ScaleType.LOG, scale_1.ScaleType.POW, scale_1.ScaleType.SQRT, scale_1.ScaleType.QUANTILE, scale_1.ScaleType.QUANTIZE, scale_1.ScaleType.LINEAR, undefined], specifiedType);\n }\n return true;\n}\nexports.fieldDefMatchScaleType = fieldDefMatchScaleType;\n//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHlwZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9jb21waWxlL3NjYWxlL3R5cGUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFBQSx5Q0FBNkU7QUFFN0UsK0JBQWlDO0FBRWpDLHFDQUFtRDtBQUNuRCxxQ0FBOEM7QUFDOUMsMkNBQW1EO0FBQ25ELG1DQUFnQztBQUNoQyxpQ0FBbUM7QUFDbkMsbUNBQW9DO0FBS3BDOzs7R0FHRztBQUNILG9DQUFvQztBQUNwQyxtQkFDRSxhQUF3QixFQUFFLE9BQWdCLEVBQUUsUUFBMEIsRUFBRSxJQUFVLEVBQ2xGLGtCQUEwQixFQUFFLFdBQXdCO0lBRXBELElBQU0sZ0JBQWdCLEdBQUcsV0FBVyxDQUFDLE9BQU8sRUFBRSxRQUFRLEVBQUUsSUFBSSxFQUFFLGtCQUFrQixFQUFFLFdBQVcsQ0FBQyxDQUFDO0lBRS9GLEVBQUUsQ0FBQyxDQUFDLENBQUMsa0JBQVEsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDdkIsdUNBQXVDO1FBQ3ZDLE1BQU0sQ0FBQyxJQUFJLENBQUM7SUFDZCxDQUFDO0lBQ0QsRUFBRSxDQUFDLENBQUMsYUFBYSxLQUFLLFNBQVMsQ0FBQyxDQUFDLENBQUM7UUFDaEMsdUVBQXVFO1FBQ3ZFLEVBQUUsQ0FBQyxDQUFDLENBQUMsMEJBQWdCLENBQUMsT0FBTyxFQUFFLGFBQWEsQ0FBQyxDQUFDLENBQUMsQ0FBQztZQUM5QyxHQUFHLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxPQUFPLENBQUMsMkJBQTJCLENBQUMsT0FBTyxFQUFFLGFBQWEsRUFBRSxnQkFBZ0IsQ0FBQyxDQUFDLENBQUM7WUFDNUYsTUFBTSxDQUFDLGdCQUFnQixDQUFDO1FBQzFCLENBQUM7UUFFRCx5RUFBeUU7UUFDekUsRUFBRSxDQUFDLENBQUMsQ0FBQyxzQkFBc0IsQ0FBQyxhQUFhLEVBQUUsUUFBUSxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQ3JELEdBQUcsQ0FB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", + "\"use strict\";\n// DateTime definition object\nObject.defineProperty(exports, \"__esModule\", { value: true });\nvar log = require(\"./log\");\nvar util_1 = require(\"./util\");\n/*\n * A designated year that starts on Sunday.\n */\nvar SUNDAY_YEAR = 2006;\nfunction isDateTime(o) {\n return !!o && (!!o.year || !!o.quarter || !!o.month || !!o.date || !!o.day ||\n !!o.hours || !!o.minutes || !!o.seconds || !!o.milliseconds);\n}\nexports.isDateTime = isDateTime;\nexports.MONTHS = ['january', 'february', 'march', 'april', 'may', 'june', 'july', 'august', 'september', 'october', 'november', 'december'];\nexports.SHORT_MONTHS = exports.MONTHS.map(function (m) { return m.substr(0, 3); });\nexports.DAYS = ['sunday', 'monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday'];\nexports.SHORT_DAYS = exports.DAYS.map(function (d) { return d.substr(0, 3); });\nfunction normalizeQuarter(q) {\n if (util_1.isNumber(q)) {\n if (q > 4) {\n log.warn(log.message.invalidTimeUnit('quarter', q));\n }\n // We accept 1-based quarter, so need to readjust to 0-based quarter\n return (q - 1) + '';\n }\n else {\n // Invalid quarter\n throw new Error(log.message.invalidTimeUnit('quarter', q));\n }\n}\nfunction normalizeMonth(m) {\n if (util_1.isNumber(m)) {\n // We accept 1-based month, so need to readjust to 0-based month\n return (m - 1) + '';\n }\n else {\n var lowerM = m.toLowerCase();\n var monthIndex = exports.MONTHS.indexOf(lowerM);\n if (monthIndex !== -1) {\n return monthIndex + ''; // 0 for january, ...\n }\n var shortM = lowerM.substr(0, 3);\n var shortMonthIndex = exports.SHORT_MONTHS.indexOf(shortM);\n if (shortMonthIndex !== -1) {\n return shortMonthIndex + '';\n }\n // Invalid month\n throw new Error(log.message.invalidTimeUnit('month', m));\n }\n}\nfunction normalizeDay(d) {\n if (util_1.isNumber(d)) {\n // mod so that this can be both 0-based where 0 = sunday\n // and 1-based where 7=sunday\n return (d % 7) + '';\n }\n else {\n var lowerD = d.toLowerCase();\n var dayIndex = exports.DAYS.indexOf(lowerD);\n if (dayIndex !== -1) {\n return dayIndex + ''; // 0 for january, ...\n }\n var shortD = lowerD.substr(0, 3);\n var shortDayIndex = exports.SHORT_DAYS.indexOf(shortD);\n if (shortDayIndex !== -1) {\n return shortDayIndex + '';\n }\n // Invalid day\n throw new Error(log.message.invalidTimeUnit('day', d));\n }\n}\n/**\n * Return Vega Expression for a particular date time.\n * @param d\n * @param normalize whether to normalize quarter, month, day.\n */\nfunction dateTimeExpr(d, normalize) {\n if (normalize === void 0) { normalize = false; }\n var units = [];\n if (normalize && d.day !== undefined) {\n if (util_1.keys(d).length > 1) {\n log.warn(log.message.droppedDay(d));\n d = util_1.duplicate(d);\n delete d.day;\n }\n }\n if (d.year !== undefined) {\n units.push(d.year);\n }\n else if (d.day !== undefined) {\n // Set year to 2006 for working with day since January 1 2006 is a Sunday\n units.push(SUNDAY_YEAR);\n }\n else {\n units.push(0);\n }\n if (d.month !== undefined) {\n var month = normalize ? normalizeMonth(d.month) : d.month;\n units.push(month);\n }\n else if (d.quarter !== undefined) {\n var quarter = normalize ? normalizeQuarter(d.quarter) : d.quarter;\n units.push(quarter + '*3');\n }\n else {\n units.push(0); // months start at zero in JS\n }\n if (d.date !== undefined) {\n units.push(d.date);\n }\n else if (d.day !== undefined) {\n // HACK: Day only works as a standalone unit\n // This is only correct because we always set year to 2006 for day\n var day = normalize ? normalizeDay(d.day) : d.day;\n units.push(day + '+1');\n }\n else {\n units.push(1); // Date starts at 1 in JS\n }\n // Note: can't use TimeUnit enum here as importing it will create\n // circular dependency problem!\n for (var _i = 0, _a = ['hours', 'minutes', 'seconds', 'milliseconds']; _i < _a.length; _i++) {\n var timeUnit = _a[_i];\n if (d[timeUnit] !== undefined) {\n units.push(d[timeUnit]);\n }\n else {\n units.push(0);\n }\n }\n if (d.utc) {\n return \"utc(\" + units.join(', ') + \")\";\n }\n else {\n return \"datetime(\" + units.join(', ') + \")\";\n }\n}\nexports.dateTimeExpr = dateTimeExpr;\n//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGF0ZXRpbWUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvZGF0ZXRpbWUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLDZCQUE2Qjs7QUFFN0IsMkJBQTZCO0FBQzdCLCtCQUFpRDtBQUdqRDs7R0FFRztBQUNILElBQU0sV0FBVyxHQUFHLElBQUksQ0FBQztBQThHekIsb0JBQTJCLENBQU07SUFDL0IsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLE9BQU8sSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLEtBQUssSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLEdBQUc7UUFDeEUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxLQUFLLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxPQUFPLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxPQUFPLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxZQUFZLENBQUMsQ0FBQztBQUNqRSxDQUFDO0FBSEQsZ0NBR0M7QUFFWSxRQUFBLE1BQU0sR0FBRyxDQUFDLFNBQVMsRUFBRSxVQUFVLEVBQUUsT0FBTyxFQUFFLE9BQU8sRUFBRSxLQUFLLEVBQUUsTUFBTSxFQUFFLE1BQU0sRUFBRSxRQUFRLEVBQUUsV0FBVyxFQUFFLFNBQVMsRUFBRSxVQUFVLEVBQUUsVUFBVSxDQUFDLENBQUM7QUFDcEksUUFBQSxZQUFZLEdBQUcsY0FBTSxDQUFDLEdBQUcsQ0FBQyxVQUFDLENBQUMsSUFBSyxPQUFBLENBQUMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFkLENBQWMsQ0FBQyxDQUFDO0FBRWpELFFBQUEsSUFBSSxHQUFHLENBQUMsUUFBUSxFQUFFLFFBQVEsRUFBRSxTQUFTLEVBQUUsV0FBVyxFQUFFLFVBQVUsRUFBRSxRQUFR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", + "\"use strict\";\n// utility for a field definition object\nObject.defineProperty(exports, \"__esModule\", { value: true });\nvar tslib_1 = require(\"tslib\");\nvar aggregate_1 = require(\"./aggregate\");\nvar bin_1 = require(\"./bin\");\nvar channel_1 = require(\"./channel\");\nvar log = require(\"./log\");\nvar timeunit_1 = require(\"./timeunit\");\nvar type_1 = require(\"./type\");\nvar util_1 = require(\"./util\");\nfunction isRepeatRef(field) {\n return field && !util_1.isString(field) && 'repeat' in field;\n}\nexports.isRepeatRef = isRepeatRef;\nfunction isConditionalDef(channelDef) {\n return !!channelDef && !!channelDef.condition;\n}\nexports.isConditionalDef = isConditionalDef;\n/**\n * Return if a channelDef is a ConditionalValueDef with ConditionFieldDef\n */\nfunction hasConditionFieldDef(channelDef) {\n return !!channelDef && !!channelDef.condition && isFieldDef(channelDef.condition);\n}\nexports.hasConditionFieldDef = hasConditionFieldDef;\nfunction isFieldDef(channelDef) {\n return !!channelDef && (!!channelDef['field'] || channelDef['aggregate'] === 'count');\n}\nexports.isFieldDef = isFieldDef;\nfunction isValueDef(channelDef) {\n return channelDef && 'value' in channelDef && channelDef['value'] !== undefined;\n}\nexports.isValueDef = isValueDef;\nfunction isScaleFieldDef(channelDef) {\n return !!channelDef && (!!channelDef['scale'] || !!channelDef['sort']);\n}\nexports.isScaleFieldDef = isScaleFieldDef;\nfunction field(fieldDef, opt) {\n if (opt === void 0) { opt = {}; }\n var field = fieldDef.field;\n var prefix = opt.prefix;\n var suffix = opt.suffix;\n if (isCount(fieldDef)) {\n field = 'count_*';\n }\n else {\n var fn = undefined;\n if (!opt.nofn) {\n if (fieldDef.bin) {\n fn = bin_1.binToString(fieldDef.bin);\n suffix = opt.binSuffix;\n }\n else if (fieldDef.aggregate) {\n fn = String(opt.aggregate || fieldDef.aggregate);\n }\n else if (fieldDef.timeUnit) {\n fn = String(fieldDef.timeUnit);\n }\n }\n if (fn) {\n field = fn + \"_\" + field;\n }\n }\n if (suffix) {\n field = field + \"_\" + suffix;\n }\n if (prefix) {\n field = prefix + \"_\" + field;\n }\n if (opt.expr) {\n field = opt.expr + \"[\" + util_1.stringValue(field) + \"]\";\n }\n return field;\n}\nexports.field = field;\nfunction isDiscrete(fieldDef) {\n switch (fieldDef.type) {\n case 'nominal':\n case 'ordinal':\n return true;\n case 'quantitative':\n return !!fieldDef.bin;\n case 'temporal':\n // TODO: deal with custom scale type case.\n return timeunit_1.isDiscreteByDefault(fieldDef.timeUnit);\n }\n throw new Error(log.message.invalidFieldType(fieldDef.type));\n}\nexports.isDiscrete = isDiscrete;\nfunction isContinuous(fieldDef) {\n return !isDiscrete(fieldDef);\n}\nexports.isContinuous = isContinuous;\nfunction isCount(fieldDef) {\n return fieldDef.aggregate === 'count';\n}\nexports.isCount = isCount;\nfunction title(fieldDef, config) {\n if (isCount(fieldDef)) {\n return config.countTitle;\n }\n var fn = fieldDef.aggregate || fieldDef.timeUnit || (fieldDef.bin && 'bin');\n if (fn) {\n return fn.toUpperCase() + '(' + fieldDef.field + ')';\n }\n else {\n return fieldDef.field;\n }\n}\nexports.title = title;\nfunction defaultType(fieldDef, channel) {\n if (fieldDef.timeUnit) {\n return 'temporal';\n }\n if (fieldDef.bin) {\n return 'quantitative';\n }\n switch (channel_1.rangeType(channel)) {\n case 'continuous':\n return 'quantitative';\n case 'discrete':\n return 'nominal';\n case 'flexible':// color\n return 'nominal';\n default:\n return 'quantitative';\n }\n}\nexports.defaultType = defaultType;\n/**\n * Returns the fieldDef -- either from the outer channelDef or from the condition of channelDef.\n * @param channelDef\n */\nfunction getFieldDef(channelDef) {\n if (isFieldDef(channelDef)) {\n return channelDef;\n }\n else if (hasConditionFieldDef(channelDef)) {\n return channelDef.condition;\n }\n return undefined;\n}\nexports.getFieldDef = getFieldDef;\n/**\n * Convert type to full, lowercase type, or augment the fieldDef with a default type if missing.\n */\nfunction normalize(channelDef, channel) {\n // If a fieldDef contains a field, we need type.\n if (isFieldDef(channelDef)) {\n return normalizeFieldDef(channelDef, channel);\n }\n else if (hasConditionFieldDef(channelDef)) {\n return tslib_1.__assign({}, channelDef, { \n // Need to cast as normalizeFieldDef normally return FieldDef, but here we know that it is definitely Condition\n condition: normalizeFieldDef(channelDef.condition, channel) });\n }\n return channelDef;\n}\nexports.normalize = normalize;\nfunction normalizeFieldDef(fieldDef, channel) {\n // Drop invalid aggregate\n if (fieldDef.aggregate && !aggregate_1.AGGREGATE_OP_INDEX[fieldDef.aggregate]) {\n var aggregate = fieldDef.aggregate, fieldDefWithoutAggregate = tslib_1.__rest(fieldDef, [\"aggregate\"]);\n log.warn(log.message.invalidAggregate(fieldDef.aggregate));\n fieldDef = fieldDefWithoutAggregate;\n }\n // Normalize bin\n if (fieldDef.bin) {\n fieldDef = tslib_1.__assign({}, fieldDef, { bin: normalizeBin(fieldDef.bin, channel) });\n }\n // Normalize Type\n if (fieldDef.type) {\n var fullType = type_1.getFullName(fieldDef.type);\n if (fieldDef.type !== fullType) {\n // convert short type to full type\n fieldDef = tslib_1.__assign({}, fieldDef, { type: fullType });\n }\n if (aggregate_1.isCountingAggregateOp(fieldDef.aggregate) && fieldDef.type !== 'quantitative') {\n log.warn(log.message.invalidFieldTypeForCountAggregate(fieldDef.type, fieldDef.aggregate));\n fieldDef = tslib_1.__assign({}, fieldDef, { type: 'quantitative' });\n }\n }\n else {\n // If type is empty / invalid, then augment with default type\n var newType = defaultType(fieldDef, channel);\n log.warn(log.message.emptyOrInvalidFieldType(fieldDef.type, channel, newType));\n fieldDef = tslib_1.__assign({}, fieldDef, { type: newType });\n }\n var _a = channelCompatibility(fieldDef, channel), compatible = _a.compatible, warning = _a.warning;\n if (!compatible) {\n log.warn(warning);\n }\n return fieldDef;\n}\nexports.normalizeFieldDef = normalizeFieldDef;\nfunction normalizeBin(bin, channel) {\n if (util_1.isBoolean(bin)) {\n return { maxbins: bin_1.autoMaxBins(channel) };\n }\n else if (!bin.maxbins && !bin.step) {\n return tslib_1.__assign({}, bin, { maxbins: bin_1.autoMaxBins(channel) });\n }\n else {\n return bin;\n }\n}\nexports.normalizeBin = normalizeBin;\nvar COMPATIBLE = { compatible: true };\nfunction channelCompatibility(fieldDef, channel) {\n switch (channel) {\n case 'row':\n case 'column':\n if (isContinuous(fieldDef) && !fieldDef.timeUnit) {\n // TODO:(https://github.com/vega/vega-lite/issues/2011):\n // with timeUnit it's not always strictly continuous\n return {\n compatible: false,\n warning: log.message.facetChannelShouldBeDiscrete(channel)\n };\n }\n return COMPATIBLE;\n case 'x':\n case 'y':\n case 'color':\n case 'text':\n case 'detail':\n case 'tooltip':\n return COMPATIBLE;\n case 'opacity':\n case 'size':\n case 'x2':\n case 'y2':\n if (isDiscrete(fieldDef) && !fieldDef.bin) {\n return {\n compatible: false,\n warning: \"Channel \" + channel + \" should not be used with discrete field.\"\n };\n }\n return COMPATIBLE;\n case 'shape':\n if (fieldDef.type !== 'nominal') {\n return {\n compatible: false,\n warning: 'Shape channel should be used with nominal data only'\n };\n }\n return COMPATIBLE;\n case 'order':\n if (fieldDef.type === 'nominal') {\n return {\n compatible: false,\n warning: \"Channel order is inappropriate for nominal field, which has no inherent order.\"\n };\n }\n return COMPATIBLE;\n }\n throw new Error('channelCompatability not implemented for channel ' + channel);\n}\nexports.channelCompatibility = channelCompatibility;\n//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZmllbGRkZWYuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvZmllbGRkZWYudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLHdDQUF3Qzs7O0FBRXhDLHlDQUFtRjtBQUVuRiw2QkFBb0Q7QUFDcEQscUNBQTZDO0FBSzdDLDJCQUE2QjtBQUs3Qix1Q0FBeUQ7QUFDekQsK0JBQXlDO0FBQ3pDLCtCQUF3RDtBQXlEeEQscUJBQTRCLEtBQVk7SUFDdEMsTUFBTSxDQUFDLEtBQUssSUFBSSxDQUFDLGVBQVEsQ0FBQyxLQUFLLENBQUMsSUFBSSxRQUFRLElBQUksS0FBSyxDQUFDO0FBQ3hELENBQUM7QUFGRCxrQ0FFQztBQXVHRCwwQkFBb0MsVUFBeUI7SUFDM0QsTUFBTSxDQUFDLENBQUMsQ0FBQyxVQUFVLElBQUksQ0FBQyxDQUFDLFVBQVUsQ0FBQyxTQUFTLENBQUM7QUFDaEQsQ0FBQztBQUZELDRDQUVDO0FBRUQ7O0dBRUc7QUFDSCw4QkFBd0MsVUFBeUI7SUFDL0QsTUFBTSxDQUFDLENBQUMsQ0FBQyxVQUFVLElBQUksQ0FBQyxDQUFDLFVBQVUsQ0FBQyxTQUFTLElBQUksVUFBVSxDQUFDLFVBQVUsQ0FBQyxTQUFTLENBQUMsQ0FBQztBQUNwRixDQUFDO0FBRkQsb0RBRUM7QUFFRCxvQkFBOEIsVUFBeUI7SUFDckQsTUFBTSxDQUFDLENBQUMsQ0FBQyxVQUFVLElBQUksQ0FBQyxDQUFDLENBQUMsVUFBVSxDQUFDLE9BQU8sQ0FBQyxJQUFJLFVBQVUsQ0FBQyxXQUFXLENBQUMsS0FBSyxPQUFPLENBQUMsQ0FBQztBQUN4RixDQUFDO0FBRkQsZ0NBRUM7QUFFRCxvQkFBOEIsVUFBeUI7SUFDckQsTUFBTSxDQUFDLFVBQVUsSUFBSSxPQUFPLElBQUksVUFBVSxJQUFJLFVBQVUsQ0FBQyxPQUFPLENBQUMsS0FBSyxTQUFTLENBQUM7QUFDbEYsQ0FBQztBQUZELGdDQUVDO0FBRUQseUJBQWdDLFVBQTJCO0lBQ3ZELE1BQU0sQ0FB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", + "\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.defaultLegendConfig = {\n orient: undefined,\n};\nexports.LEGEND_PROPERTIES = ['entryPadding', 'format', 'offset', 'orient', 'tickCount', 'title', 'type', 'values', 'zindex'];\nexports.VG_LEGEND_PROPERTIES = [].concat(['fill', 'stroke', 'shape', 'size', 'opacity', 'encode'], exports.LEGEND_PROPERTIES);\n//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibGVnZW5kLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2xlZ2VuZC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQXFFYSxRQUFBLG1CQUFtQixHQUFpQjtJQUMvQyxNQUFNLEVBQUUsU0FBUztDQUNsQixDQUFDO0FBRVcsUUFBQSxpQkFBaUIsR0FBaUMsQ0FBQyxjQUFjLEVBQUUsUUFBUSxFQUFFLFFBQVEsRUFBRSxRQUFRLEVBQUUsV0FBVyxFQUFFLE9BQU8sRUFBRSxNQUFNLEVBQUUsUUFBUSxFQUFFLFFBQVEsQ0FBQyxDQUFDO0FBRW5KLFFBQUEsb0JBQW9CLEdBQXNCLEVBQUUsQ0FBQyxNQUFNLENBQzlELENBQUMsTUFBTSxFQUFFLFFBQVEsRUFBRSxPQUFPLEVBQUUsTUFBTSxFQUFFLFNBQVMsRUFBRSxRQUFRLENBQUMsRUFDeEQseUJBQWlCLENBQ2xCLENBQUMifQ==", + "\"use strict\";\n/**\n * Vega-Lite's singleton logger utility.\n */\nObject.defineProperty(exports, \"__esModule\", { value: true });\nvar vega_util_1 = require(\"vega-util\");\n/**\n * Main (default) Vega Logger instance for Vega-Lite\n */\nvar main = vega_util_1.logger(vega_util_1.Warn);\nvar current = main;\n/**\n * Logger tool for checking if the code throws correct warning\n */\nvar LocalLogger = (function () {\n function LocalLogger() {\n this.warns = [];\n this.infos = [];\n this.debugs = [];\n }\n LocalLogger.prototype.level = function () {\n return this;\n };\n LocalLogger.prototype.warn = function () {\n var args = [];\n for (var _i = 0; _i < arguments.length; _i++) {\n args[_i] = arguments[_i];\n }\n (_a = this.warns).push.apply(_a, args);\n return this;\n var _a;\n };\n LocalLogger.prototype.info = function () {\n var args = [];\n for (var _i = 0; _i < arguments.length; _i++) {\n args[_i] = arguments[_i];\n }\n (_a = this.infos).push.apply(_a, args);\n return this;\n var _a;\n };\n LocalLogger.prototype.debug = function () {\n var args = [];\n for (var _i = 0; _i < arguments.length; _i++) {\n args[_i] = arguments[_i];\n }\n (_a = this.debugs).push.apply(_a, args);\n return this;\n var _a;\n };\n return LocalLogger;\n}());\nexports.LocalLogger = LocalLogger;\nfunction runLocalLogger(f) {\n var localLogger = current = new LocalLogger();\n f(localLogger);\n reset();\n}\nexports.runLocalLogger = runLocalLogger;\nfunction wrap(f) {\n return function () {\n var logger = current = new LocalLogger();\n f(logger);\n reset();\n };\n}\nexports.wrap = wrap;\n/**\n * Set the singleton logger to be a custom logger\n */\nfunction set(logger) {\n current = logger;\n return current;\n}\nexports.set = set;\n/**\n * Reset the main logger to use the default Vega Logger\n */\nfunction reset() {\n current = main;\n return current;\n}\nexports.reset = reset;\nfunction warn() {\n var _ = [];\n for (var _i = 0; _i < arguments.length; _i++) {\n _[_i] = arguments[_i];\n }\n current.warn.apply(current, arguments);\n}\nexports.warn = warn;\nfunction info() {\n var _ = [];\n for (var _i = 0; _i < arguments.length; _i++) {\n _[_i] = arguments[_i];\n }\n current.info.apply(current, arguments);\n}\nexports.info = info;\nfunction debug() {\n var _ = [];\n for (var _i = 0; _i < arguments.length; _i++) {\n _[_i] = arguments[_i];\n }\n current.debug.apply(current, arguments);\n}\nexports.debug = debug;\n/**\n * Collection of all Vega-Lite Error Messages\n */\nvar message;\n(function (message) {\n message.INVALID_SPEC = 'Invalid spec';\n // SELECTION\n function cannotProjectOnChannelWithoutField(channel) {\n return \"Cannot project a selection on encoding channel \" + channel + \", which has no field.\";\n }\n message.cannotProjectOnChannelWithoutField = cannotProjectOnChannelWithoutField;\n function selectionNotFound(name) {\n return \"Cannot find a selection named \\\"\" + name + \"\\\"\";\n }\n message.selectionNotFound = selectionNotFound;\n // REPEAT\n function noSuchRepeatedValue(field) {\n return \"Unknown repeated value \\\"\" + field + \"\\\".\";\n }\n message.noSuchRepeatedValue = noSuchRepeatedValue;\n // DATA\n function unrecognizedParse(p) {\n return \"Unrecognized parse \" + p + \".\";\n }\n message.unrecognizedParse = unrecognizedParse;\n function differentParse(field, local, ancestor) {\n return \"An ancestor parsed field \" + field + \" as \" + ancestor + \" but a child wants to parse the field as \" + local + \".\";\n }\n message.differentParse = differentParse;\n // TRANSFORMS\n function invalidTransformIgnored(transform) {\n return \"Ignoring an invalid transform: \" + JSON.stringify(transform) + \".\";\n }\n message.invalidTransformIgnored = invalidTransformIgnored;\n message.NO_FIELDS_NEEDS_AS = 'If `from.fields` is not specified, `as` has to be a string that specifies the key to be used for the the data from the secondary source.';\n // ENCODING & FACET\n function invalidFieldType(type) {\n return \"Invalid field type \\\"\" + type + \"\\\"\";\n }\n message.invalidFieldType = invalidFieldType;\n function invalidFieldTypeForCountAggregate(type, aggregate) {\n return \"Invalid field type \\\"\" + type + \"\\\" for aggregate: \\\"\" + aggregate + \"\\\", using \\\"quantitative\\\" instead.\";\n }\n message.invalidFieldTypeForCountAggregate = invalidFieldTypeForCountAggregate;\n function invalidAggregate(aggregate) {\n return \"Invalid aggregation operator \\\"\" + aggregate + \"\\\"\";\n }\n message.invalidAggregate = invalidAggregate;\n function emptyOrInvalidFieldType(type, channel, newType) {\n return \"Invalid field type (\" + type + \") for channel \" + channel + \", using \" + newType + \" instead.\";\n }\n message.emptyOrInvalidFieldType = emptyOrInvalidFieldType;\n function emptyFieldDef(fieldDef, channel) {\n return \"Dropping \" + JSON.stringify(fieldDef) + \" from channel \" + channel + \" since it does not contain data field or value.\";\n }\n message.emptyFieldDef = emptyFieldDef;\n function incompatibleChannel(channel, markOrFacet, when) {\n return channel + \" dropped as it is incompatible with \" + markOrFacet + (when ? \" when \" + when : '') + \".\";\n }\n message.incompatibleChannel = incompatibleChannel;\n function facetChannelShouldBeDiscrete(channel) {\n return channel + \" encoding should be discrete (ordinal / nominal / binned).\";\n }\n message.facetChannelShouldBeDiscrete = facetChannelShouldBeDiscrete;\n function discreteChannelCannotEncode(channel, type) {\n return \"Using discrete channel \" + channel + \" to encode \" + type + \" field can be misleading as it does not encode \" + (type === 'ordinal' ? 'order' : 'magnitude') + \".\";\n }\n message.discreteChannelCannotEncode = discreteChannelCannotEncode;\n // Mark\n message.BAR_WITH_POINT_SCALE_AND_RANGESTEP_NULL = 'Bar mark should not be used with point scale when rangeStep is null. Please use band scale instead.';\n function unclearOrientContinuous(mark) {\n return \"Cannot clearly determine orientation for \" + mark + \" since both x and y channel encode continous fields. In this case, we use vertical by default\";\n }\n message.unclearOrientContinuous = unclearOrientContinuous;\n function unclearOrientDiscreteOrEmpty(mark) {\n return \"Cannot clearly determine orientation for \" + mark + \" since both x and y channel encode discrete or empty fields.\";\n }\n message.unclearOrientDiscreteOrEmpty = unclearOrientDiscreteOrEmpty;\n function orientOverridden(original, actual) {\n return \"Specified orient \" + original + \" overridden with \" + actual;\n }\n message.orientOverridden = orientOverridden;\n // SCALE\n message.CANNOT_UNION_CUSTOM_DOMAIN_WITH_FIELD_DOMAIN = 'custom domain scale cannot be unioned with default field-based domain';\n function cannotUseScalePropertyWithNonColor(prop) {\n return \"Cannot use \" + prop + \" with non-color channel.\";\n }\n message.cannotUseScalePropertyWithNonColor = cannotUseScalePropertyWithNonColor;\n function unaggregateDomainHasNoEffectForRawField(fieldDef) {\n return \"Using unaggregated domain with raw field has no effect (\" + JSON.stringify(fieldDef) + \").\";\n }\n message.unaggregateDomainHasNoEffectForRawField = unaggregateDomainHasNoEffectForRawField;\n function unaggregateDomainWithNonSharedDomainOp(aggregate) {\n return \"Unaggregated domain not applicable for \" + aggregate + \" since it produces values outside the origin domain of the source data.\";\n }\n message.unaggregateDomainWithNonSharedDomainOp = unaggregateDomainWithNonSharedDomainOp;\n function unaggregatedDomainWithLogScale(fieldDef) {\n return \"Unaggregated domain is currently unsupported for log scale (\" + JSON.stringify(fieldDef) + \").\";\n }\n message.unaggregatedDomainWithLogScale = unaggregatedDomainWithLogScale;\n message.CANNOT_USE_RANGE_WITH_POSITION = 'Cannot use custom range with x or y channel. Please customize width, height, padding, or rangeStep instead.';\n function cannotUseSizeFieldWithBandSize(positionChannel) {\n return \"Using size field when \" + positionChannel + \"-channel has a band scale is not supported.\";\n }\n message.cannotUseSizeFieldWithBandSize = cannotUseSizeFieldWithBandSize;\n function cannotApplySizeToNonOrientedMark(mark) {\n return \"Cannot apply size to non-oriented mark \" + mark + \".\";\n }\n message.cannotApplySizeToNonOrientedMark = cannotApplySizeToNonOrientedMark;\n function rangeStepDropped(channel) {\n return \"rangeStep for \" + channel + \" is dropped as top-level \" + (channel === 'x' ? 'width' : 'height') + \" is provided.\";\n }\n message.rangeStepDropped = rangeStepDropped;\n function scaleTypeNotWorkWithChannel(channel, scaleType, defaultScaleType) {\n return \"Channel \" + channel + \" does not work with \" + scaleType + \" scale. We are using \" + defaultScaleType + \" scale instead.\";\n }\n message.scaleTypeNotWorkWithChannel = scaleTypeNotWorkWithChannel;\n function scaleTypeNotWorkWithFieldDef(scaleType, defaultScaleType) {\n return \"FieldDef does not work with \" + scaleType + \" scale. We are using \" + defaultScaleType + \" scale instead.\";\n }\n message.scaleTypeNotWorkWithFieldDef = scaleTypeNotWorkWithFieldDef;\n function scalePropertyNotWorkWithScaleType(scaleType, propName, channel) {\n return channel + \"-scale's \\\"\" + propName + \"\\\" is dropped as it does not work with \" + scaleType + \" scale.\";\n }\n message.scalePropertyNotWorkWithScaleType = scalePropertyNotWorkWithScaleType;\n function scaleTypeNotWorkWithMark(mark, scaleType) {\n return \"Scale type \\\"\" + scaleType + \"\\\" does not work with mark \" + mark + \".\";\n }\n message.scaleTypeNotWorkWithMark = scaleTypeNotWorkWithMark;\n function mergeConflictingProperty(property, propertyOf, v1, v2) {\n return \"Conflicting \" + propertyOf + \" property \" + property + \" (\" + v1 + \" and \" + v2 + \"). Using \" + v1 + \".\";\n }\n message.mergeConflictingProperty = mergeConflictingProperty;\n function independentScaleMeansIndependentGuide(channel) {\n return \"Setting the scale to be independent for \" + channel + \" means we also have to set the guide (axis or legend) to be independent.\";\n }\n message.independentScaleMeansIndependentGuide = independentScaleMeansIndependentGuide;\n function conflictedDomain(channel) {\n return \"Cannot set \" + channel + \"-scale's \\\"domain\\\" as it is binned. Please use \\\"bin\\\"'s \\\"extent\\\" instead.\";\n }\n message.conflictedDomain = conflictedDomain;\n message.INVAID_DOMAIN = 'Invalid scale domain';\n message.UNABLE_TO_MERGE_DOMAINS = 'Unable to merge domains';\n // AXIS\n message.INVALID_CHANNEL_FOR_AXIS = 'Invalid channel for axis.';\n // STACK\n function cannotStackRangedMark(channel) {\n return \"Cannot stack \" + channel + \" if there is already \" + channel + \"2\";\n }\n message.cannotStackRangedMark = cannotStackRangedMark;\n function cannotStackNonLinearScale(scaleType) {\n return \"Cannot stack non-linear scale (\" + scaleType + \")\";\n }\n message.cannotStackNonLinearScale = cannotStackNonLinearScale;\n function cannotStackNonSummativeAggregate(aggregate) {\n return \"Cannot stack when the aggregate function is non-summative (\" + aggregate + \")\";\n }\n message.cannotStackNonSummativeAggregate = cannotStackNonSummativeAggregate;\n // TIMEUNIT\n function invalidTimeUnit(unitName, value) {\n return \"Invalid \" + unitName + \": \" + value;\n }\n message.invalidTimeUnit = invalidTimeUnit;\n function dayReplacedWithDate(fullTimeUnit) {\n return \"Time unit \\\"\" + fullTimeUnit + \"\\\" is not supported. We are replacing it with \" + fullTimeUnit.replace('day', 'date') + \".\";\n }\n message.dayReplacedWithDate = dayReplacedWithDate;\n function droppedDay(d) {\n return \"Dropping day from datetime \" + JSON.stringify(d) + \" as day cannot be combined with other units.\";\n }\n message.droppedDay = droppedDay;\n})(message = exports.message || (exports.message = {}));\n//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibG9nLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2xvZy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUE7O0dBRUc7O0FBRUgsdUNBQXdEO0FBZ0J4RDs7R0FFRztBQUNILElBQU0sSUFBSSxHQUFHLGtCQUFNLENBQUMsZ0JBQUksQ0FBQyxDQUFDO0FBQzFCLElBQUksT0FBTyxHQUFvQixJQUFJLENBQUM7QUFFcEM7O0dBRUc7QUFDSDtJQUFBO1FBQ1MsVUFBSyxHQUFVLEVBQUUsQ0FBQztRQUNsQixVQUFLLEdBQVUsRUFBRSxDQUFDO1FBQ2xCLFdBQU0sR0FBVSxFQUFFLENBQUM7SUFvQjVCLENBQUM7SUFsQlEsMkJBQUssR0FBWjtRQUNFLE1BQU0sQ0FBQyxJQUFJLENBQUM7SUFDZCxDQUFDO0lBRU0sMEJBQUksR0FBWDtRQUFZLGNBQWM7YUFBZCxVQUFjLEVBQWQscUJBQWMsRUFBZCxJQUFjO1lBQWQseUJBQWM7O1FBQ3hCLENBQUEsS0FBQSxJQUFJLENBQUMsS0FBSyxDQUFBLENBQUMsSUFBSSxXQUFJLElBQUksRUFBRTtRQUN6QixNQUFNLENBQUMsSUFBSSxDQUFDOztJQUNkLENBQUM7SUFFTSwwQkFBSSxHQUFYO1FBQVksY0FBYzthQUFkLFVBQWMsRUFBZCxxQkFBYyxFQUFkLElBQWM7WUFBZCx5QkFBYzs7UUFDeEIsQ0FBQSxLQUFBLElBQUksQ0FBQyxLQUFLLENBQUEsQ0FBQyxJQUFJLFdBQUksSUFBSSxFQUFFO1FBQ3pCLE1BQU0sQ0FBQyxJQUFJLENBQUM7O0lBQ2QsQ0FBQztJQUVNLDJCQUFLLEdBQVo7UUFBYSxjQUFjO2FBQWQsVUFBYyxFQUFkLHFCQUFjLEVBQWQsSUFBYztZQUFkLHlCQUFjOztRQUN6QixDQUFBLEtBQUEsSUFBSSxDQUFDLE1BQU0sQ0FBQSxDQUFDLElBQUksV0FBSSxJQUFJLEVBQUU7UUFDMUIsTUFBTSxDQUFDLElBQUksQ0FBQzs7SUFDZCxDQUFDO0lBQ0gsa0JBQUM7QUFBRCxDQUFD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", + "\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nfunction isLogicalOr(op) {\n return !!op.or;\n}\nexports.isLogicalOr = isLogicalOr;\nfunction isLogicalAnd(op) {\n return !!op.and;\n}\nexports.isLogicalAnd = isLogicalAnd;\nfunction isLogicalNot(op) {\n return !!op.not;\n}\nexports.isLogicalNot = isLogicalNot;\n//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibG9naWNhbC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9sb2dpY2FsLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7O0FBY0EscUJBQTRCLEVBQXVCO0lBQ2pELE1BQU0sQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQztBQUNqQixDQUFDO0FBRkQsa0NBRUM7QUFFRCxzQkFBNkIsRUFBdUI7SUFDbEQsTUFBTSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsR0FBRyxDQUFDO0FBQ2xCLENBQUM7QUFGRCxvQ0FFQztBQUVELHNCQUE2QixFQUF1QjtJQUNsRCxNQUFNLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxHQUFHLENBQUM7QUFDbEIsQ0FBQztBQUZELG9DQUVDIn0=", + "\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nvar util_1 = require(\"./util\");\nvar Mark;\n(function (Mark) {\n Mark.AREA = 'area';\n Mark.BAR = 'bar';\n Mark.LINE = 'line';\n Mark.POINT = 'point';\n Mark.RECT = 'rect';\n Mark.RULE = 'rule';\n Mark.TEXT = 'text';\n Mark.TICK = 'tick';\n Mark.CIRCLE = 'circle';\n Mark.SQUARE = 'square';\n})(Mark = exports.Mark || (exports.Mark = {}));\nexports.AREA = Mark.AREA;\nexports.BAR = Mark.BAR;\nexports.LINE = Mark.LINE;\nexports.POINT = Mark.POINT;\nexports.TEXT = Mark.TEXT;\nexports.TICK = Mark.TICK;\nexports.RECT = Mark.RECT;\nexports.RULE = Mark.RULE;\nexports.CIRCLE = Mark.CIRCLE;\nexports.SQUARE = Mark.SQUARE;\nexports.PRIMITIVE_MARKS = [exports.AREA, exports.BAR, exports.LINE, exports.POINT, exports.TEXT, exports.TICK, exports.RECT, exports.RULE, exports.CIRCLE, exports.SQUARE];\nfunction isMarkDef(mark) {\n return mark['type'];\n}\nexports.isMarkDef = isMarkDef;\nvar PRIMITIVE_MARK_INDEX = util_1.toSet(exports.PRIMITIVE_MARKS);\nfunction isPrimitiveMark(mark) {\n var markType = isMarkDef(mark) ? mark.type : mark;\n return markType in PRIMITIVE_MARK_INDEX;\n}\nexports.isPrimitiveMark = isPrimitiveMark;\nexports.STROKE_CONFIG = ['stroke', 'strokeWidth',\n 'strokeDash', 'strokeDashOffset', 'strokeOpacity'];\nexports.FILL_CONFIG = ['fill', 'fillOpacity'];\nexports.FILL_STROKE_CONFIG = [].concat(exports.STROKE_CONFIG, exports.FILL_CONFIG);\nexports.VL_ONLY_MARK_CONFIG_PROPERTIES = ['filled', 'color'];\nexports.VL_ONLY_MARK_SPECIFIC_CONFIG_PROPERTY_INDEX = {\n bar: ['binSpacing', 'continuousBandSize', 'discreteBandSize'],\n text: ['shortTimeLabels'],\n tick: ['bandSize', 'thickness']\n};\nexports.defaultMarkConfig = {\n color: '#4c78a8',\n};\nexports.defaultBarConfig = {\n binSpacing: 1,\n continuousBandSize: 2\n};\nexports.defaultTickConfig = {\n thickness: 1\n};\n//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWFyay5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9tYXJrLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7O0FBQ0EsK0JBQW1DO0FBR25DLElBQWlCLElBQUksQ0FXcEI7QUFYRCxXQUFpQixJQUFJO0lBQ04sU0FBSSxHQUFXLE1BQU0sQ0FBQztJQUN0QixRQUFHLEdBQVUsS0FBSyxDQUFDO0lBQ25CLFNBQUksR0FBVyxNQUFNLENBQUM7SUFDdEIsVUFBSyxHQUFZLE9BQU8sQ0FBQztJQUN6QixTQUFJLEdBQVcsTUFBTSxDQUFDO0lBQ3RCLFNBQUksR0FBVyxNQUFNLENBQUM7SUFDdEIsU0FBSSxHQUFXLE1BQU0sQ0FBQztJQUN0QixTQUFJLEdBQVcsTUFBTSxDQUFDO0lBQ3RCLFdBQU0sR0FBYSxRQUFRLENBQUM7SUFDNUIsV0FBTSxHQUFhLFFBQVEsQ0FBQztBQUMzQyxDQUFDLEVBWGdCLElBQUksR0FBSixZQUFJLEtBQUosWUFBSSxRQVdwQjtBQVFZLFFBQUEsSUFBSSxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUM7QUFDakIsUUFBQSxHQUFHLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQztBQUNmLFFBQUEsSUFBSSxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUM7QUFDakIsUUFBQSxLQUFLLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQztBQUNuQixRQUFBLElBQUksR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDO0FBQ2pCLFFBQUEsSUFBSSxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUM7QUFDakIsUUFBQSxJQUFJLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQztBQUNqQixRQUFBLElBQUksR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDO0FBRWpCLFFBQUEsTUFBTSxHQUFHLElBQUksQ0FBQyxNQUFNLENBQUM7QUFDckIsUUFBQSxNQUFNLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQztBQUVyQixRQUFBLGVBQWUsR0FBRyxDQUFDLFlBQUksRUFBRSxXQUFHLEVBQUUsWUFBSSxFQUFFLGFBQUssRUFBRSxZQUFJLEVBQUUsWUFBSSxFQUFFLFlBQUksRUFBRSxZQUFJLEVBQUUsY0FBTSxFQUFFLGNBQU0sQ0FBQyxDQUFDO0FBb0VoRyxtQkFBMEIsSUFBYTtJQUNyQyxNQUFNLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDO0FBQ3RCLENBQUM7QUFGRCw4QkFFQztBQUVELElBQU0sb0JBQW9CLEdBQUcsWUFBSyxDQUFDLHVCQUFlLENBQUMsQ0FBQztBQUVwRCx5QkFBZ0MsSUFBdUQ7SUFDckYsSUFBTSxRQUFRLEdBQUcsU0FBUyxDQUFDLElBQUksQ0FBQyxHQUFHLElBQUksQ0FBQyxJQUFJLEdBQUcsSUFBSSxDQUFDO0lBQ3BELE1BQU0sQ0FBQyxRQUFRLElBQUksb0JBQW9CLENBQUM7QUFDMUMsQ0FBQztBQUhELDBDQUdDO0FBRVksUUFBQSxhQUFhLEdBQUcsQ0FBQyxRQUFRLEVBQUUsYUFBYTtJQUNuRCxZQUFZLEVBQUUsa0JBQWtCLEVBQUUsZUFBZSxDQUFDLENBQUM7QUFFeEMsUUFBQSxXQUFXLEdBQUcsQ0FBQyxNQUFNLEVBQUUsYUFBYSxDQUFDLENBQUM7QUFFdEMsUUFBQSxrQkFBa0IsR0FBRyxFQUFFLENBQUMsTUFBTSxDQUFDLHFCQUFhLEVBQUUsbUJBQVcsQ0FBQyxDQUFDO0FBRTNELFFBQUEsOEJBQThCLEdBQXlCLENBQUMsUUFBUSxFQUFFLE9BQU8sQ0FBQyxDQUFDO0FBRTNFLFFBQUEsMkNBQTJDLEdBRXBEO0lBQ0YsR0FBRyxFQUFFLENBQUMsWUFBWSxFQUFFLG9CQUFvQixFQUFFLGtCQUFrQixDQUFDO0lBQzdELElBQUksRUFBRSxDQUFDLGlCQUFpQixDQUFDO0lBQ3pCLElBQUksRUFBRSxDQUFDLFVBQVUsRUFBRSxXQUFXLENBQUM7Q0FDaEMsQ0FBQztBQThCVyxRQUFBLGlCQUFpQixHQUFlO0lBQzNDLEtBQUssRUFBRSxTQUFTO0NBQ2pCLENBQUM7QUFnRVcsUUFBQSxnQkFBZ0IsR0FBYztJQUN6QyxVQUFVLEVBQUUsQ0FBQztJQUNiLGtCQUFrQixFQUFFLENBQUM7Q0FDdEIsQ0FBQztBQXVDVyxRQUFBLGlCQUFpQixHQUFlO0lBQzNDLFNBQVMsRUFBRSxDQUFDO0NBQ2IsQ0FBQyJ9", + "\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nvar log = require(\"./log\");\nvar util_1 = require(\"./util\");\nvar ScaleType;\n(function (ScaleType) {\n // Continuous - Quantitative\n ScaleType.LINEAR = 'linear';\n ScaleType.BIN_LINEAR = 'bin-linear';\n ScaleType.LOG = 'log';\n ScaleType.POW = 'pow';\n ScaleType.SQRT = 'sqrt';\n // Continuous - Time\n ScaleType.TIME = 'time';\n ScaleType.UTC = 'utc';\n // sequential\n ScaleType.SEQUENTIAL = 'sequential';\n // Quantile, Quantize, threshold\n ScaleType.QUANTILE = 'quantile';\n ScaleType.QUANTIZE = 'quantize';\n ScaleType.THRESHOLD = 'threshold';\n ScaleType.ORDINAL = 'ordinal';\n ScaleType.BIN_ORDINAL = 'bin-ordinal';\n ScaleType.POINT = 'point';\n ScaleType.BAND = 'band';\n})(ScaleType = exports.ScaleType || (exports.ScaleType = {}));\nexports.SCALE_TYPES = [\n // Continuous - Quantitative\n 'linear', 'bin-linear', 'log', 'pow', 'sqrt',\n // Continuous - Time\n 'time', 'utc',\n // Sequential\n 'sequential',\n // Discrete\n 'ordinal', 'bin-ordinal', 'point', 'band',\n];\n/**\n * Index for scale categories -- only scale of the same categories can be merged together.\n * Current implementation is trying to be conservative and avoid merging scale type that might not work together\n */\nvar SCALE_CATEGORY_INDEX = {\n linear: 'numeric',\n log: 'numeric',\n pow: 'numeric',\n sqrt: 'numeric',\n 'bin-linear': 'bin-linear',\n time: 'time',\n utc: 'time',\n sequential: 'sequential',\n ordinal: 'ordinal',\n 'bin-ordinal': 'bin-ordinal',\n point: 'ordinal-position',\n band: 'ordinal-position'\n};\nfunction getScaleCategory(scaleType) {\n return SCALE_CATEGORY_INDEX[scaleType];\n}\nexports.getScaleCategory = getScaleCategory;\n/**\n * Whether the two given scale types can be merged together.\n */\nfunction scaleCompatible(scaleType1, scaleType2) {\n return SCALE_CATEGORY_INDEX[scaleType1] === SCALE_CATEGORY_INDEX[scaleType2];\n}\nexports.scaleCompatible = scaleCompatible;\n/**\n * Index for scale predecence -- high score = higher priority for merging.\n */\nvar SCALE_PRECEDENCE_INDEX = {\n // numeric\n linear: 0,\n log: 1,\n pow: 1,\n sqrt: 1,\n // time\n time: 0,\n utc: 0,\n // ordinal-position\n point: 0,\n band: 1,\n // non grouped types\n 'bin-linear': 0,\n sequential: 0,\n ordinal: 0,\n 'bin-ordinal': 0,\n};\n/**\n * Return scale categories -- only scale of the same categories can be merged together.\n */\nfunction scaleTypePrecedence(scaleType) {\n return SCALE_PRECEDENCE_INDEX[scaleType];\n}\nexports.scaleTypePrecedence = scaleTypePrecedence;\nexports.CONTINUOUS_TO_CONTINUOUS_SCALES = ['linear', 'bin-linear', 'log', 'pow', 'sqrt', 'time', 'utc'];\nvar CONTINUOUS_TO_CONTINUOUS_INDEX = util_1.toSet(exports.CONTINUOUS_TO_CONTINUOUS_SCALES);\nexports.CONTINUOUS_DOMAIN_SCALES = exports.CONTINUOUS_TO_CONTINUOUS_SCALES.concat(['sequential' /* TODO add 'quantile', 'quantize', 'threshold'*/]);\nvar CONTINUOUS_DOMAIN_INDEX = util_1.toSet(exports.CONTINUOUS_DOMAIN_SCALES);\nexports.DISCRETE_DOMAIN_SCALES = ['ordinal', 'bin-ordinal', 'point', 'band'];\nvar DISCRETE_DOMAIN_INDEX = util_1.toSet(exports.DISCRETE_DOMAIN_SCALES);\nvar BIN_SCALES_INDEX = util_1.toSet(['bin-linear', 'bin-ordinal']);\nexports.TIME_SCALE_TYPES = ['time', 'utc'];\nfunction hasDiscreteDomain(type) {\n return type in DISCRETE_DOMAIN_INDEX;\n}\nexports.hasDiscreteDomain = hasDiscreteDomain;\nfunction isBinScale(type) {\n return type in BIN_SCALES_INDEX;\n}\nexports.isBinScale = isBinScale;\nfunction hasContinuousDomain(type) {\n return type in CONTINUOUS_DOMAIN_INDEX;\n}\nexports.hasContinuousDomain = hasContinuousDomain;\nfunction isContinuousToContinuous(type) {\n return type in CONTINUOUS_TO_CONTINUOUS_INDEX;\n}\nexports.isContinuousToContinuous = isContinuousToContinuous;\nexports.defaultScaleConfig = {\n round: true,\n textXRangeStep: 90,\n rangeStep: 21,\n pointPadding: 0.5,\n bandPaddingInner: 0.1,\n facetSpacing: 16,\n minFontSize: 8,\n maxFontSize: 40,\n minOpacity: 0.3,\n maxOpacity: 0.8,\n // FIXME: revise if these *can* become ratios of rangeStep\n minSize: 9,\n minStrokeWidth: 1,\n maxStrokeWidth: 4,\n shapes: ['circle', 'square', 'cross', 'diamond', 'triangle-up', 'triangle-down']\n};\nfunction isExtendedScheme(scheme) {\n return scheme && !!scheme['name'];\n}\nexports.isExtendedScheme = isExtendedScheme;\nfunction isSelectionDomain(domain) {\n return domain && domain['selection'];\n}\nexports.isSelectionDomain = isSelectionDomain;\nexports.NON_TYPE_DOMAIN_RANGE_VEGA_SCALE_PROPERTIES = [\n 'reverse', 'round',\n // quantitative / time\n 'clamp', 'nice',\n // quantitative\n 'exponent', 'interpolate', 'zero',\n // ordinal\n 'padding', 'paddingInner', 'paddingOuter',\n];\nexports.SCALE_PROPERTIES = [].concat([\n 'type', 'domain',\n 'range', 'rangeStep', 'scheme'\n], exports.NON_TYPE_DOMAIN_RANGE_VEGA_SCALE_PROPERTIES);\nfunction scaleTypeSupportProperty(scaleType, propName) {\n switch (propName) {\n case 'type':\n case 'domain':\n case 'reverse':\n case 'range':\n case 'scheme':\n return true;\n case 'interpolate':\n return util_1.contains(['linear', 'bin-linear', 'pow', 'log', 'sqrt', 'utc', 'time'], scaleType);\n case 'round':\n return isContinuousToContinuous(scaleType) || scaleType === 'band' || scaleType === 'point';\n case 'rangeStep':\n case 'padding':\n case 'paddingOuter':\n return util_1.contains(['point', 'band'], scaleType);\n case 'paddingInner':\n return scaleType === 'band';\n case 'clamp':\n return isContinuousToContinuous(scaleType) || scaleType === 'sequential';\n case 'nice':\n return isContinuousToContinuous(scaleType) || scaleType === 'sequential' || scaleType === 'quantize';\n case 'exponent':\n return scaleType === 'pow' || scaleType === 'log';\n case 'zero':\n // TODO: what about quantize, threshold?\n return scaleType === 'bin-ordinal' || (!hasDiscreteDomain(scaleType) && !util_1.contains(['log', 'time', 'utc', 'bin-linear'], scaleType));\n }\n /* istanbul ignore next: should never reach here*/\n throw new Error(\"Invalid scale property \" + propName + \".\");\n}\nexports.scaleTypeSupportProperty = scaleTypeSupportProperty;\n/**\n * Returns undefined if the input channel supports the input scale property name\n */\nfunction channelScalePropertyIncompatability(channel, propName) {\n switch (propName) {\n case 'range':\n // User should not customize range for position and facet channel directly.\n if (channel === 'x' || channel === 'y') {\n return log.message.CANNOT_USE_RANGE_WITH_POSITION;\n }\n return undefined; // GOOD!\n case 'interpolate':\n case 'scheme':\n if (channel !== 'color') {\n return log.message.cannotUseScalePropertyWithNonColor(channel);\n }\n return undefined;\n case 'type':\n case 'domain':\n case 'exponent':\n case 'nice':\n case 'padding':\n case 'paddingInner':\n case 'paddingOuter':\n case 'rangeStep':\n case 'reverse':\n case 'round':\n case 'clamp':\n case 'zero':\n return undefined; // GOOD!\n }\n /* istanbul ignore next: it should never reach here */\n throw new Error('Invalid scale property \"${propName}\".');\n}\nexports.channelScalePropertyIncompatability = channelScalePropertyIncompatability;\n//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2NhbGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvc2NhbGUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFFQSwyQkFBNkI7QUFDN0IsK0JBQXVDO0FBSXZDLElBQWlCLFNBQVMsQ0FzQnpCO0FBdEJELFdBQWlCLFNBQVM7SUFDeEIsNEJBQTRCO0lBQ2YsZ0JBQU0sR0FBYSxRQUFRLENBQUM7SUFDNUIsb0JBQVUsR0FBaUIsWUFBWSxDQUFDO0lBQ3hDLGFBQUcsR0FBVSxLQUFLLENBQUM7SUFDbkIsYUFBRyxHQUFVLEtBQUssQ0FBQztJQUNuQixjQUFJLEdBQVcsTUFBTSxDQUFDO0lBQ25DLG9CQUFvQjtJQUNQLGNBQUksR0FBVyxNQUFNLENBQUM7SUFDdEIsYUFBRyxHQUFXLEtBQUssQ0FBQztJQUNqQyxhQUFhO0lBQ0Esb0JBQVUsR0FBaUIsWUFBWSxDQUFDO0lBRXJELGdDQUFnQztJQUNuQixrQkFBUSxHQUFlLFVBQVUsQ0FBQztJQUNsQyxrQkFBUSxHQUFlLFVBQVUsQ0FBQztJQUNsQyxtQkFBUyxHQUFnQixXQUFXLENBQUM7SUFFckMsaUJBQU8sR0FBYyxTQUFTLENBQUM7SUFDL0IscUJBQVcsR0FBa0IsYUFBYSxDQUFDO0lBQzNDLGVBQUssR0FBWSxPQUFPLENBQUM7SUFDekIsY0FBSSxHQUFXLE1BQU0sQ0FBQztBQUNyQyxDQUFDLEVBdEJnQixTQUFTLEdBQVQsaUJBQVMsS0FBVCxpQkFBUyxRQXNCekI7QUFTWSxRQUFBLFdBQVcsR0FBZ0I7SUFDdEMsNEJBQTRCO0lBQzVCLFFBQVEsRUFBRSxZQUFZLEVBQUUsS0FBSyxFQUFFLEtBQUssRUFBRSxNQUFNO0lBQzVDLG9CQUFvQjtJQUNwQixNQUFNLEVBQUUsS0FBSztJQUNiLGFBQWE7SUFDYixZQUFZO0lBQ1osV0FBVztJQUNYLFNBQVMsRUFBRSxhQUFhLEVBQUUsT0FBTyxFQUFFLE1BQU07Q0FDMUMsQ0FBQztBQUVGOzs7R0FHRztBQUNILElBQU0sb0JBQW9C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", + "\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nvar datetime_1 = require(\"./datetime\");\nvar log = require(\"./log\");\nvar util_1 = require(\"./util\");\nvar TimeUnit;\n(function (TimeUnit) {\n TimeUnit.YEAR = 'year';\n TimeUnit.MONTH = 'month';\n TimeUnit.DAY = 'day';\n TimeUnit.DATE = 'date';\n TimeUnit.HOURS = 'hours';\n TimeUnit.MINUTES = 'minutes';\n TimeUnit.SECONDS = 'seconds';\n TimeUnit.MILLISECONDS = 'milliseconds';\n TimeUnit.YEARMONTH = 'yearmonth';\n TimeUnit.YEARMONTHDATE = 'yearmonthdate';\n TimeUnit.YEARMONTHDATEHOURS = 'yearmonthdatehours';\n TimeUnit.YEARMONTHDATEHOURSMINUTES = 'yearmonthdatehoursminutes';\n TimeUnit.YEARMONTHDATEHOURSMINUTESSECONDS = 'yearmonthdatehoursminutesseconds';\n // MONTHDATE always include 29 February since we use year 0th (which is a leap year);\n TimeUnit.MONTHDATE = 'monthdate';\n TimeUnit.HOURSMINUTES = 'hoursminutes';\n TimeUnit.HOURSMINUTESSECONDS = 'hoursminutesseconds';\n TimeUnit.MINUTESSECONDS = 'minutesseconds';\n TimeUnit.SECONDSMILLISECONDS = 'secondsmilliseconds';\n TimeUnit.QUARTER = 'quarter';\n TimeUnit.YEARQUARTER = 'yearquarter';\n TimeUnit.QUARTERMONTH = 'quartermonth';\n TimeUnit.YEARQUARTERMONTH = 'yearquartermonth';\n TimeUnit.UTCYEAR = 'utcyear';\n TimeUnit.UTCMONTH = 'utcmonth';\n TimeUnit.UTCDAY = 'utcday';\n TimeUnit.UTCDATE = 'utcdate';\n TimeUnit.UTCHOURS = 'utchours';\n TimeUnit.UTCMINUTES = 'utcminutes';\n TimeUnit.UTCSECONDS = 'utcseconds';\n TimeUnit.UTCMILLISECONDS = 'utcmilliseconds';\n TimeUnit.UTCYEARMONTH = 'utcyearmonth';\n TimeUnit.UTCYEARMONTHDATE = 'utcyearmonthdate';\n TimeUnit.UTCYEARMONTHDATEHOURS = 'utcyearmonthdatehours';\n TimeUnit.UTCYEARMONTHDATEHOURSMINUTES = 'utcyearmonthdatehoursminutes';\n TimeUnit.UTCYEARMONTHDATEHOURSMINUTESSECONDS = 'utcyearmonthdatehoursminutesseconds';\n // MONTHDATE always include 29 February since we use year 0th (which is a leap year);\n TimeUnit.UTCMONTHDATE = 'utcmonthdate';\n TimeUnit.UTCHOURSMINUTES = 'utchoursminutes';\n TimeUnit.UTCHOURSMINUTESSECONDS = 'utchoursminutesseconds';\n TimeUnit.UTCMINUTESSECONDS = 'utcminutesseconds';\n TimeUnit.UTCSECONDSMILLISECONDS = 'utcsecondsmilliseconds';\n TimeUnit.UTCQUARTER = 'utcquarter';\n TimeUnit.UTCYEARQUARTER = 'utcyearquarter';\n TimeUnit.UTCQUARTERMONTH = 'utcquartermonth';\n TimeUnit.UTCYEARQUARTERMONTH = 'utcyearquartermonth';\n})(TimeUnit = exports.TimeUnit || (exports.TimeUnit = {}));\n/** Time Unit that only corresponds to only one part of Date objects. */\nexports.SINGLE_TIMEUNITS = [\n TimeUnit.YEAR,\n TimeUnit.QUARTER,\n TimeUnit.MONTH,\n TimeUnit.DAY,\n TimeUnit.DATE,\n TimeUnit.HOURS,\n TimeUnit.MINUTES,\n TimeUnit.SECONDS,\n TimeUnit.MILLISECONDS\n];\nvar SINGLE_TIMEUNIT_INDEX = exports.SINGLE_TIMEUNITS.reduce(function (d, timeUnit) {\n d[timeUnit] = true;\n return d;\n}, {});\nfunction isSingleTimeUnit(timeUnit) {\n return !!SINGLE_TIMEUNIT_INDEX[timeUnit];\n}\nexports.isSingleTimeUnit = isSingleTimeUnit;\n/**\n * Converts a date to only have the measurements relevant to the specified unit\n * i.e. ('yearmonth', '2000-12-04 07:58:14') -> '2000-12-01 00:00:00'\n * Note: the base date is Jan 01 1900 00:00:00\n */\nfunction convert(unit, date) {\n var result = new Date(0, 0, 1, 0, 0, 0, 0); // start with uniform date\n exports.SINGLE_TIMEUNITS.forEach(function (singleUnit) {\n if (containsTimeUnit(unit, singleUnit)) {\n switch (singleUnit) {\n case TimeUnit.DAY:\n throw new Error('Cannot convert to TimeUnits containing \\'day\\'');\n case TimeUnit.YEAR:\n result.setFullYear(date.getFullYear());\n break;\n case TimeUnit.QUARTER:\n // indicate quarter by setting month to be the first of the quarter i.e. may (4) -> april (3)\n result.setMonth((Math.floor(date.getMonth() / 3)) * 3);\n break;\n case TimeUnit.MONTH:\n result.setMonth(date.getMonth());\n break;\n case TimeUnit.DATE:\n result.setDate(date.getDate());\n break;\n case TimeUnit.HOURS:\n result.setHours(date.getHours());\n break;\n case TimeUnit.MINUTES:\n result.setMinutes(date.getMinutes());\n break;\n case TimeUnit.SECONDS:\n result.setSeconds(date.getSeconds());\n break;\n case TimeUnit.MILLISECONDS:\n result.setMilliseconds(date.getMilliseconds());\n break;\n }\n }\n });\n return result;\n}\nexports.convert = convert;\nexports.MULTI_TIMEUNITS = [\n TimeUnit.YEARQUARTER,\n TimeUnit.YEARQUARTERMONTH,\n TimeUnit.YEARMONTH,\n TimeUnit.YEARMONTHDATE,\n TimeUnit.YEARMONTHDATEHOURS,\n TimeUnit.YEARMONTHDATEHOURSMINUTES,\n TimeUnit.YEARMONTHDATEHOURSMINUTESSECONDS,\n TimeUnit.QUARTERMONTH,\n TimeUnit.HOURSMINUTES,\n TimeUnit.HOURSMINUTESSECONDS,\n TimeUnit.MINUTESSECONDS,\n TimeUnit.SECONDSMILLISECONDS,\n];\nvar MULTI_TIMEUNIT_INDEX = exports.MULTI_TIMEUNITS.reduce(function (d, timeUnit) {\n d[timeUnit] = true;\n return d;\n}, {});\nfunction isMultiTimeUnit(timeUnit) {\n return !!MULTI_TIMEUNIT_INDEX[timeUnit];\n}\nexports.isMultiTimeUnit = isMultiTimeUnit;\nexports.TIMEUNITS = [\n TimeUnit.YEAR,\n TimeUnit.QUARTER,\n TimeUnit.MONTH,\n TimeUnit.DAY,\n TimeUnit.DATE,\n TimeUnit.HOURS,\n TimeUnit.MINUTES,\n TimeUnit.SECONDS,\n TimeUnit.MILLISECONDS,\n TimeUnit.YEARQUARTER,\n TimeUnit.YEARQUARTERMONTH,\n TimeUnit.YEARMONTH,\n TimeUnit.YEARMONTHDATE,\n TimeUnit.YEARMONTHDATEHOURS,\n TimeUnit.YEARMONTHDATEHOURSMINUTES,\n TimeUnit.YEARMONTHDATEHOURSMINUTESSECONDS,\n TimeUnit.QUARTERMONTH,\n TimeUnit.HOURSMINUTES,\n TimeUnit.HOURSMINUTESSECONDS,\n TimeUnit.MINUTESSECONDS,\n TimeUnit.SECONDSMILLISECONDS,\n];\n/** Returns true if fullTimeUnit contains the timeUnit, false otherwise. */\nfunction containsTimeUnit(fullTimeUnit, timeUnit) {\n var index = fullTimeUnit.indexOf(timeUnit);\n return index > -1 &&\n (timeUnit !== TimeUnit.SECONDS ||\n index === 0 ||\n fullTimeUnit.charAt(index - 1) !== 'i' // exclude milliseconds\n );\n}\nexports.containsTimeUnit = containsTimeUnit;\n/**\n * Returns Vega expresssion for a given timeUnit and fieldRef\n */\nfunction fieldExpr(fullTimeUnit, field) {\n var fieldRef = \"datum[\" + util_1.stringValue(field) + \"]\";\n var utc = isUTCTimeUnit(fullTimeUnit) ? 'utc' : '';\n function func(timeUnit) {\n if (timeUnit === TimeUnit.QUARTER) {\n // quarter starting at 0 (0,3,6,9).\n return \"(\" + utc + \"quarter(\" + fieldRef + \")-1)\";\n }\n else {\n return \"\" + utc + timeUnit + \"(\" + fieldRef + \")\";\n }\n }\n var d = exports.SINGLE_TIMEUNITS.reduce(function (dateExpr, tu) {\n if (containsTimeUnit(fullTimeUnit, tu)) {\n dateExpr[tu] = func(tu);\n }\n return dateExpr;\n }, {});\n if (d.day && util_1.keys(d).length > 1) {\n log.warn(log.message.dayReplacedWithDate(fullTimeUnit));\n delete d.day;\n d.date = func(TimeUnit.DATE);\n }\n return datetime_1.dateTimeExpr(d);\n}\nexports.fieldExpr = fieldExpr;\n/** returns the smallest nice unit for scale.nice */\nfunction smallestUnit(timeUnit) {\n if (!timeUnit) {\n return undefined;\n }\n if (containsTimeUnit(timeUnit, TimeUnit.SECONDS)) {\n return 'second';\n }\n if (containsTimeUnit(timeUnit, TimeUnit.MINUTES)) {\n return 'minute';\n }\n if (containsTimeUnit(timeUnit, TimeUnit.HOURS)) {\n return 'hour';\n }\n if (containsTimeUnit(timeUnit, TimeUnit.DAY) ||\n containsTimeUnit(timeUnit, TimeUnit.DATE)) {\n return 'day';\n }\n if (containsTimeUnit(timeUnit, TimeUnit.MONTH)) {\n return 'month';\n }\n if (containsTimeUnit(timeUnit, TimeUnit.YEAR)) {\n return 'year';\n }\n return undefined;\n}\nexports.smallestUnit = smallestUnit;\n/**\n * returns the signal expression used for axis labels for a time unit\n */\nfunction formatExpression(timeUnit, field, shortTimeLabels, isUTCScale) {\n if (!timeUnit) {\n return undefined;\n }\n var dateComponents = [];\n var expression = '';\n var hasYear = containsTimeUnit(timeUnit, TimeUnit.YEAR);\n if (containsTimeUnit(timeUnit, TimeUnit.QUARTER)) {\n // special expression for quarter as prefix\n expression = \"'Q' + quarter(\" + field + \")\";\n }\n if (containsTimeUnit(timeUnit, TimeUnit.MONTH)) {\n // By default use short month name\n dateComponents.push(shortTimeLabels !== false ? '%b' : '%B');\n }\n if (containsTimeUnit(timeUnit, TimeUnit.DAY)) {\n dateComponents.push(shortTimeLabels ? '%a' : '%A');\n }\n else if (containsTimeUnit(timeUnit, TimeUnit.DATE)) {\n dateComponents.push('%d' + (hasYear ? ',' : '')); // add comma if there is year\n }\n if (hasYear) {\n dateComponents.push(shortTimeLabels ? '%y' : '%Y');\n }\n var timeComponents = [];\n if (containsTimeUnit(timeUnit, TimeUnit.HOURS)) {\n timeComponents.push('%H');\n }\n if (containsTimeUnit(timeUnit, TimeUnit.MINUTES)) {\n timeComponents.push('%M');\n }\n if (containsTimeUnit(timeUnit, TimeUnit.SECONDS)) {\n timeComponents.push('%S');\n }\n if (containsTimeUnit(timeUnit, TimeUnit.MILLISECONDS)) {\n timeComponents.push('%L');\n }\n var dateTimeComponents = [];\n if (dateComponents.length > 0) {\n dateTimeComponents.push(dateComponents.join(' '));\n }\n if (timeComponents.length > 0) {\n dateTimeComponents.push(timeComponents.join(':'));\n }\n if (dateTimeComponents.length > 0) {\n if (expression) {\n // Add space between quarter and main time format\n expression += \" + ' ' + \";\n }\n if (isUTCScale) {\n expression += \"utcFormat(\" + field + \", '\" + dateTimeComponents.join(' ') + \"')\";\n }\n else {\n expression += \"timeFormat(\" + field + \", '\" + dateTimeComponents.join(' ') + \"')\";\n }\n }\n // If expression is still an empty string, return undefined instead.\n return expression || undefined;\n}\nexports.formatExpression = formatExpression;\nfunction isDiscreteByDefault(timeUnit) {\n switch (timeUnit) {\n // These time unit use discrete scale by default\n case 'hours':\n case 'day':\n case 'month':\n case 'quarter':\n return true;\n }\n return false;\n}\nexports.isDiscreteByDefault = isDiscreteByDefault;\nfunction isUTCTimeUnit(timeUnit) {\n return timeUnit.substr(0, 3) === 'utc';\n}\n//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGltZXVuaXQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvdGltZXVuaXQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFDQSx1Q0FBc0Q7QUFDdEQsMkJBQTZCO0FBQzdCLCtCQUErQztBQUcvQyxJQUFpQixRQUFRLENBaUR4QjtBQWpERCxXQUFpQixRQUFRO0lBQ1YsYUFBSSxHQUFXLE1BQU0sQ0FBQztJQUN0QixjQUFLLEdBQVksT0FBTyxDQUFDO0lBQ3pCLFlBQUcsR0FBVSxLQUFLLENBQUM7SUFDbkIsYUFBSSxHQUFXLE1BQU0sQ0FBQztJQUN0QixjQUFLLEdBQVksT0FBTyxDQUFDO0lBQ3pCLGdCQUFPLEdBQWMsU0FBUyxDQUFDO0lBQy9CLGdCQUFPLEdBQWMsU0FBUyxDQUFDO0lBQy9CLHFCQUFZLEdBQW1CLGNBQWMsQ0FBQztJQUM5QyxrQkFBUyxHQUFnQixXQUFXLENBQUM7SUFDckMsc0JBQWEsR0FBb0IsZUFBZSxDQUFDO0lBQ2pELDJCQUFrQixHQUF5QixvQkFBb0IsQ0FBQztJQUNoRSxrQ0FBeUIsR0FBZ0MsMkJBQTJCLENBQUM7SUFDckYseUNBQWdDLEdBQXVDLGtDQUFrQyxDQUFDO0lBRXZILHFGQUFxRjtJQUN4RSxrQkFBUyxHQUFnQixXQUFXLENBQUM7SUFDckMscUJBQVksR0FBbUIsY0FBYyxDQUFDO0lBQzlDLDRCQUFtQixHQUEwQixxQkFBcUIsQ0FBQztJQUNuRSx1QkFBYyxHQUFxQixnQkFBZ0IsQ0FBQztJQUNwRCw0QkFBbUIsR0FBMEIscUJBQXFCLENBQUM7SUFDbkUsZ0JBQU8sR0FBYyxTQUFTLENBQUM7SUFDL0Isb0JBQVcsR0FBa0IsYUFBYSxDQUFDO0lBQzNDLHFCQUFZLEdBQW1CLGNBQWMsQ0FBQztJQUM5Qyx5QkFBZ0IsR0FBdUIsa0JBQWtCLENBQUM7SUFDMUQsZ0JBQU8sR0FBYyxTQUFTLENBQUM7SUFDL0IsaUJBQVEsR0FBZSxVQUFVLENBQUM7SUFDbEMsZUFBTSxHQUFhLFFBQVEs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", + "\"use strict\";\n/** Constants and utilities for data type */\n/** Data type based on level of measurement */\nObject.defineProperty(exports, \"__esModule\", { value: true });\nvar Type;\n(function (Type) {\n Type.QUANTITATIVE = 'quantitative';\n Type.ORDINAL = 'ordinal';\n Type.TEMPORAL = 'temporal';\n Type.NOMINAL = 'nominal';\n})(Type = exports.Type || (exports.Type = {}));\nexports.QUANTITATIVE = Type.QUANTITATIVE;\nexports.ORDINAL = Type.ORDINAL;\nexports.TEMPORAL = Type.TEMPORAL;\nexports.NOMINAL = Type.NOMINAL;\n/**\n * Get full, lowercase type name for a given type.\n * @param type\n * @return Full type name.\n */\nfunction getFullName(type) {\n if (type) {\n type = type.toLowerCase();\n switch (type) {\n case 'q':\n case exports.QUANTITATIVE:\n return 'quantitative';\n case 't':\n case exports.TEMPORAL:\n return 'temporal';\n case 'o':\n case exports.ORDINAL:\n return 'ordinal';\n case 'n':\n case exports.NOMINAL:\n return 'nominal';\n }\n }\n // If we get invalid input, return undefined type.\n return undefined;\n}\nexports.getFullName = getFullName;\n//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHlwZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy90eXBlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQSw0Q0FBNEM7QUFDNUMsOENBQThDOztBQUU5QyxJQUFpQixJQUFJLENBS3BCO0FBTEQsV0FBaUIsSUFBSTtJQUNOLGlCQUFZLEdBQW1CLGNBQWMsQ0FBQztJQUM5QyxZQUFPLEdBQWMsU0FBUyxDQUFDO0lBQy9CLGFBQVEsR0FBZSxVQUFVLENBQUM7SUFDbEMsWUFBTyxHQUFjLFNBQVMsQ0FBQztBQUM5QyxDQUFDLEVBTGdCLElBQUksR0FBSixZQUFJLEtBQUosWUFBSSxRQUtwQjtBQUdZLFFBQUEsWUFBWSxHQUFHLElBQUksQ0FBQyxZQUFZLENBQUM7QUFDakMsUUFBQSxPQUFPLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQztBQUN2QixRQUFBLFFBQVEsR0FBRyxJQUFJLENBQUMsUUFBUSxDQUFDO0FBQ3pCLFFBQUEsT0FBTyxHQUFHLElBQUksQ0FBQyxPQUFPLENBQUM7QUFFcEM7Ozs7R0FJRztBQUNILHFCQUE0QixJQUFpQjtJQUMzQyxFQUFFLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDO1FBQ1QsSUFBSSxHQUFHLElBQUksQ0FBQyxXQUFXLEVBQUUsQ0FBQztRQUMxQixNQUFNLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDO1lBQ2IsS0FBSyxHQUFHLENBQUM7WUFDVCxLQUFLLG9CQUFZO2dCQUNmLE1BQU0sQ0FBQyxjQUFjLENBQUM7WUFDeEIsS0FBSyxHQUFHLENBQUM7WUFDVCxLQUFLLGdCQUFRO2dCQUNYLE1BQU0sQ0FBQyxVQUFVLENBQUM7WUFDcEIsS0FBSyxHQUFHLENBQUM7WUFDVCxLQUFLLGVBQU87Z0JBQ1YsTUFBTSxDQUFDLFNBQVMsQ0FBQztZQUNuQixLQUFLLEdBQUcsQ0FBQztZQUNULEtBQUssZUFBTztnQkFDVixNQUFNLENBQUMsU0FBUyxDQUFDO1FBQ3JCLENBQUM7SUFDSCxDQUFDO0lBQ0Qsa0RBQWtEO0lBQ2xELE1BQU0sQ0FBQyxTQUFTLENBQUM7QUFDbkIsQ0FBQztBQXBCRCxrQ0FvQkMifQ==", + "\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nvar stringify = require(\"json-stable-stringify\");\nvar vega_util_1 = require(\"vega-util\");\nvar logical_1 = require(\"./logical\");\nvar vega_util_2 = require(\"vega-util\");\nexports.extend = vega_util_2.extend;\nexports.isArray = vega_util_2.isArray;\nexports.isObject = vega_util_2.isObject;\nexports.isNumber = vega_util_2.isNumber;\nexports.isString = vega_util_2.isString;\nexports.truncate = vega_util_2.truncate;\nexports.toSet = vega_util_2.toSet;\nexports.stringValue = vega_util_2.stringValue;\n/**\n * Creates an object composed of the picked object properties.\n *\n * Example: (from lodash)\n *\n * var object = {'a': 1, 'b': '2', 'c': 3};\n * pick(object, ['a', 'c']);\n * // → {'a': 1, 'c': 3}\n *\n */\nfunction pick(obj, props) {\n var copy = {};\n props.forEach(function (prop) {\n if (obj.hasOwnProperty(prop)) {\n copy[prop] = obj[prop];\n }\n });\n return copy;\n}\nexports.pick = pick;\n/**\n * The opposite of _.pick; this method creates an object composed of the own\n * and inherited enumerable string keyed properties of object that are not omitted.\n */\nfunction omit(obj, props) {\n var copy = duplicate(obj);\n props.forEach(function (prop) {\n delete copy[prop];\n });\n return copy;\n}\nexports.omit = omit;\nfunction hash(a) {\n if (vega_util_1.isString(a) || vega_util_1.isNumber(a) || isBoolean(a)) {\n return String(a);\n }\n return stringify(a);\n}\nexports.hash = hash;\nfunction contains(array, item) {\n return array.indexOf(item) > -1;\n}\nexports.contains = contains;\n/** Returns the array without the elements in item */\nfunction without(array, excludedItems) {\n return array.filter(function (item) { return !contains(excludedItems, item); });\n}\nexports.without = without;\nfunction union(array, other) {\n return array.concat(without(other, array));\n}\nexports.union = union;\n/**\n * Returns true if any item returns true.\n */\nfunction some(arr, f) {\n var i = 0;\n for (var k = 0; k < arr.length; k++) {\n if (f(arr[k], k, i++)) {\n return true;\n }\n }\n return false;\n}\nexports.some = some;\n/**\n * Returns true if all items return true.\n */\nfunction every(arr, f) {\n var i = 0;\n for (var k = 0; k < arr.length; k++) {\n if (!f(arr[k], k, i++)) {\n return false;\n }\n }\n return true;\n}\nexports.every = every;\nfunction flatten(arrays) {\n return [].concat.apply([], arrays);\n}\nexports.flatten = flatten;\n/**\n * recursively merges src into dest\n */\nfunction mergeDeep(dest) {\n var src = [];\n for (var _i = 1; _i < arguments.length; _i++) {\n src[_i - 1] = arguments[_i];\n }\n for (var _a = 0, src_1 = src; _a < src_1.length; _a++) {\n var s = src_1[_a];\n dest = deepMerge_(dest, s);\n }\n return dest;\n}\nexports.mergeDeep = mergeDeep;\n// recursively merges src into dest\nfunction deepMerge_(dest, src) {\n if (typeof src !== 'object' || src === null) {\n return dest;\n }\n for (var p in src) {\n if (!src.hasOwnProperty(p)) {\n continue;\n }\n if (src[p] === undefined) {\n continue;\n }\n if (typeof src[p] !== 'object' || vega_util_1.isArray(src[p]) || src[p] === null) {\n dest[p] = src[p];\n }\n else if (typeof dest[p] !== 'object' || dest[p] === null) {\n dest[p] = mergeDeep(vega_util_1.isArray(src[p].constructor) ? [] : {}, src[p]);\n }\n else {\n mergeDeep(dest[p], src[p]);\n }\n }\n return dest;\n}\nfunction unique(values, f) {\n var results = [];\n var u = {};\n var v;\n for (var _i = 0, values_1 = values; _i < values_1.length; _i++) {\n var val = values_1[_i];\n v = f(val);\n if (v in u) {\n continue;\n }\n u[v] = 1;\n results.push(val);\n }\n return results;\n}\nexports.unique = unique;\n/**\n * Returns true if the two dictionaries disagree. Applies only to defined values.\n */\nfunction differ(dict, other) {\n for (var key in dict) {\n if (dict.hasOwnProperty(key)) {\n if (other[key] && dict[key] && other[key] !== dict[key]) {\n return true;\n }\n }\n }\n return false;\n}\nexports.differ = differ;\nfunction hasIntersection(a, b) {\n for (var key in a) {\n if (key in b) {\n return true;\n }\n }\n return false;\n}\nexports.hasIntersection = hasIntersection;\nfunction differArray(array, other) {\n if (array.length !== other.length) {\n return true;\n }\n array.sort();\n other.sort();\n for (var i = 0; i < array.length; i++) {\n if (other[i] !== array[i]) {\n return true;\n }\n }\n return false;\n}\nexports.differArray = differArray;\nexports.keys = Object.keys;\nfunction vals(x) {\n var _vals = [];\n for (var k in x) {\n if (x.hasOwnProperty(k)) {\n _vals.push(x[k]);\n }\n }\n return _vals;\n}\nexports.vals = vals;\nfunction duplicate(obj) {\n return JSON.parse(JSON.stringify(obj));\n}\nexports.duplicate = duplicate;\nfunction isBoolean(b) {\n return b === true || b === false;\n}\nexports.isBoolean = isBoolean;\n/**\n * Convert a string into a valid variable name\n */\nfunction varName(s) {\n // Replace non-alphanumeric characters (anything besides a-zA-Z0-9_) with _\n var alphanumericS = s.replace(/\\W/g, '_');\n // Add _ if the string has leading numbers.\n return (s.match(/^\\d+/) ? '_' : '') + alphanumericS;\n}\nexports.varName = varName;\nfunction logicalExpr(op, cb) {\n if (logical_1.isLogicalNot(op)) {\n return '!(' + logicalExpr(op.not, cb) + ')';\n }\n else if (logical_1.isLogicalAnd(op)) {\n return '(' + op.and.map(function (and) { return logicalExpr(and, cb); }).join(') && (') + ')';\n }\n else if (logical_1.isLogicalOr(op)) {\n return '(' + op.or.map(function (or) { return logicalExpr(or, cb); }).join(') || (') + ')';\n }\n else {\n return cb(op);\n }\n}\nexports.logicalExpr = logicalExpr;\n//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXRpbC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy91dGlsLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7O0FBQUEsaURBQW1EO0FBQ25ELHVDQUFnRTtBQUNoRSxxQ0FBa0Y7QUFHbEYsdUNBQXNHO0FBQTlGLDZCQUFBLE1BQU0sQ0FBQTtBQUFFLDhCQUFBLE9BQU8sQ0FBQTtBQUFFLCtCQUFBLFFBQVEsQ0FBQTtBQUFFLCtCQUFBLFFBQVEsQ0FBQTtBQUFFLCtCQUFBLFFBQVEsQ0FBQTtBQUFFLCtCQUFBLFFBQVEsQ0FBQTtBQUFFLDRCQUFBLEtBQUssQ0FBQTtBQUFFLGtDQUFBLFdBQVcsQ0FBQTtBQUVuRjs7Ozs7Ozs7O0dBU0c7QUFDSCxjQUFxQixHQUFXLEVBQUUsS0FBZTtJQUMvQyxJQUFNLElBQUksR0FBRyxFQUFFLENBQUM7SUFDaEIsS0FBSyxDQUFDLE9BQU8sQ0FBQyxVQUFDLElBQUk7UUFDakIsRUFBRSxDQUFDLENBQUMsR0FBRyxDQUFDLGNBQWMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUM7WUFDN0IsSUFBSSxDQUFDLElBQUksQ0FBQyxHQUFHLEdBQUcsQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUN6QixDQUFDO0lBQ0gsQ0FBQyxDQUFDLENBQUM7SUFDSCxNQUFNLENBQUMsSUFBSSxDQUFDO0FBQ2QsQ0FBQztBQVJELG9CQVFDO0FBRUQ7OztHQUdHO0FBQ0gsY0FBcUIsR0FBVyxFQUFFLEtBQWU7SUFDL0MsSUFBTSxJQUFJLEdBQUcsU0FBUyxDQUFDLEdBQUcsQ0FBQyxDQUFDO0lBQzVCLEtBQUssQ0FBQyxPQUFPLENBQUMsVUFBQyxJQUFJO1FBQ2pCLE9BQU8sSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQ3BCLENBQUMsQ0FBQyxDQUFDO0lBQ0gsTUFBTSxDQUFDLElBQUksQ0FBQztBQUNkLENBQUM7QUFORCxvQkFNQztBQUVELGNBQXFCLENBQU07SUFDekIsRUFBRSxDQUFDLENBQUMsb0JBQVEs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", + "(function (global, factory) {\n\ttypeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :\n\ttypeof define === 'function' && define.amd ? define(['exports'], factory) :\n\t(factory((global.vega = global.vega || {})));\n}(this, (function (exports) { 'use strict';\n\nvar accessor = function(fn, fields, name) {\n fn.fields = fields || [];\n fn.fname = name;\n return fn;\n};\n\nfunction accessorName(fn) {\n return fn == null ? null : fn.fname;\n}\n\nfunction accessorFields(fn) {\n return fn == null ? null : fn.fields;\n}\n\nvar error = function(message) {\n throw Error(message);\n};\n\nvar splitAccessPath = function(p) {\n var path = [],\n q = null,\n b = 0,\n n = p.length,\n s = '',\n i, j, c;\n\n p = p + '';\n\n function push() {\n path.push(s + p.substring(i, j));\n s = '';\n i = j + 1;\n }\n\n for (i=j=0; j i) {\n push();\n } else {\n i = j + 1;\n }\n } else if (c === '[') {\n if (j > i) push();\n b = i = j + 1;\n } else if (c === ']') {\n if (!b) error('Access path missing open bracket: ' + p);\n if (b > 0) push();\n b = 0;\n i = j + 1;\n }\n }\n\n if (b) error('Access path missing closing bracket: ' + p);\n if (q) error('Access path missing closing quote: ' + p);\n\n if (j > i) {\n j++;\n push();\n }\n\n return path;\n};\n\nvar isArray = Array.isArray;\n\nvar isObject = function(_) {\n return _ === Object(_);\n};\n\nvar isString = function(_) {\n return typeof _ === 'string';\n};\n\nfunction $(x) {\n return isArray(x) ? '[' + x.map($) + ']'\n : isObject(x) || isString(x) ?\n // Output valid JSON and JS source strings.\n // See http://timelessrepo.com/json-isnt-a-javascript-subset\n JSON.stringify(x).replace('\\u2028','\\\\u2028').replace('\\u2029', '\\\\u2029')\n : x;\n}\n\nvar field = function(field, name) {\n var path = splitAccessPath(field),\n code = 'return _[' + path.map($).join('][') + '];';\n\n return accessor(\n Function('_', code),\n [(field = path.length===1 ? path[0] : field)],\n name || field\n );\n};\n\nvar empty = [];\n\nvar id = field('id');\n\nvar identity = accessor(function(_) { return _; }, empty, 'identity');\n\nvar zero = accessor(function() { return 0; }, empty, 'zero');\n\nvar one = accessor(function() { return 1; }, empty, 'one');\n\nvar truthy = accessor(function() { return true; }, empty, 'true');\n\nvar falsy = accessor(function() { return false; }, empty, 'false');\n\nfunction log(method, level, input) {\n var args = [level].concat([].slice.call(input));\n console[method].apply(console, args); // eslint-disable-line no-console\n}\n\nvar None = 0;\nvar Error$1 = 1;\nvar Warn = 2;\nvar Info = 3;\nvar Debug = 4;\n\nvar logger = function(_) {\n var level = _ || None;\n return {\n level: function(_) {\n if (arguments.length) {\n level = +_;\n return this;\n } else {\n return level;\n }\n },\n error: function() {\n if (level >= Error$1) log('error', 'ERROR', arguments);\n return this;\n },\n warn: function() {\n if (level >= Warn) log('warn', 'WARN', arguments);\n return this;\n },\n info: function() {\n if (level >= Info) log('log', 'INFO', arguments);\n return this;\n },\n debug: function() {\n if (level >= Debug) log('log', 'DEBUG', arguments);\n return this;\n }\n }\n};\n\nvar array = function(_) {\n return _ != null ? (isArray(_) ? _ : [_]) : [];\n};\n\nvar compare = function(fields, orders) {\n var idx = [],\n cmp = (fields = array(fields)).map(function(f, i) {\n if (f == null) {\n return null;\n } else {\n idx.push(i);\n return splitAccessPath(f).map($).join('][');\n }\n }),\n n = idx.length - 1,\n ord = array(orders),\n code = 'var u,v;return ',\n i, j, f, u, v, d, lt, gt;\n\n if (n < 0) return null;\n\n for (j=0; j<=n; ++j) {\n i = idx[j];\n f = cmp[i];\n u = '(u=a['+f+'])';\n v = '(v=b['+f+'])';\n d = '((v=v instanceof Date?+v:v),(u=u instanceof Date?+u:u))';\n if (ord[i] !== 'descending') {\n gt = 1;\n lt = -1;\n } else {\n gt = -1;\n lt = 1;\n }\n code += '(' + u+'<'+v+'||u==null)&&v!=null?' + lt\n + ':(u>v||v==null)&&u!=null?' + gt\n + ':'+d+'!==u&&v===v?' + lt\n + ':v!==v&&u===u?' + gt\n + (i < n ? ':' : ':0');\n }\n\n return accessor(\n Function('a', 'b', code + ';'),\n fields.filter(function(_) { return _ != null; })\n );\n};\n\nvar isFunction = function(_) {\n return typeof _ === 'function';\n};\n\nvar constant = function(_) {\n return isFunction(_) ? _ : function() { return _; };\n};\n\nvar debounce = function(delay, handler) {\n var tid, evt;\n\n function callback() {\n handler(evt);\n tid = evt = null;\n }\n\n return function(e) {\n evt = e;\n if (tid) clearTimeout(tid);\n tid = setTimeout(callback, delay);\n };\n};\n\nvar extend = function(_) {\n for (var x, k, i=1, len=arguments.length; i= b) {\n a = c = b;\n break;\n }\n }\n u = v = i;\n while (++i < n) {\n b = array[i];\n if (b != null) {\n if (a > b) {\n a = b;\n u = i;\n }\n if (c < b) {\n c = b;\n v = i;\n }\n }\n }\n } else {\n while (++i < n) {\n b = f(array[i], i, array);\n if (b != null && b >= b) {\n a = c = b;\n break;\n }\n }\n u = v = i;\n while (++i < n) {\n b = f(array[i], i, array);\n if (b != null) {\n if (a > b) {\n a = b;\n u = i;\n }\n if (c < b) {\n c = b;\n v = i;\n }\n }\n }\n }\n\n return [u, v];\n};\n\nvar NULL = {};\n\nvar fastmap = function(input) {\n var obj = {},\n map,\n test;\n\n function has(key) {\n return obj.hasOwnProperty(key) && obj[key] !== NULL;\n }\n\n map = {\n size: 0,\n empty: 0,\n object: obj,\n has: has,\n get: function(key) {\n return has(key) ? obj[key] : undefined;\n },\n set: function(key, value) {\n if (!has(key)) {\n ++map.size;\n if (obj[key] === NULL) --map.empty;\n }\n obj[key] = value;\n return this;\n },\n delete: function(key) {\n if (has(key)) {\n --map.size;\n ++map.empty;\n obj[key] = NULL;\n }\n return this;\n },\n clear: function() {\n map.size = map.empty = 0;\n map.object = obj = {};\n },\n test: function(_) {\n if (arguments.length) {\n test = _;\n return map;\n } else {\n return test;\n }\n },\n clean: function() {\n var next = {},\n size = 0,\n key, value;\n for (key in obj) {\n value = obj[key];\n if (value !== NULL && (!test || !test(value))) {\n next[key] = value;\n ++size;\n }\n }\n map.size = size;\n map.empty = 0;\n map.object = (obj = next);\n }\n };\n\n if (input) Object.keys(input).forEach(function(key) {\n map.set(key, input[key]);\n });\n\n return map;\n};\n\nvar inherits = function(child, parent) {\n var proto = (child.prototype = Object.create(parent.prototype));\n proto.constructor = child;\n return proto;\n};\n\nvar isBoolean = function(_) {\n return typeof _ === 'boolean';\n};\n\nvar isDate = function(_) {\n return Object.prototype.toString.call(_) === '[object Date]';\n};\n\nvar isNumber = function(_) {\n return typeof _ === 'number';\n};\n\nvar isRegExp = function(_) {\n return Object.prototype.toString.call(_) === '[object RegExp]';\n};\n\nvar key = function(fields) {\n fields = fields ? array(fields) : fields;\n var fn = !(fields && fields.length)\n ? function() { return ''; }\n : Function('_', 'return \\'\\'+' +\n fields.map(function(f) {\n return '_[' + splitAccessPath(f).map($).join('][') + ']';\n }).join('+\\'|\\'+') + ';');\n return accessor(fn, fields, 'key');\n};\n\nvar merge = function(compare, array0, array1, output) {\n var n0 = array0.length,\n n1 = array1.length;\n\n if (!n1) return array0;\n if (!n0) return array1;\n\n var merged = output || new array0.constructor(n0 + n1),\n i0 = 0, i1 = 0, i = 0;\n\n for (; i0 0\n ? array1[i1++]\n : array0[i0++];\n }\n\n for (; i0= 0) s += str;\n return s;\n};\n\nvar pad = function(str, length, padchar, align) {\n var c = padchar || ' ',\n s = str + '',\n n = length - s.length;\n\n return n <= 0 ? s\n : align === 'left' ? repeat(c, n) + s\n : align === 'center' ? repeat(c, ~~(n/2)) + s + repeat(c, Math.ceil(n/2))\n : s + repeat(c, n);\n};\n\nvar peek = function(array) {\n return array[array.length - 1];\n};\n\nvar toBoolean = function(_) {\n return _ == null || _ === '' ? null : !_ || _ === 'false' || _ === '0' ? false : !!_;\n};\n\nfunction defaultParser(_) {\n return isNumber(_) ? _ : isDate(_) ? _ : Date.parse(_);\n}\n\nvar toDate = function(_, parser) {\n parser = parser || defaultParser;\n return _ == null || _ === '' ? null : parser(_);\n};\n\nvar toNumber = function(_) {\n return _ == null || _ === '' ? null : +_;\n};\n\nvar toString = function(_) {\n return _ == null || _ === '' ? null : _ + '';\n};\n\nvar toSet = function(_) {\n for (var s={}, i=0, n=_.length; i=r.minCardinalityForBin}return!0}},{name:"binAppliedForQuantitative",description:"bin should be applied to quantitative field only.",properties:[s.Property.TYPE,s.Property.BIN],allowWildcardForProperties:!1,strict:!0,satisfy:function(e,t,n,r){return!e.bin||e.type===u.Type.QUANTITATIVE}},{name:"channelFieldCompatible",description:"encoding channel's range type be compatible with channel type.",properties:[s.Property.CHANNEL,s.Property.TYPE,s.Property.BIN,s.Property.TIMEUNIT],allowWildcardForProperties:!1,strict:!0,satisfy:function(e,t,n,i){var a=r({field:"f"},y.toFieldDef(e,["bin","timeUnit","type"]));return o.channelCompatibility(a,e.channel).compatible}},{name:"hasFn",description:"A field with as hasFn flag should have one of aggregate, timeUnit, or bin.",properties:[s.Property.AGGREGATE,s.Property.BIN,s.Property.TIMEUNIT],allowWildcardForProperties:!0,strict:!0,satisfy:function(e,t,n,r){return!e.hasFn||(!!e.aggregate||!!e.bin||!!e.timeUnit)}},{name:"omitScaleZeroWithBinnedField",description:"Do not use scale zero with binned field",properties:[s.Property.SCALE,s.getEncodingNestedProp("scale","zero"),s.Property.BIN],allowWildcardForProperties:!1,strict:!0,satisfy:function(e,t,n,r){return!e.bin||!e.scale||e.scale.zero!==!0}},{name:"onlyOneTypeOfFunction",description:"Only of of aggregate, autoCount, timeUnit, or bin should be applied at the same time.",properties:[s.Property.AGGREGATE,s.Property.AUTOCOUNT,s.Property.TIMEUNIT,s.Property.BIN],allowWildcardForProperties:!0,strict:!0,satisfy:function(e,t,n,r){if(y.isFieldQuery(e)){var i=(!d.isWildcard(e.aggregate)&&e.aggregate?1:0)+(!d.isWildcard(e.bin)&&e.bin?1:0)+(!d.isWildcard(e.timeUnit)&&e.timeUnit?1:0);return i<=1}return!0}},{name:"timeUnitAppliedForTemporal",description:"Time unit should be applied to temporal field only.",properties:[s.Property.TYPE,s.Property.TIMEUNIT],allowWildcardForProperties:!1,strict:!0,satisfy:function(e,t,n,r){return!e.timeUnit||e.type===u.Type.TEMPORAL}},{name:"timeUnitShouldHaveVariation",description:"A particular time unit should be applied only if they produce unique values.",properties:[s.Property.TIMEUNIT,s.Property.TYPE],allowWildcardForProperties:!1,strict:!1,satisfy:function(e,t,n,r){return!e.timeUnit||e.type!==u.Type.TEMPORAL||(!n.has("timeUnit")&&!r.constraintManuallySpecifiedValue||t.timeUnitHasVariation(e))}},{name:"scalePropertiesSupportedByScaleType",description:"Scale properties must be supported by correct scale type",properties:[].concat(s.SCALE_PROPS,[s.Property.SCALE,s.Property.TYPE]),allowWildcardForProperties:!0,strict:!0,satisfy:function(e,t,n,r){if(e.scale){var i=e.scale,o=y.scaleType(e);if(void 0===o||null===o)return!0;for(var u in i)if("type"!==u&&"name"!==u&&"enum"!==u){var c=u;if("point"===o){if(!a.scaleTypeSupportProperty("point",c)&&!a.scaleTypeSupportProperty("band",c))return!1}else if(!a.scaleTypeSupportProperty(o,c))return!1}}return!0}},{name:"scalePropertiesSupportedByChannel",description:"Not all scale properties are supported by all encoding channels",properties:[].concat(s.SCALE_PROPS,[s.Property.SCALE,s.Property.CHANNEL]),allowWildcardForProperties:!0,strict:!0,satisfy:function(e,t,n,r){if(e){var i=e.channel,o=e.scale;if(i&&!d.isWildcard(i)&&o){if("row"===i||"column"===i)return!1;for(var u in o)if(o.hasOwnProperty(u)&&"type"!==u&&"name"!==u&&"enum"!==u){var c=void 0===a.channelScalePropertyIncompatability(i,u);if(!c)return!1}}}return!0}},{name:"typeMatchesPrimitiveType",description:"Data type should be supported by field's primitive type.",properties:[s.Property.FIELD,s.Property.TYPE],allowWildcardForProperties:!1,strict:!0,satisfy:function(e,t,n,r){if("*"===e.field)return!0;var i=t.primitiveType(e.field),o=e.type;if(!n.has("field")&&!n.has("type")&&!r.constraintManuallySpecifiedValue)return!0;switch(i){case f.PrimitiveType.BOOLEAN:case f.PrimitiveType.STRING:return o!==u.Type.QUANTITATIVE&&o!==u.Type.TEMPORAL;case f.PrimitiveType.NUMBER:case f.PrimitiveType.INTEGER:return o!==u.Type.TEMPORAL;case f.PrimitiveType.DATETIME:return o===u.Type.TEMPORAL;case null:return!1}throw new Error("Not implemented")}},{name:"typeMatchesSchemaType",description:"Enumerated data type of a field should match the field's type in the schema.",properties:[s.Property.FIELD,s.Property.TYPE],allowWildcardForProperties:!1,strict:!1,satisfy:function(e,t,n,r){return!(n.has("field")||n.has("type")||r.constraintManuallySpecifiedValue)||("*"===e.field?e.type===u.Type.QUANTITATIVE:t.vlType(e.field)===e.type)}},{name:"maxCardinalityForCategoricalColor",description:"Categorical channel should not have too high cardinality",properties:[s.Property.CHANNEL,s.Property.FIELD],allowWildcardForProperties:!1,strict:!1,satisfy:function(e,t,n,r){return e.channel!==i.Channel.COLOR||e.type!==u.Type.NOMINAL&&e.type!==c.ExpandedType.KEY||t.cardinality(e)<=r.maxCardinalityForCategoricalColor}},{name:"maxCardinalityForFacet",description:"Row/column channel should not have too high cardinality",properties:[s.Property.CHANNEL,s.Property.FIELD,s.Property.BIN,s.Property.TIMEUNIT],allowWildcardForProperties:!1,strict:!1,satisfy:function(e,t,n,r){return e.channel!==i.Channel.ROW&&e.channel!==i.Channel.COLUMN||t.cardinality(e)<=r.maxCardinalityForFacet}},{name:"maxCardinalityForShape",description:"Shape channel should not have too high cardinality",properties:[s.Property.CHANNEL,s.Property.FIELD,s.Property.BIN,s.Property.TIMEUNIT],allowWildcardForProperties:!1,strict:!1,satisfy:function(e,t,n,r){return e.channel!==i.Channel.SHAPE||t.cardinality(e)<=r.maxCardinalityForShape}},{name:"dataTypeAndFunctionMatchScaleType",description:"Scale type must match data type",properties:[s.Property.TYPE,s.Property.SCALE,s.getEncodingNestedProp("scale","type"),s.Property.TIMEUNIT,s.Property.BIN],allowWildcardForProperties:!1,strict:!0,satisfy:function(e,t,n,r){if(e.scale){var i=e.type,o=y.scaleType(e);if(c.isDiscrete(i))return void 0===o||a.hasDiscreteDomain(o);if(i===u.Type.TEMPORAL)return e.timeUnit?p.contains([a.ScaleType.TIME,a.ScaleType.UTC,void 0],o)||a.hasDiscreteDomain(o):p.contains([a.ScaleType.TIME,a.ScaleType.UTC,void 0],o);if(i===u.Type.QUANTITATIVE)return e.bin?p.contains([a.ScaleType.LINEAR,void 0],o):p.contains([a.ScaleType.LOG,a.ScaleType.POW,a.ScaleType.SQRT,a.ScaleType.QUANTILE,a.ScaleType.QUANTIZE,a.ScaleType.LINEAR,void 0],o)}return!0}}].map(function(e){return new g.EncodingConstraintModel(e)}),n.FIELD_CONSTRAINT_INDEX=n.FIELD_CONSTRAINTS.reduce(function(e,t){return e[t.name()]=t,e},{}),n.FIELD_CONSTRAINTS_BY_PROPERTY=n.FIELD_CONSTRAINTS.reduce(function(e,t){for(var n=0,r=t.properties();n1&&(o||n.constraintManuallySpecifiedValue)))return!1}}return!0}},{name:"omitNonPositionalOrFacetOverPositionalChannels",description:"Do not use non-positional channels unless all positional channels are used",properties:[p.Property.CHANNEL],allowWildcardForProperties:!1,strict:!1,satisfy:function(e,t,n){for(var r=e.specQuery.encodings,i=!1,o=!1,u=!1,c=!1,s=0;s0},e.prototype.stack=function(){return l.stack(this._spec)},e.prototype.getEncodings=function(){return this._spec.encodings.filter(function(e){return!d.isDisabledAutoCountQuery(e)})},e.prototype.getEncodingQueryByChannel=function(e){for(var t=0,n=this._spec.encodings;t0?i[c-1].duplicate():new s.PropIndex),o.push(c>0?o[c-1].duplicate():new s.PropIndex);var f=t[c].groupBy;if(u.isArray(f)){var y=l.parseGroupBy(f,i[c],o[c]);a.push(y.replacer)}}return e.forEach(function(e){for(var o="",c=n,s=0;s"+e}).join(";")+"]"}return e.property}return e}).join(","):e}Object.defineProperty(n,"__esModule",{value:!0});var a=e("datalib/src/util"),u=e("./shorthand"),c=e("../property"),s=e("../propindex"),l=e("../util");n.REPLACE_BLANK_FIELDS={"*":""},n.REPLACE_XY_CHANNELS={x:"xy",y:"xy"},n.REPLACE_FACET_CHANNELS={row:"facet",column:"facet"},n.REPLACE_MARK_STYLE_CHANNELS={color:"style",opacity:"style",shape:"style",size:"style"},n.isExtendedGroupBy=r,n.parseGroupBy=i,n.toString=o,n.GROUP_BY_FIELD_TRANSFORM=[c.Property.FIELD,c.Property.TYPE,c.Property.AGGREGATE,c.Property.BIN,c.Property.TIMEUNIT,c.Property.STACK],n.GROUP_BY_ENCODING=n.GROUP_BY_FIELD_TRANSFORM.concat([{property:c.Property.CHANNEL,replace:{x:"xy",y:"xy",color:"style",size:"style",shape:"style",opacity:"style",row:"facet",column:"facet"}}])},{"../property":13,"../propindex":14,"../util":38,"./shorthand":20,"datalib/src/util":48}],18:[function(e,t,n){"use strict";Object.defineProperty(n,"__esModule",{value:!0}),n.encoding=e("./encoding");var r=e("./normalize");n.normalize=r.normalize,n.groupBy=e("./groupby"),n.shorthand=e("./shorthand"),n.spec=e("./spec"),n.transform=e("./transform")},{"./encoding":15,"./groupby":17,"./normalize":19,"./shorthand":20,"./spec":21,"./transform":22}],19:[function(e,t,n){"use strict";function r(e){if(e.groupBy){var t={groupBy:e.groupBy};e.orderBy&&(t.orderGroupBy=e.orderBy);var n={spec:i.duplicate(e.spec),nest:[t]};return e.chooseBy&&(n.chooseBy=e.chooseBy),e.config&&(n.config=e.config),n}return i.duplicate(e)}Object.defineProperty(n,"__esModule",{value:!0});var i=e("../util");n.normalize=r},{"../util":38}],20:[function(e,t,n){"use strict";function r(e){return e.map(function(e){return i(e)})}function i(e){return function(t){return void 0!==e[t]?e[t]:t}}function o(e,t){return N.isWildcard(e)?!N.isShortWildcard(e)&&e["enum"]?N.SHORT_WILDCARD+JSON.stringify(e["enum"]):N.SHORT_WILDCARD:t?t(e):e}function a(e,t){return t?t(e):e}function u(e,t,r){void 0===t&&(t=n.INCLUDE_ALL),void 0===r&&(r=n.REPLACE_NONE);var i=O.fromSpec(e);return c(i,t,r)}function c(e,t,r){void 0===t&&(t=n.INCLUDE_ALL),void 0===r&&(r=n.REPLACE_NONE);var i=[];if(t.get(S.Property.MARK)&&i.push(o(e.mark,r.get(S.Property.MARK))),e.transform&&e.transform.length>0&&i.push("transform:"+JSON.stringify(e.transform)),t.get(S.Property.STACK)){var a=O.stack(e);if(a){var u=t.duplicate().set("type",!1),c=l(a.fieldEncQ,u,r),d=l(a.groupByEncQ,u,r);i.push("stack={field:"+c+","+(d?"by:"+d+",":"")+"offset:"+a.offset+"}")}}if(e.encodings){var f=e.encodings.reduce(function(e,n){if(!T.isDisabledAutoCountQuery(n)){var i=s(n,t,r);i&&e.push(i)}return e},[]).sort().join("|");f&&i.push(f)}return i.join("|")}function s(e,t,r){void 0===t&&(t=n.INCLUDE_ALL),void 0===r&&(r=n.REPLACE_NONE);var i=[];if(t.get(S.Property.CHANNEL)&&i.push(o(e.channel,r.get(S.Property.CHANNEL))),T.isFieldQuery(e)){var a=l(e,t,r);a&&i.push(a)}else T.isValueQuery(e)&&i.push(e.value);return i.join(":")}function l(e,t,r){if(void 0===t&&(t=n.INCLUDE_ALL),void 0===r&&(r=n.REPLACE_NONE),t.get(S.Property.AGGREGATE)&&T.isDisabledAutoCountQuery(e))return"-";var i,a=d(e,t,r),u=f(e,t,r);if(T.isFieldQuery(e)){if(i=t.get("field")?o(e.field,r.get("field")):"...",t.get(S.Property.TYPE))if(N.isWildcard(e.type))i+=","+o(e.type,r.get(S.Property.TYPE));else{var c=((e.type||v.Type.QUANTITATIVE)+"").substr(0,1);i+=","+o(c,r.get(S.Property.TYPE))}i+=u.map(function(e){var t=e.value instanceof Array?"["+e.value+"]":e.value;return","+e.key+"="+t}).join("")}else T.isAutoCountQuery(e)&&(i="*,q");if(!i)return null;if(a){var s=E.isString(a)?a:N.SHORT_WILDCARD+(P.keys(a).length>0?JSON.stringify(a):"");return s+"("+i+")"}return i}function d(e,t,n){if(t.get(S.Property.AGGREGATE)&&e.aggregate&&!N.isWildcard(e.aggregate))return a(e.aggregate,n.get(S.Property.AGGREGATE));if(t.get(S.Property.AGGREGATE)&&T.isEnabledAutoCountQuery(e))return a("count",n.get(S.Property.AGGREGATE));if(t.get(S.Property.TIMEUNIT)&&e.timeUnit&&!N.isWildcard(e.timeUnit))return a(e.timeUnit,n.get(S.Property.TIMEUNIT));if(t.get(S.Property.BIN)&&e.bin&&!N.isWildcard(e.bin))return"bin";for(var r=null,i=0,o=[S.Property.AGGREGATE,S.Property.AUTOCOUNT,S.Property.TIMEUNIT,S.Property.BIN];i0){var h=y.sort(function(e,t){return e.key.localeCompare(t.key)}).reduce(function(e,t){return e[t.key]=t.value,e},{});i.push({key:f+"",value:JSON.stringify(h)})}}}}return i}function p(e){for(var t=e.split("|"),n={mark:t[0],encodings:[]},r=1;re.score)return n}return e},{type:"Dimension",feature:"No Dimension",score:-5}),[]},t}(i.Scorer);n.DimensionScorer=a},{"../../query/encoding":15,"./base":25}],27:[function(e,t,n){"use strict";var r=this&&this.__extends||function(){var e=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n])};return function(t,n){function r(){this.constructor=t}e(t,n),t.prototype=null===n?Object.create(n):(r.prototype=n.prototype,new r)}}(),i=this&&this.__assign||Object.assign||function(e){for(var t,n=1,r=arguments.length;ne.score?o:e},null);c.push(t)}),c},t}(u.Scorer);n.TypeChannelScorer=c},{"../../query/shorthand":20,"../../util":38,"./base":25,"./type":31}],33:[function(e,t,n){"use strict";function r(e,t,n){var r=e.wildcardIndex.encodingIndicesByProperty.get("field");if(!r)return{score:0,features:[]};for(var o=e.specQuery.encodings,a=t.fieldSchemas.length,u=[],c=0,s=1,l=r.length-1;l>=0;l--){var d=r[l],f=o[d],p=void 0;if(i.isFieldQuery(f)){p=f.field;var y=e.wildcardIndex.encodings[d].get("field"),g=t.fieldSchema(p).index,h=-g*s;c+=h,u.push({score:h,type:"fieldOrder",feature:"field "+y.name+" is "+p+" (#"+g+" in the schema)"}),s*=a}}return{score:c,features:u}}Object.defineProperty(n,"__esModule",{value:!0});var i=e("../query/encoding");n.name="fieldOrder",n.score=r},{"../query/encoding":15}],34:[function(e,t,n){"use strict";function r(e){for(var t in e)n.hasOwnProperty(t)||(n[t]=e[t])}function i(e,t){p[e]=t}function o(e){return p[e]}function a(e,t,n,r){return t.nest&&r!==t.nest.length?(e.items.forEach(function(e){a(e,t,n,r+1)}),t.nest[r].orderGroupBy&&e.items.sort(c(t.nest[r].orderGroupBy,n,t.config))):(t.orderBy||t.chooseBy)&&(e.items.sort(u(t.orderBy||t.chooseBy,n,t.config)),t.chooseBy&&e.items.length>0&&e.items.splice(1)),e}function u(e,t,n){return function(r,i){return e instanceof Array?s(e,r,i,t,n):s([e],r,i,t,n)}}function c(e,t,n){return function(r,i){var o=d.getTopSpecQueryItem(r),a=d.getTopSpecQueryItem(i);return e instanceof Array?s(e,o,a,t,n):s([e],o,a,t,n)}}function s(e,t,n,r,i){for(var o=0,a=e;ot.max.getTime()&&(t.max=new Date(y))}}else i=s.Type.NOMINAL;i===s.Type.NOMINAL&&l/t.count>n.minPercentUniqueForKey&&t.count>n.minCardinalityForKey&&(i=h.ExpandedType.KEY);var g={name:o,originalIndex:r,vlType:i,type:c,stats:t,timeStats:{},binStats:{}},m=u[g.name];return g=v.extend(g,m)}),d=0,y=l;dE[t.vlType]?1:e.name.localeCompare(t.name)}),e.fields.forEach(function(e,t){return e.index=t}),this._fieldSchemaIndex=e.fields.reduce(function(e,t){return e[t.name]=t,e},{})}return e.prototype.fieldNames=function(){return this._tableSchema.fields.map(function(e){return e.name})},Object.defineProperty(e.prototype,"fieldSchemas",{get:function(){return this._tableSchema.fields},enumerable:!0,configurable:!0}),e.prototype.fieldSchema=function(e){return this._fieldSchemaIndex[e]},e.prototype.tableSchema=function(){var e=v.duplicate(this._tableSchema);return e.fields.sort(function(e,t){return e.originalIndex-t.originalIndex}),e},e.prototype.primitiveType=function(e){return this._fieldSchemaIndex[e]?this._fieldSchemaIndex[e].type:null},e.prototype.vlType=function(e){return this._fieldSchemaIndex[e]?this._fieldSchemaIndex[e].vlType:null},e.prototype.cardinality=function(e,t,n){void 0===t&&(t=!0),void 0===n&&(n=!1);var r=this._fieldSchemaIndex[e.field];if(e.aggregate||g.isAutoCountQuery(e)&&e.autoCount)return 1;if(e.bin){var a=void 0;a="boolean"==typeof e.bin?{maxbins:l.autoMaxBins(e.channel)}:e.bin;var c=a.maxbins;return r.binStats[c]||(r.binStats[c]=i(c,r.stats)),r.binStats[c].distinct}if(e.timeUnit){if(t)switch(e.timeUnit){case d.TimeUnit.SECONDS:return 60;case d.TimeUnit.MINUTES:return 60;case d.TimeUnit.HOURS:return 24;case d.TimeUnit.DAY:return 7;case d.TimeUnit.DATE:return 31;case d.TimeUnit.MONTH:return 12;case d.TimeUnit.QUARTER:return 4;case d.TimeUnit.MILLISECONDS:return 1e3}var s=e.timeUnit,f=r.timeStats;return f[s]||(f[s]=o(e.timeUnit,r.stats)),n?f[s].distinct-u(f[s].unique,["Invalid Date",null]):f[s].distinct}return r?n?r.stats.distinct-u(r.stats.unique,[NaN,null]):r.stats.distinct:null},e.prototype.timeUnitHasVariation=function(e){if(e.timeUnit){if(e.timeUnit===d.TimeUnit.DAY){var t=v.extend({},e,{timeUnit:d.TimeUnit.DATE});if(this.cardinality(t,!1,!0)<=1)return!1}for(var n=e.timeUnit,r=0,i=d.SINGLE_TIMEUNITS;rr.smallRangeStepForHighCardinalityOrFacet.maxCardinality)){void 0===i.scale&&(i.scale={});var o=l.scaleType(i);i.scale&&(void 0===o||c.hasDiscreteDomain(o))&&(i.scale.rangeStep||(i.scale.rangeStep=12))}var a=n[u.Channel.X];if(l.isFieldQuery(a)&&(n[u.Channel.COLUMN]||t.cardinality(a)>r.smallRangeStepForHighCardinalityOrFacet.maxCardinality)){void 0===a.scale&&(a.scale={});var s=l.scaleType(a);a.scale&&(void 0===s||c.hasDiscreteDomain(s))&&(a.scale.rangeStep||(a.scale.rangeStep=12))}return e}function o(e,t,n,r){n[u.Channel.COLOR]=e.getEncodingQueryByChannel(u.Channel.COLOR);var i=n[u.Channel.COLOR];return l.isFieldQuery(i)&&void 0!==i&&(i.type===s.Type.NOMINAL||i.type===d.ExpandedType.KEY)&&t.cardinality(i)>r.nominalColorScaleForHighCardinality.maxCardinality&&(void 0===i.scale&&(i.scale={}),i.scale&&(i.scale.range||(i.scale.range=r.nominalColorScaleForHighCardinality.palette))),e}function a(e,t,n,r){if([u.Channel.COLUMN,u.Channel.X,u.Channel.Y].forEach(function(t){n[t]=e.getEncodingQueryByChannel(t)}),void 0===n[u.Channel.COLUMN]){var i=n[u.Channel.X],o=n[u.Channel.Y];l.isFieldQuery(i)&&l.isFieldQuery(o)&&void 0!==o&&o.field&&c.hasDiscreteDomain(l.scaleType(o))&&void 0!==i&&t.cardinality(o)>r.xAxisOnTopForHighYCardinalityWithoutColumn.maxCardinality&&(void 0===i.axis&&(i.axis={}),i.axis&&!i.axis.orient&&(i.axis.orient="top"))}return e}Object.defineProperty(n,"__esModule",{value:!0});var u=e("vega-lite/build/src/channel"),c=e("vega-lite/build/src/scale"),s=e("vega-lite/build/src/type"),l=e("./query/encoding"),d=e("./query/expandedtype");n.stylize=r,n.smallRangeStepForHighCardinalityOrFacet=i,n.nominalColorScaleForHighCardinality=o,n.xAxisOnTopForHighYCardinalityWithoutColumn=a},{"./query/encoding":15,"./query/expandedtype":16,"vega-lite/build/src/channel":57,"vega-lite/build/src/scale":65,"vega-lite/build/src/type":67}],38:[function(e,t,n){"use strict";function r(e,t){return e.indexOf(t)!==-1}function i(e,t){for(var n=0;n0))return o;for(n(t,1),e(t),t=0;)for(;n(e,1),!r(e););})},r&&(u.count=function(t,n){return i.setTime(+t),o.setTime(+n),e(i),e(o),Math.floor(r(i,o))},u.every=function(e){return e=Math.floor(e),isFinite(e)&&e>0?e>1?u.filter(a?function(t){return a(t)%e===0}:function(t){return u.count(0,t)%e===0}):u:null}),u}function n(e){return t(function(t){t.setHours(0,0,0,0),t.setDate(t.getDate()-(t.getDay()+7-e)%7)},function(e,t){e.setDate(e.getDate()+7*t)},function(e,t){return(t-e-6e4*(t.getTimezoneOffset()-e.getTimezoneOffset()))/6048e5})}function r(e){return t(function(t){t.setUTCHours(0,0,0,0),t.setUTCDate(t.getUTCDate()-(t.getUTCDay()+7-e)%7)},function(e,t){e.setUTCDate(e.getUTCDate()+7*t)},function(e,t){return(t-e)/6048e5})}var i=new Date,o=new Date,a=t(function(){},function(e,t){e.setTime(+e+t)},function(e,t){return t-e});a.every=function(e){return e=Math.floor(e),isFinite(e)&&e>0?e>1?t(function(t){t.setTime(Math.floor(t/e)*e)},function(t,n){t.setTime(+t+n*e)},function(t,n){return(n-t)/e}):a:null};var u=t(function(e){e.setMilliseconds(0)},function(e,t){e.setTime(+e+1e3*t)},function(e,t){return(t-e)/1e3},function(e){return e.getSeconds()}),c=t(function(e){e.setSeconds(0,0)},function(e,t){e.setTime(+e+6e4*t)},function(e,t){return(t-e)/6e4},function(e){return e.getMinutes()}),s=t(function(e){e.setMinutes(0,0,0)},function(e,t){e.setTime(+e+36e5*t)},function(e,t){return(t-e)/36e5},function(e){return e.getHours()}),l=t(function(e){e.setHours(0,0,0,0)},function(e,t){e.setDate(e.getDate()+t)},function(e,t){return(t-e-6e4*(t.getTimezoneOffset()-e.getTimezoneOffset()))/864e5},function(e){return e.getDate()-1}),d=n(0),f=n(1),p=n(2),y=n(3),g=n(4),h=n(5),m=n(6),v=t(function(e){e.setHours(0,0,0,0),e.setDate(1)},function(e,t){e.setMonth(e.getMonth()+t)},function(e,t){return t.getMonth()-e.getMonth()+12*(t.getFullYear()-e.getFullYear())},function(e){return e.getMonth()}),E=t(function(e){e.setHours(0,0,0,0),e.setMonth(0,1)},function(e,t){e.setFullYear(e.getFullYear()+t)},function(e,t){return t.getFullYear()-e.getFullYear()},function(e){return e.getFullYear()}),T=t(function(e){e.setUTCMilliseconds(0)},function(e,t){e.setTime(+e+1e3*t)},function(e,t){return(t-e)/1e3},function(e){return e.getUTCSeconds()}),O=t(function(e){e.setUTCSeconds(0,0)},function(e,t){e.setTime(+e+6e4*t)},function(e,t){return(t-e)/6e4},function(e){return e.getUTCMinutes()}),N=t(function(e){e.setUTCMinutes(0,0,0)},function(e,t){e.setTime(+e+36e5*t)},function(e,t){return(t-e)/36e5},function(e){return e.getUTCHours()}),S=t(function(e){e.setUTCHours(0,0,0,0)},function(e,t){e.setUTCDate(e.getUTCDate()+t)},function(e,t){return(t-e)/864e5},function(e){return e.getUTCDate()-1}),A=r(0),P=r(1),C=r(2),_=r(3),b=r(4),I=r(5),R=r(6),M=t(function(e){e.setUTCHours(0,0,0,0),e.setUTCDate(1)},function(e,t){e.setUTCMonth(e.getUTCMonth()+t)},function(e,t){return t.getUTCMonth()-e.getUTCMonth()+12*(t.getUTCFullYear()-e.getUTCFullYear())},function(e){return e.getUTCMonth()}),U=t(function(e){e.setUTCHours(0,0,0,0),e.setUTCMonth(0,1)},function(e,t){e.setUTCFullYear(e.getUTCFullYear()+t)},function(e,t){return t.getUTCFullYear()-e.getUTCFullYear()},function(e){return e.getUTCFullYear()}),D=a.range,w=u.range,L=c.range,x=s.range,F=l.range,k=d.range,Q=f.range,H=p.range,Y=y.range,j=g.range,G=h.range,B=m.range,W=d.range,q=v.range,V=E.range,z=a,X=D,K=T.range,$=O.range,J=N.range,Z=S.range,ee=A.range,te=P.range,ne=C.range,re=_.range,ie=b.range,oe=I.range,ae=R.range,ue=A.range,ce=M.range,se=U.range,le="0.1.1";e.version=le,e.milliseconds=D,e.seconds=w,e.minutes=L,e.hours=x,e.days=F,e.sundays=k,e.mondays=Q,e.tuesdays=H,e.wednesdays=Y,e.thursdays=j,e.fridays=G,e.saturdays=B,e.weeks=W,e.months=q,e.years=V,e.utcMillisecond=z,e.utcMilliseconds=X,e.utcSeconds=K,e.utcMinutes=$,e.utcHours=J,e.utcDays=Z,e.utcSundays=ee,e.utcMondays=te,e.utcTuesdays=ne,e.utcWednesdays=re,e.utcThursdays=ie,e.utcFridays=oe,e.utcSaturdays=ae,e.utcWeeks=ue,e.utcMonths=ce,e.utcYears=se,e.millisecond=a,e.second=u,e.minute=c,e.hour=s,e.day=l,e.sunday=d,e.monday=f,e.tuesday=p,e.wednesday=y,e.thursday=g,e.friday=h,e.saturday=m,e.week=d,e.month=v,e.year=E,e.utcSecond=T,e.utcMinute=O,e.utcHour=N,e.utcDay=S,e.utcSunday=A,e.utcMonday=P,e.utcTuesday=C,e.utcWednesday=_,e.utcThursday=b,e.utcFriday=I,e.utcSaturday=R,e.utcWeek=A,e.utcMonth=M,e.utcYear=U,e.interval=t})},{}],43:[function(e,t,n){function r(e){if(!e)throw Error("Missing binning options.");var t,n,r,u,c,s,l,d=e.maxbins||15,f=e.base||10,p=Math.log(f),y=e.div||[5,2],g=e.min,h=e.max,m=h-g;if(e.step)t=e.step;else if(e.steps)t=e.steps[Math.min(e.steps.length-1,i(e.steps,m/d,0,e.steps.length))];else{for(n=Math.ceil(Math.log(d)/p),r=e.minstep||0,t=Math.max(r,Math.pow(f,Math.round(Math.log(m)/p)-n));Math.ceil(m/t)>d;)t*=f;for(s=0;s=r&&m/c<=d&&(t=c)}return c=Math.log(t),u=c>=0?0:~~(-c/p)+1,l=Math.pow(f,-u-1),g=Math.min(g,Math.floor(g/t+l)*t),h=Math.ceil(h/t)*t,{start:g,stop:h,step:t,unit:{precision:u},value:o,index:a}}function i(e,t,n,r){for(;n>>1;s.cmp(e[i],t)<0?n=i+1:r=i}return n}function o(e){return this.step*Math.floor(e/this.step+d)}function a(e){return Math.floor((e-this.start)/this.step+d)}function u(e){return this.unit.date(o.call(this,e))}function c(e){return a.call(this,this.unit.unit(e))}var s=e("../util"),l=e("../time"),d=1e-15;r.date=function(e){if(!e)throw Error("Missing date binning options.");var t=e.utc?l.utc:l,n=e.min,i=e.max,o=e.maxbins||20,a=e.minbins||4,s=+i-+n,d=e.unit?t[e.unit]:t.find(s,a,o),f=r({min:null!=d.min?d.min:d.unit(n),max:null!=d.max?d.max:d.unit(i),maxbins:o,minstep:d.minstep,steps:d.step});return f.unit=d,f.index=c,e.raw||(f.value=u),f},t.exports=r},{"../time":47,"../util":48}],44:[function(e,t,n){var r=e("./util"),i=t.exports;i.repeat=function(e,t){var n,r=Array(t);for(n=0;nt;)i.push(r);else for(;(r=e+n*++o)=e&&r<=t?1/n:0},r.cdf=function(r){return rt?1:(r-e)/n},r.icdf=function(t){return t>=0&&t<=1?e+t*n:NaN},r},i.random.integer=function(e,t){void 0===t&&(t=e,e=0);var n=t-e,r=function(){return e+Math.floor(n*Math.random())};return r.samples=function(e){return i.zeros(e).map(r)},r.pdf=function(r){return r===Math.floor(r)&&r>=e&&r=t?1:(i-e+1)/n},r.icdf=function(t){return t>=0&&t<=1?e-1+Math.floor(t*n):NaN},r},i.random.normal=function(e,t){e=e||0,t=t||1;var n,r=function(){var r,i,o=0,a=0;if(void 0!==n)return o=n,n=void 0,o;do o=2*Math.random()-1,a=2*Math.random()-1,r=o*o+a*a;while(0===r||r>1);return i=Math.sqrt(-2*Math.log(r)/r),n=e+a*i*t,e+o*i*t};return r.samples=function(e){return i.zeros(e).map(r)},r.pdf=function(n){var r=Math.exp(Math.pow(n-e,2)/(-2*Math.pow(t,2)));return 1/(t*Math.sqrt(2*Math.PI))*r},r.cdf=function(n){var r,i=(n-e)/t,o=Math.abs(i);if(o>37)r=0;else{var a,u=Math.exp(-o*o/2);o<7.07106781186547?(a=.0352624965998911*o+.700383064443688,a=a*o+6.37396220353165,a=a*o+33.912866078383,a=a*o+112.079291497871,a=a*o+221.213596169931,a=a*o+220.206867912376,r=u*a,a=.0883883476483184*o+1.75566716318264,a=a*o+16.064177579207,a=a*o+86.7807322029461,a=a*o+296.564248779674,a=a*o+637.333633378831,a=a*o+793.826512519948,a=a*o+440.413735824752,r/=a):(a=o+.65,a=o+4/a,a=o+3/a,a=o+2/a,a=o+1/a,r=u/a/2.506628274631)}return i>0?1-r:r},r.icdf=function(n){if(n<=0||n>=1)return NaN;var r=2*n-1,i=8*(Math.PI-3)/(3*Math.PI*(4-Math.PI)),o=2/(Math.PI*i)+Math.log(1-Math.pow(r,2))/2,a=Math.log(1-r*r)/i,u=(r>0?1:-1)*Math.sqrt(Math.sqrt(o*o-a)-o);return e+t*Math.SQRT2*u},r},i.random.bootstrap=function(e,t){var n=e.filter(r.isValid),o=n.length,a=t?i.random.normal(0,t):null,u=function(){return n[~~(Math.random()*o)]+(a?a():0)};return u.samples=function(e){return i.zeros(e).map(u)},u}},{"./util":48}],45:[function(e,t,n){function r(e,t){return t?void(e[d]=t):e&&e[d]||null}function i(e){return l.keys(e)}function o(e){return"["+e+"]"}function a(e,t){e=l.array(e),t=l.$(t);var n,r,i;if(e[d]&&(n=t(e[d]),l.isString(n)))return n;for(r=0,i=e.length;!l.isValid(n)&&r0?Math.pow(u,1/n):0},s.mean.harmonic=function(e,t){t=a.$(t);var n,r,i,o,u=0;for(o=0,n=0,r=e.length;or&&(r=i));return[n,r]},s.extent.index=function(e,t){t=a.$(t);var n,r,i,o,u=-1,c=-1,s=e.length;for(o=0;or&&(r=i,c=o));return[u,c]},s.dot=function(e,t,n){var r,i,o=0;if(n)for(t=a.$(t),n=a.$(n),r=0;r-1&&l!==r){for(i=1+(n-1+s)/2;s-1)for(i=1+(u-1+s)/2;sg)&&(g=c),n=c-l,l+=n/++d,h+=n*(c-l),m.push(c));return h/=d-1,r=Math.sqrt(h),m.sort(a.cmp),{type:u(e,t),unique:v,count:e.length,valid:d,missing:f,distinct:p,min:y,max:g,mean:l,stdev:r,median:o=s.quantile(m,.5),q1:s.quantile(m,.25),q3:s.quantile(m,.75),modeskew:0===r?0:(l-o)/r}},s.summary=function(e,t){t=t||a.keys(e[0]);var n=t.map(function(t){var n=s.profile(e,a.$(t));return n.field=t,n});return n.__summary__=!0,n}},{"./generate":44,"./import/type":45,"./util":48}],47:[function(e,t,n){function r(e){return s.setTime(+e),s}function i(e,t,n,r,i,o){var a={type:e,date:t,unit:n};return r?a.step=r:a.minstep=1,null!=i&&(a.min=i),null!=o&&(a.max=o),a}function o(e,t,n,r,o,a){return i(e,function(e){return t.offset(n,e)},function(e){return t.count(n,e)},r,o,a)}function a(e,t,n,r){var i,o,a,u=y[0];for(i=1,o=y.length;iu[0]){if(a=t/u[0],a>r)return e[y[i-1][1]];if(a>=n)return e[u[1]]}return e[y[o-1][1]]}function u(e){var t,n,r={};for(t=0,n=e.length;t1?function(e,n){for(var r=0;rt||null==t)&&null!=e?1:(t=t instanceof Date?+t:t,(e=e instanceof Date?+e:e)!==e&&t===t?-1:t!==t&&e===e?1:0)},i.numcmp=function(e,t){return e-t},i.stablesort=function(e,t,n){var r=e.reduce(function(e,t,r){return e[n(t)]=r,e},{});return e.sort(function(e,i){var o=t(e),a=t(i);return oa?1:r[n(e)]-r[n(i)]}),e},i.permute=function(e){for(var t,n,r=e.length;r;)n=Math.floor(Math.random()*r--),t=e[r],e[r]=e[n],e[n]=t},i.pad=function(e,t,r,i){i=i||" ";var o=t-e.length;if(o<=0)return e;switch(r){case"left":return n(o,i)+e;case"middle":case"center":return n(Math.floor(o/2),i)+e+n(Math.ceil(o/2),i);default:return e+n(o,i)}},i.truncate=function(e,t,n,i,o){var a=e.length;if(a<=t)return e;o=void 0!==o?String(o):"…";var u=Math.max(0,t-o.length);switch(n){case"left":return o+(i?r(e,u,1):e.slice(a-u));case"middle":case"center":var c=Math.ceil(u/2),s=Math.floor(u/2);return(i?r(e,c):e.slice(0,c))+o+(i?r(e,s,1):e.slice(a-s));default:return(i?r(e,u):e.slice(0,u))+o}};var c=/([\u0009\u000A\u000B\u000C\u000D\u0020\u00A0\u1680\u180E\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F\u205F\u2028\u2029\u3000\uFEFF])/}).call(this,e("buffer").Buffer)},{buffer:41}],49:[function(e,t,n){var r="undefined"!=typeof JSON?JSON:e("jsonify");t.exports=function(e,t){t||(t={}),"function"==typeof t&&(t={cmp:t});var n=t.space||"";"number"==typeof n&&(n=Array(n+1).join(" "));var a="boolean"==typeof t.cycles&&t.cycles,u=t.replacer||function(e,t){return t},c=t.cmp&&function(e){return function(t){return function(n,r){var i={key:n,value:t[n]},o={key:r,value:t[r]};return e(i,o)}}}(t.cmp),s=[];return function l(e,t,d,f){var p=n?"\n"+new Array(f+1).join(n):"",y=n?": ":":";if(d&&d.toJSON&&"function"==typeof d.toJSON&&(d=d.toJSON()),d=u.call(e,t,d),void 0!==d){if("object"!=typeof d||null===d)return r.stringify(d);if(i(d)){for(var g=[],h=0;h="0"&&i<="9";)t+=i,s();if("."===i)for(t+=".";s()&&i>="0"&&i<="9";)t+=i;if("e"===i||"E"===i)for(t+=i,s(),"-"!==i&&"+"!==i||(t+=i,s());i>="0"&&i<="9";)t+=i,s();return e=+t,isFinite(e)?e:void c("Bad number")},d=function(){var e,t,n,r="";if('"'===i)for(;s();){if('"'===i)return s(),r;if("\\"===i)if(s(),"u"===i){for(n=0,t=0;t<4&&(e=parseInt(s(),16),isFinite(e));t+=1)n=16*n+e;r+=String.fromCharCode(n)}else{if("string"!=typeof u[i])break;r+=u[i]}else r+=i}c("Bad string")},f=function(){for(;i&&i<=" ";)s()},p=function(){switch(i){case"t":return s("t"),s("r"),s("u"),s("e"),!0;case"f":return s("f"),s("a"),s("l"),s("s"),s("e"),!1;case"n":return s("n"),s("u"),s("l"),s("l"),null}c("Unexpected '"+i+"'")},y=function(){var e=[];if("["===i){if(s("["),f(),"]"===i)return s("]"),e;for(;i;){if(e.push(a()),f(),"]"===i)return s("]"),e;s(","),f()}}c("Bad array")},g=function(){var e,t={};if("{"===i){if(s("{"),f(),"}"===i)return s("}"),t;for(;i;){if(e=d(),f(),s(":"),Object.hasOwnProperty.call(t,e)&&c('Duplicate key "'+e+'"'),t[e]=a(),f(),"}"===i)return s("}"),t;s(","),f()}}c("Bad object")};a=function(){switch(f(),i){case"{":return g();case"[":return y();case'"':return d();case"-":return l();default:return i>="0"&&i<="9"?l():p()}},t.exports=function(e,t){var n;return o=e,r=0,i=" ",n=a(),f(),i&&c("Syntax error"),"function"==typeof t?function u(e,n){var r,i,o=e[n];if(o&&"object"==typeof o)for(r in o)Object.prototype.hasOwnProperty.call(o,r)&&(i=u(o,r),void 0!==i?o[r]=i:delete o[r]);return t.call(e,n,o)}({"":n},""):n}},{}],52:[function(e,t,n){function r(e){return c.lastIndex=0,c.test(e)?'"'+e.replace(c,function(e){var t=s[e];return"string"==typeof t?t:"\\u"+("0000"+e.charCodeAt(0).toString(16)).slice(-4)})+'"':'"'+e+'"'}function i(e,t){var n,c,s,l,d,f=o,p=t[e];switch(p&&"object"==typeof p&&"function"==typeof p.toJSON&&(p=p.toJSON(e)),"function"==typeof u&&(p=u.call(t,e,p)),typeof p){case"string":return r(p);case"number":return isFinite(p)?String(p):"null";case"boolean":case"null":return String(p);case"object":if(!p)return"null";if(o+=a,d=[],"[object Array]"===Object.prototype.toString.apply(p)){for(l=p.length,n=0;n=0;u--)(i=e[u])&&(a=(o<3?i(a):o>3?i(t,n,a):i(t,n))||a);return o>3&&a&&Object.defineProperty(t,n,a),a},u=function(e,t){return function(n,r){t(n,r,e)}},c=function(e,t){if("object"==typeof Reflect&&"function"==typeof Reflect.metadata)return Reflect.metadata(e,t)},s=function(e,t,n,r){return new(n||(n=Promise))(function(i,o){function a(e){try{c(r.next(e))}catch(t){o(t)}}function u(e){try{c(r["throw"](e))}catch(t){o(t)}}function c(e){e.done?i(e.value):new n(function(t){t(e.value)}).then(a,u)}c((r=r.apply(e,t||[])).next())})},l=function(e,t){function n(e){return function(t){return r([e,t])}}function r(n){if(i)throw new TypeError("Generator is already executing.");for(;c;)try{if(i=1,o&&(a=o[2&n[0]?"return":n[0]?"throw":"next"])&&!(a=a.call(o,n[1])).done)return a;switch(o=0,a&&(n=[0,a.value]),n[0]){case 0:case 1:a=n;break;case 4:return c.label++,{value:n[1],done:!1};case 5:c.label++,o=n[1],n=[0];continue;case 7:n=c.ops.pop(),c.trys.pop();continue;default:if(a=c.trys,!(a=a.length>0&&a[a.length-1])&&(6===n[0]||2===n[0])){c=0;continue}if(3===n[0]&&(!a||n[1]>a[0]&&n[1]=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}}},p=function(e,t){var n="function"==typeof Symbol&&e[Symbol.iterator];if(!n)return e;var r,i,o=n.call(e),a=[];try{for(;(void 0===t||t-- >0)&&!(r=o.next()).done;)a.push(r.value)}catch(u){i={error:u}}finally{try{r&&!r.done&&(n=o["return"])&&n.call(o)}finally{if(i)throw i.error}}return a},y=function(){for(var e=[],t=0;t1||i(e,t)})})}function i(e,t){try{o(l[e](t))}catch(n){c(d[0][3],n)}}function o(e){e.value instanceof g?Promise.resolve(e.value.v).then(a,u):c(d[0][2],e)}function a(e){i("next",e)}function u(e){i("throw",e)}function c(e,t){e(t),d.shift(),d.length&&i(d[0][0],d[0][1])}if(!Symbol.asyncIterator)throw new TypeError("Symbol.asyncIterator is not defined.");var s,l=n.apply(e,t||[]),d=[];return s={},r("next"),r("throw"),r("return"),s[Symbol.asyncIterator]=function(){return this},s},m=function(e){function t(t,i){e[t]&&(n[t]=function(n){return(r=!r)?{value:g(e[t](n)),done:"return"===t}:i?i(n):n})}var n,r;return n={},t("next"),t("throw",function(e){throw e}),t("return"),n[Symbol.iterator]=function(){return this},n},v=function(e){if(!Symbol.asyncIterator)throw new TypeError("Symbol.asyncIterator is not defined.");var t=e[Symbol.asyncIterator];return t?t.call(e):"function"==typeof f?f(e):e[Symbol.iterator]()},e("__extends",r),e("__assign",i),e("__rest",o),e("__decorate",a),e("__param",u),e("__metadata",c),e("__awaiter",s),e("__generator",l),e("__exportStar",d),e("__values",f),e("__read",p),e("__spread",y),e("__await",g),e("__asyncGenerator",h),e("__asyncDelegator",m),e("__asyncValues",v)})}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{}],54:[function(e,t,n){"use strict";function r(e){return e&&i.contains(n.COUNTING_OPS,e)}Object.defineProperty(n,"__esModule",{value:!0});var i=e("./util");n.AGGREGATE_OPS=["values","count","valid","missing","distinct","sum","mean","average","variance","variancep","stdev","stdevp","median","q1","q3","ci0","ci1","modeskew","min","max","argmin","argmax"],n.AGGREGATE_OP_INDEX=i.toSet(n.AGGREGATE_OPS),n.COUNTING_OPS=["count","valid","missing","distinct"],n.isCountingAggregateOp=r,n.SUM_OPS=["count","sum","distinct","valid","missing"],n.SHARED_DOMAIN_OPS=["mean","average","median","q1","q3","min","max"],n.SHARED_DOMAIN_OP_INDEX=i.toSet(n.SHARED_DOMAIN_OPS)},{"./util":68}],55:[function(e,t,n){"use strict";Object.defineProperty(n,"__esModule",{value:!0}),n.DEFAULT_AXIS_CONFIG={quantitativeExtent:30},n.AXIS_PROPERTY_TYPE={grid:"grid",labelOverlap:"main",offset:"main",maxExtent:"main",minExtent:"main",title:"main"},n.AXIS_PROPERTIES=["domain","format","grid","labelPadding","labels","labelOverlap","maxExtent","minExtent","offset","orient","position","tickCount","tickExtra","ticks","tickSize","title","titlePadding","values","zindex"],n.VG_AXIS_PROPERTIES=[].concat(n.AXIS_PROPERTIES,["gridScale"])},{}],56:[function(e,t,n){"use strict";function r(e){return a.isBoolean(e)?"bin":"bin"+a.keys(e).map(function(t){return"_"+t+"_"+e[t]}).join("")}function i(e){switch(e){case o.ROW:case o.COLUMN:case o.SIZE:case o.COLOR:case o.OPACITY:case o.SHAPE:return 6;default:return 10}}Object.defineProperty(n,"__esModule",{value:!0});var o=e("./channel"),a=e("./util");n.binToString=r,n.autoMaxBins=i},{"./channel":57,"./util":68}],57:[function(e,t,n){"use strict";function r(e){return!!p[e]}function i(e){return!!y[e]}function o(e,t){return t in a(e)}function a(e){switch(e){case n.X:case n.Y:case n.COLOR:case n.DETAIL:case n.TOOLTIP:case n.ORDER:case n.OPACITY:case n.ROW:case n.COLUMN:return{point:!0,tick:!0,rule:!0,circle:!0,square:!0,bar:!0,rect:!0,line:!0,area:!0,text:!0};case n.X2:case n.Y2:return{rule:!0,bar:!0,rect:!0,area:!0};case n.SIZE:return{point:!0,tick:!0,rule:!0,circle:!0,square:!0,bar:!0,text:!0,line:!0};case n.SHAPE:return{point:!0};case n.TEXT:return{text:!0}}}function u(e){return!f.contains([n.DETAIL,n.TEXT,n.ORDER,n.TOOLTIP],e)}function c(e,t){switch(e){case n.ROW:case n.COLUMN:return"band"===t;case n.X:case n.Y:case n.SIZE:case n.OPACITY:return t in g;case n.COLOR:return"band"!==t;case n.SHAPE:return"ordinal"===t}return!1}function s(e){switch(e){case n.X:case n.Y:case n.SIZE:case n.OPACITY:case n.X2:case n.Y2:return"continuous";case n.ROW:case n.COLUMN:case n.SHAPE:case n.TEXT:case n.TOOLTIP:return"discrete";case n.COLOR:return"flexible";case n.DETAIL:case n.ORDER:return}throw new Error("getSupportedRole not implemented for "+e)}Object.defineProperty(n,"__esModule",{value:!0});var l,d=e("./scale"),f=e("./util");!function(e){e.ROW="row",e.COLUMN="column",e.X="x",e.Y="y",e.X2="x2",e.Y2="y2",e.COLOR="color",e.SHAPE="shape",e.SIZE="size",e.OPACITY="opacity",e.TEXT="text",e.ORDER="order",e.DETAIL="detail",e.TOOLTIP="tooltip"}(l=n.Channel||(n.Channel={})),n.X=l.X,n.Y=l.Y,n.X2=l.X2,n.Y2=l.Y2,n.ROW=l.ROW,n.COLUMN=l.COLUMN,n.SHAPE=l.SHAPE,n.SIZE=l.SIZE,n.COLOR=l.COLOR,n.TEXT=l.TEXT,n.DETAIL=l.DETAIL,n.ORDER=l.ORDER,n.OPACITY=l.OPACITY,n.TOOLTIP=l.TOOLTIP,n.CHANNELS=[n.X,n.Y,n.X2,n.Y2,n.ROW,n.COLUMN,n.SIZE,n.SHAPE,n.COLOR,n.ORDER,n.OPACITY,n.TEXT,n.DETAIL,n.TOOLTIP];var p=f.toSet(n.CHANNELS);n.SINGLE_DEF_CHANNELS=[n.X,n.Y,n.X2,n.Y2,n.ROW,n.COLUMN,n.SIZE,n.SHAPE,n.COLOR,n.OPACITY,n.TEXT,n.TOOLTIP],n.isChannel=r,n.UNIT_CHANNELS=[n.X,n.Y,n.X2,n.Y2,n.SIZE,n.SHAPE,n.COLOR,n.ORDER,n.OPACITY,n.TEXT,n.DETAIL,n.TOOLTIP],n.SCALE_CHANNELS=[n.X,n.Y,n.SIZE,n.SHAPE,n.COLOR,n.OPACITY];var y=f.toSet(n.SCALE_CHANNELS);n.isScaleChannel=i,n.NONSPATIAL_CHANNELS=[n.SIZE,n.SHAPE,n.COLOR,n.ORDER,n.OPACITY,n.TEXT,n.DETAIL,n.TOOLTIP],n.SPATIAL_SCALE_CHANNELS=[n.X,n.Y],n.NONSPATIAL_SCALE_CHANNELS=[n.SIZE,n.SHAPE,n.COLOR,n.OPACITY],n.LEVEL_OF_DETAIL_CHANNELS=f.without(n.NONSPATIAL_CHANNELS,["order"]),n.STACK_BY_CHANNELS=[n.COLOR,n.DETAIL,n.ORDER,n.OPACITY,n.SIZE],n.supportMark=o,n.getSupportedMark=a,n.hasScale=u;var g=f.toSet(f.without(d.SCALE_TYPES,["ordinal","sequential"]));n.supportScaleType=c,n.rangeType=s},{"./scale":65,"./util":68}],58:[function(e,t,n){"use strict";function r(e,t,n,r,o,s){var l=i(t,n,r,o,s);return u.hasScale(t)?void 0!==e?u.supportScaleType(t,e)?a(e,n)?e:(c.warn(c.message.scaleTypeNotWorkWithFieldDef(e,l)),l):(c.warn(c.message.scaleTypeNotWorkWithChannel(t,e,l)),l):l:null}function i(e,t,n,r,i){switch(t.type){case"nominal":return"color"===e||"discrete"===u.rangeType(e)?"ordinal":o(e,n,r,i);case"ordinal":return"color"===e?"ordinal":"discrete"===u.rangeType(e)?("text"!==e&&"tooltip"!==e&&c.warn(c.message.discreteChannelCannotEncode(e,"ordinal")),"ordinal"):o(e,n,r,i);case"temporal":return"color"===e?d.isDiscreteByDefault(t.timeUnit)?"ordinal":"sequential":"discrete"===u.rangeType(e)?(c.warn(c.message.discreteChannelCannotEncode(e,"temporal")),"ordinal"):d.isDiscreteByDefault(t.timeUnit)?o(e,n,r,i):"time";case"quantitative":return"color"===e?t.bin?"bin-ordinal":"sequential":"discrete"===u.rangeType(e)?(c.warn(c.message.discreteChannelCannotEncode(e,"quantitative")),"ordinal"):t.bin&&"x"!==e&&"y"!==e?"bin-linear":"linear"}throw new Error(c.message.invalidFieldType(t.type))}function o(e,t,n,r){if(p.contains(["x","y"],e)){if("rect"===t)return"band";if("bar"===t)return"band"}return"point"}function a(e,t){var n=t.type;return y.contains([f.Type.ORDINAL,f.Type.NOMINAL],n)?void 0===e||l.hasDiscreteDomain(e):n===f.Type.TEMPORAL?t.timeUnit?y.contains([s.ScaleType.TIME,s.ScaleType.UTC,void 0],e)||l.hasDiscreteDomain(e):y.contains([s.ScaleType.TIME,s.ScaleType.UTC,void 0],e):n!==f.Type.QUANTITATIVE||(t.bin?e===s.ScaleType.BIN_LINEAR||e===s.ScaleType.BIN_ORDINAL:y.contains([s.ScaleType.LOG,s.ScaleType.POW,s.ScaleType.SQRT,s.ScaleType.QUANTILE,s.ScaleType.QUANTIZE,s.ScaleType.LINEAR,void 0],e))}Object.defineProperty(n,"__esModule",{ +value:!0});var u=e("../../channel"),c=e("../../log"),s=e("../../scale"),l=e("../../scale"),d=e("../../timeunit"),f=e("../../type"),p=e("../../util"),y=e("../../util");n.scaleType=r,n.fieldDefMatchScaleType=a},{"../../channel":57,"../../log":62,"../../scale":65,"../../timeunit":66,"../../type":67,"../../util":68}],59:[function(e,t,n){"use strict";function r(e){return!!(e&&(e.year||e.quarter||e.month||e.date||e.day||e.hours||e.minutes||e.seconds||e.milliseconds))}function i(e){if(s.isNumber(e))return e>4&&c.warn(c.message.invalidTimeUnit("quarter",e)),e-1+"";throw new Error(c.message.invalidTimeUnit("quarter",e))}function o(e){if(s.isNumber(e))return e-1+"";var t=e.toLowerCase(),r=n.MONTHS.indexOf(t);if(r!==-1)return r+"";var i=t.substr(0,3),o=n.SHORT_MONTHS.indexOf(i);if(o!==-1)return o+"";throw new Error(c.message.invalidTimeUnit("month",e))}function a(e){if(s.isNumber(e))return e%7+"";var t=e.toLowerCase(),r=n.DAYS.indexOf(t);if(r!==-1)return r+"";var i=t.substr(0,3),o=n.SHORT_DAYS.indexOf(i);if(o!==-1)return o+"";throw new Error(c.message.invalidTimeUnit("day",e))}function u(e,t){void 0===t&&(t=!1);var n=[];if(t&&void 0!==e.day&&s.keys(e).length>1&&(c.warn(c.message.droppedDay(e)),e=s.duplicate(e),delete e.day),void 0!==e.year?n.push(e.year):void 0!==e.day?n.push(l):n.push(0),void 0!==e.month){var r=t?o(e.month):e.month;n.push(r)}else if(void 0!==e.quarter){var u=t?i(e.quarter):e.quarter;n.push(u+"*3")}else n.push(0);if(void 0!==e.date)n.push(e.date);else if(void 0!==e.day){var d=t?a(e.day):e.day;n.push(d+"+1")}else n.push(1);for(var f=0,p=["hours","minutes","seconds","milliseconds"];f-1&&(t!==f.SECONDS||0===n||"i"!==e.charAt(n-1))}function u(e,t){function r(e){return e===f.QUARTER?"("+o+"quarter("+i+")-1)":""+o+e+"("+i+")"}var i="datum["+g.stringValue(t)+"]",o=d(e)?"utc":"",u=n.SINGLE_TIMEUNITS.reduce(function(t,n){return a(e,n)&&(t[n]=r(n)),t},{});return u.day&&g.keys(u).length>1&&(y.warn(y.message.dayReplacedWithDate(e)),delete u.day,u.date=r(f.DATE)),p.dateTimeExpr(u)}function c(e){if(e)return a(e,f.SECONDS)?"second":a(e,f.MINUTES)?"minute":a(e,f.HOURS)?"hour":a(e,f.DAY)||a(e,f.DATE)?"day":a(e,f.MONTH)?"month":a(e,f.YEAR)?"year":void 0}function s(e,t,n,r){if(e){var i=[],o="",u=a(e,f.YEAR);a(e,f.QUARTER)&&(o="'Q' + quarter("+t+")"),a(e,f.MONTH)&&i.push(n!==!1?"%b":"%B"),a(e,f.DAY)?i.push(n?"%a":"%A"):a(e,f.DATE)&&i.push("%d"+(u?",":"")),u&&i.push(n?"%y":"%Y");var c=[];a(e,f.HOURS)&&c.push("%H"),a(e,f.MINUTES)&&c.push("%M"),a(e,f.SECONDS)&&c.push("%S"),a(e,f.MILLISECONDS)&&c.push("%L");var s=[];return i.length>0&&s.push(i.join(" ")),c.length>0&&s.push(c.join(":")),s.length>0&&(o&&(o+=" + ' ' + "),o+=r?"utcFormat("+t+", '"+s.join(" ")+"')":"timeFormat("+t+", '"+s.join(" ")+"')"),o||void 0}}function l(e){switch(e){case"hours":case"day":case"month":case"quarter":return!0}return!1}function d(e){return"utc"===e.substr(0,3)}Object.defineProperty(n,"__esModule",{value:!0});var f,p=e("./datetime"),y=e("./log"),g=e("./util");!function(e){e.YEAR="year",e.MONTH="month",e.DAY="day",e.DATE="date",e.HOURS="hours",e.MINUTES="minutes",e.SECONDS="seconds",e.MILLISECONDS="milliseconds",e.YEARMONTH="yearmonth",e.YEARMONTHDATE="yearmonthdate",e.YEARMONTHDATEHOURS="yearmonthdatehours",e.YEARMONTHDATEHOURSMINUTES="yearmonthdatehoursminutes",e.YEARMONTHDATEHOURSMINUTESSECONDS="yearmonthdatehoursminutesseconds",e.MONTHDATE="monthdate",e.HOURSMINUTES="hoursminutes",e.HOURSMINUTESSECONDS="hoursminutesseconds",e.MINUTESSECONDS="minutesseconds",e.SECONDSMILLISECONDS="secondsmilliseconds",e.QUARTER="quarter",e.YEARQUARTER="yearquarter",e.QUARTERMONTH="quartermonth",e.YEARQUARTERMONTH="yearquartermonth",e.UTCYEAR="utcyear",e.UTCMONTH="utcmonth",e.UTCDAY="utcday",e.UTCDATE="utcdate",e.UTCHOURS="utchours",e.UTCMINUTES="utcminutes",e.UTCSECONDS="utcseconds",e.UTCMILLISECONDS="utcmilliseconds",e.UTCYEARMONTH="utcyearmonth",e.UTCYEARMONTHDATE="utcyearmonthdate",e.UTCYEARMONTHDATEHOURS="utcyearmonthdatehours",e.UTCYEARMONTHDATEHOURSMINUTES="utcyearmonthdatehoursminutes",e.UTCYEARMONTHDATEHOURSMINUTESSECONDS="utcyearmonthdatehoursminutesseconds",e.UTCMONTHDATE="utcmonthdate",e.UTCHOURSMINUTES="utchoursminutes",e.UTCHOURSMINUTESSECONDS="utchoursminutesseconds",e.UTCMINUTESSECONDS="utcminutesseconds",e.UTCSECONDSMILLISECONDS="utcsecondsmilliseconds",e.UTCQUARTER="utcquarter",e.UTCYEARQUARTER="utcyearquarter",e.UTCQUARTERMONTH="utcquartermonth",e.UTCYEARQUARTERMONTH="utcyearquartermonth"}(f=n.TimeUnit||(n.TimeUnit={})),n.SINGLE_TIMEUNITS=[f.YEAR,f.QUARTER,f.MONTH,f.DAY,f.DATE,f.HOURS,f.MINUTES,f.SECONDS,f.MILLISECONDS];var h=n.SINGLE_TIMEUNITS.reduce(function(e,t){return e[t]=!0,e},{});n.isSingleTimeUnit=r,n.convert=i,n.MULTI_TIMEUNITS=[f.YEARQUARTER,f.YEARQUARTERMONTH,f.YEARMONTH,f.YEARMONTHDATE,f.YEARMONTHDATEHOURS,f.YEARMONTHDATEHOURSMINUTES,f.YEARMONTHDATEHOURSMINUTESSECONDS,f.QUARTERMONTH,f.HOURSMINUTES,f.HOURSMINUTESSECONDS,f.MINUTESSECONDS,f.SECONDSMILLISECONDS];var m=n.MULTI_TIMEUNITS.reduce(function(e,t){return e[t]=!0,e},{});n.isMultiTimeUnit=o,n.TIMEUNITS=[f.YEAR,f.QUARTER,f.MONTH,f.DAY,f.DATE,f.HOURS,f.MINUTES,f.SECONDS,f.MILLISECONDS,f.YEARQUARTER,f.YEARQUARTERMONTH,f.YEARMONTH,f.YEARMONTHDATE,f.YEARMONTHDATEHOURS,f.YEARMONTHDATEHOURSMINUTES,f.YEARMONTHDATEHOURSMINUTESSECONDS,f.QUARTERMONTH,f.HOURSMINUTES,f.HOURSMINUTESSECONDS,f.MINUTESSECONDS,f.SECONDSMILLISECONDS],n.containsTimeUnit=a,n.fieldExpr=u,n.smallestUnit=c,n.formatExpression=s,n.isDiscreteByDefault=l},{"./datetime":59,"./log":62,"./util":68}],67:[function(e,t,n){"use strict";function r(e){if(e)switch(e=e.toLowerCase()){case"q":case n.QUANTITATIVE:return"quantitative";case"t":case n.TEMPORAL:return"temporal";case"o":case n.ORDINAL:return"ordinal";case"n":case n.NOMINAL:return"nominal"}}Object.defineProperty(n,"__esModule",{value:!0});var i;!function(e){e.QUANTITATIVE="quantitative",e.ORDINAL="ordinal",e.TEMPORAL="temporal",e.NOMINAL="nominal"}(i=n.Type||(n.Type={})),n.QUANTITATIVE=i.QUANTITATIVE,n.ORDINAL=i.ORDINAL,n.TEMPORAL=i.TEMPORAL,n.NOMINAL=i.NOMINAL,n.getFullName=r},{}],68:[function(e,t,n){"use strict";function r(e,t){var n={};return t.forEach(function(t){e.hasOwnProperty(t)&&(n[t]=e[t])}),n}function i(e,t){var n=E(e);return t.forEach(function(e){delete n[e]}),n}function o(e){return A.isString(e)||A.isNumber(e)||T(e)?String(e):S(e)}function a(e,t){return e.indexOf(t)>-1}function u(e,t){return e.filter(function(e){return!a(t,e)})}function c(e,t){return e.concat(u(t,e))}function s(e,t){for(var n=0,r=0;rn&&t(),c=n=r+1):"]"===i&&(c||u("Access path missing open bracket: "+e),c>0&&t(),c=0,n=r+1):r>n?t():n=r+1}return c&&u("Access path missing closing bracket: "+e),a&&u("Access path missing closing quote: "+e),r>n&&(r++,t()),o},s=Array.isArray,l=function(e){return e===Object(e)},d=function(e){return"string"==typeof e},f=function(e,t){var n=c(e),i="return _["+n.map(r).join("][")+"];";return a(Function("_",i),[e=1===n.length?n[0]:e],t||e)},p=[],y=f("id"),g=a(function(e){return e},p,"identity"),h=a(function(){return 0},p,"zero"),m=a(function(){return 1},p,"one"),v=a(function(){return!0},p,"true"),E=a(function(){return!1},p,"false"),T=0,O=1,N=2,S=3,A=4,P=function(e){var t=e||T;return{level:function(e){return arguments.length?(t=+e,this):t},error:function(){return t>=O&&i("error","ERROR",arguments),this},warn:function(){return t>=N&&i("warn","WARN",arguments),this},info:function(){return t>=S&&i("log","INFO",arguments),this},debug:function(){return t>=A&&i("log","DEBUG",arguments),this}}},C=function(e){return null!=e?s(e)?e:[e]:[]},_=function(e,t){var n,i,o,u,s,l,d,f,p=[],y=(e=C(e)).map(function(e,t){return null==e?null:(p.push(t),c(e).map(r).join("]["))}),g=p.length-1,h=C(t),m="var u,v;return ";if(g<0)return null;for(i=0;i<=g;++i)n=p[i],o=y[n],u="(u=a["+o+"])",s="(v=b["+o+"])",l="((v=v instanceof Date?+v:v),(u=u instanceof Date?+u:u))","descending"!==h[n]?(f=1,d=-1):(f=-1,d=1),m+="("+u+"<"+s+"||u==null)&&v!=null?"+d+":(u>v||v==null)&&u!=null?"+f+":"+l+"!==u&&v===v?"+d+":v!==v&&u===u?"+f+(n=r){n=i=r;break}for(o=a=u;++ur&&(n=r,o=u),i=r){n=i=r;break}for(o=a=u;++ur&&(n=r,o=u),i0?n[c++]:t[u++];for(;u=0;)n+=e;return n},G=function(e,t,n,r){var i=n||" ",o=e+"",a=t-o.length;return a<=0?o:"left"===r?j(i,a)+o:"center"===r?j(i,~~(a/2))+o+j(i,Math.ceil(a/2)):o+j(i,a)},B=function(e){return e[e.length-1]},W=function(e){return null==e||""===e?null:!(!e||"false"===e||"0"===e)&&!!e},q=function(e,t){return t=t||o,null==e||""===e?null:t(e)},V=function(e){return null==e||""===e?null:+e},z=function(e){return null==e||""===e?null:e+""},X=function(e){for(var t={},n=0,r=e.length;n= opt.minCardinalityForBin; + } + return true; + } + }, { + name: 'binAppliedForQuantitative', + description: 'bin should be applied to quantitative field only.', + properties: [property_1.Property.TYPE, property_1.Property.BIN], + allowWildcardForProperties: false, + strict: true, + satisfy: function (fieldQ, _, __, ___) { + if (fieldQ.bin) { + // If binned, the type must be quantitative + return fieldQ.type === type_1.Type.QUANTITATIVE; + } + return true; + } + }, { + name: 'channelFieldCompatible', + description: "encoding channel's range type be compatible with channel type.", + properties: [property_1.Property.CHANNEL, property_1.Property.TYPE, property_1.Property.BIN, property_1.Property.TIMEUNIT], + allowWildcardForProperties: false, + strict: true, + satisfy: function (fieldQ, _, encWildcardIndex, opt) { + var fieldDef = __assign({ field: 'f' }, encoding_1.toFieldDef(fieldQ, ['bin', 'timeUnit', 'type'])); + return fielddef_1.channelCompatibility(fieldDef, fieldQ.channel).compatible; + } + }, { + name: 'hasFn', + description: 'A field with as hasFn flag should have one of aggregate, timeUnit, or bin.', + properties: [property_1.Property.AGGREGATE, property_1.Property.BIN, property_1.Property.TIMEUNIT], + allowWildcardForProperties: true, + strict: true, + satisfy: function (fieldQ, _, __, ___) { + if (fieldQ.hasFn) { + return !!fieldQ.aggregate || !!fieldQ.bin || !!fieldQ.timeUnit; + } + return true; + } + }, { + name: 'omitScaleZeroWithBinnedField', + description: 'Do not use scale zero with binned field', + properties: [property_1.Property.SCALE, property_1.getEncodingNestedProp('scale', 'zero'), property_1.Property.BIN], + allowWildcardForProperties: false, + strict: true, + satisfy: function (fieldQ, _, __, ___) { + if (fieldQ.bin && fieldQ.scale) { + if (fieldQ.scale.zero === true) { + return false; + } + } + return true; + } + }, { + name: 'onlyOneTypeOfFunction', + description: 'Only of of aggregate, autoCount, timeUnit, or bin should be applied at the same time.', + properties: [property_1.Property.AGGREGATE, property_1.Property.AUTOCOUNT, property_1.Property.TIMEUNIT, property_1.Property.BIN], + allowWildcardForProperties: true, + strict: true, + satisfy: function (fieldQ, _, __, ___) { + if (encoding_1.isFieldQuery(fieldQ)) { + var numFn = (!wildcard_1.isWildcard(fieldQ.aggregate) && !!fieldQ.aggregate ? 1 : 0) + + (!wildcard_1.isWildcard(fieldQ.bin) && !!fieldQ.bin ? 1 : 0) + + (!wildcard_1.isWildcard(fieldQ.timeUnit) && !!fieldQ.timeUnit ? 1 : 0); + return numFn <= 1; + } + // For autoCount there is always only one type of function + return true; + } + }, { + name: 'timeUnitAppliedForTemporal', + description: 'Time unit should be applied to temporal field only.', + properties: [property_1.Property.TYPE, property_1.Property.TIMEUNIT], + allowWildcardForProperties: false, + strict: true, + satisfy: function (fieldQ, _, __, ___) { + if (fieldQ.timeUnit && fieldQ.type !== type_1.Type.TEMPORAL) { + return false; + } + return true; + } + }, { + name: 'timeUnitShouldHaveVariation', + description: 'A particular time unit should be applied only if they produce unique values.', + properties: [property_1.Property.TIMEUNIT, property_1.Property.TYPE], + allowWildcardForProperties: false, + strict: false, + satisfy: function (fieldQ, schema, encWildcardIndex, opt) { + if (fieldQ.timeUnit && fieldQ.type === type_1.Type.TEMPORAL) { + if (!encWildcardIndex.has('timeUnit') && !opt.constraintManuallySpecifiedValue) { + // Do not have to check this as this is manually specified by users. + return true; + } + return schema.timeUnitHasVariation(fieldQ); + } + return true; + } + }, { + name: 'scalePropertiesSupportedByScaleType', + description: 'Scale properties must be supported by correct scale type', + properties: [].concat(property_1.SCALE_PROPS, [property_1.Property.SCALE, property_1.Property.TYPE]), + allowWildcardForProperties: true, + strict: true, + satisfy: function (fieldQ, _, __, ___) { + if (fieldQ.scale) { + var scale = fieldQ.scale; + // If fieldQ.type is an Wildcard and scale.type is undefined, it is equivalent + // to scale type is Wildcard. If scale type is an Wildcard, we do not yet know + // what the scale type is, and thus can ignore the constraint. + var sType = encoding_1.scaleType(fieldQ); + if (sType === undefined || sType === null) { + // If still ambiguous, doesn't check the constraint + return true; + } + for (var scaleProp in scale) { + if (scaleProp === 'type' || scaleProp === 'name' || scaleProp === 'enum') { + // ignore type and properties of wildcards + continue; + } + var sProp = scaleProp; + if (sType === 'point') { + // HACK: our current implementation of scaleType() can return point + // when the scaleType is a band since we didn't pass all parameter to Vega-Lite's scale type method. + if (!scale_1.scaleTypeSupportProperty('point', sProp) && !scale_1.scaleTypeSupportProperty('band', sProp)) { + return false; + } + } + else if (!scale_1.scaleTypeSupportProperty(sType, sProp)) { + return false; + } + } + } + return true; + } + }, { + name: 'scalePropertiesSupportedByChannel', + description: 'Not all scale properties are supported by all encoding channels', + properties: [].concat(property_1.SCALE_PROPS, [property_1.Property.SCALE, property_1.Property.CHANNEL]), + allowWildcardForProperties: true, + strict: true, + satisfy: function (fieldQ, _, __, ___) { + if (fieldQ) { + var channel = fieldQ.channel; + var scale = fieldQ.scale; + if (channel && !wildcard_1.isWildcard(channel) && scale) { + if (channel === 'row' || channel === 'column') { + // row / column do not have scale + return false; + } + for (var scaleProp in scale) { + if (!scale.hasOwnProperty(scaleProp)) + continue; + if (scaleProp === 'type' || scaleProp === 'name' || scaleProp === 'enum') { + // ignore type and properties of wildcards + continue; + } + var isSupported = scale_1.channelScalePropertyIncompatability(channel, scaleProp) === undefined; + if (!isSupported) { + return false; + } + } + } + } + return true; + } + }, { + name: 'typeMatchesPrimitiveType', + description: 'Data type should be supported by field\'s primitive type.', + properties: [property_1.Property.FIELD, property_1.Property.TYPE], + allowWildcardForProperties: false, + strict: true, + satisfy: function (fieldQ, schema, encWildcardIndex, opt) { + if (fieldQ.field === '*') { + return true; + } + var primitiveType = schema.primitiveType(fieldQ.field); + var type = fieldQ.type; + if (!encWildcardIndex.has('field') && !encWildcardIndex.has('type') && !opt.constraintManuallySpecifiedValue) { + // Do not have to check this as this is manually specified by users. + return true; + } + switch (primitiveType) { + case schema_1.PrimitiveType.BOOLEAN: + case schema_1.PrimitiveType.STRING: + return type !== type_1.Type.QUANTITATIVE && type !== type_1.Type.TEMPORAL; + case schema_1.PrimitiveType.NUMBER: + case schema_1.PrimitiveType.INTEGER: + return type !== type_1.Type.TEMPORAL; + case schema_1.PrimitiveType.DATETIME: + // TODO: add NOMINAL, ORDINAL support after we support this in Vega-Lite + return type === type_1.Type.TEMPORAL; + case null: + // field does not exist in the schema + return false; + } + throw new Error('Not implemented'); + } + }, + { + name: 'typeMatchesSchemaType', + description: 'Enumerated data type of a field should match the field\'s type in the schema.', + properties: [property_1.Property.FIELD, property_1.Property.TYPE], + allowWildcardForProperties: false, + strict: false, + satisfy: function (fieldQ, schema, encWildcardIndex, opt) { + if (!encWildcardIndex.has('field') && !encWildcardIndex.has('type') && !opt.constraintManuallySpecifiedValue) { + // Do not have to check this as this is manually specified by users. + return true; + } + if (fieldQ.field === '*') { + return fieldQ.type === type_1.Type.QUANTITATIVE; + } + return schema.vlType(fieldQ.field) === fieldQ.type; + } + }, { + name: 'maxCardinalityForCategoricalColor', + description: 'Categorical channel should not have too high cardinality', + properties: [property_1.Property.CHANNEL, property_1.Property.FIELD], + allowWildcardForProperties: false, + strict: false, + satisfy: function (fieldQ, schema, _, opt) { + // TODO: missing case where ordinal / temporal use categorical color + // (once we do so, need to add Property.BIN, Property.TIMEUNIT) + if (fieldQ.channel === channel_1.Channel.COLOR && (fieldQ.type === type_1.Type.NOMINAL || fieldQ.type === expandedtype_1.ExpandedType.KEY)) { + return schema.cardinality(fieldQ) <= opt.maxCardinalityForCategoricalColor; + } + return true; // other channel is irrelevant to this constraint + } + }, { + name: 'maxCardinalityForFacet', + description: 'Row/column channel should not have too high cardinality', + properties: [property_1.Property.CHANNEL, property_1.Property.FIELD, property_1.Property.BIN, property_1.Property.TIMEUNIT], + allowWildcardForProperties: false, + strict: false, + satisfy: function (fieldQ, schema, _, opt) { + if (fieldQ.channel === channel_1.Channel.ROW || fieldQ.channel === channel_1.Channel.COLUMN) { + return schema.cardinality(fieldQ) <= opt.maxCardinalityForFacet; + } + return true; // other channel is irrelevant to this constraint + } + }, { + name: 'maxCardinalityForShape', + description: 'Shape channel should not have too high cardinality', + properties: [property_1.Property.CHANNEL, property_1.Property.FIELD, property_1.Property.BIN, property_1.Property.TIMEUNIT], + allowWildcardForProperties: false, + strict: false, + satisfy: function (fieldQ, schema, _, opt) { + if (fieldQ.channel === channel_1.Channel.SHAPE) { + return schema.cardinality(fieldQ) <= opt.maxCardinalityForShape; + } + return true; // other channel is irrelevant to this constraint + } + }, + { + name: 'dataTypeAndFunctionMatchScaleType', + description: 'Scale type must match data type', + properties: [property_1.Property.TYPE, property_1.Property.SCALE, property_1.getEncodingNestedProp('scale', 'type'), property_1.Property.TIMEUNIT, property_1.Property.BIN], + allowWildcardForProperties: false, + strict: true, + satisfy: function (fieldQ, _, __, ___) { + if (fieldQ.scale) { + var type = fieldQ.type; + var sType = encoding_1.scaleType(fieldQ); + if (expandedtype_1.isDiscrete(type)) { + return sType === undefined || scale_1.hasDiscreteDomain(sType); + } + else if (type === type_1.Type.TEMPORAL) { + if (!fieldQ.timeUnit) { + return util_1.contains([scale_1.ScaleType.TIME, scale_1.ScaleType.UTC, undefined], sType); + } + else { + return util_1.contains([scale_1.ScaleType.TIME, scale_1.ScaleType.UTC, undefined], sType) || scale_1.hasDiscreteDomain(sType); + } + } + else if (type === type_1.Type.QUANTITATIVE) { + if (fieldQ.bin) { + return util_1.contains([scale_1.ScaleType.LINEAR, undefined], sType); + } + else { + return util_1.contains([scale_1.ScaleType.LOG, scale_1.ScaleType.POW, scale_1.ScaleType.SQRT, scale_1.ScaleType.QUANTILE, scale_1.ScaleType.QUANTIZE, scale_1.ScaleType.LINEAR, undefined], sType); + } + } + } + return true; + } + } +].map(function (ec) { return new base_1.EncodingConstraintModel(ec); }); +exports.FIELD_CONSTRAINT_INDEX = exports.FIELD_CONSTRAINTS.reduce(function (m, ec) { + m[ec.name()] = ec; + return m; +}, {}); +exports.FIELD_CONSTRAINTS_BY_PROPERTY = exports.FIELD_CONSTRAINTS.reduce(function (index, c) { + for (var _i = 0, _a = c.properties(); _i < _a.length; _i++) { + var prop = _a[_i]; + // Initialize array and use it + index.set(prop, index.get(prop) || []); + index.get(prop).push(c); + } + return index; +}, new propindex_1.PropIndex()); +//# sourceMappingURL=field.js.map \ No newline at end of file diff --git a/build/src/constraint/index.js b/build/src/constraint/index.js new file mode 100644 index 00000000..ff91745c --- /dev/null +++ b/build/src/constraint/index.js @@ -0,0 +1,7 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var encoding = require("./encoding"); +exports.encoding = encoding; +var spec = require("./spec"); +exports.spec = spec; +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/build/src/constraint/spec.js b/build/src/constraint/spec.js new file mode 100644 index 00000000..583d3175 --- /dev/null +++ b/build/src/constraint/spec.js @@ -0,0 +1,752 @@ +"use strict"; +var __extends = (this && this.__extends) || (function () { + var extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +Object.defineProperty(exports, "__esModule", { value: true }); +var aggregate_1 = require("vega-lite/build/src/aggregate"); +var channel_1 = require("vega-lite/build/src/channel"); +var mark_1 = require("vega-lite/build/src/mark"); +var scale_1 = require("vega-lite/build/src/scale"); +var type_1 = require("vega-lite/build/src/type"); +var expandedtype_1 = require("../query/expandedtype"); +var base_1 = require("./base"); +var wildcard_1 = require("../wildcard"); +var property_1 = require("../property"); +var propindex_1 = require("../propindex"); +var util_1 = require("../util"); +var encoding_1 = require("../query/encoding"); +var NONSPATIAL_CHANNELS_INDEX = channel_1.NONSPATIAL_CHANNELS.reduce(function (m, channel) { + m[channel] = true; + return m; +}, {}); +var SpecConstraintModel = (function (_super) { + __extends(SpecConstraintModel, _super); + function SpecConstraintModel(specConstraint) { + return _super.call(this, specConstraint) || this; + } + SpecConstraintModel.prototype.hasAllRequiredPropertiesSpecific = function (specM) { + return util_1.every(this.constraint.properties, function (prop) { + if (prop === property_1.Property.MARK) { + return !wildcard_1.isWildcard(specM.getMark()); + } + // TODO: transform + if (property_1.isEncodingNestedProp(prop)) { + var parent_1 = prop.parent; + var child_1 = prop.child; + return util_1.every(specM.getEncodings(), function (encQ) { + if (!encQ[parent_1]) { + return true; + } + return !wildcard_1.isWildcard(encQ[parent_1][child_1]); + }); + } + if (!property_1.isEncodingProperty(prop)) { + throw new Error('UNIMPLEMENTED'); + } + return util_1.every(specM.getEncodings(), function (encQ) { + if (!encQ[prop]) { + return true; + } + return !wildcard_1.isWildcard(encQ[prop]); + }); + }); + }; + SpecConstraintModel.prototype.satisfy = function (specM, schema, opt) { + // TODO: Re-order logic to optimize the "allowWildcardForProperties" check + if (!this.constraint.allowWildcardForProperties) { + if (!this.hasAllRequiredPropertiesSpecific(specM)) { + return true; + } + } + return this.constraint.satisfy(specM, schema, opt); + }; + return SpecConstraintModel; +}(base_1.AbstractConstraintModel)); +exports.SpecConstraintModel = SpecConstraintModel; +exports.SPEC_CONSTRAINTS = [ + { + name: 'noRepeatedChannel', + description: 'Each encoding channel should only be used once.', + properties: [property_1.Property.CHANNEL], + allowWildcardForProperties: true, + strict: true, + satisfy: function (specM, _, __) { + var usedChannel = {}; + // channel for all encodings should be valid + return util_1.every(specM.getEncodings(), function (encQ) { + if (!wildcard_1.isWildcard(encQ.channel)) { + // If channel is specified, it should no be used already + if (usedChannel[encQ.channel]) { + return false; + } + usedChannel[encQ.channel] = true; + return true; + } + return true; // unspecified channel is valid + }); + } + }, + { + name: 'alwaysIncludeZeroInScaleWithBarMark', + description: 'Do not recommend bar mark if scale does not start at zero', + properties: [property_1.Property.MARK, property_1.Property.SCALE, property_1.getEncodingNestedProp('scale', 'zero'), property_1.Property.CHANNEL, property_1.Property.TYPE], + allowWildcardForProperties: false, + strict: true, + satisfy: function (specM, _, __) { + var mark = specM.getMark(); + var encodings = specM.getEncodings(); + if (mark === mark_1.Mark.BAR) { + for (var _i = 0, encodings_1 = encodings; _i < encodings_1.length; _i++) { + var encQ = encodings_1[_i]; + if (encoding_1.isFieldQuery(encQ) && + (encQ.channel === channel_1.Channel.X || encQ.channel === channel_1.Channel.Y) && + (encQ.type === type_1.Type.QUANTITATIVE) && + (encQ.scale && encQ.scale.zero === false)) { + // TODO: zero shouldn't be manually specified + return false; + } + } + } + return true; + } + }, + { + name: 'autoAddCount', + description: 'Automatically adding count only for plots with only ordinal, binned quantitative, or temporal with timeunit fields.', + properties: [property_1.Property.BIN, property_1.Property.TIMEUNIT, property_1.Property.TYPE, property_1.Property.AUTOCOUNT], + allowWildcardForProperties: true, + strict: false, + satisfy: function (specM, _, __) { + var hasAutoCount = util_1.some(specM.getEncodings(), function (encQ) { return encoding_1.isEnabledAutoCountQuery(encQ); }); + if (hasAutoCount) { + // Auto count should only be applied if all fields are nominal, ordinal, temporal with timeUnit, binned quantitative, or autoCount + return util_1.every(specM.getEncodings(), function (encQ) { + if (encoding_1.isValueQuery(encQ)) { + return false; + } + if (encoding_1.isAutoCountQuery(encQ)) { + return true; + } + switch (encQ.type) { + case type_1.Type.QUANTITATIVE: + return !!encQ.bin; + case type_1.Type.TEMPORAL: + return !!encQ.timeUnit; + case type_1.Type.ORDINAL: + case expandedtype_1.ExpandedType.KEY: + case type_1.Type.NOMINAL: + return true; + } + /* istanbul ignore next */ + throw new Error('Unsupported Type'); + }); + } + else { + var autoCountEncIndex = specM.wildcardIndex.encodingIndicesByProperty.get('autoCount') || []; + var neverHaveAutoCount = util_1.every(autoCountEncIndex, function (index) { + var encQ = specM.getEncodingQueryByIndex(index); + return encoding_1.isAutoCountQuery(encQ) && !wildcard_1.isWildcard(encQ.autoCount); + }); + if (neverHaveAutoCount) { + // If the query surely does not have autoCount + // then one of the field should be + // (1) unbinned quantitative + // (2) temporal without time unit + // (3) nominal or ordinal field + // or at least have potential to be (still ambiguous). + return util_1.some(specM.getEncodings(), function (encQ) { + if ((encoding_1.isFieldQuery(encQ) || encoding_1.isAutoCountQuery(encQ)) && encQ.type === type_1.Type.QUANTITATIVE) { + if (encoding_1.isDisabledAutoCountQuery(encQ)) { + return false; + } + else { + return encoding_1.isFieldQuery(encQ) && (!encQ.bin || wildcard_1.isWildcard(encQ.bin)); + } + } + else if (encoding_1.isFieldQuery(encQ) && encQ.type === type_1.Type.TEMPORAL) { + return !encQ.timeUnit || wildcard_1.isWildcard(encQ.timeUnit); + } + return false; // nominal or ordinal + }); + } + } + return true; // no auto count, no constraint + } + }, + { + name: 'channelPermittedByMarkType', + description: 'Each encoding channel should be supported by the mark type', + properties: [property_1.Property.CHANNEL, property_1.Property.MARK], + allowWildcardForProperties: true, + strict: true, + satisfy: function (specM, _, __) { + var mark = specM.getMark(); + // if mark is unspecified, no need to check + if (wildcard_1.isWildcard(mark)) + return true; + // TODO: can optimize this to detect only what's the changed property if needed. + return util_1.every(specM.getEncodings(), function (encQ) { + // channel unspecified, no need to check + if (wildcard_1.isWildcard(encQ.channel)) + return true; + return channel_1.supportMark(encQ.channel, mark); + }); + } + }, + { + name: 'hasAllRequiredChannelsForMark', + description: 'All required channels for the specified mark should be specified', + properties: [property_1.Property.CHANNEL, property_1.Property.MARK], + allowWildcardForProperties: false, + strict: true, + satisfy: function (specM, _, __) { + var mark = specM.getMark(); + switch (mark) { + case mark_1.Mark.AREA: + case mark_1.Mark.LINE: + return specM.channelUsed(channel_1.Channel.X) && specM.channelUsed(channel_1.Channel.Y); + case mark_1.Mark.TEXT: + return specM.channelUsed(channel_1.Channel.TEXT); + case mark_1.Mark.BAR: + case mark_1.Mark.CIRCLE: + case mark_1.Mark.SQUARE: + case mark_1.Mark.TICK: + case mark_1.Mark.RULE: + return specM.channelUsed(channel_1.Channel.X) || specM.channelUsed(channel_1.Channel.Y); + case mark_1.Mark.POINT: + // This allows generating a point plot if channel was not a wildcard. + return !specM.wildcardIndex.hasProperty(property_1.Property.CHANNEL) || + specM.channelUsed(channel_1.Channel.X) || specM.channelUsed(channel_1.Channel.Y); + } + /* istanbul ignore next */ + throw new Error('hasAllRequiredChannelsForMark not implemented for mark' + JSON.stringify(mark)); + } + }, + { + name: 'omitAggregate', + description: 'Omit aggregate plots.', + properties: [property_1.Property.AGGREGATE, property_1.Property.AUTOCOUNT], + allowWildcardForProperties: true, + strict: false, + satisfy: function (specM, _, __) { + if (specM.isAggregate()) { + return false; + } + return true; + } + }, + { + name: 'omitAggregatePlotWithDimensionOnlyOnFacet', + description: 'Omit aggregate plots with dimensions only on facets as that leads to inefficient use of space.', + properties: [property_1.Property.CHANNEL, property_1.Property.AGGREGATE, property_1.Property.AUTOCOUNT], + allowWildcardForProperties: false, + strict: false, + satisfy: function (specM, _, opt) { + if (specM.isAggregate()) { + var hasNonFacetDim_1 = false, hasDim_1 = false, hasEnumeratedFacetDim_1 = false; + specM.specQuery.encodings.forEach(function (encQ, index) { + if (encoding_1.isValueQuery(encQ) || (encoding_1.isDisabledAutoCountQuery(encQ))) + return; // skip unused field + // FieldQuery & !encQ.aggregate + if (encoding_1.isFieldQuery(encQ) && !encQ.aggregate) { + hasDim_1 = true; + if (util_1.contains([channel_1.Channel.ROW, channel_1.Channel.COLUMN], encQ.channel)) { + if (specM.wildcardIndex.hasEncodingProperty(index, property_1.Property.CHANNEL)) { + hasEnumeratedFacetDim_1 = true; + } + } + else { + hasNonFacetDim_1 = true; + } + } + }); + if (hasDim_1 && !hasNonFacetDim_1) { + if (hasEnumeratedFacetDim_1 || opt.constraintManuallySpecifiedValue) { + return false; + } + } + } + return true; + } + }, + { + name: 'omitAggregatePlotWithoutDimension', + description: 'Aggregate plots without dimension should be omitted', + properties: [property_1.Property.AGGREGATE, property_1.Property.AUTOCOUNT, property_1.Property.BIN, property_1.Property.TIMEUNIT, property_1.Property.TYPE], + allowWildcardForProperties: false, + strict: false, + satisfy: function (specM, _, __) { + if (specM.isAggregate()) { + // TODO relax + return util_1.some(specM.getEncodings(), function (encQ) { + if (encoding_1.isDiscrete(encQ)) { + return true; + } + return false; + }); + } + return true; + } + }, + { + // TODO: we can be smarter and check if bar has occlusion based on profiling statistics + name: 'omitBarLineAreaWithOcclusion', + description: 'Don\'t use bar, line or area to visualize raw plot as they often lead to occlusion.', + properties: [property_1.Property.MARK, property_1.Property.AGGREGATE, property_1.Property.AUTOCOUNT], + allowWildcardForProperties: false, + strict: false, + satisfy: function (specM, _, __) { + if (util_1.contains([mark_1.Mark.BAR, mark_1.Mark.LINE, mark_1.Mark.AREA], specM.getMark())) { + return specM.isAggregate(); + } + return true; + } + }, + { + name: 'omitBarTickWithSize', + description: 'Do not map field to size channel with bar and tick mark', + properties: [property_1.Property.CHANNEL, property_1.Property.MARK], + allowWildcardForProperties: true, + strict: false, + satisfy: function (specM, _, opt) { + var mark = specM.getMark(); + if (util_1.contains([mark_1.Mark.TICK, mark_1.Mark.BAR], mark)) { + if (specM.channelUsed(channel_1.Channel.SIZE)) { + if (opt.constraintManuallySpecifiedValue) { + // If size is used and we constraintManuallySpecifiedValue, + // then the spec violates this constraint. + return false; + } + else { + // Otherwise have to search for the size channel and check if it is enumerated + var encodings = specM.specQuery.encodings; + for (var i = 0; i < encodings.length; i++) { + var encQ = encodings[i]; + if (encQ.channel === channel_1.Channel.SIZE) { + if (specM.wildcardIndex.hasEncodingProperty(i, property_1.Property.CHANNEL)) { + // If enumerated, then this is bad + return false; + } + else { + // If it's manually specified, no need to continue searching, just return. + return true; + } + } + } + } + } + } + return true; // skip + } + }, + { + name: 'omitBarAreaForLogScale', + description: 'Do not use bar and area mark for x and y\'s log scale', + properties: [property_1.Property.MARK, property_1.Property.CHANNEL, property_1.Property.SCALE, property_1.getEncodingNestedProp('scale', 'type'), property_1.Property.TYPE], + allowWildcardForProperties: false, + strict: true, + satisfy: function (specM, _, __) { + var mark = specM.getMark(); + var encodings = specM.getEncodings(); + // TODO: mark or scale type should be enumerated + if (mark === mark_1.Mark.AREA || mark === mark_1.Mark.BAR) { + for (var _i = 0, encodings_2 = encodings; _i < encodings_2.length; _i++) { + var encQ = encodings_2[_i]; + if (encoding_1.isFieldQuery(encQ) && ((encQ.channel === channel_1.Channel.X || encQ.channel === channel_1.Channel.Y) && encQ.scale)) { + var sType = encoding_1.scaleType(encQ); + if (sType === scale_1.ScaleType.LOG) { + return false; + } + } + } + } + return true; + } + }, + { + name: 'omitMultipleNonPositionalChannels', + description: 'Unless manually specified, do not use multiple non-positional encoding channel to avoid over-encoding.', + properties: [property_1.Property.CHANNEL], + allowWildcardForProperties: true, + strict: false, + satisfy: function (specM, _, opt) { + // have to use specM.specQuery.encodings insetad of specM.getEncodings() + // since specM.getEncodings() remove encQ with autoCount===false from the array + // and thus might shift the index + var encodings = specM.specQuery.encodings; + var nonPositionChannelCount = 0; + var hasEnumeratedNonPositionChannel = false; + for (var i = 0; i < encodings.length; i++) { + var encQ = encodings[i]; + if (encoding_1.isValueQuery(encQ) || (encoding_1.isDisabledAutoCountQuery(encQ))) { + continue; // ignore skipped encoding + } + var channel = encQ.channel; + if (!wildcard_1.isWildcard(channel)) { + if (NONSPATIAL_CHANNELS_INDEX[channel + '']) { + nonPositionChannelCount += 1; + if (specM.wildcardIndex.hasEncodingProperty(i, property_1.Property.CHANNEL)) { + hasEnumeratedNonPositionChannel = true; + } + if (nonPositionChannelCount > 1 && + (hasEnumeratedNonPositionChannel || opt.constraintManuallySpecifiedValue)) { + return false; + } + } + } + } + return true; + } + }, + { + name: 'omitNonPositionalOrFacetOverPositionalChannels', + description: 'Do not use non-positional channels unless all positional channels are used', + properties: [property_1.Property.CHANNEL], + allowWildcardForProperties: false, + strict: false, + satisfy: function (specM, _, opt) { + var encodings = specM.specQuery.encodings; + var hasNonPositionalChannelOrFacet = false; + var hasEnumeratedNonPositionOrFacetChannel = false; + var hasX = false, hasY = false; + for (var i = 0; i < encodings.length; i++) { + var encQ = encodings[i]; + if (encoding_1.isValueQuery(encQ) || (encoding_1.isDisabledAutoCountQuery(encQ))) { + continue; // ignore skipped encoding + } + var channel = encQ.channel; + if (channel === channel_1.Channel.X) { + hasX = true; + } + else if (channel === channel_1.Channel.Y) { + hasY = true; + } + else if (!wildcard_1.isWildcard(channel)) { + // All non positional channel / Facet + hasNonPositionalChannelOrFacet = true; + if (specM.wildcardIndex.hasEncodingProperty(i, property_1.Property.CHANNEL)) { + hasEnumeratedNonPositionOrFacetChannel = true; + } + } + } + if (hasEnumeratedNonPositionOrFacetChannel || + (opt.constraintManuallySpecifiedValue && hasNonPositionalChannelOrFacet)) { + return hasX && hasY; + } + return true; + } + }, + { + name: 'omitRaw', + description: 'Omit raw plots.', + properties: [property_1.Property.AGGREGATE, property_1.Property.AUTOCOUNT], + allowWildcardForProperties: false, + strict: false, + satisfy: function (specM, _, __) { + if (!specM.isAggregate()) { + return false; + } + return true; + } + }, + { + name: 'omitRawContinuousFieldForAggregatePlot', + description: 'Aggregate plot should not use raw continuous field as group by values. ' + + '(Quantitative should be binned. Temporal should have time unit.)', + properties: [property_1.Property.AGGREGATE, property_1.Property.AUTOCOUNT, property_1.Property.TIMEUNIT, property_1.Property.BIN, property_1.Property.TYPE], + allowWildcardForProperties: true, + strict: false, + satisfy: function (specM, _, opt) { + if (specM.isAggregate()) { + var encodings = specM.specQuery.encodings; + for (var i = 0; i < encodings.length; i++) { + var encQ = encodings[i]; + if (encoding_1.isValueQuery(encQ) || (encoding_1.isDisabledAutoCountQuery(encQ))) + continue; // skip unused encoding + // TODO: aggregate for ordinal and temporal + if (encoding_1.isFieldQuery(encQ) && encQ.type === type_1.Type.TEMPORAL) { + // Temporal fields should have timeUnit or is still a wildcard + if (!encQ.timeUnit && (specM.wildcardIndex.hasEncodingProperty(i, property_1.Property.TIMEUNIT) || + opt.constraintManuallySpecifiedValue)) { + return false; + } + } + if (encQ.type === type_1.Type.QUANTITATIVE) { + if (encoding_1.isFieldQuery(encQ) && !encQ.bin && !encQ.aggregate) { + // If Raw Q + if (specM.wildcardIndex.hasEncodingProperty(i, property_1.Property.BIN) || + specM.wildcardIndex.hasEncodingProperty(i, property_1.Property.AGGREGATE) || + specM.wildcardIndex.hasEncodingProperty(i, property_1.Property.AUTOCOUNT)) { + // and it's raw from enumeration + return false; + } + if (opt.constraintManuallySpecifiedValue) { + // or if we constraintManuallySpecifiedValue + return false; + } + } + } + } + } + return true; + } + }, + { + name: 'omitRawDetail', + description: 'Do not use detail channel with raw plot.', + properties: [property_1.Property.CHANNEL, property_1.Property.AGGREGATE, property_1.Property.AUTOCOUNT], + allowWildcardForProperties: false, + strict: true, + satisfy: function (specM, _, opt) { + if (specM.isAggregate()) { + return true; + } + return util_1.every(specM.specQuery.encodings, function (encQ, index) { + if (encoding_1.isValueQuery(encQ) || (encoding_1.isDisabledAutoCountQuery(encQ))) + return true; // ignore autoCount field + if (encQ.channel === channel_1.Channel.DETAIL) { + // Detail channel for raw plot is not good, except when its enumerated + // or when it's manually specified but we constraintManuallySpecifiedValue. + if (specM.wildcardIndex.hasEncodingProperty(index, property_1.Property.CHANNEL) || + opt.constraintManuallySpecifiedValue) { + return false; + } + } + return true; + }); + } + }, + { + name: 'omitRepeatedField', + description: 'Each field should be mapped to only one channel', + properties: [property_1.Property.FIELD], + allowWildcardForProperties: true, + strict: false, + satisfy: function (specM, _, opt) { + var fieldUsed = {}; + var fieldEnumerated = {}; + var encodings = specM.specQuery.encodings; + for (var i = 0; i < encodings.length; i++) { + var encQ = encodings[i]; + if (encoding_1.isValueQuery(encQ) || encoding_1.isAutoCountQuery(encQ)) + continue; + var field = void 0; + if (encQ.field && !wildcard_1.isWildcard(encQ.field)) { + field = encQ.field; + } + if (encoding_1.isAutoCountQuery(encQ) && !wildcard_1.isWildcard(encQ.autoCount)) { + field = 'count_*'; + } + if (field) { + if (specM.wildcardIndex.hasEncodingProperty(i, property_1.Property.FIELD)) { + fieldEnumerated[field] = true; + } + // When the field is specified previously, + // if it is enumerated (either previously or in this encQ) + // or if the opt.constraintManuallySpecifiedValue is true, + // then it violates the constraint. + if (fieldUsed[field]) { + if (fieldEnumerated[field] || opt.constraintManuallySpecifiedValue) { + return false; + } + } + fieldUsed[field] = true; + } + } + return true; + } + }, + // TODO: omitShapeWithBin + { + name: 'omitVerticalDotPlot', + description: 'Do not output vertical dot plot.', + properties: [property_1.Property.CHANNEL], + allowWildcardForProperties: true, + strict: false, + satisfy: function (specM, _, __) { + var encodings = specM.getEncodings(); + if (encodings.length === 1 && encodings[0].channel === channel_1.Channel.Y) { + return false; + } + return true; + } + }, + // EXPENSIVE CONSTRAINTS -- check them later! + { + name: 'hasAppropriateGraphicTypeForMark', + description: 'Has appropriate graphic type for mark', + properties: [property_1.Property.CHANNEL, property_1.Property.MARK, property_1.Property.TYPE, property_1.Property.TIMEUNIT, property_1.Property.BIN, property_1.Property.AGGREGATE, property_1.Property.AUTOCOUNT], + allowWildcardForProperties: false, + strict: false, + satisfy: function (specM, _, __) { + var mark = specM.getMark(); + switch (mark) { + case mark_1.Mark.AREA: + case mark_1.Mark.LINE: + if (specM.isAggregate()) { + var xEncQ = specM.getEncodingQueryByChannel(channel_1.Channel.X); + var yEncQ = specM.getEncodingQueryByChannel(channel_1.Channel.Y); + var xIsMeasure = encoding_1.isContinuous(xEncQ); + var yIsMeasure = encoding_1.isContinuous(yEncQ); + // for aggregate line / area, we need at least one group-by axis and one measure axis. + return xEncQ && yEncQ && (xIsMeasure !== yIsMeasure) && + // and the dimension axis should not be nominal + // TODO: make this clause optional + !(encoding_1.isFieldQuery(xEncQ) && !xIsMeasure && util_1.contains(['nominal', 'key'], xEncQ.type)) && + !(encoding_1.isFieldQuery(yEncQ) && !yIsMeasure && util_1.contains(['nominal', 'key'], yEncQ.type)); + // TODO: allow connected scatterplot + } + return true; + case mark_1.Mark.TEXT: + // FIXME correctly when we add text + return true; + case mark_1.Mark.BAR: + case mark_1.Mark.TICK: + // Bar and tick should not use size. + if (specM.channelUsed(channel_1.Channel.SIZE)) { + return false; + } + else { + // Tick and Bar should have one and only one continuous axis + var xEncQ = specM.getEncodingQueryByChannel(channel_1.Channel.X); + var yEncQ = specM.getEncodingQueryByChannel(channel_1.Channel.Y); + var xIsContinuous = encoding_1.isContinuous(xEncQ); + var yIsContinuous = encoding_1.isContinuous(yEncQ); + if (xIsContinuous !== yIsContinuous) { + // TODO: Bar and tick's dimension should not be continuous (quant/time) scale + return true; + } + return false; + } + case mark_1.Mark.CIRCLE: + case mark_1.Mark.POINT: + case mark_1.Mark.SQUARE: + case mark_1.Mark.RULE: + return true; + } + /* istanbul ignore next */ + throw new Error('hasAllRequiredChannelsForMark not implemented for mark' + mark); + } + }, + { + name: 'omitNonLinearScaleTypeWithStack', + description: 'Stacked plot should only use linear scale', + properties: [property_1.Property.CHANNEL, property_1.Property.MARK, property_1.Property.AGGREGATE, property_1.Property.AUTOCOUNT, property_1.Property.SCALE, property_1.getEncodingNestedProp('scale', 'type'), property_1.Property.TYPE], + // TODO: Property.STACK + allowWildcardForProperties: false, + strict: true, + satisfy: function (specM, _, __) { + var stack = specM.stack(); + if (stack) { + for (var _i = 0, _a = specM.getEncodings(); _i < _a.length; _i++) { + var encQ = _a[_i]; + if (encoding_1.isValueQuery(encQ)) + continue; + if (((encoding_1.isFieldQuery(encQ) && !!encQ.aggregate) || encoding_1.isEnabledAutoCountQuery(encQ)) && + encQ.type === type_1.Type.QUANTITATIVE && + util_1.contains([channel_1.Channel.X, channel_1.Channel.Y], encQ.channel)) { + if (encoding_1.scaleType(encQ) !== scale_1.ScaleType.LINEAR) { + return false; + } + } + } + } + return true; + } + }, + { + name: 'omitNonSumStack', + description: 'Stacked plot should use summative aggregation such as sum, count, or distinct', + properties: [property_1.Property.CHANNEL, property_1.Property.MARK, property_1.Property.AGGREGATE, property_1.Property.AUTOCOUNT], + allowWildcardForProperties: false, + strict: false, + satisfy: function (specM, _, __) { + var stack = specM.stack(); + if (stack) { + var measureEncQ = specM.getEncodingQueryByChannel(stack.fieldChannel); + return (encoding_1.isFieldQuery(measureEncQ) && util_1.contains(aggregate_1.SUM_OPS, measureEncQ.aggregate)) || (encoding_1.isAutoCountQuery(measureEncQ) && !!measureEncQ.autoCount); + } + return true; + } + }, + { + name: 'omitTableWithOcclusionIfAutoAddCount', + description: 'Plots without aggregation or autocount where x and y are both discrete should be omitted if autoAddCount is enabled as they often lead to occlusion', + properties: [property_1.Property.CHANNEL, property_1.Property.TYPE, property_1.Property.TIMEUNIT, property_1.Property.BIN, property_1.Property.AGGREGATE, property_1.Property.AUTOCOUNT], + allowWildcardForProperties: false, + strict: false, + satisfy: function (specM, _, opt) { + if (opt.autoAddCount) { + var xEncQ = specM.getEncodingQueryByChannel('x'); + var yEncQ = specM.getEncodingQueryByChannel('y'); + if ((!encoding_1.isFieldQuery(xEncQ) || encoding_1.isDiscrete(xEncQ)) && + (!encoding_1.isFieldQuery(yEncQ) || encoding_1.isDiscrete(yEncQ))) { + if (!specM.isAggregate()) { + return false; + } + else { + return util_1.every(specM.getEncodings(), function (encQ) { + var channel = encQ.channel; + if (channel !== channel_1.Channel.X && channel !== channel_1.Channel.Y && + channel !== channel_1.Channel.ROW && channel !== channel_1.Channel.COLUMN) { + // Non-position fields should not be unaggreated fields + if (encoding_1.isFieldQuery(encQ) && !encQ.aggregate) { + return false; + } + } + return true; + }); + } + } + } + return true; + } + } +].map(function (sc) { return new SpecConstraintModel(sc); }); +// For testing +exports.SPEC_CONSTRAINT_INDEX = exports.SPEC_CONSTRAINTS.reduce(function (m, c) { + m[c.name()] = c; + return m; +}, {}); +var SPEC_CONSTRAINTS_BY_PROPERTY = exports.SPEC_CONSTRAINTS.reduce(function (index, c) { + for (var _i = 0, _a = c.properties(); _i < _a.length; _i++) { + var prop = _a[_i]; + // Initialize array and use it + index.set(prop, index.get(prop) || []); + index.get(prop).push(c); + } + return index; +}, new propindex_1.PropIndex()); +/** + * Check all encoding constraints for a particular property and index tuple + */ +function checkSpec(prop, wildcard, specM, schema, opt) { + // Check encoding constraint + var specConstraints = SPEC_CONSTRAINTS_BY_PROPERTY.get(prop) || []; + for (var _i = 0, specConstraints_1 = specConstraints; _i < specConstraints_1.length; _i++) { + var c = specConstraints_1[_i]; + // Check if the constraint is enabled + if (c.strict() || !!opt[c.name()]) { + // For strict constraint, or enabled non-strict, check the constraints + var satisfy = c.satisfy(specM, schema, opt); + if (!satisfy) { + var violatedConstraint = '(spec) ' + c.name(); + /* istanbul ignore if */ + if (opt.verbose) { + console.log(violatedConstraint + ' failed with ' + specM.toShorthand() + ' for ' + wildcard.name); + } + return violatedConstraint; + } + } + } + return null; +} +exports.checkSpec = checkSpec; +//# sourceMappingURL=spec.js.map \ No newline at end of file diff --git a/build/src/constraint/value.js b/build/src/constraint/value.js new file mode 100644 index 00000000..ea9fe99e --- /dev/null +++ b/build/src/constraint/value.js @@ -0,0 +1,31 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var property_1 = require("../property"); +var propindex_1 = require("../propindex"); +var util_1 = require("../util"); +var base_1 = require("./base"); +exports.VALUE_CONSTRAINTS = [ + { + name: 'doesNotSupportConstantValue', + description: 'row, column, x, y, and detail should not work with constant values.', + properties: [property_1.Property.TYPE, property_1.Property.AGGREGATE], + allowWildcardForProperties: false, + strict: true, + satisfy: function (valueQ, _, __, ___) { + return !(util_1.contains(['row', 'column', 'x', 'y', 'detail'], valueQ.channel)); + } + } +].map(function (ec) { return new base_1.EncodingConstraintModel(ec); }); +exports.VALUE_CONSTRAINT_INDEX = exports.VALUE_CONSTRAINTS.reduce(function (m, ec) { + m[ec.name()] = ec; + return m; +}, {}); +exports.VALUE_CONSTRAINTS_BY_PROPERTY = exports.VALUE_CONSTRAINTS.reduce(function (index, c) { + for (var _i = 0, _a = c.properties(); _i < _a.length; _i++) { + var prop = _a[_i]; + index.set(prop, index.get(prop) || []); + index.get(prop).push(c); + } + return index; +}, new propindex_1.PropIndex()); +//# sourceMappingURL=value.js.map \ No newline at end of file diff --git a/build/src/query/encoding.js b/build/src/query/encoding.js new file mode 100644 index 00000000..c48d2756 --- /dev/null +++ b/build/src/query/encoding.js @@ -0,0 +1,133 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var vlFieldDef = require("vega-lite/build/src/fielddef"); +var expandedtype_1 = require("./expandedtype"); +var type_1 = require("vega-lite/build/src/compile/scale/type"); +var wildcard_1 = require("../wildcard"); +function isValueQuery(encQ) { + return encQ !== null && encQ !== undefined && encQ['value']; +} +exports.isValueQuery = isValueQuery; +function isFieldQuery(encQ) { + return encQ !== null && encQ !== undefined && encQ['field']; +} +exports.isFieldQuery = isFieldQuery; +function isAutoCountQuery(encQ) { + return encQ !== null && encQ !== undefined && 'autoCount' in encQ; +} +exports.isAutoCountQuery = isAutoCountQuery; +function isDisabledAutoCountQuery(encQ) { + return isAutoCountQuery(encQ) && encQ.autoCount === false; +} +exports.isDisabledAutoCountQuery = isDisabledAutoCountQuery; +function isEnabledAutoCountQuery(encQ) { + return isAutoCountQuery(encQ) && encQ.autoCount === true; +} +exports.isEnabledAutoCountQuery = isEnabledAutoCountQuery; +function toFieldDef(encQ, props) { + if (props === void 0) { props = ['aggregate', 'bin', 'timeUnit', 'field', 'type']; } + if (isFieldQuery(encQ)) { + return props.reduce(function (fieldDef, prop) { + if (wildcard_1.isWildcard(encQ[prop])) { + throw new Error("Cannot convert " + JSON.stringify(encQ) + " to fielddef: " + prop + " is wildcard"); + } + else if (encQ[prop] !== undefined) { + fieldDef[prop] = encQ[prop]; + } + return fieldDef; + }, {}); + } + else { + if (encQ.autoCount === false) { + throw new Error("Cannot convert {autoCount: false} into a field def"); + } + else { + return props.reduce(function (fieldDef, prop) { + if (wildcard_1.isWildcard(encQ[prop])) { + throw new Error("Cannot convert " + JSON.stringify(encQ) + " to fielddef: " + prop + " is wildcard"); + } + switch (prop) { + case 'type': + fieldDef.type = 'quantitative'; + break; + case 'aggregate': + fieldDef.aggregate = 'count'; + break; + } + return fieldDef; + }, {}); + } + } +} +exports.toFieldDef = toFieldDef; +/** + * Is a field query continuous field? + * This method is applicable only for fieldQuery without wildcard + */ +function isContinuous(encQ) { + return isFieldQuery(encQ) && vlFieldDef.isContinuous(toFieldDef(encQ, ['bin', 'timeUnit', 'field', 'type'])); +} +exports.isContinuous = isContinuous; +/** + * Is a field query discrete field? + * This method is applicable only for fieldQuery without wildcard + */ +function isDiscrete(encQ) { + return isFieldQuery(encQ) && vlFieldDef.isDiscrete(toFieldDef(encQ, ['bin', 'timeUnit', 'field', 'type'])); +} +exports.isDiscrete = isDiscrete; +/** + * Returns the true scale type of an encoding. + * @returns {ScaleType} If the scale type was not specified, it is inferred from the encoding's Type. + * @returns {undefined} If the scale type was not specified and Type (or TimeUnit if applicable) is a Wildcard, there is no clear scale type + */ +function scaleType(fieldQ) { + var scale = fieldQ.scale === true || fieldQ.scale === wildcard_1.SHORT_WILDCARD ? {} : fieldQ.scale || {}; + var type = fieldQ.type, channel = fieldQ.channel, timeUnit = fieldQ.timeUnit, bin = fieldQ.bin; + // HACK: All of markType, and scaleConfig only affect + // sub-type of ordinal to quantitative scales (point or band) + // Currently, most of scaleType usage in CompassQL doesn't care about this subtle difference. + // Thus, instead of making this method requiring the global mark, + // we will just call it with mark = undefined . + // Thus, currently, we will always get a point scale unless a CompassQuery specifies band. + var markType = undefined; + var scaleConfig = {}; + if (wildcard_1.isWildcard(scale.type) || wildcard_1.isWildcard(type) || wildcard_1.isWildcard(channel) || wildcard_1.isWildcard(bin)) { + return undefined; + } + // If scale type is specified, then use scale.type + if (scale.type) { + return scale.type; + } + var rangeStep = undefined; + // Note: Range step currently does not matter as we don't pass mark into compileScaleType anyway. + // However, if we pass mark, we could use a rule like the following. + // I also have few test cases listed in encoding.test.ts + // if (channel === 'x' || channel === 'y') { + // if (isWildcard(scale.rangeStep)) { + // if (isShortWildcard(scale.rangeStep)) { + // return undefined; + // } else if (scale.rangeStep.enum) { + // const e = scale.rangeStep.enum; + // // if enumerated value contains enum then we can't be sure + // if (contains(e, undefined) || contains(e, null)) { + // return undefined; + // } + // rangeStep = e[0]; + // } + // } + // } + // if type is fixed and it's not temporal, we can ignore time unit. + if (type === 'temporal' && wildcard_1.isWildcard(timeUnit)) { + return undefined; + } + // if type is fixed and it's not quantitative, we can ignore bin + if (type === 'quantitative' && wildcard_1.isWildcard(bin)) { + return undefined; + } + var vegaLiteType = type === expandedtype_1.ExpandedType.KEY ? 'nominal' : type; + var fieldDef = { type: vegaLiteType, timeUnit: timeUnit, bin: bin }; + return type_1.scaleType(scale.type, channel, fieldDef, markType, rangeStep, scaleConfig); +} +exports.scaleType = scaleType; +//# sourceMappingURL=encoding.js.map \ No newline at end of file diff --git a/build/src/query/expandedtype.js b/build/src/query/expandedtype.js new file mode 100644 index 00000000..e6ec878e --- /dev/null +++ b/build/src/query/expandedtype.js @@ -0,0 +1,16 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var type_1 = require("vega-lite/build/src/type"); +var ExpandedType; +(function (ExpandedType) { + ExpandedType.QUANTITATIVE = type_1.Type.QUANTITATIVE; + ExpandedType.ORDINAL = type_1.Type.ORDINAL; + ExpandedType.TEMPORAL = type_1.Type.TEMPORAL; + ExpandedType.NOMINAL = type_1.Type.NOMINAL; + ExpandedType.KEY = 'key'; +})(ExpandedType = exports.ExpandedType || (exports.ExpandedType = {})); +function isDiscrete(fieldType) { + return fieldType === type_1.Type.ORDINAL || fieldType === type_1.Type.NOMINAL || fieldType === ExpandedType.KEY; +} +exports.isDiscrete = isDiscrete; +//# sourceMappingURL=expandedtype.js.map \ No newline at end of file diff --git a/build/src/query/groupby.js b/build/src/query/groupby.js new file mode 100644 index 00000000..9e8f47a3 --- /dev/null +++ b/build/src/query/groupby.js @@ -0,0 +1,74 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var util_1 = require("datalib/src/util"); +var shorthand_1 = require("./shorthand"); +var property_1 = require("../property"); +var propindex_1 = require("../propindex"); +var util_2 = require("../util"); +exports.REPLACE_BLANK_FIELDS = { '*': '' }; +exports.REPLACE_XY_CHANNELS = { x: 'xy', y: 'xy' }; +exports.REPLACE_FACET_CHANNELS = { row: 'facet', column: 'facet' }; +exports.REPLACE_MARK_STYLE_CHANNELS = { color: 'style', opacity: 'style', shape: 'style', size: 'style' }; +function isExtendedGroupBy(g) { + return util_1.isObject(g) && !!g['property']; +} +exports.isExtendedGroupBy = isExtendedGroupBy; +function parseGroupBy(groupBy, include, replaceIndex) { + include = include || new propindex_1.PropIndex(); + replaceIndex = replaceIndex || new propindex_1.PropIndex(); + groupBy.forEach(function (grpBy) { + if (isExtendedGroupBy(grpBy)) { + include.setByKey(grpBy.property, true); + replaceIndex.setByKey(grpBy.property, grpBy.replace); + } + else { + include.setByKey(grpBy, true); + } + }); + return { + include: include, + replaceIndex: replaceIndex, + replacer: shorthand_1.getReplacerIndex(replaceIndex) + }; +} +exports.parseGroupBy = parseGroupBy; +function toString(groupBy) { + if (util_1.isArray(groupBy)) { + return groupBy.map(function (g) { + if (isExtendedGroupBy(g)) { + if (g.replace) { + var replaceIndex_1 = util_2.keys(g.replace).reduce(function (index, valFrom) { + var valTo = g.replace[valFrom]; + (index[valTo] = index[valTo] || []).push(valFrom); + return index; + }, {}); + return g.property + '[' + util_2.keys(replaceIndex_1).map(function (valTo) { + var valsFrom = replaceIndex_1[valTo].sort(); + return valsFrom.join(',') + '=>' + valTo; + }).join(';') + ']'; + } + return g.property; + } + return g; + }).join(','); + } + else { + return groupBy; + } +} +exports.toString = toString; +exports.GROUP_BY_FIELD_TRANSFORM = [ + property_1.Property.FIELD, property_1.Property.TYPE, + property_1.Property.AGGREGATE, property_1.Property.BIN, property_1.Property.TIMEUNIT, property_1.Property.STACK +]; +exports.GROUP_BY_ENCODING = exports.GROUP_BY_FIELD_TRANSFORM.concat([ + { + property: property_1.Property.CHANNEL, + replace: { + 'x': 'xy', 'y': 'xy', + 'color': 'style', 'size': 'style', 'shape': 'style', 'opacity': 'style', + 'row': 'facet', 'column': 'facet' + } + } +]); +//# sourceMappingURL=groupby.js.map \ No newline at end of file diff --git a/build/src/query/index.js b/build/src/query/index.js new file mode 100644 index 00000000..4bf459b1 --- /dev/null +++ b/build/src/query/index.js @@ -0,0 +1,10 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.encoding = require("./encoding"); +var normalize_1 = require("./normalize"); +exports.normalize = normalize_1.normalize; +exports.groupBy = require("./groupby"); +exports.shorthand = require("./shorthand"); +exports.spec = require("./spec"); +exports.transform = require("./transform"); +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/build/src/query/normalize.js b/build/src/query/normalize.js new file mode 100644 index 00000000..09c8f6fc --- /dev/null +++ b/build/src/query/normalize.js @@ -0,0 +1,30 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var util_1 = require("../util"); +/** + * Normalize the non-nested version of the query to a standardize nested + */ +function normalize(q) { + if (q.groupBy) { + var nest = { + groupBy: q.groupBy + }; + if (q.orderBy) { + nest.orderGroupBy = q.orderBy; + } + var normalizedQ = { + spec: util_1.duplicate(q.spec), + nest: [nest], + }; + if (q.chooseBy) { + normalizedQ.chooseBy = q.chooseBy; + } + if (q.config) { + normalizedQ.config = q.config; + } + return normalizedQ; + } + return util_1.duplicate(q); // We will cause side effect to q.spec in SpecQueryModel.build +} +exports.normalize = normalize; +//# sourceMappingURL=normalize.js.map \ No newline at end of file diff --git a/build/src/query/query.js b/build/src/query/query.js new file mode 100644 index 00000000..c57121b1 --- /dev/null +++ b/build/src/query/query.js @@ -0,0 +1,3 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +//# sourceMappingURL=query.js.map \ No newline at end of file diff --git a/build/src/query/shorthand.js b/build/src/query/shorthand.js new file mode 100644 index 00000000..f49e74f1 --- /dev/null +++ b/build/src/query/shorthand.js @@ -0,0 +1,465 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var aggregate_1 = require("vega-lite/build/src/aggregate"); +var channel_1 = require("vega-lite/build/src/channel"); +var timeunit_1 = require("vega-lite/build/src/timeunit"); +var type_1 = require("vega-lite/build/src/type"); +var util_1 = require("datalib/src/util"); +var encoding_1 = require("./encoding"); +var spec_1 = require("./spec"); +var wildcard_1 = require("../wildcard"); +var property_1 = require("../property"); +var propindex_1 = require("../propindex"); +var util_2 = require("../util"); +function getReplacerIndex(replaceIndex) { + return replaceIndex.map(function (r) { return getReplacer(r); }); +} +exports.getReplacerIndex = getReplacerIndex; +function getReplacer(replace) { + return function (s) { + if (replace[s] !== undefined) { + return replace[s]; + } + return s; + }; +} +exports.getReplacer = getReplacer; +function value(v, replacer) { + if (wildcard_1.isWildcard(v)) { + // Return the enum array if it's a full wildcard, or just return SHORT_WILDCARD for short ones. + if (!wildcard_1.isShortWildcard(v) && v.enum) { + return wildcard_1.SHORT_WILDCARD + JSON.stringify(v.enum); + } + else { + return wildcard_1.SHORT_WILDCARD; + } + } + if (replacer) { + return replacer(v); + } + return v; +} +exports.value = value; +function replace(v, replacer) { + if (replacer) { + return replacer(v); + } + return v; +} +exports.replace = replace; +exports.REPLACE_NONE = new propindex_1.PropIndex(); +exports.INCLUDE_ALL = +// FIXME: remove manual TRANSFORM concat once we really support enumerating transform. +[].concat(property_1.DEFAULT_PROP_PRECEDENCE, property_1.SORT_PROPS, [property_1.Property.TRANSFORM, property_1.Property.STACK]) + .reduce(function (pi, prop) { return pi.set(prop, true); }, new propindex_1.PropIndex()); +function vlSpec(vlspec, include, replace) { + if (include === void 0) { include = exports.INCLUDE_ALL; } + if (replace === void 0) { replace = exports.REPLACE_NONE; } + var specQ = spec_1.fromSpec(vlspec); + return spec(specQ, include, replace); +} +exports.vlSpec = vlSpec; +exports.PROPERTY_SUPPORTED_CHANNELS = { + axis: { x: true, y: true, row: true, column: true }, + legend: { color: true, opacity: true, size: true, shape: true }, + scale: { x: true, y: true, color: true, opacity: true, row: true, column: true, size: true, shape: true }, + sort: { x: true, y: true, path: true, order: true } +}; +/** + * Returns a shorthand for a spec query + * @param specQ a spec query + * @param include Dict Set listing property types (key) to be included in the shorthand + * @param replace Dictionary of replace function for values of a particular property type (key) + */ +function spec(specQ, include, replace) { + if (include === void 0) { include = exports.INCLUDE_ALL; } + if (replace === void 0) { replace = exports.REPLACE_NONE; } + var parts = []; + if (include.get(property_1.Property.MARK)) { + parts.push(value(specQ.mark, replace.get(property_1.Property.MARK))); + } + if (specQ.transform && specQ.transform.length > 0) { + parts.push('transform:' + JSON.stringify(specQ.transform)); + } + // TODO: extract this to its own stack method + if (include.get(property_1.Property.STACK)) { + var _stack = spec_1.stack(specQ); + if (_stack) { + // TODO: Refactor this once we have child stack property. + // Exclude type since we don't care about type in stack + var includeExceptType = include.duplicate().set('type', false); + var field = fieldDef(_stack.fieldEncQ, includeExceptType, replace); + var groupby = fieldDef(_stack.groupByEncQ, includeExceptType, replace); + parts.push('stack={field:' + field + ',' + + (groupby ? 'by:' + groupby + ',' : '') + + 'offset:' + _stack.offset + '}'); + } + } + if (specQ.encodings) { + var encodings = specQ.encodings.reduce(function (encQs, encQ) { + // Exclude encoding mapping with autoCount=false as they are basically disabled. + if (!encoding_1.isDisabledAutoCountQuery(encQ)) { + var str = encoding(encQ, include, replace); + if (str) { + encQs.push(str); + } + } + return encQs; + }, []) + .sort() // sort at the end to ignore order + .join('|'); + if (encodings) { + parts.push(encodings); + } + } + return parts.join('|'); +} +exports.spec = spec; +/** + * Returns a shorthand for an encoding query + * @param encQ an encoding query + * @param include Dict Set listing property types (key) to be included in the shorthand + * @param replace Dictionary of replace function for values of a particular property type (key) + */ +function encoding(encQ, include, replace) { + if (include === void 0) { include = exports.INCLUDE_ALL; } + if (replace === void 0) { replace = exports.REPLACE_NONE; } + var parts = []; + if (include.get(property_1.Property.CHANNEL)) { + parts.push(value(encQ.channel, replace.get(property_1.Property.CHANNEL))); + } + if (encoding_1.isFieldQuery(encQ)) { + var fieldDefStr = fieldDef(encQ, include, replace); + if (fieldDefStr) { + parts.push(fieldDefStr); + } + } + else if (encoding_1.isValueQuery(encQ)) { + parts.push(encQ.value); + } + return parts.join(':'); +} +exports.encoding = encoding; +/** + * Returns a field definition shorthand for an encoding query + * @param encQ an encoding query + * @param include Dict Set listing property types (key) to be included in the shorthand + * @param replace Dictionary of replace function for values of a particular property type (key) + */ +function fieldDef(encQ, include, replacer) { + if (include === void 0) { include = exports.INCLUDE_ALL; } + if (replacer === void 0) { replacer = exports.REPLACE_NONE; } + if (include.get(property_1.Property.AGGREGATE) && encoding_1.isDisabledAutoCountQuery(encQ)) { + return '-'; + } + var fn = func(encQ, include, replacer); + var props = fieldDefProps(encQ, include, replacer); + var fieldAndParams; + if (encoding_1.isFieldQuery(encQ)) { + // field + fieldAndParams = include.get('field') ? value(encQ.field, replacer.get('field')) : '...'; + // type + if (include.get(property_1.Property.TYPE)) { + if (wildcard_1.isWildcard(encQ.type)) { + fieldAndParams += ',' + value(encQ.type, replacer.get(property_1.Property.TYPE)); + } + else { + var typeShort = ((encQ.type || type_1.Type.QUANTITATIVE) + '').substr(0, 1); + fieldAndParams += ',' + value(typeShort, replacer.get(property_1.Property.TYPE)); + } + } + // encoding properties + fieldAndParams += props.map(function (p) { + var val = p.value instanceof Array ? '[' + p.value + ']' : p.value; + return ',' + p.key + '=' + val; + }).join(''); + } + else if (encoding_1.isAutoCountQuery(encQ)) { + fieldAndParams = '*,q'; + } + if (!fieldAndParams) { + return null; + } + if (fn) { + var fnPrefix = util_1.isString(fn) ? fn : wildcard_1.SHORT_WILDCARD + + (util_2.keys(fn).length > 0 ? JSON.stringify(fn) : ''); + return fnPrefix + '(' + fieldAndParams + ')'; + } + return fieldAndParams; +} +exports.fieldDef = fieldDef; +/** + * Return function part of + */ +function func(fieldQ, include, replacer) { + if (include.get(property_1.Property.AGGREGATE) && fieldQ.aggregate && !wildcard_1.isWildcard(fieldQ.aggregate)) { + return replace(fieldQ.aggregate, replacer.get(property_1.Property.AGGREGATE)); + } + else if (include.get(property_1.Property.AGGREGATE) && encoding_1.isEnabledAutoCountQuery(fieldQ)) { + // autoCount is considered a part of aggregate + return replace('count', replacer.get(property_1.Property.AGGREGATE)); + ; + } + else if (include.get(property_1.Property.TIMEUNIT) && fieldQ.timeUnit && !wildcard_1.isWildcard(fieldQ.timeUnit)) { + return replace(fieldQ.timeUnit, replacer.get(property_1.Property.TIMEUNIT)); + } + else if (include.get(property_1.Property.BIN) && fieldQ.bin && !wildcard_1.isWildcard(fieldQ.bin)) { + return 'bin'; + } + else { + var fn = null; + for (var _i = 0, _a = [property_1.Property.AGGREGATE, property_1.Property.AUTOCOUNT, property_1.Property.TIMEUNIT, property_1.Property.BIN]; _i < _a.length; _i++) { + var prop = _a[_i]; + var val = fieldQ[prop]; + if (include.get(prop) && fieldQ[prop] && wildcard_1.isWildcard(val)) { + // assign fnEnumIndex[prop] = array of enum values or just "?" if it is SHORT_WILDCARD + fn = fn || {}; + fn[prop] = wildcard_1.isShortWildcard(val) ? val : val.enum; + } + } + if (fn && fieldQ.hasFn) { + fn.hasFn = true; + } + return fn; + } +} +/** + * Return key-value of parameters of field defs + */ +function fieldDefProps(fieldQ, include, replacer) { + /** Encoding properties e.g., Scale, Axis, Legend */ + var props = []; + // Parameters of function such as bin will be just top-level properties + if (!util_2.isBoolean(fieldQ.bin) && !wildcard_1.isShortWildcard(fieldQ.bin)) { + var bin = fieldQ.bin; + for (var child in bin) { + var prop = property_1.getEncodingNestedProp('bin', child); + if (prop && include.get(prop) && bin[child] !== undefined) { + props.push({ + key: child, + value: value(bin[child], replacer.get(prop)) + }); + } + } + // Sort to make sure that parameter are ordered consistently + props.sort(function (a, b) { return a.key.localeCompare(b.key); }); + } + for (var _i = 0, _a = [property_1.Property.SCALE, property_1.Property.SORT, property_1.Property.AXIS, property_1.Property.LEGEND]; _i < _a.length; _i++) { + var parent_1 = _a[_i]; + if (!wildcard_1.isWildcard(fieldQ.channel) && !exports.PROPERTY_SUPPORTED_CHANNELS[parent_1][fieldQ.channel]) { + continue; + } + if (include.get(parent_1) && fieldQ[parent_1] !== undefined) { + var parentValue = fieldQ[parent_1]; + if (util_2.isBoolean(parentValue) || parentValue === null) { + // `scale`, `axis`, `legend` can be false/null. + props.push({ + key: parent_1 + '', + value: parentValue || false // return true or false (false if null) + }); + } + else if (util_1.isString(parentValue)) { + // `sort` can be a string (ascending/descending). + props.push({ + key: parent_1 + '', + value: replace(JSON.stringify(parentValue), replacer.get(parent_1)) + }); + } + else { + var nestedPropChildren = []; + for (var child in parentValue) { + var nestedProp = property_1.getEncodingNestedProp(parent_1, child); + if (nestedProp && include.get(nestedProp) && parentValue[child] !== undefined) { + nestedPropChildren.push({ + key: child, + value: value(parentValue[child], replacer.get(nestedProp)) + }); + } + } + if (nestedPropChildren.length > 0) { + var nestedPropObject = nestedPropChildren.sort(function (a, b) { return a.key.localeCompare(b.key); }) + .reduce(function (o, item) { + o[item.key] = item.value; + return o; + }, {}); + // Sort to make sure that parameter are ordered consistently + props.push({ + key: parent_1 + '', + value: JSON.stringify(nestedPropObject) + }); + } + } + } + } + return props; +} +var CHANNEL_INDEX = util_1.toMap(channel_1.CHANNELS); +var AGGREGATE_OP_INDEX = util_1.toMap(aggregate_1.AGGREGATE_OPS); +var SINGLE_TIMEUNIT_INDEX = util_1.toMap(timeunit_1.SINGLE_TIMEUNITS); +var MULTI_TIMEUNIT_INDEX = util_1.toMap(timeunit_1.MULTI_TIMEUNITS); +function parse(shorthand) { + // TODO(https://github.com/uwdata/compassql/issues/259): + // Do not split directly, but use an upgraded version of `getClosingBraceIndex()` + var splitShorthand = shorthand.split('|'); + var specQ = { mark: splitShorthand[0], encodings: [] }; + for (var i = 1; i < splitShorthand.length; i++) { + var part = splitShorthand[i]; + var splitPart = splitWithTail(part, ':', 1); + var splitPartKey = splitPart[0]; + var splitPartValue = splitPart[1]; + if (CHANNEL_INDEX[splitPartKey] || splitPartKey === '?') { + var encQ = shorthandParser.encoding(splitPartKey, splitPartValue); + specQ.encodings.push(encQ); + continue; + } + if (splitPartKey === 'transform') { + specQ.transform = JSON.parse(splitPartValue); + continue; + } + } + return specQ; +} +exports.parse = parse; +/** + * Split a string n times into substrings with the specified delimiter and return them as an array. + * @param str The string to be split + * @param delim The delimiter string used to separate the string + * @param number The value used to determine how many times the string is split + */ +function splitWithTail(str, delim, count) { + var result = []; + var lastIndex = 0; + for (var i = 0; i < count; i++) { + var indexOfDelim = str.indexOf(delim, lastIndex); + if (indexOfDelim !== -1) { + result.push(str.substring(lastIndex, indexOfDelim)); + lastIndex = indexOfDelim + 1; + } + else { + break; + } + } + result.push(str.substr(lastIndex)); + // If the specified count is greater than the number of delimiters that exist in the string, + // an empty string will be pushed count minus number of delimiter occurence times. + if (result.length !== count + 1) { + while (result.length !== count + 1) { + result.push(''); + } + } + return result; +} +exports.splitWithTail = splitWithTail; +var shorthandParser; +(function (shorthandParser) { + function encoding(channel, fieldDefShorthand) { + var encQ = { channel: channel }; + if (fieldDefShorthand.indexOf('(') !== -1) { + encQ = fn(encQ, fieldDefShorthand); + } + else { + encQ = rawFieldDef(encQ, splitWithTail(fieldDefShorthand, ',', 2)); + } + return encQ; + } + shorthandParser.encoding = encoding; + function rawFieldDef(fieldQ, fieldDefPart) { + fieldQ.field = fieldDefPart[0]; + fieldQ.type = type_1.getFullName(fieldDefPart[1].toUpperCase()) || '?'; + var partParams = fieldDefPart[2]; + var closingBraceIndex = 0; + var i = 0; + while (i < partParams.length) { + var propEqualSignIndex = partParams.indexOf('=', i); + var parsedValue = void 0; + if (propEqualSignIndex !== -1) { + var prop = partParams.substring(i, propEqualSignIndex); + if (partParams[i + prop.length + 1] === '{') { + var openingBraceIndex = i + prop.length + 1; + closingBraceIndex = getClosingIndex(openingBraceIndex, partParams, '}'); + var value_1 = partParams.substring(openingBraceIndex, closingBraceIndex + 1); + parsedValue = JSON.parse(value_1); + // index after next comma + i = closingBraceIndex + 2; + } + else if (partParams[i + prop.length + 1] === '[') { + // find closing square bracket + var openingBracketIndex = i + prop.length + 1; + var closingBracketIndex = getClosingIndex(openingBracketIndex, partParams, ']'); + var value_2 = partParams.substring(openingBracketIndex, closingBracketIndex + 1); + parsedValue = JSON.parse(value_2); + // index after next comma + i = closingBracketIndex + 2; + } + else { + var propIndex = i; + // Substring until the next comma (or end of the string) + var nextCommaIndex = partParams.indexOf(',', i + prop.length); + if (nextCommaIndex === -1) { + nextCommaIndex = partParams.length; + } + // index after next comma + i = nextCommaIndex + 1; + parsedValue = JSON.parse(partParams.substring(propIndex + prop.length + 1, nextCommaIndex)); + } + if (property_1.hasNestedProperty(prop)) { + fieldQ[prop] = parsedValue; + } + else { + // prop is a property of the aggregation function such as bin + fieldQ.bin[prop] = parsedValue; + } + } + else { + // something is wrong with the format of the partParams + // exits loop if don't have then infintie loop + break; + } + } + return fieldQ; + } + shorthandParser.rawFieldDef = rawFieldDef; + function getClosingIndex(openingBraceIndex, str, closingChar) { + for (var i = openingBraceIndex; i < str.length; i++) { + if (str[i] === closingChar) { + return i; + } + } + } + shorthandParser.getClosingIndex = getClosingIndex; + function fn(fieldQ, fieldDefShorthand) { + // Aggregate, Bin, TimeUnit as wildcard case + if (fieldDefShorthand[0] === '?') { + var closingBraceIndex = getClosingIndex(1, fieldDefShorthand, '}'); + var fnEnumIndex = JSON.parse(fieldDefShorthand.substring(1, closingBraceIndex + 1)); + for (var encodingProperty in fnEnumIndex) { + if (util_2.isArray(fnEnumIndex[encodingProperty])) { + fieldQ[encodingProperty] = { enum: fnEnumIndex[encodingProperty] }; + } + else { + fieldQ[encodingProperty] = fnEnumIndex[encodingProperty]; + } + } + return rawFieldDef(fieldQ, splitWithTail(fieldDefShorthand.substring(closingBraceIndex + 2, fieldDefShorthand.length - 1), ',', 2)); + } + else { + var func_1 = fieldDefShorthand.substring(0, fieldDefShorthand.indexOf('(')); + var insideFn = fieldDefShorthand.substring(func_1.length + 1, fieldDefShorthand.length - 1); + var insideFnParts = splitWithTail(insideFn, ',', 2); + if (AGGREGATE_OP_INDEX[func_1]) { + fieldQ.aggregate = func_1; + return rawFieldDef(fieldQ, insideFnParts); + } + else if (MULTI_TIMEUNIT_INDEX[func_1] || SINGLE_TIMEUNIT_INDEX[func_1]) { + fieldQ.timeUnit = func_1; + return rawFieldDef(fieldQ, insideFnParts); + } + else if (func_1 === 'bin') { + fieldQ.bin = {}; + return rawFieldDef(fieldQ, insideFnParts); + } + } + } + shorthandParser.fn = fn; +})(shorthandParser = exports.shorthandParser || (exports.shorthandParser = {})); +//# sourceMappingURL=shorthand.js.map \ No newline at end of file diff --git a/build/src/query/spec.js b/build/src/query/spec.js new file mode 100644 index 00000000..47cdb86c --- /dev/null +++ b/build/src/query/spec.js @@ -0,0 +1,129 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var channel_1 = require("vega-lite/build/src/channel"); +var wildcard_1 = require("../wildcard"); +var property_1 = require("../property"); +var util_1 = require("../util"); +var encoding_1 = require("./encoding"); +var util_2 = require("datalib/src/util"); +/** + * Convert a Vega-Lite's ExtendedUnitSpec into a CompassQL's SpecQuery + * @param {ExtendedUnitSpec} spec + * @returns + */ +function fromSpec(spec) { + return util_1.extend(spec.data ? { data: spec.data } : {}, spec.transform ? { transform: spec.transform } : {}, { + mark: spec.mark, + encodings: util_1.keys(spec.encoding).map(function (channel) { + var encQ = { channel: channel }; + var channelDef = spec.encoding[channel]; + for (var prop in channelDef) { + if (property_1.isEncodingTopLevelProperty(prop) && channelDef[prop] !== undefined) { + // Currently bin, scale, axis, legend only support boolean, but not null. + // Therefore convert null to false. + if (util_1.contains(['bin', 'scale', 'axis', 'legend'], prop) && channelDef[prop] === null) { + encQ[prop] = false; + } + else { + encQ[prop] = channelDef[prop]; + } + } + } + return encQ; + }) + }, spec.config ? { config: spec.config } : {}); +} +exports.fromSpec = fromSpec; +function isAggregate(specQ) { + return util_1.some(specQ.encodings, function (encQ) { + return (encoding_1.isFieldQuery(encQ) && !wildcard_1.isWildcard(encQ.aggregate) && !!encQ.aggregate) || encoding_1.isEnabledAutoCountQuery(encQ); + }); +} +exports.isAggregate = isAggregate; +/** + * @return the stack offset type for the specQuery + */ +function stack(specQ) { + var config = specQ.config; + var stacked = config ? config.stack : undefined; + // Should not have stack explicitly disabled + if (util_1.contains(['none', null, false], stacked)) { + return null; + } + // Should have stackable mark + if (!util_1.contains(['bar', 'area'], specQ.mark)) { + return null; + } + // Should be aggregate plot + if (!isAggregate(specQ)) { + return null; + } + var stackBy = specQ.encodings.reduce(function (sc, encQ) { + if (util_1.contains(channel_1.STACK_BY_CHANNELS, encQ.channel) && (encoding_1.isValueQuery(encQ) || (encoding_1.isFieldQuery(encQ) && !encQ.aggregate))) { + sc.push({ + channel: encQ.channel, + fieldDef: encQ + }); + } + return sc; + }, []); + if (stackBy.length === 0) { + return null; + } + // Has only one aggregate axis + var xEncQ = specQ.encodings.reduce(function (f, encQ) { + return f || (encQ.channel === channel_1.Channel.X ? encQ : null); + }, null); + var yEncQ = specQ.encodings.reduce(function (f, encQ) { + return f || (encQ.channel === channel_1.Channel.Y ? encQ : null); + }, null); + // TODO(akshatsh): Check if autoCount undef is ok + var xIsAggregate = (encoding_1.isFieldQuery(xEncQ) && !!xEncQ.aggregate) || (encoding_1.isAutoCountQuery(xEncQ) && !!xEncQ.autoCount); + var yIsAggregate = (encoding_1.isFieldQuery(yEncQ) && !!yEncQ.aggregate) || (encoding_1.isAutoCountQuery(yEncQ) && !!yEncQ.autoCount); + if (xIsAggregate !== yIsAggregate) { + return { + groupbyChannel: xIsAggregate ? (!!yEncQ ? channel_1.Y : null) : (!!xEncQ ? channel_1.X : null), + groupByEncQ: xIsAggregate ? yEncQ : xEncQ, + fieldChannel: xIsAggregate ? channel_1.X : channel_1.Y, + fieldEncQ: xIsAggregate ? xEncQ : yEncQ, + stackBy: stackBy, + offset: stacked || 'zero' + }; + } + return null; +} +exports.stack = stack; +function hasWildcard(specQ, opt) { + if (opt === void 0) { opt = {}; } + var exclude = opt.exclude ? util_2.toMap(opt.exclude.map(property_1.toKey)) : {}; + if (wildcard_1.isWildcard(specQ.mark) && !exclude['mark']) { + return true; + } + for (var _i = 0, _a = specQ.encodings; _i < _a.length; _i++) { + var encQ = _a[_i]; + // TODO: implement more efficiently, just check only properties of encQ + for (var key in encQ) { + var parentProp = key; + if (encQ.hasOwnProperty(parentProp) && property_1.isEncodingTopLevelProperty(parentProp)) { + if (wildcard_1.isWildcard(encQ[parentProp]) && !exclude[parentProp]) { + return true; + } + var propObj = encQ[parentProp]; + for (var childProp in propObj) { + if (propObj.hasOwnProperty(childProp) && !util_1.contains(['enum', 'name'], childProp)) { + var prop = { + parent: parentProp, + child: childProp + }; + if (wildcard_1.isWildcard(propObj[childProp]) && !exclude[property_1.toKey(prop)]) { + return true; + } + } + } + } + } + } + return false; +} +exports.hasWildcard = hasWildcard; +//# sourceMappingURL=spec.js.map \ No newline at end of file diff --git a/build/src/query/transform.js b/build/src/query/transform.js new file mode 100644 index 00000000..f07f1525 --- /dev/null +++ b/build/src/query/transform.js @@ -0,0 +1,3 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +//# sourceMappingURL=transform.js.map \ No newline at end of file diff --git a/build/src/ranking/aggregation.js b/build/src/ranking/aggregation.js new file mode 100644 index 00000000..46a88dda --- /dev/null +++ b/build/src/ranking/aggregation.js @@ -0,0 +1,90 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var type_1 = require("vega-lite/build/src/type"); +var util_1 = require("../util"); +var encoding_1 = require("../query/encoding"); +exports.name = 'aggregationQuality'; +function score(specM, schema, opt) { + var feature = aggregationQualityFeature(specM, schema, opt); + return { + score: feature.score, + features: [feature] + }; +} +exports.score = score; +function isDimension(encQ) { + return encoding_1.isDiscrete(encQ) || !!encQ.timeUnit; +} +function aggregationQualityFeature(specM, _, __) { + var encodings = specM.getEncodings(); + if (specM.isAggregate()) { + var isRawContinuous = function (encQ) { + return encoding_1.isFieldQuery(encQ) && ((encQ.type === type_1.Type.QUANTITATIVE && !encQ.bin && !encQ.aggregate) || + (encQ.type === type_1.Type.TEMPORAL && !encQ.timeUnit)); + }; + if (util_1.some(encodings, isRawContinuous)) { + // These are plots that pollute continuous fields as dimension. + // They are often intermediate visualizations rather than what users actually want. + return { + type: exports.name, + score: 0.1, + feature: 'Aggregate with raw continuous' + }; + } + if (util_1.some(encodings, function (encQ) { return encoding_1.isFieldQuery(encQ) && isDimension(encQ); })) { + var hasCount = util_1.some(encodings, function (encQ) { + return (encoding_1.isFieldQuery(encQ) && encQ.aggregate === 'count') || encoding_1.isEnabledAutoCountQuery(encQ); + }); + var hasBin = util_1.some(encodings, function (encQ) { + return encoding_1.isFieldQuery(encQ) && !!encQ.bin; + }); + if (hasCount) { + // If there is count, we might add additional count field, making it a little less simple + // then when we just apply aggregate to Q field + return { + type: exports.name, + score: 0.8, + feature: 'Aggregate with count' + }; + } + else if (hasBin) { + // This is not as good as binning all the Q and show heatmap + return { + type: exports.name, + score: 0.7, + feature: 'Aggregate with bin but without count' + }; + } + else { + return { + type: exports.name, + score: 0.9, + feature: 'Aggregate without count and without bin' + }; + } + } + // no dimension -- often not very useful + return { + type: exports.name, + score: 0.3, + feature: 'Aggregate without dimension' + }; + } + else { + if (util_1.some(encodings, function (encQ) { return encoding_1.isFieldQuery(encQ) && !isDimension(encQ); })) { + // raw plots with measure -- simplest of all! + return { + type: exports.name, + score: 1, + feature: 'Raw with measure' + }; + } + // raw plots with no measure -- often a lot of occlusion + return { + type: exports.name, + score: 0.2, + feature: 'Raw without measure' + }; + } +} +//# sourceMappingURL=aggregation.js.map \ No newline at end of file diff --git a/build/src/ranking/fieldorder.js b/build/src/ranking/fieldorder.js new file mode 100644 index 00000000..f7063420 --- /dev/null +++ b/build/src/ranking/fieldorder.js @@ -0,0 +1,54 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var encoding_1 = require("../query/encoding"); +exports.name = 'fieldOrder'; +/** + * Return ranking score based on indices of encoded fields in the schema. + * If there are multiple fields, prioritize field on the lower indices of encodings. + * + * For example, to compare two specs with two encodings each, + * first we compare the field on the 0-th index + * and only compare the field on the 1-th index only if the fields on the 0-th index are the same. + */ +function score(specM, schema, _) { + var fieldWildcardIndices = specM.wildcardIndex.encodingIndicesByProperty.get('field'); + if (!fieldWildcardIndices) { + return { + score: 0, + features: [] + }; + } + var encodings = specM.specQuery.encodings; + var numFields = schema.fieldSchemas.length; + var features = []; + var totalScore = 0, base = 1; + for (var i = fieldWildcardIndices.length - 1; i >= 0; i--) { + var index = fieldWildcardIndices[i]; + var encoding = encodings[index]; + // Skip ValueQuery as we only care about order of fields. + var field = void 0; + if (encoding_1.isFieldQuery(encoding)) { + field = encoding.field; + } + else { + continue; + } + var fieldWildcard = specM.wildcardIndex.encodings[index].get('field'); + var fieldIndex = schema.fieldSchema(field).index; + // reverse order field with lower index should get higher score and come first + var score_1 = -fieldIndex * base; + totalScore += score_1; + features.push({ + score: score_1, + type: 'fieldOrder', + feature: "field " + fieldWildcard.name + " is " + field + " (#" + fieldIndex + " in the schema)" + }); + base *= numFields; + } + return { + score: totalScore, + features: features + }; +} +exports.score = score; +//# sourceMappingURL=fieldorder.js.map \ No newline at end of file diff --git a/build/src/ranking/ranking.js b/build/src/ranking/ranking.js new file mode 100644 index 00000000..3bf7f978 --- /dev/null +++ b/build/src/ranking/ranking.js @@ -0,0 +1,98 @@ +"use strict"; +function __export(m) { + for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; +} +Object.defineProperty(exports, "__esModule", { value: true }); +var model_1 = require("../model"); +var effectiveness_1 = require("./effectiveness"); +__export(require("./effectiveness")); +exports.aggregation = require("./aggregation"); +exports.fieldOrder = require("./fieldorder"); +/** + * Registry for all encoding ranking functions + */ +var rankingRegistry = {}; +/** + * Add an ordering function to the registry. + */ +function register(name, keyFn) { + rankingRegistry[name] = keyFn; +} +exports.register = register; +function get(name) { + return rankingRegistry[name]; +} +exports.get = get; +function rank(group, query, schema, level) { + if (!query.nest || level === query.nest.length) { + if (query.orderBy || query.chooseBy) { + group.items.sort(comparatorFactory(query.orderBy || query.chooseBy, schema, query.config)); + if (query.chooseBy) { + if (group.items.length > 0) { + // for chooseBy -- only keep the top-item + group.items.splice(1); + } + } + } + } + else { + // sort lower-level nodes first because our ranking takes top-item in the subgroup + group.items.forEach(function (subgroup) { + rank(subgroup, query, schema, level + 1); + }); + if (query.nest[level].orderGroupBy) { + group.items.sort(groupComparatorFactory(query.nest[level].orderGroupBy, schema, query.config)); + } + } + return group; +} +exports.rank = rank; +function comparatorFactory(name, schema, opt) { + return function (m1, m2) { + if (name instanceof Array) { + return getScoreDifference(name, m1, m2, schema, opt); + } + else { + return getScoreDifference([name], m1, m2, schema, opt); + } + }; +} +exports.comparatorFactory = comparatorFactory; +function groupComparatorFactory(name, schema, opt) { + return function (g1, g2) { + var m1 = model_1.getTopSpecQueryItem(g1); + var m2 = model_1.getTopSpecQueryItem(g2); + if (name instanceof Array) { + return getScoreDifference(name, m1, m2, schema, opt); + } + else { + return getScoreDifference([name], m1, m2, schema, opt); + } + }; +} +exports.groupComparatorFactory = groupComparatorFactory; +function getScoreDifference(name, m1, m2, schema, opt) { + for (var _i = 0, name_1 = name; _i < name_1.length; _i++) { + var rankingName = name_1[_i]; + var scoreDifference = getScore(m2, rankingName, schema, opt).score - getScore(m1, rankingName, schema, opt).score; + if (scoreDifference !== 0) { + return scoreDifference; + } + } + return 0; +} +function getScore(model, rankingName, schema, opt) { + if (model.getRankingScore(rankingName) !== undefined) { + return model.getRankingScore(rankingName); + } + var fn = get(rankingName); + var score = fn(model, schema, opt); + model.setRankingScore(rankingName, score); + return score; +} +exports.getScore = getScore; +exports.EFFECTIVENESS = 'effectiveness'; +register(exports.EFFECTIVENESS, effectiveness_1.effectiveness); +register(exports.aggregation.name, exports.aggregation.score); +register(exports.fieldOrder.name, exports.fieldOrder.score); +//# sourceMappingURL=ranking.js.map \ No newline at end of file