190 lines
4.6 KiB
JavaScript
190 lines
4.6 KiB
JavaScript
import {promisify} from 'util';
|
|
import fs from 'fs';
|
|
import path from 'path';
|
|
import {client} from '../../idb.js';
|
|
import {PROJECT_ROOT, MAX_SESSION_TIME, TAGS} from '../../R.js';
|
|
import {argmaxThresh} from '../../helpers/utils.js';
|
|
import pickRandomFile from '../../helpers/pickRandomFile.js';
|
|
import Session from '../../models/Session.js';
|
|
import express from 'express';
|
|
const router = express.Router();
|
|
|
|
|
|
/**
|
|
* @typedef {Object} FileMat
|
|
* @property {Array<number>} mat Matrix of floats
|
|
* @property {number} nums Number of users that have seen this challenge
|
|
* @property {number} obj The object in the image
|
|
*/
|
|
|
|
/** @type {FileMat} */
|
|
const defaultMat = {
|
|
mat: Array(16).fill(0.5),
|
|
nums: 0,
|
|
obj: 0,
|
|
};
|
|
|
|
/**
|
|
* Get file matrix
|
|
* @param {string} image
|
|
* @return {FileMat}
|
|
*/
|
|
function getMat(image) {
|
|
const mats = JSON.parse(
|
|
fs.readFileSync(
|
|
path.join(PROJECT_ROOT, 'dev', 'mat.json'), {encoding: 'utf8'}));
|
|
|
|
return mats[image] || defaultMat;
|
|
}
|
|
|
|
/**
|
|
* Update the image mat
|
|
* @param {FileMat} 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;
|
|
}
|
|
}
|
|
}
|
|
|
|
console.log('OLD MAT: ', imageMat.mat);
|
|
console.log('NEW MAT: ', updatedMat);
|
|
|
|
imageMat.nums += 1;
|
|
imageMat.mat = updatedMat;
|
|
|
|
const mats = JSON.parse(
|
|
fs.readFileSync(
|
|
path.join(PROJECT_ROOT, 'dev', 'mat.json'), {encoding: 'utf8'}));
|
|
mats[image] = imageMat;
|
|
|
|
fs.writeFileSync(
|
|
path.join(PROJECT_ROOT, 'dev', 'mat.json'),
|
|
JSON.stringify(mats, null, 2), {encoding: 'utf8'});
|
|
}
|
|
|
|
/**
|
|
* @param {string} sessionId
|
|
* @param {Array<number>} userMat
|
|
* @return {Promise}
|
|
*/
|
|
async function verify(sessionId, userMat) {
|
|
const redisGet = promisify(client.get);
|
|
const session = await redisGet(sessionId)
|
|
.then((resp) => {
|
|
if (!resp) {
|
|
throw new Error('Session expired');
|
|
}
|
|
/** @type {Session} */
|
|
const result = JSON.parse(resp);
|
|
let {image, score, websiteKey} = result;
|
|
const imageMat = getMat(image);
|
|
const trueArgmax = argmaxThresh(imageMat.mat, 0.6).join(',');
|
|
const userArgmax = argmaxThresh(userMat, 1).join(',');
|
|
|
|
updateMat(imageMat, userMat, image);
|
|
|
|
console.log('trueArgmax', trueArgmax);
|
|
console.log('userArgmax', userArgmax);
|
|
|
|
const delta = imageMat.nums * 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;
|
|
}
|
|
|
|
|
|
return pickRandomFile().then((image)=>{
|
|
// TODO: Make me dynamic
|
|
const newImageTag = 1;
|
|
const update = JSON.stringify(
|
|
Object.assign(result, {
|
|
image: image,
|
|
obj: newImageTag,
|
|
}));
|
|
|
|
return promisify(client.setex)(sessionId, MAX_SESSION_TIME, update).then(()=>new Session({
|
|
sessionId, websiteKey, imageTag: TAGS[newImageTag],
|
|
}));
|
|
});
|
|
});
|
|
}
|
|
|
|
|
|
/**
|
|
* @typedef {import('../../models/Session.js').Session} IDBSession
|
|
*/
|
|
|
|
/**
|
|
* serveImage
|
|
* @param {string} sessionId
|
|
* @return {Promise}
|
|
*/
|
|
export function serveImage(sessionId) {
|
|
const redisGet = promisify(client.get);
|
|
return redisGet(sessionId)
|
|
.then((result) => {
|
|
if (!result) {
|
|
throw new Error('Session expired');
|
|
}
|
|
return result;
|
|
})
|
|
.then((result) => {
|
|
/** @type {Session} */
|
|
const sessionData = JSON.parse(result);
|
|
|
|
console.log(sessionData);
|
|
|
|
const {
|
|
// sessionId,
|
|
image,
|
|
// score,
|
|
} = sessionData;
|
|
|
|
// if (score < 0.1) {
|
|
// client.del(sessionId, (err)=>{
|
|
// if (err) return reject(err);
|
|
|
|
// return resolve([
|
|
// true,
|
|
// null,
|
|
// ]);
|
|
// });
|
|
// }
|
|
|
|
return [
|
|
null,
|
|
image + '.jpg',
|
|
];
|
|
});
|
|
}
|
|
|
|
export default router.post('/verify', async (req, res)=>{
|
|
const sessionId = req.body.s;
|
|
const mat = req.body.mat;
|
|
console.log(req.body);
|
|
|
|
const session = await verify(sessionId, mat);
|
|
res.json(session);
|
|
});
|