Project Euler Problem Translator

Provides translations in Romanian, Russian, Korean and German for Project Euler problems

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
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
/*******************************************************************************
 * Copyright (c) 2012 - 2016 Radu Murzea. All rights reserved.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 *
 *******************************************************************************/
 
 /*******************************************************************************
 * DESCRIPTION:
 * 
 * This script is intended for use only on ProjectEuler.net and it was build to be used together
 * with Firefox's GreaseMonkey extension.
 *
 * It places 5 flags (British, Romanian, Russian, Korean and German) on top of every problem's page.
 * By clicking on the flag, the corresponding translation of a problem is retrieved.
 *
 * Obviously, not at all problems are available in the above mentioned languages. In this case, clicking on the flag will do nothing.
 *
 * Notes about implementation:
 *
 * - The technique used for implementing this is **JSONP** (JSON with padding), since AJAX wouldn't work (see Same Origin Policy).
 * - The processing function (only 2 - 3 lines of code) is found in the **processtranslation.js** file. That function will be executed when the response comes back.
 * - The 5 flag images are stored inside the script in Base64 format, to avoid additional HTTP requests.
 *
 * LIMITATIONS:
 *
 * - does not work on HTTPS version of ProjectEuler (Firefox 23+), unless you disable Mixed Active Content blocker
 * - for some unknown reason, it needs at least Firefox 9+ to work.
 *
 * The translations are parsed from the corresponding translations websites:
 *
 * - http://projecteuler.radumurzea.net/ for Romanian
 * - http://euler.jakumo.org/ for Russian,
 * - http://euler.synap.co.kr/ for Korean and
 * - http://projekteuler.de for German
 *
 * You can see a demo on how the script works in the video on this page: http://projecteuler.radumurzea.net/greasemonkey.php
 * 
 * The script is also hosted here, for easier installation:
 *
 * - https://greasyfork.org/en/scripts/4899-project-euler-problem-translator
 * - https://openuserjs.org/scripts/SoboLAN/Project_Euler_Problem_Translator
 *
 *
 *******************************************************************************/
 
 /***************************************************
 *
 * Version 1.7 (24 September 2016)
 * - The domain name where the scripts and romanian translations live has been changed, so this new version updates them.
 * _______________________________
 *
 * Version 1.6 (15 June 2014)
 * - Since Firefox introduced the Mixed Active Content blocker in Firefox 23, this script will
 * only run when viewing problems in HTTP mode and it will fail in HTTPS. So it's now
 * disabled on HTTPS.
 * @see https://blog.mozilla.org/tanvi/2013/04/10/mixed-content-blocking-enabled-in-firefox-23/
 * A solution would be to buy a HTTPS certificate for my domain, but atm the costs are not justified.
 * _______________________________
 *
 * Version 1.5 (15 June 2014)
 * - Added translations in German.
 *_______________________________
 *
 * Version 1.4 (24 May 2014)
 * - Due to significant and frequent accessibility issues, support for Spanish translations is now
 * dropped.
 * _______________________________
 * 
 * Version 1.3 (18 March 2013)
 * - support for Korean added. At this date, 110 problems are translated in this language.
 * _______________________________
 *
 * Version 1.2.5 (13 January 2013)
 * - the flags will no longer appear on the page exactly after
 * you enter a (correct or incorrect) answer. This issue existed because the URL remains
 * the same.
 * - a few minor changes
 * _______________________________
 *
 * Version 1.2 (28 December 2012)
 * - translations are now offered in Russian and Spanish as well. These translations are parsed from
 * euler.jakumo.org and euleres.tk, respectively. Because of this, additional roundtrips must be made to
 * retrieve these translations, which is why it will feel slower... sometimes very slow.
 * - some small changes here and there.
 * - the backend part has been changed from "read.php" to "getjsontranslation.php". Although the old version
 * is still functional, it is highly recommended to switch to the new one (spanish and russian are accessible
 * only in the new one). Please note that the old version will be taken out of rotation on the 20th of January.
 *
 * WARNING: I have no control over how many problems are accessible in the 2 new languages and the quality
 * of these translations. Any problem regarding these 2 languages (Russian and Spanish) should be directed
 * to their authors.
 *
 * WARNING: In my tests, the Spanish version would sometimes fail for some problems and then work again
 * a few minutes later. Apparently, this issue has something to do
 * with network connection timeouts (low quality hosting ?), so this is not a bug in the script
 * itself. Please do not report this as a bug.
 * _______________________________
 *
 * Version 1.0.2 (17 December 2012)
 * - script functionality was broken by some changes in
 * the HTML code on projecteuler.net that occured on 16 December 2012. This version
 * fixes this issue.
 * _______________________________
 *
 * Version 1.0.1 (22 September 2012)
 * - added some extra safety by checking that the parsing of
 * the problem's ID did not return NaN
 * _______________________________
 *
 * Version 1.0 (18 September 2012)
 * - initial release
 *
 ****************************************************/


// ==UserScript==
// @name Project Euler Problem Translator
// @description Provides translations in Romanian, Russian, Korean and German for Project Euler problems
// @author Radu Murzea
// @version 1.7
// @icon http://projecteuler.radumurzea.net/favicon.ico
// @include http://projecteuler.net/problem=*
// @grant none
// @namespace https://greasyfork.org/users/5099
// ==/UserScript==  



function setNewTranslation(problem, lang)
{
    var script = document.createElement('script');
    
    script.setAttribute('src', 'http://projecteuler.radumurzea.net/getjsontranslation.php?problem=' + problem + '&lang=' + lang);
    
    document.getElementsByTagName('head')[0].appendChild(script); 
}

function getProblemID()
{
    var h3Nodes = document.getElementsByTagName('h3');
    
    for (var nodeIndex = 0; nodeIndex < h3Nodes.length; nodeIndex++) {
        var nodePieces = h3Nodes[nodeIndex].innerHTML.split(" ");
        
        if (nodePieces[0] === "Problem") {
            var problemID = parseInt(nodePieces[1]);
            
            return problemID;
        }
    }
    
    return -1;
}

function getROFlag()
{
    var RO = document.createElement("img");
    RO.src = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAIAAAD5gJpuAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHd" +
            "hcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAGBSURBVHjaYmTQPs7w6Q8DCDAxMLC8P2DOwcbA8I/hHxix/GD4pw3kIRBAALEwvPtT3aQIV" +
            "P7vH+O//0yc0hWsrD8ZGP78//8HRH75/T/mz//fv///AZFfNm0CCCAWBhYGhv8MT17//vvv/99/TP/+PWJg+P7//28o+vP7/+1f/3/9Aqp" +
            "mlJUF2gAQQCwgs/8zAFX/+QtCQIP///8FJn+DGP+Aqn9DNDD8/g3UABBALAx//oFV//vzhwGs4RfCeBAbRQPQdIAAYmH49Q+o7vef/zANv" +
            "5H0gBm/oE5i+PMHaANAAIE0/AUZ//8XUM9fBiQNYBLJSYxgJwEEEEjD778Mv/6A9Pz+wwB1BpoNYOOBbgAGHEAAsTD8BNL/gJqBrvr9lxF" +
            "JA8QGsIY/QA1/Gf7+BfoBIICAofQHqFRShBXkjb/MTEzSDAzfGBmB/gMa95uB5Q+D0h+QUjACOgkggBgZGLYyMPwCS4Nc+HxvMAsLw78/4" +
            "HgFkh8Y/oVD4xgCAAIMACetb51Fz+5FAAAAAElFTkSuQmCC";
    
    RO.alt = "Romania";
    RO.title = "Romanian";
    RO.style.cursor = "pointer";
    
    RO.onclick = function() {
        var problemID = getProblemID();
        
        if (! isNaN(problemID) && problemID !== -1) {
            setNewTranslation(problemID, "ro");
        }
    };

    return RO;
}

