Commit 689fbb4c by Иван Кубота

back2. attempt crud

parent ee949a3d
......@@ -34,7 +34,12 @@ const print = function(data) {
return tpls.index.replace('$DATA$', data)
};
const api = [require('./src/api/generateRandom'),require('./src/api/log'), require('./src/api/crud')].reduce((store, el)=>{
const api = [
require('./src/api/generateRandom'),
require('./src/api/log'),
require('./src/api/crud'),
require('./src/api/quiz')
].reduce((store, el)=>{
return Object.assign(store, el)
}, {});
const {api2html, api2routes} = require('./src/apiMappers.js');
......
......@@ -6,6 +6,7 @@
"csv-parser": "^2.3.2",
"dotenv": "^8.2.0",
"express": "^4.17.1",
"mysql": "^2.18.1",
"node-async-router": "^0.0.2",
"request": "^2.88.2",
"yargs": "^15.1.0"
......
/*
TABLE: quiz
id
name
description
start_date
end_date
question_time_limit
created_at
updated_at
TABLE: quiz_position // должности в тестировании
id
quiz_id
user_position_id
question_count
top_count
prev_top_count
tags
created_at
updated_at
TABLE: quiz_attempt
id
user_id
count_question
count_correct
is_top
completed
quiz_position_id
updated_at
aborted
created_at
completed_at
max_chain
TABLE: quiz_question
id
text
image
start_quiz
question_time_limit
type
user_choice_correct
attempt_id
number
category_id
card_id
created_at
updated_at
TABLE: quiz_answer
id
quiz_question_id
text
correct
user_choice
updated_at
created_at
*/
var mysql = require('mysql');
var pool = mysql.createPool({
connectionLimit : 10,
host : process.env.DB_HOST,
user : process.env.DB_USERNAME,
password : process.env.DB_PASSWORD,
database : process.env.DB_DATABASE
});
var asyncPool = function(q,v){
return new Promise((r,j)=>{
v = v || [];
pool.query(q, v, function (error, results, fields) {
if (error) return j(error);
r(results);
});
});
}
module.exports = {
'/api/quiz/attempt/complete': {
options: {},
method: 'POST',
summary: 'Compliting attempt',
fn: async function (args) {
var att = await asyncPool('SELECT * from quiz_attempt WHERE' +
'quiz_position_id=?, user_id=??', [args.body.quiz_position_id, args.body.user_id]);
if(!att || !att.length){
console.error('NO ATTEMPT, ', att);
return false;
}
return await asyncPool('UPDATE quiz_attempt SET' +
'is_top=?, completed=?, completed_at=?,' +
' WHERE attempt_id=?', [args.body.is_top?1:0, 1, new Date(), att.id])
}
},
'/api/quiz/attempt/answer': {
options: {},
method: 'POST',
summary: 'Set single answer',
fn: async function (args) {
var result = await asyncPool('UPDATE `quiz_question` SET user_choice_correct=?, updated_at=? WHERE id=?;', [
args.body.user_choice_correct?1:0,
new Date(),
args.body.quizQuestion
]);
var ans = await Promise.all(args.body.quizAnswers.map(async(a,i)=>{
return await asyncPool('UPDATE `quiz_answer` SET ' +
'user_choice=?, updated_at=? WHERE id=?;', [
a.user_choice?1:0,
new Date(),
a.id
]);
}));
if(args.body.currentQuestion === args.body.allQuestions - 1){
// calculations
var q = await asyncPool('SELECT * from `quiz_question` WHERE id=?', [args.body.quizQuestion]);
if(q && q.length){
var qs = await asyncPool('SELECT * from `quiz_question` WHERE attempt_id=?', [q[0].attempt_id])
var countCorrect = qs.filter(q=>q.user_choice_correct).length;
var maxChain = 0, curChain = 0;
for(var i = 0; i<qs.length; i++){
var correct = qs[i].user_choice_correct;
if(correct){
curChain++;
}else{
maxChain = Math.max(maxChain, curChain);
curChain = 0;
}
}
maxChain = Math.max(maxChain, curChain);
return await asyncPool('UPDATE quiz_attempt SET' +
'count_correct=?, max_chain=?, completed=?, completed_at=?,' +
' WHERE attempt_id=?', [countCorrect, maxChain, 1, new Date(), q[0].attempt_id])
}else{
console.error('No such attempt');
}
}
return {status: 'ok'};
}
},
'/api/quiz/attempt/create': {
options: {
quiz_position_id: {required: false, description: 'id of job in quiz', type: Number},
user_id: {required: false, description: 'id of user', type: Number},
},
method: 'POST',
summary: 'Create quiz attempt',
fn: async function (args) {
try {
var oldAttempt = await asyncPool('SELECT * FROM quiz_attempt WHERE user_id=? AND quiz_position_id=?;', [
args.body.user_id,
args.body.quiz_position_id
]);
if (oldAttempt.length > 0) {
console.log('REMOVE OLD ATTEMPT');
var removeResult = await asyncPool('DELETE FROM quiz_attempt WHERE user_id=? AND quiz_position_id=?;', [
args.body.user_id,
args.body.quiz_position_id
]);
}
} catch (e) {
console.error(e);
}
try {
console.log('CREATE ATTEMPT');
var attempt = await asyncPool('INSERT INTO `quiz_attempt` (' +
'user_id,' +
'quiz_position_id,' +
'count_question, is_top,count_correct, completed,' +
'aborted, max_chain,' +
'created_at, updated_at' +
') VALUES (?,?,?,?,?,?,?,?,?,?);', [
args.body.user_id,
args.body.quiz_position_id,
args.body.questions.length,
args.body.is_top,
0, false, false, 0,
new Date(),
new Date()
]),
attemptID = attempt.insertId;
var qS = args.body.questions;
await Promise.all(qS.map(async (q, i) => {
q.user_choice_correct = q.answers.map((a, i) => ({a, i})).filter(a => a.a.correct)[0].i;
q.attempt_id = attemptID;
q.number = i;
//user_choice_correct
var list = ('text,image,question_time_limit,type,' +
'attempt_id,number,card_id,created_at,updated_at').split(',');
q.created_at = q.updated_at = new Date();
console.log('CREATE QUESTION');
var dbQ = await asyncPool(`INSERT INTO \`quiz_question\` (${list.map(l => '`' + l + '`').join(',')}) VALUES (${list.map(l => '?').join(',')});`,
list.map(l => q[l]));
q.id = dbQ.insertId;
await Promise.all(q.answers.map(async (a, j) => {
var list = ('quiz_question_id,' +
'text,correct,updated_at,created_at').split(',');
a.created_at = a.updated_at = new Date();
a.quiz_question_id = q.id;
console.log(`CREATE ANSWER ${j}`);
var dbA = await asyncPool(`INSERT INTO \`quiz_answer\` (${list.map(l => '`' + l + '`').join(',')}) VALUES (${list.map(l => '?').join(',')});`,
list.map(l => a[l]));
a.id = dbA.insertId;
}));
}))
} catch (e) {
console.error(e);
throw e;
}
return {
id: attemptID,
questions: qS
};
}
}
};
\ No newline at end of file
......@@ -179,7 +179,12 @@ ${opt.required?'<span class="api-option-required">Required</span>': '<span class
});
req.on('end', function () {
r(JSON.parse(body));
try {
r(body === '' ? void 0 : JSON.parse(body));
}catch (e) {
console.error(e)
j(body);
}
});
} )
}catch(e){
......
......@@ -120,6 +120,11 @@ bcrypt-pbkdf@^1.0.0:
dependencies:
tweetnacl "^0.14.3"
bignumber.js@9.0.0:
version "9.0.0"
resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-9.0.0.tgz#805880f84a329b5eac6e7cb6f8274b6d82bdf075"
integrity sha512-t/OYhhJ2SD+YGBQcjY8GzzDHEk9f3nerxjtfa6tlMXfe7frs/WozhvCNoGvpM0P3bNf3Gq5ZRMlGr5f3r4/N8A==
body-parser@1.19.0:
version "1.19.0"
resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.19.0.tgz#96b2709e57c9c4e09a6fd66a8fd979844f69f08a"
......@@ -613,6 +618,16 @@ ms@2.1.1:
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a"
integrity sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==
mysql@^2.18.1:
version "2.18.1"
resolved "https://registry.yarnpkg.com/mysql/-/mysql-2.18.1.tgz#2254143855c5a8c73825e4522baf2ea021766717"
integrity sha512-Bca+gk2YWmqp2Uf6k5NFEurwY/0td0cpebAucFpY/3jhrwrVGuxU2uQFCHjU19SJfje0yQvi+rVWdq78hR5lig==
dependencies:
bignumber.js "9.0.0"
readable-stream "2.3.7"
safe-buffer "5.1.2"
sqlstring "2.3.1"
ndjson@^1.4.0:
version "1.5.0"
resolved "https://registry.yarnpkg.com/ndjson/-/ndjson-1.5.0.tgz#ae603b36b134bcec347b452422b0bf98d5832ec8"
......@@ -735,7 +750,7 @@ raw-body@2.4.0:
iconv-lite "0.4.24"
unpipe "1.0.0"
readable-stream@~2.3.6:
readable-stream@2.3.7, readable-stream@~2.3.6:
version "2.3.7"
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57"
integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==
......@@ -863,6 +878,11 @@ split2@^2.1.0:
dependencies:
through2 "^2.0.2"
sqlstring@2.3.1:
version "2.3.1"
resolved "https://registry.yarnpkg.com/sqlstring/-/sqlstring-2.3.1.tgz#475393ff9e91479aea62dcaf0ca3d14983a7fb40"
integrity sha1-R1OT/56RR5rqYtyvDKPRSYOn+0A=
sshpk@^1.7.0:
version "1.16.1"
resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.16.1.tgz#fb661c0bef29b39db40769ee39fa70093d6f6877"
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment