Skip to content

Commit

Permalink
[WIP] add testing for filtering functions
Browse files Browse the repository at this point in the history
  • Loading branch information
brauliorivas committed May 24, 2024
1 parent 5e221d6 commit 849cfcf
Show file tree
Hide file tree
Showing 4 changed files with 329 additions and 114 deletions.
112 changes: 9 additions & 103 deletions js/menu/filter/filter.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { Link } from "../../objects.js";
import { drawAll } from "../../draw.js";
import { parentLinks, childrenLinks, infoBoxes, ctx } from "../../main.js";
import { Range, Checkbox } from "./parameters.js";
import { Range, Checkbox, buildCriteriaFunction } from "./parameters.js";
import { reconnect } from "./reconnect.js";

const filterButton = document.getElementById("filter-button");
const openFilter = document.getElementById("open-filter");
Expand Down Expand Up @@ -36,49 +37,18 @@ parametersRange.forEach((parameter) => parameter.render(filters));

let bitsCheckbox = [23, 24, 25, 26, 27, 28, 29, 30];

bitsCheckbox = bitsCheckbox.map((bit) => new Checkbox(bit));
bitsCheckbox = bitsCheckbox.map((bit) => new Checkbox("simStatus", bit));

bitsCheckbox.forEach((checkbox) => checkbox.render(filters));