function getDEFlag()
{
    var DE = document.createElement("img");
    DE.src = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAIAAAD5gJpuAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHd" +
            "hcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAGzSURBVHjaYvTxcWb4+53h3z8GZpZff/79+v3n/7/fDAz/GHAAgABi+f37e3FxOZD1Dwz+/" +
            "v3z9y+E/AMFv3//+Qumfv9et241QACxMDExAVWfOHkJJAEW/gUEP0EQDn78+AHE/gFOQJUAAcQiy8Ag8O+fLFj1n1+/QDp+/gQioK7fP37" +
            "8+vkDqOH39x9A/RJ/gE5lAAhAYhzcAACCQBDkgRXRjP034R0IaDTZTFZn0DItot37S94KLOINerEcI7aKHAHE8v/3r/9//zIA1f36/R+o4" +
            "tevf1ANYNVA9P07RD9IJQMDQACxADHD3z8Ig4GMHz+AqqHagKp//fwLVA0U//v7LwMDQACx/LZiYFD7/5/53/+///79BqK/EMZ/UPACSYa" +
            "/v/8DyX9A0oTxx2EGgABi+a/H8F/m339BoCoQ+g8kgRaCQvgPJJiBYmAuw39hxn+uDAABxMLwi+E/0PusRkwMvxhBGoDkH4b/v/+D2EDyz" +
            "///QB1/QLb8+sP0lQEggFh+vGXYM2/SP6A2Zoaf30Ex/J+PgekHwz9gQDAz/P0FYrAyMfz7wcDAzPDtFwNAgAEAd3SIyRitX1gAAAAASUV" +
            "ORK5CYII=";
    
    DE.alt = "Germany";
    DE.title = "German";
    DE.style.cursor = "pointer";
    
    DE.onclick = function() {
        var problemID = getProblemID();
        
        if (! isNaN(problemID) && problemID !== -1) {
            setNewTranslation(problemID, "de");
        }
    };

    return DE;
}

function getKRFlag()
{
    var KR = document.createElement("img");
    KR.src = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAIAAAD5gJpuAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHd" + 
            "hcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAHDSURBVHjaYjSs/f/lBwME/Pn379cfIMnw6xfDrz9A9r/fIA4SYmMACCDGgzf/q4iBlf///" +
            "5+B4d9/KPMfCIMY/xn+//sH4f4/duMLQAAxfmRgZO/v+/fiFcNfkJkMLEz/v3wB6fn95//fPyDy9+9/f37///WbSUry+ZzZAAHEApRifPW" +
            "KiYmBOSiEUV6e8efPX6tX/9m9m+HXb4bfv0Do129GoBN//2b49YOJgQEggJj+AZ3x9y+zv/+/W7f+P7j/a8cO5qCg/2xs/379AqK/P3/9/" +
            "QVCf4Dc30DdDAABBNLA8Ocvg6gIk77+z1Wrmays/vPwMIiI/P8N0gB0z3+wTiD5/8+fPwwMAAHEBHIu0K0vXv7evIklIODP9u0M37//e/7" +
            "838+fIEU/f0JVg20AKgYIIKAfGBiBdi1ZwpaY+F9SgkVN7Wdt7f83bxjBZgOdDvEA0HgmIGJgAAggFqAt/3h4/j169K29AxRQwOD78pWBi" +
            "+s/K+s/sDpwKAFj588/QUFghAEEEMups9+1pFlAgQ0Nc0iog6MCLAQR/weSY9hx6jVAADEyx3/9+wEWkcB4BRryC4kLj+l/QDYDAx8DQIA" +
            "BAA2EWORnICKSAAAAAElFTkSuQmCC";
    
    KR.alt = "Korea";
    KR.title = "Korean";
    KR.style.cursor = "pointer";
    
    KR.onclick = function() {
        var problemID = getProblemID();
        
        if (! isNaN(problemID) && problemID !== -1) {
            setNewTranslation(problemID, "kr");
        }
    };
    
    return KR;
}

function getRUFlag()
{
    var RU = document.createElement("img");
    RU.src = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAIAAAD5gJpuAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHd" +
            "hcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAE2SURBVHjaYvz69T8DAvz79w9CQVj/0MCffwwAAcQClObiAin6/x+okxHMgPCAbOb//5n+I" +
            "4EXL74ABBALxGSwagTjPzbAyMgItAQggBg9Pf9nZPx//x7kjL9////9C2QAyf9//qCQQCQkxFhY+BEggFi2b/+nq8v46BEDSPQ3w+8//3/" +
            "/BqFfv9BJeXmQEwACCOSkP38YgHy4Bog0RN0vIOMXVOTPH6Cv/gEEEEgDxFKgHEgDXCmGDUAE1AAQQCybGZg1f/d8//XsH0jTn3+///z79" +
            "RtE/v4NZfz68xfI/vOX+4/0ZoZFAAHE4gYMvD+3/v2+h91wCANo9Z+/jH9VxBkYAAKIBRg9TL//MEhKAuWAogxgZzGC2CCfgUggAoYdGAE" +
            "VAwQQ41egu5AQAyoXTQoIAAIMAD+JZR7YOGEWAAAAAElFTkSuQmCC";
    
    RU.alt = "Russia";
    RU.title = "Russian";
    RU.style.cursor = "pointer";
    
    RU.onclick = function() {
        var problemID = getProblemID();
        
        if (! isNaN(problemID) && problemID !== -1) {
            setNewTranslation(problemID, "ru");
        }
    };
    
    return RU;
}

