Skip to content

Commit 80a0e82

Browse files
authored
Merge pull request #2 from HumanSignal/fb-leap-1834/readable-pause-script
feat: LEAP-1834: Better readability of the pausing annotators script
2 parents b51e428 + 81e101b commit 80a0e82

File tree

1 file changed

+53
-20
lines changed

1 file changed

+53
-20
lines changed

pausing_annotator/pause.js

Lines changed: 53 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,69 @@
1-
const rules = {
2-
timesInARow: (times) => (items, field) => {
1+
/****** CONFIGURATION FOR PAUSING RULES ******/
2+
/**
3+
* `fields` describe per-field rules in a format
4+
* <field-name>: [<rule>(<optional params for the rule>)]
5+
* `global` is for rules applied to the whole annotation
6+
*/
7+
const RULES = {
8+
fields: {
9+
comment: [timesInARow(3)],
10+
sentiment: [tooSimilar()],
11+
},
12+
global: [tooFast()],
13+
}
14+
/**
15+
* Messages for users when they are paused.
16+
* Each message is a function with the same name as original rule and it receives an object with
17+
* `items` and `field`.
18+
*/
19+
const MESSAGES = {
20+
timesInARow: ({ field }) => `Too many similar values for ${field}`,
21+
tooSimilar: ({ field }) => `Too similar values for ${field}`,
22+
tooFast: () => `Too fast annotations`,
23+
}
24+
25+
26+
27+
/****** ALL AVAILABLE RULES ******/
28+
/**
29+
* They recieve params and return function which recieves `items` and optional `field`.
30+
* If condition is met it returns warning message. If not — returns `false`.
31+
*/
32+
33+
// check if values for the `field` in last `times` items are the same
34+
function timesInARow(times) {
35+
return (items, field) => {
336
if (items.length < times) return false
437
const last = String(items.at(-1).values[field])
538
return items.slice(-times).every((item) => String(item.values[field]) === last)
6-
? `Too many similar values for ${field}`
39+
? MESSAGES.timesInARow({ items, field })
740
: false
8-
},
9-
tooSimilar: (deviation = 0.1, max_count = 10) => (items, field) => {
41+
};
42+
}
43+
function tooSimilar(deviation = 0.1, max_count = 10) {
44+
return (items, field) => {
1045
if (items.length < max_count) return false
1146
const values = items.map((item) => item.values[field])
1247
const points = values.map((v) => values.indexOf(v))
1348
return calcDeviation(points) < deviation
14-
? `Too similar values for ${field}`
49+
? MESSAGES.tooSimilar({ items, field })
1550
: false
16-
},
17-
tooFast: (minutes = 10, times = 20) => (items) => {
51+
};
52+
}
53+
function tooFast(minutes = 10, times = 20) {
54+
return (items) => {
1855
if (items.length < times) return false
1956
const last = items.at(-1)
2057
const first = items.at(-times)
2158
return last.created_at - first.created_at < minutes * 60
22-
? `Too fast annotations`
59+
? MESSAGES.tooFast({ items })
2360
: false
24-
}
61+
};
2562
}
2663

27-
/****** RULES FOR SUBMITTED ANNOTATIONS ******/
28-
const RULES = {
29-
fields: {
30-
comment: [rules.timesInARow(3)],
31-
sentiment: [rules.tooSimilar()],
32-
},
33-
global: [rules.tooFast()],
34-
}
3564

65+
66+
/****** INTERNAL CODE ******/
3667
const project = DM.project.id
3768
if (!DM.project) return;
3869

@@ -43,6 +74,7 @@ const values = Object.fromEntries(fields.map(
4374
(field) => [field, DM.project.parsed_label_config[field]?.labels],
4475
))
4576

77+
// simplified version of MSE with normalized x-axis
4678
function calcDeviation(data) {
4779
const n = data.length;
4880
// we normalize indices from -n/2 to n/2 so meanX is 0
@@ -72,9 +104,10 @@ LSI.on("submitAnnotation", (_store, ann) => {
72104
stats.push({ values, created_at: Date.now() / 1000 })
73105

74106
for (const rule of RULES.global) {
75-
if (rule(stats)) {
107+
const result = rule(stats)
108+
if (result) {
76109
localStorage.setItem(key, "[]");
77-
pause("Wow, cowboy, not so fast!");
110+
pause(result);
78111
return;
79112
}
80113
}

0 commit comments

Comments
 (0)