Skip to content

Commit

Permalink
develop a simple speed aggregate, dont hook it up
Browse files Browse the repository at this point in the history
  • Loading branch information
mcnuttandrew committed Feb 15, 2024
1 parent e6f7cd6 commit f314915
Show file tree
Hide file tree
Showing 8 changed files with 104 additions and 25 deletions.
4 changes: 3 additions & 1 deletion LintLanguageDocs.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ Aggregates
{min: Variable | Number[]}
{max: Variable | Number[]}
{mean: Variable | Number[]}
{std: Variable | Number[]}
{first: Variable | Number[]}
{last: Variable | Number[]}
{extent: Variable | Number[]}
Expand All @@ -50,8 +51,9 @@ Color Manipulations:
Maps:
{map: Variable | Value[], func: Operation, varb: Variable}
{sort: Variable | Value[], func: Operation, varb: Variable}
{reverse: Variable | Value[]}
{filter: Variable | Value[], func: EXPR, varb: Variable}
{reverse: Variable | Value[]}
{speed: Variable | Value[]}

```yaml
---
Expand Down
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,9 @@ First time you start it up you should also run `yarn prep data`
- [ ] Handles get stuck on channel picker again, ugh
- [ ] Bug: Color channel usage slightly cursed (doesn't update positions correctly)
- [ ] Bug: rotate in polar coordinates doesn't work right
- [ ] Dont allow saves to examples when there's an error
- [ ] Switch the examples to be tabs or single
- [ ] Consider moving the names and color chunks into the left hand column for space
- [x] LCH colors upside down god damn it
- [x] Clone Rule
- [x] Compact more compact
Expand Down
16 changes: 12 additions & 4 deletions public/lint-schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -131,14 +131,22 @@
"varb": { "$ref": "#/definitions/LintVariable" }
},
"required": ["sort", "func", "varb"]
},
{
"type": "object",
"additionalProperties": false,
"properties": {
"speed": { "$ref": "#/definitions/LintVariable" }
},
"required": ["speed"]
}
]
},
"LintReduce": {
"LintAggregate": {
"type": "object",
"additionalProperties": false,
"patternProperties": {
"^(sum|count|mean|max|min|first|last|extent)$": {
"^(sum|count|mean|max|min|first|last|extent|std)$": {
"anyOf": [
{ "$ref": "#/definitions/LintVariable" },
{ "type": "array" },
Expand Down Expand Up @@ -365,7 +373,7 @@
]
},
"LintValue": {
"description": "A LintValue is a JSON object that represents a value. It can be a string, a number, a boolean, a LintColor, a LintVariable, a LintMathOps, a LintPairOps, a LintReduce, a LintColorFunction or a LintExpression.",
"description": "A LintValue is a JSON object that represents a value. It can be a string, a number, a boolean, a LintColor, a LintVariable, a LintMathOps, a LintPairOps, a LintAggregate, a LintColorFunction or a LintExpression.",
"anyOf": [
{ "type": "string" },
{ "type": "number" },
Expand All @@ -374,7 +382,7 @@
{ "$ref": "#/definitions/LintVariable" },
{ "$ref": "#/definitions/LintMathOps" },
{ "$ref": "#/definitions/LintPairOps" },
{ "$ref": "#/definitions/LintReduce" },
{ "$ref": "#/definitions/LintAggregate" },
{ "$ref": "#/definitions/LintColorFunction" }
]
},
Expand Down
4 changes: 2 additions & 2 deletions src/lib/ColorLint.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,12 @@ import BackgroundContrast from "./lints/background-contrast";
import CatOrderSimilarity from "./lints/cat-order-similarity";
import ColorBlindness from "./lints/color-blindness";
import ColorNameDiscriminability, { getName } from "./lints/name-discrim";
import Discrims from "./lints/size-discrim";
import Fair from "./lints/fair";
import Gamut from "./lints/in-gamut";
import MaxColors from "./lints/max-colors";
import MutuallyDistinct from "./lints/mutually-distinct";
import SequentialOrder from "./lints/sequential-order";
import SizeDiscrims from "./lints/size-discrim";
import UglyColors from "./lints/ugly-colors";

const unique = <T>(arr: T[]): T[] => [...new Set(arr)];
Expand Down Expand Up @@ -182,13 +182,13 @@ test("ColorLint - ColorNameDiscriminability", async () => {

test("ColorLint - SizeDiscrim (Thin)", () => {
const examplePal = makePalFromString(["#0084a9", "#bad", "#008000"]);
const newLint = CreateCustomLint(Discrims[0]);
const exampleLint = new newLint(examplePal).run();
expect(exampleLint.passes).toBe(true);
expect(exampleLint.message).toMatchSnapshot();

const examplePal2 = makePalFromString(["#0084a9", "#009de5", "#8ca9fa"]);
const exampleLint2 = new newLint(examplePal2).run();
const newLint = CreateCustomLint(SizeDiscrims[0]);
expect(exampleLint2.passes).toBe(false);
expect(exampleLint2.message).toMatchSnapshot();
});
Expand Down
52 changes: 45 additions & 7 deletions src/lib/lint-language/lint-language.ts
Original file line number Diff line number Diff line change
Expand Up @@ -478,7 +478,7 @@ export class LLValue extends LLNode {
| LLColor
| LLNumber
| LLVariable
| LLReduces
| LLAggregate
| LLNumberOp
) {
super();
Expand All @@ -495,7 +495,7 @@ export class LLValue extends LLNode {
LLColor,
LLNumber,
LLVariable,
LLReduces,
LLAggregate,
LLNumberOp,
];
const value = tryTypes(types, options)(node);
Expand Down Expand Up @@ -821,11 +821,12 @@ const reduceTypes = [
"min",
"max",
"mean",
"std",
"first",
"last",
"extent",
] as const;
export class LLReduces extends LLNode {
export class LLAggregate extends LLNode {
constructor(
private type: (typeof reduceTypes)[number],
private children: LLValueArray | LLVariable | LLMap
Expand All @@ -836,7 +837,9 @@ export class LLReduces extends LLNode {
this.evalCheck(env);
const children = this.children.evaluate(env).result;
if (!Array.isArray(children)) {
throw new Error("Type error");
throw new Error(
"Type error, aggregate received something that was an array"
);
}
switch (this.type) {
case "count":
Expand All @@ -847,6 +850,12 @@ export class LLReduces extends LLNode {
return { result: children[children.length - 1], env };
case "sum":
return { result: children.reduce((a, b) => a + b, 0), env };
case "std":
const sum = children.reduce((a, b) => a + b, 0);
const mean = sum / children.length;
const variance =
children.reduce((a, b) => a + (b - mean) ** 2, 0) / children.length;
return { result: Math.sqrt(variance), env };
case "mean":
return {
result: children.reduce((a, b) => a + b, 0) / children.length,
Expand All @@ -865,6 +874,9 @@ export class LLReduces extends LLNode {
}
static tryToConstruct(node: any, options: OptionsConfig) {
const reduceType = reduceTypes.find((x) => node[x]);
if (node.avg) {
throw new Error("Did you mean mean instead of avg?");
}
if (!reduceType) return false;
const children = node[reduceType];
if (!children) return false;
Expand All @@ -875,14 +887,14 @@ export class LLReduces extends LLNode {
childType = tryTypes([LLVariable, LLMap], options)(children);
}
if (!childType) return false;
return new LLReduces(reduceType, childType);
return new LLAggregate(reduceType, childType);
}
toString(): string {
return `${this.type}(${this.children.toString()})`;
}
}

const mapTypes = ["map", "filter", "sort", "reverse"] as const;
const mapTypes = ["map", "filter", "sort", "reverse", "speed"] as const;
// example syntax
// {map: colors, func: {cvdSim: {type: "protanomaly"}}, varb: "x"}
export class LLMap extends LLNode {
Expand Down Expand Up @@ -920,6 +932,32 @@ export class LLMap extends LLNode {
const childrenCopy2 = [...children];
childrenCopy2.reverse();
return { result: childrenCopy2, env };
case "speed":
// todo maybe make this take algorithm as argument?
const speed = [];
const allNumbers = children.every(
(x) =>
typeof x === "number" ||
(typeof x === "object" && x?.type === "<number>")
);
const allColors = children.every((x) => x instanceof Color);
if (!allNumbers && !allColors) {
const types = children.map((x) => x);
console.log(children);
throw new Error(
`Type error, speed must receive all numbers or all colors, got ${types}`
);
}
for (let i = 0; i < children.length - 1; i++) {
const a = children[i];
const b = children[i + 1];
if (allNumbers) {
speed.push(Math.abs(a - b));
} else {
speed.push(a.symmetricDeltaE(b, "2000"));
}
}
return { result: speed, env };
}
}
static tryToConstruct(node: any, options: OptionsConfig) {
Expand All @@ -932,7 +970,7 @@ export class LLMap extends LLNode {
let func;
if (op === "filter") {
func = tryTypes([LLExpression], options)(node.func);
} else if (op === "reverse") {
} else if (op === "reverse" || op === "speed") {
// reverse doesn't take any arguments besides the target
varb = " ";
func = " ";
Expand Down
21 changes: 12 additions & 9 deletions src/lib/lint-language/lint-type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,13 +59,16 @@ type LintPairOps =
| "Lstar"
| "DeltaPhi";
};
type MapTarget = LintVariable | LintValue[];
type MapEval = LintColorFunction | LintPairOps;
type LintMap =
// | { map: LintVariable | LintValue[]; func: LintColorFunction | LintPairOps }
// | { sort: LintVariable | LintValue[]; func: LintColorFunction | LintPairOps }
// | {reverse: LintVariable | LintValue[]}
{ filter: LintVariable | LintValue[]; func: LintExpression };
| { map: MapTarget; func: MapEval; varb: string }
| { sort: MapTarget; func: MapEval; varb: string }
| { reverse: LintVariable | LintValue[] }
| { filter: MapTarget; func: LintExpression; varb: string }
| { speed: MapTarget };

type LintReduce = Record<
type Aggs =
| "sum"
| "count"
| "mean"
Expand All @@ -74,9 +77,9 @@ type LintReduce = Record<
| "mean"
| "first"
| "last"
| "extent",
LintVariable | any[] | LintMap
>;
| "extent"
| "std";
type LintAggregate = Record<Aggs, LintVariable | any[] | LintMap>;
type LintColorFunction =
| {
cvdSim: LintVariable | LintColor;
Expand Down Expand Up @@ -127,7 +130,7 @@ type LintValue =
| LintVariable
| LintMathOps
| LintPairOps
| LintReduce
| LintAggregate
| LintColorFunction;

// raw values
Expand Down
4 changes: 2 additions & 2 deletions src/lib/linter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,18 @@ import DivergingOrder from "./lints/diverging-order";
import EvenDistribution from "./lints/even-distribution";

// custom lints
import Affects from "./lints/affects";
import AvoidExtremes from "./lints/avoid-extremes";
import BackgroundDifferentiability from "./lints/background-contrast";
import CatOrderSimilarity from "./lints/cat-order-similarity";
import ColorBlindness from "./lints/color-blindness";
import SizeDiscrim from "./lints/size-discrim";
import Fair from "./lints/fair";
import Gamut from "./lints/in-gamut";
import MaxColors from "./lints/max-colors";
import MutuallyDistinct from "./lints/mutually-distinct";
import SequentialOrder from "./lints/sequential-order";
import SizeDiscrim from "./lints/size-discrim";
import UglyColors from "./lints/ugly-colors";
import Affects from "./lints/affects";

export const BUILT_INS: CustomLint[] = [
...Affects,
Expand Down
25 changes: 25 additions & 0 deletions src/lib/lints/discriminative-power.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { JSONToPrettyString } from "../utils";
import type { CustomLint } from "../CustomLint";
import type { LintFixer } from "../linter-tools/lint-fixer";

const lint: CustomLint = {
name: "Discriminative Power Sufficient",
program: JSONToPrettyString({
// @ts-ignore
$schema: `${location.href}lint-schema.json`,
"<": {
left: {
std: { speed: "colors" },
},
right: 0,
},
}),
taskTypes: ["sequential", "diverging", "categorical"] as const,
level: "warning",
group: "design",
description: "Palette should have sufficient discriminative power. ",
failMessage: ``,
id: "discrim-power-built-in",
blameMode: "single",
};
export default lint;

0 comments on commit f314915

Please sign in to comment.