function getUKFlag()
{
    var UK = document.createElement("img");
    UK.src = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAIAAAD5gJpuAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJ" +
            "lYWR5ccllPAAAAflJREFUeNpinDRzn5qN3uFDt16+YWBg+Pv339+KGN0rbVP+//2rW5tf0Hfy/2+mr99+yKpyOl3Ydt8njEWIn8f9zj639" +
            "NC7j78eP//8739GVUUhNUNuhl8//ysKeZrJ/v7z10Zb2PTQTIY1XZO2Xmfad+f7XgkXxuUrVB6cjPVXef78JyMjA8PFuwyX7gAZj97+T2e" +
            "9o3d4BWNp84K1NzubTjAB3fH0+fv6N3qP/ir9bW6ozNQCijB8/8zw/TuQ7r4/ndvN5mZgkpPXiis3Pv34+ZPh5t23//79Rwehof/9/NDEg" +
            "MrOXHvJcrllgpoRN8PFOwy/fzP8+gUlgZI/f/5xcPj/69e/37//AUX+/mXRkN555gsOG2xt/5hZQMwF4r9///75++f3nz8nr75gSms82jf" +
            "vQnT6zqvXPjC8e/srJQHo9P9fvwNtAHmG4f8zZ6dDc3bIyM2LTNlsbtfM9OPHH3FhtqUz3eXX9H+cOy9ZMB2o6t/Pn0DHMPz/b+2wXGTvP" +
            "lPGFxdcD+mZyjP8+8MUE6sa7a/xo6Pykn1s4zdzIZ6///8zMGpKM2pKAB0jqy4UE7/msKat6Jw5mafrsxNtWZ6/fjvNLW29qv25pQd///n" +
            "+5+/fxDDVbcc//P/zx/36m5Ub9zL8+7t66yEROcHK7q5bldMBAgwADcRBCuVLfoEAAAAASUVORK5CYII=";
    
    UK.alt = "United Kingdom";
    UK.title = "British English";
    UK.style.cursor = "pointer";
    
    UK.onclick = function() {
        var problemID = getProblemID();
        
        if (! isNaN(problemID) && problemID !== -1) {
            setNewTranslation(problemID, "en");
        }
    };
    
    return UK;
}

function insertFlags()
{
    var UK = getUKFlag();   //UK
    var RO = getROFlag();   //Romania
    var RU = getRUFlag();   //Russia
    var KR = getKRFlag();   //Korea
    var DE = getDEFlag();   //Germany
    
    var flagsParagraph = document.createElement("p");
    
    UK.style.marginRight = "12px";
    RO.style.marginRight = "12px";
    RU.style.marginRight = "12px";
    KR.style.marginRight = "12px";
    
    flagsParagraph.appendChild(UK);
    flagsParagraph.appendChild(RO);
    flagsParagraph.appendChild(RU);
    flagsParagraph.appendChild(KR);
    flagsParagraph.appendChild(DE);
    
    flagsParagraph.style.display = "block";
    flagsParagraph.style.marginLeft = "auto";
    flagsParagraph.style.marginRight = "auto";
    flagsParagraph.style.textAlign = "center";
    
    // reference node
    var refNode = document.getElementById("content");
    
    // insert before
    refNode.parentNode.insertBefore(flagsParagraph, refNode);
}

function insertTranslationProcessing()
{
    var pscript = document.createElement('script');
    
    pscript.setAttribute('type', 'text/javascript');
    
    pscript.setAttribute('src', 'https://raw.githubusercontent.com/SoboLAN/projecteuler-translation-script/master/processtranslation.js');
    
    var bodyElement = document.getElementsByTagName('body')[0];
    
    bodyElement.insertBefore(pscript, bodyElement.firstChild);
}

var problemID = getProblemID();

if (! isNaN(problemID) && problemID !== -1) {
    insertFlags();
    
    insertTranslationProcessing();
}