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

Commit 644d19d

Browse files
committed
Merge branch 'user_algo_challenges' into dev
Conflicts: actions/user.js initializers/helper.js routes.js
2 parents 69f1b7f + 17a6f9c commit 644d19d

21 files changed

+1066
-4
lines changed

actions/user.js

Lines changed: 143 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,16 @@
11
/*
22
* Copyright (C) 2014 TopCoder Inc., All Rights Reserved.
33
*
4-
* @version 1.3
4+
* @version 1.4
55
* @author muzehyun, Ghost_141
66
* Changes in 1.1:
77
* - Implement user activation email api.
88
* Changes in 1.2:
99
* - Implement get user identity api.
1010
* Changes in 1.3:
1111
* - Implement get user marathon match api.
12+
* Changes in 1.4:
13+
* - Implement get user algorithm challenges api.
1214
*/
1315
'use strict';
1416
var async = require('async');
@@ -38,6 +40,13 @@ var activationEmailSenderName = "Topcoder API";
3840
var VALID_SORT_COLUMN_MARATHON_MATCH = ['id', 'type', 'codingDuration', 'placement', 'numContestants',
3941
'numSubmitters'];
4042

43+
/**
44+
* The valid sort column values for get user algo challenges api.
45+
* @since 1.4
46+
*/
47+
var VALID_SORT_COLUMN_ALGO_CHALLENGES = ['id', 'type', 'codingDuration', 'placement', 'numContestants',
48+
'numSubmitters'];
49+
4150
/**
4251
* It validates activation code and retrieves user id from activation code
4352
* @param {String} activationCode - activation code string
@@ -553,3 +562,136 @@ exports.getUserMarathonMatches = {
553562
}
554563
}
555564
};
565+
566+
/**
567+
* Handle the get algorithm challenges that user participated to.
568+
* @param {Object} api - The api object.
569+
* @param {Object} connection - The connection object.
570+
* @param {Function} next - The callback function.
571+
* @since 1.4
572+
*/
573+
function getUserAlgorithmChallenges(api, connection, next) {
574+
var helper = api.helper, dbConnectionMap = connection.dbConnectionMap, response, sqlParams, sortOrder, sortColumn,
575+
exeQuery = function (name) {
576+
return function (cbx) {
577+
api.dataAccess.executeQuery(name, sqlParams, dbConnectionMap, cbx);
578+
};
579+
},
580+
handle = connection.params.handle,
581+
pageIndex = Number(connection.params.pageIndex || 1),
582+
pageSize = Number(connection.params.pageSize || 10);
583+
584+
// If the sortOrder is set and sortColumn is missing.
585+
if (connection.params.sortOrder && !connection.params.sortColumn) {
586+
helper.handleError(api, connection, new BadRequestError('The sortColumn is missing.'));
587+
next(connection, true);
588+
return;
589+
}
590+
591+
sortOrder = (connection.params.sortOrder || "asc").toLowerCase();
592+
sortColumn = connection.params.sortColumn || "id";
593+
594+
if (pageIndex === -1) {
595+
pageSize = helper.MAX_INT;
596+
pageIndex = 1;
597+
}
598+
599+
if (sortColumn.toLowerCase() === 'placement') {
600+
//reverse the sortOrder value because for placement 1 is the best so the descending order should be like 1, 2, 3.
601+
sortOrder = sortOrder === 'asc' ? 'desc' : 'asc';
602+
}
603+
604+
async.waterfall([
605+
function (cb) {
606+
var error = helper.checkPageIndex(pageIndex, "pageIndex")
607+
|| helper.checkStringParameter(handle, "handle", 30)
608+
|| helper.checkPositiveInteger(pageSize, "pageSize")
609+
|| helper.checkMaxInt(pageSize, "pageSize")
610+
|| helper.checkContains(['asc', 'desc'], sortOrder, "sortOrder")
611+
|| helper.checkSortColumn(VALID_SORT_COLUMN_ALGO_CHALLENGES, sortColumn.toLowerCase());
612+
cb(error);
613+
},
614+
function (cb) {
615+
helper.checkUserExists(handle, api, dbConnectionMap, cb);
616+
},
617+
function (err, cb) {
618+
if (err) {
619+
cb(err);
620+
return;
621+
}
622+
helper.checkUserActivated(handle, api, dbConnectionMap, cb);
623+
},
624+
function (err, cb) {
625+
if (err) {
626+
cb(err);
627+
return;
628+
}
629+
sqlParams = {
630+
first_row_index: (pageIndex - 1) * pageSize,
631+
page_size: pageSize,
632+
sort_order: sortOrder,
633+
sort_column: helper.getSortColumnDBName(sortColumn.toLowerCase()),
634+
handle: handle.toLowerCase()
635+
};
636+
async.parallel({
637+
data: exeQuery('get_user_algo_challenges'),
638+
count: exeQuery('get_user_algo_challenges_count')
639+
}, cb);
640+
},
641+
function (queryResult, cb) {
642+
var total = queryResult.count[0].total_count;
643+
response = {
644+
pageIndex: pageIndex,
645+
pageSize: pageIndex === -1 ? total : pageSize,
646+
total: total,
647+
data: queryResult.data.map(function (row) {
648+
return {
649+
id: row.id,
650+
type: row.type,
651+
prize: row.paid > 0,
652+
codingDuration: row.coding_duration,
653+
placement: row.placement,
654+
numContestants: row.num_contestants,
655+
numSubmitters: row.num_submitters,
656+
platforms: [],
657+
technologies: row.technologies.split(',').map(function (s) { return s.trim(); })
658+
};
659+
})
660+
};
661+
cb();
662+
}
663+
], function (err) {
664+
if (err) {
665+
helper.handleError(api, connection, err);
666+
} else {
667+
connection.response = response;
668+
}
669+
next(connection, true);
670+
});
671+
}
672+
673+
/**
674+
* The API for get user algorithm challenges.
675+
* @since 1.4
676+
*/
677+
exports.getUserAlgorithmChallenges = {
678+
name: 'getUserAlgorithmChallenges',
679+
description: 'Get user algorithm challenges related information',
680+
inputs: {
681+
required: ['handle'],
682+
optional: ["sortOrder", "pageIndex", "pageSize", "sortColumn"]
683+
},
684+
blockedConnectionTypes: [],
685+
outputExample: {},
686+
version: 'v2',
687+
transaction: 'read',
688+
databases: ['topcoder_dw', 'common_oltp'],
689+
run: function (api, connection, next) {
690+
if (connection.dbConnectionMap) {
691+
api.log('getUserAlgorithmChallenges#run', 'debug');
692+
getUserAlgorithmChallenges(api, connection, next);
693+
} else {
694+
api.helper.handleNoConnection(api, connection, next);
695+
}
696+
}
697+
};