apply.addEventListener("click", () => {
let rangeFunctions = parametersRange.map((parameter) =>
parameter.buildCondition()
);
rangeFunctions = rangeFunctions.filter((fn) => fn);
rangeFunctions = rangeFunctions.reduce((acc, fn) => acc && fn, true);

let bitsFunction = bitsCheckbox.map((checkbox) => checkbox.buildCondition());
bitsFunction = bitsFunction.filter((fn) => fn);

if (bitsFunction.length === 0) {
bitsFunction = true;
} else {
bitsFunction = bitsFunction.reduce(
(acc, fn) => {
return (particle) => acc(particle) || fn(particle);
},
() => false
);
}

function criteriaFunction(particle) {
if (
typeof bitsFunction === "function" &&
typeof rangeFunctions === "function"
) {
return rangeFunctions(particle) && bitsFunction(particle);
}

if (typeof bitsFunction === "function") {
return bitsFunction(particle);
}
const rangeFunctions = Range.buildFilter(parametersRange);
const checkboxFunctions = Checkbox.buildFilter(bitsCheckbox);

if (typeof rangeFunctions === "function") {
return rangeFunctions(particle);
}

return true;
}
const criteriaFunction = buildCriteriaFunction(
rangeFunctions,
checkboxFunctions
);

const [newParentLinks, newChildrenLinks, filteredParticles] = reconnect(
criteriaFunction,
Expand Down Expand Up @@ -106,67 +76,3 @@ reset.addEventListener("click", () => {
checkbox.render(filters);
});
});

function reconnect(criteriaFunction, parentLinks, childrenLinks, particles) {
const newParentLinks = [];
const newChildrenLinks = [];
const filteredParticles = [];

for (const particle of particles) {
if (!particle) continue;

if (!criteriaFunction(particle)) {
filteredParticles.push(null);

const parentParticles = [];
const childrenParticles = [];

for (const parent of particle.parents) {
if (criteriaFunction(particles[parent])) {
parentParticles.push(parent);
}
}

for (const child of particle.children) {
if (criteriaFunction(particles[child])) {
childrenParticles.push(child);
}
}

for (const parent of parentParticles) {
for (const child of childrenParticles) {
const linkToParent = new Link(newParentLinks.length, parent, child);
linkToParent.xShift = 3;
const linkToChild = new Link(newChildrenLinks.length, parent, child);
linkToChild.color = "#0A0";
linkToChild.xShift = -3;

newParentLinks.push(linkToParent);
newChildrenLinks.push(linkToChild);
}
}
} else {
filteredParticles.push(particle);

for (const parentLinkId of particle.parentLinks) {
const parentLink = parentLinks[parentLinkId];
if (!parentLink) continue;
const parent = particles[parentLink.from];
if (criteriaFunction(parent)) {
newParentLinks.push(parentLink);
}
}

for (const childrenLinkId of particle.childrenLinks) {
const childrenLink = childrenLinks[childrenLinkId];
if (!childrenLink) continue;
const child = particles[childrenLink.to];
if (criteriaFunction(child)) {
newChildrenLinks.push(childrenLink);
}
}
}
}

return [newParentLinks, newChildrenLinks, filteredParticles];
}
76 changes: 65 additions & 11 deletions js/menu/filter/parameters.js
Original file line number Diff line number Diff line change
@@ -1,21 +1,31 @@
class FilterParameter {
constructor(name) {
this.name = name;
property;

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

render(container) {}

buildCondition() {}

static parametersFunctions(parameters) {
const functions = parameters.map((parameter) => parameter.buildCondition());
return functions.filter((fn) => fn);
}
}

export class Range extends FilterParameter {
constructor(name) {
super(name);
min;
max;

constructor(property) {
super(property);
}

render(container) {
const label = document.createElement("label");
label.textContent = this.name;
label.textContent = this.property;
container.appendChild(label);

const inputMin = document.createElement("input");
Expand Down Expand Up @@ -45,31 +55,47 @@ export class Range extends FilterParameter {

return (particle) => {
if (particle) {
if (particle[this.name] < this.min) {
if (particle[this.property] < this.min) {
return false;
}

if (particle[this.name] > this.max) {
if (particle[this.property] > this.max) {
return false;
}

return true;
}
};
}

static buildFilter(parametersRange) {
const rangeFunctions = Range.parametersFunctions(parametersRange);

const func = rangeFunctions.reduce(
(acc, fn) => {
return (particle) => acc(particle) && fn(particle);
},
() => true
);

return func;
}
}

export class Checkbox extends FilterParameter {
constructor(name) {
super(name);
value;

constructor(property, value) {
super(property);
this.value = value;
}

render(container) {
const div = document.createElement("div");
container.appendChild(div);

const label = document.createElement("label");
label.textContent = `Sim Status: ${this.name}`;
label.textContent = `${this.property}: ${this.value}`;
div.appendChild(label);

const input = document.createElement("input");
Expand All @@ -88,6 +114,34 @@ export class Checkbox extends FilterParameter {
buildCondition() {
if (!this.checked) return null;

return (particle) => particle.simStatus === this.name;
return (particle) => particle[this.property] === this.value;
}

static buildFilter(parametersCheckbox) {
const checkboxFunctions = Checkbox.parametersFunctions(parametersCheckbox);

if (checkboxFunctions.length === 0) return () => true;

const func = checkboxFunctions.reduce(
(acc, fn) => {
return (particle) => acc(particle) || fn(particle);
},
() => false
);

return func;
}
}

export function buildCriteriaFunction(...functions) {
const filterFunctions = functions.filter((fn) => typeof fn === "function");

const finalFunction = filterFunctions.reduce(
(acc, fn) => {
return (particle) => acc(particle) && fn(particle);
},
() => true
);

return (particle) => finalFunction(particle);
}
68 changes: 68 additions & 0 deletions js/menu/filter/reconnect.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
export function reconnect(
criteriaFunction,
parentLinks,
childrenLinks,
particles
) {
const newParentLinks = [];
const newChildrenLinks = [];
const filteredParticles = [];

for (const particle of particles) {
if (!particle) continue;

if (!criteriaFunction(particle)) {
filteredParticles.push(null);

const parentParticles = [];
const childrenParticles = [];

for (const parent of particle.parents) {
if (criteriaFunction(particles[parent])) {
parentParticles.push(parent);
}
}

for (const child of particle.children) {
if (criteriaFunction(particles[child])) {
childrenParticles.push(child);
}
}

for (const parent of parentParticles) {
for (const child of childrenParticles) {
const linkToParent = new Link(newParentLinks.length, parent, child);
linkToParent.xShift = 3;
const linkToChild = new Link(newChildrenLinks.length, parent, child);
linkToChild.color = "#0A0";
linkToChild.xShift = -3;

newParentLinks.push(linkToParent);
newChildrenLinks.push(linkToChild);
}
}
} else {
filteredParticles.push(particle);

for (const parentLinkId of particle.parentLinks) {
const parentLink = parentLinks[parentLinkId];
if (!parentLink) continue;
const parent = particles[parentLink.from];
if (criteriaFunction(parent)) {
newParentLinks.push(parentLink);
}
}

for (const childrenLinkId of particle.childrenLinks) {
const childrenLink = childrenLinks[childrenLinkId];
if (!childrenLink) continue;
const child = particles[childrenLink.to];
if (criteriaFunction(child)) {
newChildrenLinks.push(childrenLink);
}
}
}
}

return [newParentLinks, newChildrenLinks, filteredParticles];
}
Loading

0 comments on commit 849cfcf

Please sign in to comment.