air18n 0.1.40 → 0.1.41

Sign up to get free protection for your applications and to get access to all the features.
@@ -337,10 +337,10 @@ module Air18n
337
337
  end
338
338
 
339
339
  def self.translator_activity_data_v3 user_id=0, opts={}
340
- activity_from_translation_pairs(get_translation_pairs(user_id, opts[:since], opts[:to]), opts)
340
+ aggregate_v3_translation_activity(compute_v3_translation_activity(user_id, opts[:since], opts[:to]), opts)
341
341
  end
342
342
 
343
- def self.activity_from_translation_pairs(translation_pairs, opts={})
343
+ def self.aggregate_v3_translation_activity(translation_pairs, opts={})
344
344
  per_user_locale_month_year =
345
345
  Hash.new {|h, year| h[year] =
346
346
  Hash.new {|h, month| h[month] =
@@ -356,16 +356,15 @@ module Air18n
356
356
  } } } } } }
357
357
 
358
358
  translation_pairs.each do |pair|
359
- words_translated, words_verified = self.word_counts_from_translation_pair(pair)
360
359
  sums = per_user_locale_month_year[
361
360
  pair[:datetime].year][
362
361
  pair[:datetime].month][
363
362
  pair[:user_id]][
364
363
  pair[:locale]][
365
364
  pair[:datetime].day]
366
- sums[:words_translated] += words_translated
367
- sums[:words_verified] += words_verified
368
- if words_verified > 0
365
+ sums[:words_translated] += pair[:words_translated]
366
+ sums[:words_verified] += pair[:words_verified]
367
+ if pair[:words_verified] > 0
369
368
  sums[:keys_verified] << pair[:phrase_key]
370
369
  sums[:phrases_verified] += 1
371
370
  else
@@ -397,9 +396,6 @@ module Air18n
397
396
  :verified_keys => sums[:keys_verified],
398
397
  }
399
398
  }
400
- LoggingHelper.info("keys translated: #{sums[:keys_translated]}")
401
- LoggingHelper.info("keys verified: #{sums[:keys_verified]}")
402
- LoggingHelper.info("ret now: #{ret.inspect}")
403
399
  end
404
400
  else
405
401
  monthly_sums = {
@@ -429,9 +425,6 @@ module Air18n
429
425
  :verified_keys => monthly_sums[:keys_verified],
430
426
  }
431
427
  }
432
- LoggingHelper.info("keys translated: #{monthly_sums[:keys_translated]}")
433
- LoggingHelper.info("keys verified: #{monthly_sums[:keys_verified]}")
434
- LoggingHelper.info("ret now: #{ret.inspect}")
435
428
  end
436
429
  end
437
430
  end
@@ -485,7 +478,7 @@ module Air18n
485
478
  (translation_pair[:source_word_count] * proportion_verified).floor]
486
479
  end
487
480
 
488
- def self.get_translation_pairs(user_id, from_date, to_date)
481
+ def self.compute_v3_translation_activity(user_id, from_date, to_date)
489
482
  ret = []
490
483
  Phrase.select(:id).find_in_batches do |batch|
491
484
  pt_scope = PhraseTranslation.where(:phrase_id => batch)
@@ -502,32 +495,68 @@ module Air18n
502
495
  phrase_to_phrase_translations.each do |(locale, phrase_id), phrase_translations|
503
496
  phrase_translations.sort_by! { |pt| pt.created_at }
504
497
 
505
- previous_translation = PhraseTranslation.where("created_at < ?", phrase_translations.first.created_at - 1.second).
506
- where(:locale => locale).
507
- where(:phrase_id => phrase_id).
508
- order("created_at DESC").
509
- first
498
+ previous_translation = :uncomputed
499
+
510
500
  phrase_translations.each do |pt|
511
- if previous_translation
512
- previous_translation_text = previous_translation.value
513
- previous_translation_user_id = previous_translation.user_id
514
- was_stale = previous_translation.source_hash != pt.source_hash
501
+ translation_pair = {
502
+ :translation => pt.value,
503
+ :locale => pt.locale,
504
+ :user_id => pt.user_id,
505
+ :datetime => pt.created_at,
506
+ :source_word_count => pt.source_word_count,
507
+ :phrase_key => pt.key,
508
+ }
509
+
510
+ if pt.payment_details.present?
511
+ payment_details = JSON.parse(pt.payment_details)
515
512
  else
516
- previous_translation_text = ''
517
- previous_translation_user_id = 0
518
- was_stale = false
513
+ payment_details = {}
519
514
  end
520
- translation_text = pt.value
521
- ret << { :translation => translation_text,
522
- :previous_translation => previous_translation_text,
523
- :was_stale => was_stale,
524
- :locale => pt.locale,
525
- :user_id => pt.user_id,
526
- :previous_user_id => previous_translation_user_id,
527
- :datetime => pt.created_at,
528
- :source_word_count => pt.source_word_count,
529
- :phrase_key => pt.key,
530
- }
515
+
516
+ if !payment_details.include?('v3')
517
+ # If we haven't computed v3 payment details already, compute them
518
+ # and then save details to the PhraseTranslation itself.
519
+
520
+ if previous_translation == :uncomputed
521
+ previous_translation = PhraseTranslation.
522
+ where("created_at < ?", phrase_translations.first.created_at - 1.second).
523
+ where(:locale => locale).
524
+ where(:phrase_id => phrase_id).
525
+ order("created_at DESC").
526
+ first
527
+ end
528
+
529
+ if previous_translation
530
+ previous_translation_text = previous_translation.value
531
+ previous_translation_user_id = previous_translation.user_id
532
+ was_stale = previous_translation.source_hash != pt.source_hash
533
+ else
534
+ previous_translation_text = ''
535
+ previous_translation_user_id = 0
536
+ was_stale = false
537
+ end
538
+
539
+ words_translated, words_verified = self.word_counts_from_translation_pair(
540
+ translation_pair.merge(
541
+ :previous_translation => previous_translation_text,
542
+ :was_stale => was_stale,
543
+ :previous_user_id => previous_translation_user_id,
544
+ ))
545
+
546
+ payment_details['v3'] = {
547
+ 't' => words_translated,
548
+ 'v' => words_verified
549
+ }
550
+
551
+ pt.payment_details = payment_details.to_json
552
+ LoggingHelper.info "saving payment details: "
553
+ pt.save
554
+ end
555
+
556
+ translation_pair[:words_translated] = payment_details['v3']['t']
557
+ translation_pair[:words_verified] = payment_details['v3']['v']
558
+
559
+ ret << translation_pair
531
560
 
532
561
  previous_translation = pt
533
562
  end
@@ -1,3 +1,3 @@
1
1
  module Air18n
2
- VERSION = "0.1.40"
2
+ VERSION = "0.1.41"
3
3
  end
@@ -40,6 +40,7 @@ class Air18nMigration < ActiveRecord::Migration
40
40
  t.boolean "is_latest", :default => false
41
41
  t.integer "source_word_count", :default => 0
42
42
  t.string "source_hash"
43
+ t.text "payment_details"
43
44
  end
44
45
 
45
46
  add_index "phrase_translations", ["locale", "is_latest", "is_stale", "is_verification"], :name => "index_phrase_translations_on_locale_and_flags"
@@ -374,54 +374,133 @@ describe Air18n::PhraseTranslation do
374
374
  ##### Phrase 1
375
375
 
376
376
  # User 1 translates Phrase 1 for the first time [edit of untranslated phrase]
377
- translation = FactoryGirl.create(:phrase_translation, :locale => :de, :value => 'urgle burgle', :phrase => @phrase1, :user_id => @user1, :created_at => Date.new(2012, 11, 1))
377
+ @translation_wih_precomputed_edits = FactoryGirl.create(
378
+ :phrase_translation,
379
+ :locale => :de,
380
+ :value => 'urgle burgle',
381
+ :phrase => @phrase1,
382
+ :user_id => @user1,
383
+ :created_at => Date.new(2012, 11, 1),
384
+ :payment_details => '{"v3":{"t":8,"v":0}}')
378
385
 
