ajax-cat 1.0.0 → 2.0.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.
@@ -44,3 +44,19 @@ class Utils
44
44
 
45
45
  @trim: (text) =>
46
46
  return text.replace(/^\s+|\s+$/g, "")
47
+
48
+ @edit_distance: (source, target) ->
49
+ a = []
50
+ for i in [0..source.length]
51
+ a[i] = new Array(target.length + 1)
52
+ a[i][0] = i
53
+ a[0] = [0..target.length]
54
+
55
+ for i in [1..source.length]
56
+ for j in [1..target.length]
57
+ substitute_cost = a[i - 1][j - 1]
58
+ substitute_cost += 1 if (source.charAt(i - 1) != target.charAt(j - 1))
59
+ a[i][j] = Math.min(substitute_cost, a[i-1][j] + 1, a[i][j-1] + 1)
60
+ return a[source.length][target.length]
61
+
62
+
@@ -40,6 +40,7 @@ AjaxCatList = (function() {
40
40
  alert("Write your email, please.");
41
41
  return;
42
42
  }
43
+ $.cookie("email", email);
43
44
  return $.ajax("/admin/get_experiment", {
44
45
  data: {
45
46
  email: email,
@@ -48,7 +49,7 @@ AjaxCatList = (function() {
48
49
  success: function(data) {
49
50
  var id;
50
51
  data = JSON.parse(data);
51
- id = _this.add_translation(data.sentence, "EXPERIMENT #" + data.task_id + ", " + data.email, data.pair, data.task_id, data.email);
52
+ id = _this.add_translation(JSON.parse(data.sentences), "EXPERIMENT #" + data.task_id + ", " + data.email, data.pair, data.task_id, data.email, data);
52
53
  return window.location = "/translation.html#" + id;
53
54
  },
54
55
  error: function() {
@@ -60,6 +61,7 @@ AjaxCatList = (function() {
60
61
  AjaxCatList.prototype.new_experiment_translation = function() {
61
62
  var _this = this;
62
63
  $("#new-experiment-pair").html("");
64
+ $("#new-experiment-email").val($.cookie("email"));
63
65
  return $.ajax("/api/info", {
64
66
  success: function(data) {
65
67
  var p, _i, _len, _ref;
@@ -138,7 +140,7 @@ AjaxCatList = (function() {
138
140
  return this.show_translations();
139
141
  };
140
142
 
141
- AjaxCatList.prototype.add_translation = function(text, name, pair, task_id, email) {
143
+ AjaxCatList.prototype.add_translation = function(text, name, pair, task_id, email, experiment_data) {
142
144
  var doc, docs;
143
145
  if (task_id == null) task_id = false;
144
146
  if (email == null) email = false;
@@ -153,7 +155,12 @@ AjaxCatList = (function() {
153
155
  doc.pair = pair;
154
156
  doc.email = email;
155
157
  doc.task_id = task_id;
156
- doc.source = Utils.split_source(text);
158
+ if (jQuery.isArray(text)) {
159
+ doc.source = text;
160
+ doc.options = JSON.parse(experiment_data.options);
161
+ } else {
162
+ doc.source = Utils.split_source(text);
163
+ }
157
164
  doc.target = new Array(doc.source.length);
158
165
  docs.push(doc.id);
159
166
  localStorage.setItem('ac-data', JSON.stringify(docs));
@@ -169,6 +176,10 @@ AjaxCatTranslation = (function() {
169
176
 
170
177
  AjaxCatTranslation.prototype.cur_position = false;
171
178
 
179
+ AjaxCatTranslation.prototype.experiment = false;
180
+
181
+ AjaxCatTranslation.prototype.param_suggestion = true;
182
+
172
183
  function AjaxCatTranslation() {
173
184
  this.add_words = __bind(this.add_words, this);
174
185
  this.change_position = __bind(this.change_position, this);
@@ -179,6 +190,7 @@ AjaxCatTranslation = (function() {
179
190
  this.resize = __bind(this.resize, this);
180
191
  this.log = __bind(this.log, this);
181
192
  this.prepare_test = __bind(this.prepare_test, this);
193
+ this.change_experiment_sentence = __bind(this.change_experiment_sentence, this);
182
194
  this.time = __bind(this.time, this);
183
195
  var data, i, s, t, _i, _j, _len, _len2, _ref, _ref2,
184
196
  _this = this;
@@ -235,16 +247,16 @@ AjaxCatTranslation = (function() {
235
247
  return setTimeout(this.time, 10);
236
248
  };
237
249
 
238
- AjaxCatTranslation.prototype.prepare_test = function() {
250
+ AjaxCatTranslation.prototype.change_experiment_sentence = function() {
239
251
  var _this = this;
240
- AjaxCatList.delete_document(this.hash);
241
- $("#save").hide();
242
- $("#send-experiment").show();
243
- $("#send-experiment").click(function() {
252
+ if (this.cur_position + 1 < this.doc.source.length) {
253
+ return this.change_position(this.cur_position + 1);
254
+ } else {
244
255
  $("#send-experiment").hide();
245
256
  return $.ajax("/admin/save_experiment", {
246
257
  data: {
247
- log: JSON.stringify(_this.doc)
258
+ "log_id": this.doc.task_id,
259
+ log: JSON.stringify(this.doc)
248
260
  },
249
261
  type: "post",
250
262
  success: function() {
@@ -255,6 +267,20 @@ AjaxCatTranslation = (function() {
255
267
  return alert("Could not save experiment.");
256
268
  }
257
269
  });
270
+ }
271
+ };
272
+
273
+ AjaxCatTranslation.prototype.prepare_test = function() {
274
+ var _this = this;
275
+ AjaxCatList.delete_document(this.hash);
276
+ this.experiment = true;
277
+ $("#save").hide();
278
+ $("#experiment-settings").show();
279
+ $("#top-translations").hide();
280
+ $("#bottom-translations").hide();
281
+ $("#send-experiment").show();
282
+ $("#send-experiment").click(function() {
283
+ return _this.change_experiment_sentence();
258
284
  });
259
285
  this.doc.log = [];
260
286
  this.time();
@@ -273,7 +299,10 @@ AjaxCatTranslation = (function() {
273
299
  };
274
300
  if (type) new_log.type = type;
275
301
  if (param) new_log.param = param;
276
- this.doc.log.push(new_log);
302
+ if (this.doc.log[this.cur_position] === void 0) {
303
+ this.doc.log[this.cur_position] = [];
304
+ }
305
+ this.doc.log[this.cur_position].push(new_log);
277
306
  return $("#log").append(JSON.stringify(new_log) + "<br>");
278
307
  };
279
308
 
@@ -357,6 +386,7 @@ AjaxCatTranslation = (function() {
357
386
 
358
387
  AjaxCatTranslation.prototype.load_translation_table = function(sentence) {
359
388
  var _this = this;
389
+ if (this.table_request) this.table_request.abort();
360
390
  sentence = Utils.tokenize(sentence);
361
391
  if (sentence.match(/^[\ \t]*$/)) {
362
392
  $("#translation-table-container").html("");
@@ -364,7 +394,7 @@ AjaxCatTranslation = (function() {
364
394
  return;
365
395
  }
366
396
  $("#translation-table-container").text("");
367
- return $.ajax("/api/table", {
397
+ return this.table_request = $.ajax("/api/table", {
368
398
  data: {
369
399
  pair: this.pair,
370
400
  q: sentence
@@ -379,6 +409,18 @@ AjaxCatTranslation = (function() {
379
409
  };
380
410
 
381
411
  AjaxCatTranslation.prototype.change_position = function(position) {
412
+ if (this.experiment) {
413
+ if (!((position === 0 && this.cur_position === false) || (this.cur_position + 1 === position))) {
414
+ return;
415
+ }
416
+ this.param_suggestion = this.doc.options[position].suggestion;
417
+ $("#suggestion-panel-is-on").text(this.param_suggestion);
418
+ $("#translated-status").text("translating sentence " + (position + 1) + " out of " + this.doc.source.length);
419
+ if ((position + 1) === this.doc.source.length) {
420
+ $("#send-experiment").text("Finish experiment");
421
+ }
422
+ }
423
+ this.suggestions.clear();
382
424
  if (this.cur_position !== false) this.save_target();
383
425
  $("#source-top").children().slice(0, position).show();
384
426
  $("#source-top").children().slice(position, this.length).hide();
@@ -453,6 +495,7 @@ Suggestions = (function() {
453
495
  }
454
496
 
455
497
  Suggestions.prototype.clear = function() {
498
+ if (this.suggestion_request) this.suggestion_request.abort();
456
499
  $(".ac-suggestion").text("");
457
500
  $(".ac-suggestion").removeClass('suggestion-enabled');
458
501
  return $(".ac-suggestion").removeClass('suggestion-active');
@@ -462,11 +505,12 @@ Suggestions = (function() {
462
505
  var covered, sentence, translated,
463
506
  _this = this;
464
507
  this.clear();
508
+ if (!this.translation.param_suggestion) return;
465
509
  sentence = $("#source-sentence").text();
466
510
  sentence = Utils.tokenize(sentence);
467
511
  translated = Utils.tokenize($("#source-target").text());
468
512
  covered = this.translation.table.covered_vector();
469
- return $.ajax("/api/suggestion", {
513
+ return this.suggestion_request = $.ajax("/api/suggestion", {
470
514
  data: {
471
515
  pair: this.translation.pair,
472
516
  q: Utils.tokenize(sentence),
@@ -482,11 +526,13 @@ Suggestions = (function() {
482
526
  };
483
527
 
484
528
  Suggestions.prototype.take_suggestion = function() {
485
- var text;
529
+ var from, text, to;
486
530
  if (this.get_position() === false) return;
487
531
  text = $(".suggestion-active span").text();
532
+ from = $(".suggestion-active").data('from');
533
+ to = $(".suggestion-active").data('to');
488
534
  this.translation.add_words(text);
489
- return this.translation.table.mark_words(text);
535
+ return this.translation.table.mark_interval(from, to);
490
536
  };
491
537
 
492
538
  Suggestions.prototype.process_suggestions = function(data) {
@@ -498,7 +544,9 @@ Suggestions = (function() {
498
544
  suggestion = _ref[_i];
499
545
  translation = $("#target-sentence").val();
500
546
  el = $(".ac-suggestion").slice(i, i + 1);
501
- el.html("" + translation + " <span>" + suggestion + "</span>");
547
+ el.html("" + translation + " <span>" + suggestion.text + "</span>");
548
+ el.data('from', suggestion.from);
549
+ el.data('to', suggestion.to);
502
550
  el.addClass('suggestion-enabled');
503
551
  _results.push(i += 1);
504
552
  }
@@ -550,6 +598,7 @@ TranslationTable = (function() {
550
598
  this.unmark_position = __bind(this.unmark_position, this);
551
599
  this.mark_position = __bind(this.mark_position, this);
552
600
  this.mark_interval = __bind(this.mark_interval, this);
601
+ this.mark_words_OLD = __bind(this.mark_words_OLD, this);
553
602
  this.mark_words = __bind(this.mark_words, this);
554
603
  this.position_marked = __bind(this.position_marked, this);
555
604
  this.get_row = __bind(this.get_row, this);
@@ -643,8 +692,32 @@ TranslationTable = (function() {
643
692
  return false;
644
693
  };
645
694
 
646
- TranslationTable.prototype.mark_words = function(words) {
695
+ TranslationTable.prototype.mark_words = function(word) {
696
+ var best_element, best_result, el, element_text, maximal_acceptable_distance, result, _i, _len, _ref;
697
+ word = Utils.trim(word);
698
+ best_result = 10000;
699
+ best_element = null;
700
+ maximal_acceptable_distance = 1;
701
+ if (word.length < 5) maximal_acceptable_distance = 0;
702
+ if (word.length > 10) maximal_acceptable_distance = 2;
703
+ _ref = $(".ac-word div");
704
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
705
+ el = _ref[_i];
706
+ element_text = Utils.trim($(el).text());
707
+ result = Utils.edit_distance(word, element_text);
708
+ if (result < best_result) {
709
+ best_result = result;
710
+ best_element = $(el);
711
+ }
712
+ }
713
+ if (best_element !== null && best_result <= maximal_acceptable_distance) {
714
+ return this.mark_interval(best_element.data('position-from'), best_element.data('position-to'));
715
+ }
716
+ };
717
+
718
+ TranslationTable.prototype.mark_words_OLD = function(words) {
647
719
  var el, el_text, _i, _len, _ref;
720
+ console.log("MARKING WORDS: " + words);
648
721
  words = "" + words + " ";
649
722
  _ref = $(".ac-word div");
650
723
  for (_i = 0, _len = _ref.length; _i < _len; _i++) {
@@ -761,6 +834,28 @@ Utils = (function() {
761
834
  return text.replace(/^\s+|\s+$/g, "");
762
835
  };
763
836
 
837
+ Utils.edit_distance = function(source, target) {
838
+ var a, i, j, substitute_cost, _i, _ref, _ref2, _ref3, _ref4, _results;
839
+ a = [];
840
+ for (i = 0, _ref = source.length; 0 <= _ref ? i <= _ref : i >= _ref; 0 <= _ref ? i++ : i--) {
841
+ a[i] = new Array(target.length + 1);
842
+ a[i][0] = i;
843
+ }
844
+ a[0] = (function() {
845
+ _results = [];
846
+ for (var _i = 0, _ref2 = target.length; 0 <= _ref2 ? _i <= _ref2 : _i >= _ref2; 0 <= _ref2 ? _i++ : _i--){ _results.push(_i); }
847
+ return _results;
848
+ }).apply(this);
849
+ for (i = 1, _ref3 = source.length; 1 <= _ref3 ? i <= _ref3 : i >= _ref3; 1 <= _ref3 ? i++ : i--) {
850
+ for (j = 1, _ref4 = target.length; 1 <= _ref4 ? j <= _ref4 : j >= _ref4; 1 <= _ref4 ? j++ : j--) {
851
+ substitute_cost = a[i - 1][j - 1];
852
+ if (source.charAt(i - 1) !== target.charAt(j - 1)) substitute_cost += 1;
853
+ a[i][j] = Math.min(substitute_cost, a[i - 1][j] + 1, a[i][j - 1] + 1);
854
+ }
855
+ }
856
+ return a[source.length][target.length];
857
+ };
858
+
764
859
  return Utils;
765
860
 
766
861
  }).call(this);
@@ -0,0 +1,72 @@
1
+ /*jshint eqnull:true */
2
+ /*!
3
+ * jQuery Cookie Plugin v1.2
4
+ * https://github.com/carhartl/jquery-cookie
5
+ *
6
+ * Copyright 2011, Klaus Hartl
7
+ * Dual licensed under the MIT or GPL Version 2 licenses.
8
+ * http://www.opensource.org/licenses/mit-license.php
9
+ * http://www.opensource.org/licenses/GPL-2.0
10
+ */
11
+ (function ($, document, undefined) {
12
+
13
+ var pluses = /\+/g;
14
+
15
+ function raw(s) {
16
+ return s;
17
+ }
18
+
19
+ function decoded(s) {
20
+ return decodeURIComponent(s.replace(pluses, ' '));
21
+ }
22
+
23
+ $.cookie = function (key, value, options) {
24
+
25
+ // key and at least value given, set cookie...
26
+ if (value !== undefined && !/Object/.test(Object.prototype.toString.call(value))) {
27
+ options = $.extend({}, $.cookie.defaults, options);
28
+
29
+ if (value === null) {
30
+ options.expires = -1;
31
+ }
32
+
33
+ if (typeof options.expires === 'number') {
34
+ var days = options.expires, t = options.expires = new Date();
35
+ t.setDate(t.getDate() + days);
36
+ }
37
+
38
+ value = String(value);
39
+
40
+ return (document.cookie = [
41
+ encodeURIComponent(key), '=', options.raw ? value : encodeURIComponent(value),
42
+ options.expires ? '; expires=' + options.expires.toUTCString() : '', // use expires attribute, max-age is not supported by IE
43
+ options.path ? '; path=' + options.path : '',
44
+ options.domain ? '; domain=' + options.domain : '',
45
+ options.secure ? '; secure' : ''
46
+ ].join(''));
47
+ }
48
+
49
+ // key and possibly options given, get cookie...
50
+ options = value || $.cookie.defaults || {};
51
+ var decode = options.raw ? raw : decoded;
52
+ var cookies = document.cookie.split('; ');
53
+ for (var i = 0, parts; (parts = cookies[i] && cookies[i].split('=')); i++) {
54
+ if (decode(parts.shift()) === key) {
55
+ return decode(parts.join('='));
56
+ }
57
+ }
58
+
59
+ return null;
60
+ };
61
+
62
+ $.cookie.defaults = {};
63
+
64
+ $.removeCookie = function (key, options) {
65
+ if ($.cookie(key, options) !== null) {
66
+ $.cookie(key, null, options);
67
+ return true;
68
+ }
69
+ return false;
70
+ };
71
+
72
+ })(jQuery, document);
@@ -6,7 +6,7 @@
6
6
  <link rel="stylesheet" type="text/css" href="/bootstrap.css" />
7
7
  <link rel="stylesheet" type="text/css" href="/style.css" />
8
8
  <script src="/jquery.js"></script>
9
- <script src="/jquery.js"></script>
9
+ <script src="/cookie.js"></script>
10
10
  <script src="/bootstrap.js"></script>
11
11
  <script src="/ajax-cat.js"></script>
12
12
  <script src="/index.js"></script>
@@ -30,9 +30,6 @@
30
30
  <li><a href="#about" id="preview">Preview</a></li>
31
31
  </ul>
32
32
  <p class="pull-right">
33
- <button class="btn btn-info" id="send-experiment">
34
- Send experiment results
35
- </button>
36
33
  <button class="btn btn-info" id="save">
37
34
  Save into browser
38
35
  </button>
@@ -47,10 +44,13 @@
47
44
  <div class="container-fluid">
48
45
  <div class="row-fluid">
49
46
  <h1>Translations</h1>
50
- <span id="time"></span>
47
+ <h2><span id="translated-status"></span> <span id="time"></span></h2>
48
+ <button class="btn btn-info btn-large" id="send-experiment">
49
+ Next sentence >
50
+ </button>
51
51
 
52
52
  <table class=" table-bordered table-condensed" id="translation">
53
- <tr>
53
+ <tr id="top-translations">
54
54
  <td width="50%" id="source-top"></td>
55
55
  <td width="50%" id="target-top"></td>
56
56
  </tr>
@@ -62,7 +62,7 @@
62
62
  <div id="translation-table-container"></div>
63
63
  </td>
64
64
  </tr>
65
- <tr>
65
+ <tr id="bottom-translations">
66
66
  <td id="source-bottom"></td>
67
67
  <td id="target-bottom"></td>
68
68
  </tr>
@@ -70,7 +70,13 @@
70
70
 
71
71
  </div><!--/row-->
72
72
 
73
- <div id="log"></div>
73
+ <div id="experiment-settings" style="display: none;">
74
+ <h2>Current experiment settings</h2>
75
+ <table class="table">
76
+ <tr><th>Suggestion panel:</th><td id="suggestion-panel-is-on"></td></tr>
77
+ </table>
78
+ </div>
79
+ <div id="log" style="display: none;"></div>
74
80
 
75
81
  <hr>
76
82
 
@@ -13,6 +13,7 @@ module AjaxCat
13
13
  @translated = translated
14
14
  @translated_length = tokenize(translated).length
15
15
  @suggestions = []
16
+ @suggested_phrases = []
16
17
  end
17
18
 
18
19
  def prepare_moses_request
@@ -28,8 +29,17 @@ module AjaxCat
28
29
  def process_line(line)
29
30
  words = line.split(" ||| ")[1].strip.split(" ")
30
31
  if @suggestions.length < @@rows
31
- suggestion = words[@translated_length, @@suggestion_length].join(" ")
32
- @suggestions.push(suggestion) unless @suggestions.member?(suggestion)
32
+ alignment = line.split(" ||| ")[4].strip.split(" ").first
33
+ phrase = Phrase.new(words, alignment)
34
+ suggestion = {
35
+ "text" => phrase.words,
36
+ "from" => phrase.from,
37
+ "to" => phrase.to
38
+ }
39
+ if not @suggested_phrases.member?(suggestion['text'])
40
+ @suggested_phrases.push(suggestion['text'])
41
+ @suggestions.push(suggestion)
42
+ end
33
43
  end
34
44
  end
35
45