Skip to content

Commit

Permalink
Losers can record a loss or a resignation without a prior challenge. C…
Browse files Browse the repository at this point in the history
…loses #78.
  • Loading branch information
dblock committed Jan 18, 2016
1 parent f92b862 commit 1817978
Show file tree
Hide file tree
Showing 11 changed files with 384 additions and 138 deletions.
22 changes: 11 additions & 11 deletions .rubocop_todo.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# This configuration was generated by
# `rubocop --auto-gen-config`
# on 2016-01-12 08:44:10 -0500 using RuboCop version 0.34.2.
# on 2016-01-18 16:47:02 -0500 using RuboCop version 0.34.2.
# The point is for the user to remove these configuration records
# one by one as the offenses are removed from the code base.
# Note that changes in the inspected code, or installation of new
Expand Down Expand Up @@ -38,32 +38,32 @@ Lint/RescueException:
Metrics/AbcSize:
Max: 91

# Offense count: 1
# Offense count: 5
Metrics/BlockNesting:
Max: 4

# Offense count: 1
# Offense count: 2
# Configuration parameters: CountComments.
Metrics/ClassLength:
Max: 186
Max: 177

# Offense count: 9
# Offense count: 11
Metrics/CyclomaticComplexity:
Max: 17
Max: 19

# Offense count: 498
# Offense count: 522
# Configuration parameters: AllowURI, URISchemes.
Metrics/LineLength:
Max: 197
Max: 208

# Offense count: 32
# Configuration parameters: CountComments.
Metrics/MethodLength:
Max: 39
Max: 48

# Offense count: 9
# Offense count: 11
Metrics/PerceivedComplexity:
Max: 17
Max: 20

# Offense count: 73
# Configuration parameters: Exclude.
Expand Down
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
### Changelog