379
386
  # User 1 tweaks his own translation of Phrase 1. [edit of own unverified translation]
380
- translation_tweak = FactoryGirl.create(:phrase_translation, :locale => :de, :value => 'urgle burgle boo', :phrase => @phrase1, :user_id => @user1, :created_at => Date.new(2012, 11, 2))
387
+ FactoryGirl.create(
388
+ :phrase_translation,
389
+ :locale => :de,
390
+ :value => 'urgle burgle boo',
391
+ :phrase => @phrase1,
392
+ :user_id => @user1,
393
+ :created_at => Date.new(2012, 11, 2))
381
394
 
382
395
  # User 2 verifies translation of Phrase 1. [pure verification]
383
- verification_by_other_user = FactoryGirl.create(:phrase_translation, :locale => :de, :value => 'urgle burgle boo', :phrase => @phrase1, :user_id => @user2, :is_verification => true, :created_at => Date.new(2012, 11, 3))
396
+ FactoryGirl.create(
397
+ :phrase_translation,
398
+ :locale => :de,
399
+ :value => 'urgle burgle boo',
400
+ :phrase => @phrase1,
401
+ :user_id => @user2,
402
+ :is_verification => true,
403
+ :created_at => Date.new(2012, 11, 3))
384
404
 
385
405
  # Phrase 1 becomes stale.
386
406
  @phrase1.value = "one two three four five six seven eight nine ten eleven twelve thirteen"
387
407
  @phrase1.save!
388
408
 
389
409
  # User 1 reedits translation of Phrase 1. [edit of other's stale translation]
390
- retranslation = FactoryGirl.create(:phrase_translation, :locale => :de, :value => 'oogie boogie boo', :phrase => @phrase1, :user_id => @user1, :created_at => Date.new(2012, 11, 4))
410
+ @phrase_without_payment_details = FactoryGirl.create(
411
+ :phrase_translation,
412
+ :locale => :de,
413
+ :value => 'oogie boogie boo',
414
+ :phrase => @phrase1,
415
+ :user_id => @user1,
416
+ :created_at => Date.new(2012, 11, 4))
391
417
 
392
418
  # User 2 pure-verifies of Phrase 1.
393
- other_user_translation = FactoryGirl.create(:phrase_translation, :locale => :de, :value => 'oogie boogie boo', :is_verification => true, :phrase => @phrase1, :user_id => @user2, :created_at => Date.new(2012, 11, 5))
419
+ FactoryGirl.create(
420
+ :phrase_translation,
421
+ :locale => :de,
422
+ :value => 'oogie boogie boo',
423
+ :is_verification => true,
424
+ :phrase => @phrase1,
425
+ :user_id => @user2,
426
+ :created_at => Date.new(2012, 11, 5))
394
427
 
395
428
  # User 1 edits verified translation of Phrase 1. [edit of other's verified translation]
396
- verification = FactoryGirl.create(:phrase_translation, :locale => :de, :value => 'oogie booooogie boo hat ogl', :phrase => @phrase1, :user_id => @user1, :is_verification => true, :created_at => Date.new(2012, 11, 6))
429
+ FactoryGirl.create(:phrase_translation,
430
+ :locale => :de,
431
+ :value => 'oogie booooogie boo hat ogl',
432
+ :phrase => @phrase1,
433
+ :user_id => @user1,
434
+ :is_verification => true,
435
+ :created_at => Date.new(2012, 11, 6))
397
436
 
398
437
  ##### Phrase 2
399
438
 
400
439
  # User 1 translates Phrase 2 for the first time, but earlier in the year.
401
- translation = FactoryGirl.create(:phrase_translation, :locale => :de, :value => 'The only verdict is vengence', :phrase => @phrase2, :user_id => @user1, :created_at => Date.new(2012, 9, 1))
440
+ FactoryGirl.create(
441
+ :phrase_translation,
442
+ :locale => :de,
443
+ :value => 'The only verdict is vengence',
444
+ :phrase => @phrase2,
445
+ :user_id => @user1,
446
+ :created_at => Date.new(2012, 9, 1))
402
447
 
