diff --git a/packages/sourcecred/src/core/credequate/scoredContribution.js b/packages/sourcecred/src/core/credequate/scoredContribution.js index eccb7b365..0caeeaee2 100644 --- a/packages/sourcecred/src/core/credequate/scoredContribution.js +++ b/packages/sourcecred/src/core/credequate/scoredContribution.js @@ -112,6 +112,37 @@ export const scoreContribution = ( }; }; +export function expressionHasSubkey( + expression: Expression | ScoredExpression, + key: string, + subkey: string +): boolean { + for (const weightOperand of expression.weightOperands) { + if (weightOperand.key === key && weightOperand.subkey === subkey) + return true; + } + for (const expressionOperand of expression.expressionOperands) { + if (expressionHasSubkey(expressionOperand, key, subkey)) return true; + } + return false; +} + +export function* findContributionsBySubkey< + T: Contribution | ScoredContribution +>(contributions: Iterable, key: string, subkey: string): Iterable { + for (const contribution of contributions) { + if (expressionHasSubkey(contribution.expression, key, subkey)) + yield contribution; + else { + for (const participant of contribution.participants) { + for (const share of participant.shares) { + if (share.key === key && share.subkey === subkey) yield contribution; + } + } + } + } +} + export function* scoreContributions( contributions: Iterable, configs: $ReadOnlyArray diff --git a/packages/sourcecred/src/core/credequate/scoredContribution.test.js b/packages/sourcecred/src/core/credequate/scoredContribution.test.js new file mode 100644 index 000000000..49f00f9bc --- /dev/null +++ b/packages/sourcecred/src/core/credequate/scoredContribution.test.js @@ -0,0 +1,92 @@ +// @flow + +import {findContributionsBySubkey} from "./scoredContribution.js"; +import {type Contribution, type Expression} from "./contribution.js"; +import {NodeAddress} from "../graph.js"; + +describe("core/credequate/scoredContribution", () => { + const weightOperand0 = { + key: ":key0:", + subkey: ":subkey0:", + }; + + const weightOperand1 = { + key: ":key1:", + subkey: ":subkey1:", + }; + const weightOperand2 = { + key: ":key2:", + subkey: ":subkey2:", + }; + + const weightOperand3 = { + key: ":key3:", + subkey: ":subkey3:", + }; + const weightOperand4 = { + key: ":key4:", + subkey: ":subkey4:", + }; + + const weightOperand5 = { + key: ":key5:", + subkey: ":subkey5:", + }; + + const expression: Expression = { + operator: "ADD", + expressionOperands: [], + description: "", + weightOperands: [weightOperand0, weightOperand1], + }; + + const participants = [ + { + id: NodeAddress.fromParts(["amrro"]), + shares: [weightOperand2, weightOperand3], + }, + { + id: NodeAddress.fromParts(["thena"]), + shares: [weightOperand4, weightOperand5], + }, + ]; + + const contribution: Contribution = { + id: "one", + plugin: "discord", + type: "", + timestampMs: 0, + expression, + participants, + }; + + it("should find contributions with matching expression's key & subkey", () => { + const iter = findContributionsBySubkey( + [contribution], + expression.weightOperands[0].key, + expression.weightOperands[0].subkey ?? "" + ); + + const contributions = Array.from(iter); + expect(contributions).toEqual([contribution]); + }); + + it("should find contributions with matching participant's share's key & subkey", () => { + const iter = findContributionsBySubkey( + [contribution], + contribution.participants[0].shares[0].key, + contribution.participants[0].shares[0].subkey ?? "" + ); + + const contributions = Array.from(iter); + expect(contributions).toEqual([contribution]); + }); + + it("shouldn't find any contributions", () => { + const iter = findContributionsBySubkey([contribution], "channel", "abcd"); + + const contributions = Array.from(iter); + console.log(contributions); + expect(contributions).toEqual([]); + }); +});