-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathJavaScript.html
More file actions
200 lines (175 loc) · 5.04 KB
/
JavaScript.html
File metadata and controls
200 lines (175 loc) · 5.04 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
<script>
//loaded from server on page load
var data = {
'randomizer_choices':{},
'names_corpora':{}
};
//event handlers
function onload(e) {
setButtonsDisabled(true);
displayWarning('Please wait - loading data');
google.script.run.withSuccessHandler(onloadSuccess).withFailureHandler(onloadFailure).getData();
}
function handleClick(endpoint) {
clearWarning();
displayHeader(endpoint);
displayOutput('Generating...');
handleRandomize(endpoint).then(onRandomizeSuccess, onRandomizeFailure);
}
function refresh(e) {
google.script.run.showSidebar();
}
function onloadSuccess(result) {
setButtonsDisabled(false);
clearWarning();
displayOutput('');
data = result;
}
function onloadFailure(error) {
displayWarning('Failed to load data - please try again');
displayOutput('');
}
function handleRandomize(endpoint) {
return new Promise((resolve, reject) => {
try {
data['user_vars'] = {}; //reset user-defined variables
var input = data['randomizer_choices'][endpoint][0]; //each endpoint is an array of length one
if (input.toString().trim().length == 0) throw ('Endpoint "' + endpoint + '" is empty');
var output = randomize(input);
resolve(output);
} catch(e) {
reject(e);
}
});
}
function onRandomizeSuccess(output) {
displayOutput(output);
}
function onRandomizeFailure(error) {
displayWarning('ERROR: ' + error);
displayOutput('');
}
function randomize(input) {
//search for curly-bracketed syntax, strip brackets and parse inner text
var output = input.replace(/{([^{]+)}/g, function(match, p1, offset, string) {
try {
return parse(p1);
} catch (e) {
displayWarning('ERROR: ' + e);
return match;
}
});
//repeat until no change
if (input == output) {
return output;
} else {
return randomize(output);
}
}
function parse(input) {
/*
determine format of input (outer brackets have been stripped)
{key}
{[list|of|some options]}
{#0-100}
{@varname:key}
{@varname:[list|of|some options]}
{@varname:#0-100}
{@varname}
*/
var match;
//match @varname:statement
match = input.match(/^@(\w+):(\w+)$/);
if (match) {
var varname = match[1];
var value = parse(match[2]);
data['user_vars'][varname] = value;
return value;
}
//match @varname
match = input.match(/^@(\w+)$/);
if (match) {
var varname = match[1];
if (data['user_vars'].hasOwnProperty(varname)) {
return data['user_vars'][varname];
} else {
throw ('the variable "@' + varname + '" is undefined');
}
}
//match [list|of|some options]
match = input.match(/^\[([\W\w]+)]$/);
if (match) {
var choices = match[1].split('|');
return choices[Math.floor(Math.random() * choices.length)];
}
//match #0-100
match = input.match(/^#(\d+)-(\d+)$/);
if (match) {
var min = parseInt(match[1]);
var max = parseInt(match[2]);
return (Math.floor(Math.random() * (max - min + 1) ) + min).toString(); //result is inclusive
}
//match label
match = input.match(/^(\w+)$/);
if (match) {
var key = match[1];
if (data['randomizer_choices'].hasOwnProperty(key)) {
//get random choice
var choices = data['randomizer_choices'][key];
if (choices.length == 0) throw ('the label "' + key + '" does not define any options');
return choices[Math.floor(Math.random() * choices.length)];
} else if (data['names_corpora'].hasOwnProperty(key)) {
//generate name
var corpus = data['names_corpora'][key];
var name;
do {
name = generateName(corpus);
} while(!name.match(/[aeiouy]+/)); //ensure name contains at least one vowel
name = capitalize(name);
return name;
} else {
throw ('the label "' + key + '" is undefined');
}
}
//no match
throw ('invalid syntax: "' + input + '"');
}
function generateName(corpus) {
//choose random starting characters
var name = corpus['<s>'][Math.floor(Math.random() * corpus['<s>'].length)];
var keyLength = name.length;
//choose next character at random until sentinel symbol encountered
while (true) {
var nextKey = name.substring(name.length - keyLength);
var next = corpus[nextKey][Math.floor(Math.random() * corpus[nextKey].length)];
if (next != '</s>') name += next;
else break;
}
return name;
}
function capitalize(str) {
return str.replace(/(\w)([\w]*)/g, function(match, p1, p2, offset, string) {
return p1.toUpperCase() + p2;
});
}
function displayHeader(header) {
document.getElementById('header').innerHTML = header;
}
function displayOutput(output) {
document.getElementById('output').innerHTML = output;
}
function displayWarning(msg) {
if (!document.getElementById('warning').innerHTML.includes(msg)) {
document.getElementById('warning').innerHTML += msg + "\n";
}
}
function clearWarning() {
document.getElementById('warning').innerHTML = '';
}
function setButtonsDisabled(bool) {
var buttons = document.getElementsByClassName('endpoint');
for (var i = 0; i < buttons.length; i++) {
buttons[i].disabled = bool;
}
}
</script>