403
448
  # User 1 tweaks their own translation later.
404
- translation = FactoryGirl.create(:phrase_translation, :locale => :de, :value => 'The only verdict is VENGENCE', :phrase => @phrase2, :user_id => @user1, :created_at => Date.new(2012, 11, 1))
449
+ FactoryGirl.create(
450
+ :phrase_translation,
451
+ :locale => :de,
452
+ :value => 'The only verdict is VENGENCE',
453
+ :phrase => @phrase2,
454
+ :user_id => @user1,
455
+ :created_at => Date.new(2012, 11, 1))
405
456
 
406
457
  # User 2 tweaks translation of Phrase 2.
407
- translation = FactoryGirl.create(:phrase_translation, :locale => :de, :value => 'a vendetta, held as a votive', :is_verification => true, :phrase => @phrase2, :user_id => @user2, :created_at => Date.new(2012, 11, 2))
458
+ FactoryGirl.create(
459
+ :phrase_translation,
460
+ :locale => :de,
461
+ :value => 'a vendetta, held as a votive',
462
+ :is_verification => true,
463
+ :phrase => @phrase2,
464
+ :user_id => @user2,
465
+ :created_at => Date.new(2012, 11, 2))
408
466
 
409
467
  # User 2 tweaks their own translation of Phrase 2. [edit of own verified translation]
410
- translation = FactoryGirl.create(:phrase_translation, :locale => :de, :value => 'a vendetta, held as a votive, not in vain', :is_verification => true, :phrase => @phrase2, :user_id => @user2, :created_at => Date.new(2012, 11, 3))
468
+ FactoryGirl.create(
469
+ :phrase_translation,
470
+ :locale => :de,
471
+ :value => 'a vendetta, held as a votive, not in vain',
472
+ :is_verification => true,
473
+ :phrase => @phrase2,
474
+ :user_id => @user2,
475
+ :created_at => Date.new(2012, 11, 3))
411
476
 
412
477
  # Phrase 2 becomes stale.
413
478
  @phrase2.value = "one two three four five six seven eight nine"
414
479
  @phrase2.save!
415
480
 
416
481
  # User 2 verifies existing translation of Phrase 2. [pure verification of own stale translation]
417
- translation = FactoryGirl.create(:phrase_translation, :locale => :de, :value => 'a vendetta, held as a votive, not in vain', :is_verification => true, :phrase => @phrase2, :user_id => @user2, :created_at => Date.new(2012, 11, 4))
482
+ FactoryGirl.create(
483
+ :phrase_translation,
484
+ :locale => :de,
485
+ :value => 'a vendetta, held as a votive, not in vain',
486
+ :is_verification => true,
487
+ :phrase => @phrase2,
488
+ :user_id => @user2,
489
+ :created_at => Date.new(2012, 11, 4))
418
490
 
419
491
  # Phrase 2 becomes stale again.
420
492
  @phrase2.value = "one two three"
421
493
  @phrase2.save!
422
494
 
423
495
  # User 2 tweaks translation of Phrase 2. [pure verification of own stale translation]
424
- translation = FactoryGirl.create(:phrase_translation, :locale => :de, :value => 'a vendetta, held as a votive, not in vain, for the value and veracity of such shall one day vindicate the vigilant and the virtuous', :is_verification => true, :phrase => @phrase2, :user_id => @user2, :created_at => Date.new(2012, 11, 5))
496
+ FactoryGirl.create(
497
+ :phrase_translation,
498
+ :locale => :de,
499
+ :value => 'a vendetta, held as a votive, not in vain, for the value and veracity of such shall one day vindicate the vigilant and the virtuous',
500
+ :is_verification => true,
501
+ :phrase => @phrase2,
502
+ :user_id => @user2,
503
+ :created_at => Date.new(2012, 11, 5))
425
504
  end
426
505
 
427
506
  @golden_pairs =
@@ -433,6 +512,8 @@ describe Air18n::PhraseTranslation do
433
512
  :previous_user_id=>0,
434
513
  :datetime=>Date.new(2012, 11, 01),
435
514
  :source_word_count=>8,
515
+ :words_translated=>8, # "" -> "urgle burgle", user 5
516
+ :words_verified=>0,
436
517
  :phrase_key=>'v3 regime payments key 1'},
437
518
  {:translation=>"urgle burgle boo",
438
519
  :previous_translation=>"urgle burgle",
@@ -442,6 +523,8 @@ describe Air18n::PhraseTranslation do
442
523
  :previous_user_id=>5,
443
524
  :datetime=>Date.new(2012, 11, 02),
444
525
  :source_word_count=>8,
526
+ :words_translated=>0, # same translator making an edit, user 5
527
+ :words_verified=>0,
445
528
  :phrase_key=>'v3 regime payments key 1'},
446
529
  {:translation=>"urgle burgle boo",
447
530
  :previous_translation=>"urgle burgle boo",
@@ -451,6 +534,8 @@ describe Air18n::PhraseTranslation do
451
534
  :previous_user_id=>5,
452
535
  :datetime=>Date.new(2012, 11, 03),
453
536
  :source_word_count=>8,
537
+ :words_translated=>0, # different translator verifying, user 6
538
+ :words_verified=>8,
454
539
  :phrase_key=>'v3 regime payments key 1'},
455
540
  {:translation=>"oogie boogie boo",
456
541
  :previous_translation=>"urgle burgle boo",
@@ -460,6 +545,8 @@ describe Air18n::PhraseTranslation do
460
545
  :previous_user_id=>6,
461
546
  :datetime=>Date.new(2012, 11, 04),
462
547
  :source_word_count=>13,
548
+ :words_translated=>9, # edit of stale phrase; 2/3 words changed, 2/3*13=8.66; ceils to 9, user 5
549
+ :words_verified=>4,
463
550
  :phrase_key=>'v3 regime payments key 1'},
464
551
  {:translation=>"oogie boogie boo",
465
552
  :previous_translation=>"oogie boogie boo",
@@ -469,6 +556,8 @@ describe Air18n::PhraseTranslation do
469
556
  :previous_user_id=>5,
470
557
  :datetime=>Date.new(2012, 11, 05),
471
558
  :source_word_count=>13,
559
+ :words_translated=>0, # verification, user 6
560
+ :words_verified=>13,
472
561
  :phrase_key=>'v3 regime payments key 1'},
473
562
  {:translation=>"oogie booooogie boo hat ogl",
474
563
  :previous_translation=>"oogie boogie boo",
@@ -478,6 +567,8 @@ describe Air18n::PhraseTranslation do
478
567
  :previous_user_id=>6,
479
568
  :datetime=>Date.new(2012, 11, 06),
480
569
  :source_word_count=>13,
570
+ :words_translated=>13, # 3 new words; 3/3 words changed, 3/3*13=13, user 5
571
+ :words_verified=>0,
481
572
  :phrase_key=>'v3 regime payments key 1'},
482
573
  {:translation=>"The only verdict is VENGENCE",
483
574
  :previous_translation=>"The only verdict is vengence",
@@ -487,6 +578,8 @@ describe Air18n::PhraseTranslation do
487
578
  :previous_user_id=>5,
488
579
  :datetime=>Date.new(2012, 11, 01),
489
580
  :source_word_count=>6,
581
+ :words_translated=>0, # Tweak of a translation that was done in past by same person, user 5
582
+ :words_verified=>0,
490
583
  :phrase_key=>'v3 regime payments key 2'},
491
584
  {:translation=>"a vendetta, held as a votive",
492
585
  :previous_translation=>"The only verdict is VENGENCE",
@@ -496,6 +589,8 @@ describe Air18n::PhraseTranslation do
496
589
  :previous_user_id=>5,
497
590
  :datetime=>Date.new(2012, 11, 02),
498
591
  :source_word_count=>6,
592
+ :words_translated=>6, # Rewrite of translation by other person, user 6
593
+ :words_verified=>0,
499
594
  :phrase_key=>'v3 regime payments key 2'},
