forked from wowhack/showcase
-
Notifications
You must be signed in to change notification settings - Fork 8
/
teams.js
180 lines (150 loc) · 4.47 KB
/
teams.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
// Deps
var
request = require('request'),
fs = require('fs'),
us = require('underscore'),
Promise = require('es6-promise').Promise,
debug = require('debug')('showcase-teams'),
OWNERS_ID = 1660775,
// Cache the team data for a full minute
CACHE_LIFE_CYCLE = process.env.CACHE_LIFE_CYCLE || 60 * 1000;
function compile (string, key) {
return string.replace('@', key);
}
// Github endpoints ***
var gh = {
teams: compile.bind(null, 'https://api.github.com/orgs/hackoutwest15/teams'),
members: compile.bind(null, 'https://api.github.com/teams/@/members'),
repos: compile.bind(null, 'https://api.github.com/teams/@/repos'),
thumnbnail: compile.bind(null, process.env.HOST_NAME + '/hackshots/@.png')
};
var options = {
winnerIDs: JSON.parse(fs.readFileSync('./winners.json')),
cache: null
};
// Request options
request = request.defaults({
auth: {
user: process.env.GH_USER,
pass: process.env.GH_PASS
},
headers: {
// Github best practices proposes this
'User-Agent': 'wowhack-showcase'
}
});
function populator (url, key, fn) {
return new Promise(function (resolve) {
debug('Sending populate request to ' + url);
request.get(url, function (err, res, body) {
var value = fn(body, (res || {}).statusCode);
var result = {};
result[key] = value;
debug('Resolving request to ' + url + ' with ' + result);
resolve(result);
});
});
}
// TODO, populate with repository data etc.
function populate (team) {
debug('Populating team ' + team.id);
var populators = [];
// Add team members
populators.push(populator(gh.members(team.id), 'members', function (body) {
return JSON.parse(body);
}));
// Repo data
populators.push(populator(gh.repos(team.id), 'repository', function (body) {
return JSON.parse(body)[0] || {};
}));
// Image
var tnUrl = gh.thumnbnail(team.slug);
populators.push(populator(tnUrl, 'thumbnail', function (body, statusCode) {
return statusCode === 200 ? tnUrl : '';
}));
debug('Waiting for ' + populators.length + ' populations to finish');
// Collect all info and return
return Promise.all(populators).then(function (objects) {
debug('Collecting info for team ' + team.id);
return us.extend.apply(us, [team].concat(objects));
});
}
/*
Set 'points' to sort from according to some weighted
props, like description, thumbnail and homepage.
*/
function calculateSortPoints(team) {
debug('Calculating sorting bonus points');
var weights = [
{ prop: 'homepage', weight: 1 },
{ prop: 'description', weight: 2 }
];
team.points = weights.reduce(function(points, obj) {
points += !!team.repository[obj.prop] ? obj.weight : 0;
return points;
}, 0);
team.points += !!team.thumbnail ? 3 : 0;
return team;
}
// Fetch and group teams by winners and others
function loadTeams (callback) {
debug('Fetching teams');
request.get(gh.teams(), function (err, res, body) {
var teams;
try {
teams = JSON.parse(body);
} catch (e) {
return callback({ error: e });
}
// Exclude owner team
teams = us.reject(teams, function (team) {
return team.id === OWNERS_ID;
});
var populationRequests = teams.map(populate);
debug('Waiting for ' + populationRequests + ' FULL populations to finish');
Promise.all(populationRequests)
.then(function(teams) {
return teams.map(calculateSortPoints);
})
.then(function (teams) {
debug('All populations finished, found ' + teams.length + ' teams');
var winners = [];
var others = [];
// Categorize winning teams
teams.forEach(function (team) {
if (options.winnerIDs.indexOf(team.id) >= 0) {
winners.push(team);
} else {
others.push(team);
}
});
// We know the outcome :)
console.assert(winners.length === 3, winners);
// Sort the hacks
others.sort(function(a, b) {
return b.points - a.points;
});
// TODO We should cache the result and send modified since headers
var result = {
winners: winners,
others: others
};
options.cache = result;
setTimeout(function () {
options.cache = null;
}, CACHE_LIFE_CYCLE);
callback(result);
});
});
}
module.exports = {
loadTeams: function (callback) {
if (options.cache) {
debug('Serving cached team data');
callback(options.cache);
} else {
debug('Serving new team data');
loadTeams(callback);
}
}
};