[pinpoint] parse values per commit

Create a helper function to parse values from combinedresults into a map
of combinedcommit keys to the values. This assumes that the values generated
for a combinedcommit is re-used.

Bug: b/335543541
Change-Id: I6d5b0b0617efe0432975111e1041fed3adc15428
Reviewed-on: https://skia-review.googlesource.com/c/buildbot/+/842945
Reviewed-by: Leina Sun <sunxiaodi@google.com>
Commit-Queue: Jeff Yoon <jeffyoon@google.com>
diff --git a/pinpoint/go/workflows/catapult/parsers.go b/pinpoint/go/workflows/catapult/parsers.go
index b7bd352..63835d3 100644
--- a/pinpoint/go/workflows/catapult/parsers.go
+++ b/pinpoint/go/workflows/catapult/parsers.go
@@ -119,6 +119,19 @@
 	return commitToAttempts, bots, nil
 }
 
+// parseResultValuesPerCommit converts combinedresults into an accessible map of combinedcommit's keys to its values.
+//
+// This assumes that result values are re-used, so for Combined Commits that appear multiple times in comparisons
+// the values should be the same.
+func parseResultValuesPerCommit(comparisons []*internal.CombinedResults) map[uint32][]float64 {
+	resp := map[uint32][]float64{}
+	for _, comparison := range comparisons {
+		resp[comparison.CommitPairValues.Lower.Commit.Key()] = comparison.CommitPairValues.Lower.Values
+		resp[comparison.CommitPairValues.Higher.Commit.Key()] = comparison.CommitPairValues.Higher.Values
+	}
+	return resp
+}
+
 // parseRawDataToLegacyObject does the heavy lifting of converting all the raw run data to objects needed for the LegacyJobResponse.
 func parseRawDataToLegacyObject(ctx workflow.Context, comparisons []*internal.CombinedResults, runData []*internal.BisectRun) ([]*pinpoint_proto.LegacyJobResponse_State, []string, error) {
 	states := []*pinpoint_proto.LegacyJobResponse_State{}
diff --git a/pinpoint/go/workflows/catapult/parsers_test.go b/pinpoint/go/workflows/catapult/parsers_test.go
index 373c954..002159a 100644
--- a/pinpoint/go/workflows/catapult/parsers_test.go
+++ b/pinpoint/go/workflows/catapult/parsers_test.go
@@ -99,3 +99,44 @@
 	assert.Equal(t, 1, len(actual.Bots))
 	assert.Equal(t, botID, actual.Bots[0])
 }
+
+// createCombinedResults a helper function to generate combinedresults
+func createCombinedResults(lower string, lowerValues []float64, higher string, higherValues []float64) *internal.CombinedResults {
+	return &internal.CombinedResults{
+		CommitPairValues: internal.CommitPairValues{
+			Lower: internal.CommitValues{
+				Commit: midpoint.NewCombinedCommit(midpoint.NewChromiumCommit(lower)),
+				Values: lowerValues,
+			},
+			Higher: internal.CommitValues{
+				Commit: midpoint.NewCombinedCommit(midpoint.NewChromiumCommit(higher)),
+				Values: higherValues,
+			},
+		},
+	}
+}
+
+func TestParseResultValuesPerCommit_ListOfCombinedResults_MapOfKeysToValues(t *testing.T) {
+	// commit order from oldest to newest: 493a946, 2887740, 93dd3db, 836476df, f8e1800
+	comparisons := []*internal.CombinedResults{
+		// initial range
+		createCombinedResults("493a946", []float64{0.0}, "f8e1800", []float64{5.0}),
+		// midpoint comparisons with 93dd3db
+		createCombinedResults("93dd3db", []float64{3.0}, "f8e1800", []float64{5.0}),
+		createCombinedResults("493a946", []float64{0.0}, "93dd3db", []float64{3.0}),
+		// lower side midpoint 2887740 comparisons
+		createCombinedResults("493a946", []float64{0.0}, "2887740", []float64{1.0}),
+		createCombinedResults("2887740", []float64{1.0}, "93dd3db", []float64{3.0}),
+		// higher side midpoint 8d36476df comparisons
+		createCombinedResults("93dd3db", []float64{3.0}, "836476df", []float64{4.0}),
+		createCombinedResults("836476df", []float64{4.0}, "f8e1800", []float64{5.0}),
+	}
+	res := parseResultValuesPerCommit(comparisons)
+	require.NotNil(t, res)
+	assert.Equal(t, 5, len(res))
+	// spot checking a few
+	baseCommit := midpoint.NewCombinedCommit(midpoint.NewChromiumCommit("493a946"))
+	assert.Equal(t, 0.0, res[baseCommit.Key()][0])
+	fourthCommit := midpoint.NewCombinedCommit(midpoint.NewChromiumCommit("836476df"))
+	assert.Equal(t, 4.0, res[fourthCommit.Key()][0])
+}