Update output format to include credOverTime (#1791)
As requested by @s-ben, we map now include cred over time for all contributions, not just contributors. Based on discussion with @Beanow, we made it an optional field so that we can optionally filter to save space instead. I was initially concerned that we wouldn't be able to compute credOverTime for non-user nodes in CredRank, which is why I left it out. However, informed by discussions with @mZargham, I'm less concerned because PageRank (and thus CredRank) is a linear operator on the seed vector. So, if we want to compute the "cred over time" for individual contributions in CredRank, we can do so by constructing time-specific seed vectors (which flow only to activity minting cred in the specified interval), and the sum of contributions time-scoped cred will be equal to the non-time-scoped cred. It's good that we'll still have the epoch nodes for users, as that will allow us to model sponsorship cred flow dynamics. cc @wchargin for CredRank considerations. Test plan: Unit tests updated, `yarn test` passes.
This commit is contained in:
parent
ec56ce79c8
commit
91ca897d99
File diff suppressed because it is too large
Load Diff
|
@ -18,7 +18,7 @@ export type CredFlow = {|+forwards: number, +backwards: number|};
|
|||
export type Output = OutputV1;
|
||||
export const COMPAT_INFO = {
|
||||
type: "sourcecred/analysis/output",
|
||||
version: "0.1.0",
|
||||
version: "0.2.0",
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -33,6 +33,10 @@ export const COMPAT_INFO = {
|
|||
export type OutputNode = {|
|
||||
+address: $ReadOnlyArray<string>,
|
||||
+cred: number,
|
||||
// Full cred over time (aligned with output interval boundaries).
|
||||
// It's optional because it inflates the output size a lot -- we'll
|
||||
// want to filter out low-cred nodes for large projects
|
||||
+credOverTime: ?$ReadOnlyArray<number>,
|
||||
+minted: number,
|
||||
+timestamp: TimestampMs | null,
|
||||
// Description comes from the underlying Graph node, so it's determined by the
|
||||
|
@ -50,6 +54,8 @@ export type OutputV1 = {|
|
|||
// Ordered by address
|
||||
+orderedNodes: $ReadOnlyArray<OutputNode>,
|
||||
+plugins: $ReadOnlyArray<PluginDeclaration>,
|
||||
// Interval endpoints, aligned with credOverTime
|
||||
+intervalEndpoints: $ReadOnlyArray<TimestampMs>,
|
||||
|};
|
||||
|
||||
export function fromTimelineCredAndPlugins(
|
||||
|
@ -58,23 +64,26 @@ export function fromTimelineCredAndPlugins(
|
|||
): Output {
|
||||
const {graph, weights} = tc.weightedGraph();
|
||||
const nodeEvaluator = nodeWeightEvaluator(weights);
|
||||
const intervalEndpoints = tc.intervals().map((x) => x.endTimeMs);
|
||||
const orderedNodes = Array.from(graph.nodes()).map(
|
||||
({description, address, timestampMs}) => {
|
||||
const cred = NullUtil.get(tc.credNode(address)).total;
|
||||
const {cred, total} = NullUtil.get(tc.credNode(address));
|
||||
// In TimelineCred, a node with a null timestamp will never mint cred, because we don't
|
||||
// know what period to mint it in.
|
||||
// When we transition to CredRank, we should remove this check.
|
||||
const minted = timestampMs == null ? 0 : nodeEvaluator(address);
|
||||
return {
|
||||
address: NodeAddress.toParts(address),
|
||||
cred,
|
||||
cred: total,
|
||||
// todo: add optional filtering to reduce the data size
|
||||
credOverTime: cred,
|
||||
minted,
|
||||
description,
|
||||
timestamp: timestampMs,
|
||||
};
|
||||
}
|
||||
);
|
||||
return {orderedNodes, plugins};
|
||||
return {orderedNodes, plugins, intervalEndpoints};
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -115,7 +124,7 @@ export type OutputV2 = {|
|
|||
+orderedNodes: $ReadOnlyArray<OutputNode>,
|
||||
+plugins: $ReadOnlyArray<PluginDeclaration>,
|
||||
+contributors: $ReadOnlyArray<Contributor>,
|
||||
+intervalEnd: $ReadOnlyArray<TimestampMs>,
|
||||
+intervalEndpoints: $ReadOnlyArray<TimestampMs>,
|
||||
|};
|
||||
|
||||
/**
|
||||
|
|
|
@ -122,5 +122,15 @@ describe("src/analysis/output", () => {
|
|||
expect(cred).toEqual(credNode.total);
|
||||
}
|
||||
});
|
||||
it("by default, all nodes have cred over time", () => {
|
||||
const {output, timelineCred} = example();
|
||||
for (const {address, credOverTime} of output.orderedNodes) {
|
||||
const credNode = timelineCred.credNode(NodeAddress.fromParts(address));
|
||||
if (credNode == null) {
|
||||
throw new Error("Can't find node");
|
||||
}
|
||||
expect(credOverTime).toEqual(credNode.cred);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue