barker 0.2.2

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.
Files changed (91) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +3 -0
  3. data/.ruby-gemset +1 -0
  4. data/.ruby-version +1 -0
  5. data/.simplecov +7 -0
  6. data/Gemfile +6 -0
  7. data/Gemfile.lock +50 -0
  8. data/LICENSE +22 -0
  9. data/README.md +204 -0
  10. data/Rakefile +12 -0
  11. data/barker.gemspec +29 -0
  12. data/ci/run +20 -0
  13. data/lib/barker/answer.rb +11 -0
  14. data/lib/barker/api/base.rb +145 -0
  15. data/lib/barker/api/response/base.rb +25 -0
  16. data/lib/barker/api/response/candidate.rb +38 -0
  17. data/lib/barker/api/response/candidate_answer.rb +23 -0
  18. data/lib/barker/api/response/candidate_joker.rb +21 -0
  19. data/lib/barker/api/response/candidate_question.rb +51 -0
  20. data/lib/barker/api/response/error.rb +17 -0
  21. data/lib/barker/api/response/game_show.rb +43 -0
  22. data/lib/barker/api/response/round.rb +21 -0
  23. data/lib/barker/api/response.rb +15 -0
  24. data/lib/barker/api.rb +7 -0
  25. data/lib/barker/candidate.rb +52 -0
  26. data/lib/barker/candidate_answer.rb +42 -0
  27. data/lib/barker/candidate_joker.rb +30 -0
  28. data/lib/barker/candidate_question.rb +116 -0
  29. data/lib/barker/candidate_round.rb +32 -0
  30. data/lib/barker/entity.rb +15 -0
  31. data/lib/barker/game_show.rb +176 -0
  32. data/lib/barker/guideline/base.rb +33 -0
  33. data/lib/barker/guideline/llmcquiz/questions.yaml +300 -0
  34. data/lib/barker/guideline/llmcquiz.rb +28 -0
  35. data/lib/barker/guideline/mock.rb +17 -0
  36. data/lib/barker/guideline.rb +8 -0
  37. data/lib/barker/import/yaml.rb +22 -0
  38. data/lib/barker/import.rb +6 -0
  39. data/lib/barker/joker.rb +28 -0
  40. data/lib/barker/question.rb +12 -0
  41. data/lib/barker/quiz.rb +19 -0
  42. data/lib/barker/repo/memory/game_show.rb +38 -0
  43. data/lib/barker/repo/memory.rb +8 -0
  44. data/lib/barker/repo.rb +6 -0
  45. data/lib/barker/round.rb +68 -0
  46. data/lib/barker/stage.rb +38 -0
  47. data/lib/barker/store/memory.rb +158 -0
  48. data/lib/barker/store.rb +6 -0
  49. data/lib/barker/validations.rb +14 -0
  50. data/lib/barker/version.rb +3 -0
  51. data/lib/barker.rb +45 -0
  52. data/test/factories/answer.rb +21 -0
  53. data/test/factories/candidate.rb +23 -0
  54. data/test/factories/candidate_answer.rb +12 -0
  55. data/test/factories/candidate_joker.rb +8 -0
  56. data/test/factories/candidate_question.rb +16 -0
  57. data/test/factories/candidate_round.rb +8 -0
  58. data/test/factories/game_show.rb +12 -0
  59. data/test/factories/joker.rb +5 -0
  60. data/test/factories/question.rb +13 -0
  61. data/test/factories/quiz.rb +11 -0
  62. data/test/factories/round.rb +12 -0
  63. data/test/factories/stage.rb +12 -0
  64. data/test/fixtures/questions.yaml +20 -0
  65. data/test/test_helper.rb +72 -0
  66. data/test/test_mocks.rb +21 -0
  67. data/test/unit/answer_test.rb +49 -0
  68. data/test/unit/api/base_test.rb +207 -0
  69. data/test/unit/api/response/base_test.rb +35 -0
  70. data/test/unit/api/response/candidate_answer_test.rb +64 -0
  71. data/test/unit/api/response/candidate_joker_test.rb +60 -0
  72. data/test/unit/api/response/candidate_question_test.rb +99 -0
  73. data/test/unit/api/response/candidate_test.rb +82 -0
  74. data/test/unit/api/response/game_show_test.rb +105 -0
  75. data/test/unit/api/response/round_test.rb +49 -0
  76. data/test/unit/candidate_answer_test.rb +66 -0
  77. data/test/unit/candidate_question_test.rb +277 -0
  78. data/test/unit/candidate_round_test.rb +64 -0
  79. data/test/unit/candidate_test.rb +76 -0
  80. data/test/unit/game_show_test.rb +372 -0
  81. data/test/unit/guideline/base_test.rb +34 -0
  82. data/test/unit/guideline/llmcquiz_test.rb +35 -0
  83. data/test/unit/guideline/mock_test.rb +33 -0
  84. data/test/unit/import/yaml_test.rb +41 -0
  85. data/test/unit/joker_test.rb +32 -0
  86. data/test/unit/question_test.rb +55 -0
  87. data/test/unit/quiz_test.rb +37 -0
  88. data/test/unit/repo/memory/game_show_test.rb +54 -0
  89. data/test/unit/round_test.rb +167 -0
  90. data/test/unit/stage_test.rb +53 -0
  91. metadata +283 -0
