Преглед на файлове

Continue Burndown.Merge development

Vadim Markovtsev преди 7 години
родител
ревизия
7d82a017d1
променени са 4 файла, в които са добавени 122 реда и са изтрити 17 реда
  1. 77 6
      burndown.go
  2. 5 6
      labours.py
  3. 14 5
      pipeline.go
  4. 26 0
      pipeline_test.go

+ 77 - 6
burndown.go

@@ -307,7 +307,7 @@ func (analyser *BurndownAnalysis) MergeResults(
 	r1, r2 interface{}, c1, c2 *CommonAnalysisResult) interface{} {
 	bar1 := r1.(BurndownResult)
 	bar2 := r2.(BurndownResult)
-  merged := BurndownResult{}
+	merged := BurndownResult{}
 	if bar1.sampling < bar2.sampling {
 		merged.sampling = bar1.sampling
 	} else {
@@ -318,9 +318,20 @@ func (analyser *BurndownAnalysis) MergeResults(
 	} else {
 		merged.granularity = bar2.granularity
 	}
-	people := make([]string, len(bar1.reversedPeopleDict))
-	copy(people, bar1.reversedPeopleDict)
-	merged.reversedPeopleDict = append(people, bar2.reversedPeopleDict...)
+	people := map[string]int{}
+	for _, id := range bar1.reversedPeopleDict {
+		people[id] = len(people)
+	}
+	for _, id := range bar2.reversedPeopleDict {
+		if _, exists := people[id]; !exists {
+			people[id] = len(people)
+		}
+	}
+	merged.reversedPeopleDict = make([]string, len(people))
+	for name, index := range people {
+		merged.reversedPeopleDict[index] = name
+	}
+
 	// interpolate to daily and sum
 	_ = bar1
 	_ = bar2
@@ -328,8 +339,68 @@ func (analyser *BurndownAnalysis) MergeResults(
 	// return merged
 }
 
-func interpolateMatrix(matrix [][]int64, granularity, sampling int, daily [][]int64, offset int) {
-
+func mergeMatrices(m1, m2 [][]int64, granularity1, sampling1, granularity2, sampling2 int,
+	c1, c2 *CommonAnalysisResult) {
+	commonMerged := CommonAnalysisResult{}
+	commonMerged.Merge(c1)
+	commonMerged.Merge(c2)
+	size := (commonMerged.EndTime - commonMerged.BeginTime) / (3600 * 24)
+	daily := make([][]float32, size)
+	for i := range daily {
+		daily[i] = make([]float32, size)
+	}
+	addMatrix(m1, granularity1, sampling1, daily,
+		int(c1.BeginTime-commonMerged.BeginTime)/(3600*24))
+	addMatrix(m2, granularity2, sampling2, daily,
+		int(c2.BeginTime-commonMerged.BeginTime)/(3600*24))
+	// convert daily to [][]int64
+}
+
+func addMatrix(matrix [][]int64, granularity, sampling int, daily [][]float32, offset int) {
+	/*
+	 daily_matrix = numpy.zeros(
+	            (matrix.shape[0] * granularity, matrix.shape[1] * sampling),
+	            dtype=numpy.float32)
+	*/
+	// Determine the maximum number of bands; the actual one may be larger but we do not care
+	maxCols := 0
+	for _, row := range matrix {
+		if maxCols < len(row) {
+			maxCols = len(row)
+		}
+	}
+	// Ported from labours.py load_burndown()
+	for y := 0; y < maxCols; y++ {
+		for x := 0; x < len(matrix); x++ {
+			if (y+1)*granularity <= x*sampling {
+				// interpolate
+				var previous int64
+				if x > 0 && y < len(matrix[x-1]) {
+					previous = matrix[x-1][y]
+				}
+				for i := 0; i < sampling; i++ {
+					var value float32
+					if y < len(matrix[x]) {
+						value = (float32(previous) +
+							float32((matrix[x][y]-previous)*int64(i))/float32(sampling)) / float32(granularity)
+					} else {
+						value = float32(previous) *
+							(float32(1) - float32(i)/float32(sampling)) / float32(granularity)
+					}
+					for j := y * granularity; j < (y+1)*granularity; j++ {
+						daily[j+offset][x*sampling+i+offset] += value
+					}
+				}
+			} else if y*granularity <= (x+1)*sampling && y < len(matrix[x]) {
+				// fill constant
+				for suby := y*granularity + offset; suby < (y+1)*granularity+offset; suby++ {
+					for subx := suby; subx < (x+1)*sampling+offset; subx++ {
+						daily[suby][subx] += float32(matrix[x][y]) / float32(granularity)
+					}
+				}
+			}
+		}
+	}
 }
 
 func (analyser *BurndownAnalysis) serializeText(result *BurndownResult, writer io.Writer) {

+ 5 - 6
labours.py

@@ -295,17 +295,16 @@ def load_burndown(header, name, matrix, resample):
         epsrange = numpy.arange(0, 1, 1.0 / sampling)
         for y in range(matrix.shape[0]):
             for x in range(matrix.shape[1]):
-                previous = matrix[y, x - 1] if x > 0 else 0
-                value = ((previous + (matrix[y, x] - previous) * epsrange)
-                         / granularity)[numpy.newaxis, :]
                 if (y + 1) * granularity <= x * sampling:
+                    previous = matrix[y, x - 1] if x > 0 else 0
+                    value = ((previous + (matrix[y, x] - previous) * epsrange)
+                             / granularity)[numpy.newaxis, :]
                     daily_matrix[y * granularity:(y + 1) * granularity,
                     x * sampling:(x + 1) * sampling] = value
                 elif y * granularity <= (x + 1) * sampling:
                     for suby in range(y * granularity, (y + 1) * granularity):
                         for subx in range(suby, (x + 1) * sampling):
-                            daily_matrix[suby, subx] = matrix[
-                                                           y, x] / granularity
+                            daily_matrix[suby, subx] = matrix[y, x] / granularity
         daily_matrix[(last - start).days:] = 0
         # Resample the bands
         aliases = {
@@ -337,7 +336,7 @@ def load_burndown(header, name, matrix, resample):
                     break
             matrix[i, j:] = \
                 daily_matrix[istart:ifinish, (sdt - start).days:].sum(axis=0)
-        # Hardcode some cases to improve labels" readability
+        # Hardcode some cases to improve labels' readability
         if resample in ("year", "A"):
             labels = [dt.year for dt in date_granularity_sampling]
         elif resample in ("month", "M"):

+ 14 - 5
pipeline.go

@@ -116,11 +116,12 @@ type CommonAnalysisResult struct {
 	RunTime time.Duration
 }
 
-func (car *CommonAnalysisResult) FillMetadata(meta *pb.Metadata) {
-	meta.BeginUnixTime = car.BeginTime
-	meta.EndUnixTime = car.EndTime
-	meta.Commits = int32(car.CommitsNumber)
-	meta.RunTime = car.RunTime.Nanoseconds() / 1e6
+func (car *CommonAnalysisResult) BeginTimeAsTime() time.Time {
+	return time.Unix(car.BeginTime, 0)
+}
+
+func (car *CommonAnalysisResult) EndTimeAsTime() time.Time {
+	return time.Unix(car.EndTime, 0)
 }
 
 func (car *CommonAnalysisResult) Merge(other *CommonAnalysisResult) {
@@ -134,6 +135,14 @@ func (car *CommonAnalysisResult) Merge(other *CommonAnalysisResult) {
 	car.RunTime += other.RunTime
 }
 
+func (car *CommonAnalysisResult) FillMetadata(meta *pb.Metadata) *pb.Metadata {
+	meta.BeginUnixTime = car.BeginTime
+	meta.EndUnixTime = car.EndTime
+	meta.Commits = int32(car.CommitsNumber)
+	meta.RunTime = car.RunTime.Nanoseconds() / 1e6
+	return meta
+}
+
 func MetadataToCommonAnalysisResult(meta *pb.Metadata) *CommonAnalysisResult {
 	return &CommonAnalysisResult{
 		BeginTime:     meta.BeginUnixTime,

+ 26 - 0
pipeline_test.go

@@ -15,6 +15,7 @@ import (
 	"gopkg.in/src-d/go-git.v4/plumbing"
 	"gopkg.in/src-d/go-git.v4/plumbing/object"
 	"gopkg.in/src-d/go-git.v4/storage/memory"
+	"gopkg.in/src-d/hercules.v3/pb"
 )
 
 type testPipelineItem struct {
@@ -405,6 +406,31 @@ func TestPipelineSerializeNoUast(t *testing.T) {
 }`, dot)
 }
 
+func TestCommonAnalysisResultMerge(t *testing.T) {
+	c1 := CommonAnalysisResult{
+		BeginTime: 1513620635, EndTime: 1513720635, CommitsNumber: 1, RunTime: 100}
+	assert.Equal(t, c1.BeginTimeAsTime().Unix(), int64(1513620635))
+	assert.Equal(t, c1.EndTimeAsTime().Unix(), int64(1513720635))
+	c2 := CommonAnalysisResult{
+		BeginTime: 1513620535, EndTime: 1513730635, CommitsNumber: 2, RunTime: 200}
+	c1.Merge(&c2)
+	assert.Equal(t, c1.BeginTime, int64(1513620535))
+	assert.Equal(t, c1.EndTime, int64(1513730635))
+	assert.Equal(t, c1.CommitsNumber, 3)
+	assert.Equal(t, c1.RunTime.Nanoseconds(), int64(300))
+}
+
+func TestCommonAnalysisResultMetadata(t *testing.T) {
+	c1 := &CommonAnalysisResult{
+		BeginTime: 1513620635, EndTime: 1513720635, CommitsNumber: 1, RunTime: 100 * 1e6}
+	meta := &pb.Metadata{}
+	c1 = MetadataToCommonAnalysisResult(c1.FillMetadata(meta))
+	assert.Equal(t, c1.BeginTimeAsTime().Unix(), int64(1513620635))
+	assert.Equal(t, c1.EndTimeAsTime().Unix(), int64(1513720635))
+	assert.Equal(t, c1.CommitsNumber, 1)
+	assert.Equal(t, c1.RunTime.Nanoseconds(), int64(100*1e6))
+}
+
 func init() {
 	cwd, err := os.Getwd()
 	if err == nil {