diff --git a/core/code/filters.js b/core/code/filters.js index 172af279d..69c545998 100644 --- a/core/code/filters.js +++ b/core/code/filters.js @@ -1,71 +1,26 @@ -/* Filters API - -Filters API is a mechanism to hide intel entities using their properties (faction, -health, timestamp...). It provides two level APIs: a set of named filters that -apply globally (any entity matching one of the filters will be hidden), and low -level API to test an entity against a filter for generic purpose. -This comes with a Leaflet layer system following the old layer system, the filter -is disabled when the layer is added to the map and is enabled when removed. - -A filter applies to a combinaison of portal/link/field and is described by - - data properties that must (all) match - - or a predicate for complex filter - - { portal: true, link: true, data: { team: 'E' }} - filters any ENL portal/link - - [{ link: true, data: { oGuid: "some guid" }}, { link: true, data: { dGuid: "some guid" }}] - filters any links on portal with guid "some guid" - - { field: true, pred: function (f) { return f.options.timestamp < Date.parse('2021-10-31'); } } - filters any fields made before Halloween 2021 - -Data properties can be specified as value, or as a complex expression (required -for array data properties). A complex expression is a 2-array, first element is -an operator, second is the argument of the operator for the property. -The operators are: - - ['eq', value] : this is equivalent to type directly `value` - - ['not', ] - - ['or', [exp1, exp2,...]]: the expression matches if one of the exp1.. matches - - ['and', [exp1, exp2...]]: matches if all exp1 matches (useful for array - properties) - - ['some', exp]: when the property is an array, matches if one of the element - matches `exp` - - ['every', exp]: all elements must match `exp` - - ['<', number]: for number comparison (and <= > >=) - -Examples: - { portal: true, data: ['not', { history: { scoutControlled: false }, ornaments: - ['some', 'sc5_p'] }] } - filters all portals but the one never scout controlled that have a scout - volatile ornament - - { portal: true, data: ['not', { resonators: ['every', { owner: 'some agent' } ] } ] } - filters all portals that have resonators not owned from 'some agent' - (note: that would need to load portal details) +/* global IITC, L */ - { portal: true, data: { level: ['or', [1,4,5]], health: ['>', 85] } } - filters all portals with level 1,4 or 5 and health over 85 +/** # Filters API - { portal: true, link: true, field: true, options: { timestamp: ['<', - Date.now() - 3600000] } } - filters all entities with no change since 1 hour (from the creation of - the filter) + @memberof IITC + @namespace filters */ IITC.filters = {}; /** - * @type {Object.} + * @type {Object.} */ IITC.filters._filters = {}; /** + * @memberof IITC.filters * @callback FilterPredicate * @param {Object} ent - IITC entity * @returns {boolean} */ /** + * @memberof IITC.filters * @typedef FilterDesc * @type {object} * @property {boolean} filterDesc.portal apply to portal @@ -73,21 +28,35 @@ IITC.filters._filters = {}; * @property {boolean} filterDesc.field apply to field * @property {object} [filterDesc.data] entity data properties that must match * @property {object} [filterDesc.options] entity options that must match - * @property {FilterPredicate} [filterDesc.pred] predicate on the entity + * @property {IITC.filters.FilterPredicate} [filterDesc.pred] predicate on the entity */ /** + * Sets or updates a filter with a given name. If a filter with the same name already exists, it is overwritten. + * * @param {string} name filter name - * @param {FilterDesc | FilterDesc[]} filterDesc filter description (OR) + * @param {IITC.filters.FilterDesc | IITC.filters.FilterDesc[]} filterDesc filter description (OR) */ IITC.filters.set = function (name, filterDesc) { IITC.filters._filters[name] = filterDesc; }; +/** + * Checks if a filter with the specified name exists. + * + * @param {string} name - The name of the filter to check. + * @returns {boolean} True if the filter exists, false otherwise. + */ IITC.filters.has = function (name) { return name in IITC.filters._filters; }; +/** + * Removes a filter with the specified name. + * + * @param {string} name - The name of the filter to be removed. + * @returns {boolean} True if the filter was successfully deleted, false otherwise. + */ IITC.filters.remove = function (name) { return delete IITC.filters._filters[name]; }; @@ -188,10 +157,11 @@ function genericCompare(constraint, object) { } /** + * Tests whether a given entity matches a specified filter. * * @param {"portal"|"link"|"field"} type Type of the entity * @param {object} entity Portal/link/field to test - * @param {FilterDesc} filter Filter + * @param {IITC.filters.FilterDesc} filter Filter * @returns {boolean} `true` if the the `entity` of type `type` matches the `filter` */ IITC.filters.testFilter = function (type, entity, filter) { @@ -221,6 +191,7 @@ function arrayFilter(type, entity, filters) { } /** + * Tests whether a given portal matches any of the currently active filters. * * @param {object} portal Portal to test * @returns {boolean} `true` if the the portal matches one of the filters @@ -230,6 +201,7 @@ IITC.filters.filterPortal = function (portal) { }; /** + * Tests whether a given link matches any of the currently active filters. * * @param {object} link Link to test * @returns {boolean} `true` if the the link matches one of the filters @@ -239,6 +211,7 @@ IITC.filters.filterLink = function (link) { }; /** + * Tests whether a given field matches any of the currently active filters. * * @param {object} field Field to test * @returns {boolean} `true` if the the field matches one of the filters @@ -247,6 +220,10 @@ IITC.filters.filterField = function (field) { return arrayFilter('field', field, Object.values(IITC.filters._filters)); }; +/** + * Applies all existing filters to the entities (portals, links, and fields) on the map. + * Entities that match any of the active filters are removed from the map; others are added or remain on the map. + */ IITC.filters.filterEntities = function () { for (const guid in window.portals) { const p = window.portals[guid]; @@ -266,11 +243,14 @@ IITC.filters.filterEntities = function () { }; /** + * @memberof IITC.filters * @class FilterLayer * @description Layer abstraction to control with the layer chooser a filter. * The filter is disabled on layer add, and enabled on layer remove. * @extends L.Layer - * @param {{name: string, filter: FilterDesc}} options + * @param {Object} options - Configuration options for the filter layer + * @param {string} options.name - The name of the filter + * @param {IITC.filters.FilterDesc} options.filter - The filter description */ IITC.filters.FilterLayer = L.Layer.extend({ options: { @@ -293,5 +273,3 @@ IITC.filters.FilterLayer = L.Layer.extend({ IITC.filters.filterEntities(); }, }); - -/* global IITC, L */