apiary.apib

Lines changed: 170 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2342,6 +2342,176 @@ Request
23422342
"description":"Servers are up but overloaded. Try again later."
23432343
}
23442344

2345+
## Get User Algo Challenges [/user/{handle}/challenges/algo?pageIndex={pageIndex}&pageSize={pageSize}&sortOrder={sortOrder}&sortColumn={sortColumn}]
2346+
### Get User Algo Challenges [GET]
2347+
2348+
+ Parameters
2349+
+ handle (required, string, `heffan`) ... the user handle that to search
2350+
+ pageIndex (optional, number, `1`) ... The page index of the returned resources. 1-based. It can be null. The default value will be 1
2351+
+ pageSize (optional, number, `10`) ... The page size of the returned resources. 1-based. It can be null. The default value will be 10.
2352+
+ sortColumn (optional, string, `id`) ... The column name to sort, can be null.
2353+
+ sortOrder (optional, string, `asc`) ... The sorting order, can be null. If it's set, it can only be 'asc' or 'desc'.
2354+
2355+
+ Response 200 (application/json)
2356+
2357+
{
2358+
"total": 1,
2359+
"pageIndex": 1,
2360+
"pageSize": 10,
2361+
"data": [
2362+
{
2363+
"id": 2001,
2364+
"type": "Single Round Match",
2365+
"placement": 1,
2366+
"prize": true,
2367+
"numContestants": 14,
2368+
"numSubmitters": 6,
2369+
"codingDuration": 30000000,
2370+
"platforms": [],
2371+
"technologies": [
2372+
"Java",
2373+
"C++"
2374+
]
2375+
}
2376+
]
2377+
}
2378+
2379+
+ Response 400 (application/json)
2380+
{
2381+
"name": "Bad Request",
2382+
"value": 400,
2383+
"description": "The request was invalid. An accompanying message will explain why.",
2384+
"details": "pageIndex should be number."
2385+
}
2386+
2387+
+ Response 400 (application/json)
2388+
{
2389+
"name": "Bad Request",
2390+
"value": 400,
2391+
"description": "The request was invalid. An accompanying message will explain why.",
2392+
"details": "pageIndex should be equal to -1 or greater than 0"
2393+
}
2394+
2395+
+ Response 400 (application/json)
2396+
{
2397+
"name": "Bad Request",
2398+
"value": 400,
2399+
"description": "The request was invalid. An accompanying message will explain why.",
2400+
"details": "pageIndex should be Integer."
2401+
}
2402+
2403+
+ Response 400 (application/json)
2404+
{
2405+
"name": "Bad Request",
2406+
"value": 400,
2407+
"description": "The request was invalid. An accompanying message will explain why.",
2408+
"details": "pageIndex should be less or equal to 2147483647."
2409+
}
2410+
2411+
+ Response 400 (application/json)
2412+
{
2413+
"name": "Bad Request",
2414+
"value": 400,
2415+
"description": "The request was invalid. An accompanying message will explain why.",
2416+
"details": "pageSize should be number."
2417+
}
2418+
2419+
+ Response 400 (application/json)
2420+
{
2421+
"name": "Bad Request",
2422+
"value": 400,
2423+
"description": "The request was invalid. An accompanying message will explain why.",
2424+
"details": "pageSize should be positive."
2425+
}
2426+
2427+
+ Response 400 (application/json)
2428+
{
2429+
"name": "Bad Request",
2430+
"value": 400,
2431+
"description": "The request was invalid. An accompanying message will explain why.",
2432+
"details": "pageSize should be Integer."
2433+
}
2434+
2435+
+ Response 400 (application/json)
2436+
{
2437+
"name": "Bad Request",
2438+
"value": 400,
2439+
"description": "The request was invalid. An accompanying message will explain why.",
2440+
"details": "pageSize should be less or equal to 2147483647."
2441+
}
2442+
2443+
+ Response 400 (application/json)
2444+
{
2445+
"name": "Bad Request",
2446+
"value": 400,
2447+
"description": "The request was invalid. An accompanying message will explain why.",
2448+
"details": ""
2449+
}
2450+
2451+
+ Response 400 (application/json)
2452+
{
2453+
"name": "Bad Request",
2454+
"value": 400,
2455+
"description": "The request was invalid. An accompanying message will explain why.",
2456+
"details": "handle exceeds 30 characters."
2457+
}
2458+
2459+
+ Response 400 (application/json)
2460+
{
2461+
"name": "Bad Request",
2462+
"value": 400,
2463+
"description": "The request was invalid. An accompanying message will explain why.",
2464+
"details": "sortOrder should be an element of asc,desc."
2465+
}
2466+
2467+
+ Response 400 (application/json)
2468+
{
2469+
"name": "Bad Request",
2470+
"value": 400,
2471+
"description": "The request was invalid. An accompanying message will explain why.",
2472+
"details": "The sort column 'abc' is invalid, it should be element of id,type,prize,codingDuration,placement,numContestants,numSubmitters."
2473+
}
2474+
2475+
+ Response 400 (application/json)
2476+
{
2477+
"name": "Bad Request",
2478+
"value": 400,
2479+
"description": "The request was invalid. An accompanying message will explain why.",
2480+
"details": "The sortColumn is missing."
2481+
}
2482+
2483+
+ Response 400 (application/json)
2484+
{
2485+
"name": "Bad Request",
2486+
"value": 400,
2487+
"description": "The request was invalid. An accompanying message will explain why.",
2488+
"details": "User is not activated."
2489+
}
2490+
2491+
+ Response 404 (application/json)
2492+
{
2493+
"name": "Not Found",
2494+
"value": 404,
2495+
"description": "The request was invalid. An accompanying message will explain why.",
2496+
"details": "User does not exist."
2497+
}
2498+
2499+
+ Response 500 (application/json)
2500+
2501+
{
2502+
"name":"Internal Server Error",
2503+
"value":"500",
2504+
"description":"Unknown server error. Please contact support."
2505+
}
2506+
2507+
+ Response 503 (application/json)
2508+
2509+
{
2510+
"name":"Service Unavailable",
2511+
"value":"503",
2512+
"description":"Servers are up but overloaded. Try again later."
2513+
}
2514+
23452515

