Skip to content
This repository was archived by the owner on Jan 23, 2025. It is now read-only.

Commit d182ae7

Browse files
author
ykohata
committed
Merge branch 'technology-2014-09-18'
Conflicts: apiary.apib
2 parents 2fa89d2 + 40e8a07 commit d182ae7

File tree

47 files changed

+1606
-99
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+1606
-99
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
TopCoder API (built on NodeJS)
44
==============================
55

6-
As [TopCoder](http://www.topcoder.com/tc) and [CloudSpokes](http://www.cloudspokes) integrate, the APIs are going to play a critical role. TopCoder has already started work on a API, which can be found [here](http://dev.topcoder.com). That API is built on a Java stack.
6+
As Topcoder(http://www.topcoder.com/tc) and [CloudSpokes](http://www.cloudspokes) integrate, the APIs are going to play a critical role. TopCoder has already started work on a API, which can be found [here](http://dev.topcoder.com). That API is built on a Java stack.
77

88
In order to accelerate development we are looking to move some of the API work to use a more cloud-friendly approach built on [NodeJS](http://www.nodejs.org). This is complicated by the fact that the back end of TC relies on an Informix DB.
99

actions/challenges.js

Lines changed: 9 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -2321,20 +2321,11 @@ var getChallengeResults = function (api, connection, dbConnectionMap, isStudio,
23212321
}, cb);
23222322

23232323
}, function (res, cb) {
2324-
// TODO: The logic of calculating dr points of each submissions need to be updated.
23252324
var infoRow = res.info[0],
2326-
prizedSubmissionCount = _.countBy(res.results, function (item) { return _.isDefined(item.prize_id); })['true'] || 0,
2327-
drPointsConfig,
2328-
drPoints = infoRow.dr_points || 0;
2325+
challengeRestrictions = res.restrictions[0];
23292326
if (!_.isDefined(infoRow)) {
23302327
cb(new BadRequestError('No Result Found'));
23312328
return;
2332-
2333-
}
2334-
if (prizedSubmissionCount > 5) {
2335-
drPointsConfig = helper.DR_POINTS[5];
2336-
} else {
2337-
drPointsConfig = helper.DR_POINTS[prizedSubmissionCount];
23382329
}
23392330

23402331
_.extend(result, {
@@ -2365,8 +2356,9 @@ var getChallengeResults = function (api, connection, dbConnectionMap, isStudio,
23652356
placement: el.placed === 0 ? 'n/a' : el.placed,
23662357
submissionDate: el.submission_date,
23672358
submissionStatus: el.submission_status,
2368-
registrationDate: el.registration_date
2369-
}, rate;
2359+
registrationDate: el.registration_date,
2360+
points: el.dr_points
2361+
};
23702362

23712363
if (!isStudio) {
23722364
_.extend(resEl, {
@@ -2380,12 +2372,9 @@ var getChallengeResults = function (api, connection, dbConnectionMap, isStudio,
23802372
});
23812373
}
23822374

2383-
rate = drPointsConfig[el.placed - 1] || 0;
2384-
resEl.points = Number((drPoints * rate).toFixed(2));
2385-
23862375
//Submission Links
23872376
if (isStudio) {
2388-
if (res.restrictions[0].show_submissions) {
2377+
if (challengeRestrictions.show_submissions) {
23892378
resEl.submissionDownloadLink = api.config.tcConfig.designSubmissionLink + el.submission_id;
23902379
resEl.previewDownloadLink = api.config.tcConfig.designSubmissionLink + el.submission_id + "&sbt=small";
23912380
}
@@ -2395,7 +2384,7 @@ var getChallengeResults = function (api, connection, dbConnectionMap, isStudio,
23952384

23962385
//Handle
23972386
if (isStudio) {
2398-
if (res.restrictions[0].show_coders) {
2387+
if (challengeRestrictions.show_coders) {
23992388
resEl.handle = el.handle;
24002389
}
24012390
} else {
@@ -2407,7 +2396,7 @@ var getChallengeResults = function (api, connection, dbConnectionMap, isStudio,
24072396

24082397
//Populate the final fixes
24092398
if (isStudio) {
2410-
if (res.restrictions[0].show_submissions) {
2399+
if (challengeRestrictions.show_submissions) {
24112400
result.finalFixes = _.map(res.finalFixes, function (ff) {
24122401
return api.config.tcConfig.designSubmissionLink + ff.submission_id;
24132402
});
@@ -2503,9 +2492,8 @@ exports.getChallenge = {
25032492

25042493
if (error) {
25052494
api.helper.handleError(api, connection, new NotFoundError("Challenge Id Not Valid."));
2506-
next(connection, true)
2507-
}
2508-
else if (connection.dbConnectionMap) {
2495+
next(connection, true);
2496+
} else if (connection.dbConnectionMap) {
25092497
api.log("Execute getChallenge#run", 'debug');
25102498
api.dataAccess.executeQuery('check_challenge_exists', {challengeId: connection.params.challengeId}, connection.dbConnectionMap, function (err, result) {
25112499
if (err) {

actions/dataScienceChallenges.js

Lines changed: 241 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,241 @@
1+
/*
2+
* Copyright (C) 2014 TopCoder Inc., All Rights Reserved.
3+
*
4+
* @version 1.0
5+
* @author isv
6+
*/
7+
/*jslint node: true, nomen: true */
8+
9+
"use strict";
10+
11+
var async = require('async');
12+
var _ = require('underscore');
13+
var moment = require('moment');
14+
var IllegalArgumentError = require('../errors/IllegalArgumentError');
15+
16+
/**
17+
* A value of 'pageIndex' request parameter to indicate that no paging of returned data is required.
18+
*/
19+
var NO_PAGING = -1;
20+
21+
/**
22+
* A value of 'sortingOrder' request parameter to indicate that sorting in ascending order is requested.
23+
*/
24+
var SORTING_ORDER_ASCENDING = 'asc';
25+
26+
/**
27+
* A value of 'sortingOrder' request parameter to indicate that sorting in descending order is requested.
28+
*/
29+
var SORTING_ORDER_DESCENDING = 'desc';
30+
31+
/**
32+
* A list of names for columns in Past Data Science data.
33+
*/
34+
var PAST_CHALLENGES_DATA_COLUMN_NAMES = ['challengetype', 'challengename', 'challengeid', 'numsubmissions',
35+
'numregistrants', 'registrationstartdate', 'submissionenddate', 'challengecommunity', 'postingdate'];
36+
37+
/**
38+
* A format for the dates for Past Data Science Challenges filter.
39+
*/
40+
var PAST_CHALLENGES_FILTER_DATE_FORMAT = 'YYYY-MM-DD';
41+
42+
/**
43+
* A format for the dates for Past Data Science Challenges output.
44+
*/
45+
var PAST_CHALLENGES_OUTPUT_DATE_FORMAT = 'YYYY-MM-DD HH:mm z';
46+
47+
/**
48+
* Maximum value for integer number.
49+
*/
50+
var MAX_INT = 2147483647;
51+
52+
/**
53+
* A name for the column to sort the data for past Data Science challenges by default.
54+
*/
55+
var PAST_CHALLENGES_DEFAULT_SORT_COLUMN = "submissionEndDate";
56+
57+
/**
58+
* An order to sort the data for past Data Science challenges by default.
59+
*/
60+
var PAST_CHALLENGES_DEFAULT_SORT_ORDER = "desc";
61+
62+
/**
63+
* Gets the details for the past Data Science challenges and provides it to specified callback.
64+
*
65+
* @param {Number} pageIndex - an index of the page of the data to be returned or -1 if no paging is required.
66+
* @param {Number} pageSize - a size of page of the data to be returned or 0 if pageIndex is -1.
67+
* @param {String} sortingColumnName - a name of the column to sort the data against. Must not be null.
68+
* @param {String} sortingOrder - a sorting order (either 'asc' or 'desc'). Must not be null.
69+
* @param {Date} submissionEndFrom - a lower boundary for the submission end date filter. Must not be null.
70+
* @param {Date} submissionEndTo - - an upper boundary for the submission end date filter. Must not be null.
71+
* @param {Object} api - an action hero api object.
72+
* @param {Object} connection - a connection object for the current request.
73+
* @param callback - a callback to be notified on retrieved data matching the specified criteria.
74+
*/
75+
function pastDataScienceChallenges(pageIndex, pageSize, sortingColumnName, sortingOrder, submissionEndFrom,
76+
submissionEndTo, api, connection, callback) {
77+
if (pageIndex === NO_PAGING) {
78+
pageIndex = 1;
79+
pageSize = MAX_INT;
80+
}
81+
82+
var sqlParams = {};
83+
sqlParams.firstRowIndex = (pageIndex - 1) * pageSize;
84+
sqlParams.pageSize = pageSize;
85+
sqlParams.sortColumn = api.helper.getSortColumnDBName(sortingColumnName);
86+
sqlParams.sortOrder = sortingOrder;
87+
sqlParams.submitByFrom = submissionEndFrom;
88+
sqlParams.submitByTo = submissionEndTo;
89+
90+
async.parallel({
91+
total: function (cb) {
92+
api.dataAccess.executeQuery('past_data_science_challenges_count', sqlParams, connection.dbConnectionMap, cb);
93+
},
94+
data: function (cb) {
95+
api.dataAccess.executeQuery('past_data_science_challenges', sqlParams, connection.dbConnectionMap, cb);
96+
}
97+
}, function (err, results) {
98+
if (err) {
99+
callback(err);
100+
} else {
101+
callback(null, results.total[0].total_count, results.data);
102+
}
103+
});
104+
}
105+
106+
107+
/**
108+
* View Past Data Science Challenges API.
109+
*/
110+
exports.pastDataScienceChallenges = {
111+
name: 'pastDataScienceChallenges',
112+
description: 'Get the list of past Data Science challenges',
113+
inputs: {
114+
required: [],
115+
optional: ['pageIndex', 'pageSize', 'sortColumn', 'sortOrder', 'submissionEndFrom', 'submissionEndTo']
116+
},
117+
blockedConnectionTypes: [],
118+
outputExample: {},
119+
version: 'v2',
120+
cacheEnabled: false,
121+
transaction: 'read',
122+
databases: ['tcs_dw'],
123+
run: function (api, connection, next) {
124+
if (connection.dbConnectionMap) {
125+
api.log('Execute pastDataScienceChallenges#run', 'debug');
126+
var pageIndex,
127+
pageSize,
128+
sortingColumnName,
129+
sortingOrder,
130+
submissionEndFrom,
131+
submissionEndTo,
132+
err,
133+
helper = api.helper;
134+
135+
async.waterfall([
136+
function (cb) { // Parse and validate request parameters
137+
pageIndex = Number(connection.params.pageIndex || 1);
138+
pageSize = Number(connection.params.pageSize || 50);
139+
sortingOrder = connection.params.sortOrder || PAST_CHALLENGES_DEFAULT_SORT_ORDER;
140+
sortingColumnName = connection.params.sortColumn || PAST_CHALLENGES_DEFAULT_SORT_COLUMN;
141+
142+
err = helper.checkContains([SORTING_ORDER_ASCENDING, SORTING_ORDER_DESCENDING], sortingOrder.toLowerCase(), "sortOrder")
143+
|| helper.checkContains(PAST_CHALLENGES_DATA_COLUMN_NAMES, sortingColumnName.toLowerCase(), "sortColumn")
144+
|| helper.checkPageIndex(pageIndex, "pageIndex")
145+
|| helper.checkPositiveInteger(pageSize, "pageSize")
146+
|| helper.checkMaxInt(pageSize, 'pageSize');
147+
148+
if (err) {
149+
cb(err);
150+
return;
151+
}
152+
153+
if (_.isDefined(connection.params.submissionEndFrom)) {
154+
err = helper.checkDateFormat(connection.params.submissionEndFrom,
155+
PAST_CHALLENGES_FILTER_DATE_FORMAT, 'submissionEndFrom');
156+
if (err) {
157+
cb(err);
158+
return;
159+
}
160+
submissionEndFrom = connection.params.submissionEndFrom;
161+
} else {
162+
submissionEndFrom = '1900-01-01';
163+
}
164+
if (_.isDefined(connection.params.submissionEndTo)) {
165+
err = helper.checkDateFormat(connection.params.submissionEndTo,
166+
PAST_CHALLENGES_FILTER_DATE_FORMAT, 'submissionEndTo');
167+
if (err) {
168+
cb(err);
169+
return;
170+
}
171+
submissionEndTo = connection.params.submissionEndTo;
172+
} else {
173+
submissionEndTo = '2999-12-31';
174+
}
175+
176+
err = helper.checkDates(submissionEndFrom, submissionEndTo,
177+
'submissionEndFrom must be before submissionEndTo');
178+
if (err) {
179+
cb(err);
180+
return;
181+
}
182+
183+
cb();
184+
}, function (cb) { // Get the data based on requested parameters once provided parameters are valid
185+
pastDataScienceChallenges(pageIndex, pageSize, sortingColumnName, sortingOrder, submissionEndFrom,
186+
submissionEndTo, api, connection, cb);
187+
}
188+
], function (err, total, data) {
189+
if (err) {
190+
helper.handleError(api, connection, err);
191+
} else {
192+
// Build the response from the results
193+
var response = {};
194+
response.total = total;
195+
response.data = [];
196+
197+
// Copy request parameters for filter into response
198+
if (_.isDefined(connection.params.pageIndex)) {
199+
response.pageIndex = connection.params.pageIndex;
200+
}
201+
if (_.isDefined(connection.params.pageSize)) {
202+
response.pageSize = connection.params.pageSize;
203+
}
204+
if (_.isDefined(connection.params.sortColumn)) {
205+
response.sortColumn = connection.params.sortColumn;
206+
}
207+
if (_.isDefined(connection.params.sortOrder)) {
208+
response.sortOrder = connection.params.sortOrder;
209+
}
210+
if (_.isDefined(connection.params.submissionEndFrom)) {
211+
response.submissionEndFrom = connection.params.submissionEndFrom;
212+
}
213+
if (_.isDefined(connection.params.submissionEndTo)) {
214+
response.submissionEndTo = connection.params.submissionEndTo;
215+
}
216+
// Convert the rows returned from DB into format suitable for response
217+
_.each(data, function (row) {
218+
var challenge = {
219+
challengeType: row.challenge_type,
220+
challengeName: row.challenge_name,
221+
challengeId: row.challenge_id,
222+
numSubmissions: row.num_submissions,
223+
numRegistrants: row.num_registrants,
224+
registrationStartDate: helper.formatDateWithTimezone(row.registration_start_date, PAST_CHALLENGES_OUTPUT_DATE_FORMAT),
225+
submissionEndDate: helper.formatDateWithTimezone(row.submission_end_date, PAST_CHALLENGES_OUTPUT_DATE_FORMAT),
226+
challengeCommunity: row.challenge_community,
227+
postingDate: helper.formatDateWithTimezone(row.posting_date, PAST_CHALLENGES_OUTPUT_DATE_FORMAT)
228+
};
229+
response.data.push(challenge);
230+
});
231+
232+
233+
connection.response = response;
234+
}
235+
next(connection, true);
236+
});
237+
} else {
238+
api.helper.handleNoConnection(api, connection, next);
239+
}
240+
}
241+
};

actions/memberRegistration.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -110,12 +110,12 @@ var PASSWORD_HASH_KEY = process.env.PASSWORD_HASH_KEY || 'default';
110110
/**
111111
* The activation email subject.
112112
*/
113-
var activationEmailSubject = "[topcoder] User Registration Activation";
113+
var activationEmailSubject = "Topcoder User Registration Activation";
114114

115115
/**
116116
* The activation email sender name.
117117
*/
118-
var activationEmailSenderName = "[topcoder] API";
118+
var activationEmailSenderName = "Topcoder API";
119119

120120
/**
121121
* this is the random int generator class

0 commit comments

Comments
 (0)