artaius 0.2.0

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.
@@ -0,0 +1,335 @@
1
+ module Artaius
2
+ module Plugins
3
+ # The plugins allows to create game mixes in IRC.
4
+ class Mixer
5
+ include Cinch::Plugin
6
+
7
+ # Internal: Create a new game.
8
+ #
9
+ # players - The Enumerable of players (Set or Array).
10
+ # limit - The Integer, describes the needed quantity of players, in
11
+ # order to start the game.
12
+ # time - The Time, when the game was created.
13
+ #
14
+ # Returns Game Struct object.
15
+ Game = Struct.new(:players, :limit, :time)
16
+
17
+ # Internal: Create a new gamer. Gamer is a player, which wants to play a
18
+ # mix.
19
+ #
20
+ # irc_nick - The String, representing gamer's IRC nickname.
21
+ # irc_authname - The String, representing gamer's IRC authname.
22
+ # role - The Integer, representing KAG player's role
23
+ #
24
+ # Returns Gamer object.
25
+ Gamer = Struct.new(:irc_nick, :irc_authname, :premium?, :role)
26
+
27
+ # Internal: Limit to be used, when the op didn't specify the number of
28
+ # players in the mix.
29
+ DEFAULT_LIMIT = 10
30
+
31
+ # Internal: Minimal number of slots needed to be able to play the game.
32
+ MIN_SLOTS = 2
33
+
34
+ # Internal: Delay between the beginning of game and its ending (in
35
+ # seconds).
36
+ PENDING_DELAY = 300
37
+
38
+
39
+ set react_on: :channel
40
+
41
+ match /#{I18n.mixer.m.game}(\s([2-9]|[1-9][0-9]))?$/,
42
+ method: :start_game,
43
+ use_suffix: false
44
+
45
+ # Internal: Create new game and add the creator to that game, so he/she
46
+ # will be the first player in that game.
47
+ #
48
+ # m - The recieved Message.
49
+ # limit - The Integer, which sets the limit of the players in the mix.
50
+ #
51
+ # Returns nothing.
52
+ def start_game(m, limit)
53
+ return if @game or !Player.exists?(m.user.authname)
54
+
55
+ @limit = if limit && !limit.empty?
56
+ limit.to_i
57
+ else
58
+ DEFAULT_LIMIT
59
+ end
60
+
61
+ @game = Game.new([], limit, Time.now)
62
+ @initiator = create_gamer(m)
63
+ add_player(m)
64
+ end
65
+
66
+ match /#{I18n.mixer.m.play}$/,
67
+ method: :add_player,
68
+ use_suffix: false
69
+
70
+ # Internal: Add a new player to the game.
71
+ #
72
+ # m - The recieved Message.
73
+ #
74
+ # Returns nothing.
75
+ def add_player(m)
76
+ return if !@game or !Player.exists?(m.user.authname)
77
+
78
+ unless @game.players.map(&:irc_authname).include?(m.user.authname)
79
+ @game.players << create_gamer(m)
80
+
81
+ need_players = @limit - @game.players.size
82
+
83
+ if ready_to_begin?
84
+ each_team { |blue, red| begin_game!(m, blue, red) }
85
+ else
86
+ m.reply I18n.mixer.players(show_players)
87
+ m.reply I18n.mixer.need_players(need_players)
88
+ end
89
+
90
+ end
91
+
92
+ @timer.stop if @timer
93
+
94
+ @timer = Timer(PENDING_DELAY, :shots => 1) do
95
+ @game = nil
96
+ Channel(m.channel.name).send I18n.mixer.game_cancelled
97
+ end
98
+ end
99
+
100
+ match /#{I18n.mixer.m.cancel}$/,
101
+ method: :cancel,
102
+ use_suffix: false
103
+
104
+ # Internal: Remove the user from the game. If the user is the last user in
105
+ # the game, automatically revoke that game.
106
+ #
107
+ # m - The recieved Message.
108
+ #
109
+ # Returns nothing.
110
+ def cancel(m)
111
+ player = @game.players.find { |p| p.irc_authname == m.user.authname}
112
+ @game.players.delete(player)
113
+
114
+ @initiator = @game.players[0]
115
+ m.reply I18n.mixer.cancel(m.user.nick)
116
+
117
+ unless @initiator
118
+ @timer.stop
119
+ @game = nil
120
+ m.reply I18n.mixer.last_left
121
+ else
122
+ m.reply I18n.mixer.new_initiator(@initiator.irc_nick)
123
+ m.reply show_players
124
+ end
125
+ end
126
+
127
+ match /#{I18n.mixer.m.roster}$/,
128
+ method: :roster,
129
+ use_suffix: false
130
+
131
+ # Internal: Send message about current roster in the mix, if there is any.
132
+ #
133
+ # m - The recieved Message.
134
+ #
135
+ # Returns nothing.
136
+ def roster(m)
137
+ return unless @game
138
+
139
+ m.reply I18n.mixer.roster(show_players)
140
+ end
141
+
142
+ match /#{I18n.mixer.m.start}$/,
143
+ method: :force_start,
144
+ use_suffix: false
145
+
146
+ # Internal: Start the game by all means.
147
+ #
148
+ # m - The recieved Message.
149
+ #
150
+ # Returns nothing.
151
+ def force_start(m)
152
+ return unless @game && m.user.authname == @initiator.irc_authname
153
+
154
+ each_team { |blue, red| begin_game!(m, blue, red) }
155
+ end
156
+
157
+ match /#{I18n.mixer.m.slot}(\+|-)(\s([2-9]|[1-9][0-9]))?$/,
158
+ method: :slot_dispatcher,
159
+ use_suffix: false
160
+
161
+ # Internal: Add or remove slot from the current game.
162
+ #
163
+ # m - The recieved Message.
164
+ # sign - The + or - sign, indicates adding on removing a slot
165
+ # respectively.
166
+ # slots - The Integer, reperesenting number of slots to be added or
167
+ # removed from the game.
168
+ #
169
+ def slot_dispatcher(m, sign, slots)
170
+ return unless @game && m.user.authname == @initiator.irc_authname
171
+
172
+ case sign
173
+ when '+'
174
+
175
+ if slots
176
+ slots.to_i.times { add_slot }
177
+ m.reply I18n.mixer.n_slots_added(slots, slots_message)
178
+ else
179
+ if @limit >= MIN_SLOTS
180
+ add_slot
181
+ m.reply I18n.mixer.slot_added(slots_message)
182
+ end
183
+ end
184
+
185
+ when '-'
186
+
187
+ if slots
188
+ removed_slots = 0
189
+ slots.to_i.times { |i|
190
+ remove_slot
191
+ removed_slots = i+1
192
+ break unless @limit > MIN_SLOTS
193
+ }
194
+ m.reply I18n.mixer.n_slots_removed(removed_slots, slots_message)
195
+ else
196
+ if @limit > MIN_SLOTS
197
+ remove_slot
198
+ m.reply I18n.mixer.slot_removed(slots_message)
199
+ end
200
+ end
201
+
202
+ end
203
+
204
+ if ready_to_begin?
205
+ each_team { |blue, red| begin_game!(m, blue, red) }
206
+ end
207
+ end
208
+
209
+ match /#{I18n.mixer.m.slots}$/,
210
+ method: :slots,
211
+ use_suffix: false
212
+
213
+ # Internal: Display information about slots of the current game.
214
+ #
215
+ # m - The recieved Message.
216
+ #
217
+ # Returns nothing.
218
+ def slots(m)
219
+ return unless @game
220
+
221
+ m.reply I18n.mixer.slot_stats(@game.players.size, @limit)
222
+ end
223
+
224
+ protected
225
+
226
+ # Internal: Show all players in the game. Colorize some nicks.
227
+ #
228
+ # Returns nothing.
229
+ def show_players
230
+ @game.players.map do |gamer|
231
+ colorize_nick(gamer)
232
+ end.join ', '
233
+ end
234
+
235
+ # Internal: Colorize the nick of given gamer. Based on role of the gamer.
236
+ # Golds are yellow, guards are green and normal are untouched.
237
+ #
238
+ # nick - The Gamer, which nick should be colorized.
239
+ #
240
+ # Returns colorized nick.
241
+ def colorize_nick(gamer)
242
+ if gamer[:premium?]
243
+ case gamer.role
244
+ when 2
245
+ Format(:green, gamer.irc_nick)
246
+ else
247
+ Format(:yellow, gamer.irc_nick)
248
+ end
249
+ else
250
+ gamer.irc_nick
251
+ end
252
+ end
253
+
254
+ # Internal: Iterate over each team.
255
+ #
256
+ # Yields the Array of the Red team and the Array of the Blue team
257
+ # respectively.
258
+ #
259
+ # Returns nothing.
260
+ def each_team
261
+ players = @game.players.shuffle
262
+
263
+ blue = players.pop(@limit / 2)
264
+ red = players
265
+
266
+ yield blue, red
267
+ end
268
+
269
+ # Internal: Send messages with team rosters and destroy game object.
270
+ #
271
+ # m - The recieved Message.
272
+ # blue - The Array of Blue team.
273
+ # red - The Array of Red team.
274
+ #
275
+ # Returns nil.
276
+ def begin_game!(m, blue, red)
277
+ @timer.stop
278
+
279
+ blue = blue.map { |gamer| colorize_nick(gamer) }.join(', ')
280
+ red = red.map { |gamer| colorize_nick(gamer) }.join(', ')
281
+
282
+ m.reply I18n.mixer.blue_team(blue)
283
+ m.reply I18n.mixer.red_team(red)
284
+ m.reply I18n.mixer.glhf
285
+
286
+ @game = nil
287
+ end
288
+
289
+ # Internal: Display slots used/overall number information.
290
+ #
291
+ # Returns String.
292
+ def slots_message
293
+ I18n.mixer.slots_overall(@limit)
294
+ end
295
+
296
+ # Internal: Increments game slot.
297
+ #
298
+ # Returns incremented Integer, representing limit.
299
+ def add_slot
300
+ @limit += 1
301
+ end
302
+
303
+ # Internal: Decrements game slot.
304
+ #
305
+ # Returns decremented Integer, representing limit.
306
+ def remove_slot
307
+ @limit -= 1
308
+ end
309
+
310
+ # Internal: Check if the quantity of players reached the limit. If so,
311
+ # that means, we can say "Let's get ready to rumble!".
312
+ #
313
+ # Returns true if the quantity of players, that are in game, equals to the
314
+ # slot limit or false otherwise.
315
+ def ready_to_begin?
316
+ @game.players.size == @limit
317
+ end
318
+
319
+ # Internal: Create a new gamer. Gamers are persons, that want to play mix.
320
+ #
321
+ # Returns Gamer object.
322
+ def create_gamer(m)
323
+ player = Player.filter(:irc_authname => m.user.authname).first
324
+
325
+ Gamer.new(
326
+ m.user.nick,
327
+ m.user.authname,
328
+ player[:premium],
329
+ player[:role]
330
+ )
331
+ end
332
+
333
+ end
334
+ end
335
+ end
@@ -0,0 +1,3 @@
1
+ module Artaius
2
+ VERSION = '0.2.0'
3
+ end
@@ -0,0 +1,54 @@
1
+ require_relative '../../spec_helper'
2
+
3
+ describe Artaius::Bot do
4
+ let(:bot) { Artaius::Bot.new }
5
+
6
+ describe 'bot IRC configuration' do
7
+
8
+ it 'must have correct nick' do
9
+ bot.config.nick.must_equal 'Artaius'
10
+ end
11
+
12
+ it 'must have correct realname' do
13
+ bot.config.realname.must_equal 'Artaius Lucius'
14
+ end
15
+
16
+ it 'must have correct username' do
17
+ bot.config.user.must_equal 'Artaius Lucius'
18
+ end
19
+
20
+ it 'must have correct server to join' do
21
+ bot.config.server.must_equal 'irc.quakenet.org'
22
+ end
23
+
24
+ it 'must have correct port of a server' do
25
+ bot.config.port.must_equal 6667
26
+ end
27
+
28
+ it 'must have correct channels to join' do
29
+ bot.config.channels.must_equal %w{ #kag2d.ru }
30
+ end
31
+
32
+ describe 'plugins' do
33
+
34
+ describe 'identify plugin' do
35
+ it 'must contain identify' do
36
+ bot.config.plugins.plugins.must_include Artaius::Plugins::Identify
37
+ end
38
+
39
+ it 'must have correct username option' do
40
+ bot.config.plugins
41
+ .options[Artaius::Plugins::Identify][:username].must_equal 'Artaius'
42
+ end
43
+
44
+ it 'must have password option' do
45
+ bot.config.plugins
46
+ .options[Artaius::Plugins::Identify][:password]
47
+ .must_be_instance_of String
48
+ end
49
+ end
50
+
51
+ end # plugins
52
+
53
+ end
54
+ end
@@ -0,0 +1,59 @@
1
+ require_relative '../../../spec_helper'
2
+
3
+ describe Artaius::Plugins::Archivarius do
4
+
5
+ Archivarius = Artaius::Plugins::Archivarius
6
+
7
+ it 'must include required modules' do
8
+ Archivarius.must_include Cinch::Plugin
9
+ end
10
+
11
+ it "must use correct plugin's name" do
12
+ Archivarius.plugin_name.must_equal 'archivarius'
13
+ end
14
+
15
+ it 'must react on private messages' do
16
+ Archivarius.react_on.must_equal :private
17
+ end
18
+
19
+ describe 'matchers' do
20
+ let(:reg) { Archivarius.matchers.find { |m| m.method == :sign_up } }
21
+
22
+ it 'must have correct number of matchers' do
23
+ Archivarius.matchers.size.must_equal 1
24
+ end
25
+
26
+ describe 'reg matcher' do
27
+ it 'must exist' do
28
+ reg.wont_be_nil
29
+ end
30
+
31
+ it 'must match the pattern' do
32
+ reg.pattern.must_match 'reg lol'
33
+ reg.pattern.must_match 'reg nick'
34
+ reg.pattern.must_match 'reg nickname'
35
+ reg.pattern.must_match 'reg awesomenick'
36
+ reg.pattern.must_match 'reg 10nicks'
37
+ reg.pattern.must_match 'reg nicks10'
38
+ reg.pattern.must_match 'reg ni10cks'
39
+ reg.pattern.must_match 'reg yadda_yadda'
40
+ reg.pattern.must_match 'reg IaMiDiOt'
41
+
42
+ reg.pattern.wont_match 'reg blah'
43
+ reg.pattern.wont_match 'reg me'
44
+ reg.pattern.wont_match 'reg i'
45
+ reg.pattern.wont_match 'reg averylongnicknamereally'
46
+ reg.pattern.wont_match 'reg supernick '
47
+ reg.pattern.wont_match 'reg fancy 10'
48
+ reg.pattern.wont_match 'reg ps[E]udo_player'
49
+ reg.pattern.wont_match "reg don'ttellmymother"
50
+ reg.pattern.wont_match 'reg yadda-yadda'
51
+ end
52
+
53
+ it 'does not have suffix' do
54
+ reg.suffix.must_be_nil
55
+ end
56
+ end
57
+
58
+ end
59
+ end