mirror of
https://github.com/status-im/sourcecred.git
synced 2025-01-29 22:05:29 +00:00
Move weight logic to analysis (#966)
There's a folder called `app/credExplorer/weights` which contains the type specification for weights (for PageRank configurability), and also contains frontend code for specifying those weights. This commit creates a `weights` module under `analysis` which will contain just the logic for specifying and using the weights, without any frontend consideration. It's mostly a port of the existing logic in `credExplorer/weights`, with the caveat that app adapter related concepts have been removed, in favor of referencing the declaration instead. We then remove the duplicated logic and re-route imports. Test plan: `yarn test`
This commit is contained in:
parent
86a5b532f8
commit
f3ddb84cbd
57
src/analysis/weights.js
Normal file
57
src/analysis/weights.js
Normal file
@ -0,0 +1,57 @@
|
||||
// @flow
|
||||
|
||||
import * as MapUtil from "../util/map";
|
||||
import {type NodeAddressT, type EdgeAddressT} from "../core/graph";
|
||||
import type {EdgeType, NodeType} from "./types";
|
||||
import type {PluginDeclaration} from "./pluginDeclaration";
|
||||
|
||||
export type WeightedNodeType = {|+type: NodeType, +weight: number|};
|
||||
|
||||
export type WeightedEdgeType = {|
|
||||
+type: EdgeType,
|
||||
+forwardWeight: number,
|
||||
+backwardWeight: number,
|
||||
|};
|
||||
|
||||
export type WeightedTypes = {|
|
||||
// Map from the weighted type's prefix to the type
|
||||
+nodes: Map<NodeAddressT, WeightedNodeType>,
|
||||
+edges: Map<EdgeAddressT, WeightedEdgeType>,
|
||||
|};
|
||||
|
||||
export function defaultWeightedNodeType(type: NodeType): WeightedNodeType {
|
||||
return {
|
||||
type,
|
||||
weight: type.defaultWeight,
|
||||
};
|
||||
}
|
||||
|
||||
export function defaultWeightedEdgeType(type: EdgeType): WeightedEdgeType {
|
||||
return {
|
||||
type,
|
||||
forwardWeight: type.defaultForwardWeight,
|
||||
backwardWeight: type.defaultBackwardWeight,
|
||||
};
|
||||
}
|
||||
|
||||
export function defaultWeightsForDeclaration(
|
||||
declaration: PluginDeclaration
|
||||
): WeightedTypes {
|
||||
return {
|
||||
nodes: new Map(
|
||||
declaration.nodeTypes.map((x) => [x.prefix, defaultWeightedNodeType(x)])
|
||||
),
|
||||
edges: new Map(
|
||||
declaration.edgeTypes.map((x) => [x.prefix, defaultWeightedEdgeType(x)])
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
export function combineWeights(
|
||||
ws: $ReadOnlyArray<WeightedTypes>
|
||||
): WeightedTypes {
|
||||
return {
|
||||
nodes: MapUtil.merge(ws.map((x) => x.nodes)),
|
||||
edges: MapUtil.merge(ws.map((x) => x.edges)),
|
||||
};
|
||||
}
|
106
src/analysis/weights.test.js
Normal file
106
src/analysis/weights.test.js
Normal file
@ -0,0 +1,106 @@
|
||||
// @flow
|
||||
|
||||
import {
|
||||
defaultWeightedNodeType,
|
||||
defaultWeightedEdgeType,
|
||||
defaultWeightsForDeclaration,
|
||||
combineWeights,
|
||||
} from "./weights";
|
||||
import {
|
||||
inserterNodeType,
|
||||
machineNodeType,
|
||||
assemblesEdgeType,
|
||||
transportsEdgeType,
|
||||
declaration,
|
||||
} from "../plugins/demo/declaration";
|
||||
|
||||
describe("analysis/weights", () => {
|
||||
describe("defaultWeightedNodeType", () => {
|
||||
it("sets default weight as specified in type", () => {
|
||||
const wnt = defaultWeightedNodeType(inserterNodeType);
|
||||
expect(wnt.weight).toEqual(wnt.type.defaultWeight);
|
||||
});
|
||||
});
|
||||
describe("defaultWeightedEdgeType", () => {
|
||||
it("sets default weights as specified in the type", () => {
|
||||
const wet = defaultWeightedEdgeType(assemblesEdgeType);
|
||||
expect(wet.forwardWeight).toEqual(wet.type.defaultForwardWeight);
|
||||
expect(wet.backwardWeight).toEqual(wet.type.defaultBackwardWeight);
|
||||
});
|
||||
});
|
||||
describe("defaultWeightsForDeclaration", () => {
|
||||
it("works on the demo declaration", () => {
|
||||
const expected = {
|
||||
nodes: new Map(
|
||||
declaration.nodeTypes.map((x) => [
|
||||
x.prefix,
|
||||
defaultWeightedNodeType(x),
|
||||
])
|
||||
),
|
||||
edges: new Map(
|
||||
declaration.edgeTypes.map((x) => [
|
||||
x.prefix,
|
||||
defaultWeightedEdgeType(x),
|
||||
])
|
||||
),
|
||||
};
|
||||
expect(defaultWeightsForDeclaration(declaration)).toEqual(expected);
|
||||
});
|
||||
});
|
||||
describe("combineWeights", () => {
|
||||
const defaultWeights = () => defaultWeightsForDeclaration(declaration);
|
||||
const emptyWeights = () => ({nodes: new Map(), edges: new Map()});
|
||||
it("successfully combines WeightedTypes", () => {
|
||||
const weights1 = {
|
||||
nodes: new Map().set(
|
||||
inserterNodeType.prefix,
|
||||
defaultWeightedNodeType(inserterNodeType)
|
||||
),
|
||||
edges: new Map().set(
|
||||
assemblesEdgeType.prefix,
|
||||
defaultWeightedEdgeType(assemblesEdgeType)
|
||||
),
|
||||
};
|
||||
const weights2 = {
|
||||
nodes: new Map().set(
|
||||
machineNodeType.prefix,
|
||||
defaultWeightedNodeType(machineNodeType)
|
||||
),
|
||||
edges: new Map().set(
|
||||
transportsEdgeType.prefix,
|
||||
defaultWeightedEdgeType(transportsEdgeType)
|
||||
),
|
||||
};
|
||||
expect(combineWeights([weights1, weights2])).toEqual(defaultWeights());
|
||||
});
|
||||
it("treats empty weights as an identity", () => {
|
||||
expect(
|
||||
combineWeights([emptyWeights(), defaultWeights(), emptyWeights()])
|
||||
).toEqual(defaultWeights());
|
||||
});
|
||||
it("errors on duplicate edge prefix", () => {
|
||||
const weights = {
|
||||
nodes: new Map(),
|
||||
edges: new Map().set(
|
||||
assemblesEdgeType.prefix,
|
||||
defaultWeightedEdgeType(assemblesEdgeType)
|
||||
),
|
||||
};
|
||||
expect(() => combineWeights([weights, weights])).toThrowError(
|
||||
"duplicate key"
|
||||
);
|
||||
});
|
||||
it("errors on duplicate node prefix", () => {
|
||||
const weights = {
|
||||
nodes: new Map().set(
|
||||
inserterNodeType.prefix,
|
||||
defaultWeightedNodeType(inserterNodeType)
|
||||
),
|
||||
edges: new Map(),
|
||||
};
|
||||
expect(() => combineWeights([weights, weights])).toThrowError(
|
||||
"duplicate key"
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
@ -10,10 +10,8 @@ import Link from "../Link";
|
||||
|
||||
import {defaultStaticAdapters} from "../adapters/defaultPlugins";
|
||||
import {PagerankTable} from "./pagerankTable/Table";
|
||||
import {
|
||||
type WeightedTypes,
|
||||
defaultWeightsForAdapterSet,
|
||||
} from "./weights/weights";
|
||||
import type {WeightedTypes} from "../../analysis/weights";
|
||||
import {defaultWeightsForAdapterSet} from "./weights/weights";
|
||||
import RepositorySelect from "./RepositorySelect";
|
||||
import {Prefix as GithubPrefix} from "../../plugins/github/nodes";
|
||||
import {
|
||||
|
@ -9,7 +9,7 @@ import type {PagerankNodeDecomposition} from "../../../analysis/pagerankNodeDeco
|
||||
import {DynamicAdapterSet} from "../../adapters/adapterSet";
|
||||
import type {DynamicAppAdapter} from "../../adapters/appAdapter";
|
||||
import {FALLBACK_NAME} from "../../adapters/fallbackAdapter";
|
||||
import {type WeightedTypes} from "../weights/weights";
|
||||
import type {WeightedTypes} from "../../../analysis/weights";
|
||||
import {WeightConfig} from "../weights/WeightConfig";
|
||||
|
||||
import {NodeRowList} from "./Node";
|
||||
|
@ -13,7 +13,7 @@ import {
|
||||
} from "../../analysis/pagerank";
|
||||
|
||||
import {StaticAdapterSet, DynamicAdapterSet} from "../adapters/adapterSet";
|
||||
import type {WeightedTypes} from "./weights/weights";
|
||||
import type {WeightedTypes} from "../../analysis/weights";
|
||||
import {weightsToEdgeEvaluator} from "./weights/weightsToEdgeEvaluator";
|
||||
|
||||
/*
|
||||
|
@ -11,10 +11,8 @@ import {Graph, NodeAddress} from "../../core/graph";
|
||||
import {Assets} from "../assets";
|
||||
import {makeRepoId, type RepoId} from "../../core/repoId";
|
||||
import {type EdgeEvaluator} from "../../analysis/pagerank";
|
||||
import {
|
||||
type WeightedTypes,
|
||||
defaultWeightsForAdapterSet,
|
||||
} from "./weights/weights";
|
||||
import type {WeightedTypes} from "../../analysis/weights";
|
||||
import {defaultWeightsForAdapterSet} from "./weights/weights";
|
||||
import {StaticAdapterSet, DynamicAdapterSet} from "../adapters/adapterSet";
|
||||
import type {
|
||||
PagerankNodeDecomposition,
|
||||
|
@ -3,7 +3,7 @@
|
||||
import React from "react";
|
||||
import {WeightSlider, type Props as WeightSliderProps} from "./WeightSlider";
|
||||
|
||||
import type {WeightedEdgeType} from "./weights";
|
||||
import type {WeightedEdgeType} from "../../../analysis/weights";
|
||||
|
||||
export class EdgeTypeConfig extends React.Component<{
|
||||
+weightedType: WeightedEdgeType,
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
import React from "react";
|
||||
import {WeightSlider} from "./WeightSlider";
|
||||
import type {WeightedNodeType} from "./weights";
|
||||
import type {WeightedNodeType} from "../../../analysis/weights";
|
||||
|
||||
export class NodeTypeConfig extends React.Component<{
|
||||
+weightedType: WeightedNodeType,
|
||||
|
@ -7,11 +7,11 @@ import {NodeTypeConfig} from "./NodeTypeConfig";
|
||||
import {EdgeTypeConfig} from "./EdgeTypeConfig";
|
||||
import {StaticAppAdapter} from "../../adapters/appAdapter";
|
||||
import {styledVariable} from "./EdgeTypeConfig";
|
||||
import {
|
||||
type WeightedTypes,
|
||||
type WeightedEdgeType,
|
||||
type WeightedNodeType,
|
||||
} from "./weights";
|
||||
import type {
|
||||
WeightedTypes,
|
||||
WeightedEdgeType,
|
||||
WeightedNodeType,
|
||||
} from "../../../analysis/weights";
|
||||
|
||||
export type Props = {|
|
||||
+adapter: StaticAppAdapter,
|
||||
|
@ -15,11 +15,11 @@ import {
|
||||
import {NodeTypeConfig} from "./NodeTypeConfig";
|
||||
import {EdgeTypeConfig} from "./EdgeTypeConfig";
|
||||
import {
|
||||
defaultWeightsForAdapter,
|
||||
type WeightedTypes,
|
||||
defaultWeightedNodeType,
|
||||
defaultWeightedEdgeType,
|
||||
type WeightedTypes,
|
||||
} from "./weights";
|
||||
} from "../../../analysis/weights";
|
||||
import {defaultWeightsForAdapter} from "./weights";
|
||||
|
||||
require("../../testUtil").configureEnzyme();
|
||||
|
||||
|
@ -5,7 +5,7 @@ import * as NullUtil from "../../../util/null";
|
||||
import * as MapUtil from "../../../util/map";
|
||||
|
||||
import type {StaticAdapterSet} from "../../adapters/adapterSet";
|
||||
import type {WeightedTypes} from "./weights";
|
||||
import type {WeightedTypes} from "../../../analysis/weights";
|
||||
import {PluginWeightConfig} from "./PluginWeightConfig";
|
||||
import {FALLBACK_NAME} from "../../adapters/fallbackAdapter";
|
||||
|
||||
|
@ -1,64 +1,17 @@
|
||||
// @flow
|
||||
|
||||
import * as MapUtil from "../../../util/map";
|
||||
import {type NodeAddressT, type EdgeAddressT} from "../../../core/graph";
|
||||
import type {EdgeType, NodeType} from "../../../analysis/types";
|
||||
import {
|
||||
type WeightedTypes,
|
||||
combineWeights,
|
||||
defaultWeightsForDeclaration,
|
||||
} from "../../../analysis/weights";
|
||||
import type {StaticAppAdapter} from "../../adapters/appAdapter";
|
||||
import type {StaticAdapterSet} from "../../adapters/adapterSet";
|
||||
|
||||
export type WeightedNodeType = {|+type: NodeType, +weight: number|};
|
||||
|
||||
export type WeightedEdgeType = {|
|
||||
+type: EdgeType,
|
||||
+forwardWeight: number,
|
||||
+backwardWeight: number,
|
||||
|};
|
||||
|
||||
export type WeightedTypes = {|
|
||||
// Map from the weighted type's prefix to the type
|
||||
+nodes: Map<NodeAddressT, WeightedNodeType>,
|
||||
+edges: Map<EdgeAddressT, WeightedEdgeType>,
|
||||
|};
|
||||
|
||||
export function defaultWeightedNodeType(type: NodeType): WeightedNodeType {
|
||||
return {
|
||||
type,
|
||||
weight: type.defaultWeight,
|
||||
};
|
||||
}
|
||||
|
||||
export function defaultWeightedEdgeType(type: EdgeType): WeightedEdgeType {
|
||||
return {
|
||||
type,
|
||||
forwardWeight: type.defaultForwardWeight,
|
||||
backwardWeight: type.defaultBackwardWeight,
|
||||
};
|
||||
}
|
||||
|
||||
export function defaultWeightsForAdapter(
|
||||
adapter: StaticAppAdapter
|
||||
): WeightedTypes {
|
||||
return {
|
||||
nodes: new Map(
|
||||
adapter
|
||||
.declaration()
|
||||
.nodeTypes.map((x) => [x.prefix, defaultWeightedNodeType(x)])
|
||||
),
|
||||
edges: new Map(
|
||||
adapter
|
||||
.declaration()
|
||||
.edgeTypes.map((x) => [x.prefix, defaultWeightedEdgeType(x)])
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
export function combineWeights(
|
||||
ws: $ReadOnlyArray<WeightedTypes>
|
||||
): WeightedTypes {
|
||||
return {
|
||||
nodes: MapUtil.merge(ws.map((x) => x.nodes)),
|
||||
edges: MapUtil.merge(ws.map((x) => x.edges)),
|
||||
};
|
||||
return defaultWeightsForDeclaration(adapter.declaration());
|
||||
}
|
||||
|
||||
export function defaultWeightsForAdapterSet(
|
||||
|
@ -1,112 +1,25 @@
|
||||
// @flow
|
||||
|
||||
import {defaultWeightsForAdapter, defaultWeightsForAdapterSet} from "./weights";
|
||||
import {
|
||||
defaultWeightedNodeType,
|
||||
defaultWeightedEdgeType,
|
||||
defaultWeightsForAdapter,
|
||||
defaultWeightsForDeclaration,
|
||||
combineWeights,
|
||||
defaultWeightsForAdapterSet,
|
||||
} from "./weights";
|
||||
import {
|
||||
inserterNodeType,
|
||||
machineNodeType,
|
||||
assemblesEdgeType,
|
||||
transportsEdgeType,
|
||||
} from "../../../plugins/demo/declaration";
|
||||
} from "../../../analysis/weights";
|
||||
import {declaration} from "../../../plugins/demo/declaration";
|
||||
import {
|
||||
FactorioStaticAdapter,
|
||||
staticAdapterSet,
|
||||
} from "../../../plugins/demo/appAdapter";
|
||||
|
||||
describe("app/credExplorer/weights/weights", () => {
|
||||
describe("defaultWeightedNodeType", () => {
|
||||
it("sets default weight as specified in type", () => {
|
||||
const wnt = defaultWeightedNodeType(inserterNodeType);
|
||||
expect(wnt.weight).toEqual(wnt.type.defaultWeight);
|
||||
});
|
||||
});
|
||||
describe("defaultWeightedEdgeType", () => {
|
||||
it("sets default weights as specified in the type", () => {
|
||||
const wet = defaultWeightedEdgeType(assemblesEdgeType);
|
||||
expect(wet.forwardWeight).toEqual(wet.type.defaultForwardWeight);
|
||||
expect(wet.backwardWeight).toEqual(wet.type.defaultBackwardWeight);
|
||||
});
|
||||
});
|
||||
describe("defaultWeightsForAdapter", () => {
|
||||
it("works on the demo adapter", () => {
|
||||
const adapter = new FactorioStaticAdapter();
|
||||
const expected = {
|
||||
nodes: new Map(
|
||||
adapter
|
||||
.declaration()
|
||||
.nodeTypes.map((x) => [x.prefix, defaultWeightedNodeType(x)])
|
||||
),
|
||||
edges: new Map(
|
||||
adapter
|
||||
.declaration()
|
||||
.edgeTypes.map((x) => [x.prefix, defaultWeightedEdgeType(x)])
|
||||
),
|
||||
};
|
||||
const expected = defaultWeightsForDeclaration(declaration);
|
||||
expect(defaultWeightsForAdapter(adapter)).toEqual(expected);
|
||||
});
|
||||
});
|
||||
describe("combineWeights", () => {
|
||||
const defaultWeights = () =>
|
||||
defaultWeightsForAdapter(new FactorioStaticAdapter());
|
||||
const emptyWeights = () => ({nodes: new Map(), edges: new Map()});
|
||||
it("successfully combines WeightedTypes", () => {
|
||||
const weights1 = {
|
||||
nodes: new Map().set(
|
||||
inserterNodeType.prefix,
|
||||
defaultWeightedNodeType(inserterNodeType)
|
||||
),
|
||||
edges: new Map().set(
|
||||
assemblesEdgeType.prefix,
|
||||
defaultWeightedEdgeType(assemblesEdgeType)
|
||||
),
|
||||
};
|
||||
const weights2 = {
|
||||
nodes: new Map().set(
|
||||
machineNodeType.prefix,
|
||||
defaultWeightedNodeType(machineNodeType)
|
||||
),
|
||||
edges: new Map().set(
|
||||
transportsEdgeType.prefix,
|
||||
defaultWeightedEdgeType(transportsEdgeType)
|
||||
),
|
||||
};
|
||||
expect(combineWeights([weights1, weights2])).toEqual(defaultWeights());
|
||||
});
|
||||
it("treats empty weights as an identity", () => {
|
||||
expect(
|
||||
combineWeights([emptyWeights(), defaultWeights(), emptyWeights()])
|
||||
).toEqual(defaultWeights());
|
||||
});
|
||||
it("errors on duplicate edge prefix", () => {
|
||||
const weights = {
|
||||
nodes: new Map(),
|
||||
edges: new Map().set(
|
||||
assemblesEdgeType.prefix,
|
||||
defaultWeightedEdgeType(assemblesEdgeType)
|
||||
),
|
||||
};
|
||||
expect(() => combineWeights([weights, weights])).toThrowError(
|
||||
"duplicate key"
|
||||
);
|
||||
});
|
||||
it("errors on duplicate node prefix", () => {
|
||||
const weights = {
|
||||
nodes: new Map().set(
|
||||
inserterNodeType.prefix,
|
||||
defaultWeightedNodeType(inserterNodeType)
|
||||
),
|
||||
edges: new Map(),
|
||||
};
|
||||
expect(() => combineWeights([weights, weights])).toThrowError(
|
||||
"duplicate key"
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe("defaultWeightsForAdapterSet", () => {
|
||||
it("works on a demo adapter set", () => {
|
||||
expect(defaultWeightsForAdapterSet(staticAdapterSet())).toEqual(
|
||||
|
@ -1,7 +1,7 @@
|
||||
// @flow
|
||||
|
||||
import type {Edge} from "../../../core/graph";
|
||||
import type {WeightedTypes} from "./weights";
|
||||
import type {WeightedTypes} from "../../../analysis/weights";
|
||||
import type {EdgeEvaluator} from "../../../analysis/pagerank";
|
||||
import {NodeTrie, EdgeTrie} from "../../../core/trie";
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user