Skip to content
This repository was archived by the owner on May 16, 2023. It is now read-only.

Commit c905514

Browse files
author
Lauri Piispanen
committed
output both private and public contributions in YAML
1 parent 14060db commit c905514

File tree

3 files changed

+188
-120
lines changed

3 files changed

+188
-120
lines changed

main.go

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,11 @@ package main
33
import (
44
"bufio"
55
"flag"
6-
"github.com/lauripiispanen/most-active-github-users-counter/output"
7-
"github.com/lauripiispanen/most-active-github-users-counter/top"
86
"log"
97
"os"
8+
9+
"github.com/lauripiispanen/most-active-github-users-counter/output"
10+
"github.com/lauripiispanen/most-active-github-users-counter/top"
1011
)
1112

1213
type arrayFlags []string
@@ -49,7 +50,8 @@ func main() {
4950
log.Fatal("Unrecognized output format: ", *outputOpt)
5051
}
5152

52-
data, err := top.GithubTop(top.Options{Token: *token, Locations: locations, Amount: *amount, ConsiderNum: *considerNum})
53+
opts := top.Options{Token: *token, Locations: locations, Amount: *amount, ConsiderNum: *considerNum}
54+
data, err := top.GithubTop(opts)
5355

5456
if err != nil {
5557
log.Fatal(err)
@@ -67,7 +69,7 @@ func main() {
6769
writer = bufio.NewWriter(os.Stdout)
6870
}
6971

70-
err = format(data, writer)
72+
err = format(data, writer, opts)
7173
if err != nil {
7274
log.Fatal(err)
7375
}

output/output.go

Lines changed: 179 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,20 @@ import (
44
"encoding/csv"
55
"fmt"
66
"io"
7+
"math"
8+
"regexp"
9+
"sort"
710
"strconv"
811
"strings"
912
"time"
1013

14+
"github.com/lauripiispanen/most-active-github-users-counter/github"
1115
"github.com/lauripiispanen/most-active-github-users-counter/top"
1216
)
1317

14-
type Format func(users top.GithubUsers, writer io.Writer) error
18+
type Format func(users GithubUserList, writer io.Writer, options top.Options) error
1519

16-
func PlainOutput(users top.GithubUsers, writer io.Writer) error {
20+
func PlainOutput(users GithubUserList, writer io.Writer, options top.Options) error {
1721
fmt.Fprintln(writer, "USERS\n--------")
1822
for i, user := range users {
1923
fmt.Fprintf(writer, "#%+v: %+v (%+v):%+v (%+v) %+v\n", i+1, user.Name, user.Login, user.ContributionCount, user.Company, strings.Join(user.Organizations, ","))
@@ -25,7 +29,7 @@ func PlainOutput(users top.GithubUsers, writer io.Writer) error {
2529
return nil
2630
}
2731

28-
func CsvOutput(users top.GithubUsers, writer io.Writer) error {
32+
func CsvOutput(users GithubUserList, writer io.Writer, options top.Options) error {
2933
w := csv.NewWriter(writer)
3034
if err := w.Write([]string{"rank", "name", "login", "contributions", "company", "organizations"}); err != nil {
3135
return err
@@ -45,12 +49,16 @@ func CsvOutput(users top.GithubUsers, writer io.Writer) error {
4549
return nil
4650
}
4751

48-
func YamlOutput(users top.GithubUsers, writer io.Writer) error {
49-
fmt.Fprintln(writer, "users:")
50-
for i, user := range users {
51-
fmt.Fprintf(
52-
writer,
53-
`
52+
func YamlOutput(users GithubUserList, writer io.Writer, options top.Options) error {
53+
outputUsers := func(user []github.User, public_only bool) {
54+
for i, u := range user {
55+
contributionCount := u.ContributionCount
56+
if public_only {
57+
contributionCount = u.PublicContributionCount
58+
}
59+
fmt.Fprintf(
60+
writer,
61+
`
5462
- rank: %+v
5563
name: '%+v'
5664
login: '%+v'
@@ -59,30 +67,177 @@ func YamlOutput(users top.GithubUsers, writer io.Writer) error {
5967
company: '%+v'
6068
organizations: '%+v'
6169
`,
62-
i+1,
63-
strings.Replace(user.Name, "'", "''", -1),
64-
strings.Replace(user.Login, "'", "''", -1),
65-
user.AvatarURL,
66-
user.ContributionCount,
67-
strings.Replace(user.Company, "'", "''", -1),
68-
strings.Replace(strings.Join(user.Organizations, ","), "'", "''", -1))
70+
i+1,
71+
strings.Replace(u.Name, "'", "''", -1),
72+
strings.Replace(u.Login, "'", "''", -1),
73+
u.AvatarURL,
74+
contributionCount,
75+
strings.Replace(u.Company, "'", "''", -1),
76+
strings.Replace(strings.Join(u.Organizations, ","), "'", "''", -1))
77+
}
6978
}
70-
fmt.Fprintln(writer, "\norganizations:")
7179

72-
for i, org := range users.TopOrgs(10) {
73-
fmt.Fprintf(
74-
writer,
75-
`
80+
topPublic := users.TopPublic(options.Amount)
81+
fmt.Fprintln(writer, "public_users:")
82+
outputUsers(topPublic, true)
83+
84+
topPrivate := users.TopPrivate(options.Amount)
85+
fmt.Fprintln(writer, "\nprivate_users:")
86+
outputUsers(topPrivate, false)
87+
88+
outputOrganizations := func(orgs Organizations) {
89+
for i, org := range orgs {
90+
fmt.Fprintf(
91+
writer,
92+
`
7693
- rank: %+v
7794
name: '%+v'
7895
membercount: %+v
7996
`,
80-
i+1,
81-
strings.Replace(org.Name, "'", "''", -1),
82-
org.MemberCount)
97+
i+1,
98+
strings.Replace(org.Name, "'", "''", -1),
99+
org.MemberCount)
100+
}
83101
}
84102

103+
fmt.Fprintln(writer, "\npublic_organizations:")
104+
outputOrganizations(topPublic.TopOrgs(10))
105+
fmt.Fprintln(writer, "\nprivate_organizations:")
106+
outputOrganizations(topPrivate.TopOrgs(10))
107+
85108
fmt.Fprintf(writer, "generated: %+v\n", time.Now())
109+
fmt.Fprintf(writer, "min_followers_required: %+v\n", users.MinFollowers())
86110

87111
return nil
88112
}
113+
114+
var companyLogin = regexp.MustCompile(`^\@([a-zA-Z0-9]+)$`)
115+
116+
func trim(users GithubUserList, numTop int) GithubUserList {
117+
if numTop == 0 {
118+
numTop = 256
119+
}
120+
if len(users) < numTop {
121+
numTop = len(users)
122+
}
123+
return users[:numTop]
124+
}
125+
126+
func clone(users GithubUserList) GithubUserList {
127+
usersCloned := make(GithubUserList, len(users))
128+
copy(usersCloned, users)
129+
return usersCloned
130+
}
131+
132+
type GithubUserList []github.User
133+
134+
func (users GithubUserList) TopPublic(amount int) GithubUserList {
135+
u := TopPublicUsers(clone(users))
136+
sort.Sort(u)
137+
return trim(GithubUserList(u), amount)
138+
}
139+
140+
func (users GithubUserList) TopPrivate(amount int) GithubUserList {
141+
u := TopPrivateUsers(clone(users))
142+
sort.Sort(u)
143+
return trim(GithubUserList(u), amount)
144+
}
145+
146+
func (slice GithubUserList) MinFollowers() int {
147+
if len(slice) == 0 {
148+
return 0
149+
}
150+
followers := math.MaxInt32
151+
for _, user := range slice {
152+
if user.FollowerCount < followers {
153+
followers = user.FollowerCount
154+
}
155+
}
156+
return followers
157+
}
158+
159+
type TopPublicUsers GithubUserList
160+
161+
func (slice TopPublicUsers) Len() int {
162+
return len(slice)
163+
}
164+
165+
func (slice TopPublicUsers) Less(i, j int) bool {
166+
return slice[i].PublicContributionCount > slice[j].PublicContributionCount
167+
}
168+
169+
func (slice TopPublicUsers) Swap(i, j int) {
170+
slice[i], slice[j] = slice[j], slice[i]
171+
}
172+
173+
type TopPrivateUsers GithubUserList
174+
175+
func (slice TopPrivateUsers) Len() int {
176+
return len(slice)
177+
}
178+
179+
func (slice TopPrivateUsers) Less(i, j int) bool {
180+
return slice[i].ContributionCount > slice[j].ContributionCount
181+
}
182+
183+
func (slice TopPrivateUsers) Swap(i, j int) {
184+
slice[i], slice[j] = slice[j], slice[i]
185+
}
186+
187+
type Organization struct {
188+
Name string
189+
MemberCount int
190+
}
191+
192+
type Organizations []Organization
193+
194+
func (slice Organizations) Len() int {
195+
return len(slice)
196+
}
197+
198+
func (slice Organizations) Less(i, j int) bool {
199+
return slice[i].MemberCount > slice[j].MemberCount
200+
}
201+
202+
func (slice Organizations) Swap(i, j int) {
203+
slice[i], slice[j] = slice[j], slice[i]
204+
}
205+
206+
func (slice GithubUserList) TopOrgs(count int) Organizations {
207+
orgsMap := make(map[string]int)
208+
for _, user := range slice {
209+
userOrgs := user.Organizations
210+
orgMatches := companyLogin.FindStringSubmatch(strings.Trim(user.Company, " "))
211+
if len(orgMatches) > 0 {
212+
orgLogin := companyLogin.FindStringSubmatch(strings.Trim(user.Company, " "))[1]
213+
if len(orgLogin) > 0 && !contains(userOrgs, orgLogin) {
214+
userOrgs = append(userOrgs, orgLogin)
215+
}
216+
}
217+
218+
for _, o := range userOrgs {
219+
org := strings.ToLower(o)
220+
orgsMap[org] = orgsMap[org] + 1
221+
}
222+
}
223+
224+
orgs := Organizations{}
225+
226+
for k, v := range orgsMap {
227+
orgs = append(orgs, Organization{Name: k, MemberCount: v})
228+
}
229+
sort.Sort(orgs)
230+
if len(orgs) > count {
231+
return orgs[:count]
232+
}
233+
return orgs
234+
}
235+
236+
func contains(s []string, e string) bool {
237+
for _, a := range s {
238+
if a == e {
239+
return true
240+
}
241+
}
242+
return false
243+
}

0 commit comments

Comments
 (0)