@reality.eth/reality-eth-lib 3.0.1 → 3.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/formatters/question.js +86 -12
- package/package.json +5 -5
- package/test/formatters.js +83 -6
package/formatters/question.js
CHANGED
|
@@ -171,7 +171,7 @@ exports.secondsTodHms = function(sec) {
|
|
|
171
171
|
return dDisplay + hDisplay + mDisplay + sDisplay;
|
|
172
172
|
}
|
|
173
173
|
|
|
174
|
-
exports.parseQuestionJSON = function(data) {
|
|
174
|
+
exports.parseQuestionJSON = function(data, errors_to_title) {
|
|
175
175
|
|
|
176
176
|
var question_json;
|
|
177
177
|
try {
|
|
@@ -179,23 +179,43 @@ exports.parseQuestionJSON = function(data) {
|
|
|
179
179
|
} catch(e) {
|
|
180
180
|
question_json = {
|
|
181
181
|
'title': '[Badly formatted question]: ' + data,
|
|
182
|
-
'type': 'broken-question'
|
|
182
|
+
'type': 'broken-question',
|
|
183
|
+
'errors': {"json_parse_failed": true}
|
|
183
184
|
};
|
|
184
185
|
}
|
|
185
186
|
if (question_json['outcomes'] && question_json['outcomes'].length > QUESTION_MAX_OUTCOMES) {
|
|
186
|
-
|
|
187
|
+
question_json['errors'] = {'too_many_outcomes': true}
|
|
188
|
+
}
|
|
189
|
+
if ('type' in question_json && question_json['type'] == 'datetime' && 'precision' in question_json) {
|
|
190
|
+
if (!(['Y', 'm', 'd', 'H', 'i', 's'].includes(question_json['precision']))) {
|
|
191
|
+
question_json['errors'] = {'invalid_precision': true};
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
// If errors_to_title is specified, we add any error message to the title to make sure we don't lose it
|
|
195
|
+
if (errors_to_title) {
|
|
196
|
+
if ('errors' in question_json) {
|
|
197
|
+
const prependers = {
|
|
198
|
+
'invalid_precision': 'Invalid date format',
|
|
199
|
+
'too_many_outcomes': 'Too many outcomes'
|
|
200
|
+
}
|
|
201
|
+
for (var e in question_json['errors']) {
|
|
202
|
+
if (e in prependers) {
|
|
203
|
+
question_json['title'] = '['+prependers[e]+'] ' + question_json['title'];
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
}
|
|
187
207
|
}
|
|
188
208
|
return question_json;
|
|
189
209
|
|
|
190
210
|
}
|
|
191
211
|
|
|
192
|
-
exports.populatedJSONForTemplate = function(template, question) {
|
|
212
|
+
exports.populatedJSONForTemplate = function(template, question, errors_to_title) {
|
|
193
213
|
var qbits = question.split(module.exports.delimiter());
|
|
194
214
|
//console.log('pp', template);
|
|
195
215
|
//console.log('qbits', qbits);
|
|
196
216
|
var interpolated = vsprintf(template, qbits);
|
|
197
217
|
//console.log('resulting template', interpolated);
|
|
198
|
-
return module.exports.parseQuestionJSON(interpolated);
|
|
218
|
+
return module.exports.parseQuestionJSON(interpolated, errors_to_title);
|
|
199
219
|
}
|
|
200
220
|
|
|
201
221
|
exports.encodeText = function(qtype, txt, outcomes, category, lang) {
|
|
@@ -292,18 +312,72 @@ exports.getAnswerString = function(question_json, answer) {
|
|
|
292
312
|
}
|
|
293
313
|
break;
|
|
294
314
|
case 'datetime':
|
|
315
|
+
let precision = 'd';
|
|
316
|
+
if ('precision' in question_json && ['Y', 'm', 'd', 'H', 'i', 's'].includes(question_json['precision'])) {
|
|
317
|
+
precision = question_json['precision'];
|
|
318
|
+
}
|
|
295
319
|
let ts = parseInt(module.exports.bytes32ToString(answer, question_json));
|
|
296
320
|
let dateObj = new Date(ts * 1000);
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
321
|
+
|
|
322
|
+
const year = dateObj.getUTCFullYear();
|
|
323
|
+
const month = dateObj.getUTCMonth() + 1;
|
|
324
|
+
const date = dateObj.getUTCDate();
|
|
325
|
+
const hour = dateObj.getUTCHours();
|
|
326
|
+
const min = dateObj.getUTCMinutes();
|
|
327
|
+
const sec = dateObj.getUTCSeconds();
|
|
328
|
+
|
|
329
|
+
// We need whatever the precision states, plus anything above
|
|
330
|
+
const needy = true;
|
|
331
|
+
const needm = (precision != 'Y');
|
|
332
|
+
const needd = needm && (precision != 'm');
|
|
333
|
+
const needH = needd && (precision != 'd');
|
|
334
|
+
const needi = needH && (precision != 'H');
|
|
335
|
+
const needs = needi && (precision != 'i');
|
|
336
|
+
|
|
337
|
+
// If anything is set then we've got it.
|
|
338
|
+
// We also consider that anything required by the precision is there, but set to 0
|
|
339
|
+
const hass = needs || sec > 0;
|
|
340
|
+
const hasi = needi || hass || min > 0;
|
|
341
|
+
const hasH = needH || hasi || hour > 0;
|
|
342
|
+
const hasd = needd || hasH || date > 1;
|
|
343
|
+
const hasm = needm || hasd || month > 1;
|
|
344
|
+
const hasy = true;
|
|
345
|
+
|
|
346
|
+
// We'll show an invalid warning if we've got a more precise date than the precision demands
|
|
347
|
+
let invalid = false;
|
|
348
|
+
if (!needm && hasm) invalid = true;
|
|
349
|
+
if (!needd && hasd) invalid = true;
|
|
350
|
+
if (!needH && hasH) invalid = true;
|
|
351
|
+
if (!needi && hasi) invalid = true;
|
|
352
|
+
if (!needs && hass) invalid = true;
|
|
353
|
+
|
|
354
|
+
if (invalid) {
|
|
355
|
+
label = '[Invalid datetime]: ';
|
|
356
|
+
}
|
|
301
357
|
|
|
302
358
|
function pad2(n) { return ("0" + n).slice(-2); }
|
|
303
|
-
|
|
304
|
-
if (
|
|
305
|
-
label
|
|
359
|
+
|
|
360
|
+
if (hasy) {
|
|
361
|
+
label += year;
|
|
362
|
+
}
|
|
363
|
+
if (hasm) {
|
|
364
|
+
label += '-'+pad2(month);
|
|
365
|
+
}
|
|
366
|
+
if (hasd) {
|
|
367
|
+
label += '-'+pad2(date);
|
|
368
|
+
}
|
|
369
|
+
if (hasH) {
|
|
370
|
+
label += ' '+pad2(hour);
|
|
371
|
+
}
|
|
372
|
+
if (hasi) {
|
|
373
|
+
label += ':'+pad2(min);
|
|
374
|
+
} else if (hasH) {
|
|
375
|
+
// "2021-12-23 11" without the minutes at the end is hard to understand so add "hr"
|
|
376
|
+
label += 'hr';
|
|
306
377
|
}
|
|
378
|
+
if (hass) {
|
|
379
|
+
label += ':'+pad2(sec);
|
|
380
|
+
}
|
|
307
381
|
break;
|
|
308
382
|
}
|
|
309
383
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@reality.eth/reality-eth-lib",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.1.1",
|
|
4
4
|
"description": "Tools for handling questions in the reality.eth fact verification platform",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"test": "env TZ='Asia/Kabul' mocha ./test"
|
|
@@ -16,14 +16,14 @@
|
|
|
16
16
|
"author": "Edmund Edgar (https://reality.eth.link)",
|
|
17
17
|
"license": "GPL-3.0",
|
|
18
18
|
"dependencies": {
|
|
19
|
-
"@reality.eth/contracts": "^3.0.
|
|
19
|
+
"@reality.eth/contracts": "^3.0.3",
|
|
20
20
|
"bignumber.js": "^7.2.1",
|
|
21
|
-
"bn.js": "^
|
|
21
|
+
"bn.js": "^5.2.1",
|
|
22
22
|
"ethereumjs-abi": "^0.6.5",
|
|
23
23
|
"sprintf-js": "^1.1.1"
|
|
24
24
|
},
|
|
25
25
|
"devDependencies": {
|
|
26
|
-
"chai": "^4.
|
|
26
|
+
"chai": "^4.3.6",
|
|
27
27
|
"chai-bignumber": "^2.0.2",
|
|
28
28
|
"mocha": "^5.2.0",
|
|
29
29
|
"truffle": "^4.0.1"
|
|
@@ -36,5 +36,5 @@
|
|
|
36
36
|
"url": "https://github.com/RealityETH/monorepo/issues"
|
|
37
37
|
},
|
|
38
38
|
"homepage": "https://reality.eth.link",
|
|
39
|
-
"gitHead": "
|
|
39
|
+
"gitHead": "b9fcb24ff3274a58c4f98c0c97b58c4d5c5b0fcd"
|
|
40
40
|
}
|
package/test/formatters.js
CHANGED
|
@@ -116,13 +116,66 @@ describe('Answer strings', function() {
|
|
|
116
116
|
expect(rc_question.getAnswerString(q, '0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff')).to.equal('-1e-18');
|
|
117
117
|
});
|
|
118
118
|
*/
|
|
119
|
-
it('Handles datetimes as expected', function() {
|
|
119
|
+
it('Handles datetimes of default precision as expected', function() {
|
|
120
120
|
var q = rc_question.populatedJSONForTemplate(rc_template.defaultTemplateForType('datetime'), '');
|
|
121
|
-
expect(rc_question.getAnswerString(q, '0x0000000000000000000000000000000000000000000000000000000000000000')).to.equal('1970
|
|
122
|
-
expect(rc_question.getAnswerString(q, '0x000000000000000000000000000000000000000000000000000000005B0DE980')).to.equal('2018
|
|
123
|
-
expect(rc_question.getAnswerString(q, '0x000000000000000000000000000000000000000000000000000000005B0DE981')).to.equal('2018
|
|
124
|
-
expect(rc_question.getAnswerString(q, '0x000000000000000000000000000000000000000000000000000000005B0E02F7')).to.equal('2018
|
|
121
|
+
expect(rc_question.getAnswerString(q, '0x0000000000000000000000000000000000000000000000000000000000000000')).to.equal('1970-01-01');
|
|
122
|
+
expect(rc_question.getAnswerString(q, '0x000000000000000000000000000000000000000000000000000000005B0DE980')).to.equal('2018-05-30');
|
|
123
|
+
expect(rc_question.getAnswerString(q, '0x000000000000000000000000000000000000000000000000000000005B0DE981')).to.equal('[Invalid datetime]: 2018-05-30 00:00:01');
|
|
124
|
+
expect(rc_question.getAnswerString(q, '0x000000000000000000000000000000000000000000000000000000005B0E02F7')).to.equal('[Invalid datetime]: 2018-05-30 01:48:39');
|
|
125
125
|
});
|
|
126
|
+
it('Handles datetimes of specified precision as expected', function() {
|
|
127
|
+
var q = rc_question.populatedJSONForTemplate(rc_template.defaultTemplateForType('datetime'), '');
|
|
128
|
+
q['precision'] = 'd';
|
|
129
|
+
expect(rc_question.getAnswerString(q, '0x0000000000000000000000000000000000000000000000000000000000000000')).to.equal('1970-01-01');
|
|
130
|
+
expect(rc_question.getAnswerString(q, '0x000000000000000000000000000000000000000000000000000000005B0DE980')).to.equal('2018-05-30');
|
|
131
|
+
expect(rc_question.getAnswerString(q, '0x000000000000000000000000000000000000000000000000000000005B0DE981')).to.equal('[Invalid datetime]: 2018-05-30 00:00:01');
|
|
132
|
+
expect(rc_question.getAnswerString(q, '0x000000000000000000000000000000000000000000000000000000005B0E02F7')).to.equal('[Invalid datetime]: 2018-05-30 01:48:39');
|
|
133
|
+
|
|
134
|
+
q['precision'] = 'H';
|
|
135
|
+
expect(rc_question.getAnswerString(q, '0x000000000000000000000000000000000000000000000000000000005B0E02F7')).to.equal('[Invalid datetime]: 2018-05-30 01:48:39');
|
|
136
|
+
expect(rc_question.getAnswerString(q, '0x000000000000000000000000000000000000000000000000000000005B0DE980')).to.equal('2018-05-30 00hr');
|
|
137
|
+
|
|
138
|
+
q['precision'] = 'i';
|
|
139
|
+
expect(rc_question.getAnswerString(q, '0x000000000000000000000000000000000000000000000000000000005B0E02F7')).to.equal('[Invalid datetime]: 2018-05-30 01:48:39');
|
|
140
|
+
expect(rc_question.getAnswerString(q, '0x000000000000000000000000000000000000000000000000000000005B0DE980')).to.equal('2018-05-30 00:00');
|
|
141
|
+
|
|
142
|
+
q['precision'] = 's';
|
|
143
|
+
expect(rc_question.getAnswerString(q, '0x000000000000000000000000000000000000000000000000000000005B0E02F7')).to.equal('2018-05-30 01:48:39');
|
|
144
|
+
expect(rc_question.getAnswerString(q, '0x000000000000000000000000000000000000000000000000000000005B0DE980')).to.equal('2018-05-30 00:00:00');
|
|
145
|
+
|
|
146
|
+
q['precision'] = 'i';
|
|
147
|
+
expect(rc_question.getAnswerString(q, '0x000000000000000000000000000000000000000000000000000000006163683C')).to.equal('2021-10-10 22:25');
|
|
148
|
+
|
|
149
|
+
q['precision'] = 'H';
|
|
150
|
+
expect(rc_question.getAnswerString(q, '0x000000000000000000000000000000000000000000000000000000006163683C')).to.equal('[Invalid datetime]: 2021-10-10 22:25');
|
|
151
|
+
expect(rc_question.getAnswerString(q, '0x0000000000000000000000000000000000000000000000000000000061636260')).to.equal('2021-10-10 22hr');
|
|
152
|
+
// q['precision'] = 'H';
|
|
153
|
+
|
|
154
|
+
q['precision'] = 'd';
|
|
155
|
+
expect(rc_question.getAnswerString(q, '0x0000000000000000000000000000000000000000000000000000000061636260')).to.equal('[Invalid datetime]: 2021-10-10 22hr');
|
|
156
|
+
|
|
157
|
+
q['precision'] = 's';
|
|
158
|
+
expect(rc_question.getAnswerString(q, '0x000000000000000000000000000000000000000000000000000000005FEE6600')).to.equal('2021-01-01 00:00:00');
|
|
159
|
+
q['precision'] = 'i';
|
|
160
|
+
expect(rc_question.getAnswerString(q, '0x000000000000000000000000000000000000000000000000000000005FEE6600')).to.equal('2021-01-01 00:00');
|
|
161
|
+
q['precision'] = 'H';
|
|
162
|
+
expect(rc_question.getAnswerString(q, '0x000000000000000000000000000000000000000000000000000000005FEE6600')).to.equal('2021-01-01 00hr');
|
|
163
|
+
q['precision'] = 'd';
|
|
164
|
+
expect(rc_question.getAnswerString(q, '0x000000000000000000000000000000000000000000000000000000005FEE6600')).to.equal('2021-01-01');
|
|
165
|
+
q['precision'] = 'm';
|
|
166
|
+
expect(rc_question.getAnswerString(q, '0x000000000000000000000000000000000000000000000000000000005FEE6600')).to.equal('2021-01');
|
|
167
|
+
q['precision'] = 'Y';
|
|
168
|
+
expect(rc_question.getAnswerString(q, '0x000000000000000000000000000000000000000000000000000000005FEE6600')).to.equal('2021');
|
|
169
|
+
|
|
170
|
+
// 1609426800 2021 5FEE6600
|
|
171
|
+
|
|
172
|
+
//1633904700 6163683C
|
|
173
|
+
//1633903200 61636260
|
|
174
|
+
//1609426800 5FEDE770
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
});
|
|
178
|
+
|
|
126
179
|
it('Handles single selects as expected', function() {
|
|
127
180
|
var outcomes = ['thing1', 'thing2', 'thing3'];
|
|
128
181
|
var qtext = rc_question.encodeText('single-select', 'oink', outcomes, 'my-category');
|
|
@@ -139,7 +192,21 @@ describe('Answer strings', function() {
|
|
|
139
192
|
expect(rc_question.getAnswerString(q, '0x0000000000000000000000000000000000000000000000000000000000000002')).to.equal('thing2');
|
|
140
193
|
expect(rc_question.getAnswerString(q, '0x0000000000000000000000000000000000000000000000000000000000000003')).to.equal('thing1 / thing2');
|
|
141
194
|
});
|
|
142
|
-
|
|
195
|
+
it('Sets an error if there are too many outcomes', function() {
|
|
196
|
+
var outcomes = [];
|
|
197
|
+
for(var i=0; i<129; i++) {
|
|
198
|
+
outcomes.push('thing'+i);
|
|
199
|
+
}
|
|
200
|
+
var qtext = rc_question.encodeText('multiple-select', 'oink', outcomes, 'my-category');
|
|
201
|
+
var q1 = rc_question.populatedJSONForTemplate(rc_template.defaultTemplateForType('multiple-select'), qtext);
|
|
202
|
+
expect(q1.errors.too_many_outcomes).to.equal(true);
|
|
203
|
+
console.log(q1.title);
|
|
204
|
+
expect(q1.title).to.equal('oink');
|
|
205
|
+
var q2 = rc_question.populatedJSONForTemplate(rc_template.defaultTemplateForType('multiple-select'), qtext, true);
|
|
206
|
+
expect(q2.errors.too_many_outcomes).to.equal(true);
|
|
207
|
+
expect(q2.title).to.equal('[Too many outcomes] oink');
|
|
208
|
+
//expect(rc_question.getAnswerString(q, '0x0000000000000000000000000000000000000000000000000000000000000003')).to.equal('thing1 / thing2');
|
|
209
|
+
});
|
|
143
210
|
});
|
|
144
211
|
/*
|
|
145
212
|
describe('Min Number Formatter', function() {
|
|
@@ -161,6 +228,16 @@ describe('Broken questions', function() {
|
|
|
161
228
|
var broken = '{ "title": "You need to quote your "quotation marks" before parsing", "type": "bool" }';
|
|
162
229
|
var q = rc_question.populatedJSONForTemplate(rc_template.defaultTemplateForType('bool'), broken);
|
|
163
230
|
expect(q.type).to.equal('broken-question');
|
|
231
|
+
expect(q.errors.json_parse_failed).to.equal(true);
|
|
232
|
+
});
|
|
233
|
+
it('Sets the invalid_precision error if the precision is set but to something other than Y m d H i s', function() {
|
|
234
|
+
var broken = '{ "title": "This datetime will not work", "type": "datetime", "precision": "X" }';
|
|
235
|
+
var q1 = rc_question.populatedJSONForTemplate(broken, '');
|
|
236
|
+
expect(q1.errors.invalid_precision).to.equal(true);
|
|
237
|
+
expect(q1.title).to.equal('This datetime will not work');
|
|
238
|
+
var q2 = rc_question.populatedJSONForTemplate(broken, '', true);
|
|
239
|
+
expect(q2.errors.invalid_precision).to.equal(true);
|
|
240
|
+
expect(q2.title).to.equal('[Invalid date format] This datetime will not work');
|
|
164
241
|
});
|
|
165
242
|
});
|
|
166
243
|
|