func Means(properties map[string][]string) map[string]float64 {
	out := make(map[string]float64, len(properties))
	for name, values := range properties {
		var sum float64
		var n int
		for _, str := range values {
			v, err := strconv.ParseFloat(str, 64)
			if err != nil {
				continue
			}
			sum += v
			n++
		}
		if n == 0 {
			continue
		}
		out[name] = sum / float64(n)
	}
	return out
}
Means returns means for each given property's values.
package updater
import (
	"fmt"
	"sort"
	"strconv"
	"strings"
	"time"
	"github.com/sirupsen/logrus"
	"github.com/GoogleCloudPlatform/testgrid/internal/result"
	"github.com/GoogleCloudPlatform/testgrid/metadata"
	"github.com/GoogleCloudPlatform/testgrid/metadata/junit"
	statepb "github.com/GoogleCloudPlatform/testgrid/pb/state"
	statuspb "github.com/GoogleCloudPlatform/testgrid/pb/test_status"
	"github.com/GoogleCloudPlatform/testgrid/util/gcs"
)
type gcsResult struct {
	podInfo   gcs.PodInfo
	started   gcs.Started
	finished  gcs.Finished
	suites    []gcs.SuitesMeta
	job       string
	build     string
	malformed []string
}
func (r gcsResult) deadline() time.Time {
	f := r.finished.Timestamp
	if f == nil {
		return time.Unix(r.started.Timestamp, 0).Add(24 * time.Hour)
	}
	return time.Unix(*f, 0).Add(time.Hour)
}
const maxDuplicates = 20
const EmailListKey = "EmailAddresses"
var overflowCell = Cell{
	Result:  statuspb.TestStatus_FAIL,
	Icon:    "...",
	Message: "Too many duplicately named rows",
}
func propertyMap(r *junit.Result) map[string][]string {
	out := map[string][]string{}
	if r.Properties == nil {
		return out
	}
	for _, p := range r.Properties.PropertyList {
		out[p.Name] = append(out[p.Name], p.Value)
	}
	return out
}