/
credequate.js
147 lines (138 loc) · 4.62 KB
/
credequate.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
// @flow
import type {ContributionsByTarget} from "../../core/credequate/contribution";
import {
type ScoredContribution,
scoreContributions,
} from "../../core/credequate/scoredContribution";
import {type PluginId} from "../pluginId";
import type {InstanceConfig} from "../instanceConfig";
import {
ensureIdentityExists,
toBonusPolicy,
type DependenciesConfig,
} from "../../api/dependenciesConfig";
import {Ledger} from "../../core/ledger/ledger";
import {computeBonusMintingByIntervals} from "../../core/bonusMinting";
import {CredGrainView} from "../../core/credGrainView";
export type CredequateInput = {|
+pluginContributions: Iterable<{|
+pluginId: PluginId,
+contributionsByTarget: ContributionsByTarget,
|}>,
+instanceConfig: InstanceConfig,
|};
export type CredequateOutput = {|
+scoredContributions: Iterable<ScoredContribution>,
|};
/**
A primary SourceCred API that runs the CredEquate algorithm on the given
inputs to create ScoredContributions containing info on the cred scores of
contributions and the cred earned by participants in each contribution.
*/
export function credequate(input: CredequateInput): CredequateOutput {
return {scoredContributions: credequateGenerator(input)};
}
function* credequateGenerator(
input: CredequateInput
): Iterable<ScoredContribution> {
for (const plugin of input.pluginContributions) {
const configs = input.instanceConfig.credEquatePlugins.find(
(p) => p.id === plugin.pluginId
)?.configsByTarget;
if (!configs)
throw new Error(
`CredEquate configurations not found for plugin ${plugin.pluginId}`
);
for (const target of Object.keys(plugin.contributionsByTarget)) {
if (!configs[target])
throw new Error(
`CredEquate configuration not found for plugin ${plugin.pluginId} and target ${target}`
);
const iterable = scoreContributions(
plugin.contributionsByTarget[target],
configs[target]
);
for (const scoredContribution of iterable) {
yield scoredContribution;
}
}
}
}
export type DependenciesInput = {|
+credGrainView: CredGrainView,
+ledger: Ledger,
+dependencies: DependenciesConfig,
|};
export type DependenciesOutput = {|
/** The input CredGrainView merged with information from the generated
scoredContributions */
+credGrainView: CredGrainView,
+ledger: Ledger,
+dependencies: DependenciesConfig,
/** Scored contributions for the dependencies. 1 per week per dependency. */
+scoredDependencyContributions: $ReadOnlyArray<ScoredContribution>,
|};
/**
A SourceCred API that generates ScoredContributions to give bonus cred to
organizations and projects that the instance depends on or supports.
May mutate the ledger and the dependencies inputs. Will return a new
CredGrainView with dependencies included.
*/
export function dependencies(input: DependenciesInput): DependenciesOutput {
const dependenciesWithIds = input.dependencies.map((d) =>
// This mutates the ledger, adding new identities when needed.
ensureIdentityExists(d, input.ledger)
);
const bonusPolicies = dependenciesWithIds.map((d) =>
toBonusPolicy(d, input.ledger)
);
const mintIntervals = input.credGrainView
.totalCredPerInterval()
.map((cred, index) => ({
totalMint: cred,
interval: input.credGrainView.intervals()[index],
}));
const bonusIntervalsByRecipient = computeBonusMintingByIntervals(
mintIntervals,
bonusPolicies
);
const scoredDependencyContributions: $ReadOnlyArray<ScoredContribution> = bonusIntervalsByRecipient.flatMap(
({recipient, bonusIntervals}) => {
return bonusIntervals.map(({amount, interval}) => ({
id: `${recipient} / ${interval.startTimeMs}`,
expression: {
score: amount,
operator: "ADD",
description: "stubbed expression stucture for dependencies",
weightOperands: [],
expressionOperands: [],
},
plugin: "DependenciesConfig",
type: "Dependency",
timestampMs: interval.startTimeMs,
participants: [
{
id: recipient,
score: amount,
shares: [],
},
],
}));
}
);
const dependencyCredGrainView = CredGrainView.fromScoredContributionsAndLedger(
scoredDependencyContributions,
input.ledger,
mintIntervals[0].interval.startTimeMs
);
const mergedCredGrainView = CredGrainView.fromCredGrainViews(
input.credGrainView,
dependencyCredGrainView
);
return {
credGrainView: mergedCredGrainView,
ledger: input.ledger,
dependencies: dependenciesWithIds,
scoredDependencyContributions,
};
}