* [#78](https://github.com/dblock/slack-gamebot/issues/78): Losers can record a loss or a resignation without a prior challenge - [@dblock](https://github.com/dblock).
* [#77](https://github.com/dblock/slack-gamebot/issues/77): Opt-in now required to expose team data via the public API - [@dblock](https://github.com/dblock).
* [#76](https://github.com/dblock/slack-gamebot/issues/76): Prevent multiple bots from responding to you suck - [@dblock](https://github.com/dblock).
* [#75](https://github.com/dblock/slack-gamebot/issues/75): Nudge inactive teams every couple of weeks - [@dblock](https://github.com/dblock).
Expand Down
33 changes: 29 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ gamebot register
Welcome back Victor Barna! I've updated your registration.
```

#### gamebot challenge <opponent>, ... [with <teammate>, ...]
#### gamebot challenge <opponent> ... [with <teammate> ...]

Creates a new challenge between you and an opponent.

Expand Down Expand Up @@ -92,7 +92,7 @@ gamebot accept
Wang Hoe and Zhang Jike accepted Victor Barna and Deng Yaping's challenge.
```

#### gamebot lost [score, ...]
#### gamebot lost [to <opponent> [with <teammate>]] [score ...]

Record your loss.

Expand Down Expand Up @@ -128,7 +128,24 @@ gamebot lost 15:21 21:17 18:21
Match scores have been updated! Wang Hoe defeated Victor Barna with the scores of 15:21 21:17 18:21.
```

#### gamebot draw [score, ...]
You can record a loss without a challenge.

```
gamebot lost to @WangHoe
Match has been recorded! Wang Hoe defeated Victor Barna.
```

You can also record scores and record lost matches with multiple players.

```
gamebot lost to @WangHoe @ZhangJike with @DengYaping 5:21
Match has been recorded! Wang Hoe and Zhang Jike defeated Victor Barna and Deng Yaping with the score of 21:5.
```


#### gamebot draw [score ...]

Draws a challenge, records a tie. All other players will also have to draw to record a match.

Expand All @@ -142,7 +159,7 @@ gamebot draw 2:2
Match has been recorded. Victor Barna tied with Zhang Jike with a score of 2:2.
```

#### gamebot resigned
#### gamebot resigned [to <opponent> [with <teammate>]]

Records your resignation, which is a special kind of `lost` without a score.

Expand All @@ -154,6 +171,14 @@ Match has been recorded! Victor Barna resigned against Wang Hoe.

![](screenshots/resigned.gif)

You can resign without a prior challenge.

```
gamebot resigned to WangHoe
Match has been recorded! Victor Barna resigned against Wang Hoe.
```

#### gamebot decline

Decline a challenge.
Expand Down
38 changes: 36 additions & 2 deletions slack-gamebot/commands/lost.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,43 @@ module Commands
class Lost < SlackRubyBot::Commands::Base
def self.call(client, data, match)
challenger = ::User.find_create_or_update_by_slack_id!(client, data.user)
expression = match['expression'] if match.names.include?('expression')
arguments = expression.split.reject(&:blank?) if expression

scores = nil
opponents = []
teammates = [challenger]
multi_player = expression && expression.include?(' with ')

current = :scores
while arguments && arguments.any?
argument = arguments.shift
case argument
when 'to' then
current = :opponents
when 'with' then
current = :teammates
else
if current == :opponents
opponents << ::User.find_by_slack_mention!(client.team, argument)
current = :scores unless multi_player
elsif current == :teammates
teammates << ::User.find_by_slack_mention!(client.team, argument)
current = :scores if opponents.count == teammates.count
else
scores ||= []
scores << Score.check(argument)
end
end
end

challenge = ::Challenge.find_by_user(client.team, data.channel, challenger, [ChallengeState::PROPOSED, ChallengeState::ACCEPTED])
scores = Score.parse(match['expression']) if match.names.include?('expression')
if challenge

if opponents.any? && (challenge.nil? || (challenge.challengers != opponents && challenge.challenged != opponents))
match = ::Match.lose!(team: client.team, winners: opponents, losers: teammates, scores: scores)
client.say(channel: data.channel, text: "Match has been recorded! #{match}.", gif: 'loser')
logger.info "LOST TO: #{client.team} - #{match}"
elsif challenge
challenge.lose!(challenger, scores)
client.say(channel: data.channel, text: "Match has been recorded! #{challenge.match}.", gif: 'loser')
logger.info "LOST: #{client.team} - #{challenge}"
Expand Down
45 changes: 41 additions & 4 deletions slack-gamebot/commands/resigned.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,48 @@ module Commands
class Resigned < SlackRubyBot::Commands::Base
def self.call(client, data, match)
challenger = ::User.find_create_or_update_by_slack_id!(client, data.user)
expression = match['expression'] if match.names.include?('expression')
arguments = expression.split.reject(&:blank?) if expression

scores = nil
opponents = []
teammates = [challenger]
multi_player = expression && expression.include?(' with ')

current = :scores
while arguments && arguments.any?
argument = arguments.shift
case argument
when 'to' then
current = :opponents
when 'with' then
current = :teammates
else
if current == :opponents
opponents << ::User.find_by_slack_mention!(client.team, argument)
current = :scores unless multi_player
elsif current == :teammates
teammates << ::User.find_by_slack_mention!(client.team, argument)
current = :scores if opponents.count == teammates.count
else
scores ||= []
scores << argument
end
end
end

challenge = ::Challenge.find_by_user(client.team, data.channel, challenger, [ChallengeState::PROPOSED, ChallengeState::ACCEPTED])
scores = Score.parse(match['expression']) if match.names.include?('expression')
if challenge
challenge.resign!(challenger, scores)
client.say(channel: data.channel, text: "Match has been recorded! #{challenge.match}.", gif: 'coward')

if scores && scores.any?
client.say(channel: data.channel, text: 'Cannot score when resigning.', gif: 'idiot')
logger.info "RESIGNED: #{client.team} - #{data.user}, cannot score."
elsif opponents.any? && (challenge.nil? || (challenge.challengers != opponents && challenge.challenged != opponents))
match = ::Match.resign!(team: client.team, winners: opponents, losers: teammates)
client.say(channel: data.channel, text: "Match has been recorded! #{match}.", gif: 'loser')
logger.info "RESIGNED TO: #{client.team} - #{match}"
elsif challenge
challenge.resign!(challenger)
client.say(channel: data.channel, text: "Match has been recorded! #{challenge.match}.", gif: 'loser')
logger.info "RESIGNED: #{client.team} - #{challenge}"
else
client.say(channel: data.channel, text: 'No challenge to resign!')
Expand Down
15 changes: 3 additions & 12 deletions slack-gamebot/models/challenge.rb
Original file line number Diff line number Diff line change
Expand Up @@ -101,10 +101,7 @@ def lose!(loser, scores = nil)
else
fail SlackGamebot::Error, "Only #{(challenged + challengers).map(&:user_name).or} can lose this challenge."
end
Match.create!(team: team, challenge: self, winners: winners, losers: losers, scores: scores)
winners.inc(wins: 1)
losers.inc(losses: 1)
User.rank!(team)
Match.lose!(team: team, challenge: self, winners: winners, losers: losers, scores: scores)
update_attributes!(state: ChallengeState::PLAYED)
end

Expand All @@ -122,10 +119,7 @@ def resign!(loser, scores = nil)
else
fail SlackGamebot::Error, "Only #{(challenged + challengers).map(&:user_name).or} can lose this challenge."
end
Match.create!(team: team, challenge: self, winners: winners, losers: losers, scores: scores, resigned: true)
winners.inc(wins: 1)
losers.inc(losses: 1)
User.rank!(team)
Match.resign!(team: team, challenge: self, winners: winners, losers: losers, scores: scores)
update_attributes!(state: ChallengeState::PLAYED)
end

Expand All @@ -146,10 +140,7 @@ def draw!(player, scores = nil)
losers = challenged
winners = challengers
end
Match.create!(team: team, challenge: self, winners: winners, losers: losers, tied: true, scores: scores)
challenged.inc(ties: 1)
challengers.inc(ties: 1)
User.rank!(team)
Match.draw!(team: team, challenge: self, winners: winners, losers: losers, scores: scores)
update_attributes!(state: ChallengeState::PLAYED)
end

Expand Down
23 changes: 23 additions & 0 deletions slack-gamebot/models/match.rb
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,29 @@ def to_s
end
end

def self.lose!(attrs)
match = Match.create!(attrs)
match.winners.inc(wins: 1)
match.losers.inc(losses: 1)
User.rank!(match.team)
match
end

def self.resign!(attrs)
match = Match.create!(attrs.merge(resigned: true))
match.winners.inc(wins: 1)
match.losers.inc(losses: 1)
User.rank!(match.team)
match
end

def self.draw!(attrs)
match = Match.create!(attrs.merge(tied: true))
match.winners.inc(ties: 1)
match.losers.inc(ties: 1)
User.rank!(match.team)
end

private

def validate_teams
Expand Down
39 changes: 21 additions & 18 deletions slack-gamebot/models/score.rb
Original file line number Diff line number Diff line change
Expand Up @@ -26,28 +26,31 @@ def self.parse(expression)
return unless expression
scores = []
expression.split.reject(&:blank?).each do |pair|
pair_n = if pair.include?(':')
pair.split(':') if pair.include?(':')
elsif pair.include?('-')
pair.split('-')
elsif pair.include?(',')
pair.split(',')
end
fail SlackGamebot::Error, "Invalid score: #{pair}." unless pair_n && pair_n.length == 2
pair_n = pair_n.map do |points|
begin
points = Integer(points)
fail SlackGamebot::Error, 'points must be greater or equal to zero' if points < 0
points
rescue StandardError => e
raise SlackGamebot::Error, "Invalid score: #{pair}, #{e}."
end
end
scores << pair_n
scores << check(pair)
end
scores
end

def self.check(pair)
pair_n = if pair.include?(':')
pair.split(':') if pair.include?(':')
elsif pair.include?('-')
pair.split('-')
elsif pair.include?(',')
pair.split(',')
end
fail SlackGamebot::Error, "Invalid score: #{pair}." unless pair_n && pair_n.length == 2
pair_n.map do |points|
begin
points = Integer(points)
fail SlackGamebot::Error, 'points must be greater or equal to zero' if points < 0
points
rescue StandardError => e
raise SlackGamebot::Error, "Invalid score: #{pair}, #{e}."
end
end
end

def self.scores_to_string(scores)
[
scores.count > 1 ? 'the scores of' : 'the score of',
Expand Down
14 changes: 14 additions & 0 deletions spec/slack-gamebot/commands/challenge_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,20 @@
)
end.to change(Challenge, :count).by(1)
end
it 'creates a doubles challenge by user name' do
opponent2 = Fabricate(:user, team: team)
teammate = Fabricate(:user, team: team)
expect do
expect(message: "#{SlackRubyBot.config.user} challenge #{opponent.user_name} #{opponent2.user_name} with #{teammate.user_name}", user: user.user_id, channel: 'pongbot').to respond_with_slack_message(
"#{user.user_name} and #{teammate.user_name} challenged #{opponent.user_name} and #{opponent2.user_name} to a match!"
)
end.to change(Challenge, :count).by(1)
challenge = Challenge.last
expect(challenge.channel).to eq 'pongbot'
expect(challenge.created_by).to eq user
expect(challenge.challengers).to eq [teammate, user]
expect(challenge.challenged).to eq [opponent2, opponent]
end
it 'creates a singles challenge by user name case-insensitive' do
expect do
expect(message: "#{SlackRubyBot.config.user} challenge #{opponent.user_name.capitalize}", user: user.user_id, channel: 'pongbot').to respond_with_slack_message(
Expand Down
Loading

0 comments on commit 1817978

Please sign in to comment.