500
595
  {:translation=>"a vendetta, held as a votive, not in vain",
501
596
  :previous_translation=>"a vendetta, held as a votive",
@@ -505,6 +600,8 @@ describe Air18n::PhraseTranslation do
505
600
  :previous_user_id=>6,
506
601
  :datetime=>Date.new(2012, 11, 03),
507
602
  :source_word_count=>6,
603
+ :words_translated=>0, # Tweak by same person, user 6
604
+ :words_verified=>0,
508
605
  :phrase_key=>'v3 regime payments key 2'},
509
606
  {:translation=>"a vendetta, held as a votive, not in vain",
510
607
  :previous_translation=>"a vendetta, held as a votive, not in vain",
@@ -514,6 +611,8 @@ describe Air18n::PhraseTranslation do
514
611
  :previous_user_id=>6,
515
612
  :datetime=>Date.new(2012, 11, 04),
516
613
  :source_word_count=>9,
614
+ :words_translated=>0, # Pure verification of stale, user 6
615
+ :words_verified=>9,
517
616
  :phrase_key=>'v3 regime payments key 2'},
518
617
  {:translation=>
519
618
  "a vendetta, held as a votive, not in vain, for the value and veracity of such shall one day vindicate the vigilant and the virtuous",
@@ -524,6 +623,8 @@ describe Air18n::PhraseTranslation do
524
623
  :previous_user_id=>6,
525
624
  :datetime=>Date.new(2012, 11, 05),
526
625
  :source_word_count=>3,
626
+ :words_translated=>3, # Edit of stale, user 6
627
+ :words_verified=>0,
527
628
  :phrase_key=>'v3 regime payments key 2'}]
528
629
 
529
630
  @golden_word_counts =
@@ -572,10 +673,16 @@ describe Air18n::PhraseTranslation do
572
673
  end
573
674
 
574
675
  it 'should be able to enumerate pairs of translations' do
575
- pairs = Air18n::PhraseTranslation.get_translation_pairs(0, Date.new(2012, 11, 1), Date.new(2012, 12, 1))
676
+ pairs = Air18n::PhraseTranslation.compute_v3_translation_activity(0, Date.new(2012, 11, 1), Date.new(2012, 12, 1))
576
677
  pairs = pairs.select { |pair| pair[:locale] == 'de' }
577
678
 
578
- pairs.should == @golden_pairs
679
+ (0...@golden_pairs.size).each do |i|
680
+ # Check that @golden_pairs[i] includes all keys/values in pairs[i].
681
+ pairs[i].should == @golden_pairs[i].slice(*pairs[i].keys)
682
+ end
683
+
684
+ # Check that it stores computed payment details in the database.
685
+ @phrase_without_payment_details.reload.payment_details.should == '{"v3":{"t":9,"v":4}}'
579
686
  end
580
687
 
581
688
  it 'should be able to count words proportional to amount of translation edited' do
@@ -682,13 +789,13 @@ describe Air18n::PhraseTranslation do
682
789
  end
683
790
 
684
791
  it 'should compute correct monthly activities' do
685
- data = Air18n::PhraseTranslation.activity_from_translation_pairs(@golden_pairs, :daily => false)
792
+ data = Air18n::PhraseTranslation.aggregate_v3_translation_activity(@golden_pairs, :daily => false)
686
793
 
687
794
  data.should == @golden_monthly_activity
688
795
  end
689
796
 
690
797
  it 'should compute correct daily activities' do
691
- data = Air18n::PhraseTranslation.activity_from_translation_pairs(@golden_pairs, :daily => true)
798
+ data = Air18n::PhraseTranslation.aggregate_v3_translation_activity(@golden_pairs, :daily => true)
692
799
 
693
800
  data.first.should ==
694
801
  {:year=>2012,
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: air18n
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.40
4
+ version: 0.1.41
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -13,7 +13,7 @@ authors:
13
13
  autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
- date: 2012-11-27 00:00:00.000000000 Z
16
+ date: 2012-11-28 00:00:00.000000000 Z
17
17
  dependencies:
18
18
  - !ruby/object:Gem::Dependency
19
19
  name: i18n