23462516
## Get User Marathon Matches Information [/user/{handle}/challenges/marathon?pageIndex={pageIndex}&pageSize={pageSize}&sortColumn={sortColumn}&sortOrder={sortOrder}]
23472517
### Get User Marathon Matches Information [GET]

initializers/helper.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@
55

66
/**
77
* This module contains helper functions.
8-
* @author Sky_, Ghost_141, muzehyun, kurtrips, isv, LazyChild, hesibo, panoptimum, flytoj2ee, TCSASSEMBLER
9-
* @version 1.39
8+
* @author Sky_, Ghost_141, muzehyun, kurtrips, isv, LazyChild, hesibo, panoptimum, flytoj2ee
9+
* @version 1.40
1010
* changes in 1.1:
1111
* - add mapProperties
1212
* changes in 1.2:
@@ -104,6 +104,8 @@
104104
* Changes in 1.39:
105105
* - Update apiName2dbNameMap to add entries for coding_duration, num_contestants and num_submitters.
106106
* - Move checkUserExistAndActivated method from actions/memberStatistics.js to this file.
107+
* Changes in 1.40:
108+
* - Update apiName2dbNameMap to add entries for coding_duration, num_contestants and num_submitters.
107109
*/
108110
"use strict";
109111

0 commit comments

Comments
 (0)