utils.go 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. package stdout
  2. import (
  3. "fmt"
  4. "sort"
  5. "strconv"
  6. "strings"
  7. "gopkg.in/src-d/hercules.v2"
  8. )
  9. func SafeString(str string) string {
  10. str = strings.Replace(str, "\\", "\\\\", -1)
  11. str = strings.Replace(str, "\"", "\\\"", -1)
  12. return "\"" + str + "\""
  13. }
  14. func PrintMatrix(matrix [][]int64, name string, fixNegative bool) {
  15. // determine the maximum length of each value
  16. var maxnum int64 = -(1 << 32)
  17. var minnum int64 = 1 << 32
  18. for _, status := range matrix {
  19. for _, val := range status {
  20. if val > maxnum {
  21. maxnum = val
  22. }
  23. if val < minnum {
  24. minnum = val
  25. }
  26. }
  27. }
  28. width := len(strconv.FormatInt(maxnum, 10))
  29. if !fixNegative && minnum < 0 {
  30. negativeWidth := len(strconv.FormatInt(minnum, 10))
  31. if negativeWidth > width {
  32. width = negativeWidth
  33. }
  34. }
  35. last := len(matrix[len(matrix)-1])
  36. indent := 2
  37. if name != "" {
  38. fmt.Printf(" %s: |-\n", SafeString(name))
  39. indent += 2
  40. }
  41. // print the resulting triangular matrix
  42. first := true
  43. for _, status := range matrix {
  44. fmt.Print(strings.Repeat(" ", indent-1))
  45. for i := 0; i < last; i++ {
  46. var val int64
  47. if i < len(status) {
  48. val = status[i]
  49. // not sure why this sometimes happens...
  50. // TODO(vmarkovtsev): find the root cause of tiny negative balances
  51. if fixNegative && val < 0 {
  52. val = 0
  53. }
  54. }
  55. if !first {
  56. fmt.Printf(" %[1]*[2]d", width, val)
  57. } else {
  58. first = false
  59. fmt.Printf("%d%s", val, strings.Repeat(" ", width-len(strconv.FormatInt(val, 10))))
  60. }
  61. }
  62. fmt.Println()
  63. }
  64. }
  65. func PrintCouples(result *hercules.CouplesResult, peopleDict []string) {
  66. fmt.Println("files_coocc:")
  67. fmt.Println(" index:")
  68. for _, file := range result.Files {
  69. fmt.Printf(" - %s\n", SafeString(file))
  70. }
  71. fmt.Println(" matrix:")
  72. for _, files := range result.FilesMatrix {
  73. fmt.Print(" - {")
  74. indices := []int{}
  75. for file := range files {
  76. indices = append(indices, file)
  77. }
  78. sort.Ints(indices)
  79. for i, file := range indices {
  80. fmt.Printf("%d: %d", file, files[file])
  81. if i < len(indices)-1 {
  82. fmt.Print(", ")
  83. }
  84. }
  85. fmt.Println("}")
  86. }
  87. fmt.Println("people_coocc:")
  88. fmt.Println(" index:")
  89. for _, person := range peopleDict {
  90. fmt.Printf(" - %s\n", SafeString(person))
  91. }
  92. fmt.Println(" matrix:")
  93. for _, people := range result.PeopleMatrix {
  94. fmt.Print(" - {")
  95. indices := []int{}
  96. for file := range people {
  97. indices = append(indices, file)
  98. }
  99. sort.Ints(indices)
  100. for i, person := range indices {
  101. fmt.Printf("%d: %d", person, people[person])
  102. if i < len(indices)-1 {
  103. fmt.Print(", ")
  104. }
  105. }
  106. fmt.Println("}")
  107. }
  108. fmt.Println(" author_files:") // sorted by number of files each author changed
  109. peopleFiles := sortByNumberOfFiles(result.PeopleFiles, peopleDict, result.Files)
  110. for _, authorFiles := range peopleFiles {
  111. fmt.Printf(" - %s:\n", SafeString(authorFiles.Author))
  112. sort.Strings(authorFiles.Files)
  113. for _, file := range authorFiles.Files {
  114. fmt.Printf(" - %s\n", SafeString(file)) // sorted by path
  115. }
  116. }
  117. }
  118. func sortByNumberOfFiles(
  119. peopleFiles [][]int, peopleDict []string, filesDict []string) authorFilesList {
  120. var pfl authorFilesList
  121. for peopleIdx, files := range peopleFiles {
  122. if peopleIdx < len(peopleDict) {
  123. fileNames := make([]string, len(files))
  124. for i, fi := range files {
  125. fileNames[i] = filesDict[fi]
  126. }
  127. pfl = append(pfl, authorFiles{peopleDict[peopleIdx], fileNames})
  128. }
  129. }
  130. sort.Sort(pfl)
  131. return pfl
  132. }
  133. type authorFiles struct {
  134. Author string
  135. Files []string
  136. }
  137. type authorFilesList []authorFiles
  138. func (s authorFilesList) Len() int {
  139. return len(s)
  140. }
  141. func (s authorFilesList) Swap(i, j int) {
  142. s[i], s[j] = s[j], s[i]
  143. }
  144. func (s authorFilesList) Less(i, j int) bool {
  145. return len(s[i].Files) < len(s[j].Files)
  146. }