export default class Query { $$criteria = {with: [], without: []}; $$index = new Set(); constructor(parameters, Components) { for (let i = 0; i < parameters.length; ++i) { const parameter = parameters[i]; switch (parameter.charCodeAt(0)) { case '!'.charCodeAt(0): this.$$criteria.without.push(Components[parameter.slice(1)]); break; default: this.$$criteria.with.push(Components[parameter]); break; } } } get count() { return this.$$index.size; } deindex(entityIds) { for (let i = 0; i < entityIds.length; ++i) { this.$$index.delete(entityIds[i]); } } reindex(entityIds) { if (0 === this.$$criteria.with.length && 0 === this.$$criteria.without.length) { for (const entityId of entityIds) { this.$$index.add(entityId); } return; } for (const entityId of entityIds) { let should = true; for (let j = 0; j < this.$$criteria.with.length; ++j) { if ('undefined' === typeof this.$$criteria.with[j].get(entityId)) { should = false; break; } } if (should) { for (let j = 0; j < this.$$criteria.without.length; ++j) { if ('undefined' !== typeof this.$$criteria.without[j].get(entityId)) { should = false; break; } } } if (should) { this.$$index.add(entityId); } else if (!should) { this.$$index.delete(entityId); } } } select() { const it = this.$$index.values(); const value = []; return { [Symbol.iterator]() { return this; }, next: () => { const result = it.next(); if (result.done) { return {done: true, value: undefined}; } for (let i = 0; i < this.$$criteria.with.length; ++i) { value[i] = this.$$criteria.with[i].get(result.value); } value[this.$$criteria.with.length] = result.value; return {done: false, value}; }, }; } }