# A method that calculates win streaks

Right now, I have the following:

• A win_streak column on the User table.
• This method in game.rb

I'm interpreting win_streak as follows:

• The number if the number games in the streak
• The value (positive or negative) specifies whether those games were wins (positive) or losses (negative)

game.rb:

def adjust_streak
u = self.user
case self.result
when 'Win'
u.win_streak > 0 ? u.win_streak += 1 : u.win_streak = 1
when 'Loss'
u.win_streak > 0 ? u.win_streak = -1 : u.win_streak -= 1
end
u.save
end


I'm looking for a cleaner, and more succinct way to do this (e.g. keep track of win/loss streaks).

• Can there be a draw? – Eric Duminil Feb 23 '18 at 13:30
• The way the game is set up, no, there cannot be a draw. – Hyrum Carlile Mar 2 '18 at 15:44

• You can use Array#min and Array#max to calculate the win/lose streak;
• You don't need to use self on getters;
• And you can use user.update instead of assigning and calling .save;
• I would also rename the win_streak column to streak;

def adjust_streak
streak = case result
when 'Win'  then [user.streak, 0].max + 1
when 'Loss' then [user.streak, 0].min - 1
end

user.update streak: streak
end

• This is solid. I really like the ingenuity of using Array#min and Array#max. I wouldn't have even thought of that. Very clever! Thanks! – Hyrum Carlile Feb 19 '18 at 19:40
• Nice! [0, streak].max + 1 and [0, streak].min - 1 might be even clearer. – Eric Duminil Feb 23 '18 at 13:41
• great idea @EricDuminil, I updated my answer :) – Peoplee Feb 23 '18 at 17:49

Can the result be a tie? If not, then you can store wins and losses as Boolean values.

Thus you can use reduce the method to:

def adjust_streak
u = self.user
self.result == 1 ? u.win_streak += 1 : u.win_streak = 0
u.save
end


If the result is a 'Win' (1/true) then increment the win streak, otherwise if the result is a loss the win streak is 0.

The value (positive or negative) specifies whether those games were wins (positive) or losses (negative)

This can be the sum of the result column if you are saving the values as 1 and 0.

• The problem is that I also need to know how many losses in a row the user has, if they've lost multiple games in a row. (I guess I should probably rename the win_streak column to just streak) – Hyrum Carlile Feb 15 '18 at 19:04
• If the streak is LLWLL, what number would you want to show and why? – danielsmith1789 Feb 15 '18 at 19:58
• -2, to indicate that the user is on a 2 game losing streak. It doesn't necessarily have to be -2 I guess. But I would have to somehow know that the user is on a 2 game losing streak. I'm not sure how I would get that info from the sum of the result column like you said. – Hyrum Carlile Feb 15 '18 at 21:17

I played around with a bunch of options, but kept coming back to the structure you have. So here are a couple tweaks you could apply:

Make the logic in the cases look more alike / easier to reason about:

def adjust_streak
u = self.user
case self.result
when 'Win'
u.win_streak > 0 ? u.win_streak += 1 : u.win_streak = 1
when 'Loss'
u.win_streak < 0 ? u.win_streak -= 1 : u.win_streak = -1
end
u.save
end


Could use #positive?/#negative?:

def adjust_streak
u = self.user
case self.result
when 'Win'
u.win_streak.positive? ? u.win_streak += 1 : u.win_streak = 1
when 'Loss'
u.win_streak.negative? ? u.win_streak -= 1 : u.win_streak = -1
end
u.save
end


DRY up assignment (assumes result can only be "Win" or "Loss"):

def adjust_streak
u = self.user
u.win_streak = case self.result
when 'Win'
u.win_streak.positive? ? u.win_streak + 1 : 1
when 'Loss'
u.win_streak.negative? ? u.win_streak - 1 : -1
end
u.save
end


As you mentioned in the comment on the other answer, the column name should be streak instead of win_streak.