138 lines
2.9 KiB
JavaScript
138 lines
2.9 KiB
JavaScript
import utils from './utils.js';
|
|
import db from '../helpers/db/index.js';
|
|
import {
|
|
MAX_SESSION_TIME,
|
|
MAX_TOKEN_TIME,
|
|
TAGS,
|
|
MAT_TOLERANCE,
|
|
SCORE_TOLERANCE,
|
|
} from '../R.js';
|
|
import pickRandomFile from './pickRandomFile.js';
|
|
import logger from './logging.js';
|
|
|
|
/** @typedef {import("../models/Mat.js").DbMat} DbMat */
|
|
|
|
/**
|
|
* Update the image mat
|
|
* @param {DbMat} imageMat
|
|
* @param {Array<number>} userMat
|
|
* @param {string} image
|
|
*/
|
|
function updateMat(imageMat, userMat, image) {
|
|
const updatedMat = [...imageMat.mat];
|
|
for (let i = 0; i < imageMat.mat.length; i++) {
|
|
const delta = 0.1;
|
|
if (userMat[i] === 1) {
|
|
if (updatedMat[i] + delta > 1) {
|
|
updatedMat[i] = 1.0;
|
|
} else {
|
|
updatedMat[i] += delta;
|
|
}
|
|
} else {
|
|
if (updatedMat[i] < delta) {
|
|
updatedMat[i] = 0.0;
|
|
} else {
|
|
updatedMat[i] -= delta;
|
|
}
|
|
}
|
|
}
|
|
|
|
logger.debug({oldMat: imageMat.mat});
|
|
logger.debug({newMat: updatedMat});
|
|
|
|
imageMat.num += 1;
|
|
imageMat.mat = updatedMat;
|
|
|
|
db.updateMat(image, imageMat);
|
|
}
|
|
|
|
/**
|
|
* @param {string} sessionId
|
|
* @param {Array<number>} userMat
|
|
* @return {Promise<Session>}
|
|
*/
|
|
export default async function verifyImage(sessionId, userMat) {
|
|
const result = await db.getSession(sessionId);
|
|
/** @type {import('../models/Session').DbSession} */
|
|
logger.debug({session: result});
|
|
|
|
if (!result) {
|
|
return [
|
|
'Session Expired',
|
|
null,
|
|
];
|
|
}
|
|
|
|
let {image, score, websiteKey} = result;
|
|
|
|
/** @type {import('../models/Session.js').Session)} */
|
|
const session = {
|
|
sessionId,
|
|
websiteKey,
|
|
};
|
|
|
|
const imageMat = await db.getMat(image);
|
|
logger.debug({imageMat});
|
|
const trueArgmax = utils.argmaxThresh(imageMat.mat, MAT_TOLERANCE).join(',');
|
|
const userArgmax = utils.argmaxThresh(userMat, 1).join(',');
|
|
|
|
updateMat(imageMat, userMat, image);
|
|
|
|
logger.debug({trueArgmax});
|
|
logger.debug({userArgmax});
|
|
|
|
const delta = imageMat.num * 0.05;
|
|
|
|
if (userArgmax !== trueArgmax) {
|
|
// TODO: Decrease the score based on mat dispersion
|
|
// High variance = small reduction
|
|
// Low variance = high reduction
|
|
score -= delta;
|
|
} else {
|
|
score += delta;
|
|
}
|
|
|
|
if (score >= SCORE_TOLERANCE) {
|
|
const nonce = utils.randomBytes(24);
|
|
session.token = nonce;
|
|
|
|
await db.deleteSession(sessionId);
|
|
await db.setToken({
|
|
token: nonce,
|
|
websiteKey,
|
|
score,
|
|
expiry: Date.now() + MAX_TOKEN_TIME,
|
|
});
|
|
|
|
return [
|
|
null,
|
|
session,
|
|
{
|
|
removeCookie: websiteKey,
|
|
},
|
|
];
|
|
}
|
|
|
|
const newImageFilename = await pickRandomFile();
|
|
// TODO: Make imageTagId dynamic
|
|
const newImageTagId = 1;
|
|
|
|
const update = Object.assign(result, {
|
|
image: newImageFilename.split('.')[0],
|
|
obj: newImageTagId,
|
|
score,
|
|
expiry: Date.now() + MAX_SESSION_TIME,
|
|
});
|
|
|
|
logger.debug({update});
|
|
|
|
await db.updateSession(sessionId, update);
|
|
|
|
session.imageTag = TAGS[newImageTagId];
|
|
|
|
return [
|
|
null,
|
|
session,
|
|
];
|
|
}
|