Persist Cred Explorer weights in LocalStore (#493)
The implementation is similar to the LocalStore usage in `credExplorer/app.js`. Had to make a spurious refactor from Map to Object because ES6 maps don't stringify by default, and I didn't feel like writing a custom JSON serializer. Test plan: Didn't add unit tests, although at some point we should come up with a nice LocalStore mock and test LocalStore code. I did, however, manually try it out and verify that it works :) Paired with @wchargin
This commit is contained in:
parent
50792a7088
commit
95fca7db17
|
@ -11,6 +11,7 @@ import {
|
|||
|
||||
import {type EdgeEvaluator} from "../../core/attribution/pagerank";
|
||||
import {byEdgeType, byNodeType} from "./edgeWeights";
|
||||
import LocalStore from "./LocalStore";
|
||||
|
||||
// Hacks...
|
||||
import * as GithubNode from "../../plugins/github/nodes";
|
||||
|
@ -22,37 +23,45 @@ type Props = {
|
|||
onChange: (EdgeEvaluator) => void,
|
||||
};
|
||||
|
||||
// The key should be an EdgeAddressT, but a Flow bug prevents this.
|
||||
type EdgeWeights = {[string]: UserEdgeWeight};
|
||||
type UserEdgeWeight = {|+logWeight: number, +directionality: number|};
|
||||
const EDGE_WEIGHTS_KEY = "edgeWeights";
|
||||
const defaultEdgeWeights = (): EdgeWeights => ({
|
||||
[(GithubEdge._Prefix.authors: string)]: {logWeight: 0, directionality: 0.5},
|
||||
[(GithubEdge._Prefix.mergedAs: string)]: {logWeight: 0, directionality: 0.5},
|
||||
[(GithubEdge._Prefix.references: string)]: {
|
||||
logWeight: 0,
|
||||
directionality: 0.5,
|
||||
},
|
||||
[(GithubEdge._Prefix.hasParent: string)]: {logWeight: 0, directionality: 0.5},
|
||||
[(GitEdge._Prefix.hasTree: string)]: {logWeight: 0, directionality: 0.5},
|
||||
[(GitEdge._Prefix.hasParent: string)]: {logWeight: 0, directionality: 0.5},
|
||||
[(GitEdge._Prefix.includes: string)]: {logWeight: 0, directionality: 0.5},
|
||||
[(GitEdge._Prefix.becomes: string)]: {logWeight: 0, directionality: 0.5},
|
||||
[(GitEdge._Prefix.hasContents: string)]: {logWeight: 0, directionality: 0.5},
|
||||
});
|
||||
|
||||
// The key should be a NodeAddressT, but a Flow bug prevents this.
|
||||
type NodeWeights = {[string]: UserNodeWeight};
|
||||
type UserNodeWeight = number /* in log space */;
|
||||
|
||||
const defaultEdgeWeights = (): Map<EdgeAddressT, UserEdgeWeight> =>
|
||||
new Map()
|
||||
.set(GithubEdge._Prefix.authors, {logWeight: 0, directionality: 0.5})
|
||||
.set(GithubEdge._Prefix.mergedAs, {logWeight: 0, directionality: 0.5})
|
||||
.set(GithubEdge._Prefix.references, {logWeight: 0, directionality: 0.5})
|
||||
.set(GithubEdge._Prefix.hasParent, {logWeight: 0, directionality: 0.5})
|
||||
.set(GitEdge._Prefix.hasTree, {logWeight: 0, directionality: 0.5})
|
||||
.set(GitEdge._Prefix.hasParent, {logWeight: 0, directionality: 0.5})
|
||||
.set(GitEdge._Prefix.includes, {logWeight: 0, directionality: 0.5})
|
||||
.set(GitEdge._Prefix.becomes, {logWeight: 0, directionality: 0.5})
|
||||
.set(GitEdge._Prefix.hasContents, {logWeight: 0, directionality: 0.5});
|
||||
|
||||
const defaultNodeWeights = (): Map<NodeAddressT, UserNodeWeight> =>
|
||||
new Map()
|
||||
.set(GithubNode._Prefix.repo, 0)
|
||||
.set(GithubNode._Prefix.issue, 0)
|
||||
.set(GithubNode._Prefix.pull, 0)
|
||||
.set(GithubNode._Prefix.review, 0)
|
||||
.set(GithubNode._Prefix.comment, 0)
|
||||
.set(GithubNode._Prefix.userlike, 0)
|
||||
.set(GitNode._Prefix.blob, 0)
|
||||
.set(GitNode._Prefix.commit, 0)
|
||||
.set(GitNode._Prefix.tree, 0)
|
||||
.set(GitNode._Prefix.treeEntry, 0);
|
||||
const NODE_WEIGHTS_KEY = "nodeWeights";
|
||||
const defaultNodeWeights = (): NodeWeights => ({
|
||||
[(GithubNode._Prefix.repo: string)]: 0,
|
||||
[(GithubNode._Prefix.issue: string)]: 0,
|
||||
[(GithubNode._Prefix.pull: string)]: 0,
|
||||
[(GithubNode._Prefix.review: string)]: 0,
|
||||
[(GithubNode._Prefix.comment: string)]: 0,
|
||||
[(GithubNode._Prefix.userlike: string)]: 0,
|
||||
[(GitNode._Prefix.blob: string)]: 0,
|
||||
[(GitNode._Prefix.commit: string)]: 0,
|
||||
[(GitNode._Prefix.tree: string)]: 0,
|
||||
[(GitNode._Prefix.treeEntry: string)]: 0,
|
||||
});
|
||||
|
||||
type State = {
|
||||
edgeWeights: Map<EdgeAddressT, UserEdgeWeight>,
|
||||
nodeWeights: Map<NodeAddressT, UserNodeWeight>,
|
||||
edgeWeights: EdgeWeights,
|
||||
nodeWeights: NodeWeights,
|
||||
};
|
||||
|
||||
export class WeightConfig extends React.Component<Props, State> {
|
||||
|
@ -63,6 +72,17 @@ export class WeightConfig extends React.Component<Props, State> {
|
|||
nodeWeights: defaultNodeWeights(),
|
||||
};
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.setState(
|
||||
(state) => ({
|
||||
edgeWeights: LocalStore.get(EDGE_WEIGHTS_KEY, state.edgeWeights),
|
||||
nodeWeights: LocalStore.get(NODE_WEIGHTS_KEY, state.nodeWeights),
|
||||
}),
|
||||
() => this.fire()
|
||||
);
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div
|
||||
|
@ -84,34 +104,32 @@ export class WeightConfig extends React.Component<Props, State> {
|
|||
);
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.fire();
|
||||
}
|
||||
|
||||
fire() {
|
||||
const {edgeWeights, nodeWeights} = this.state;
|
||||
const edgePrefixes = Array.from(edgeWeights.entries()).map(
|
||||
([prefix, {logWeight, directionality}]) => ({
|
||||
prefix,
|
||||
weight: 2 ** logWeight,
|
||||
directionality,
|
||||
})
|
||||
);
|
||||
const nodePrefixes = Array.from(nodeWeights.entries()).map(
|
||||
([prefix, logWeight]) => ({prefix, weight: 2 ** logWeight})
|
||||
);
|
||||
LocalStore.set(EDGE_WEIGHTS_KEY, edgeWeights);
|
||||
LocalStore.set(NODE_WEIGHTS_KEY, nodeWeights);
|
||||
const edgePrefixes = Object.keys(edgeWeights).map((key) => {
|
||||
const {logWeight, directionality} = edgeWeights[key];
|
||||
const prefix: EdgeAddressT = (key: any);
|
||||
return {prefix, weight: 2 ** logWeight, directionality};
|
||||
});
|
||||
const nodePrefixes = Object.keys(nodeWeights).map((key) => ({
|
||||
prefix: ((key: any): NodeAddressT),
|
||||
weight: 2 ** nodeWeights[key],
|
||||
}));
|
||||
const edgeEvaluator = byNodeType(byEdgeType(edgePrefixes), nodePrefixes);
|
||||
this.props.onChange(edgeEvaluator);
|
||||
}
|
||||
}
|
||||
|
||||
class EdgeConfig extends React.Component<{
|
||||
edgeWeights: Map<EdgeAddressT, UserEdgeWeight>,
|
||||
onChange: (Map<EdgeAddressT, UserEdgeWeight>) => void,
|
||||
edgeWeights: EdgeWeights,
|
||||
onChange: (EdgeWeights) => void,
|
||||
}> {
|
||||
render() {
|
||||
const controls = [];
|
||||
for (const [key, currentValue] of this.props.edgeWeights.entries()) {
|
||||
for (const key of Object.keys(this.props.edgeWeights)) {
|
||||
const {logWeight} = this.props.edgeWeights[key];
|
||||
controls.push(
|
||||
<label style={{display: "block"}} key={key}>
|
||||
<input
|
||||
|
@ -119,20 +137,18 @@ class EdgeConfig extends React.Component<{
|
|||
min={-10}
|
||||
max={10}
|
||||
step={0.1}
|
||||
value={currentValue.logWeight}
|
||||
value={logWeight}
|
||||
onChange={(e) => {
|
||||
const value: number = e.target.valueAsNumber;
|
||||
const edgeWeights = new Map(this.props.edgeWeights);
|
||||
const oldValue = edgeWeights.get(key);
|
||||
if (oldValue == null) {
|
||||
throw new Error(key);
|
||||
}
|
||||
edgeWeights.set(key, {...oldValue, logWeight: value});
|
||||
const edgeWeights = {
|
||||
...this.props.edgeWeights,
|
||||
[key]: {...this.props.edgeWeights[key], logWeight: value},
|
||||
};
|
||||
this.props.onChange(edgeWeights);
|
||||
}}
|
||||
/>{" "}
|
||||
{formatNumber(currentValue.logWeight)}{" "}
|
||||
{JSON.stringify(EdgeAddress.toParts(key))}
|
||||
{formatNumber(logWeight)}{" "}
|
||||
{JSON.stringify(EdgeAddress.toParts((key: any)))}
|
||||
</label>
|
||||
);
|
||||
}
|
||||
|
@ -146,12 +162,13 @@ class EdgeConfig extends React.Component<{
|
|||
}
|
||||
|
||||
class NodeConfig extends React.Component<{
|
||||
nodeWeights: Map<NodeAddressT, UserNodeWeight>,
|
||||
onChange: (Map<NodeAddressT, UserNodeWeight>) => void,
|
||||
nodeWeights: NodeWeights,
|
||||
onChange: (NodeWeights) => void,
|
||||
}> {
|
||||
render() {
|
||||
const controls = [];
|
||||
for (const [key, currentValue] of this.props.nodeWeights.entries()) {
|
||||
for (const key of Object.keys(this.props.nodeWeights)) {
|
||||
const currentValue = this.props.nodeWeights[key];
|
||||
controls.push(
|
||||
<label style={{display: "block"}} key={key}>
|
||||
<input
|
||||
|
@ -162,13 +179,12 @@ class NodeConfig extends React.Component<{
|
|||
value={currentValue}
|
||||
onChange={(e) => {
|
||||
const value: number = e.target.valueAsNumber;
|
||||
const nodeWeights = new Map(this.props.nodeWeights);
|
||||
nodeWeights.set(key, value);
|
||||
const nodeWeights = {...this.props.nodeWeights, [key]: value};
|
||||
this.props.onChange(nodeWeights);
|
||||
}}
|
||||
/>{" "}
|
||||
{formatNumber(currentValue)}{" "}
|
||||
{JSON.stringify(NodeAddress.toParts(key))}
|
||||
{JSON.stringify(NodeAddress.toParts((key: any)))}
|
||||
</label>
|
||||
);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue