utils.go 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  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. for _, status := range matrix {
  43. fmt.Print(strings.Repeat(" ", indent-1))
  44. for i := 0; i < last; i++ {
  45. var val int64
  46. if i < len(status) {
  47. val = status[i]
  48. // not sure why this sometimes happens...
  49. // TODO(vmarkovtsev): find the root cause of tiny negative balances
  50. if fixNegative && val < 0 {
  51. val = 0
  52. }
  53. }
  54. fmt.Printf(" %[1]*[2]d", width, val)
  55. }
  56. fmt.Println()
  57. }
  58. }
  59. func PrintCouples(result *hercules.CouplesResult, peopleDict []string) {
  60. fmt.Println("files_coocc:")
  61. fmt.Println(" index:")
  62. for _, file := range result.Files {
  63. fmt.Printf(" - %s\n", SafeString(file))
  64. }
  65. fmt.Println(" matrix:")
  66. for _, files := range result.FilesMatrix {
  67. fmt.Print(" - {")
  68. indices := []int{}
  69. for file := range files {
  70. indices = append(indices, file)
  71. }
  72. sort.Ints(indices)
  73. for i, file := range indices {
  74. fmt.Printf("%d: %d", file, files[file])
  75. if i < len(indices)-1 {
  76. fmt.Print(", ")
  77. }
  78. }
  79. fmt.Println("}")
  80. }
  81. fmt.Println("people_coocc:")
  82. fmt.Println(" index:")
  83. for _, person := range peopleDict {
  84. fmt.Printf(" - %s\n", SafeString(person))
  85. }
  86. fmt.Println(" matrix:")
  87. for _, people := range result.PeopleMatrix {
  88. fmt.Print(" - {")
  89. indices := []int{}
  90. for file := range people {
  91. indices = append(indices, file)
  92. }
  93. sort.Ints(indices)
  94. for i, person := range indices {
  95. fmt.Printf("%d: %d", person, people[person])
  96. if i < len(indices)-1 {
  97. fmt.Print(", ")
  98. }
  99. }
  100. fmt.Println("}")
  101. }
  102. fmt.Println(" author_files:") // sorted by number of files each author changed
  103. peopleFiles := sortByNumberOfFiles(result.PeopleFiles, peopleDict, result.Files)
  104. for _, authorFiles := range peopleFiles {
  105. fmt.Printf(" - %s:\n", SafeString(authorFiles.Author))
  106. sort.Strings(authorFiles.Files)
  107. for _, file := range authorFiles.Files {
  108. fmt.Printf(" - %s\n", SafeString(file)) // sorted by path
  109. }
  110. }
  111. }
  112. func sortByNumberOfFiles(
  113. peopleFiles [][]int, peopleDict []string, filesDict []string) authorFilesList {
  114. var pfl authorFilesList
  115. for peopleIdx, files := range peopleFiles {
  116. if peopleIdx < len(peopleDict) {
  117. fileNames := make([]string, len(files))
  118. for i, fi := range files {
  119. fileNames[i] = filesDict[fi]
  120. }
  121. pfl = append(pfl, authorFiles{peopleDict[peopleIdx], fileNames})
  122. }
  123. }
  124. sort.Sort(pfl)
  125. return pfl
  126. }
  127. type authorFiles struct {
  128. Author string
  129. Files []string
  130. }
  131. type authorFilesList []authorFiles
  132. func (s authorFilesList) Len() int {
  133. return len(s)
  134. }
  135. func (s authorFilesList) Swap(i, j int) {
  136. s[i], s[j] = s[j], s[i]
  137. }
  138. func (s authorFilesList) Less(i, j int) bool {
  139. return len(s[i].Files) < len(s[j].Files)
  140. }