@@ -0,0 +1,158 @@
1
+ require 'thread_safe'
2
+
3
+ module Barker
4
+ module Store
5
+ class Memory
6
+ def initialize(key, options = {})
7
+ @key = key
8
+ @index = ThreadSafe::Cache.new
9
+ @build_key = options[:build_key] || false
10
+ init_index options[:init]
11
+ end
12
+
13
+ def add(item)
14
+ key = lookup_key(item)
15
+
16
+ raise DuplicateError if exist?(key)
17
+
18
+ __add(key, item)
19
+ item
20
+ end
21
+
22
+ def update(item)
23
+ key = key(item)
24
+ raise NotFoundError unless exist?(key)
25
+ @index[key] = deep_copy(item)
26
+ end
27
+
28
+ def remove(item)
29
+ key = key(item)
30
+ raise NotFoundError unless exist?(key)
31
+ @index.delete(key)
32
+ end
33
+
34
+ def filter(&block)
35
+ @index.values.select(&block)
36
+ end
37
+
38
+ def exist?(key)
39
+ @index.key?(key)
40
+ end
41
+
42
+ def get(key)
43
+ if item = __get(key)
44
+ deep_copy(item)
45
+ end
46
+ end
47
+
48
+ def select(group_by, *values)
49
+ conditions = Hash[Array(group_by).each_with_index.map do |group, i|
50
+ [group, values[i]]
51
+ end]
52
+
53
+ __all.select do |item|
54
+ conditions.each.all? do |k, v|
55
+ item.respond_to?(k) && item.public_send(k) == v
56
+ end
57
+ end
58
+ end
59
+
60
+ def all
61
+ deep_copy(__all)
62
+ end
63
+
64
+ def size
65
+ @index.size
66
+ end
67
+
68
+ def reload(item)
69
+ if item
70
+ get(key(item))
71
+ else
72
+ nil
73
+ end
74
+ end
75
+
76
+ def update_attributes(key, attributes)
77
+ if item = __get(key)
78
+ attributes.each do |attribute, value|
79
+ item.public_send("#{attribute}=", value)
80
+ end
81
+ end
82
+
83
+ get(key)
84
+ end
85
+
86
+ private
87
+
88
+ def key(item)
89
+ item.send(@key)
90
+ end
91
+
92
+ def deep_copy(object)
93
+ Marshal.load(Marshal.dump(object))
94
+ end
95
+
96
+ def __get(key)
97
+ @index[key]
98
+ end
99
+
100
+ def __add(key, item)
101
+ copy = deep_copy(item)
102
+ add_to_index key, copy
103
+ end
104
+
105
+ def __all
106
+ @index.values
107
+ end
108
+
109
+ def each_group(&block)
110
+ @group_by.each(&block)
111
+ end
112
+
113
+ def add_to_index(key, item)
114
+ @index[key] = item
115
+ end
116
+
117
+ def build_key?
118
+ @build_key
119
+ end
120
+
121
+ def lookup_key(item)
122
+ if build_key?
123
+ assign_generated_key(item)
124
+ else
125
+ key(item)
126
+ end
127
+ end
128
+
129
+ def assign_generated_key(item)
130
+ raise KeyPresetError if key(item)
131
+ key = next_key!
132
+ item.send("#{@key}=", key)
133
+ key
134
+ end
135
+
136
+ def next_key!
137
+ @current_key ||= 0
138
+ (@current_key += 1).to_s
139
+ end
140
+
141
+ def init_index(items = nil)
142
+ if items
143
+ unless build_key?
144
+ keys = Hash.new {|h,k| h[k] = 0}
145
+ items.each do |item|
146
+ keys[key(item)] += 1
147
+ end
148
+ raise DuplicateError if keys.values.any?{|v| v > 1}
149
+ end
150
+
151
+ items.each do |item|
152
+ __add(lookup_key(item), item)
153
+ end
154
+ end
155
+ end
156
+ end
157
+ end
158
+ end
@@ -0,0 +1,6 @@
1
+ require 'barker/store/memory'
2
+
3
+ module Barker
4
+ module Store
5
+ end
6
+ end
@@ -0,0 +1,14 @@
1
+ module Barker
2
+ module Validations
3
+ module NumericalityOfId
4
+ def self.included(base)
5
+ base.validate :numericality_of_id
6
+ end
7
+
8
+ def numericality_of_id
9
+ self.class.validates :id, :numericality => { :only_integer => true }
10
+ errors.add(:id, 'is not a number') if id.kind_of? String
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,3 @@
1
+ module Barker
2
+ VERSION = "0.2.2"
3
+ end
data/lib/barker.rb ADDED
@@ -0,0 +1,45 @@
1
+ module Barker
2
+ module Errors
3
+ BarkerError = Class.new(RuntimeError)
4
+
5
+ AlreadyAnsweredError = Class.new(BarkerError)
6
+ AnswerNotFoundError = Class.new(BarkerError)
7
+ JokerAlreadyUsedError = Class.new(BarkerError)
8
+ HasToRespondToIdError = Class.new(BarkerError)
9
+ HasToRespondToLocaleError = Class.new(BarkerError)
10
+ UnknownJokerError = Class.new(BarkerError)
11
+ NoCurrentStageError = Class.new(BarkerError)
12
+ NotStartedError = Class.new(BarkerError)
13
+ AlreadyStartedError = Class.new(BarkerError)
14
+ FileNotExistError = Class.new(BarkerError)
15
+ RecordNotFound = Class.new(BarkerError)
16
+ end
17
+ end
18
+
19
+ require 'forwardable'
20
+ require 'active_support/all'
21
+ require 'active_model'
22
+
23
+ require "barker/version"
24
+ require "barker/validations"
25
+
26
+ require "barker/store"
27
+ require "barker/repo"
28
+ require "barker/api"
29
+ require "barker/guideline"
30
+ require "barker/import"
31
+
32
+ require "barker/game_show"
33
+ require "barker/entity"
34
+ require "barker/answer"
35
+ require "barker/question"
36
+ require "barker/quiz"
37
+ require "barker/stage"
38
+ require "barker/round"
39
+ require "barker/joker"
40
+ require "barker/candidate"
41
+
42
+ require "barker/candidate_answer"
43
+ require "barker/candidate_question"
44
+ require "barker/candidate_round"
45
+ require "barker/candidate_joker"
@@ -0,0 +1,21 @@
1
+ FactoryGirl.define do
2
+ factory :answer, :class => Barker::Answer do
3
+ sequence(:id) { |i| i }
4
+ sequence(:label) {{ "en" => "answer", "de" => "antwort" }}
5
+ sequence(:correct) { |i| i.odd? }
6
+
7
+ trait :correct do
8
+ correct true
9
+ end
10
+
11
+ trait :wrong do
12
+ correct false
13
+ end
14
+
15
+ trait :invalid do
16
+ id "not_a_number"
17
+ end
18
+
19
+ initialize_with { new(id, label, correct) }
20
+ end
21
+ end
@@ -0,0 +1,23 @@
1
+ require 'test_mocks'
2
+
3
+ FactoryGirl.define do
4
+ factory :candidate, :class => Barker::Candidate do
5
+ sequence(:object) {|i| Mock::ValidUser.new(:id => i)}
6
+ initialize_with { new(object) }
7
+ end
8
+
9
+ factory :valid_candidate, :class => Barker::Candidate do
10
+ sequence(:object) {|i| Mock::ValidUser.new(:id => i)}
11
+ initialize_with { new(object) }
12
+ end
13
+
14
+ factory :candidate_without_id, :class => Barker::Candidate do
15
+ object { Mock::UserWithoutId.new }
16
+ initialize_with { new(object) }
17
+ end
18
+
19
+ factory :candidate_without_locale, :class => Barker::Candidate do
20
+ object { Mock::UserWithoutLocale.new }
21
+ initialize_with { new(object) }
22
+ end
23
+ end
@@ -0,0 +1,12 @@
1
+ FactoryGirl.define do
2
+ factory :candidate_answer, :class => Barker::CandidateAnswer do
3
+ candidate { FactoryGirl.build(:candidate) }
4
+ answer { FactoryGirl.build(:answer) }
5
+
6
+ trait :invalid do
7
+ answer { FactoryGirl.build(:answer, :invalid) }
8
+ end
9
+
10
+ initialize_with { new(candidate, answer) }
11
+ end
12
+ end
@@ -0,0 +1,8 @@
1
+ FactoryGirl.define do
2
+ factory :candidate_joker, :class => Barker::CandidateJoker do
3
+ candidate { FactoryGirl.build(:candidate) }
4
+ joker { FactoryGirl.build(:joker) }
5
+
6
+ initialize_with { new(candidate, joker) }
7
+ end
8
+ end
@@ -0,0 +1,16 @@
1
+ FactoryGirl.define do
2
+ factory :candidate_question, :class => Barker::CandidateQuestion do
3
+ candidate { FactoryGirl.build(:candidate) }
4
+ question { FactoryGirl.build(:question) }
5
+
6
+ trait :valid do
7
+ asked_at { Time.now }
8
+ answered_at { Time.now + 1 }
9
+ end
10
+
11
+ trait :invalid do
12
+ end
13
+
14
+ initialize_with { new(candidate, question) }
15
+ end
16
+ end
@@ -0,0 +1,8 @@
1
+ FactoryGirl.define do
2
+ factory :candidate_round, :class => Barker::CandidateRound do
3
+ round { FactoryGirl.build(:round) }
4
+ candidate { round.candidates[0] }
5
+
6
+ initialize_with { new(candidate, round) }
7
+ end
8
+ end
@@ -0,0 +1,12 @@
1
+ FactoryGirl.define do
2
+ factory :game_show, :class => Barker::GameShow do
3
+ candidates { FactoryGirl.build_list(:candidate, 2) }
4
+ quizzes { FactoryGirl.build_list(:quiz, 2) }
5
+
6
+ trait :invalid do
7
+ candidates { [] }
8
+ end
9
+
10
+ initialize_with { new(quizzes, candidates) }
11
+ end
12
+ end
@@ -0,0 +1,5 @@
1
+ FactoryGirl.define do
2
+ factory :joker, :class => Barker::Joker do
3
+ initialize_with { new("fifty_fifty") }
4
+ end
5
+ end
@@ -0,0 +1,13 @@
1
+ FactoryGirl.define do
2
+ factory :question, :class => Barker::Question do
3
+ sequence(:id) { |i| i }
4
+ label {{ "en" => "question", "de" => "frage" }}
5
+ answers { FactoryGirl.build_list(:answer, 2) }
6
+
7
+ trait :invalid do
8
+ id "not_a_number"
9
+ end
10
+
11
+ initialize_with { new(id, label, answers) }
12
+ end
13
+ end
@@ -0,0 +1,11 @@
1
+ FactoryGirl.define do
2
+ factory :quiz, :class => Barker::Quiz do
3
+ questions { FactoryGirl.build_list(:question, 2) }
4
+
5
+ trait :invalid do
6
+ questions { [FactoryGirl.build(:question),FactoryGirl.build(:question, :invalid)] }
7
+ end
8
+
9
+ initialize_with { new(questions) }
10
+ end
11
+ end
@@ -0,0 +1,12 @@
1
+ FactoryGirl.define do
2
+ factory :round, :class => Barker::Round do
3
+ question { FactoryGirl.build(:question) }
4
+ candidates { FactoryGirl.build_list(:candidate, 2) }
5
+
6
+ trait :invalid do
7
+ question { FactoryGirl.build(:question, :invalid) }
8
+ end
9
+
10
+ initialize_with { new(question, candidates) }
11
+ end
12
+ end
@@ -0,0 +1,12 @@
1
+ FactoryGirl.define do
2
+ factory :stage, :class => Barker::Stage do
3
+ quiz { FactoryGirl.build(:quiz) }
4
+ candidates { FactoryGirl.build_list(:candidate, 2) }
5
+
6
+ trait :invalid do
7
+ quiz { FactoryGirl.build(:quiz, :invalid) }
8
+ end
9
+
10
+ initialize_with { new(quiz, candidates) }
11
+ end
12
+ end
@@ -0,0 +1,20 @@
1
+ 1:
2
+ label:
3
+ de: Wann ist der SuperCode nach Kauf einlösbar?
4
+ answers:
5
+ 1:
6
+ correct: false
7
+ label:
8
+ de: 10 Minuten
9
+ 2:
10
+ correct: true
11
+ label:
12
+ de: 30 Minuten
13
+ 3:
14
+ correct: false
15
+ label:
16
+ de: 5 Minuten
17
+ 4:
18
+ correct: false
19
+ label:
20
+ de: sofort
@@ -0,0 +1,72 @@
1
+ require 'bundler/setup'
2
+ require 'simplecov' if ENV['COVERAGE']
3
+ require 'minitest/autorun'
4
+ require 'barker'
5
+ require 'factory_girl'
6
+ require 'mocha/setup'
7
+ require 'test_mocks'
8
+
9
+ class Spec < MiniTest::Spec
10
+ FactoryGirl.find_definitions
11
+
12
+ class << self
13
+ alias :context :describe
14
+ alias :test :it
15
+ end
16
+
17
+ # time
18
+ let(:time) { Time.parse('20:00') }
19
+ let(:started_at) { time }
20
+ let(:asked_at) { started_at + 2.seconds }
21
+ let(:finished_at) { started_at + 120.seconds }
22
+ let(:answered_at) { asked_at + 20.seconds }
23
+ let(:delay) { answered_at - asked_at }
24
+
25
+ # candidate
26
+ let(:candidates) { [FactoryGirl.build(:candidate)] }
27
+ let(:candidate) { candidates.first }
28
+ let(:candidate_without_id) { FactoryGirl.build(:candidate_without_id) }
29
+ let(:candidate_without_locale) { FactoryGirl.build(:candidate_without_locale) }
30
+
31
+ # answer
32
+ let(:answers) { [correct_answer, wrong_answer] }
33
+ let(:answer) { answers.first }
34
+ let(:correct_answer) { FactoryGirl.build(:answer, :correct, :id => 1) }
35
+ let(:wrong_answer) { FactoryGirl.build(:answer, :wrong, :id => 2) }
36
+ let(:candidate_answer) { Barker::CandidateAnswer.new(candidate, answer) }
37
+
38
+ # question
39
+ let(:questions) { FactoryGirl.build_list(:question, 2, :answers => answers) }
40
+ let(:question) { questions.first }
41
+ let(:candidate_question) { Barker::CandidateQuestion.new(candidate, question) }
42
+
43
+ # quiz
44
+ let(:quiz) { Barker::Quiz.new(questions) }
45
+
46
+ # quizshow
47
+ let(:quizshow) { Barker::Quizshow.create(quiz, candidates) }
48
+
49
+ def fake_ctime(file, time)
50
+ $ctime_fake_hash = {
51
+ file => time
52
+ }
53
+ File.class_eval do
54
+ class << self
55
+ alias :old_ctime :ctime
56
+
57
+ def ctime(filepath)
58
+ $ctime_fake_hash[filepath] || old_ctime(filepath)
59
+ end
60
+ end
61
+ end
62
+
63
+ yield
64
+ ensure
65
+ File.class_eval do
66
+ class << self
67
+ alias :ctime :old_ctime
68
+ end
69
+ end
70
+ end
71
+
72
+ end
@@ -0,0 +1,21 @@
1
+ module Mock
2
+ class ValidUser
3
+ attr_reader :id
4
+
5
+ def initialize(options = {})
6
+ @id = options.delete(:id) || rand(Time.now.to_i)
7
+ end
8
+
9
+ def locale
10
+ :en
11
+ end
12
+ end
13
+
14
+ class UserWithoutId < ValidUser
15
+ undef :id
16
+ end
17
+
18
+ class UserWithoutLocale < ValidUser
19
+ undef :locale
20
+ end
21
+ end
@@ -0,0 +1,49 @@
1
+ require 'test_helper'
2
+
3
+ module Barker
4
+ class AnswerTest < Spec
5
+
6
+ test "interface" do
7
+ Barker::Answer.new(1, {"en" => "label"}, true)
8
+ end
9
+
10
+ test "valid factory" do
11
+ assert FactoryGirl.build(:answer).valid?
12
+ end
13
+
14
+ test "invalid factory" do
15
+ refute FactoryGirl.build(:answer, :invalid).valid?
16
+ end
17
+
18
+ test "validate numerically of id" do
19
+ assert FactoryGirl.build(:answer, :id => 1).valid?
20
+ refute FactoryGirl.build(:answer, :id => 1.5).valid?
21
+ refute FactoryGirl.build(:answer, :id => "1").valid?
22
+ end
23
+
24
+ test "equality by id" do
25
+ assert_equal FactoryGirl.build(:answer, :id => 1), FactoryGirl.build(:answer, :id => 1)
26
+ refute_equal FactoryGirl.build(:answer, :id => 1), FactoryGirl.build(:answer, :id => 2)
27
+ end
28
+
29
+ test "id" do
30
+ assert_equal 1, FactoryGirl.build(:answer, :id => 1).id
31
+ end
32
+
33
+ test "label" do
34
+ label = { "en" => "answer", "de" => "antwort" }
35
+ assert_equal label, FactoryGirl.build(:answer, :label => label).label
36
+ end
37
+
38
+ test "correct?" do
39
+ assert correct.correct?
40
+ refute wrong.correct?
41
+ end
42
+
43
+ private
44
+
45
+ let(:correct) { FactoryGirl.build(:answer, :correct) }
46
+ let(:wrong) { FactoryGirl.build(:answer, :wrong) }
47
+
48
+ end
49
+ end