Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Server-side usability metrics #107

Open
wants to merge 60 commits into
base: pacesetters
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
60 commits
Select commit Hold shift + click to select a range
d18a20b
updated README w/ current routes
lucyq Jan 5, 2018
1e8a1ce
Fix Zenodo name
frederickjansen Feb 7, 2018
92f8347
Remove unused dependencies
frederickjansen Mar 8, 2018
4a0e996
Update package-lock.json
frederickjansen Mar 8, 2018
bca4360
add preliminary analytic collection
p-flock Sep 16, 2018
0ebdd9c
Add analytic fields to encrypt_and_send in the client app.
p-flock Sep 16, 2018
ebc96c9
data submission working
lucyq Sep 17, 2018
e0b00e4
making route changes
lucyq Sep 17, 2018
b810bf9
Merge branch 'PF_analytics' of github.com:multiparty/web-mpc into PF_…
lucyq Sep 17, 2018
452f4ae
normalize # of fields in analytic data being sent to the server. Log …
p-flock Sep 17, 2018
1255cdb
changes before switching branches
lucyq Sep 18, 2018
de2ceda
make positional array 2d instead of 3d.
p-flock Sep 18, 2018
0b16ea5
Merge branch 'PF_analytics' of github.com:multiparty/web-mpc into PF_…
lucyq Sep 18, 2018
70d723f
line 84 fix array access.
p-flock Sep 18, 2018
33ceafb
Merge branch 'PF_analytics' of github.com:multiparty/web-mpc into PF_…
lucyq Sep 18, 2018
aeabc1a
data submission actually working with correct masks
lucyq Sep 18, 2018
295fc7d
getting usability data and writing mouse positions to csv
lucyq Sep 18, 2018
edf88d4
encrypting and decrypting masks
lucyq Sep 28, 2018
5b86aac
Anonymize client site by not loading any organizational logos or images.
p-flock Oct 7, 2018
0ffe30b
Re-add navigational images for buttons
p-flock Oct 7, 2018
9d508f8
anonymized client/submission page, removed BU and BWWC logos and text.
p-flock Oct 8, 2018
9c8ca51
Add all validation errors to analytics object, to be incremented when…
p-flock Oct 8, 2018
acf7f80
Added mouse clicks and corected validation errors, added new fields t…
p-flock Oct 9, 2018
fb6752f
Merge branch 'PF_analytics' of github.com:multiparty/web-mpc into PF_…
lucyq Oct 9, 2018
8125b8b
move analytics functions and data structures for the client into cont…
p-flock Nov 9, 2018
8d6485d
small fixes/linting in usabilityController.
p-flock Nov 9, 2018
4febc73
delete analyticsController in favor of usabilityController which is l…
p-flock Nov 9, 2018
e15a8a6
fix conflicts
lucyq Nov 12, 2018
181f0fe
removed extraneous required libs
lucyq Nov 12, 2018
bacea85
resolving merge conflicts
lucyq Jan 15, 2019
e7b5163
resolving more merge conflicts
lucyq Jan 15, 2019
8a37a18
moved valdiation error updates to usabilitycontroller
lucyq Jan 16, 2019
37290bb
progress
lucyq Jan 16, 2019
ee67584
reorganizing code
lucyq Jan 22, 2019
a9d74e9
merging to pacesetters jiff integration update
lucyq Feb 1, 2019
f0fc600
adding usabilitycontroller back
lucyq Feb 1, 2019
1cad3b4
migrating some basic test infra
lucyq Feb 7, 2019
336e4c1
minor change to usabilitycontroller
lucyq Feb 7, 2019
5bb996c
added browser metrics
lucyq Feb 7, 2019
9ad78e3
sending browser and time spent to server. cannot unmask
lucyq Feb 8, 2019
45d4c2a
deleting placeholder value in unmask.html
lucyq Feb 8, 2019
92c617d
saving gitignore
lucyq Feb 8, 2019
b4f8f14
fixing merge conflicts
lucyq Feb 8, 2019
3f018c7
getting browser analytics end-to-end
lucyq Feb 8, 2019
4e659b6
Saving usability metrics as JSON file
lucyq Feb 8, 2019
67e585a
adding data prefilled. still bug
lucyq Feb 8, 2019
9e89dc5
linting
KinanBab Feb 9, 2019
844745b
data prefilled complete
lucyq Feb 11, 2019
a0cea17
Merge branch 'PF_analytics' of github.com:multiparty/web-mpc into PF_…
lucyq Feb 11, 2019
5377778
generalize initialization of usability metrics by moving measurements…
lucyq Feb 11, 2019
1549638
adding actual means of measuring time spent, validation errors, gener…
lucyq Feb 12, 2019
943a24e
removing values from testing
lucyq Feb 12, 2019
54bb48f
added time spent in session area
lucyq Feb 12, 2019
a6b4b2b
minor linting fix
lucyq Feb 12, 2019
22ca285
fixed previous bugs in session_info_error. generalized time spent
lucyq Feb 13, 2019
d99ff28
deleted testcafe files
lucyq Feb 13, 2019
2656f00
fixing merge conflicts
lucyq Feb 13, 2019
001f22d
fixing new merge conflicts
lucyq Feb 13, 2019
077762e
basic code structure for server side analytics
lucyq Feb 13, 2019
1725397
Resubmission average
KinanBab Feb 14, 2019
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
.idea
node_modules
.DS_store
test/cafe/node_modules
Empty file modified LICENSE
100644 → 100755
Empty file.
Empty file modified README.md
100644 → 100755
Empty file.
Empty file modified client/app/config/common.js
100644 → 100755
Empty file.
Empty file modified client/app/config/jiff.js
100644 → 100755
Empty file.
Empty file modified client/app/controllers/analystController.js
100644 → 100755
Empty file.
22 changes: 18 additions & 4 deletions client/app/controllers/clientController.js
100644 → 100755
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/* global alertify, $ */
define(['jquery', 'controllers/tableController', 'controllers/jiffController', 'alertify', 'alertify_defaults', 'table_template'],
function ($, tableController, jiffController, alertify, _, table_template) {
define(['jquery', 'controllers/tableController', 'controllers/jiffController', 'controllers/usabilityController', 'alertify', 'alertify_defaults', 'table_template'],
function ($, tableController, jiffController, usabilityController, alertify, _, table_template) {
var client = (function () {
/**
* Displays the given submission as the last submission in
Expand Down Expand Up @@ -94,7 +94,7 @@ define(['jquery', 'controllers/tableController', 'controllers/jiffController', '
dataType: 'text'
}).then(function (response) {
JSON.parse(response); // verify response is json (error responses are string messages)

var $parent = $('#session, #participation-code').parent();
$parent.removeClass('has-error').addClass('has-success has-feedback');
$parent.find('.success-icon').removeClass('hidden').addClass('show');
Expand All @@ -104,6 +104,7 @@ define(['jquery', 'controllers/tableController', 'controllers/jiffController', '
callback && callback(true);
}).catch(function (err) {
var errorMsg = SERVER_ERR;
usabilityController.addValidationError("SESSION_INFO_ERROR");
if (err && err.hasOwnProperty('responseText') && err.responseText !== undefined) {
errorMsg = err.responseText;
}
Expand All @@ -127,24 +128,28 @@ define(['jquery', 'controllers/tableController', 'controllers/jiffController', '
var $session = $('#session');
if (!validateSessionInput($session, false)) {
errors.push(SESSION_KEY_ERROR);
usabilityController.addValidationError("SESSION_KEY_ERROR");
}

var $participationCode = $('#participation-code');
if (!validateSessionInput($participationCode, false)) {
errors.push(PARTICIPATION_CODE_ERROR);
usabilityController.addValidationError("PARTICIPATION_CODE_ERROR");
}

// Validate the remaining components after session and
// and participation code are validated with the server.
var validateRemainingComponents = function (result) {
if (!result) {
errors.push(SESSION_PARTICIPATION_CODE_SERVER_ERROR);
usabilityController.addValidationError("SESSION_PARTICIPATION_CODE_SERVER_ERROR");
}

// Verify confirmation check box was checked
var verifyChecked = $('#verify').is(':checked');
if (!verifyChecked) {
errors.push(UNCHECKED_ERR);
usabilityController.addValidationError("UNCHECKED_ERR");
}

// Verify additional questions
Expand Down Expand Up @@ -194,6 +199,7 @@ define(['jquery', 'controllers/tableController', 'controllers/jiffController', '
}
if (errors.indexOf(errorMsg) === -1) {
errors.push(errorMsg);
usabilityController.addValidationError("CELL_ERROR");
}
};
tableController.registerErrorHandler(errorHandler);
Expand Down Expand Up @@ -264,7 +270,7 @@ define(['jquery', 'controllers/tableController', 'controllers/jiffController', '
var text = $(questions_text[q]).text();
text = text.replace(/\s+/g, ' '); // Replace many white spaces with just one space.
data_submission['questions'][text] = question_data;
questions_public[text] = Object.assign({}, question_data);
questions_public[text] = Object.assign({}, question_data);
}

// Handle table data, tables are represented as 2D associative arrays
Expand All @@ -274,6 +280,12 @@ define(['jquery', 'controllers/tableController', 'controllers/jiffController', '
data_submission[tables_data[i].name] = tables_data[i].data;
}

if (document.getElementById('choose-file').files.length > 0) {
usabilityController.dataPrefilled();
}

data_submission['usability'] = usabilityController.analytics;

// Secret share / mask the data.
jiffController.client.submit(session, participationCode, data_submission, function (err, response) {
if (err == null || err === 200) {
Expand All @@ -286,8 +298,10 @@ define(['jquery', 'controllers/tableController', 'controllers/jiffController', '
} else if (err === 0 || err === 500) {
// check for status 0 or status 500 (Server not reachable.)
error(SERVER_ERR);
usabilityController.addValidationError("SERVER_ERR");
} else {
error(GENERIC_SUBMISSION_ERR);
usabilityController.addValidationError("GENERIC_SUBMISSION_ERR");
}

la.stop();
Expand Down
18 changes: 16 additions & 2 deletions client/app/controllers/jiffController.js
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,16 @@ define(['mpc', 'pki', 'BigNumber', 'jiff', 'jiff_bignumber', 'jiff_restAPI', 'ta
values.push(dataSubmission['questions'][q.question][q.option]);
}

for (var k = 0; k < ordering.usability.length; k++) {
const m = ordering.usability[k].metric;
const f = ordering.usability[k].field;
if (f !== null) {
values.push(dataSubmission.usability[m][f]);
} else {
values.push(dataSubmission.usability[m]);
}
}

// Handle jiff errors returned from server
var options = {
onError: function (errorString) {
Expand Down Expand Up @@ -149,18 +159,22 @@ define(['mpc', 'pki', 'BigNumber', 'jiff', 'jiff_bignumber', 'jiff_restAPI', 'ta

// Meta-info
var ordering = mpc.consistentOrdering(table_template);
var submitters = JSON.parse(msg);
msg = JSON.parse(msg);
var submitters = msg['submitters'];
var resubmission_avg = msg['resubmission_avg'];

// Compute and Format
var promise = mpc.compute(jiff, submitters, ordering);
promise = mpc.format(promise, submitters, ordering);
promise.then(function (result) {
jiff.disconnect(false, false);
result['usability']['resubmission_avg'] = resubmission_avg;
callback(result);
}).catch(function (err) {
error(err);
});
});

};

// Exports
Expand All @@ -169,7 +183,7 @@ define(['mpc', 'pki', 'BigNumber', 'jiff', 'jiff_bignumber', 'jiff_restAPI', 'ta
submit: clientSubmit
},
analyst: {
computeAndFormat: computeAndFormat
computeAndFormat
}
}
});
6 changes: 6 additions & 0 deletions client/app/controllers/tableController.js
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -1013,6 +1013,11 @@ define(['jquery', 'Handsontable', 'table_template', 'filesaver', 'alertify', 'qt
return colWidths;
}

function saveUsability(usability, session) {
var json = JSON.stringify(usability);
filesaver.saveAs(new Blob([json], {type: 'application/json'}), 'Usability_' + session + '.json');
}

function saveQuestions(questions, session) {
if (questions == null) {
return;
Expand Down Expand Up @@ -1050,6 +1055,7 @@ define(['jquery', 'Handsontable', 'table_template', 'filesaver', 'alertify', 'qt
fillData,
saveTables,
saveQuestions,
saveUsability,
displayReadTable,
resetTableWidth,
updateTableWidth,
Expand Down
109 changes: 109 additions & 0 deletions client/app/controllers/usabilityController.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
define(['table_template'], function (table_template) {

let analytics = {};
let timers = {};

function initialize() {
for (var metric of table_template.usability) {
if (typeof(metric) === 'string') {
analytics[metric] = 0;
} else if (typeof(metric) === 'object') {
var key = Object.keys(metric)[0];
var fields = metric[key];
analytics[key] = {};

for (var f of fields) {
analytics[key][f] = 0;
}
}
}

for (let k of Object.keys(analytics.time_spent)) {

if (k === 'page') {
timers[k] = new Date();
} else {
timers[k] = null;
}

$('#session-area').on("mouseenter", function() {
startTimer(k);
});

$('#session-area').on("mouseleave", function() {
endTimer(k);
});
}
window.addEventListener('blur', endTimer);
window.addEventListener('beforeunload', endTimer);
}

function detectBrave() {
// initial assertions
if (!window.google_onload_fired &&
navigator.userAgent &&
!navigator.userAgent.includes('Chrome'))
return false;

// set up test
var test = document.createElement('iframe');
test.style.display = 'none';
document.body.appendChild(test);

// empty frames only have this attribute set in Brave Shield
var is_brave = (test.contentWindow.google_onload_fired === true);

// teardown test
test.parentNode.removeChild(test);

return is_brave;
}

function startTimer(key) {
timers[key] = new Date();
};

function endTimer(key) {
if (typeof(key) !== 'string') {
key = 'page';
}
const endDate = new Date();
const spentTime = endDate.getTime() - timers[key].getTime();
analytics.time_spent[key] += spentTime;
};

function saveBrowser() {
// check Edge
var ua=navigator.userAgent,tem,M=ua.match(/(opera|chrome|safari|edge|firefox|msie|trident(?=\/))\/?\s*(\d+)/i) || [];
var browser = M[0].toLowerCase();

if (detectBrave) {
analytics.browser.brave += 1;
return;
}

for (let key in analytics.browser) {
if (browser.includes(key)) {
analytics.browser[key] += 1;
return;
}
}
analytics.browser.other += 1;
}

function addValidationError(err) {
analytics.validation_errors[err] += 1;
}

function dataPrefilled() {
analytics.data_prefilled += 1;
}

return {
addValidationError,
analytics,
dataPrefilled,
initialize,
saveBrowser
};
});
Empty file modified client/app/data/bwwc.js
100644 → 100755
Empty file.
20 changes: 20 additions & 0 deletions client/app/data/pacesetters.js
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,26 @@ define([], function () {
}
]
}
],
'usability': [
'data_prefilled',
{'time_spent': ['page', 'session_area', 'tables-area', 'review-and-submit', 'amount-spent', 'addressable-spend', 'number-MBEs']},
{'browser': ['brave', 'chrome', 'edge', 'msie', 'firefox', 'opera', 'other', 'safari']
},
{'validation_errors': [
'SESSION_KEY_ERROR',
'SESSION_INFO_ERROR',
'PARTICIPATION_CODE_ERROR',
'SESSION_PARTICIPATION_CODE_SERVER_ERROR',
'UNCHECKED_ERR',
'GENERIC_TABLE_ERR',
'SERVER_ERR',
'GENERIC_SUBMISSION_ERR',
'NAN_EMPTY_CELLS',
'SEMANTIC_CELLS',
'CELL_ERROR'
]
}
]
}
});
Empty file modified client/app/helper/alertify_defaults.js
100644 → 100755
Empty file.
Empty file modified client/app/helper/array.reduce-polyfill.min.js
100644 → 100755
Empty file.
Empty file modified client/app/helper/drop_sheet.js
100644 → 100755
Empty file.
Loading