utils.go 3.4 KB

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