From d70ce44c5fc347363d497af07eff9c42f5f26539 Mon Sep 17 00:00:00 2001 From: Emily Bache Date: Wed, 24 Aug 2011 11:08:32 +0200 Subject: [PATCH 001/634] first commit --- README | 0 Tennis/java/defactored1/TennisGame.java | 80 +++++++++++ Tennis/java/defactored1/TennisTest.java | 94 +++++++++++++ Tennis/java/defactored2/TennisGame.java | 138 +++++++++++++++++++ Tennis/java/defactored2/TennisTest.java | 94 +++++++++++++ Tennis/java/defactored3/TennisGame.java | 37 +++++ Tennis/java/defactored3/TennisTest.java | 94 +++++++++++++ Tennis/java/factored1/TennisGame.java | 63 +++++++++ Tennis/java/factored1/TennisTest.java | 93 +++++++++++++ Tennis/python/tennis.py | 176 ++++++++++++++++++++++++ Tennis/python/tennis.pyc | Bin 0 -> 6001 bytes Tennis/python/tennis_test.py | 64 +++++++++ Tennis/python/tennis_test.pyc | Bin 0 -> 2878 bytes 13 files changed, 933 insertions(+) create mode 100644 README create mode 100644 Tennis/java/defactored1/TennisGame.java create mode 100644 Tennis/java/defactored1/TennisTest.java create mode 100644 Tennis/java/defactored2/TennisGame.java create mode 100644 Tennis/java/defactored2/TennisTest.java create mode 100644 Tennis/java/defactored3/TennisGame.java create mode 100644 Tennis/java/defactored3/TennisTest.java create mode 100644 Tennis/java/factored1/TennisGame.java create mode 100644 Tennis/java/factored1/TennisTest.java create mode 100644 Tennis/python/tennis.py create mode 100644 Tennis/python/tennis.pyc create mode 100644 Tennis/python/tennis_test.py create mode 100644 Tennis/python/tennis_test.pyc diff --git a/README b/README new file mode 100644 index 00000000..e69de29b diff --git a/Tennis/java/defactored1/TennisGame.java b/Tennis/java/defactored1/TennisGame.java new file mode 100644 index 00000000..fee379aa --- /dev/null +++ b/Tennis/java/defactored1/TennisGame.java @@ -0,0 +1,80 @@ +package defactored1; + +public class TennisGame { + + private int m_score1 = 0; + private int m_score2 = 0; + private String player1Name; + private String player2Name; + + public TennisGame(String player1Name, String player2Name) { + this.player1Name = player1Name; + this.player2Name = player2Name; + } + + public void wonPoint(String playerName) { + if (playerName == "player1") + m_score1 += 1; + else + m_score2 += 1; + } + + public String getScore() { + String score = ""; + int tempScore=0; + if (m_score1==m_score2) + { + switch (m_score1) + { + case 0: + score = "Love-All"; + break; + case 1: + score = "Fifteen-All"; + break; + case 2: + score = "Thirty-All"; + break; + case 3: + score = "Forty-All"; + break; + default: + score = "Deuce"; + break; + + } + } + else if (m_score1>=4 || m_score2>=4) + { + int minusResult = m_score1-m_score2; + if (minusResult==1) score ="Advantage player1"; + else if (minusResult ==-1) score ="Advantage player2"; + else if (minusResult>=2) score = "Win for player1"; + else score ="Win for player2"; + } + else + { + for (int i=1; i<3; i++) + { + if (i==1) tempScore = m_score1; + else { score+="-"; tempScore = m_score2;} + switch(tempScore) + { + case 0: + score+="Love"; + break; + case 1: + score+="Fifteen"; + break; + case 2: + score+="Thirty"; + break; + case 3: + score+="Forty"; + break; + } + } + } + return score; + } +} diff --git a/Tennis/java/defactored1/TennisTest.java b/Tennis/java/defactored1/TennisTest.java new file mode 100644 index 00000000..48c247bc --- /dev/null +++ b/Tennis/java/defactored1/TennisTest.java @@ -0,0 +1,94 @@ +package defactored1; + +import static org.junit.Assert.*; + +import java.util.Arrays; +import java.util.Collection; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.junit.runners.Parameterized.Parameters; + +@RunWith(Parameterized.class) +public class TennisTest { + + private int player1Score; + private int player2Score; + private String expectedScore; + + public TennisTest(int player1Score, int player2Score, String expectedScore) { + this.player1Score = player1Score; + this.player2Score = player2Score; + this.expectedScore = expectedScore; + } + + @Parameters + public static Collection getAllScores() { + return Arrays.asList(new Object[][] { + { 0, 0, "Love-All" }, + { 1, 1, "Fifteen-All" }, + { 2, 2, "Thirty-All"}, + { 3, 3, "Forty-All"}, + { 4, 4, "Deuce"}, + + { 1, 0, "Fifteen-Love"}, + { 0, 1, "Love-Fifteen"}, + { 2, 0, "Thirty-Love"}, + { 0, 2, "Love-Thirty"}, + { 3, 0, "Forty-Love"}, + { 0, 3, "Love-Forty"}, + { 4, 0, "Win for player1"}, + { 0, 4, "Win for player2"}, + + { 2, 1, "Thirty-Fifteen"}, + { 1, 2, "Fifteen-Thirty"}, + { 3, 1, "Forty-Fifteen"}, + { 1, 3, "Fifteen-Forty"}, + { 4, 1, "Win for player1"}, + { 1, 4, "Win for player2"}, + + { 3, 2, "Forty-Thirty"}, + { 2, 3, "Thirty-Forty"}, + { 4, 2, "Win for player1"}, + { 2, 4, "Win for player2"}, + + { 4, 3, "Advantage player1"}, + { 3, 4, "Advantage player2"}, + { 5, 4, "Advantage player1"}, + { 4, 5, "Advantage player2"}, + { 15, 14, "Advantage player1"}, + { 14, 15, "Advantage player2"}, + + { 6, 4, "Win for player1"}, + { 4, 6, "Win for player2"}, + { 16, 14, "Win for player1"}, + { 14, 16, "Win for player2"}, + }); + } + + @Test + public void checkAllScores() { + TennisGame game = new TennisGame("player1", "player2"); + for (int i = 0; i < this.player1Score; i++) + game.wonPoint("player1"); + for (int i = 0; i < this.player2Score; i++) + game.wonPoint("player2"); + assertEquals(this.expectedScore, game.getScore()); + } + + @Test + public void realisticGame() { + TennisGame game = new TennisGame("player1", "player2"); + String[] points = {"player1", "player1", "player2", "player2", "player1", "player1"}; + String[] expected_scores = {"Fifteen-Love", "Thirty-Love", "Thirty-Fifteen", "Thirty-All", "Forty-Thirty", "Win for player1"}; + for (int i = 0; i < 6; i++) { + game.wonPoint(points[i]); + assertEquals(expected_scores[i], game.getScore()); + } + + + } + +} diff --git a/Tennis/java/defactored2/TennisGame.java b/Tennis/java/defactored2/TennisGame.java new file mode 100644 index 00000000..6d1ecd78 --- /dev/null +++ b/Tennis/java/defactored2/TennisGame.java @@ -0,0 +1,138 @@ +package defactored2; + +public class TennisGame +{ + public int P1point = 0; + public int P2point = 0; + + public String P1res = ""; + public String P2res = ""; + private String player1Name; + private String player2Name; + + public TennisGame(String player1Name, String player2Name) { + this.player1Name = player1Name; + this.player2Name = player2Name; + } + + public String getScore(){ + String score = ""; + if (P1point == P2point && P1point < 4) + { + if (P1point==0) + score = "Love"; + if (P1point==1) + score = "Fifteen"; + if (P1point==2) + score = "Thirty"; + if (P1point==3) + score = "Forty"; + score += "-All"; + } + if (P1point==P2point && P1point>3) + score = "Deuce"; + + if (P1point > 0 && P2point==0) + { + if (P1point==1) + P1res = "Fifteen"; + if (P1point==2) + P1res = "Thirty"; + if (P1point==3) + P1res = "Forty"; + + P2res = "Love"; + score = P1res + "-" + P2res; + } + if (P2point > 0 && P1point==0) + { + if (P2point==1) + P2res = "Fifteen"; + if (P2point==2) + P2res = "Thirty"; + if (P2point==3) + P2res = "Forty"; + + P1res = "Love"; + score = P1res + "-" + P2res; + } + + if (P1point>P2point && P1point < 4) + { + if (P1point==2) + P1res="Thirty"; + if (P1point==3) + P1res="Forty"; + if (P2point==1) + P2res="Fifteen"; + if (P2point==2) + P2res="Thirty"; + score = P1res + "-" + P2res; + } + if (P2point>P1point && P2point < 4) + { + if (P2point==2) + P2res="Thirty"; + if (P2point==3) + P2res="Forty"; + if (P1point==1) + P1res="Fifteen"; + if (P1point==2) + P1res="Thirty"; + score = P1res + "-" + P2res; + } + + if (P1point > P2point && P2point >= 3) + { + score = "Advantage player1"; + } + + if (P2point > P1point && P1point >= 3) + { + score = "Advantage player2"; + } + + if (P1point>=4 && P2point>=0 && (P1point-P2point)>=2) + { + score = "Win for player1"; + } + if (P2point>=4 && P1point>=0 && (P2point-P1point)>=2) + { + score = "Win for player2"; + } + return score; + } + + public void SetP1Score(int number){ + + for (int i = 0; i < number; i++) + { + P1Score(); + } + + } + + public void SetP2Score(int number){ + + for (int i = 0; i < number; i++) + { + P2Score(); + } + + } + + public void P1Score(){ + P1point++; + } + + public void P2Score(){ + P2point++; + } + + public void wonPoint(String player) { + if (player == "player1") + P1Score(); + else + P2Score(); + } +} \ No newline at end of file diff --git a/Tennis/java/defactored2/TennisTest.java b/Tennis/java/defactored2/TennisTest.java new file mode 100644 index 00000000..92807971 --- /dev/null +++ b/Tennis/java/defactored2/TennisTest.java @@ -0,0 +1,94 @@ +package defactored2; + +import static org.junit.Assert.*; + +import java.util.Arrays; +import java.util.Collection; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.junit.runners.Parameterized.Parameters; + +@RunWith(Parameterized.class) +public class TennisTest { + + private int player1Score; + private int player2Score; + private String expectedScore; + + public TennisTest(int player1Score, int player2Score, String expectedScore) { + this.player1Score = player1Score; + this.player2Score = player2Score; + this.expectedScore = expectedScore; + } + + @Parameters + public static Collection getAllScores() { + return Arrays.asList(new Object[][] { + { 0, 0, "Love-All" }, + { 1, 1, "Fifteen-All" }, + { 2, 2, "Thirty-All"}, + { 3, 3, "Forty-All"}, + { 4, 4, "Deuce"}, + + { 1, 0, "Fifteen-Love"}, + { 0, 1, "Love-Fifteen"}, + { 2, 0, "Thirty-Love"}, + { 0, 2, "Love-Thirty"}, + { 3, 0, "Forty-Love"}, + { 0, 3, "Love-Forty"}, + { 4, 0, "Win for player1"}, + { 0, 4, "Win for player2"}, + + { 2, 1, "Thirty-Fifteen"}, + { 1, 2, "Fifteen-Thirty"}, + { 3, 1, "Forty-Fifteen"}, + { 1, 3, "Fifteen-Forty"}, + { 4, 1, "Win for player1"}, + { 1, 4, "Win for player2"}, + + { 3, 2, "Forty-Thirty"}, + { 2, 3, "Thirty-Forty"}, + { 4, 2, "Win for player1"}, + { 2, 4, "Win for player2"}, + + { 4, 3, "Advantage player1"}, + { 3, 4, "Advantage player2"}, + { 5, 4, "Advantage player1"}, + { 4, 5, "Advantage player2"}, + { 15, 14, "Advantage player1"}, + { 14, 15, "Advantage player2"}, + + { 6, 4, "Win for player1"}, + { 4, 6, "Win for player2"}, + { 16, 14, "Win for player1"}, + { 14, 16, "Win for player2"}, + }); + } + + @Test + public void checkAllScores() { + TennisGame game = new TennisGame("player1", "player2"); + for (int i = 0; i < this.player1Score; i++) + game.wonPoint("player1"); + for (int i = 0; i < this.player2Score; i++) + game.wonPoint("player2"); + assertEquals(this.expectedScore, game.getScore()); + } + + @Test + public void realisticGame() { + TennisGame game = new TennisGame("player1", "player2"); + String[] points = {"player1", "player1", "player2", "player2", "player1", "player1"}; + String[] expected_scores = {"Fifteen-Love", "Thirty-Love", "Thirty-Fifteen", "Thirty-All", "Forty-Thirty", "Win for player1"}; + for (int i = 0; i < 6; i++) { + game.wonPoint(points[i]); + assertEquals(expected_scores[i], game.getScore()); + } + + + } + +} diff --git a/Tennis/java/defactored3/TennisGame.java b/Tennis/java/defactored3/TennisGame.java new file mode 100644 index 00000000..e3fcf7bd --- /dev/null +++ b/Tennis/java/defactored3/TennisGame.java @@ -0,0 +1,37 @@ +package defactored3; + +public class TennisGame { + + private int p2; + private int p1; + private String p1N; + private String p2N; + + public TennisGame(String p1N, String p2N) { + this.p1N = p1N; + this.p2N = p2N; + } + + public String getScore() { + String s; + if (p1 < 4 && p2 < 4) { + String[] p = new String[]{"Love", "Fifteen", "Thirty", "Forty"}; + s = p[p1]; + return (p1 == p2) ? s + "-All" : s + "-" + p[p2]; + } else { + if (p1 == p2) + return "Deuce"; + s = p1 > p2 ? p1N : p2N; + return ((p1-p2)*(p1-p2) == 1) ? "Advantage " + s : "Win for " + s; + } + } + + public void wonPoint(String playerName) { + if (playerName == "player1") + this.p1 += 1; + else + this.p2 += 1; + + } + +} diff --git a/Tennis/java/defactored3/TennisTest.java b/Tennis/java/defactored3/TennisTest.java new file mode 100644 index 00000000..0780329a --- /dev/null +++ b/Tennis/java/defactored3/TennisTest.java @@ -0,0 +1,94 @@ +package defactored3; + +import static org.junit.Assert.*; + +import java.util.Arrays; +import java.util.Collection; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.junit.runners.Parameterized.Parameters; + +@RunWith(Parameterized.class) +public class TennisTest { + + private int player1Score; + private int player2Score; + private String expectedScore; + + public TennisTest(int player1Score, int player2Score, String expectedScore) { + this.player1Score = player1Score; + this.player2Score = player2Score; + this.expectedScore = expectedScore; + } + + @Parameters + public static Collection getAllScores() { + return Arrays.asList(new Object[][] { + { 0, 0, "Love-All" }, + { 1, 1, "Fifteen-All" }, + { 2, 2, "Thirty-All"}, + { 3, 3, "Forty-All"}, + { 4, 4, "Deuce"}, + + { 1, 0, "Fifteen-Love"}, + { 0, 1, "Love-Fifteen"}, + { 2, 0, "Thirty-Love"}, + { 0, 2, "Love-Thirty"}, + { 3, 0, "Forty-Love"}, + { 0, 3, "Love-Forty"}, + { 4, 0, "Win for player1"}, + { 0, 4, "Win for player2"}, + + { 2, 1, "Thirty-Fifteen"}, + { 1, 2, "Fifteen-Thirty"}, + { 3, 1, "Forty-Fifteen"}, + { 1, 3, "Fifteen-Forty"}, + { 4, 1, "Win for player1"}, + { 1, 4, "Win for player2"}, + + { 3, 2, "Forty-Thirty"}, + { 2, 3, "Thirty-Forty"}, + { 4, 2, "Win for player1"}, + { 2, 4, "Win for player2"}, + + { 4, 3, "Advantage player1"}, + { 3, 4, "Advantage player2"}, + { 5, 4, "Advantage player1"}, + { 4, 5, "Advantage player2"}, + { 15, 14, "Advantage player1"}, + { 14, 15, "Advantage player2"}, + + { 6, 4, "Win for player1"}, + { 4, 6, "Win for player2"}, + { 16, 14, "Win for player1"}, + { 14, 16, "Win for player2"}, + }); + } + + @Test + public void checkAllScores() { + TennisGame game = new TennisGame("player1", "player2"); + for (int i = 0; i < this.player1Score; i++) + game.wonPoint("player1"); + for (int i = 0; i < this.player2Score; i++) + game.wonPoint("player2"); + assertEquals(this.expectedScore, game.getScore()); + } + + @Test + public void realisticGame() { + TennisGame game = new TennisGame("player1", "player2"); + String[] points = {"player1", "player1", "player2", "player2", "player1", "player1"}; + String[] expected_scores = {"Fifteen-Love", "Thirty-Love", "Thirty-Fifteen", "Thirty-All", "Forty-Thirty", "Win for player1"}; + for (int i = 0; i < 6; i++) { + game.wonPoint(points[i]); + assertEquals(expected_scores[i], game.getScore()); + } + + + } + +} diff --git a/Tennis/java/factored1/TennisGame.java b/Tennis/java/factored1/TennisGame.java new file mode 100644 index 00000000..0ff71289 --- /dev/null +++ b/Tennis/java/factored1/TennisGame.java @@ -0,0 +1,63 @@ +package factored1; + +public class TennisGame { + + public static final String[] POINTS = new String[]{"Love", "Fifteen", "Thirty", "Forty"}; + + private int player2Score; + private int player1Score; + + private String player1Name; + private String player2Name; + + public TennisGame(String player1Name, String player2Name) { + this.player1Name = player1Name; + this.player2Name = player2Name; + } + + public String getScore() { + if (someoneHasWon()) + return "Win for " + winningPlayerName(); + + if (isEndgame()) { + if (pointsAreEven()) + return "Deuce"; + else + return "Advantage " + winningPlayerName(); + } else { + if (pointsAreEven()) + return POINTS[player1Score] + "-All"; + else { + return POINTS[player1Score] + "-" + POINTS[player2Score]; + } + } + } + + public boolean someoneHasWon() { + return isEndgame() && (player1Score-player2Score >= 2 || player2Score-player1Score >= 2); + } + + private boolean pointsAreEven() { + return player1Score == player2Score; + } + + private boolean isEndgame() { + return player1Score > 3 || player2Score > 3; + } + + public String winningPlayerName() { + if (player1Score > player2Score) + return player1Name; + else + return player2Name; + } + + public void wonPoint(String playerName) { + if (playerName == player1Name) + this.player1Score += 1; + else + this.player2Score += 1; + + } + +} diff --git a/Tennis/java/factored1/TennisTest.java b/Tennis/java/factored1/TennisTest.java new file mode 100644 index 00000000..e6e8b26e --- /dev/null +++ b/Tennis/java/factored1/TennisTest.java @@ -0,0 +1,93 @@ +package factored1; + +import static org.junit.Assert.*; + +import java.util.Arrays; +import java.util.Collection; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.junit.runners.Parameterized.Parameters; + +@RunWith(Parameterized.class) +public class TennisTest { + + private int player1Score; + private int player2Score; + private String expectedScore; + + public TennisTest(int player1Score, int player2Score, String expectedScore) { + this.player1Score = player1Score; + this.player2Score = player2Score; + this.expectedScore = expectedScore; + } + + @Parameters + public static Collection getAllScores() { + return Arrays.asList(new Object[][] { + { 0, 0, "Love-All" }, + { 1, 1, "Fifteen-All" }, + { 2, 2, "Thirty-All"}, + { 3, 3, "Forty-All"}, + { 4, 4, "Deuce"}, + + { 1, 0, "Fifteen-Love"}, + { 0, 1, "Love-Fifteen"}, + { 2, 0, "Thirty-Love"}, + { 0, 2, "Love-Thirty"}, + { 3, 0, "Forty-Love"}, + { 0, 3, "Love-Forty"}, + { 4, 0, "Win for player1"}, + { 0, 4, "Win for player2"}, + + { 2, 1, "Thirty-Fifteen"}, + { 1, 2, "Fifteen-Thirty"}, + { 3, 1, "Forty-Fifteen"}, + { 1, 3, "Fifteen-Forty"}, + { 4, 1, "Win for player1"}, + { 1, 4, "Win for player2"}, + + { 3, 2, "Forty-Thirty"}, + { 2, 3, "Thirty-Forty"}, + { 4, 2, "Win for player1"}, + { 2, 4, "Win for player2"}, + + { 4, 3, "Advantage player1"}, + { 3, 4, "Advantage player2"}, + { 5, 4, "Advantage player1"}, + { 4, 5, "Advantage player2"}, + { 15, 14, "Advantage player1"}, + { 14, 15, "Advantage player2"}, + + { 6, 4, "Win for player1"}, + { 4, 6, "Win for player2"}, + { 16, 14, "Win for player1"}, + { 14, 16, "Win for player2"}, + }); + } + + @Test + public void checkAllScores() { + TennisGame game = new TennisGame("player1", "player2"); + for (int i = 0; i < this.player1Score; i++) + game.wonPoint("player1"); + for (int i = 0; i < this.player2Score; i++) + game.wonPoint("player2"); + assertEquals(this.expectedScore, game.getScore()); + } + + @Test + public void realisticGame() { + TennisGame game = new TennisGame("player1", "player2"); + String[] points = {"player1", "player1", "player2", "player2", "player1", "player1"}; + String[] expected_scores = {"Fifteen-Love", "Thirty-Love", "Thirty-Fifteen", "Thirty-All", "Forty-Thirty", "Win for player1"}; + for (int i = 0; i < 6; i++) { + game.wonPoint(points[i]); + assertEquals(expected_scores[i], game.getScore()); + } + + + } + +} diff --git a/Tennis/python/tennis.py b/Tennis/python/tennis.py new file mode 100644 index 00000000..af859684 --- /dev/null +++ b/Tennis/python/tennis.py @@ -0,0 +1,176 @@ + + +class TennisGameDefactored1: + + def __init__(self, player1Name, player2Name): + self.player1Name = player1Name + self.player2Name = player2Name + self.p1points = 0 + self.p2points = 0 + + def won_point(self, playerName): + if playerName == self.player1Name: + self.p1points += 1 + else: + self.p2points += 1 + + def score(self): + result = "" + tempScore=0 + if (self.p1points==self.p2points): + result = { + 0 : "Love-All", + 1 : "Fifteen-All", + 2 : "Thirty-All", + 3 : "Forty-All", + }.get(self.p1points, "Deuce") + elif (self.p1points>=4 or self.p2points>=4): + minusResult = self.p1points-self.p2points + if (minusResult==1): + result ="Advantage player1" + elif (minusResult ==-1): + result ="Advantage player2" + elif (minusResult>=2): + result = "Win for player1" + else: + result ="Win for player2" + else: + for i in range(1,3): + if (i==1): + tempScore = self.p1points + else: + result+="-" + tempScore = self.p2points + result += { + 0 : "Love", + 1 : "Fifteen", + 2 : "Thirty", + 3 : "Forty", + }[tempScore] + return result + + +class TennisGameDefactored2: + def __init__(self, player1Name, player2Name): + self.player1Name = player1Name + self.player2Name = player2Name + self.p1points = 0 + self.p2points = 0 + + def won_point(self, playerName): + if playerName == self.player1Name: + self.P1Score() + else: + self.P2Score() + + def score(self): + result = "" + if (self.p1points == self.p2points and self.p1points < 4): + if (self.p1points==0): + result = "Love" + if (self.p1points==1): + result = "Fifteen" + if (self.p1points==2): + result = "Thirty" + if (self.p1points==3): + result = "Forty" + result += "-All" + if (self.p1points==self.p2points and self.p1points>3): + result = "Deuce" + + P1res = "" + P2res = "" + if (self.p1points > 0 and self.p2points==0): + if (self.p1points==1): + P1res = "Fifteen" + if (self.p1points==2): + P1res = "Thirty" + if (self.p1points==3): + P1res = "Forty" + + P2res = "Love" + result = P1res + "-" + P2res + if (self.p2points > 0 and self.p1points==0): + if (self.p2points==1): + P2res = "Fifteen" + if (self.p2points==2): + P2res = "Thirty" + if (self.p2points==3): + P2res = "Forty" + + P1res = "Love" + result = P1res + "-" + P2res + + + if (self.p1points>self.p2points and self.p1points < 4): + if (self.p1points==2): + P1res="Thirty" + if (self.p1points==3): + P1res="Forty" + if (self.p2points==1): + P2res="Fifteen" + if (self.p2points==2): + P2res="Thirty" + result = P1res + "-" + P2res + if (self.p2points>self.p1points and self.p2points < 4): + if (self.p2points==2): + P2res="Thirty" + if (self.p2points==3): + P2res="Forty" + if (self.p1points==1): + P1res="Fifteen" + if (self.p1points==2): + P1res="Thirty" + result = P1res + "-" + P2res + + if (self.p1points > self.p2points and self.p2points >= 3): + result = "Advantage player1" + + if (self.p2points > self.p1points and self.p1points >= 3): + result = "Advantage player2" + + if (self.p1points>=4 and self.p2points>=0 and (self.p1points-self.p2points)>=2): + result = "Win for player1" + if (self.p2points>=4 and self.p1points>=0 and (self.p2points-self.p1points)>=2): + result = "Win for player2" + return result + + def SetP1Score(self, number): + for i in range(number): + self.P1Score() + + def SetP2Score(self, number): + for i in range(number): + self.P2Score() + + def P1Score(self): + self.p1points +=1 + + + def P2Score(self): + self.p2points +=1 + +class TennisGameDefactored3: + def __init__(self, player1Name, player2Name): + self.p1N = player1Name + self.p2N = player2Name + self.p1 = 0 + self.p2 = 0 + + def won_point(self, n): + if n == self.p1N: + self.p1 += 1 + else: + self.p2 += 1 + + def score(self): + if (self.p1 < 4 and self.p2 < 4): + p = ["Love", "Fifteen", "Thirty", "Forty"] + s = p[self.p1] + return s + "-All" if (self.p1 == self.p2) else s + "-" + p[self.p2] + else: + if (self.p1 == self.p2): + return "Deuce" + s = self.p1N if self.p1 > self.p2 else self.p2N + return "Advantage " + s if ((self.p1-self.p2)*(self.p1-self.p2) == 1) else "Win for " + s + diff --git a/Tennis/python/tennis.pyc b/Tennis/python/tennis.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2a7e16267570c95bd1fd6b14371034283a8dca4c GIT binary patch literal 6001 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 literal 0 HcmV?d00001 From 0b77db28e9801b610f7a7c4669401bd78540b4e3 Mon Sep 17 00:00:00 2001 From: Emily Bache Date: Wed, 24 Aug 2011 11:10:27 +0200 Subject: [PATCH 002/634] no need to store pyc files in repo --- Tennis/python/tennis.pyc | Bin 6001 -> 0 bytes Tennis/python/tennis_test.pyc | Bin 2878 -> 0 bytes 2 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 Tennis/python/tennis.pyc delete mode 100644 Tennis/python/tennis_test.pyc diff --git a/Tennis/python/tennis.pyc b/Tennis/python/tennis.pyc deleted file mode 100644 index 2a7e16267570c95bd1fd6b14371034283a8dca4c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6001 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 From 5453deb427e5e500cf462f8c4c38c12355b5de7d Mon Sep 17 00:00:00 2001 From: Emily Bache Date: Thu, 25 Aug 2011 08:48:08 +0200 Subject: [PATCH 003/634] initial text --- README | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/README b/README index e69de29b..46e9722c 100644 --- a/README +++ b/README @@ -0,0 +1,5 @@ +This is a collection of starting files for when practicing refactoring. + +Contents so far: + +Tennis kata in Java and python. \ No newline at end of file From 33fa98f175bd33bafa2983ee0610e634a78ba0e2 Mon Sep 17 00:00:00 2001 From: Fredrik Wendt Date: Fri, 7 Oct 2011 00:50:32 +0200 Subject: [PATCH 004/634] added test and fix - player's names weren't used --- Tennis/python/tennis.py | 16 ++++++++-------- Tennis/python/tennis_test.py | 17 +++++++++++++---- 2 files changed, 21 insertions(+), 12 deletions(-) diff --git a/Tennis/python/tennis.py b/Tennis/python/tennis.py index af859684..e7e33791 100644 --- a/Tennis/python/tennis.py +++ b/Tennis/python/tennis.py @@ -27,13 +27,13 @@ class TennisGameDefactored1: elif (self.p1points>=4 or self.p2points>=4): minusResult = self.p1points-self.p2points if (minusResult==1): - result ="Advantage player1" + result ="Advantage " + self.player1Name elif (minusResult ==-1): - result ="Advantage player2" + result ="Advantage " + self.player2Name elif (minusResult>=2): - result = "Win for player1" + result = "Win for " + self.player1Name else: - result ="Win for player2" + result ="Win for " + self.player2Name else: for i in range(1,3): if (i==1): @@ -124,15 +124,15 @@ class TennisGameDefactored2: result = P1res + "-" + P2res if (self.p1points > self.p2points and self.p2points >= 3): - result = "Advantage player1" + result = "Advantage " + self.player1Name if (self.p2points > self.p1points and self.p1points >= 3): - result = "Advantage player2" + result = "Advantage " + self.player2Name if (self.p1points>=4 and self.p2points>=0 and (self.p1points-self.p2points)>=2): - result = "Win for player1" + result = "Win for " + self.player1Name if (self.p2points>=4 and self.p1points>=0 and (self.p2points-self.p1points)>=2): - result = "Win for player2" + result = "Win for " + self.player2Name return result def SetP1Score(self, number): diff --git a/Tennis/python/tennis_test.py b/Tennis/python/tennis_test.py index e12198db..2c5afe81 100644 --- a/Tennis/python/tennis_test.py +++ b/Tennis/python/tennis_test.py @@ -10,6 +10,10 @@ def params(funcarglist): def pytest_generate_tests(metafunc): for funcargs in getattr(metafunc.function, 'funcarglist', ()): + if "p1Name" not in funcargs: + funcargs["p1Name"] = "player1" + if "p2Name" not in funcargs: + funcargs["p2Name"] = "player2" metafunc.addcall(funcargs=funcargs) # actual test code @@ -53,12 +57,17 @@ class TestTennis: dict(p1Points=4, p2Points=6, score="Win for player2"), dict(p1Points=16, p2Points=14, score="Win for player1"), dict(p1Points=14, p2Points=16, score="Win for player2"), + + dict(p1Points=6, p2Points=4, score="Win for One", p1Name='One'), + dict(p1Points=4, p2Points=6, score="Win for Two", p2Name="Two"), + dict(p1Points=6, p2Points=5, score="Advantage One", p1Name='One'), + dict(p1Points=5, p2Points=6, score="Advantage Two", p2Name="Two"), ]) - def test_get_score(self, p1Points, p2Points, score): - game = TennisGame("player1", "player2") + def test_get_score(self, p1Points, p2Points, score, p1Name, p2Name): + game = TennisGame(p1Name, p2Name) for i in range(p1Points): - game.won_point("player1") + game.won_point(p1Name) for i in range(p2Points): - game.won_point("player2") + game.won_point(p2Name) assert score == game.score() From 16079c8f9ff11c6fbe867c077a334e269c847e1e Mon Sep 17 00:00:00 2001 From: Emily Bache Date: Wed, 4 Jan 2012 09:53:16 +0100 Subject: [PATCH 005/634] version of three exercises, in c++ --- Tennis/cpp/defactored1/Makefile | 75 ++++++++ Tennis/cpp/defactored1/README | 14 ++ Tennis/cpp/defactored1/Tennis.cc | 227 ++++++++++++++++++++++ Tennis/cpp/defactored1/run-endless.sh | 1 + Tennis/cpp/defactored1/run-once.sh | 4 + Tennis/cpp/defactored2/Makefile | 75 ++++++++ Tennis/cpp/defactored2/README | 14 ++ Tennis/cpp/defactored2/Tennis.cc | 258 ++++++++++++++++++++++++++ Tennis/cpp/defactored2/run-endless.sh | 1 + Tennis/cpp/defactored2/run-once.sh | 4 + Tennis/cpp/defactored3/Makefile | 75 ++++++++ Tennis/cpp/defactored3/README | 14 ++ Tennis/cpp/defactored3/Tennis.cc | 183 ++++++++++++++++++ Tennis/cpp/defactored3/run-endless.sh | 1 + Tennis/cpp/defactored3/run-once.sh | 4 + Tennis/cpp/generate_tests.py | 55 ++++++ Tennis/cpp/starting/Makefile | 75 ++++++++ Tennis/cpp/starting/README | 14 ++ Tennis/cpp/starting/Tennis.cc | 171 +++++++++++++++++ Tennis/cpp/starting/run-endless.sh | 1 + Tennis/cpp/starting/run-once.sh | 4 + 21 files changed, 1270 insertions(+) create mode 100644 Tennis/cpp/defactored1/Makefile create mode 100644 Tennis/cpp/defactored1/README create mode 100644 Tennis/cpp/defactored1/Tennis.cc create mode 100755 Tennis/cpp/defactored1/run-endless.sh create mode 100755 Tennis/cpp/defactored1/run-once.sh create mode 100644 Tennis/cpp/defactored2/Makefile create mode 100644 Tennis/cpp/defactored2/README create mode 100644 Tennis/cpp/defactored2/Tennis.cc create mode 100755 Tennis/cpp/defactored2/run-endless.sh create mode 100755 Tennis/cpp/defactored2/run-once.sh create mode 100644 Tennis/cpp/defactored3/Makefile create mode 100644 Tennis/cpp/defactored3/README create mode 100644 Tennis/cpp/defactored3/Tennis.cc create mode 100755 Tennis/cpp/defactored3/run-endless.sh create mode 100755 Tennis/cpp/defactored3/run-once.sh create mode 100644 Tennis/cpp/generate_tests.py create mode 100644 Tennis/cpp/starting/Makefile create mode 100644 Tennis/cpp/starting/README create mode 100644 Tennis/cpp/starting/Tennis.cc create mode 100755 Tennis/cpp/starting/run-endless.sh create mode 100755 Tennis/cpp/starting/run-once.sh diff --git a/Tennis/cpp/defactored1/Makefile b/Tennis/cpp/defactored1/Makefile new file mode 100644 index 00000000..a97fcd8b --- /dev/null +++ b/Tennis/cpp/defactored1/Makefile @@ -0,0 +1,75 @@ +# Makefile for building the kata file with the Google Testing Framework +# +# SYNOPSIS: +# +# make [all] - makes everything. +# make TARGET - makes the given target. +# make clean - removes all files generated by make. + +# Please tweak the following variable definitions as needed by your +# project, except GTEST_HEADERS, which you can use in your own targets +# but shouldn't modify. + +# Points to the root of Google Test, relative to where this file is. +# Remember to tweak this if you move this file. +GTEST_DIR = gtest + +# Where to find user code. +USER_DIR = . + +# Flags passed to the preprocessor. +CPPFLAGS += -I$(GTEST_DIR)/include + +# Flags passed to the C++ compiler. +CXXFLAGS += -g -Wall -Wextra + +# All tests produced by this Makefile. Remember to add new tests you +# created to the list. +TESTS = Tennis + +# All Google Test headers. Usually you shouldn't change this +# definition. +GTEST_HEADERS = $(GTEST_DIR)/include/gtest/*.h \ + $(GTEST_DIR)/include/gtest/internal/*.h + +# House-keeping build targets. + +all : $(TESTS) + +clean : + rm -f $(TESTS) gtest.a gtest_main.a *.o + +# Builds gtest.a and gtest_main.a. + +# Usually you shouldn't tweak such internal variables, indicated by a +# trailing _. +GTEST_SRCS_ = $(GTEST_DIR)/src/*.cc $(GTEST_DIR)/src/*.h $(GTEST_HEADERS) + +# For simplicity and to avoid depending on Google Test's +# implementation details, the dependencies specified below are +# conservative and not optimized. This is fine as Google Test +# compiles fast and for ordinary users its source rarely changes. +gtest-all.o : $(GTEST_SRCS_) + $(CXX) $(CPPFLAGS) -I$(GTEST_DIR) $(CXXFLAGS) -c \ + $(GTEST_DIR)/src/gtest-all.cc + +gtest_main.o : $(GTEST_SRCS_) + $(CXX) $(CPPFLAGS) -I$(GTEST_DIR) $(CXXFLAGS) -c \ + $(GTEST_DIR)/src/gtest_main.cc + +gtest.a : gtest-all.o + $(AR) $(ARFLAGS) $@ $^ + +gtest_main.a : gtest-all.o gtest_main.o + $(AR) $(ARFLAGS) $@ $^ + +# Builds a sample test. A test should link with either gtest.a or +# gtest_main.a, depending on whether it defines its own main() +# function. + +Tennis.o : $(USER_DIR)/Tennis.cc \ + $(GTEST_HEADERS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/Tennis.cc + +Tennis : Tennis.o gtest_main.a + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@ diff --git a/Tennis/cpp/defactored1/README b/Tennis/cpp/defactored1/README new file mode 100644 index 00000000..59cd984e --- /dev/null +++ b/Tennis/cpp/defactored1/README @@ -0,0 +1,14 @@ +These files were created: + README is what you are currently reading + run-once.sh runs your tests once + run-endless.sh runs your tests endlessly via run-once.sh + +Run run-endless.sh and start your kata. (On Mac/Linux you have to call ./run-endless.sh.) + +Assumptions: + - make and a C++ compiler (like gcc) is installed on your system and is in the PATH + - The GTest framework is in the directory gtest. + - If your IDE does the compilation and linking, you should remove the first 3 lines + in the run-once.sh file. + +The support for C++/GTest was contributed by Stefan Roock. diff --git a/Tennis/cpp/defactored1/Tennis.cc b/Tennis/cpp/defactored1/Tennis.cc new file mode 100644 index 00000000..b2737310 --- /dev/null +++ b/Tennis/cpp/defactored1/Tennis.cc @@ -0,0 +1,227 @@ +#include + +const std::string tennis_score(int p1Score, int p2Score) { + std::string score = ""; + int tempScore=0; + if (p1Score==p2Score) + { + switch (p1Score) + { + case 0: + score = "Love-All"; + break; + case 1: + score = "Fifteen-All"; + break; + case 2: + score = "Thirty-All"; + break; + case 3: + score = "Forty-All"; + break; + default: + score = "Deuce"; + break; + + } + } + else if (p1Score>=4 || p2Score>=4) + { + int minusResult = p1Score-p2Score; + if (minusResult==1) score ="Advantage player1"; + else if (minusResult ==-1) score ="Advantage player2"; + else if (minusResult>=2) score = "Win for player1"; + else score ="Win for player2"; + } + else + { + for (int i=1; i<3; i++) + { + if (i==1) tempScore = p1Score; + else { score+="-"; tempScore = p2Score;} + switch(tempScore) + { + case 0: + score+="Love"; + break; + case 1: + score+="Fifteen"; + break; + case 2: + score+="Thirty"; + break; + case 3: + score+="Forty"; + break; + } + } + } + return score; + +} + +TEST(TennisTest, LoveAll_0_0) { + EXPECT_EQ("Love-All", tennis_score(0, 0)); +} + + +TEST(TennisTest, FifteenAll_1_1) { + EXPECT_EQ("Fifteen-All", tennis_score(1, 1)); +} + + +TEST(TennisTest, ThirtyAll_2_2) { + EXPECT_EQ("Thirty-All", tennis_score(2, 2)); +} + + +TEST(TennisTest, FortyAll_3_3) { + EXPECT_EQ("Forty-All", tennis_score(3, 3)); +} + + +TEST(TennisTest, Deuce_4_4) { + EXPECT_EQ("Deuce", tennis_score(4, 4)); +} + + +TEST(TennisTest, FifteenLove_1_0) { + EXPECT_EQ("Fifteen-Love", tennis_score(1, 0)); +} + + +TEST(TennisTest, LoveFifteen_0_1) { + EXPECT_EQ("Love-Fifteen", tennis_score(0, 1)); +} + + +TEST(TennisTest, ThirtyLove_2_0) { + EXPECT_EQ("Thirty-Love", tennis_score(2, 0)); +} + + +TEST(TennisTest, LoveThirty_0_2) { + EXPECT_EQ("Love-Thirty", tennis_score(0, 2)); +} + + +TEST(TennisTest, FortyLove_3_0) { + EXPECT_EQ("Forty-Love", tennis_score(3, 0)); +} + + +TEST(TennisTest, LoveForty_0_3) { + EXPECT_EQ("Love-Forty", tennis_score(0, 3)); +} + + +TEST(TennisTest, Winforplayer1_4_0) { + EXPECT_EQ("Win for player1", tennis_score(4, 0)); +} + + +TEST(TennisTest, Winforplayer2_0_4) { + EXPECT_EQ("Win for player2", tennis_score(0, 4)); +} + + +TEST(TennisTest, ThirtyFifteen_2_1) { + EXPECT_EQ("Thirty-Fifteen", tennis_score(2, 1)); +} + + +TEST(TennisTest, FifteenThirty_1_2) { + EXPECT_EQ("Fifteen-Thirty", tennis_score(1, 2)); +} + + +TEST(TennisTest, FortyFifteen_3_1) { + EXPECT_EQ("Forty-Fifteen", tennis_score(3, 1)); +} + + +TEST(TennisTest, FifteenForty_1_3) { + EXPECT_EQ("Fifteen-Forty", tennis_score(1, 3)); +} + + +TEST(TennisTest, Winforplayer1_4_1) { + EXPECT_EQ("Win for player1", tennis_score(4, 1)); +} + + +TEST(TennisTest, Winforplayer2_1_4) { + EXPECT_EQ("Win for player2", tennis_score(1, 4)); +} + + +TEST(TennisTest, FortyThirty_3_2) { + EXPECT_EQ("Forty-Thirty", tennis_score(3, 2)); +} + + +TEST(TennisTest, ThirtyForty_2_3) { + EXPECT_EQ("Thirty-Forty", tennis_score(2, 3)); +} + + +TEST(TennisTest, Winforplayer1_4_2) { + EXPECT_EQ("Win for player1", tennis_score(4, 2)); +} + + +TEST(TennisTest, Winforplayer2_2_4) { + EXPECT_EQ("Win for player2", tennis_score(2, 4)); +} + + +TEST(TennisTest, Advantageplayer1_4_3) { + EXPECT_EQ("Advantage player1", tennis_score(4, 3)); +} + + +TEST(TennisTest, Advantageplayer2_3_4) { + EXPECT_EQ("Advantage player2", tennis_score(3, 4)); +} + + +TEST(TennisTest, Advantageplayer1_5_4) { + EXPECT_EQ("Advantage player1", tennis_score(5, 4)); +} + + +TEST(TennisTest, Advantageplayer2_4_5) { + EXPECT_EQ("Advantage player2", tennis_score(4, 5)); +} + + +TEST(TennisTest, Advantageplayer1_15_14) { + EXPECT_EQ("Advantage player1", tennis_score(15, 14)); +} + + +TEST(TennisTest, Advantageplayer2_14_15) { + EXPECT_EQ("Advantage player2", tennis_score(14, 15)); +} + + +TEST(TennisTest, Winforplayer1_6_4) { + EXPECT_EQ("Win for player1", tennis_score(6, 4)); +} + + +TEST(TennisTest, Winforplayer2_4_6) { + EXPECT_EQ("Win for player2", tennis_score(4, 6)); +} + + +TEST(TennisTest, Winforplayer1_16_14) { + EXPECT_EQ("Win for player1", tennis_score(16, 14)); +} + + +TEST(TennisTest, Winforplayer2_14_16) { + EXPECT_EQ("Win for player2", tennis_score(14, 16)); +} + + diff --git a/Tennis/cpp/defactored1/run-endless.sh b/Tennis/cpp/defactored1/run-endless.sh new file mode 100755 index 00000000..ad449aa3 --- /dev/null +++ b/Tennis/cpp/defactored1/run-endless.sh @@ -0,0 +1 @@ +codersdojo start run-once.sh diff --git a/Tennis/cpp/defactored1/run-once.sh b/Tennis/cpp/defactored1/run-once.sh new file mode 100755 index 00000000..1b1bffef --- /dev/null +++ b/Tennis/cpp/defactored1/run-once.sh @@ -0,0 +1,4 @@ +rm Tennis +rm Tennis.o +make +./Tennis \ No newline at end of file diff --git a/Tennis/cpp/defactored2/Makefile b/Tennis/cpp/defactored2/Makefile new file mode 100644 index 00000000..a97fcd8b --- /dev/null +++ b/Tennis/cpp/defactored2/Makefile @@ -0,0 +1,75 @@ +# Makefile for building the kata file with the Google Testing Framework +# +# SYNOPSIS: +# +# make [all] - makes everything. +# make TARGET - makes the given target. +# make clean - removes all files generated by make. + +# Please tweak the following variable definitions as needed by your +# project, except GTEST_HEADERS, which you can use in your own targets +# but shouldn't modify. + +# Points to the root of Google Test, relative to where this file is. +# Remember to tweak this if you move this file. +GTEST_DIR = gtest + +# Where to find user code. +USER_DIR = . + +# Flags passed to the preprocessor. +CPPFLAGS += -I$(GTEST_DIR)/include + +# Flags passed to the C++ compiler. +CXXFLAGS += -g -Wall -Wextra + +# All tests produced by this Makefile. Remember to add new tests you +# created to the list. +TESTS = Tennis + +# All Google Test headers. Usually you shouldn't change this +# definition. +GTEST_HEADERS = $(GTEST_DIR)/include/gtest/*.h \ + $(GTEST_DIR)/include/gtest/internal/*.h + +# House-keeping build targets. + +all : $(TESTS) + +clean : + rm -f $(TESTS) gtest.a gtest_main.a *.o + +# Builds gtest.a and gtest_main.a. + +# Usually you shouldn't tweak such internal variables, indicated by a +# trailing _. +GTEST_SRCS_ = $(GTEST_DIR)/src/*.cc $(GTEST_DIR)/src/*.h $(GTEST_HEADERS) + +# For simplicity and to avoid depending on Google Test's +# implementation details, the dependencies specified below are +# conservative and not optimized. This is fine as Google Test +# compiles fast and for ordinary users its source rarely changes. +gtest-all.o : $(GTEST_SRCS_) + $(CXX) $(CPPFLAGS) -I$(GTEST_DIR) $(CXXFLAGS) -c \ + $(GTEST_DIR)/src/gtest-all.cc + +gtest_main.o : $(GTEST_SRCS_) + $(CXX) $(CPPFLAGS) -I$(GTEST_DIR) $(CXXFLAGS) -c \ + $(GTEST_DIR)/src/gtest_main.cc + +gtest.a : gtest-all.o + $(AR) $(ARFLAGS) $@ $^ + +gtest_main.a : gtest-all.o gtest_main.o + $(AR) $(ARFLAGS) $@ $^ + +# Builds a sample test. A test should link with either gtest.a or +# gtest_main.a, depending on whether it defines its own main() +# function. + +Tennis.o : $(USER_DIR)/Tennis.cc \ + $(GTEST_HEADERS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/Tennis.cc + +Tennis : Tennis.o gtest_main.a + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@ diff --git a/Tennis/cpp/defactored2/README b/Tennis/cpp/defactored2/README new file mode 100644 index 00000000..59cd984e --- /dev/null +++ b/Tennis/cpp/defactored2/README @@ -0,0 +1,14 @@ +These files were created: + README is what you are currently reading + run-once.sh runs your tests once + run-endless.sh runs your tests endlessly via run-once.sh + +Run run-endless.sh and start your kata. (On Mac/Linux you have to call ./run-endless.sh.) + +Assumptions: + - make and a C++ compiler (like gcc) is installed on your system and is in the PATH + - The GTest framework is in the directory gtest. + - If your IDE does the compilation and linking, you should remove the first 3 lines + in the run-once.sh file. + +The support for C++/GTest was contributed by Stefan Roock. diff --git a/Tennis/cpp/defactored2/Tennis.cc b/Tennis/cpp/defactored2/Tennis.cc new file mode 100644 index 00000000..fe7e480f --- /dev/null +++ b/Tennis/cpp/defactored2/Tennis.cc @@ -0,0 +1,258 @@ +#include + +const std::string tennis_score(int p1Score, int p2Score) { + std::string score = ""; + std::string P1res = ""; + std::string P2res = ""; + if (p1Score == p2Score && p1Score < 4) + { + if (p1Score==0) + score = "Love"; + if (p1Score==1) + score = "Fifteen"; + if (p1Score==2) + score = "Thirty"; + if (p1Score==3) + score = "Forty"; + score += "-All"; + } + if (p1Score==p2Score && p1Score>3) + score = "Deuce"; + + if (p1Score > 0 && p2Score==0) + { + if (p1Score==1) + P1res = "Fifteen"; + if (p1Score==2) + P1res = "Thirty"; + if (p1Score==3) + P1res = "Forty"; + + P2res = "Love"; + score = P1res + "-" + P2res; + } + if (p2Score > 0 && p1Score==0) + { + if (p2Score==1) + P2res = "Fifteen"; + if (p2Score==2) + P2res = "Thirty"; + if (p2Score==3) + P2res = "Forty"; + + P1res = "Love"; + score = P1res + "-" + P2res; + } + + if (p1Score>p2Score && p1Score < 4) + { + if (p1Score==2) + P1res="Thirty"; + if (p1Score==3) + P1res="Forty"; + if (p2Score==1) + P2res="Fifteen"; + if (p2Score==2) + P2res="Thirty"; + score = P1res + "-" + P2res; + } + if (p2Score>p1Score && p2Score < 4) + { + if (p2Score==2) + P2res="Thirty"; + if (p2Score==3) + P2res="Forty"; + if (p1Score==1) + P1res="Fifteen"; + if (p1Score==2) + P1res="Thirty"; + score = P1res + "-" + P2res; + } + + if (p1Score > p2Score && p2Score >= 3) + { + score = "Advantage player1"; + } + + if (p2Score > p1Score && p1Score >= 3) + { + score = "Advantage player2"; + } + + if (p1Score>=4 && p2Score>=0 && (p1Score-p2Score)>=2) + { + score = "Win for player1"; + } + if (p2Score>=4 && p1Score>=0 && (p2Score-p1Score)>=2) + { + score = "Win for player2"; + } + return score; + +} + +TEST(TennisTest, LoveAll_0_0) { + EXPECT_EQ("Love-All", tennis_score(0, 0)); +} + + +TEST(TennisTest, FifteenAll_1_1) { + EXPECT_EQ("Fifteen-All", tennis_score(1, 1)); +} + + +TEST(TennisTest, ThirtyAll_2_2) { + EXPECT_EQ("Thirty-All", tennis_score(2, 2)); +} + + +TEST(TennisTest, FortyAll_3_3) { + EXPECT_EQ("Forty-All", tennis_score(3, 3)); +} + + +TEST(TennisTest, Deuce_4_4) { + EXPECT_EQ("Deuce", tennis_score(4, 4)); +} + + +TEST(TennisTest, FifteenLove_1_0) { + EXPECT_EQ("Fifteen-Love", tennis_score(1, 0)); +} + + +TEST(TennisTest, LoveFifteen_0_1) { + EXPECT_EQ("Love-Fifteen", tennis_score(0, 1)); +} + + +TEST(TennisTest, ThirtyLove_2_0) { + EXPECT_EQ("Thirty-Love", tennis_score(2, 0)); +} + + +TEST(TennisTest, LoveThirty_0_2) { + EXPECT_EQ("Love-Thirty", tennis_score(0, 2)); +} + + +TEST(TennisTest, FortyLove_3_0) { + EXPECT_EQ("Forty-Love", tennis_score(3, 0)); +} + + +TEST(TennisTest, LoveForty_0_3) { + EXPECT_EQ("Love-Forty", tennis_score(0, 3)); +} + + +TEST(TennisTest, Winforplayer1_4_0) { + EXPECT_EQ("Win for player1", tennis_score(4, 0)); +} + + +TEST(TennisTest, Winforplayer2_0_4) { + EXPECT_EQ("Win for player2", tennis_score(0, 4)); +} + + +TEST(TennisTest, ThirtyFifteen_2_1) { + EXPECT_EQ("Thirty-Fifteen", tennis_score(2, 1)); +} + + +TEST(TennisTest, FifteenThirty_1_2) { + EXPECT_EQ("Fifteen-Thirty", tennis_score(1, 2)); +} + + +TEST(TennisTest, FortyFifteen_3_1) { + EXPECT_EQ("Forty-Fifteen", tennis_score(3, 1)); +} + + +TEST(TennisTest, FifteenForty_1_3) { + EXPECT_EQ("Fifteen-Forty", tennis_score(1, 3)); +} + + +TEST(TennisTest, Winforplayer1_4_1) { + EXPECT_EQ("Win for player1", tennis_score(4, 1)); +} + + +TEST(TennisTest, Winforplayer2_1_4) { + EXPECT_EQ("Win for player2", tennis_score(1, 4)); +} + + +TEST(TennisTest, FortyThirty_3_2) { + EXPECT_EQ("Forty-Thirty", tennis_score(3, 2)); +} + + +TEST(TennisTest, ThirtyForty_2_3) { + EXPECT_EQ("Thirty-Forty", tennis_score(2, 3)); +} + + +TEST(TennisTest, Winforplayer1_4_2) { + EXPECT_EQ("Win for player1", tennis_score(4, 2)); +} + + +TEST(TennisTest, Winforplayer2_2_4) { + EXPECT_EQ("Win for player2", tennis_score(2, 4)); +} + + +TEST(TennisTest, Advantageplayer1_4_3) { + EXPECT_EQ("Advantage player1", tennis_score(4, 3)); +} + + +TEST(TennisTest, Advantageplayer2_3_4) { + EXPECT_EQ("Advantage player2", tennis_score(3, 4)); +} + + +TEST(TennisTest, Advantageplayer1_5_4) { + EXPECT_EQ("Advantage player1", tennis_score(5, 4)); +} + + +TEST(TennisTest, Advantageplayer2_4_5) { + EXPECT_EQ("Advantage player2", tennis_score(4, 5)); +} + + +TEST(TennisTest, Advantageplayer1_15_14) { + EXPECT_EQ("Advantage player1", tennis_score(15, 14)); +} + + +TEST(TennisTest, Advantageplayer2_14_15) { + EXPECT_EQ("Advantage player2", tennis_score(14, 15)); +} + + +TEST(TennisTest, Winforplayer1_6_4) { + EXPECT_EQ("Win for player1", tennis_score(6, 4)); +} + + +TEST(TennisTest, Winforplayer2_4_6) { + EXPECT_EQ("Win for player2", tennis_score(4, 6)); +} + + +TEST(TennisTest, Winforplayer1_16_14) { + EXPECT_EQ("Win for player1", tennis_score(16, 14)); +} + + +TEST(TennisTest, Winforplayer2_14_16) { + EXPECT_EQ("Win for player2", tennis_score(14, 16)); +} + + diff --git a/Tennis/cpp/defactored2/run-endless.sh b/Tennis/cpp/defactored2/run-endless.sh new file mode 100755 index 00000000..ad449aa3 --- /dev/null +++ b/Tennis/cpp/defactored2/run-endless.sh @@ -0,0 +1 @@ +codersdojo start run-once.sh diff --git a/Tennis/cpp/defactored2/run-once.sh b/Tennis/cpp/defactored2/run-once.sh new file mode 100755 index 00000000..1b1bffef --- /dev/null +++ b/Tennis/cpp/defactored2/run-once.sh @@ -0,0 +1,4 @@ +rm Tennis +rm Tennis.o +make +./Tennis \ No newline at end of file diff --git a/Tennis/cpp/defactored3/Makefile b/Tennis/cpp/defactored3/Makefile new file mode 100644 index 00000000..a97fcd8b --- /dev/null +++ b/Tennis/cpp/defactored3/Makefile @@ -0,0 +1,75 @@ +# Makefile for building the kata file with the Google Testing Framework +# +# SYNOPSIS: +# +# make [all] - makes everything. +# make TARGET - makes the given target. +# make clean - removes all files generated by make. + +# Please tweak the following variable definitions as needed by your +# project, except GTEST_HEADERS, which you can use in your own targets +# but shouldn't modify. + +# Points to the root of Google Test, relative to where this file is. +# Remember to tweak this if you move this file. +GTEST_DIR = gtest + +# Where to find user code. +USER_DIR = . + +# Flags passed to the preprocessor. +CPPFLAGS += -I$(GTEST_DIR)/include + +# Flags passed to the C++ compiler. +CXXFLAGS += -g -Wall -Wextra + +# All tests produced by this Makefile. Remember to add new tests you +# created to the list. +TESTS = Tennis + +# All Google Test headers. Usually you shouldn't change this +# definition. +GTEST_HEADERS = $(GTEST_DIR)/include/gtest/*.h \ + $(GTEST_DIR)/include/gtest/internal/*.h + +# House-keeping build targets. + +all : $(TESTS) + +clean : + rm -f $(TESTS) gtest.a gtest_main.a *.o + +# Builds gtest.a and gtest_main.a. + +# Usually you shouldn't tweak such internal variables, indicated by a +# trailing _. +GTEST_SRCS_ = $(GTEST_DIR)/src/*.cc $(GTEST_DIR)/src/*.h $(GTEST_HEADERS) + +# For simplicity and to avoid depending on Google Test's +# implementation details, the dependencies specified below are +# conservative and not optimized. This is fine as Google Test +# compiles fast and for ordinary users its source rarely changes. +gtest-all.o : $(GTEST_SRCS_) + $(CXX) $(CPPFLAGS) -I$(GTEST_DIR) $(CXXFLAGS) -c \ + $(GTEST_DIR)/src/gtest-all.cc + +gtest_main.o : $(GTEST_SRCS_) + $(CXX) $(CPPFLAGS) -I$(GTEST_DIR) $(CXXFLAGS) -c \ + $(GTEST_DIR)/src/gtest_main.cc + +gtest.a : gtest-all.o + $(AR) $(ARFLAGS) $@ $^ + +gtest_main.a : gtest-all.o gtest_main.o + $(AR) $(ARFLAGS) $@ $^ + +# Builds a sample test. A test should link with either gtest.a or +# gtest_main.a, depending on whether it defines its own main() +# function. + +Tennis.o : $(USER_DIR)/Tennis.cc \ + $(GTEST_HEADERS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/Tennis.cc + +Tennis : Tennis.o gtest_main.a + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@ diff --git a/Tennis/cpp/defactored3/README b/Tennis/cpp/defactored3/README new file mode 100644 index 00000000..59cd984e --- /dev/null +++ b/Tennis/cpp/defactored3/README @@ -0,0 +1,14 @@ +These files were created: + README is what you are currently reading + run-once.sh runs your tests once + run-endless.sh runs your tests endlessly via run-once.sh + +Run run-endless.sh and start your kata. (On Mac/Linux you have to call ./run-endless.sh.) + +Assumptions: + - make and a C++ compiler (like gcc) is installed on your system and is in the PATH + - The GTest framework is in the directory gtest. + - If your IDE does the compilation and linking, you should remove the first 3 lines + in the run-once.sh file. + +The support for C++/GTest was contributed by Stefan Roock. diff --git a/Tennis/cpp/defactored3/Tennis.cc b/Tennis/cpp/defactored3/Tennis.cc new file mode 100644 index 00000000..15da13ac --- /dev/null +++ b/Tennis/cpp/defactored3/Tennis.cc @@ -0,0 +1,183 @@ +#include + +const std::string tennis_score(int p1, int p2) { + std::string s; + std::string p1N = "player1"; + std::string p2N = "player2"; + if (p1 < 4 && p2 < 4) { + std::string p[4] = {"Love", "Fifteen", "Thirty", "Forty"}; + s = p[p1]; + return (p1 == p2) ? s + "-All" : s + "-" + p[p2]; + } else { + if (p1 == p2) + return "Deuce"; + s = p1 > p2 ? p1N : p2N; + return ((p1-p2)*(p1-p2) == 1) ? "Advantage " + s : "Win for " + s; + } +} + +TEST(TennisTest, LoveAll_0_0) { + EXPECT_EQ("Love-All", tennis_score(0, 0)); +} + + +TEST(TennisTest, FifteenAll_1_1) { + EXPECT_EQ("Fifteen-All", tennis_score(1, 1)); +} + + +TEST(TennisTest, ThirtyAll_2_2) { + EXPECT_EQ("Thirty-All", tennis_score(2, 2)); +} + + +TEST(TennisTest, FortyAll_3_3) { + EXPECT_EQ("Forty-All", tennis_score(3, 3)); +} + + +TEST(TennisTest, Deuce_4_4) { + EXPECT_EQ("Deuce", tennis_score(4, 4)); +} + + +TEST(TennisTest, FifteenLove_1_0) { + EXPECT_EQ("Fifteen-Love", tennis_score(1, 0)); +} + + +TEST(TennisTest, LoveFifteen_0_1) { + EXPECT_EQ("Love-Fifteen", tennis_score(0, 1)); +} + + +TEST(TennisTest, ThirtyLove_2_0) { + EXPECT_EQ("Thirty-Love", tennis_score(2, 0)); +} + + +TEST(TennisTest, LoveThirty_0_2) { + EXPECT_EQ("Love-Thirty", tennis_score(0, 2)); +} + + +TEST(TennisTest, FortyLove_3_0) { + EXPECT_EQ("Forty-Love", tennis_score(3, 0)); +} + + +TEST(TennisTest, LoveForty_0_3) { + EXPECT_EQ("Love-Forty", tennis_score(0, 3)); +} + + +TEST(TennisTest, Winforplayer1_4_0) { + EXPECT_EQ("Win for player1", tennis_score(4, 0)); +} + + +TEST(TennisTest, Winforplayer2_0_4) { + EXPECT_EQ("Win for player2", tennis_score(0, 4)); +} + + +TEST(TennisTest, ThirtyFifteen_2_1) { + EXPECT_EQ("Thirty-Fifteen", tennis_score(2, 1)); +} + + +TEST(TennisTest, FifteenThirty_1_2) { + EXPECT_EQ("Fifteen-Thirty", tennis_score(1, 2)); +} + + +TEST(TennisTest, FortyFifteen_3_1) { + EXPECT_EQ("Forty-Fifteen", tennis_score(3, 1)); +} + + +TEST(TennisTest, FifteenForty_1_3) { + EXPECT_EQ("Fifteen-Forty", tennis_score(1, 3)); +} + + +TEST(TennisTest, Winforplayer1_4_1) { + EXPECT_EQ("Win for player1", tennis_score(4, 1)); +} + + +TEST(TennisTest, Winforplayer2_1_4) { + EXPECT_EQ("Win for player2", tennis_score(1, 4)); +} + + +TEST(TennisTest, FortyThirty_3_2) { + EXPECT_EQ("Forty-Thirty", tennis_score(3, 2)); +} + + +TEST(TennisTest, ThirtyForty_2_3) { + EXPECT_EQ("Thirty-Forty", tennis_score(2, 3)); +} + + +TEST(TennisTest, Winforplayer1_4_2) { + EXPECT_EQ("Win for player1", tennis_score(4, 2)); +} + + +TEST(TennisTest, Winforplayer2_2_4) { + EXPECT_EQ("Win for player2", tennis_score(2, 4)); +} + + +TEST(TennisTest, Advantageplayer1_4_3) { + EXPECT_EQ("Advantage player1", tennis_score(4, 3)); +} + + +TEST(TennisTest, Advantageplayer2_3_4) { + EXPECT_EQ("Advantage player2", tennis_score(3, 4)); +} + + +TEST(TennisTest, Advantageplayer1_5_4) { + EXPECT_EQ("Advantage player1", tennis_score(5, 4)); +} + + +TEST(TennisTest, Advantageplayer2_4_5) { + EXPECT_EQ("Advantage player2", tennis_score(4, 5)); +} + + +TEST(TennisTest, Advantageplayer1_15_14) { + EXPECT_EQ("Advantage player1", tennis_score(15, 14)); +} + + +TEST(TennisTest, Advantageplayer2_14_15) { + EXPECT_EQ("Advantage player2", tennis_score(14, 15)); +} + + +TEST(TennisTest, Winforplayer1_6_4) { + EXPECT_EQ("Win for player1", tennis_score(6, 4)); +} + + +TEST(TennisTest, Winforplayer2_4_6) { + EXPECT_EQ("Win for player2", tennis_score(4, 6)); +} + + +TEST(TennisTest, Winforplayer1_16_14) { + EXPECT_EQ("Win for player1", tennis_score(16, 14)); +} + + +TEST(TennisTest, Winforplayer2_14_16) { + EXPECT_EQ("Win for player2", tennis_score(14, 16)); +} + + diff --git a/Tennis/cpp/defactored3/run-endless.sh b/Tennis/cpp/defactored3/run-endless.sh new file mode 100755 index 00000000..ad449aa3 --- /dev/null +++ b/Tennis/cpp/defactored3/run-endless.sh @@ -0,0 +1 @@ +codersdojo start run-once.sh diff --git a/Tennis/cpp/defactored3/run-once.sh b/Tennis/cpp/defactored3/run-once.sh new file mode 100755 index 00000000..1b1bffef --- /dev/null +++ b/Tennis/cpp/defactored3/run-once.sh @@ -0,0 +1,4 @@ +rm Tennis +rm Tennis.o +make +./Tennis \ No newline at end of file diff --git a/Tennis/cpp/generate_tests.py b/Tennis/cpp/generate_tests.py new file mode 100644 index 00000000..2e645fde --- /dev/null +++ b/Tennis/cpp/generate_tests.py @@ -0,0 +1,55 @@ + +template = """\ +TEST(TennisTest, %(testcase_name)s) { + EXPECT_EQ("%(score)s", tennis_score(%(p1Points)s, %(p2Points)s)); +} +""" + +test_cases = [dict(p1Points=0, p2Points=0, score="Love-All"), + dict(p1Points=1, p2Points=1, score="Fifteen-All"), + dict(p1Points=2, p2Points=2, score="Thirty-All"), + dict(p1Points=3, p2Points=3, score="Forty-All"), + dict(p1Points=4, p2Points=4, score="Deuce"), + + dict(p1Points=1, p2Points=0, score="Fifteen-Love"), + dict(p1Points=0, p2Points=1, score="Love-Fifteen"), + dict(p1Points=2, p2Points=0, score="Thirty-Love"), + dict(p1Points=0, p2Points=2, score="Love-Thirty"), + dict(p1Points=3, p2Points=0, score="Forty-Love"), + dict(p1Points=0, p2Points=3, score="Love-Forty"), + dict(p1Points=4, p2Points=0, score="Win for player1"), + dict(p1Points=0, p2Points=4, score="Win for player2"), + + dict(p1Points=2, p2Points=1, score="Thirty-Fifteen"), + dict(p1Points=1, p2Points=2, score="Fifteen-Thirty"), + dict(p1Points=3, p2Points=1, score="Forty-Fifteen"), + dict(p1Points=1, p2Points=3, score="Fifteen-Forty"), + dict(p1Points=4, p2Points=1, score="Win for player1"), + dict(p1Points=1, p2Points=4, score="Win for player2"), + + dict(p1Points=3, p2Points=2, score="Forty-Thirty"), + dict(p1Points=2, p2Points=3, score="Thirty-Forty"), + dict(p1Points=4, p2Points=2, score="Win for player1"), + dict(p1Points=2, p2Points=4, score="Win for player2"), + + dict(p1Points=4, p2Points=3, score="Advantage player1"), + dict(p1Points=3, p2Points=4, score="Advantage player2"), + dict(p1Points=5, p2Points=4, score="Advantage player1"), + dict(p1Points=4, p2Points=5, score="Advantage player2"), + dict(p1Points=15, p2Points=14, score="Advantage player1"), + dict(p1Points=14, p2Points=15, score="Advantage player2"), + + dict(p1Points=6, p2Points=4, score="Win for player1"), + dict(p1Points=4, p2Points=6, score="Win for player2"), + dict(p1Points=16, p2Points=14, score="Win for player1"), + dict(p1Points=14, p2Points=16, score="Win for player2"), + ] + +for test in test_cases: + cleaned = test["score"] + cleaned = cleaned.replace("-", "") + cleaned = cleaned.replace(" ", "") + test["cleaned"] = cleaned + test["testcase_name"] = "%(cleaned)s_%(p1Points)s_%(p2Points)s" % test + print template % test + print \ No newline at end of file diff --git a/Tennis/cpp/starting/Makefile b/Tennis/cpp/starting/Makefile new file mode 100644 index 00000000..a97fcd8b --- /dev/null +++ b/Tennis/cpp/starting/Makefile @@ -0,0 +1,75 @@ +# Makefile for building the kata file with the Google Testing Framework +# +# SYNOPSIS: +# +# make [all] - makes everything. +# make TARGET - makes the given target. +# make clean - removes all files generated by make. + +# Please tweak the following variable definitions as needed by your +# project, except GTEST_HEADERS, which you can use in your own targets +# but shouldn't modify. + +# Points to the root of Google Test, relative to where this file is. +# Remember to tweak this if you move this file. +GTEST_DIR = gtest + +# Where to find user code. +USER_DIR = . + +# Flags passed to the preprocessor. +CPPFLAGS += -I$(GTEST_DIR)/include + +# Flags passed to the C++ compiler. +CXXFLAGS += -g -Wall -Wextra + +# All tests produced by this Makefile. Remember to add new tests you +# created to the list. +TESTS = Tennis + +# All Google Test headers. Usually you shouldn't change this +# definition. +GTEST_HEADERS = $(GTEST_DIR)/include/gtest/*.h \ + $(GTEST_DIR)/include/gtest/internal/*.h + +# House-keeping build targets. + +all : $(TESTS) + +clean : + rm -f $(TESTS) gtest.a gtest_main.a *.o + +# Builds gtest.a and gtest_main.a. + +# Usually you shouldn't tweak such internal variables, indicated by a +# trailing _. +GTEST_SRCS_ = $(GTEST_DIR)/src/*.cc $(GTEST_DIR)/src/*.h $(GTEST_HEADERS) + +# For simplicity and to avoid depending on Google Test's +# implementation details, the dependencies specified below are +# conservative and not optimized. This is fine as Google Test +# compiles fast and for ordinary users its source rarely changes. +gtest-all.o : $(GTEST_SRCS_) + $(CXX) $(CPPFLAGS) -I$(GTEST_DIR) $(CXXFLAGS) -c \ + $(GTEST_DIR)/src/gtest-all.cc + +gtest_main.o : $(GTEST_SRCS_) + $(CXX) $(CPPFLAGS) -I$(GTEST_DIR) $(CXXFLAGS) -c \ + $(GTEST_DIR)/src/gtest_main.cc + +gtest.a : gtest-all.o + $(AR) $(ARFLAGS) $@ $^ + +gtest_main.a : gtest-all.o gtest_main.o + $(AR) $(ARFLAGS) $@ $^ + +# Builds a sample test. A test should link with either gtest.a or +# gtest_main.a, depending on whether it defines its own main() +# function. + +Tennis.o : $(USER_DIR)/Tennis.cc \ + $(GTEST_HEADERS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/Tennis.cc + +Tennis : Tennis.o gtest_main.a + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@ diff --git a/Tennis/cpp/starting/README b/Tennis/cpp/starting/README new file mode 100644 index 00000000..59cd984e --- /dev/null +++ b/Tennis/cpp/starting/README @@ -0,0 +1,14 @@ +These files were created: + README is what you are currently reading + run-once.sh runs your tests once + run-endless.sh runs your tests endlessly via run-once.sh + +Run run-endless.sh and start your kata. (On Mac/Linux you have to call ./run-endless.sh.) + +Assumptions: + - make and a C++ compiler (like gcc) is installed on your system and is in the PATH + - The GTest framework is in the directory gtest. + - If your IDE does the compilation and linking, you should remove the first 3 lines + in the run-once.sh file. + +The support for C++/GTest was contributed by Stefan Roock. diff --git a/Tennis/cpp/starting/Tennis.cc b/Tennis/cpp/starting/Tennis.cc new file mode 100644 index 00000000..90fac43c --- /dev/null +++ b/Tennis/cpp/starting/Tennis.cc @@ -0,0 +1,171 @@ +#include + +const std::string tennis_score(int p1Score, int p2Score) { + return "foo"; +} + +TEST(TennisTest, LoveAll_0_0) { + EXPECT_EQ("Love-All", tennis_score(0, 0)); +} + + +TEST(TennisTest, FifteenAll_1_1) { + EXPECT_EQ("Fifteen-All", tennis_score(1, 1)); +} + + +TEST(TennisTest, ThirtyAll_2_2) { + EXPECT_EQ("Thirty-All", tennis_score(2, 2)); +} + + +TEST(TennisTest, FortyAll_3_3) { + EXPECT_EQ("Forty-All", tennis_score(3, 3)); +} + + +TEST(TennisTest, Deuce_4_4) { + EXPECT_EQ("Deuce", tennis_score(4, 4)); +} + + +TEST(TennisTest, FifteenLove_1_0) { + EXPECT_EQ("Fifteen-Love", tennis_score(1, 0)); +} + + +TEST(TennisTest, LoveFifteen_0_1) { + EXPECT_EQ("Love-Fifteen", tennis_score(0, 1)); +} + + +TEST(TennisTest, ThirtyLove_2_0) { + EXPECT_EQ("Thirty-Love", tennis_score(2, 0)); +} + + +TEST(TennisTest, LoveThirty_0_2) { + EXPECT_EQ("Love-Thirty", tennis_score(0, 2)); +} + + +TEST(TennisTest, FortyLove_3_0) { + EXPECT_EQ("Forty-Love", tennis_score(3, 0)); +} + + +TEST(TennisTest, LoveForty_0_3) { + EXPECT_EQ("Love-Forty", tennis_score(0, 3)); +} + + +TEST(TennisTest, Winforplayer1_4_0) { + EXPECT_EQ("Win for player1", tennis_score(4, 0)); +} + + +TEST(TennisTest, Winforplayer2_0_4) { + EXPECT_EQ("Win for player2", tennis_score(0, 4)); +} + + +TEST(TennisTest, ThirtyFifteen_2_1) { + EXPECT_EQ("Thirty-Fifteen", tennis_score(2, 1)); +} + + +TEST(TennisTest, FifteenThirty_1_2) { + EXPECT_EQ("Fifteen-Thirty", tennis_score(1, 2)); +} + + +TEST(TennisTest, FortyFifteen_3_1) { + EXPECT_EQ("Forty-Fifteen", tennis_score(3, 1)); +} + + +TEST(TennisTest, FifteenForty_1_3) { + EXPECT_EQ("Fifteen-Forty", tennis_score(1, 3)); +} + + +TEST(TennisTest, Winforplayer1_4_1) { + EXPECT_EQ("Win for player1", tennis_score(4, 1)); +} + + +TEST(TennisTest, Winforplayer2_1_4) { + EXPECT_EQ("Win for player2", tennis_score(1, 4)); +} + + +TEST(TennisTest, FortyThirty_3_2) { + EXPECT_EQ("Forty-Thirty", tennis_score(3, 2)); +} + + +TEST(TennisTest, ThirtyForty_2_3) { + EXPECT_EQ("Thirty-Forty", tennis_score(2, 3)); +} + + +TEST(TennisTest, Winforplayer1_4_2) { + EXPECT_EQ("Win for player1", tennis_score(4, 2)); +} + + +TEST(TennisTest, Winforplayer2_2_4) { + EXPECT_EQ("Win for player2", tennis_score(2, 4)); +} + + +TEST(TennisTest, Advantageplayer1_4_3) { + EXPECT_EQ("Advantage player1", tennis_score(4, 3)); +} + + +TEST(TennisTest, Advantageplayer2_3_4) { + EXPECT_EQ("Advantage player2", tennis_score(3, 4)); +} + + +TEST(TennisTest, Advantageplayer1_5_4) { + EXPECT_EQ("Advantage player1", tennis_score(5, 4)); +} + + +TEST(TennisTest, Advantageplayer2_4_5) { + EXPECT_EQ("Advantage player2", tennis_score(4, 5)); +} + + +TEST(TennisTest, Advantageplayer1_15_14) { + EXPECT_EQ("Advantage player1", tennis_score(15, 14)); +} + + +TEST(TennisTest, Advantageplayer2_14_15) { + EXPECT_EQ("Advantage player2", tennis_score(14, 15)); +} + + +TEST(TennisTest, Winforplayer1_6_4) { + EXPECT_EQ("Win for player1", tennis_score(6, 4)); +} + + +TEST(TennisTest, Winforplayer2_4_6) { + EXPECT_EQ("Win for player2", tennis_score(4, 6)); +} + + +TEST(TennisTest, Winforplayer1_16_14) { + EXPECT_EQ("Win for player1", tennis_score(16, 14)); +} + + +TEST(TennisTest, Winforplayer2_14_16) { + EXPECT_EQ("Win for player2", tennis_score(14, 16)); +} + + diff --git a/Tennis/cpp/starting/run-endless.sh b/Tennis/cpp/starting/run-endless.sh new file mode 100755 index 00000000..ad449aa3 --- /dev/null +++ b/Tennis/cpp/starting/run-endless.sh @@ -0,0 +1 @@ +codersdojo start run-once.sh diff --git a/Tennis/cpp/starting/run-once.sh b/Tennis/cpp/starting/run-once.sh new file mode 100755 index 00000000..1b1bffef --- /dev/null +++ b/Tennis/cpp/starting/run-once.sh @@ -0,0 +1,4 @@ +rm Tennis +rm Tennis.o +make +./Tennis \ No newline at end of file From 34b36ec3f2520ce3eb190c8afa8330f84907d8f4 Mon Sep 17 00:00:00 2001 From: Emily Bache Date: Wed, 4 Jan 2012 09:55:21 +0100 Subject: [PATCH 006/634] remove codersdojo run-endless.sh since we've taken away .meta already --- Tennis/cpp/defactored1/run-endless.sh | 1 - Tennis/cpp/defactored2/run-endless.sh | 1 - Tennis/cpp/defactored3/run-endless.sh | 1 - Tennis/cpp/starting/run-endless.sh | 1 - 4 files changed, 4 deletions(-) delete mode 100755 Tennis/cpp/defactored1/run-endless.sh delete mode 100755 Tennis/cpp/defactored2/run-endless.sh delete mode 100755 Tennis/cpp/defactored3/run-endless.sh delete mode 100755 Tennis/cpp/starting/run-endless.sh diff --git a/Tennis/cpp/defactored1/run-endless.sh b/Tennis/cpp/defactored1/run-endless.sh deleted file mode 100755 index ad449aa3..00000000 --- a/Tennis/cpp/defactored1/run-endless.sh +++ /dev/null @@ -1 +0,0 @@ -codersdojo start run-once.sh diff --git a/Tennis/cpp/defactored2/run-endless.sh b/Tennis/cpp/defactored2/run-endless.sh deleted file mode 100755 index ad449aa3..00000000 --- a/Tennis/cpp/defactored2/run-endless.sh +++ /dev/null @@ -1 +0,0 @@ -codersdojo start run-once.sh diff --git a/Tennis/cpp/defactored3/run-endless.sh b/Tennis/cpp/defactored3/run-endless.sh deleted file mode 100755 index ad449aa3..00000000 --- a/Tennis/cpp/defactored3/run-endless.sh +++ /dev/null @@ -1 +0,0 @@ -codersdojo start run-once.sh diff --git a/Tennis/cpp/starting/run-endless.sh b/Tennis/cpp/starting/run-endless.sh deleted file mode 100755 index ad449aa3..00000000 --- a/Tennis/cpp/starting/run-endless.sh +++ /dev/null @@ -1 +0,0 @@ -codersdojo start run-once.sh From 926f8a26860586d6f44b797a75219ded08690612 Mon Sep 17 00:00:00 2001 From: Emily Bache Date: Wed, 4 Jan 2012 19:52:03 +0100 Subject: [PATCH 007/634] On closer examination of the rules I notice Forty-All should in fact be Deuce --- Tennis/cpp/defactored1/Tennis.cc | 6 +++--- Tennis/cpp/defactored2/Tennis.cc | 6 +++--- Tennis/cpp/defactored3/Tennis.cc | 6 +++--- Tennis/cpp/generate_tests.py | 2 +- Tennis/cpp/starting/Tennis.cc | 4 ++-- 5 files changed, 12 insertions(+), 12 deletions(-) diff --git a/Tennis/cpp/defactored1/Tennis.cc b/Tennis/cpp/defactored1/Tennis.cc index b2737310..eeac646d 100644 --- a/Tennis/cpp/defactored1/Tennis.cc +++ b/Tennis/cpp/defactored1/Tennis.cc @@ -17,7 +17,7 @@ const std::string tennis_score(int p1Score, int p2Score) { score = "Thirty-All"; break; case 3: - score = "Forty-All"; + score = "Deuce"; break; default: score = "Deuce"; @@ -75,8 +75,8 @@ TEST(TennisTest, ThirtyAll_2_2) { } -TEST(TennisTest, FortyAll_3_3) { - EXPECT_EQ("Forty-All", tennis_score(3, 3)); +TEST(TennisTest, Deuce_3_3) { + EXPECT_EQ("Deuce", tennis_score(3, 3)); } diff --git a/Tennis/cpp/defactored2/Tennis.cc b/Tennis/cpp/defactored2/Tennis.cc index fe7e480f..5f193038 100644 --- a/Tennis/cpp/defactored2/Tennis.cc +++ b/Tennis/cpp/defactored2/Tennis.cc @@ -16,7 +16,7 @@ const std::string tennis_score(int p1Score, int p2Score) { score = "Forty"; score += "-All"; } - if (p1Score==p2Score && p1Score>3) + if (p1Score==p2Score && p1Score>2) score = "Deuce"; if (p1Score > 0 && p2Score==0) @@ -106,8 +106,8 @@ TEST(TennisTest, ThirtyAll_2_2) { } -TEST(TennisTest, FortyAll_3_3) { - EXPECT_EQ("Forty-All", tennis_score(3, 3)); +TEST(TennisTest, Deuce_3_3) { + EXPECT_EQ("Deuce", tennis_score(3, 3)); } diff --git a/Tennis/cpp/defactored3/Tennis.cc b/Tennis/cpp/defactored3/Tennis.cc index 15da13ac..cb2fae89 100644 --- a/Tennis/cpp/defactored3/Tennis.cc +++ b/Tennis/cpp/defactored3/Tennis.cc @@ -4,7 +4,7 @@ const std::string tennis_score(int p1, int p2) { std::string s; std::string p1N = "player1"; std::string p2N = "player2"; - if (p1 < 4 && p2 < 4) { + if (p1 < 4 && p2 < 4 && !(p1 == 3 && p2 == 3)) { std::string p[4] = {"Love", "Fifteen", "Thirty", "Forty"}; s = p[p1]; return (p1 == p2) ? s + "-All" : s + "-" + p[p2]; @@ -31,8 +31,8 @@ TEST(TennisTest, ThirtyAll_2_2) { } -TEST(TennisTest, FortyAll_3_3) { - EXPECT_EQ("Forty-All", tennis_score(3, 3)); +TEST(TennisTest, Deuce_3_3) { + EXPECT_EQ("Deuce", tennis_score(3, 3)); } diff --git a/Tennis/cpp/generate_tests.py b/Tennis/cpp/generate_tests.py index 2e645fde..78dcb928 100644 --- a/Tennis/cpp/generate_tests.py +++ b/Tennis/cpp/generate_tests.py @@ -8,7 +8,7 @@ TEST(TennisTest, %(testcase_name)s) { test_cases = [dict(p1Points=0, p2Points=0, score="Love-All"), dict(p1Points=1, p2Points=1, score="Fifteen-All"), dict(p1Points=2, p2Points=2, score="Thirty-All"), - dict(p1Points=3, p2Points=3, score="Forty-All"), + dict(p1Points=3, p2Points=3, score="Deuce"), dict(p1Points=4, p2Points=4, score="Deuce"), dict(p1Points=1, p2Points=0, score="Fifteen-Love"), diff --git a/Tennis/cpp/starting/Tennis.cc b/Tennis/cpp/starting/Tennis.cc index 90fac43c..87ce94ac 100644 --- a/Tennis/cpp/starting/Tennis.cc +++ b/Tennis/cpp/starting/Tennis.cc @@ -19,8 +19,8 @@ TEST(TennisTest, ThirtyAll_2_2) { } -TEST(TennisTest, FortyAll_3_3) { - EXPECT_EQ("Forty-All", tennis_score(3, 3)); +TEST(TennisTest, Deuce_3_3) { + EXPECT_EQ("Deuce", tennis_score(3, 3)); } From e8e5e0223fb5127fa2fd6e47bea25ab135af38e6 Mon Sep 17 00:00:00 2001 From: Emily Bache Date: Thu, 12 Jan 2012 20:37:08 +0100 Subject: [PATCH 008/634] first hack at a version for each language, translated from the C#. --- GildedRose/Java/GildedRose.java | 99 ++++++++++++++++++++++ GildedRose/Java/Item.java | 14 +++ GildedRose/README | 28 ++++++ GildedRose/cpp/GildedRose.cc | 117 ++++++++++++++++++++++++++ GildedRose/python/gilded_rose.py | 48 +++++++++++ GildedRose/python/test_gilded_rose.py | 6 ++ README | 3 +- 7 files changed, 314 insertions(+), 1 deletion(-) create mode 100644 GildedRose/Java/GildedRose.java create mode 100644 GildedRose/Java/Item.java create mode 100644 GildedRose/README create mode 100644 GildedRose/cpp/GildedRose.cc create mode 100644 GildedRose/python/gilded_rose.py create mode 100644 GildedRose/python/test_gilded_rose.py diff --git a/GildedRose/Java/GildedRose.java b/GildedRose/Java/GildedRose.java new file mode 100644 index 00000000..ed89f8a4 --- /dev/null +++ b/GildedRose/Java/GildedRose.java @@ -0,0 +1,99 @@ + +class GildedRose { + List items; + + public static void Main(string[] args) { + System.out.println("OMGHAI!"); + + List items = new List { + new Item("+5 Dexterity Vest", 10, 20), + new Item("Aged Brie", 2, 0), + new Item("Elixir of the Mongoose", 5, 7), + new Item("Sulfuras, Hand of Ragnaros", 0, 80), + new Item("Backstage passes to a TAFKAL80ETC concert", 15, 20), + new Item("Conjured Mana Cake", 3, 6) + } + + GildedRose app = new GildedRose(items); + + app.updateQuality(); + + } + + public void updateQuality() { + for (int i = 0; i < items.length; i++) + { + if (items[i].name != "Aged Brie" && items[i].name != "Backstage passes to a TAFKAL80ETC concert") + { + if (items[i].quality > 0) + { + if (items[i].name != "Sulfuras, Hand of Ragnaros") + { + items[i].quality = items[i].quality - 1; + } + } + } + else + { + if (items[i].quality < 50) + { + items[i].quality = items[i].quality + 1; + + if (items[i].name == "Backstage passes to a TAFKAL80ETC concert") + { + if (items[i].sellIn < 11) + { + if (items[i].quality < 50) + { + items[i].quality = items[i].quality + 1; + } + } + + if (items[i].sellIn < 6) + { + if (items[i].quality < 50) + { + items[i].quality = items[i].quality + 1; + } + } + } + } + } + + if (items[i].name != "Sulfuras, Hand of Ragnaros") + { + items[i].sellIn = items[i].sellIn - 1; + } + + if (items[i].sellIn < 0) + { + if (items[i].name != "Aged Brie") + { + if (items[i].name != "Backstage passes to a TAFKAL80ETC concert") + { + if (items[i].quality > 0) + { + if (items[i].name != "Sulfuras, Hand of Ragnaros") + { + items[i].quality = items[i].quality - 1; + } + } + } + else + { + items[i].quality = items[i].quality - items[i].quality; + } + } + else + { + if (items[i].quality < 50) + { + items[i].quality = items[i].quality + 1; + } + } + } + } + } + +} + diff --git a/GildedRose/Java/Item.java b/GildedRose/Java/Item.java new file mode 100644 index 00000000..afe3ef8f --- /dev/null +++ b/GildedRose/Java/Item.java @@ -0,0 +1,14 @@ +public class Item { + + public String name; + + public int sellIn; + + public int quality; + + public Item(String name, int sellIn, int quality) { + this.name = name; + this.sellIn = sellIn; + this.quality = quality; + } +} diff --git a/GildedRose/README b/GildedRose/README new file mode 100644 index 00000000..22bc5233 --- /dev/null +++ b/GildedRose/README @@ -0,0 +1,28 @@ +(This Kata is already on GitHub as "GildedRose" with several forks, and I'm not sure who put it up there first. All the forks I could find were pure C# so rather than fork one of them I decided to just put other languages in here.) + +================ +Gilded Rose Kata +================ + +Hi and welcome to team Gilded Rose. As you know, we are a small inn with a prime location in a prominent city ran by a friendly innkeeper named Allison. We also buy and sell only the finest goods. Unfortunately, our goods are constantly degrading in quality as they approach their sell by date. We have a system in place that updates our inventory for us. It was developed by a no-nonsense type named Leeroy, who has moved on to new adventures. Your task is to add the new feature to our system so that we can begin selling a new category of items. First an introduction to our system: + + - All items have a SellIn value which denotes the number of days we have to sell the item + - All items have a Quality value which denotes how valuable the item is + - At the end of each day our system lowers both values for every item + +Pretty simple, right? Well this is where it gets interesting: + + - Once the sell by date has passed, Quality degrades twice as fast + - The Quality of an item is never negative + - "Aged Brie" actually increases in Quality the older it gets + - The Quality of an item is never more than 50 + - "Sulfuras", being a legendary item, never has to be sold or decreases in Quality + - "Backstage passes", like aged brie, increases in Quality as it's SellIn value approaches; Quality increases by 2 when there are 10 days or less and by 3 when there are 5 days or less but Quality drops to 0 after the concert + +We have recently signed a supplier of conjured items. This requires an update to our system: + + - "Conjured" items degrade in Quality twice as fast as normal items + +Feel free to make any changes to the UpdateQuality method and add any new code as long as everything still works correctly. However, do not alter the Item class or Items property as those belong to the goblin in the corner who will insta-rage and one-shot you as he doesn't believe in shared code ownership (you can make the UpdateQuality method and Items property static if you like, we'll cover for you). Your work needs to be completed by Friday, February 18, 2011 08:00:00 AM PST. + +Just for clarification, an item can never have its Quality increase above 50, however "Sulfuras" is a legendary item and as such its Quality is 80 and it never alters. \ No newline at end of file diff --git a/GildedRose/cpp/GildedRose.cc b/GildedRose/cpp/GildedRose.cc new file mode 100644 index 00000000..fa001b07 --- /dev/null +++ b/GildedRose/cpp/GildedRose.cc @@ -0,0 +1,117 @@ +#include + +void example() +{ + std::list items = new std::list(); + items.push_back(new Item("+5 Dexterity Vest", 10, 20)); + items.push_back(new Item("Aged Brie", 2, 0)); + items.push_back(new Item("Elixir of the Mongoose", 5, 7)); + items.push_back(new Item("Sulfuras, Hand of Ragnaros", 0, 80)); + items.push_back(new Item("Backstage passes to a TAFKAL80ETC concert", 15, 20)); + items.push_back(new Item("Conjured Mana Cake", 3, 6)); + GildedRose app = new GildedRose(items); + app.updateQuality(); +} + +class GildedRose +{ +public: + std::list items; + GildedRose(std::list items) + { + this.items = items; + } + + void updateQuality() + { + for (int i = 0; i < items.length; i++) + { + if (items[i].name != "Aged Brie" && items[i].name != "Backstage passes to a TAFKAL80ETC concert") + { + if (items[i].quality > 0) + { + if (items[i].name != "Sulfuras, Hand of Ragnaros") + { + items[i].quality = items[i].quality - 1; + } + } + } + else + { + if (items[i].quality < 50) + { + items[i].quality = items[i].quality + 1; + + if (items[i].name == "Backstage passes to a TAFKAL80ETC concert") + { + if (items[i].sellIn < 11) + { + if (items[i].quality < 50) + { + items[i].quality = items[i].quality + 1; + } + } + + if (items[i].sellIn < 6) + { + if (items[i].quality < 50) + { + items[i].quality = items[i].quality + 1; + } + } + } + } + } + + if (items[i].name != "Sulfuras, Hand of Ragnaros") + { + items[i].sellIn = items[i].sellIn - 1; + } + + if (items[i].sellIn < 0) + { + if (items[i].name != "Aged Brie") + { + if (items[i].name != "Backstage passes to a TAFKAL80ETC concert") + { + if (items[i].quality > 0) + { + if (items[i].name != "Sulfuras, Hand of Ragnaros") + { + items[i].quality = items[i].quality - 1; + } + } + } + else + { + items[i].quality = items[i].quality - items[i].quality; + } + } + else + { + if (items[i].quality < 50) + { + items[i].quality = items[i].quality + 1; + } + } + } + } + } +}; + +class Item +{ +public: + std::string name; + int sellIn; + int quality; +}; + +TEST(GildedRoseTest, Foo) { + std::list items = new std::list(); + items.push_back(new Item("Foo", 0, 0)); + GildedRose app = new GildedRose(items); + app.updateQuality(); + EXPECT_EQ("fixme", app.items[0].name); +} + diff --git a/GildedRose/python/gilded_rose.py b/GildedRose/python/gilded_rose.py new file mode 100644 index 00000000..a518844e --- /dev/null +++ b/GildedRose/python/gilded_rose.py @@ -0,0 +1,48 @@ + +def update_quality(items): + for item in items: + if item.name != "Aged Brie" and item.name != "Backstage passes to a TAFKAL80ETC concert": + if item.quality > 0: + if item.name != "Sulfuras, Hand of Ragnaros": + item.quality = item.quality - 1; + else: + if item.quality < 50: + item.quality = item.quality + 1; + if item.name == "Backstage passes to a TAFKAL80ETC concert": + if item.sell_in < 11: + if item.quality < 50: + item.quality = item.quality + 1; + if item.sell_in < 6: + if item.quality < 50: + item.quality = item.quality + 1; + if item.name != "Sulfuras, Hand of Ragnaros": + item.sell_in = item.sell_in - 1; + if item.sell_in < 0: + if item.name != "Aged Brie": + if item.name != "Backstage passes to a TAFKAL80ETC concert": + if item.quality > 0: + if item.name != "Sulfuras, Hand of Ragnaros": + item.quality = item.quality - 1; + else: + item.quality = item.quality - item.quality; + else: + if item.quality < 50: + item.quality = item.quality + 1; + return items + +class Item: + def __init__(self, name, sell_in, quality): + self.name = name + self.sell_in = sell_in + self.quality = quality + +if __name__ == "__main__": + items = [ + Item(name="+5 Dexterity Vest", sell_in=10, quality=20), + Item(name="Aged Brie", sell_in=2, quality=0), + Item(name="Elixir of the Mongoose", sell_in=5, quality=7), + Item(name="Sulfuras, Hand of Ragnaros", sell_in=0, quality=80), + Item(name="Backstage passes to a TAFKAL80ETC concert", sell_in=15, quality=20), + Item(name="Conjured Mana Cake", sell_in=3, quality=6), + ] + update_quality(items) \ No newline at end of file diff --git a/GildedRose/python/test_gilded_rose.py b/GildedRose/python/test_gilded_rose.py new file mode 100644 index 00000000..34304cdb --- /dev/null +++ b/GildedRose/python/test_gilded_rose.py @@ -0,0 +1,6 @@ +from gilded_rose import Item, update_quality + +def test_foo(): + items = [Item("foo", 0, 0)] + update_quality(items) + assert "fixme" == items[0].name \ No newline at end of file diff --git a/README b/README index 46e9722c..9e44d8ec 100644 --- a/README +++ b/README @@ -2,4 +2,5 @@ This is a collection of starting files for when practicing refactoring. Contents so far: -Tennis kata in Java and python. \ No newline at end of file +Tennis Kata in Java, Python and C++. +GildedRose Kata in Java, Python and C++. (a C# version is already available on github) \ No newline at end of file From a43bfe0f0dd21e3ad1daa30473532e0262d631b8 Mon Sep 17 00:00:00 2001 From: Emily Bache Date: Thu, 12 Jan 2012 21:55:28 +0100 Subject: [PATCH 009/634] Java version of the kata now compiles and has a failing test --- GildedRose/Java/GildedRose.java | 12 ++++++++---- GildedRose/Java/GildedRoseTest.java | 16 ++++++++++++++++ README | 2 +- 3 files changed, 25 insertions(+), 5 deletions(-) create mode 100644 GildedRose/Java/GildedRoseTest.java diff --git a/GildedRose/Java/GildedRose.java b/GildedRose/Java/GildedRose.java index ed89f8a4..747f9d2c 100644 --- a/GildedRose/Java/GildedRose.java +++ b/GildedRose/Java/GildedRose.java @@ -1,18 +1,22 @@ class GildedRose { - List items; + Item[] items; - public static void Main(string[] args) { + public GildedRose(Item[] items) { + this.items = items; + } + + public static void main(String[] args) { System.out.println("OMGHAI!"); - List items = new List { + Item[] items = new Item[] { new Item("+5 Dexterity Vest", 10, 20), new Item("Aged Brie", 2, 0), new Item("Elixir of the Mongoose", 5, 7), new Item("Sulfuras, Hand of Ragnaros", 0, 80), new Item("Backstage passes to a TAFKAL80ETC concert", 15, 20), new Item("Conjured Mana Cake", 3, 6) - } + }; GildedRose app = new GildedRose(items); diff --git a/GildedRose/Java/GildedRoseTest.java b/GildedRose/Java/GildedRoseTest.java new file mode 100644 index 00000000..a7176534 --- /dev/null +++ b/GildedRose/Java/GildedRoseTest.java @@ -0,0 +1,16 @@ +import static org.junit.Assert.*; + +import org.junit.Test; + +public class GildedRoseTest { + + @Test + public void foo() { + Item[] items = new Item[] { + new Item("foo", 0, 0) + }; + GildedRose app = new GildedRose(items); + app.updateQuality(); + assertEquals("fixme", app.items[0].name); + } +} diff --git a/README b/README index 9e44d8ec..1675c9c5 100644 --- a/README +++ b/README @@ -3,4 +3,4 @@ This is a collection of starting files for when practicing refactoring. Contents so far: Tennis Kata in Java, Python and C++. -GildedRose Kata in Java, Python and C++. (a C# version is already available on github) \ No newline at end of file +Gilded Rose Kata in Java, Python and C++. (a C# version is already available on github) \ No newline at end of file From 5b6c47ccc8b05eda7d74251e727e57b5d86ae151 Mon Sep 17 00:00:00 2001 From: Emily Bache Date: Thu, 12 Jan 2012 22:05:13 +0100 Subject: [PATCH 010/634] formatted code according to eclipse's formatter --- GildedRose/Java/GildedRose.java | 150 ++++++++++++---------------- GildedRose/Java/GildedRoseTest.java | 4 +- 2 files changed, 63 insertions(+), 91 deletions(-) diff --git a/GildedRose/Java/GildedRose.java b/GildedRose/Java/GildedRose.java index 747f9d2c..fcce1785 100644 --- a/GildedRose/Java/GildedRose.java +++ b/GildedRose/Java/GildedRose.java @@ -1,103 +1,77 @@ - class GildedRose { - Item[] items; + Item[] items; - public GildedRose(Item[] items) { - this.items = items; - } + public GildedRose(Item[] items) { + this.items = items; + } public static void main(String[] args) { - System.out.println("OMGHAI!"); + System.out.println("OMGHAI!"); - Item[] items = new Item[] { - new Item("+5 Dexterity Vest", 10, 20), - new Item("Aged Brie", 2, 0), - new Item("Elixir of the Mongoose", 5, 7), - new Item("Sulfuras, Hand of Ragnaros", 0, 80), - new Item("Backstage passes to a TAFKAL80ETC concert", 15, 20), - new Item("Conjured Mana Cake", 3, 6) - }; + Item[] items = new Item[] { new Item("+5 Dexterity Vest", 10, 20), + new Item("Aged Brie", 2, 0), + new Item("Elixir of the Mongoose", 5, 7), + new Item("Sulfuras, Hand of Ragnaros", 0, 80), + new Item("Backstage passes to a TAFKAL80ETC concert", 15, 20), + new Item("Conjured Mana Cake", 3, 6) }; - GildedRose app = new GildedRose(items); + GildedRose app = new GildedRose(items); - app.updateQuality(); + app.updateQuality(); - } + } - public void updateQuality() { - for (int i = 0; i < items.length; i++) - { - if (items[i].name != "Aged Brie" && items[i].name != "Backstage passes to a TAFKAL80ETC concert") - { - if (items[i].quality > 0) - { - if (items[i].name != "Sulfuras, Hand of Ragnaros") - { - items[i].quality = items[i].quality - 1; - } - } - } - else - { - if (items[i].quality < 50) - { - items[i].quality = items[i].quality + 1; + public void updateQuality() { + for (int i = 0; i < items.length; i++) { + if (items[i].name != "Aged Brie" + && items[i].name != "Backstage passes to a TAFKAL80ETC concert") { + if (items[i].quality > 0) { + if (items[i].name != "Sulfuras, Hand of Ragnaros") { + items[i].quality = items[i].quality - 1; + } + } + } else { + if (items[i].quality < 50) { + items[i].quality = items[i].quality + 1; - if (items[i].name == "Backstage passes to a TAFKAL80ETC concert") - { - if (items[i].sellIn < 11) - { - if (items[i].quality < 50) - { - items[i].quality = items[i].quality + 1; - } - } + if (items[i].name == "Backstage passes to a TAFKAL80ETC concert") { + if (items[i].sellIn < 11) { + if (items[i].quality < 50) { + items[i].quality = items[i].quality + 1; + } + } - if (items[i].sellIn < 6) - { - if (items[i].quality < 50) - { - items[i].quality = items[i].quality + 1; - } - } - } - } - } + if (items[i].sellIn < 6) { + if (items[i].quality < 50) { + items[i].quality = items[i].quality + 1; + } + } + } + } + } - if (items[i].name != "Sulfuras, Hand of Ragnaros") - { - items[i].sellIn = items[i].sellIn - 1; - } + if (items[i].name != "Sulfuras, Hand of Ragnaros") { + items[i].sellIn = items[i].sellIn - 1; + } - if (items[i].sellIn < 0) - { - if (items[i].name != "Aged Brie") - { - if (items[i].name != "Backstage passes to a TAFKAL80ETC concert") - { - if (items[i].quality > 0) - { - if (items[i].name != "Sulfuras, Hand of Ragnaros") - { - items[i].quality = items[i].quality - 1; - } - } - } - else - { - items[i].quality = items[i].quality - items[i].quality; - } - } - else - { - if (items[i].quality < 50) - { - items[i].quality = items[i].quality + 1; - } - } - } - } - } + if (items[i].sellIn < 0) { + if (items[i].name != "Aged Brie") { + if (items[i].name != "Backstage passes to a TAFKAL80ETC concert") { + if (items[i].quality > 0) { + if (items[i].name != "Sulfuras, Hand of Ragnaros") { + items[i].quality = items[i].quality - 1; + } + } + } else { + items[i].quality = items[i].quality - items[i].quality; + } + } else { + if (items[i].quality < 50) { + items[i].quality = items[i].quality + 1; + } + } + } + } + } } - diff --git a/GildedRose/Java/GildedRoseTest.java b/GildedRose/Java/GildedRoseTest.java index a7176534..6a21ee64 100644 --- a/GildedRose/Java/GildedRoseTest.java +++ b/GildedRose/Java/GildedRoseTest.java @@ -6,9 +6,7 @@ public class GildedRoseTest { @Test public void foo() { - Item[] items = new Item[] { - new Item("foo", 0, 0) - }; + Item[] items = new Item[] { new Item("foo", 0, 0) }; GildedRose app = new GildedRose(items); app.updateQuality(); assertEquals("fixme", app.items[0].name); From 5010475a2f39a9a94f5dbda0ea46fae1480f0ad8 Mon Sep 17 00:00:00 2001 From: Emily Bache Date: Sun, 15 Jan 2012 20:30:31 +0100 Subject: [PATCH 011/634] C++ version with a vector to hold the items. --- GildedRose/cpp/GildedRose.cc | 58 ++++++++++++++++++++---------------- 1 file changed, 32 insertions(+), 26 deletions(-) diff --git a/GildedRose/cpp/GildedRose.cc b/GildedRose/cpp/GildedRose.cc index fa001b07..c3ebb814 100644 --- a/GildedRose/cpp/GildedRose.cc +++ b/GildedRose/cpp/GildedRose.cc @@ -1,30 +1,29 @@ #include -void example() +#include + +using namespace std; + +class Item { - std::list items = new std::list(); - items.push_back(new Item("+5 Dexterity Vest", 10, 20)); - items.push_back(new Item("Aged Brie", 2, 0)); - items.push_back(new Item("Elixir of the Mongoose", 5, 7)); - items.push_back(new Item("Sulfuras, Hand of Ragnaros", 0, 80)); - items.push_back(new Item("Backstage passes to a TAFKAL80ETC concert", 15, 20)); - items.push_back(new Item("Conjured Mana Cake", 3, 6)); - GildedRose app = new GildedRose(items); - app.updateQuality(); -} +public: + string name; + int sellIn; + int quality; + Item(string name, int sellIn, int quality) : name(name), sellIn(sellIn), quality(quality) + {} +}; class GildedRose { public: - std::list items; - GildedRose(std::list items) - { - this.items = items; - } + vector items; + GildedRose(vector items) : items (items) + {} void updateQuality() { - for (int i = 0; i < items.length; i++) + for (int i = 0; i < items.size(); i++) { if (items[i].name != "Aged Brie" && items[i].name != "Backstage passes to a TAFKAL80ETC concert") { @@ -99,18 +98,25 @@ public: } }; -class Item + +void example() { -public: - std::string name; - int sellIn; - int quality; -}; + vector items; + items.push_back(Item("+5 Dexterity Vest", 10, 20)); + items.push_back(Item("Aged Brie", 2, 0)); + items.push_back(Item("Elixir of the Mongoose", 5, 7)); + items.push_back(Item("Sulfuras, Hand of Ragnaros", 0, 80)); + items.push_back(Item("Backstage passes to a TAFKAL80ETC concert", 15, 20)); + items.push_back(Item("Conjured Mana Cake", 3, 6)); + GildedRose app(items); + app.updateQuality(); +} + TEST(GildedRoseTest, Foo) { - std::list items = new std::list(); - items.push_back(new Item("Foo", 0, 0)); - GildedRose app = new GildedRose(items); + vector items; + items.push_back(Item("Foo", 0, 0)); + GildedRose app(items); app.updateQuality(); EXPECT_EQ("fixme", app.items[0].name); } From 354cf5e78067fab81bd514566ca18caa3286e3dd Mon Sep 17 00:00:00 2001 From: Emily Bache Date: Sun, 15 Jan 2012 20:37:43 +0100 Subject: [PATCH 012/634] Updated the credits now I found out who invented the kata. --- GildedRose/README | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/GildedRose/README b/GildedRose/README index 22bc5233..87ab2511 100644 --- a/GildedRose/README +++ b/GildedRose/README @@ -1,4 +1,6 @@ -(This Kata is already on GitHub as "GildedRose" with several forks, and I'm not sure who put it up there first. All the forks I could find were pure C# so rather than fork one of them I decided to just put other languages in here.) +This Kata was originally created by Terry Hughes (http://twitter.com/#!/TerryHughes). It is already on GitHub as "GildedRose", a sample project for C#. I could have forked it again, but I thought other language users might not want to download a whole C# project environment. In this repository are starting code samples for Java, Python and C++. + +See also http://iamnotmyself.com/2011/02/13/refactor-this-the-gilded-rose-kata/ ================ Gilded Rose Kata @@ -23,6 +25,6 @@ We have recently signed a supplier of conjured items. This requires an update to - "Conjured" items degrade in Quality twice as fast as normal items -Feel free to make any changes to the UpdateQuality method and add any new code as long as everything still works correctly. However, do not alter the Item class or Items property as those belong to the goblin in the corner who will insta-rage and one-shot you as he doesn't believe in shared code ownership (you can make the UpdateQuality method and Items property static if you like, we'll cover for you). Your work needs to be completed by Friday, February 18, 2011 08:00:00 AM PST. +Feel free to make any changes to the UpdateQuality method and add any new code as long as everything still works correctly. However, do not alter the Item class or Items property as those belong to the goblin in the corner who will insta-rage and one-shot you as he doesn't believe in shared code ownership (you can make the UpdateQuality method and Items property static if you like, we'll cover for you). Just for clarification, an item can never have its Quality increase above 50, however "Sulfuras" is a legendary item and as such its Quality is 80 and it never alters. \ No newline at end of file From 8c534ac0d9d71111345c59c2eb0a63967ae30a3b Mon Sep 17 00:00:00 2001 From: Emily Bache Date: Sun, 15 Jan 2012 20:40:56 +0100 Subject: [PATCH 013/634] added supporting files for c++ --- GildedRose/cpp/Makefile | 75 ++++++++++++++++++++++++++++++++++++++ GildedRose/cpp/README | 7 ++++ GildedRose/cpp/run-once.sh | 4 ++ 3 files changed, 86 insertions(+) create mode 100644 GildedRose/cpp/Makefile create mode 100644 GildedRose/cpp/README create mode 100755 GildedRose/cpp/run-once.sh diff --git a/GildedRose/cpp/Makefile b/GildedRose/cpp/Makefile new file mode 100644 index 00000000..f6f284a1 --- /dev/null +++ b/GildedRose/cpp/Makefile @@ -0,0 +1,75 @@ +# Makefile for building the kata file with the Google Testing Framework +# +# SYNOPSIS: +# +# make [all] - makes everything. +# make TARGET - makes the given target. +# make clean - removes all files generated by make. + +# Please tweak the following variable definitions as needed by your +# project, except GTEST_HEADERS, which you can use in your own targets +# but shouldn't modify. + +# Points to the root of Google Test, relative to where this file is. +# Remember to tweak this if you move this file. +GTEST_DIR = gtest + +# Where to find user code. +USER_DIR = . + +# Flags passed to the preprocessor. +CPPFLAGS += -I$(GTEST_DIR)/include + +# Flags passed to the C++ compiler. +CXXFLAGS += -g -Wall -Wextra + +# All tests produced by this Makefile. Remember to add new tests you +# created to the list. +TESTS = GildedRose + +# All Google Test headers. Usually you shouldn't change this +# definition. +GTEST_HEADERS = $(GTEST_DIR)/include/gtest/*.h \ + $(GTEST_DIR)/include/gtest/internal/*.h + +# House-keeping build targets. + +all : $(TESTS) + +clean : + rm -f $(TESTS) gtest.a gtest_main.a *.o + +# Builds gtest.a and gtest_main.a. + +# Usually you shouldn't tweak such internal variables, indicated by a +# trailing _. +GTEST_SRCS_ = $(GTEST_DIR)/src/*.cc $(GTEST_DIR)/src/*.h $(GTEST_HEADERS) + +# For simplicity and to avoid depending on Google Test's +# implementation details, the dependencies specified below are +# conservative and not optimized. This is fine as Google Test +# compiles fast and for ordinary users its source rarely changes. +gtest-all.o : $(GTEST_SRCS_) + $(CXX) $(CPPFLAGS) -I$(GTEST_DIR) $(CXXFLAGS) -c \ + $(GTEST_DIR)/src/gtest-all.cc + +gtest_main.o : $(GTEST_SRCS_) + $(CXX) $(CPPFLAGS) -I$(GTEST_DIR) $(CXXFLAGS) -c \ + $(GTEST_DIR)/src/gtest_main.cc + +gtest.a : gtest-all.o + $(AR) $(ARFLAGS) $@ $^ + +gtest_main.a : gtest-all.o gtest_main.o + $(AR) $(ARFLAGS) $@ $^ + +# Builds a sample test. A test should link with either gtest.a or +# gtest_main.a, depending on whether it defines its own main() +# function. + +GildedRose.o : $(USER_DIR)/GildedRose.cc \ + $(GTEST_HEADERS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/GildedRose.cc + +GildedRose : GildedRose.o gtest_main.a + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@ diff --git a/GildedRose/cpp/README b/GildedRose/cpp/README new file mode 100644 index 00000000..5d4673a4 --- /dev/null +++ b/GildedRose/cpp/README @@ -0,0 +1,7 @@ +run-once.sh runs your tests once + +Assumptions: + - make and a C++ compiler (like gcc) is installed on your system and is in the PATH + - The GTest framework is in the directory gtest. + - If your IDE does the compilation and linking, you should remove the first 3 lines + in the run-once.sh file. diff --git a/GildedRose/cpp/run-once.sh b/GildedRose/cpp/run-once.sh new file mode 100755 index 00000000..7090228b --- /dev/null +++ b/GildedRose/cpp/run-once.sh @@ -0,0 +1,4 @@ +rm GildedRose +rm GildedRose.o +make +./GildedRose \ No newline at end of file From 838f61dd979fc4a2eb30713eadd5bff4e6c0dab9 Mon Sep 17 00:00:00 2001 From: Anders Arnholm Date: Fri, 20 Jan 2012 08:05:45 +0100 Subject: [PATCH 014/634] CHanges -lphread into -pthread, removed compile error --- GildedRose/cpp/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/GildedRose/cpp/Makefile b/GildedRose/cpp/Makefile index f6f284a1..e5e1d3e9 100644 --- a/GildedRose/cpp/Makefile +++ b/GildedRose/cpp/Makefile @@ -72,4 +72,4 @@ GildedRose.o : $(USER_DIR)/GildedRose.cc \ $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/GildedRose.cc GildedRose : GildedRose.o gtest_main.a - $(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@ + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -pthread $^ -o $@ From 8da58f6dd1615422e9164c2fb5db07aa88984acb Mon Sep 17 00:00:00 2001 From: Emily Date: Mon, 20 Feb 2012 14:17:47 +0100 Subject: [PATCH 015/634] added a text based test for the java and python versions --- GildedRose/Java/Main.java | 31 ++ GildedRose/texttests/._config.gr | Bin 0 -> 4096 bytes GildedRose/texttests/._environment.gr | Bin 0 -> 4096 bytes GildedRose/texttests/._testsuite.gr | Bin 0 -> 4096 bytes GildedRose/texttests/ThirtyDays/._options.gr | Bin 0 -> 4096 bytes GildedRose/texttests/ThirtyDays/errors.gr | 0 GildedRose/texttests/ThirtyDays/options.gr | 1 + GildedRose/texttests/ThirtyDays/output.gr | 280 +++++++++++++++++++ GildedRose/texttests/config.gr | 18 ++ GildedRose/texttests/environment.gr | 3 + GildedRose/texttests/testsuite.gr | 2 + 11 files changed, 335 insertions(+) create mode 100755 GildedRose/Java/Main.java create mode 100755 GildedRose/texttests/._config.gr create mode 100755 GildedRose/texttests/._environment.gr create mode 100755 GildedRose/texttests/._testsuite.gr create mode 100755 GildedRose/texttests/ThirtyDays/._options.gr create mode 100644 GildedRose/texttests/ThirtyDays/errors.gr create mode 100755 GildedRose/texttests/ThirtyDays/options.gr create mode 100644 GildedRose/texttests/ThirtyDays/output.gr create mode 100755 GildedRose/texttests/config.gr create mode 100755 GildedRose/texttests/environment.gr create mode 100755 GildedRose/texttests/testsuite.gr diff --git a/GildedRose/Java/Main.java b/GildedRose/Java/Main.java new file mode 100755 index 00000000..87d79509 --- /dev/null +++ b/GildedRose/Java/Main.java @@ -0,0 +1,31 @@ + +public class Main { + public static void main(String[] args) { + System.out.println("OMGHAI!"); + + Item[] items = new Item[] { new Item("+5 Dexterity Vest", 10, 20), + new Item("Aged Brie", 2, 0), + new Item("Elixir of the Mongoose", 5, 7), + new Item("Sulfuras, Hand of Ragnaros", 0, 80), + new Item("Backstage passes to a TAFKAL80ETC concert", 15, 20), + new Item("Conjured Mana Cake", 3, 6) }; + + GildedRose app = new GildedRose(items); + + int days = 2; + if (args.length > 0) { + days = Integer.parseInt(args[0]) + 1; + } + + for (int i = 0; i < days; i++) { + System.out.println("-------- day " + i + " --------"); + System.out.println("name, sellIn, quality"); + for (Item item : items) { + System.out.println(item); + } + System.out.println(); + app.updateQuality(); + } + } + +} \ No newline at end of file diff --git a/GildedRose/texttests/._config.gr b/GildedRose/texttests/._config.gr new file mode 100755 index 0000000000000000000000000000000000000000..05c1b19e8f0ad2fec8b155dc875ced3a8f4603bd GIT binary patch literal 4096 zcmZQz6=P>$Vqox1Ojhs@R)|o50+1L3ClDJkFz{^v(m+1nBL)UWIUt(=a103vvYvJF zKST$^44`r)G%bukK2%&ZIX_n~H!-;=KR2-?wOB7Xu_(2Kp_&WikmUTF(%d`+TLlAa zFh3_VFBQl$G_&TaMKf`fI~oF`Aut*OqaiRF0;3@?8UmvsFd71*Aut*OqaiTjLjcs- z1Yt0c3(3eVRwzm>&Mz%WPE|$Vqox1Ojhs@R)|o50+1L3ClDJkFz{^v(m+1nBL)UWIUt(=a103vvYvJF zKST$^44`r)G%bukK2%&ZIX_n~H!-;=KR2-?wOB7Xu_(2Kp_&WikmUTF(%d`+TLoiN zYp_60W?m|gYhcY)i)P{|cQgb>Ltr!nMnhmU1V%$(Gz3ONU^E0qLtr!nMnho4hXAOv z3Bq6?7m|@#tWcC%oL^d$oT`wPUzDwonOBmUSCW~Zmza}NsgRSJR-%xUlbDwc?14gc R4QUG1|8TF!Fv$J?4*-sUFJAxv literal 0 HcmV?d00001 diff --git a/GildedRose/texttests/._testsuite.gr b/GildedRose/texttests/._testsuite.gr new file mode 100755 index 0000000000000000000000000000000000000000..9c4f9870ed67e7fbd23c2e36667e95c1a148a5b1 GIT binary patch literal 4096 zcmZQz6=P>$Vqox1Ojhs@R)|o50+1L3ClDJkFz{^v(m+1nBL)UWIUt(=a103vvYvJF zKST$^44`r)G%bukK2%&ZIX_n~H!-;=KR2-?wOB7Xu_(2Kp_&WikmUTF(%d`+TLlYK zYp_60W?m|gYhcY)i)P{|cQgb>Ltr!nMnhmU1V%$(Gz3ONU^E0qLtr!nMnho4hXAOv z3Bq6?7m|@#tWcC%oL^d$oT`wPUzDwonOBmUSCW~Zmza}NsgRSJR-%xUlbDwc?14gc R4QUG1|8TF!Fv$J?4*=UeFJu4! literal 0 HcmV?d00001 diff --git a/GildedRose/texttests/ThirtyDays/._options.gr b/GildedRose/texttests/ThirtyDays/._options.gr new file mode 100755 index 0000000000000000000000000000000000000000..5ffc020ca9a07576f2666083de5aca2ad8d1ca85 GIT binary patch literal 4096 zcmeH~u?oU45QeXUh#lN?l5)O4QP<+&1BjpgNW}TK83I0Yxp8H)gtKP zEZo6y`H%b|_iYF5K?hm@3&wG|#tk-6_n_-@3eday>UHl95Jdj`Bj#zkN-nqR<$$xl zKKil*UN`+dH+h^hZcWadC}Pg6aBvLkk8q>PT;mMK$x|z-g;$d#JbgV#k_Zq1B0vO) z01+SpM1Tko0U|&Ih(Nt;*7=Mm-N^#2C`@U&z|7b^O6`Pp(rBjC0hP!cZWYsezkxQc Ozb>EizegEDR8 Date: Mon, 20 Feb 2012 14:22:55 +0100 Subject: [PATCH 016/634] added code needed for test fixture - ie toString methods and main method --- GildedRose/Java/GildedRose.java | 16 ---------------- GildedRose/Java/Item.java | 4 ++++ GildedRose/python/gilded_rose.py | 17 ++++++++++++++++- 3 files changed, 20 insertions(+), 17 deletions(-) mode change 100644 => 100755 GildedRose/Java/GildedRose.java mode change 100644 => 100755 GildedRose/Java/Item.java mode change 100644 => 100755 GildedRose/python/gilded_rose.py diff --git a/GildedRose/Java/GildedRose.java b/GildedRose/Java/GildedRose.java old mode 100644 new mode 100755 index fcce1785..f5d9a549 --- a/GildedRose/Java/GildedRose.java +++ b/GildedRose/Java/GildedRose.java @@ -5,22 +5,6 @@ class GildedRose { this.items = items; } - public static void main(String[] args) { - System.out.println("OMGHAI!"); - - Item[] items = new Item[] { new Item("+5 Dexterity Vest", 10, 20), - new Item("Aged Brie", 2, 0), - new Item("Elixir of the Mongoose", 5, 7), - new Item("Sulfuras, Hand of Ragnaros", 0, 80), - new Item("Backstage passes to a TAFKAL80ETC concert", 15, 20), - new Item("Conjured Mana Cake", 3, 6) }; - - GildedRose app = new GildedRose(items); - - app.updateQuality(); - - } - public void updateQuality() { for (int i = 0; i < items.length; i++) { if (items[i].name != "Aged Brie" diff --git a/GildedRose/Java/Item.java b/GildedRose/Java/Item.java old mode 100644 new mode 100755 index afe3ef8f..8c846b45 --- a/GildedRose/Java/Item.java +++ b/GildedRose/Java/Item.java @@ -11,4 +11,8 @@ public class Item { this.sellIn = sellIn; this.quality = quality; } + + public String toString() { + return this.name + ", " + this.sellIn + ", " + this.quality; + } } diff --git a/GildedRose/python/gilded_rose.py b/GildedRose/python/gilded_rose.py old mode 100644 new mode 100755 index a518844e..22f23a0d --- a/GildedRose/python/gilded_rose.py +++ b/GildedRose/python/gilded_rose.py @@ -36,7 +36,11 @@ class Item: self.sell_in = sell_in self.quality = quality + def __repr__(self): + return "%s, %s, %s" % (self.name, self.sell_in, self.quality) + if __name__ == "__main__": + print ("OMGHAI!") items = [ Item(name="+5 Dexterity Vest", sell_in=10, quality=20), Item(name="Aged Brie", sell_in=2, quality=0), @@ -45,4 +49,15 @@ if __name__ == "__main__": Item(name="Backstage passes to a TAFKAL80ETC concert", sell_in=15, quality=20), Item(name="Conjured Mana Cake", sell_in=3, quality=6), ] - update_quality(items) \ No newline at end of file + + days = 2 + import sys + if len(sys.argv) > 1: + days = int(sys.argv[1]) + 1 + for day in range(days): + print("-------- day %s --------" % day) + print("name, sellIn, quality") + for item in items: + print(item) + print("") + update_quality(items) \ No newline at end of file From 7832dd745cf09db125c34e4fbb32a9209de5579c Mon Sep 17 00:00:00 2001 From: Emily Date: Mon, 20 Feb 2012 14:39:51 +0100 Subject: [PATCH 017/634] Adjusted the config file to work with the standard filename configuration, and a checkout location to reduce duplication. --- .../ThirtyDays/{errors.gr => stderr.gr} | 0 .../ThirtyDays/{output.gr => stdout.gr} | 0 GildedRose/texttests/config.gr | 17 ++++++++++------- GildedRose/texttests/environment.gr | 5 ++--- 4 files changed, 12 insertions(+), 10 deletions(-) rename GildedRose/texttests/ThirtyDays/{errors.gr => stderr.gr} (100%) rename GildedRose/texttests/ThirtyDays/{output.gr => stdout.gr} (100%) diff --git a/GildedRose/texttests/ThirtyDays/errors.gr b/GildedRose/texttests/ThirtyDays/stderr.gr similarity index 100% rename from GildedRose/texttests/ThirtyDays/errors.gr rename to GildedRose/texttests/ThirtyDays/stderr.gr diff --git a/GildedRose/texttests/ThirtyDays/output.gr b/GildedRose/texttests/ThirtyDays/stdout.gr similarity index 100% rename from GildedRose/texttests/ThirtyDays/output.gr rename to GildedRose/texttests/ThirtyDays/stdout.gr diff --git a/GildedRose/texttests/config.gr b/GildedRose/texttests/config.gr index d0821f77..52958b3d 100755 --- a/GildedRose/texttests/config.gr +++ b/GildedRose/texttests/config.gr @@ -1,18 +1,21 @@ full_name:Gilded Rose Refactoring Kata +# location where you have your clone +default_checkout:/home/emily/workspace/Refactoring-Katas/GildedRose + # Settings for the Java version executable:Main interpreter:java -# note you'll also need to update the file environment.gr with your classpath +# note you'll also need to update the file environment.gr with your classpath if you keep your classfiles somewhere unusual # Settings for the Python version -# note you should have the full path to your code here, not this example -#executable:/home/emily/workspace/Refactoring-Katas/GildedRose/python/gilded_rose.py +#executable:${TEXTTEST_CHECKOUT}/python/gilded_rose.py #interpreter:python - # turn on one of these if you prefer them to notepad or emacs. -#view_program:gedit -#view_program:mate +[view_program] +#*:mate +#*:gedit +[end] -file_convention_scheme:standard +filename_convention_scheme:standard diff --git a/GildedRose/texttests/environment.gr b/GildedRose/texttests/environment.gr index 92369c7c..d419d84d 100755 --- a/GildedRose/texttests/environment.gr +++ b/GildedRose/texttests/environment.gr @@ -1,3 +1,2 @@ -#CLASSPATH:/path/to/where/your/java/class/files/live -# eg: -CLASSPATH:/home/emily/workspace/Refactoring-Katas/GildedRose/Java \ No newline at end of file +# If your .class files are somewhere else, add the path to the list +CLASSPATH:${TEXTTEST_CHECKOUT}/Java:${TEXTTEST_CHECKOUT}/Java/bin From e8cfd96ccf8ab90afd457b98800511537f3ac731 Mon Sep 17 00:00:00 2001 From: Jonas Granquist Date: Sat, 25 Feb 2012 08:50:42 +0100 Subject: [PATCH 018/634] Move the code into a header file --- GildedRose/cpp/{GildedRose.cc => GildedRose.h} | 0 GildedRose/cpp/Makefile | 12 ++++++------ 2 files changed, 6 insertions(+), 6 deletions(-) rename GildedRose/cpp/{GildedRose.cc => GildedRose.h} (100%) diff --git a/GildedRose/cpp/GildedRose.cc b/GildedRose/cpp/GildedRose.h similarity index 100% rename from GildedRose/cpp/GildedRose.cc rename to GildedRose/cpp/GildedRose.h diff --git a/GildedRose/cpp/Makefile b/GildedRose/cpp/Makefile index e5e1d3e9..460e959d 100644 --- a/GildedRose/cpp/Makefile +++ b/GildedRose/cpp/Makefile @@ -12,7 +12,7 @@ # Points to the root of Google Test, relative to where this file is. # Remember to tweak this if you move this file. -GTEST_DIR = gtest +GTEST_DIR = ../../../googletest # Where to find user code. USER_DIR = . @@ -67,9 +67,9 @@ gtest_main.a : gtest-all.o gtest_main.o # gtest_main.a, depending on whether it defines its own main() # function. -GildedRose.o : $(USER_DIR)/GildedRose.cc \ - $(GTEST_HEADERS) - $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/GildedRose.cc +#GildedRose.o : $(USER_DIR)/GildedRose.h \ +# $(GTEST_HEADERS) +# $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/GildedRose.h -GildedRose : GildedRose.o gtest_main.a - $(CXX) $(CPPFLAGS) $(CXXFLAGS) -pthread $^ -o $@ +GildedRose : GildedRose.h gtest_main.a + $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(USER_DIR)/GildedRose.h -pthread $^ -o $@ From b6553ce2f19a770260f38de30f0e3290b8791536 Mon Sep 17 00:00:00 2001 From: Jonas Granquist Date: Sat, 25 Feb 2012 08:59:26 +0100 Subject: [PATCH 019/634] Moved gtest to a new file --- GildedRose/cpp/GildedRose.h | 10 ---------- GildedRose/cpp/GildedRoseUnitTests.cc | 12 ++++++++++++ GildedRose/cpp/Makefile | 4 ++-- 3 files changed, 14 insertions(+), 12 deletions(-) create mode 100644 GildedRose/cpp/GildedRoseUnitTests.cc diff --git a/GildedRose/cpp/GildedRose.h b/GildedRose/cpp/GildedRose.h index c3ebb814..0cb1bbf9 100644 --- a/GildedRose/cpp/GildedRose.h +++ b/GildedRose/cpp/GildedRose.h @@ -1,5 +1,3 @@ -#include - #include using namespace std; @@ -113,11 +111,3 @@ void example() } -TEST(GildedRoseTest, Foo) { - vector items; - items.push_back(Item("Foo", 0, 0)); - GildedRose app(items); - app.updateQuality(); - EXPECT_EQ("fixme", app.items[0].name); -} - diff --git a/GildedRose/cpp/GildedRoseUnitTests.cc b/GildedRose/cpp/GildedRoseUnitTests.cc new file mode 100644 index 00000000..000cc6b5 --- /dev/null +++ b/GildedRose/cpp/GildedRoseUnitTests.cc @@ -0,0 +1,12 @@ +#include + +#include "GildedRose.h" + +TEST(GildedRoseTest, Foo) { + vector items; + items.push_back(Item("Foo", 0, 0)); + GildedRose app(items); + app.updateQuality(); + EXPECT_EQ("fixme", app.items[0].name); +} + diff --git a/GildedRose/cpp/Makefile b/GildedRose/cpp/Makefile index 460e959d..56b3f6c3 100644 --- a/GildedRose/cpp/Makefile +++ b/GildedRose/cpp/Makefile @@ -71,5 +71,5 @@ gtest_main.a : gtest-all.o gtest_main.o # $(GTEST_HEADERS) # $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/GildedRose.h -GildedRose : GildedRose.h gtest_main.a - $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(USER_DIR)/GildedRose.h -pthread $^ -o $@ +GildedRose : GildedRoseUnitTests.cc gtest_main.a + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -pthread $^ -o $@ From c56f013f1d58fd66c2a4fa37b5bfa95d7bb93eed Mon Sep 17 00:00:00 2001 From: Jonas Granquist Date: Sat, 25 Feb 2012 09:14:10 +0100 Subject: [PATCH 020/634] Moved GildedRose implementation to new file GildedRose.cc --- GildedRose/cpp/GildedRose.cc | 80 ++++++++++++++++++++++ GildedRose/cpp/GildedRose.h | 95 +-------------------------- GildedRose/cpp/GildedRoseUnitTests.cc | 12 ++++ GildedRose/cpp/Makefile | 11 ++-- 4 files changed, 102 insertions(+), 96 deletions(-) create mode 100644 GildedRose/cpp/GildedRose.cc diff --git a/GildedRose/cpp/GildedRose.cc b/GildedRose/cpp/GildedRose.cc new file mode 100644 index 00000000..dd570b1a --- /dev/null +++ b/GildedRose/cpp/GildedRose.cc @@ -0,0 +1,80 @@ +#include "GildedRose.h" + +GildedRose::GildedRose(vector items) : items(items) +{} + +void GildedRose::updateQuality() +{ + for (int i = 0; i < items.size(); i++) + { + if (items[i].name != "Aged Brie" && items[i].name != "Backstage passes to a TAFKAL80ETC concert") + { + if (items[i].quality > 0) + { + if (items[i].name != "Sulfuras, Hand of Ragnaros") + { + items[i].quality = items[i].quality - 1; + } + } + } + else + { + if (items[i].quality < 50) + { + items[i].quality = items[i].quality + 1; + + if (items[i].name == "Backstage passes to a TAFKAL80ETC concert") + { + if (items[i].sellIn < 11) + { + if (items[i].quality < 50) + { + items[i].quality = items[i].quality + 1; + } + } + + if (items[i].sellIn < 6) + { + if (items[i].quality < 50) + { + items[i].quality = items[i].quality + 1; + } + } + } + } + } + + if (items[i].name != "Sulfuras, Hand of Ragnaros") + { + items[i].sellIn = items[i].sellIn - 1; + } + + if (items[i].sellIn < 0) + { + if (items[i].name != "Aged Brie") + { + if (items[i].name != "Backstage passes to a TAFKAL80ETC concert") + { + if (items[i].quality > 0) + { + if (items[i].name != "Sulfuras, Hand of Ragnaros") + { + items[i].quality = items[i].quality - 1; + } + } + } + else + { + items[i].quality = items[i].quality - items[i].quality; + } + } + else + { + if (items[i].quality < 50) + { + items[i].quality = items[i].quality + 1; + } + } + } + } +} diff --git a/GildedRose/cpp/GildedRose.h b/GildedRose/cpp/GildedRose.h index 0cb1bbf9..8d236457 100644 --- a/GildedRose/cpp/GildedRose.h +++ b/GildedRose/cpp/GildedRose.h @@ -1,4 +1,5 @@ #include +#include using namespace std; @@ -16,98 +17,8 @@ class GildedRose { public: vector items; - GildedRose(vector items) : items (items) - {} + GildedRose(vector items); - void updateQuality() - { - for (int i = 0; i < items.size(); i++) - { - if (items[i].name != "Aged Brie" && items[i].name != "Backstage passes to a TAFKAL80ETC concert") - { - if (items[i].quality > 0) - { - if (items[i].name != "Sulfuras, Hand of Ragnaros") - { - items[i].quality = items[i].quality - 1; - } - } - } - else - { - if (items[i].quality < 50) - { - items[i].quality = items[i].quality + 1; - - if (items[i].name == "Backstage passes to a TAFKAL80ETC concert") - { - if (items[i].sellIn < 11) - { - if (items[i].quality < 50) - { - items[i].quality = items[i].quality + 1; - } - } - - if (items[i].sellIn < 6) - { - if (items[i].quality < 50) - { - items[i].quality = items[i].quality + 1; - } - } - } - } - } - - if (items[i].name != "Sulfuras, Hand of Ragnaros") - { - items[i].sellIn = items[i].sellIn - 1; - } - - if (items[i].sellIn < 0) - { - if (items[i].name != "Aged Brie") - { - if (items[i].name != "Backstage passes to a TAFKAL80ETC concert") - { - if (items[i].quality > 0) - { - if (items[i].name != "Sulfuras, Hand of Ragnaros") - { - items[i].quality = items[i].quality - 1; - } - } - } - else - { - items[i].quality = items[i].quality - items[i].quality; - } - } - else - { - if (items[i].quality < 50) - { - items[i].quality = items[i].quality + 1; - } - } - } - } - } + void updateQuality(); }; - -void example() -{ - vector items; - items.push_back(Item("+5 Dexterity Vest", 10, 20)); - items.push_back(Item("Aged Brie", 2, 0)); - items.push_back(Item("Elixir of the Mongoose", 5, 7)); - items.push_back(Item("Sulfuras, Hand of Ragnaros", 0, 80)); - items.push_back(Item("Backstage passes to a TAFKAL80ETC concert", 15, 20)); - items.push_back(Item("Conjured Mana Cake", 3, 6)); - GildedRose app(items); - app.updateQuality(); -} - - diff --git a/GildedRose/cpp/GildedRoseUnitTests.cc b/GildedRose/cpp/GildedRoseUnitTests.cc index 000cc6b5..7e72d830 100644 --- a/GildedRose/cpp/GildedRoseUnitTests.cc +++ b/GildedRose/cpp/GildedRoseUnitTests.cc @@ -10,3 +10,15 @@ TEST(GildedRoseTest, Foo) { EXPECT_EQ("fixme", app.items[0].name); } +void example() +{ + vector items; + items.push_back(Item("+5 Dexterity Vest", 10, 20)); + items.push_back(Item("Aged Brie", 2, 0)); + items.push_back(Item("Elixir of the Mongoose", 5, 7)); + items.push_back(Item("Sulfuras, Hand of Ragnaros", 0, 80)); + items.push_back(Item("Backstage passes to a TAFKAL80ETC concert", 15, 20)); + items.push_back(Item("Conjured Mana Cake", 3, 6)); + GildedRose app(items); + app.updateQuality(); +} diff --git a/GildedRose/cpp/Makefile b/GildedRose/cpp/Makefile index 56b3f6c3..46c1eb6f 100644 --- a/GildedRose/cpp/Makefile +++ b/GildedRose/cpp/Makefile @@ -67,9 +67,12 @@ gtest_main.a : gtest-all.o gtest_main.o # gtest_main.a, depending on whether it defines its own main() # function. -#GildedRose.o : $(USER_DIR)/GildedRose.h \ -# $(GTEST_HEADERS) -# $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/GildedRose.h +GildedRose.o : $(USER_DIR)/GildedRose.cc + $(CXX) -c $^ -GildedRose : GildedRoseUnitTests.cc gtest_main.a +GildedRoseUnitTests.o : $(USER_DIR)/GildedRoseUnitTests.cc \ + $(GTEST_HEADERS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/GildedRoseUnitTests.cc + +GildedRose : GildedRoseUnitTests.o GildedRose.o gtest_main.a $(CXX) $(CPPFLAGS) $(CXXFLAGS) -pthread $^ -o $@ From 975c5edd7fdf129e5b37161b5657bda071efc85e Mon Sep 17 00:00:00 2001 From: Jonas Granquist Date: Sat, 25 Feb 2012 09:21:31 +0100 Subject: [PATCH 021/634] Added texttest --- GildedRose/cpp/GildedRoseTextTests.cc | 38 +++++++++++++++++++++++++++ GildedRose/cpp/Makefile | 12 +++++++-- 2 files changed, 48 insertions(+), 2 deletions(-) create mode 100644 GildedRose/cpp/GildedRoseTextTests.cc diff --git a/GildedRose/cpp/GildedRoseTextTests.cc b/GildedRose/cpp/GildedRoseTextTests.cc new file mode 100644 index 00000000..6a1366ed --- /dev/null +++ b/GildedRose/cpp/GildedRoseTextTests.cc @@ -0,0 +1,38 @@ +#include "GildedRose.h" + +#include + +using namespace std; + +ostream& operator<<(ostream& s, Item& item) +{ + s << item.name << ", " << item.sellIn << ", " << item.quality; + return s; +} + +int main() +{ + vector items; + items.push_back(Item("+5 Dexterity Vest", 10, 20)); + items.push_back(Item("Aged Brie", 2, 0)); + items.push_back(Item("Elixir of the Mongoose", 5, 7)); + items.push_back(Item("Sulfuras, Hand of Ragnaros", 0, 80)); + items.push_back(Item("Backstage passes to a TAFKAL80ETC concert", 15, 20)); + items.push_back(Item("Conjured Mana Cake", 3, 6)); + GildedRose app(items); + + cout << "OMGHAI!" << endl; + + for (int day = 0; day <= 30; day++) + { + cout << "-------- day " << day << " --------" << endl; + cout << "name, sellIn, quality" << endl; + for (vector::iterator i = items.begin(); i != items.end(); i++) + { + cout << *i << endl; + } + cout << endl; + + app.updateQuality(); + } +} diff --git a/GildedRose/cpp/Makefile b/GildedRose/cpp/Makefile index 46c1eb6f..d68fc1c6 100644 --- a/GildedRose/cpp/Makefile +++ b/GildedRose/cpp/Makefile @@ -27,6 +27,8 @@ CXXFLAGS += -g -Wall -Wextra # created to the list. TESTS = GildedRose +TEXTTESTS = GildedRoseTextTests + # All Google Test headers. Usually you shouldn't change this # definition. GTEST_HEADERS = $(GTEST_DIR)/include/gtest/*.h \ @@ -34,10 +36,10 @@ GTEST_HEADERS = $(GTEST_DIR)/include/gtest/*.h \ # House-keeping build targets. -all : $(TESTS) +all : $(TESTS) $(TEXTTESTS) clean : - rm -f $(TESTS) gtest.a gtest_main.a *.o + rm -f $(TESTS) $(TEXTTESTS) gtest.a gtest_main.a *.o # Builds gtest.a and gtest_main.a. @@ -76,3 +78,9 @@ GildedRoseUnitTests.o : $(USER_DIR)/GildedRoseUnitTests.cc \ GildedRose : GildedRoseUnitTests.o GildedRose.o gtest_main.a $(CXX) $(CPPFLAGS) $(CXXFLAGS) -pthread $^ -o $@ + +GildedRoseTextTests.o : $(USER_DIR)/GildedRoseTextTests.cc + $(CXX) -c $(USER_DIR)/GildedRoseTextTests.cc + +GildedRoseTextTests : GildedRoseTextTests.o GildedRose.o + $(CXX) -pthread $^ -o $@ From 072c37dd89d5556eb8e33910febed7cf9506386e Mon Sep 17 00:00:00 2001 From: Jonas Granquist Date: Sat, 25 Feb 2012 09:24:52 +0100 Subject: [PATCH 022/634] GildedRose class takes reference to items vector --- GildedRose/cpp/GildedRose.cc | 2 +- GildedRose/cpp/GildedRose.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/GildedRose/cpp/GildedRose.cc b/GildedRose/cpp/GildedRose.cc index dd570b1a..8df23e47 100644 --- a/GildedRose/cpp/GildedRose.cc +++ b/GildedRose/cpp/GildedRose.cc @@ -1,6 +1,6 @@ #include "GildedRose.h" -GildedRose::GildedRose(vector items) : items(items) +GildedRose::GildedRose(vector & items) : items(items) {} void GildedRose::updateQuality() diff --git a/GildedRose/cpp/GildedRose.h b/GildedRose/cpp/GildedRose.h index 8d236457..8464f87b 100644 --- a/GildedRose/cpp/GildedRose.h +++ b/GildedRose/cpp/GildedRose.h @@ -16,8 +16,8 @@ public: class GildedRose { public: - vector items; - GildedRose(vector items); + vector & items; + GildedRose(vector & items); void updateQuality(); }; From 5e873aeefdc6f437502a963d5a15ba1f30712d44 Mon Sep 17 00:00:00 2001 From: Jonas Granquist Date: Sat, 25 Feb 2012 10:18:01 +0100 Subject: [PATCH 023/634] Changed back to original googletest path --- GildedRose/cpp/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/GildedRose/cpp/Makefile b/GildedRose/cpp/Makefile index d68fc1c6..5ebc68d9 100644 --- a/GildedRose/cpp/Makefile +++ b/GildedRose/cpp/Makefile @@ -12,7 +12,7 @@ # Points to the root of Google Test, relative to where this file is. # Remember to tweak this if you move this file. -GTEST_DIR = ../../../googletest +GTEST_DIR = gtest # Where to find user code. USER_DIR = . @@ -80,7 +80,7 @@ GildedRose : GildedRoseUnitTests.o GildedRose.o gtest_main.a $(CXX) $(CPPFLAGS) $(CXXFLAGS) -pthread $^ -o $@ GildedRoseTextTests.o : $(USER_DIR)/GildedRoseTextTests.cc - $(CXX) -c $(USER_DIR)/GildedRoseTextTests.cc + $(CXX) -c $^ GildedRoseTextTests : GildedRoseTextTests.o GildedRose.o $(CXX) -pthread $^ -o $@ From bf68d49d55b6fcb906e2c1a14967d2b9177782e2 Mon Sep 17 00:00:00 2001 From: Andreas Ekeroot Date: Thu, 8 Mar 2012 11:53:56 +0100 Subject: [PATCH 024/634] Made print a function from the future. Added more items to cover all the branches of the code. --- GildedRose/python/gilded_rose.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/GildedRose/python/gilded_rose.py b/GildedRose/python/gilded_rose.py index 22f23a0d..129bad0a 100755 --- a/GildedRose/python/gilded_rose.py +++ b/GildedRose/python/gilded_rose.py @@ -1,3 +1,4 @@ +from __future__ import print_function def update_quality(items): for item in items: @@ -46,8 +47,11 @@ if __name__ == "__main__": Item(name="Aged Brie", sell_in=2, quality=0), Item(name="Elixir of the Mongoose", sell_in=5, quality=7), Item(name="Sulfuras, Hand of Ragnaros", sell_in=0, quality=80), + Item(name="Sulfuras, Hand of Ragnaros", sell_in=-1, quality=80), Item(name="Backstage passes to a TAFKAL80ETC concert", sell_in=15, quality=20), - Item(name="Conjured Mana Cake", sell_in=3, quality=6), + Item(name="Backstage passes to a TAFKAL80ETC concert", sell_in=10, quality=49), + Item(name="Backstage passes to a TAFKAL80ETC concert", sell_in=5, quality=49), + Item(name="Conjured Mana Cake", sell_in=3, quality=6), # <-- :O ] days = 2 @@ -60,4 +64,4 @@ if __name__ == "__main__": for item in items: print(item) print("") - update_quality(items) \ No newline at end of file + update_quality(items) From 88ef5a059e0284ab814df66a6ef988e33218764e Mon Sep 17 00:00:00 2001 From: Emily Bache Date: Wed, 28 Mar 2012 12:59:42 +0200 Subject: [PATCH 025/634] adding original csharp code to repo --- GildedRose/csharp/Program.cs | 124 +++++++++++++++++++++++++++++++++++ 1 file changed, 124 insertions(+) create mode 100644 GildedRose/csharp/Program.cs diff --git a/GildedRose/csharp/Program.cs b/GildedRose/csharp/Program.cs new file mode 100644 index 00000000..5b58730c --- /dev/null +++ b/GildedRose/csharp/Program.cs @@ -0,0 +1,124 @@ +using System.Collections.Generic; + +namespace GildedRose.Console +{ + class Program + { + IList Items; + static void Main(string[] args) + { + System.Console.WriteLine("OMGHAI!"); + + var app = new Program() + { + Items = new List + { + new Item {Name = "+5 Dexterity Vest", SellIn = 10, Quality = 20}, + new Item {Name = "Aged Brie", SellIn = 2, Quality = 0}, + new Item {Name = "Elixir of the Mongoose", SellIn = 5, Quality = 7}, + new Item {Name = "Sulfuras, Hand of Ragnaros", SellIn = 0, Quality = 80}, + new Item + { + Name = "Backstage passes to a TAFKAL80ETC concert", + SellIn = 15, + Quality = 20 + }, + new Item {Name = "Conjured Mana Cake", SellIn = 3, Quality = 6} + } + + }; + + app.UpdateQuality(); + + System.Console.ReadKey(); + + } + + public void UpdateQuality() + { + for (var i = 0; i < Items.Count; i++) + { + if (Items[i].Name != "Aged Brie" && Items[i].Name != "Backstage passes to a TAFKAL80ETC concert") + { + if (Items[i].Quality > 0) + { + if (Items[i].Name != "Sulfuras, Hand of Ragnaros") + { + Items[i].Quality = Items[i].Quality - 1; + } + } + } + else + { + if (Items[i].Quality < 50) + { + Items[i].Quality = Items[i].Quality + 1; + + if (Items[i].Name == "Backstage passes to a TAFKAL80ETC concert") + { + if (Items[i].SellIn < 11) + { + if (Items[i].Quality < 50) + { + Items[i].Quality = Items[i].Quality + 1; + } + } + + if (Items[i].SellIn < 6) + { + if (Items[i].Quality < 50) + { + Items[i].Quality = Items[i].Quality + 1; + } + } + } + } + } + + if (Items[i].Name != "Sulfuras, Hand of Ragnaros") + { + Items[i].SellIn = Items[i].SellIn - 1; + } + + if (Items[i].SellIn < 0) + { + if (Items[i].Name != "Aged Brie") + { + if (Items[i].Name != "Backstage passes to a TAFKAL80ETC concert") + { + if (Items[i].Quality > 0) + { + if (Items[i].Name != "Sulfuras, Hand of Ragnaros") + { + Items[i].Quality = Items[i].Quality - 1; + } + } + } + else + { + Items[i].Quality = Items[i].Quality - Items[i].Quality; + } + } + else + { + if (Items[i].Quality < 50) + { + Items[i].Quality = Items[i].Quality + 1; + } + } + } + } + } + + } + + public class Item + { + public string Name { get; set; } + + public int SellIn { get; set; } + + public int Quality { get; set; } + } + +} From c73ac70498ac75aa4933f2747b2f63ba4fe048e6 Mon Sep 17 00:00:00 2001 From: Emily Date: Wed, 28 Mar 2012 15:02:21 +0200 Subject: [PATCH 026/634] updating python, Java and cpp versions to all work with the same texttests --- GildedRose/Java/Main.java | 4 + GildedRose/cpp/GildedRoseTextTests.cc | 4 + GildedRose/texttests/ThirtyDays/stderr.gr | 0 GildedRose/texttests/ThirtyDays/stdout.gr | 93 +++++++++++++++++++++++ GildedRose/texttests/config.gr | 5 +- 5 files changed, 105 insertions(+), 1 deletion(-) mode change 100644 => 100755 GildedRose/texttests/ThirtyDays/stderr.gr diff --git a/GildedRose/Java/Main.java b/GildedRose/Java/Main.java index 87d79509..b227b7ed 100755 --- a/GildedRose/Java/Main.java +++ b/GildedRose/Java/Main.java @@ -7,7 +7,11 @@ public class Main { new Item("Aged Brie", 2, 0), new Item("Elixir of the Mongoose", 5, 7), new Item("Sulfuras, Hand of Ragnaros", 0, 80), + new Item("Sulfuras, Hand of Ragnaros", -1, 80), new Item("Backstage passes to a TAFKAL80ETC concert", 15, 20), + new Item("Backstage passes to a TAFKAL80ETC concert", 10, 49), + new Item("Backstage passes to a TAFKAL80ETC concert", 5, 49), + // this conjured item does not work properly yet new Item("Conjured Mana Cake", 3, 6) }; GildedRose app = new GildedRose(items); diff --git a/GildedRose/cpp/GildedRoseTextTests.cc b/GildedRose/cpp/GildedRoseTextTests.cc index 6a1366ed..182412a6 100644 --- a/GildedRose/cpp/GildedRoseTextTests.cc +++ b/GildedRose/cpp/GildedRoseTextTests.cc @@ -17,7 +17,11 @@ int main() items.push_back(Item("Aged Brie", 2, 0)); items.push_back(Item("Elixir of the Mongoose", 5, 7)); items.push_back(Item("Sulfuras, Hand of Ragnaros", 0, 80)); + items.push_back(Item("Sulfuras, Hand of Ragnaros", -1, 80)); items.push_back(Item("Backstage passes to a TAFKAL80ETC concert", 15, 20)); + items.push_back(Item("Backstage passes to a TAFKAL80ETC concert", 10, 49)); + items.push_back(Item("Backstage passes to a TAFKAL80ETC concert", 5, 49)); + // this Conjured item doesn't yet work properly items.push_back(Item("Conjured Mana Cake", 3, 6)); GildedRose app(items); diff --git a/GildedRose/texttests/ThirtyDays/stderr.gr b/GildedRose/texttests/ThirtyDays/stderr.gr old mode 100644 new mode 100755 diff --git a/GildedRose/texttests/ThirtyDays/stdout.gr b/GildedRose/texttests/ThirtyDays/stdout.gr index 9bfb34d9..a04e48ac 100644 --- a/GildedRose/texttests/ThirtyDays/stdout.gr +++ b/GildedRose/texttests/ThirtyDays/stdout.gr @@ -5,7 +5,10 @@ name, sellIn, quality Aged Brie, 2, 0 Elixir of the Mongoose, 5, 7 Sulfuras, Hand of Ragnaros, 0, 80 +Sulfuras, Hand of Ragnaros, -1, 80 Backstage passes to a TAFKAL80ETC concert, 15, 20 +Backstage passes to a TAFKAL80ETC concert, 10, 49 +Backstage passes to a TAFKAL80ETC concert, 5, 49 Conjured Mana Cake, 3, 6 -------- day 1 -------- @@ -14,7 +17,10 @@ name, sellIn, quality Aged Brie, 1, 1 Elixir of the Mongoose, 4, 6 Sulfuras, Hand of Ragnaros, 0, 80 +Sulfuras, Hand of Ragnaros, -1, 80 Backstage passes to a TAFKAL80ETC concert, 14, 21 +Backstage passes to a TAFKAL80ETC concert, 9, 50 +Backstage passes to a TAFKAL80ETC concert, 4, 50 Conjured Mana Cake, 2, 5 -------- day 2 -------- @@ -23,7 +29,10 @@ name, sellIn, quality Aged Brie, 0, 2 Elixir of the Mongoose, 3, 5 Sulfuras, Hand of Ragnaros, 0, 80 +Sulfuras, Hand of Ragnaros, -1, 80 Backstage passes to a TAFKAL80ETC concert, 13, 22 +Backstage passes to a TAFKAL80ETC concert, 8, 50 +Backstage passes to a TAFKAL80ETC concert, 3, 50 Conjured Mana Cake, 1, 4 -------- day 3 -------- @@ -32,7 +41,10 @@ name, sellIn, quality Aged Brie, -1, 4 Elixir of the Mongoose, 2, 4 Sulfuras, Hand of Ragnaros, 0, 80 +Sulfuras, Hand of Ragnaros, -1, 80 Backstage passes to a TAFKAL80ETC concert, 12, 23 +Backstage passes to a TAFKAL80ETC concert, 7, 50 +Backstage passes to a TAFKAL80ETC concert, 2, 50 Conjured Mana Cake, 0, 3 -------- day 4 -------- @@ -41,7 +53,10 @@ name, sellIn, quality Aged Brie, -2, 6 Elixir of the Mongoose, 1, 3 Sulfuras, Hand of Ragnaros, 0, 80 +Sulfuras, Hand of Ragnaros, -1, 80 Backstage passes to a TAFKAL80ETC concert, 11, 24 +Backstage passes to a TAFKAL80ETC concert, 6, 50 +Backstage passes to a TAFKAL80ETC concert, 1, 50 Conjured Mana Cake, -1, 1 -------- day 5 -------- @@ -50,7 +65,10 @@ name, sellIn, quality Aged Brie, -3, 8 Elixir of the Mongoose, 0, 2 Sulfuras, Hand of Ragnaros, 0, 80 +Sulfuras, Hand of Ragnaros, -1, 80 Backstage passes to a TAFKAL80ETC concert, 10, 25 +Backstage passes to a TAFKAL80ETC concert, 5, 50 +Backstage passes to a TAFKAL80ETC concert, 0, 50 Conjured Mana Cake, -2, 0 -------- day 6 -------- @@ -59,7 +77,10 @@ name, sellIn, quality Aged Brie, -4, 10 Elixir of the Mongoose, -1, 0 Sulfuras, Hand of Ragnaros, 0, 80 +Sulfuras, Hand of Ragnaros, -1, 80 Backstage passes to a TAFKAL80ETC concert, 9, 27 +Backstage passes to a TAFKAL80ETC concert, 4, 50 +Backstage passes to a TAFKAL80ETC concert, -1, 0 Conjured Mana Cake, -3, 0 -------- day 7 -------- @@ -68,7 +89,10 @@ name, sellIn, quality Aged Brie, -5, 12 Elixir of the Mongoose, -2, 0 Sulfuras, Hand of Ragnaros, 0, 80 +Sulfuras, Hand of Ragnaros, -1, 80 Backstage passes to a TAFKAL80ETC concert, 8, 29 +Backstage passes to a TAFKAL80ETC concert, 3, 50 +Backstage passes to a TAFKAL80ETC concert, -2, 0 Conjured Mana Cake, -4, 0 -------- day 8 -------- @@ -77,7 +101,10 @@ name, sellIn, quality Aged Brie, -6, 14 Elixir of the Mongoose, -3, 0 Sulfuras, Hand of Ragnaros, 0, 80 +Sulfuras, Hand of Ragnaros, -1, 80 Backstage passes to a TAFKAL80ETC concert, 7, 31 +Backstage passes to a TAFKAL80ETC concert, 2, 50 +Backstage passes to a TAFKAL80ETC concert, -3, 0 Conjured Mana Cake, -5, 0 -------- day 9 -------- @@ -86,7 +113,10 @@ name, sellIn, quality Aged Brie, -7, 16 Elixir of the Mongoose, -4, 0 Sulfuras, Hand of Ragnaros, 0, 80 +Sulfuras, Hand of Ragnaros, -1, 80 Backstage passes to a TAFKAL80ETC concert, 6, 33 +Backstage passes to a TAFKAL80ETC concert, 1, 50 +Backstage passes to a TAFKAL80ETC concert, -4, 0 Conjured Mana Cake, -6, 0 -------- day 10 -------- @@ -95,7 +125,10 @@ name, sellIn, quality Aged Brie, -8, 18 Elixir of the Mongoose, -5, 0 Sulfuras, Hand of Ragnaros, 0, 80 +Sulfuras, Hand of Ragnaros, -1, 80 Backstage passes to a TAFKAL80ETC concert, 5, 35 +Backstage passes to a TAFKAL80ETC concert, 0, 50 +Backstage passes to a TAFKAL80ETC concert, -5, 0 Conjured Mana Cake, -7, 0 -------- day 11 -------- @@ -104,7 +137,10 @@ name, sellIn, quality Aged Brie, -9, 20 Elixir of the Mongoose, -6, 0 Sulfuras, Hand of Ragnaros, 0, 80 +Sulfuras, Hand of Ragnaros, -1, 80 Backstage passes to a TAFKAL80ETC concert, 4, 38 +Backstage passes to a TAFKAL80ETC concert, -1, 0 +Backstage passes to a TAFKAL80ETC concert, -6, 0 Conjured Mana Cake, -8, 0 -------- day 12 -------- @@ -113,7 +149,10 @@ name, sellIn, quality Aged Brie, -10, 22 Elixir of the Mongoose, -7, 0 Sulfuras, Hand of Ragnaros, 0, 80 +Sulfuras, Hand of Ragnaros, -1, 80 Backstage passes to a TAFKAL80ETC concert, 3, 41 +Backstage passes to a TAFKAL80ETC concert, -2, 0 +Backstage passes to a TAFKAL80ETC concert, -7, 0 Conjured Mana Cake, -9, 0 -------- day 13 -------- @@ -122,7 +161,10 @@ name, sellIn, quality Aged Brie, -11, 24 Elixir of the Mongoose, -8, 0 Sulfuras, Hand of Ragnaros, 0, 80 +Sulfuras, Hand of Ragnaros, -1, 80 Backstage passes to a TAFKAL80ETC concert, 2, 44 +Backstage passes to a TAFKAL80ETC concert, -3, 0 +Backstage passes to a TAFKAL80ETC concert, -8, 0 Conjured Mana Cake, -10, 0 -------- day 14 -------- @@ -131,7 +173,10 @@ name, sellIn, quality Aged Brie, -12, 26 Elixir of the Mongoose, -9, 0 Sulfuras, Hand of Ragnaros, 0, 80 +Sulfuras, Hand of Ragnaros, -1, 80 Backstage passes to a TAFKAL80ETC concert, 1, 47 +Backstage passes to a TAFKAL80ETC concert, -4, 0 +Backstage passes to a TAFKAL80ETC concert, -9, 0 Conjured Mana Cake, -11, 0 -------- day 15 -------- @@ -140,7 +185,10 @@ name, sellIn, quality Aged Brie, -13, 28 Elixir of the Mongoose, -10, 0 Sulfuras, Hand of Ragnaros, 0, 80 +Sulfuras, Hand of Ragnaros, -1, 80 Backstage passes to a TAFKAL80ETC concert, 0, 50 +Backstage passes to a TAFKAL80ETC concert, -5, 0 +Backstage passes to a TAFKAL80ETC concert, -10, 0 Conjured Mana Cake, -12, 0 -------- day 16 -------- @@ -149,7 +197,10 @@ name, sellIn, quality Aged Brie, -14, 30 Elixir of the Mongoose, -11, 0 Sulfuras, Hand of Ragnaros, 0, 80 +Sulfuras, Hand of Ragnaros, -1, 80 Backstage passes to a TAFKAL80ETC concert, -1, 0 +Backstage passes to a TAFKAL80ETC concert, -6, 0 +Backstage passes to a TAFKAL80ETC concert, -11, 0 Conjured Mana Cake, -13, 0 -------- day 17 -------- @@ -158,7 +209,10 @@ name, sellIn, quality Aged Brie, -15, 32 Elixir of the Mongoose, -12, 0 Sulfuras, Hand of Ragnaros, 0, 80 +Sulfuras, Hand of Ragnaros, -1, 80 Backstage passes to a TAFKAL80ETC concert, -2, 0 +Backstage passes to a TAFKAL80ETC concert, -7, 0 +Backstage passes to a TAFKAL80ETC concert, -12, 0 Conjured Mana Cake, -14, 0 -------- day 18 -------- @@ -167,7 +221,10 @@ name, sellIn, quality Aged Brie, -16, 34 Elixir of the Mongoose, -13, 0 Sulfuras, Hand of Ragnaros, 0, 80 +Sulfuras, Hand of Ragnaros, -1, 80 Backstage passes to a TAFKAL80ETC concert, -3, 0 +Backstage passes to a TAFKAL80ETC concert, -8, 0 +Backstage passes to a TAFKAL80ETC concert, -13, 0 Conjured Mana Cake, -15, 0 -------- day 19 -------- @@ -176,7 +233,10 @@ name, sellIn, quality Aged Brie, -17, 36 Elixir of the Mongoose, -14, 0 Sulfuras, Hand of Ragnaros, 0, 80 +Sulfuras, Hand of Ragnaros, -1, 80 Backstage passes to a TAFKAL80ETC concert, -4, 0 +Backstage passes to a TAFKAL80ETC concert, -9, 0 +Backstage passes to a TAFKAL80ETC concert, -14, 0 Conjured Mana Cake, -16, 0 -------- day 20 -------- @@ -185,7 +245,10 @@ name, sellIn, quality Aged Brie, -18, 38 Elixir of the Mongoose, -15, 0 Sulfuras, Hand of Ragnaros, 0, 80 +Sulfuras, Hand of Ragnaros, -1, 80 Backstage passes to a TAFKAL80ETC concert, -5, 0 +Backstage passes to a TAFKAL80ETC concert, -10, 0 +Backstage passes to a TAFKAL80ETC concert, -15, 0 Conjured Mana Cake, -17, 0 -------- day 21 -------- @@ -194,7 +257,10 @@ name, sellIn, quality Aged Brie, -19, 40 Elixir of the Mongoose, -16, 0 Sulfuras, Hand of Ragnaros, 0, 80 +Sulfuras, Hand of Ragnaros, -1, 80 Backstage passes to a TAFKAL80ETC concert, -6, 0 +Backstage passes to a TAFKAL80ETC concert, -11, 0 +Backstage passes to a TAFKAL80ETC concert, -16, 0 Conjured Mana Cake, -18, 0 -------- day 22 -------- @@ -203,7 +269,10 @@ name, sellIn, quality Aged Brie, -20, 42 Elixir of the Mongoose, -17, 0 Sulfuras, Hand of Ragnaros, 0, 80 +Sulfuras, Hand of Ragnaros, -1, 80 Backstage passes to a TAFKAL80ETC concert, -7, 0 +Backstage passes to a TAFKAL80ETC concert, -12, 0 +Backstage passes to a TAFKAL80ETC concert, -17, 0 Conjured Mana Cake, -19, 0 -------- day 23 -------- @@ -212,7 +281,10 @@ name, sellIn, quality Aged Brie, -21, 44 Elixir of the Mongoose, -18, 0 Sulfuras, Hand of Ragnaros, 0, 80 +Sulfuras, Hand of Ragnaros, -1, 80 Backstage passes to a TAFKAL80ETC concert, -8, 0 +Backstage passes to a TAFKAL80ETC concert, -13, 0 +Backstage passes to a TAFKAL80ETC concert, -18, 0 Conjured Mana Cake, -20, 0 -------- day 24 -------- @@ -221,7 +293,10 @@ name, sellIn, quality Aged Brie, -22, 46 Elixir of the Mongoose, -19, 0 Sulfuras, Hand of Ragnaros, 0, 80 +Sulfuras, Hand of Ragnaros, -1, 80 Backstage passes to a TAFKAL80ETC concert, -9, 0 +Backstage passes to a TAFKAL80ETC concert, -14, 0 +Backstage passes to a TAFKAL80ETC concert, -19, 0 Conjured Mana Cake, -21, 0 -------- day 25 -------- @@ -230,7 +305,10 @@ name, sellIn, quality Aged Brie, -23, 48 Elixir of the Mongoose, -20, 0 Sulfuras, Hand of Ragnaros, 0, 80 +Sulfuras, Hand of Ragnaros, -1, 80 Backstage passes to a TAFKAL80ETC concert, -10, 0 +Backstage passes to a TAFKAL80ETC concert, -15, 0 +Backstage passes to a TAFKAL80ETC concert, -20, 0 Conjured Mana Cake, -22, 0 -------- day 26 -------- @@ -239,7 +317,10 @@ name, sellIn, quality Aged Brie, -24, 50 Elixir of the Mongoose, -21, 0 Sulfuras, Hand of Ragnaros, 0, 80 +Sulfuras, Hand of Ragnaros, -1, 80 Backstage passes to a TAFKAL80ETC concert, -11, 0 +Backstage passes to a TAFKAL80ETC concert, -16, 0 +Backstage passes to a TAFKAL80ETC concert, -21, 0 Conjured Mana Cake, -23, 0 -------- day 27 -------- @@ -248,7 +329,10 @@ name, sellIn, quality Aged Brie, -25, 50 Elixir of the Mongoose, -22, 0 Sulfuras, Hand of Ragnaros, 0, 80 +Sulfuras, Hand of Ragnaros, -1, 80 Backstage passes to a TAFKAL80ETC concert, -12, 0 +Backstage passes to a TAFKAL80ETC concert, -17, 0 +Backstage passes to a TAFKAL80ETC concert, -22, 0 Conjured Mana Cake, -24, 0 -------- day 28 -------- @@ -257,7 +341,10 @@ name, sellIn, quality Aged Brie, -26, 50 Elixir of the Mongoose, -23, 0 Sulfuras, Hand of Ragnaros, 0, 80 +Sulfuras, Hand of Ragnaros, -1, 80 Backstage passes to a TAFKAL80ETC concert, -13, 0 +Backstage passes to a TAFKAL80ETC concert, -18, 0 +Backstage passes to a TAFKAL80ETC concert, -23, 0 Conjured Mana Cake, -25, 0 -------- day 29 -------- @@ -266,7 +353,10 @@ name, sellIn, quality Aged Brie, -27, 50 Elixir of the Mongoose, -24, 0 Sulfuras, Hand of Ragnaros, 0, 80 +Sulfuras, Hand of Ragnaros, -1, 80 Backstage passes to a TAFKAL80ETC concert, -14, 0 +Backstage passes to a TAFKAL80ETC concert, -19, 0 +Backstage passes to a TAFKAL80ETC concert, -24, 0 Conjured Mana Cake, -26, 0 -------- day 30 -------- @@ -275,6 +365,9 @@ name, sellIn, quality Aged Brie, -28, 50 Elixir of the Mongoose, -25, 0 Sulfuras, Hand of Ragnaros, 0, 80 +Sulfuras, Hand of Ragnaros, -1, 80 Backstage passes to a TAFKAL80ETC concert, -15, 0 +Backstage passes to a TAFKAL80ETC concert, -20, 0 +Backstage passes to a TAFKAL80ETC concert, -25, 0 Conjured Mana Cake, -27, 0 diff --git a/GildedRose/texttests/config.gr b/GildedRose/texttests/config.gr index 52958b3d..733e5ab4 100755 --- a/GildedRose/texttests/config.gr +++ b/GildedRose/texttests/config.gr @@ -12,10 +12,13 @@ interpreter:java #executable:${TEXTTEST_CHECKOUT}/python/gilded_rose.py #interpreter:python +# Settings for the C++ version +#executable:${TEXTTEST_CHECKOUT}/cpp/GildedRoseTextTests + # turn on one of these if you prefer them to notepad or emacs. [view_program] #*:mate -#*:gedit +*:gedit [end] filename_convention_scheme:standard From 1c2ef84b66d9fcbdc8640534beded593eef17ef7 Mon Sep 17 00:00:00 2001 From: Emily Bache Date: Wed, 28 Mar 2012 19:41:41 +0200 Subject: [PATCH 027/634] Adding Ruby version of the exercise --- GildedRose/ruby/gilded_rose.rb | 67 +++++++++++++++++++++++++++++ GildedRose/ruby/gilded_rose_spec.rb | 13 ++++++ GildedRose/ruby/main.rb | 33 ++++++++++++++ 3 files changed, 113 insertions(+) create mode 100755 GildedRose/ruby/gilded_rose.rb create mode 100644 GildedRose/ruby/gilded_rose_spec.rb create mode 100644 GildedRose/ruby/main.rb diff --git a/GildedRose/ruby/gilded_rose.rb b/GildedRose/ruby/gilded_rose.rb new file mode 100755 index 00000000..43b43a10 --- /dev/null +++ b/GildedRose/ruby/gilded_rose.rb @@ -0,0 +1,67 @@ + +class GildedRose + def update_quality(items) + items.each do |item| + if item.name != "Aged Brie" and item.name != "Backstage passes to a TAFKAL80ETC concert" + if item.quality > 0 + if item.name != "Sulfuras, Hand of Ragnaros" + item.quality = item.quality - 1 + end + end + else + if item.quality < 50 + item.quality = item.quality + 1 + if item.name == "Backstage passes to a TAFKAL80ETC concert" + if item.sell_in < 11 + if item.quality < 50 + item.quality = item.quality + 1 + end + end + if item.sell_in < 6 + if item.quality < 50 + item.quality = item.quality + 1 + end + end + end + end + end + if item.name != "Sulfuras, Hand of Ragnaros" + item.sell_in = item.sell_in - 1 + end + if item.sell_in < 0 + if item.name != "Aged Brie" + if item.name != "Backstage passes to a TAFKAL80ETC concert" + if item.quality > 0 + if item.name != "Sulfuras, Hand of Ragnaros" + item.quality = item.quality - 1 + end + end + else + item.quality = item.quality - item.quality + end + else + if item.quality < 50 + item.quality = item.quality + 1 + end + end + end + end + items + end +end + +class Item + attr_accessor :name, :sell_in, :quality + + def initialize(name, sell_in, quality) + @name = name + @sell_in = sell_in + @quality = quality + end + + def to_s() + "#{@name}, #{@sell_in}, #{@quality}" + end +end + + diff --git a/GildedRose/ruby/gilded_rose_spec.rb b/GildedRose/ruby/gilded_rose_spec.rb new file mode 100644 index 00000000..a84947d1 --- /dev/null +++ b/GildedRose/ruby/gilded_rose_spec.rb @@ -0,0 +1,13 @@ + +require File.join(File.dirname(__FILE__), 'gilded_rose') + + +describe GildedRose do + + describe "#update_quality" do + items = [Item.new("foo", 0, 0)] + GildedRose.new().update_quality(items) + items[0].name.should == "fixme" + end + +end diff --git a/GildedRose/ruby/main.rb b/GildedRose/ruby/main.rb new file mode 100644 index 00000000..a5426bbb --- /dev/null +++ b/GildedRose/ruby/main.rb @@ -0,0 +1,33 @@ +#!/usr/bin/ruby -w + +require File.join(File.dirname(__FILE__), 'gilded_rose') + +puts "OMGHAI!" +items = [ + Item.new(name="+5 Dexterity Vest", sell_in=10, quality=20), + Item.new(name="Aged Brie", sell_in=2, quality=0), + Item.new(name="Elixir of the Mongoose", sell_in=5, quality=7), + Item.new(name="Sulfuras, Hand of Ragnaros", sell_in=0, quality=80), + Item.new(name="Sulfuras, Hand of Ragnaros", sell_in=-1, quality=80), + Item.new(name="Backstage passes to a TAFKAL80ETC concert", sell_in=15, quality=20), + Item.new(name="Backstage passes to a TAFKAL80ETC concert", sell_in=10, quality=49), + Item.new(name="Backstage passes to a TAFKAL80ETC concert", sell_in=5, quality=49), + # This Conjured item does not work properly yet + Item.new(name="Conjured Mana Cake", sell_in=3, quality=6), # <-- :O + ] + +days = 2 +if ARGV.size > 0: + days = ARGV[0].to_i + 1 +end + +gilded_rose = GildedRose.new +(0...days).each do |day| + puts "-------- day #{day} --------" + puts "name, sellIn, quality" + items.each do |item| + puts item + end + puts "" + gilded_rose.update_quality(items) +end From df0d688718df56c6de3229a36bc397bbe2cbf98a Mon Sep 17 00:00:00 2001 From: Emily Bache Date: Wed, 28 Mar 2012 19:53:44 +0200 Subject: [PATCH 028/634] config settings to run the ruby version with the texttests --- GildedRose/texttests/config.gr | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/GildedRose/texttests/config.gr b/GildedRose/texttests/config.gr index 733e5ab4..532a7d4a 100755 --- a/GildedRose/texttests/config.gr +++ b/GildedRose/texttests/config.gr @@ -4,8 +4,8 @@ full_name:Gilded Rose Refactoring Kata default_checkout:/home/emily/workspace/Refactoring-Katas/GildedRose # Settings for the Java version -executable:Main -interpreter:java +#executable:Main +#interpreter:java # note you'll also need to update the file environment.gr with your classpath if you keep your classfiles somewhere unusual # Settings for the Python version @@ -15,6 +15,10 @@ interpreter:java # Settings for the C++ version #executable:${TEXTTEST_CHECKOUT}/cpp/GildedRoseTextTests +# Settings for the Ruby version +executable:${TEXTTEST_CHECKOUT}/ruby/main.rb +interpreter:ruby + # turn on one of these if you prefer them to notepad or emacs. [view_program] #*:mate From 2e5a38d0008a50d595436cb7a7bf00d62ea8747c Mon Sep 17 00:00:00 2001 From: Emily Bache Date: Wed, 28 Mar 2012 20:59:53 +0200 Subject: [PATCH 029/634] make c sharp version work together with texttests --- GildedRose/csharp/Program.cs | 27 +++++++++++++++++++++++++-- GildedRose/texttests/config.gr | 7 +++++-- 2 files changed, 30 insertions(+), 4 deletions(-) diff --git a/GildedRose/csharp/Program.cs b/GildedRose/csharp/Program.cs index 5b58730c..3ba8371e 100644 --- a/GildedRose/csharp/Program.cs +++ b/GildedRose/csharp/Program.cs @@ -17,19 +17,42 @@ namespace GildedRose.Console new Item {Name = "Aged Brie", SellIn = 2, Quality = 0}, new Item {Name = "Elixir of the Mongoose", SellIn = 5, Quality = 7}, new Item {Name = "Sulfuras, Hand of Ragnaros", SellIn = 0, Quality = 80}, + new Item {Name = "Sulfuras, Hand of Ragnaros", SellIn = -1, Quality = 80}, new Item { Name = "Backstage passes to a TAFKAL80ETC concert", SellIn = 15, Quality = 20 }, + new Item + { + Name = "Backstage passes to a TAFKAL80ETC concert", + SellIn = 10, + Quality = 49 + }, + new Item + { + Name = "Backstage passes to a TAFKAL80ETC concert", + SellIn = 5, + Quality = 49 + }, + // this conjured item does not work properly yet new Item {Name = "Conjured Mana Cake", SellIn = 3, Quality = 6} } }; - app.UpdateQuality(); - + for (var i = 0; i < 31; i++) + { + System.Console.WriteLine("-------- day " + i + " --------"); + System.Console.WriteLine("name, sellIn, quality"); + for (var j = 0; j < app.Items.Count; j++) + { + System.Console.WriteLine(app.Items[j].Name + ", " + app.Items[j].SellIn + ", " + app.Items[j].Quality); + } + System.Console.WriteLine(""); + app.UpdateQuality(); + } System.Console.ReadKey(); } diff --git a/GildedRose/texttests/config.gr b/GildedRose/texttests/config.gr index 532a7d4a..a5b31f77 100755 --- a/GildedRose/texttests/config.gr +++ b/GildedRose/texttests/config.gr @@ -16,8 +16,11 @@ default_checkout:/home/emily/workspace/Refactoring-Katas/GildedRose #executable:${TEXTTEST_CHECKOUT}/cpp/GildedRoseTextTests # Settings for the Ruby version -executable:${TEXTTEST_CHECKOUT}/ruby/main.rb -interpreter:ruby +#executable:${TEXTTEST_CHECKOUT}/ruby/main.rb +#interpreter:ruby + +# Settings for the C# version +executable:${TEXTTEST_CHECKOUT}/csharp/Program.exe # turn on one of these if you prefer them to notepad or emacs. [view_program] From bf68436e113f288d25bbed99437e8cbe401a678e Mon Sep 17 00:00:00 2001 From: Emily Bache Date: Wed, 4 Apr 2012 13:42:26 +0200 Subject: [PATCH 030/634] Improving the documentation, especially around text-based testing --- GildedRose/README | 32 ++++++++++++++++++++++++++++---- GildedRose/texttests/README | 37 +++++++++++++++++++++++++++++++++++++ README | 4 +++- 3 files changed, 68 insertions(+), 5 deletions(-) create mode 100644 GildedRose/texttests/README diff --git a/GildedRose/README b/GildedRose/README index 87ab2511..45accd75 100644 --- a/GildedRose/README +++ b/GildedRose/README @@ -1,10 +1,34 @@ -This Kata was originally created by Terry Hughes (http://twitter.com/#!/TerryHughes). It is already on GitHub as "GildedRose", a sample project for C#. I could have forked it again, but I thought other language users might not want to download a whole C# project environment. In this repository are starting code samples for Java, Python and C++. +This Kata was originally created by Terry Hughes (http://twitter.com/#!/TerryHughes). It is already on GitHub as "GildedRose", a sample project for C#. I could have forked it again, but I thought other language users might not want to download a whole C# project environment. In this repository are starting code samples for Java, Python, Ruby, C# and C++. See also http://iamnotmyself.com/2011/02/13/refactor-this-the-gilded-rose-kata/ -================ -Gilded Rose Kata -================ +==================== +How to use this Kata +==================== + +The simplest way is to just clone the code and start hacking away improving the design. I strongly advise you that you'll need some tests if you want to make sure you don't break the code in the process though. + +You could write some unit tests yourself, using the Kata Background Reading (below) to identify suitable test cases. I've provided a failing unit test in a popular test framework as a starting point for most languages. + +Alternatively, use the "Text-Based" tests provided in this repository. (Read more about that in the next section) + +Whichever testing approach you choose, the idea of the exercise is to do some deliberate practice, and improve your Refactoring skills. The idea is not to re-write the code from scratch, but rather to practice taking small steps, running the tests often, and incrementally improving the design. + +================== +Text-Based Testing +================== + +This is a testing approach which is very useful when refactoring legacy code. The basic idea is to create tests that use the text which the code produces. Before you change the code, you run it, and save the output as a "Golden Copy". Then after you change the code, you run it again, and compare the output against the Golden Copy. Any differences, and the test fails. + +It's basically the same idea as "assertEquals(expected, actual)" in a unit test, except the text you are comparing is typically much longer, and the "expected" value is saved from actual output, rather than being defined in advance. + +Typically a piece of legacy code may not produce suitable textual output from the start, so you may need to modify it before you can write your first text-based test. That could involve inserting log statements into the code, or just writing a "main" method that executes the code and prints out what the result is afterwards. It's this latter approach we are using here to test GildedRose. + +The Text-Based tests in this repository are designed to be used with the tool "TextTest" (http://texttest.org). This tool helps you to organize and run text-based tests. There is more information in the README file in the "texttests" subdirectory. + +=================================== +Gilded Rose Kata Background Reading +=================================== Hi and welcome to team Gilded Rose. As you know, we are a small inn with a prime location in a prominent city ran by a friendly innkeeper named Allison. We also buy and sell only the finest goods. Unfortunately, our goods are constantly degrading in quality as they approach their sell by date. We have a system in place that updates our inventory for us. It was developed by a no-nonsense type named Leeroy, who has moved on to new adventures. Your task is to add the new feature to our system so that we can begin selling a new category of items. First an introduction to our system: diff --git a/GildedRose/texttests/README b/GildedRose/texttests/README new file mode 100644 index 00000000..fa903565 --- /dev/null +++ b/GildedRose/texttests/README @@ -0,0 +1,37 @@ +This folder contains Text-Based tests for the GildedRose Refactoring Kata. + +These tests are designed to be used with the open source testing tool "TextTest", available from http://texttest.org You can run them without it too though, see below. + +======================== +Running without TextTest +======================== + +This should be perfectly possible, but is probably less convenient than using TextTest. + +Write a script that will execute the SUT (see "config.gr" for details of the executables), giving the commandline options listed in "options.gr". Collect the output from standard output in a file, and diff that against the golden copy "stdout.gr". Any diff is a test failure. + +===================== +Running with TextTest +===================== + +- Install TextTest (see http://texttest.org) +- set $TEXTTEST_HOME environment variable to point at the "texttests" folder +- run texttest using a command like "python texttest.py -a gr" + +This should start the GUI for the TextTest tool. + +Each test case has it's own subdirectory. The name of the directory is the name of the test - in this case "ThirtyDays". The "Golden Copy" of the output for that test case is kept in that directory. In this case we have three files: + +stderr.gr - the expected output to Standard Error (stderr) +stdout.gr - the expected output to Standard Output (stdout) +options.gr - the options to give on the command line when you run the System Under Test (SUT) + +In the directory above, there are configuration files for TextTest: + +config.gr - this tells TextTest where to find the SUT executable, and sets up options for how it runs the SUT and interprets the output. +environment.gr - this file lists environment variables that will be set before TextTest runs the SUT. This is especially important for Java applications, that must set the CLASSPATH environment variable in order to run properly. +testsuite.gr - lists the constituent test cases of this suite. Change the order of the entries here to change the order they appear in the TextTest GUI. + +To run a test, click on it in the GUI and select "Run". TextTest will run it in a temporary (sandbox) directory and report the results. If the test fails, you can double click on a file to see the diff against the Golden Copy. + + diff --git a/README b/README index 1675c9c5..310d3eb2 100644 --- a/README +++ b/README @@ -1,6 +1,8 @@ +Can you refactor? In really small steps? Can you turn some, frankly, ugly code into a paradigm of elegant, readable, extensible design? + This is a collection of starting files for when practicing refactoring. Contents so far: Tennis Kata in Java, Python and C++. -Gilded Rose Kata in Java, Python and C++. (a C# version is already available on github) \ No newline at end of file +Gilded Rose Kata in C++, C#, Java, Python and Ruby. (a C# version together with a starting project is already available on github) \ No newline at end of file From 4d87cac40df033fb94f74f643ec49136d8df978e Mon Sep 17 00:00:00 2001 From: Emily Bache Date: Wed, 4 Apr 2012 13:45:58 +0200 Subject: [PATCH 031/634] removing unwanted files that got here by accident --- GildedRose/texttests/._config.gr | Bin 4096 -> 0 bytes GildedRose/texttests/._environment.gr | Bin 4096 -> 0 bytes GildedRose/texttests/._testsuite.gr | Bin 4096 -> 0 bytes 3 files changed, 0 insertions(+), 0 deletions(-) delete mode 100755 GildedRose/texttests/._config.gr delete mode 100755 GildedRose/texttests/._environment.gr delete mode 100755 GildedRose/texttests/._testsuite.gr diff --git a/GildedRose/texttests/._config.gr b/GildedRose/texttests/._config.gr deleted file mode 100755 index 05c1b19e8f0ad2fec8b155dc875ced3a8f4603bd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4096 zcmZQz6=P>$Vqox1Ojhs@R)|o50+1L3ClDJkFz{^v(m+1nBL)UWIUt(=a103vvYvJF zKST$^44`r)G%bukK2%&ZIX_n~H!-;=KR2-?wOB7Xu_(2Kp_&WikmUTF(%d`+TLlAa zFh3_VFBQl$G_&TaMKf`fI~oF`Aut*OqaiRF0;3@?8UmvsFd71*Aut*OqaiTjLjcs- z1Yt0c3(3eVRwzm>&Mz%WPE|$Vqox1Ojhs@R)|o50+1L3ClDJkFz{^v(m+1nBL)UWIUt(=a103vvYvJF zKST$^44`r)G%bukK2%&ZIX_n~H!-;=KR2-?wOB7Xu_(2Kp_&WikmUTF(%d`+TLoiN zYp_60W?m|gYhcY)i)P{|cQgb>Ltr!nMnhmU1V%$(Gz3ONU^E0qLtr!nMnho4hXAOv z3Bq6?7m|@#tWcC%oL^d$oT`wPUzDwonOBmUSCW~Zmza}NsgRSJR-%xUlbDwc?14gc R4QUG1|8TF!Fv$J?4*-sUFJAxv diff --git a/GildedRose/texttests/._testsuite.gr b/GildedRose/texttests/._testsuite.gr deleted file mode 100755 index 9c4f9870ed67e7fbd23c2e36667e95c1a148a5b1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4096 zcmZQz6=P>$Vqox1Ojhs@R)|o50+1L3ClDJkFz{^v(m+1nBL)UWIUt(=a103vvYvJF zKST$^44`r)G%bukK2%&ZIX_n~H!-;=KR2-?wOB7Xu_(2Kp_&WikmUTF(%d`+TLlYK zYp_60W?m|gYhcY)i)P{|cQgb>Ltr!nMnhmU1V%$(Gz3ONU^E0qLtr!nMnho4hXAOv z3Bq6?7m|@#tWcC%oL^d$oT`wPUzDwonOBmUSCW~Zmza}NsgRSJR-%xUlbDwc?14gc R4QUG1|8TF!Fv$J?4*=UeFJu4! From 14303cc7e05e3dfeb75f1ffe1ca810c68348642b Mon Sep 17 00:00:00 2001 From: Emily Bache Date: Wed, 4 Apr 2012 14:30:27 +0200 Subject: [PATCH 032/634] Small tweak to text --- GildedRose/README | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/GildedRose/README b/GildedRose/README index 45accd75..bf54061f 100644 --- a/GildedRose/README +++ b/GildedRose/README @@ -6,7 +6,7 @@ See also http://iamnotmyself.com/2011/02/13/refactor-this-the-gilded-rose-kata/ How to use this Kata ==================== -The simplest way is to just clone the code and start hacking away improving the design. I strongly advise you that you'll need some tests if you want to make sure you don't break the code in the process though. +The simplest way is to just clone the code and start hacking away improving the design. You'll want to look at the "Gilded Rose Background Reading" (below) which explains what the code is for. I strongly advise you that you'll also need some tests if you want to make sure you don't break the code while you refactor. You could write some unit tests yourself, using the Kata Background Reading (below) to identify suitable test cases. I've provided a failing unit test in a popular test framework as a starting point for most languages. From 2eb0418b0381c853359cd99e032c16fb66dd1ad5 Mon Sep 17 00:00:00 2001 From: leider Date: Sat, 21 Apr 2012 17:09:11 +0200 Subject: [PATCH 033/634] Smalltalk version created --- GildedRose/Smalltalk/GildedRose.st | 1 + 1 file changed, 1 insertion(+) create mode 100644 GildedRose/Smalltalk/GildedRose.st diff --git a/GildedRose/Smalltalk/GildedRose.st b/GildedRose/Smalltalk/GildedRose.st new file mode 100644 index 00000000..99a06db0 --- /dev/null +++ b/GildedRose/Smalltalk/GildedRose.st @@ -0,0 +1 @@ +Object subclass: #GildedRose instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'GildedRose'! !GildedRose commentStamp: 'AndreasLeidig 4/21/2012 15:38' prior: 0! This Kata was originally created by Terry Hughes (http://twitter.com/#!!/TerryHughes). It is already on GitHub as "GildedRose", a sample project for C#. I could have forked it again, but I thought other language users might not want to download a whole C# project environment. In this repository are starting code samples for Java, Python, Ruby, C# and C++. See also http://iamnotmyself.com/2011/02/13/refactor-this-the-gilded-rose-kata/ ==================== How to use this Kata ==================== The simplest way is to just clone the code and start hacking away improving the design. You'll want to look at the "Gilded Rose Background Reading" (below) which explains what the code is for. I strongly advise you that you'll also need some tests if you want to make sure you don't break the code while you refactor. You could write some unit tests yourself, using the Kata Background Reading (below) to identify suitable test cases. I've provided a failing unit test in a popular test framework as a starting point for most languages. Alternatively, use the "Text-Based" tests provided in this repository. (Read more about that in the next section) Whichever testing approach you choose, the idea of the exercise is to do some deliberate practice, and improve your Refactoring skills. The idea is not to re-write the code from scratch, but rather to practice taking small steps, running the tests often, and incrementally improving the design. ================== Text-Based Testing ================== This is a testing approach which is very useful when refactoring legacy code. The basic idea is to create tests that use the text which the code produces. Before you change the code, you run it, and save the output as a "Golden Copy". Then after you change the code, you run it again, and compare the output against the Golden Copy. Any differences, and the test fails. It's basically the same idea as "assertEquals(expected, actual)" in a unit test, except the text you are comparing is typically much longer, and the "expected" value is saved from actual output, rather than being defined in advance. Typically a piece of legacy code may not produce suitable textual output from the start, so you may need to modify it before you can write your first text-based test. That could involve inserting log statements into the code, or just writing a "main" method that executes the code and prints out what the result is afterwards. It's this latter approach we are using here to test GildedRose. The Text-Based tests in this repository are designed to be used with the tool "TextTest" (http://texttest.org). This tool helps you to organize and run text-based tests. There is more information in the README file in the "texttests" subdirectory. =================================== Gilded Rose Kata Background Reading =================================== Hi and welcome to team Gilded Rose. As you know, we are a small inn with a prime location in a prominent city ran by a friendly innkeeper named Allison. We also buy and sell only the finest goods. Unfortunately, our goods are constantly degrading in quality as they approach their sell by date. We have a system in place that updates our inventory for us. It was developed by a no-nonsense type named Leeroy, who has moved on to new adventures. Your task is to add the new feature to our system so that we can begin selling a new category of items. First an introduction to our system: - All items have a SellIn value which denotes the number of days we have to sell the item - All items have a Quality value which denotes how valuable the item is - At the end of each day our system lowers both values for every item Pretty simple, right? Well this is where it gets interesting: - Once the sell by date has passed, Quality degrades twice as fast - The Quality of an item is never negative - "Aged Brie" actually increases in Quality the older it gets - The Quality of an item is never more than 50 - "Sulfuras", being a legendary item, never has to be sold or decreases in Quality - "Backstage passes", like aged brie, increases in Quality as it's SellIn value approaches; Quality increases by 2 when there are 10 days or less and by 3 when there are 5 days or less but Quality drops to 0 after the concert We have recently signed a supplier of conjured items. This requires an update to our system: - "Conjured" items degrade in Quality twice as fast as normal items Feel free to make any changes to the UpdateQuality method and add any new code as long as everything still works correctly. However, do not alter the Item class or Items property as those belong to the goblin in the corner who will insta-rage and one-shot you as he doesn't believe in shared code ownership (you can make the UpdateQuality method and Items property static if you like, we'll cover for you). Just for clarification, an item can never have its Quality increase above 50, however "Sulfuras" is a legendary item and as such its Quality is 80 and it never alters.! !GildedRose methodsFor: 'API' stamp: 'AndreasLeidig 4/21/2012 17:02'! updateQualityFor: items items do: [:item | (item name ~= 'Aged Brie' and: [item name ~= 'Backstage passes to a TAFKAL80ETC concert']) ifTrue: [item quality > 0 ifTrue: [item name ~= 'Sulfuras, Hand of Ragnaros' ifTrue: [item quality: item quality - 1]]] ifFalse: [item quality < 50 ifTrue: [item quality: item quality + 1. item name = 'Backstage passes to a TAFKAL80ETC concert' ifTrue: [item sellIn < 11 ifTrue: [item quality < 50 ifTrue: [item quality: item quality + 1]]. item sellIn < 6 ifTrue: [item quality < 50 ifTrue: [item quality: item quality + 1]]]]]. item name ~= 'Sulfuras, Hand of Ragnaros' ifTrue: [item sellIn: item sellIn - 1]. item sellIn < 0 ifTrue: [item name ~= 'Aged Brie' ifTrue: [item name ~= 'Backstage passes to a TAFKAL80ETC concert' ifTrue: [item quality > 0 ifTrue: [item name ~= 'Sulfuras, Hand of Ragnaros' ifTrue: [item quality: item quality - 1]]] ifFalse: [item quality: item quality - item quality]] ifFalse: [item quality < 50 ifTrue: [item quality: item quality + 1]]]]! ! Object subclass: #Item instanceVariableNames: 'name sellIn quality' classVariableNames: '' poolDictionaries: '' category: 'GildedRose'! !Item methodsFor: 'accessing' stamp: 'AndreasLeidig 4/21/2012 15:40'! name ^name! ! !Item methodsFor: 'accessing' stamp: 'AndreasLeidig 4/21/2012 15:41'! name: aString name := aString! ! !Item methodsFor: 'accessing' stamp: 'AndreasLeidig 4/21/2012 15:41'! quality ^quality! ! !Item methodsFor: 'accessing' stamp: 'AndreasLeidig 4/21/2012 15:42'! quality: aNumber quality := aNumber! ! !Item methodsFor: 'accessing' stamp: 'AndreasLeidig 4/21/2012 15:41'! sellIn ^sellIn! ! !Item methodsFor: 'accessing' stamp: 'AndreasLeidig 4/21/2012 15:42'! sellIn: aNumber sellIn := aNumber ! ! \ No newline at end of file From e7b2e2a3ad27a6eb34ee64eb772835746eb99f19 Mon Sep 17 00:00:00 2001 From: leider Date: Sat, 21 Apr 2012 20:31:21 +0200 Subject: [PATCH 034/634] added Transcript output --- GildedRose/Smalltalk/GildedRose.st | 2 +- GildedRose/texttests/.DS_Store | Bin 0 -> 6148 bytes 2 files changed, 1 insertion(+), 1 deletion(-) create mode 100644 GildedRose/texttests/.DS_Store diff --git a/GildedRose/Smalltalk/GildedRose.st b/GildedRose/Smalltalk/GildedRose.st index 99a06db0..8be7cd18 100644 --- a/GildedRose/Smalltalk/GildedRose.st +++ b/GildedRose/Smalltalk/GildedRose.st @@ -1 +1 @@ -Object subclass: #GildedRose instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'GildedRose'! !GildedRose commentStamp: 'AndreasLeidig 4/21/2012 15:38' prior: 0! This Kata was originally created by Terry Hughes (http://twitter.com/#!!/TerryHughes). It is already on GitHub as "GildedRose", a sample project for C#. I could have forked it again, but I thought other language users might not want to download a whole C# project environment. In this repository are starting code samples for Java, Python, Ruby, C# and C++. See also http://iamnotmyself.com/2011/02/13/refactor-this-the-gilded-rose-kata/ ==================== How to use this Kata ==================== The simplest way is to just clone the code and start hacking away improving the design. You'll want to look at the "Gilded Rose Background Reading" (below) which explains what the code is for. I strongly advise you that you'll also need some tests if you want to make sure you don't break the code while you refactor. You could write some unit tests yourself, using the Kata Background Reading (below) to identify suitable test cases. I've provided a failing unit test in a popular test framework as a starting point for most languages. Alternatively, use the "Text-Based" tests provided in this repository. (Read more about that in the next section) Whichever testing approach you choose, the idea of the exercise is to do some deliberate practice, and improve your Refactoring skills. The idea is not to re-write the code from scratch, but rather to practice taking small steps, running the tests often, and incrementally improving the design. ================== Text-Based Testing ================== This is a testing approach which is very useful when refactoring legacy code. The basic idea is to create tests that use the text which the code produces. Before you change the code, you run it, and save the output as a "Golden Copy". Then after you change the code, you run it again, and compare the output against the Golden Copy. Any differences, and the test fails. It's basically the same idea as "assertEquals(expected, actual)" in a unit test, except the text you are comparing is typically much longer, and the "expected" value is saved from actual output, rather than being defined in advance. Typically a piece of legacy code may not produce suitable textual output from the start, so you may need to modify it before you can write your first text-based test. That could involve inserting log statements into the code, or just writing a "main" method that executes the code and prints out what the result is afterwards. It's this latter approach we are using here to test GildedRose. The Text-Based tests in this repository are designed to be used with the tool "TextTest" (http://texttest.org). This tool helps you to organize and run text-based tests. There is more information in the README file in the "texttests" subdirectory. =================================== Gilded Rose Kata Background Reading =================================== Hi and welcome to team Gilded Rose. As you know, we are a small inn with a prime location in a prominent city ran by a friendly innkeeper named Allison. We also buy and sell only the finest goods. Unfortunately, our goods are constantly degrading in quality as they approach their sell by date. We have a system in place that updates our inventory for us. It was developed by a no-nonsense type named Leeroy, who has moved on to new adventures. Your task is to add the new feature to our system so that we can begin selling a new category of items. First an introduction to our system: - All items have a SellIn value which denotes the number of days we have to sell the item - All items have a Quality value which denotes how valuable the item is - At the end of each day our system lowers both values for every item Pretty simple, right? Well this is where it gets interesting: - Once the sell by date has passed, Quality degrades twice as fast - The Quality of an item is never negative - "Aged Brie" actually increases in Quality the older it gets - The Quality of an item is never more than 50 - "Sulfuras", being a legendary item, never has to be sold or decreases in Quality - "Backstage passes", like aged brie, increases in Quality as it's SellIn value approaches; Quality increases by 2 when there are 10 days or less and by 3 when there are 5 days or less but Quality drops to 0 after the concert We have recently signed a supplier of conjured items. This requires an update to our system: - "Conjured" items degrade in Quality twice as fast as normal items Feel free to make any changes to the UpdateQuality method and add any new code as long as everything still works correctly. However, do not alter the Item class or Items property as those belong to the goblin in the corner who will insta-rage and one-shot you as he doesn't believe in shared code ownership (you can make the UpdateQuality method and Items property static if you like, we'll cover for you). Just for clarification, an item can never have its Quality increase above 50, however "Sulfuras" is a legendary item and as such its Quality is 80 and it never alters.! !GildedRose methodsFor: 'API' stamp: 'AndreasLeidig 4/21/2012 17:02'! updateQualityFor: items items do: [:item | (item name ~= 'Aged Brie' and: [item name ~= 'Backstage passes to a TAFKAL80ETC concert']) ifTrue: [item quality > 0 ifTrue: [item name ~= 'Sulfuras, Hand of Ragnaros' ifTrue: [item quality: item quality - 1]]] ifFalse: [item quality < 50 ifTrue: [item quality: item quality + 1. item name = 'Backstage passes to a TAFKAL80ETC concert' ifTrue: [item sellIn < 11 ifTrue: [item quality < 50 ifTrue: [item quality: item quality + 1]]. item sellIn < 6 ifTrue: [item quality < 50 ifTrue: [item quality: item quality + 1]]]]]. item name ~= 'Sulfuras, Hand of Ragnaros' ifTrue: [item sellIn: item sellIn - 1]. item sellIn < 0 ifTrue: [item name ~= 'Aged Brie' ifTrue: [item name ~= 'Backstage passes to a TAFKAL80ETC concert' ifTrue: [item quality > 0 ifTrue: [item name ~= 'Sulfuras, Hand of Ragnaros' ifTrue: [item quality: item quality - 1]]] ifFalse: [item quality: item quality - item quality]] ifFalse: [item quality < 50 ifTrue: [item quality: item quality + 1]]]]! ! Object subclass: #Item instanceVariableNames: 'name sellIn quality' classVariableNames: '' poolDictionaries: '' category: 'GildedRose'! !Item methodsFor: 'accessing' stamp: 'AndreasLeidig 4/21/2012 15:40'! name ^name! ! !Item methodsFor: 'accessing' stamp: 'AndreasLeidig 4/21/2012 15:41'! name: aString name := aString! ! !Item methodsFor: 'accessing' stamp: 'AndreasLeidig 4/21/2012 15:41'! quality ^quality! ! !Item methodsFor: 'accessing' stamp: 'AndreasLeidig 4/21/2012 15:42'! quality: aNumber quality := aNumber! ! !Item methodsFor: 'accessing' stamp: 'AndreasLeidig 4/21/2012 15:41'! sellIn ^sellIn! ! !Item methodsFor: 'accessing' stamp: 'AndreasLeidig 4/21/2012 15:42'! sellIn: aNumber sellIn := aNumber ! ! \ No newline at end of file +Object subclass: #GildedRose instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'GildedRose'! !GildedRose commentStamp: 'AndreasLeidig 4/21/2012 15:38' prior: 0! This Kata was originally created by Terry Hughes (http://twitter.com/#!!/TerryHughes). It is already on GitHub as "GildedRose", a sample project for C#. I could have forked it again, but I thought other language users might not want to download a whole C# project environment. In this repository are starting code samples for Java, Python, Ruby, C# and C++. See also http://iamnotmyself.com/2011/02/13/refactor-this-the-gilded-rose-kata/ ==================== How to use this Kata ==================== The simplest way is to just clone the code and start hacking away improving the design. You'll want to look at the "Gilded Rose Background Reading" (below) which explains what the code is for. I strongly advise you that you'll also need some tests if you want to make sure you don't break the code while you refactor. You could write some unit tests yourself, using the Kata Background Reading (below) to identify suitable test cases. I've provided a failing unit test in a popular test framework as a starting point for most languages. Alternatively, use the "Text-Based" tests provided in this repository. (Read more about that in the next section) Whichever testing approach you choose, the idea of the exercise is to do some deliberate practice, and improve your Refactoring skills. The idea is not to re-write the code from scratch, but rather to practice taking small steps, running the tests often, and incrementally improving the design. ================== Text-Based Testing ================== This is a testing approach which is very useful when refactoring legacy code. The basic idea is to create tests that use the text which the code produces. Before you change the code, you run it, and save the output as a "Golden Copy". Then after you change the code, you run it again, and compare the output against the Golden Copy. Any differences, and the test fails. It's basically the same idea as "assertEquals(expected, actual)" in a unit test, except the text you are comparing is typically much longer, and the "expected" value is saved from actual output, rather than being defined in advance. Typically a piece of legacy code may not produce suitable textual output from the start, so you may need to modify it before you can write your first text-based test. That could involve inserting log statements into the code, or just writing a "main" method that executes the code and prints out what the result is afterwards. It's this latter approach we are using here to test GildedRose. The Text-Based tests in this repository are designed to be used with the tool "TextTest" (http://texttest.org). This tool helps you to organize and run text-based tests. There is more information in the README file in the "texttests" subdirectory. =================================== Gilded Rose Kata Background Reading =================================== Hi and welcome to team Gilded Rose. As you know, we are a small inn with a prime location in a prominent city ran by a friendly innkeeper named Allison. We also buy and sell only the finest goods. Unfortunately, our goods are constantly degrading in quality as they approach their sell by date. We have a system in place that updates our inventory for us. It was developed by a no-nonsense type named Leeroy, who has moved on to new adventures. Your task is to add the new feature to our system so that we can begin selling a new category of items. First an introduction to our system: - All items have a SellIn value which denotes the number of days we have to sell the item - All items have a Quality value which denotes how valuable the item is - At the end of each day our system lowers both values for every item Pretty simple, right? Well this is where it gets interesting: - Once the sell by date has passed, Quality degrades twice as fast - The Quality of an item is never negative - "Aged Brie" actually increases in Quality the older it gets - The Quality of an item is never more than 50 - "Sulfuras", being a legendary item, never has to be sold or decreases in Quality - "Backstage passes", like aged brie, increases in Quality as it's SellIn value approaches; Quality increases by 2 when there are 10 days or less and by 3 when there are 5 days or less but Quality drops to 0 after the concert We have recently signed a supplier of conjured items. This requires an update to our system: - "Conjured" items degrade in Quality twice as fast as normal items Feel free to make any changes to the UpdateQuality method and add any new code as long as everything still works correctly. However, do not alter the Item class or Items property as those belong to the goblin in the corner who will insta-rage and one-shot you as he doesn't believe in shared code ownership (you can make the UpdateQuality method and Items property static if you like, we'll cover for you). Just for clarification, an item can never have its Quality increase above 50, however "Sulfuras" is a legendary item and as such its Quality is 80 and it never alters.! !GildedRose methodsFor: 'API' stamp: 'AndreasLeidig 4/21/2012 17:02'! updateQualityFor: items items do: [:item | (item name ~= 'Aged Brie' and: [item name ~= 'Backstage passes to a TAFKAL80ETC concert']) ifTrue: [item quality > 0 ifTrue: [item name ~= 'Sulfuras, Hand of Ragnaros' ifTrue: [item quality: item quality - 1]]] ifFalse: [item quality < 50 ifTrue: [item quality: item quality + 1. item name = 'Backstage passes to a TAFKAL80ETC concert' ifTrue: [item sellIn < 11 ifTrue: [item quality < 50 ifTrue: [item quality: item quality + 1]]. item sellIn < 6 ifTrue: [item quality < 50 ifTrue: [item quality: item quality + 1]]]]]. item name ~= 'Sulfuras, Hand of Ragnaros' ifTrue: [item sellIn: item sellIn - 1]. item sellIn < 0 ifTrue: [item name ~= 'Aged Brie' ifTrue: [item name ~= 'Backstage passes to a TAFKAL80ETC concert' ifTrue: [item quality > 0 ifTrue: [item name ~= 'Sulfuras, Hand of Ragnaros' ifTrue: [item quality: item quality - 1]]] ifFalse: [item quality: item quality - item quality]] ifFalse: [item quality < 50 ifTrue: [item quality: item quality + 1]]]]! ! "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "! GildedRose class instanceVariableNames: ''! !GildedRose class methodsFor: 'run Example' stamp: 'AndreasLeidig 4/21/2012 20:26'! runExamples "GildedRose runExamples" | items gildedRose | items := OrderedCollection new add: (Item new name: '+5 Dexterity Vest'; sellIn: 10; quality: 20; yourself); add: (Item new name: 'Aged Brie'; sellIn: 2; quality: 0; yourself); add: (Item new name: 'Elixir of the Mongoose'; sellIn: 5; quality: 7; yourself); add: (Item new name: 'Sulfuras, Hand of Ragnaros'; sellIn: 0; quality: 80; yourself); add: (Item new name: 'Sulfuras, Hand of Ragnaros'; sellIn: -1; quality: 80; yourself); add: (Item new name: 'Backstage passes to a TAFKAL80ETC concert'; sellIn: 15; quality: 20; yourself); add: (Item new name: 'Backstage passes to a TAFKAL80ETC concert'; sellIn: 10; quality: 49; yourself); add: (Item new name: 'Backstage passes to a TAFKAL80ETC concert'; sellIn: 5; quality: 49; yourself); add: (Item new name: 'Conjured Mana Cake'; sellIn: 3; quality: 6; yourself); "this conjured item does not work properly yet" yourself. gildedRose := GildedRose new. Transcript show: 'OMGHAI!!'; cr. 0 to: 30 do: [:idx | Transcript show: '-------- day ' , idx printString , ' --------'; cr; show: 'name, sellIn, quality'; cr. items do: [:item | Transcript show: item name , ', ' , item sellIn printString , ', ' , item quality printString; cr]. Transcript cr. gildedRose updateQualityFor: items]. Transcript cr! ! Object subclass: #Item instanceVariableNames: 'name sellIn quality' classVariableNames: '' poolDictionaries: '' category: 'GildedRose'! !Item methodsFor: 'accessing' stamp: 'AndreasLeidig 4/21/2012 15:40'! name ^name! ! !Item methodsFor: 'accessing' stamp: 'AndreasLeidig 4/21/2012 15:41'! name: aString name := aString! ! !Item methodsFor: 'accessing' stamp: 'AndreasLeidig 4/21/2012 15:41'! quality ^quality! ! !Item methodsFor: 'accessing' stamp: 'AndreasLeidig 4/21/2012 15:42'! quality: aNumber quality := aNumber! ! !Item methodsFor: 'accessing' stamp: 'AndreasLeidig 4/21/2012 15:41'! sellIn ^sellIn! ! !Item methodsFor: 'accessing' stamp: 'AndreasLeidig 4/21/2012 15:42'! sellIn: aNumber sellIn := aNumber ! ! \ No newline at end of file diff --git a/GildedRose/texttests/.DS_Store b/GildedRose/texttests/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..d01643f900f685a498b539a8e9c9ab7ffd74e89f GIT binary patch literal 6148 zcmeHKJ5Iw;5S)b+5i}_&-vMa2ffbpKE*t=`C4%J05lIR<1L&q@{oz zX?L9U?6W+DHw!@KyY>p00hltB@v3PIy{|FCNmNeBVrOjef*SYCo00l(L3__|izS}$ zjJ^JL({vAg-|^tXg06pDH2rGr=U(0%)2;ftZg<-T_;_EwxjJ(?kPf5+=|DR0e;v@# zN=(n4Gp7UTKsxa4fPNneL%9kbobA)WWGeu9!m@$awo8zU7RXib;LHjk-b(gXi4{Y< zo%IsBDtK`Ac1SEA5>J-cP{f|j^NYzLm2>8FARYMWfbQPJOy~bK*zIg))vMc;|tW9oXJKp*+wyc=qSF}(-pnu{VI5HwszL7ot%FJ)R#m$ I@EZ<%0y*0zSpWb4 literal 0 HcmV?d00001 From 80bd31bea40883b894910c512820d9b800c2f436 Mon Sep 17 00:00:00 2001 From: Emily Bache Date: Thu, 24 May 2012 14:21:21 +0200 Subject: [PATCH 035/634] changing names to Fixture so that it's obvious this code is not part of the refactoring kata itself --- GildedRose/Java/TexttestFixture.java | 35 +++++++++++++++++++++++++++ GildedRose/python/texttest_fixture.py | 29 ++++++++++++++++++++++ GildedRose/ruby/texttest_fixture.rb | 33 +++++++++++++++++++++++++ 3 files changed, 97 insertions(+) create mode 100755 GildedRose/Java/TexttestFixture.java create mode 100644 GildedRose/python/texttest_fixture.py create mode 100644 GildedRose/ruby/texttest_fixture.rb diff --git a/GildedRose/Java/TexttestFixture.java b/GildedRose/Java/TexttestFixture.java new file mode 100755 index 00000000..3f48d3aa --- /dev/null +++ b/GildedRose/Java/TexttestFixture.java @@ -0,0 +1,35 @@ + +public class TexttestFixture { + public static void main(String[] args) { + System.out.println("OMGHAI!"); + + Item[] items = new Item[] { new Item("+5 Dexterity Vest", 10, 20), + new Item("Aged Brie", 2, 0), + new Item("Elixir of the Mongoose", 5, 7), + new Item("Sulfuras, Hand of Ragnaros", 0, 80), + new Item("Sulfuras, Hand of Ragnaros", -1, 80), + new Item("Backstage passes to a TAFKAL80ETC concert", 15, 20), + new Item("Backstage passes to a TAFKAL80ETC concert", 10, 49), + new Item("Backstage passes to a TAFKAL80ETC concert", 5, 49), + // this conjured item does not work properly yet + new Item("Conjured Mana Cake", 3, 6) }; + + GildedRose app = new GildedRose(items); + + int days = 2; + if (args.length > 0) { + days = Integer.parseInt(args[0]) + 1; + } + + for (int i = 0; i < days; i++) { + System.out.println("-------- day " + i + " --------"); + System.out.println("name, sellIn, quality"); + for (Item item : items) { + System.out.println(item); + } + System.out.println(); + app.updateQuality(); + } + } + +} \ No newline at end of file diff --git a/GildedRose/python/texttest_fixture.py b/GildedRose/python/texttest_fixture.py new file mode 100644 index 00000000..b85634c1 --- /dev/null +++ b/GildedRose/python/texttest_fixture.py @@ -0,0 +1,29 @@ +from __future__ import print_function + +from gilded_rose import * + +if __name__ == "__main__": + print ("OMGHAI!") + items = [ + Item(name="+5 Dexterity Vest", sell_in=10, quality=20), + Item(name="Aged Brie", sell_in=2, quality=0), + Item(name="Elixir of the Mongoose", sell_in=5, quality=7), + Item(name="Sulfuras, Hand of Ragnaros", sell_in=0, quality=80), + Item(name="Sulfuras, Hand of Ragnaros", sell_in=-1, quality=80), + Item(name="Backstage passes to a TAFKAL80ETC concert", sell_in=15, quality=20), + Item(name="Backstage passes to a TAFKAL80ETC concert", sell_in=10, quality=49), + Item(name="Backstage passes to a TAFKAL80ETC concert", sell_in=5, quality=49), + Item(name="Conjured Mana Cake", sell_in=3, quality=6), # <-- :O + ] + + days = 2 + import sys + if len(sys.argv) > 1: + days = int(sys.argv[1]) + 1 + for day in range(days): + print("-------- day %s --------" % day) + print("name, sellIn, quality") + for item in items: + print(item) + print("") + update_quality(items) diff --git a/GildedRose/ruby/texttest_fixture.rb b/GildedRose/ruby/texttest_fixture.rb new file mode 100644 index 00000000..c639c06b --- /dev/null +++ b/GildedRose/ruby/texttest_fixture.rb @@ -0,0 +1,33 @@ +#!/usr/bin/ruby -w + +require File.join(File.dirname(__FILE__), 'gilded_rose') + +puts "OMGHAI!" +items = [ + Item.new(name="+5 Dexterity Vest", sell_in=10, quality=20), + Item.new(name="Aged Brie", sell_in=2, quality=0), + Item.new(name="Elixir of the Mongoose", sell_in=5, quality=7), + Item.new(name="Sulfuras, Hand of Ragnaros", sell_in=0, quality=80), + Item.new(name="Sulfuras, Hand of Ragnaros", sell_in=-1, quality=80), + Item.new(name="Backstage passes to a TAFKAL80ETC concert", sell_in=15, quality=20), + Item.new(name="Backstage passes to a TAFKAL80ETC concert", sell_in=10, quality=49), + Item.new(name="Backstage passes to a TAFKAL80ETC concert", sell_in=5, quality=49), + # This Conjured item does not work properly yet + Item.new(name="Conjured Mana Cake", sell_in=3, quality=6), # <-- :O + ] + +days = 2 +if ARGV.size > 0 + days = ARGV[0].to_i + 1 +end + +gilded_rose = GildedRose.new +(0...days).each do |day| + puts "-------- day #{day} --------" + puts "name, sellIn, quality" + items.each do |item| + puts item + end + puts "" + gilded_rose.update_quality(items) +end From 32ce66e211a408ab4271fc2647ae1dba02afeb90 Mon Sep 17 00:00:00 2001 From: Emily Bache Date: Thu, 24 May 2012 14:25:44 +0200 Subject: [PATCH 036/634] Renamed main functions to TexttestFixture to make it clear they're not part of the actual refactoring kata --- GildedRose/Java/Main.java | 35 -------------------------------- GildedRose/README | 2 +- GildedRose/python/gilded_rose.py | 26 ------------------------ GildedRose/ruby/main.rb | 33 ------------------------------ GildedRose/texttests/config.gr | 16 +++++++-------- 5 files changed, 9 insertions(+), 103 deletions(-) delete mode 100755 GildedRose/Java/Main.java delete mode 100644 GildedRose/ruby/main.rb diff --git a/GildedRose/Java/Main.java b/GildedRose/Java/Main.java deleted file mode 100755 index b227b7ed..00000000 --- a/GildedRose/Java/Main.java +++ /dev/null @@ -1,35 +0,0 @@ - -public class Main { - public static void main(String[] args) { - System.out.println("OMGHAI!"); - - Item[] items = new Item[] { new Item("+5 Dexterity Vest", 10, 20), - new Item("Aged Brie", 2, 0), - new Item("Elixir of the Mongoose", 5, 7), - new Item("Sulfuras, Hand of Ragnaros", 0, 80), - new Item("Sulfuras, Hand of Ragnaros", -1, 80), - new Item("Backstage passes to a TAFKAL80ETC concert", 15, 20), - new Item("Backstage passes to a TAFKAL80ETC concert", 10, 49), - new Item("Backstage passes to a TAFKAL80ETC concert", 5, 49), - // this conjured item does not work properly yet - new Item("Conjured Mana Cake", 3, 6) }; - - GildedRose app = new GildedRose(items); - - int days = 2; - if (args.length > 0) { - days = Integer.parseInt(args[0]) + 1; - } - - for (int i = 0; i < days; i++) { - System.out.println("-------- day " + i + " --------"); - System.out.println("name, sellIn, quality"); - for (Item item : items) { - System.out.println(item); - } - System.out.println(); - app.updateQuality(); - } - } - -} \ No newline at end of file diff --git a/GildedRose/README b/GildedRose/README index bf54061f..3ba18362 100644 --- a/GildedRose/README +++ b/GildedRose/README @@ -1,4 +1,4 @@ -This Kata was originally created by Terry Hughes (http://twitter.com/#!/TerryHughes). It is already on GitHub as "GildedRose", a sample project for C#. I could have forked it again, but I thought other language users might not want to download a whole C# project environment. In this repository are starting code samples for Java, Python, Ruby, C# and C++. +This Kata was originally created by Terry Hughes (http://twitter.com/#!/TerryHughes). It is already on GitHub as "GildedRose", a sample project for C#. I could have forked it again, but I thought other language users might not want to download a whole C# project environment. In this repository are starting code samples for Java, Python, Ruby, Smalltalk, C# and C++. See also http://iamnotmyself.com/2011/02/13/refactor-this-the-gilded-rose-kata/ diff --git a/GildedRose/python/gilded_rose.py b/GildedRose/python/gilded_rose.py index 129bad0a..334bec86 100755 --- a/GildedRose/python/gilded_rose.py +++ b/GildedRose/python/gilded_rose.py @@ -1,4 +1,3 @@ -from __future__ import print_function def update_quality(items): for item in items: @@ -40,28 +39,3 @@ class Item: def __repr__(self): return "%s, %s, %s" % (self.name, self.sell_in, self.quality) -if __name__ == "__main__": - print ("OMGHAI!") - items = [ - Item(name="+5 Dexterity Vest", sell_in=10, quality=20), - Item(name="Aged Brie", sell_in=2, quality=0), - Item(name="Elixir of the Mongoose", sell_in=5, quality=7), - Item(name="Sulfuras, Hand of Ragnaros", sell_in=0, quality=80), - Item(name="Sulfuras, Hand of Ragnaros", sell_in=-1, quality=80), - Item(name="Backstage passes to a TAFKAL80ETC concert", sell_in=15, quality=20), - Item(name="Backstage passes to a TAFKAL80ETC concert", sell_in=10, quality=49), - Item(name="Backstage passes to a TAFKAL80ETC concert", sell_in=5, quality=49), - Item(name="Conjured Mana Cake", sell_in=3, quality=6), # <-- :O - ] - - days = 2 - import sys - if len(sys.argv) > 1: - days = int(sys.argv[1]) + 1 - for day in range(days): - print("-------- day %s --------" % day) - print("name, sellIn, quality") - for item in items: - print(item) - print("") - update_quality(items) diff --git a/GildedRose/ruby/main.rb b/GildedRose/ruby/main.rb deleted file mode 100644 index a5426bbb..00000000 --- a/GildedRose/ruby/main.rb +++ /dev/null @@ -1,33 +0,0 @@ -#!/usr/bin/ruby -w - -require File.join(File.dirname(__FILE__), 'gilded_rose') - -puts "OMGHAI!" -items = [ - Item.new(name="+5 Dexterity Vest", sell_in=10, quality=20), - Item.new(name="Aged Brie", sell_in=2, quality=0), - Item.new(name="Elixir of the Mongoose", sell_in=5, quality=7), - Item.new(name="Sulfuras, Hand of Ragnaros", sell_in=0, quality=80), - Item.new(name="Sulfuras, Hand of Ragnaros", sell_in=-1, quality=80), - Item.new(name="Backstage passes to a TAFKAL80ETC concert", sell_in=15, quality=20), - Item.new(name="Backstage passes to a TAFKAL80ETC concert", sell_in=10, quality=49), - Item.new(name="Backstage passes to a TAFKAL80ETC concert", sell_in=5, quality=49), - # This Conjured item does not work properly yet - Item.new(name="Conjured Mana Cake", sell_in=3, quality=6), # <-- :O - ] - -days = 2 -if ARGV.size > 0: - days = ARGV[0].to_i + 1 -end - -gilded_rose = GildedRose.new -(0...days).each do |day| - puts "-------- day #{day} --------" - puts "name, sellIn, quality" - items.each do |item| - puts item - end - puts "" - gilded_rose.update_quality(items) -end diff --git a/GildedRose/texttests/config.gr b/GildedRose/texttests/config.gr index a5b31f77..e7b88344 100755 --- a/GildedRose/texttests/config.gr +++ b/GildedRose/texttests/config.gr @@ -1,31 +1,31 @@ full_name:Gilded Rose Refactoring Kata # location where you have your clone -default_checkout:/home/emily/workspace/Refactoring-Katas/GildedRose +default_checkout:/Users/emily/training_materials/Refactoring-Katas/GildedRose # Settings for the Java version -#executable:Main -#interpreter:java +executable:TexttestFixture +interpreter:java # note you'll also need to update the file environment.gr with your classpath if you keep your classfiles somewhere unusual # Settings for the Python version -#executable:${TEXTTEST_CHECKOUT}/python/gilded_rose.py +#executable:${TEXTTEST_CHECKOUT}/python/texttest_fixture.py #interpreter:python # Settings for the C++ version #executable:${TEXTTEST_CHECKOUT}/cpp/GildedRoseTextTests # Settings for the Ruby version -#executable:${TEXTTEST_CHECKOUT}/ruby/main.rb +#executable:${TEXTTEST_CHECKOUT}/ruby/texttest_fixture.rb #interpreter:ruby # Settings for the C# version -executable:${TEXTTEST_CHECKOUT}/csharp/Program.exe +#executable:${TEXTTEST_CHECKOUT}/csharp/Program.exe # turn on one of these if you prefer them to notepad or emacs. [view_program] -#*:mate -*:gedit +*:mate +#*:gedit [end] filename_convention_scheme:standard From 4945165df2757f3e032324a966b10607ecd12fa0 Mon Sep 17 00:00:00 2001 From: Emily Bache Date: Thu, 14 Jun 2012 11:30:21 +0200 Subject: [PATCH 037/634] New Refactoring Kata - Yahtzee - by Jon Jagger --- Yahtzee/README | 120 ++++++++++++++++ Yahtzee/csharp/Yahtzee.cs | 238 ++++++++++++++++++++++++++++++++ Yahtzee/csharp/YahtzeeTest.cs | 124 +++++++++++++++++ Yahtzee/java/Yahtzee.java | 241 +++++++++++++++++++++++++++++++++ Yahtzee/java/YahtzeeTest.java | 110 +++++++++++++++ Yahtzee/python/test_yahtzee.py | 94 +++++++++++++ Yahtzee/python/yahtzee.py | 230 +++++++++++++++++++++++++++++++ 7 files changed, 1157 insertions(+) create mode 100644 Yahtzee/README create mode 100644 Yahtzee/csharp/Yahtzee.cs create mode 100644 Yahtzee/csharp/YahtzeeTest.cs create mode 100644 Yahtzee/java/Yahtzee.java create mode 100644 Yahtzee/java/YahtzeeTest.java create mode 100644 Yahtzee/python/test_yahtzee.py create mode 100644 Yahtzee/python/yahtzee.py diff --git a/Yahtzee/README b/Yahtzee/README new file mode 100644 index 00000000..c6a65a1b --- /dev/null +++ b/Yahtzee/README @@ -0,0 +1,120 @@ +======================== +Yahtzee Refactoring Kata +======================== + +This Refactoring Kata was designed by Jon Jagger and is available in his Cyber-Dojo on these urls: + +C#: http://cyber-dojo.com/diff/show/E4466E24B2?avatar=elephant&tag=26 +Java: http://cyber-dojo.com/diff/show/3D5589AA49?avatar=panda&tag=1 + +The other language translations have been contributed by: + +Python: Emily Bache + +============= +Yahtzee rules +============= + +The game of yahtzee is a simple dice game. Each player +rolls five six-sided dice. They can re-roll some or all +of the dice up to three times (including the original roll). + +For example, suppose a players rolls + 3,4,5,5,2 +They hold (-,-,5,5,-) and re-roll (3,4,-,-,2) + 5,1,5,5,3 +They hold (5,-,5,5,-) and re-roll (-,1,-,-,3) + 5,6,5,5,2 + +The player then places the roll in a category, such as ones, +twos, fives, pair, two pairs etc (see below). If the roll is +compatible with the category, the player gets a score for the +roll according to the rules. If the roll is not compatible +with the category, the player scores zero for the roll. + +For example, suppose a player scores 5,6,5,5,2 in the fives +category they would score 15 (three fives). The score for +that go is then added to their total and the category cannot +be used again in the remaining goes for that game. +A full game consists of one go for each category. Thus, for +their last go in a game, a player must choose their only +remaining category. + +Your task is to score a GIVEN roll in a GIVEN category. +You do NOT have to program the random dice rolling. +The game is NOT played by letting the computer choose the +highest scoring category for a given roll. + + +Yahzee Categories and Scoring Rules +=================================== + +Chance: + The player scores the sum of all dice, + no matter what they read. + For example, + 1,1,3,3,6 placed on "chance" scores 14 (1+1+3+3+6) + 4,5,5,6,1 placed on "chance" scores 21 (4+5+5+6+1) + +Yahtzee: + If all dice have the same number, + the player scores 50 points. + For example, + 1,1,1,1,1 placed on "yahtzee" scores 50 + 1,1,1,2,1 placed on "yahtzee" scores 0 + +Ones, Twos, Threes, Fours, Fives, Sixes: + The player scores the sum of the dice that reads one, + two, three, four, five or six, respectively. + For example, + 1,1,2,4,4 placed on "fours" scores 8 (4+4) + 2,3,2,5,1 placed on "twos" scores 4 (2+2) + 3,3,3,4,5 placed on "ones" scores 0 + +Pair: + The player scores the sum of the two highest matching dice. + For example, when placed on "pair" + 3,3,3,4,4 scores 8 (4+4) + 1,1,6,2,6 scores 12 (6+6) + 3,3,3,4,1 scores 0 + 3,3,3,3,1 scores 0 + +Two pairs: + If there are two pairs of dice with the same number, the + player scores the sum of these dice. + For example, when placed on "two pairs" + 1,1,2,3,3 scores 8 (1+1+3+3) + 1,1,2,3,4 scores 0 + 1,1,2,2,2 scores 0 + +Three of a kind: + If there are three dice with the same number, the player + scores the sum of these dice. + For example, when placed on "three of a kind" + 3,3,3,4,5 scores 9 (3+3+3) + 3,3,4,5,6 scores 0 + 3,3,3,3,1 scores 0 + +Four of a kind: + If there are four dice with the same number, the player + scores the sum of these dice. + For example, when placed on "four of a kind" + 2,2,2,2,5 scores 8 (2+2+2+2) + 2,2,2,5,5 scores 0 + 2,2,2,2,2 scores 0 + +Small straight: + When placed on "small straight", if the dice read + 1,2,3,4,5, the player scores 15 (the sum of all the dice. + +Large straight: + When placed on "large straight", if the dice read + 2,3,4,5,6, the player scores 20 (the sum of all the dice). + +Full house: + If the dice are two of a kind and three of a kind, the + player scores the sum of all the dice. + For example, when placed on "full house" + 1,1,2,2,2 scores 8 (1+1+2+2+2) + 2,2,3,3,4 scores 0 + 4,4,4,4,4 scores 0 diff --git a/Yahtzee/csharp/Yahtzee.cs b/Yahtzee/csharp/Yahtzee.cs new file mode 100644 index 00000000..6f7d8867 --- /dev/null +++ b/Yahtzee/csharp/Yahtzee.cs @@ -0,0 +1,238 @@ +public class Yahtzee { + + public static int Chance(int d1, int d2, int d3, int d4, int d5) + { + int total = 0; + total += d1; + total += d2; + total += d3; + total += d4; + total += d5; + return total; + } + + public static int yahtzee(params int[] dice) + { + int[] counts = new int[6]; + foreach (int die in dice) + counts[die-1]++; + for (int i = 0; i != 6; i++) + if (counts[i] == 5) + return 50; + return 0; + } + + public static int Ones(int d1, int d2, int d3, int d4, int d5) { + int sum = 0; + if (d1 == 1) sum++; + if (d2 == 1) sum++; + if (d3 == 1) sum++; + if (d4 == 1) sum++; + if (d5 == 1) + sum++; + + return sum; + } + + public static int Twos(int d1, int d2, int d3, int d4, int d5) { + int sum = 0; + if (d1 == 2) sum += 2; + if (d2 == 2) sum += 2; + if (d3 == 2) sum += 2; + if (d4 == 2) sum += 2; + if (d5 == 2) sum += 2; + return sum; + } + + public static int Threes(int d1, int d2, int d3, int d4, int d5) { + int s; + s = 0; + if (d1 == 3) s += 3; + if (d2 == 3) s += 3; + if (d3 == 3) s += 3; + if (d4 == 3) s += 3; + if (d5 == 3) s += 3; + return s; + } + + protected int[] dice; + public Yahtzee(int d1, int d2, int d3, int d4, int _5) + { + dice = new int[5]; + dice[0] = d1; + dice[1] = d2; + dice[2] = d3; + dice[3] = d4; + dice[4] = _5; + } + + public int Fours() + { + int sum; + sum = 0; + for (int at = 0; at != 5; at++) { + if (dice[at] == 4) { + sum += 4; + } + } + return sum; + } + + public int Fives() + { + int s = 0; + int i; + for (i = 0; i < dice.Length; i++) + if (dice[i] == 5) + s = s + 5; + return s; + } + + public int sixes() + { + int sum = 0; + for (int at = 0; at < dice.Length; at++) + if (dice[at] == 6) + sum = sum + 6; + return sum; + } + + public static int ScorePair(int d1, int d2, int d3, int d4, int d5) + { + int[] counts = new int[6]; + counts[d1-1]++; + counts[d2-1]++; + counts[d3-1]++; + counts[d4-1]++; + counts[d5-1]++; + int at; + for (at = 0; at != 6; at++) + if (counts[6-at-1] == 2) + return (6-at)*2; + return 0; + } + + public static int TwoPair(int d1, int d2, int d3, int d4, int d5) + { + int[] counts = new int[6]; + counts[d1-1]++; + counts[d2-1]++; + counts[d3-1]++; + counts[d4-1]++; + counts[d5-1]++; + int n = 0; + int score = 0; + for (int i = 0; i < 6; i += 1) + if (counts[6-i-1] == 2) { + n++; + score += (6-i); + } + if (n == 2) + return score * 2; + else + return 0; + } + + public static int FourOfAKind(int _1, int _2, int d3, int d4, int d5) + { + int[] tallies; + tallies = new int[6]; + tallies[_1-1]++; + tallies[_2-1]++; + tallies[d3-1]++; + tallies[d4-1]++; + tallies[d5-1]++; + for (int i = 0; i < 6; i++) + if (tallies[i] == 4) + return (i+1) * 4; + return 0; + } + + public static int ThreeOfAKind(int d1, int d2, int d3, int d4, int d5) + { + int[] t; + t = new int[6]; + t[d1-1]++; + t[d2-1]++; + t[d3-1]++; + t[d4-1]++; + t[d5-1]++; + for (int i = 0; i < 6; i++) + if (t[i] == 3) + return (i+1) * 3; + return 0; + } + + public static int SmallStraight(int d1, int d2, int d3, int d4, int d5) + { + int[] tallies; + tallies = new int[6]; + tallies[d1-1] += 1; + tallies[d2-1] += 1; + tallies[d3-1] += 1; + tallies[d4-1] += 1; + tallies[d5-1] += 1; + if (tallies[0] == 1 && + tallies[1] == 1 && + tallies[2] == 1 && + tallies[3] == 1 && + tallies[4] == 1) + return 15; + return 0; + } + + public static int LargeStraight(int d1, int d2, int d3, int d4, int d5) + { + int[] tallies; + tallies = new int[6]; + tallies[d1-1] += 1; + tallies[d2-1] += 1; + tallies[d3-1] += 1; + tallies[d4-1] += 1; + tallies[d5-1] += 1; + if (tallies[1] == 1 && + tallies[2] == 1 && + tallies[3] == 1 && + tallies[4] == 1 + && tallies[5] == 1) + return 20; + return 0; + } + + public static int FullHouse(int d1, int d2, int d3, int d4, int d5) + { + int[] tallies; + bool _2 = false; + int i; + int _2_at = 0; + bool _3 = false; + int _3_at = 0; + + + + + tallies = new int[6]; + tallies[d1-1] += 1; + tallies[d2-1] += 1; + tallies[d3-1] += 1; + tallies[d4-1] += 1; + tallies[d5-1] += 1; + + for (i = 0; i != 6; i += 1) + if (tallies[i] == 2) { + _2 = true; + _2_at = i+1; + } + + for (i = 0; i != 6; i += 1) + if (tallies[i] == 3) { + _3 = true; + _3_at = i+1; + } + + if (_2 && _3) + return _2_at * 2 + _3_at * 3; + else + return 0; + } +} diff --git a/Yahtzee/csharp/YahtzeeTest.cs b/Yahtzee/csharp/YahtzeeTest.cs new file mode 100644 index 00000000..be63fa6f --- /dev/null +++ b/Yahtzee/csharp/YahtzeeTest.cs @@ -0,0 +1,124 @@ +using NUnit.Framework; + +[TestFixture] +public class UntitledTest +{ + [Test] + public void Chance_scores_sum_of_all_dice() + { + int expected = 15; + int actual = Yahtzee.Chance(2,3,4,5,1); + Assert.AreEqual(expected, actual); + Assert.AreEqual(16, Yahtzee.Chance(3,3,4,5,1)); + } + + [Test] + public void Yahtzee_scores_50() + { + int expected = 50; + int actual = Yahtzee.yahtzee(4,4,4,4,4); + Assert.AreEqual(expected, actual); + Assert.AreEqual(50, Yahtzee.yahtzee(6,6,6,6,6)); + Assert.AreEqual(0, Yahtzee.yahtzee(6,6,6,6,3)); + } + + [Test] + public void Test_1s() { + Assert.IsTrue(Yahtzee.Ones(1,2,3,4,5) == 1); + Assert.AreEqual(2, Yahtzee.Ones(1,2,1,4,5)); + Assert.AreEqual(0, Yahtzee.Ones(6,2,2,4,5)); + Assert.AreEqual(4, Yahtzee.Ones(1,2,1,1,1)); + } + + [Test] + public void test_2s() + { + Assert.AreEqual(4, Yahtzee.Twos(1,2,3,2,6)); + Assert.AreEqual(10, Yahtzee.Twos(2,2,2,2,2)); + } + + [Test] + public void test_threes() + { + Assert.AreEqual(6, Yahtzee.Threes(1,2,3,2,3)); + Assert.AreEqual(12, Yahtzee.Threes(2,3,3,3,3)); + } + + [Test] + public void fours_test() + { + Assert.AreEqual(12, new Yahtzee(4,4,4,5,5).Fours()); + Assert.AreEqual(8, new Yahtzee(4,4,5,5,5).Fours()); + Assert.AreEqual(4, new Yahtzee(4,5,5,5,5).Fours()); + } + + [Test] + public void fives() { + Assert.AreEqual(10, new Yahtzee(4,4,4,5,5).Fives()); + Assert.AreEqual(15, new Yahtzee(4,4,5,5,5).Fives()); + Assert.AreEqual(20, new Yahtzee(4,5,5,5,5).Fives()); + } + + [Test] + public void sixes_test() + { + Assert.AreEqual(0, new Yahtzee(4,4,4,5,5).sixes()); + Assert.AreEqual(6, new Yahtzee(4,4,6,5,5).sixes()); + Assert.AreEqual(18, new Yahtzee(6,5,6,6,5).sixes()); + } + + [Test] + public void one_pair() + { + Assert.AreEqual(6, Yahtzee.ScorePair(3,4,3,5,6)); + Assert.AreEqual(10, Yahtzee.ScorePair(5,3,3,3,5)); + Assert.AreEqual(12, Yahtzee.ScorePair(5,3,6,6,5)); + } + + [Test] + public void two_Pair() + { + Assert.AreEqual(16, Yahtzee.TwoPair(3,3,5,4,5)); + Assert.AreEqual(0, Yahtzee.TwoPair(3,3,5,5,5)); + } + + [Test] + public void three_of_a_kind() + { + Assert.AreEqual(9, Yahtzee.ThreeOfAKind(3,3,3,4,5)); + Assert.AreEqual(15, Yahtzee.ThreeOfAKind(5,3,5,4,5)); + Assert.AreEqual(0, Yahtzee.ThreeOfAKind(3,3,3,3,5)); + } + + [Test] + public void four_of_a_knd() + { + Assert.AreEqual(12, Yahtzee.FourOfAKind(3,3,3,3,5)); + Assert.AreEqual(20, Yahtzee.FourOfAKind(5,5,5,4,5)); + Assert.AreEqual(0, Yahtzee.FourOfAKind(3,3,3,3,3)); + } + + [Test] + public void smallStraight() + { + Assert.AreEqual(15, Yahtzee.SmallStraight(1,2,3,4,5)); + Assert.AreEqual(15, Yahtzee.SmallStraight(2,3,4,5,1)); + Assert.AreEqual(0, Yahtzee.SmallStraight(1,2,2,4,5)); + } + + [Test] + public void largeStraight() + { + Assert.AreEqual(20, Yahtzee.LargeStraight(6,2,3,4,5)); + Assert.AreEqual(20, Yahtzee.LargeStraight(2,3,4,5,6)); + Assert.AreEqual(0, Yahtzee.LargeStraight(1,2,2,4,5)); + } + + [Test] + public void fullHouse() + { + Assert.AreEqual(18, Yahtzee.FullHouse(6,2,2,2,6)); + Assert.AreEqual(0, Yahtzee.FullHouse(2,3,4,5,6)); + } +} + diff --git a/Yahtzee/java/Yahtzee.java b/Yahtzee/java/Yahtzee.java new file mode 100644 index 00000000..d200df07 --- /dev/null +++ b/Yahtzee/java/Yahtzee.java @@ -0,0 +1,241 @@ +public class Yahtzee { + + public static int chance(int d1, int d2, int d3, int d4, int d5) + { + int total = 0; + total += d1; + total += d2; + total += d3; + total += d4; + total += d5; + return total; + } + + public static int yahtzee(int... dice) + { + int[] counts = new int[6]; + for (int die : dice) + counts[die-1]++; + for (int i = 0; i != 6; i++) + if (counts[i] == 5) + return 50; + return 0; + } + + public static int ones(int d1, int d2, int d3, int d4, int d5) { + int sum = 0; + if (d1 == 1) sum++; + if (d2 == 1) sum++; + if (d3 == 1) sum++; + if (d4 == 1) sum++; + if (d5 == 1) + sum++; + + return sum; + } + + public static int twos(int d1, int d2, int d3, int d4, int d5) { + int sum = 0; + if (d1 == 2) sum += 2; + if (d2 == 2) sum += 2; + if (d3 == 2) sum += 2; + if (d4 == 2) sum += 2; + if (d5 == 2) sum += 2; + return sum; + } + + public static int threes(int d1, int d2, int d3, int d4, int d5) { + int s; + s = 0; + if (d1 == 3) s += 3; + if (d2 == 3) s += 3; + if (d3 == 3) s += 3; + if (d4 == 3) s += 3; + if (d5 == 3) s += 3; + return s; + } + + protected int[] dice; + public Yahtzee(int d1, int d2, int d3, int d4, int _5) + { + dice = new int[5]; + dice[0] = d1; + dice[1] = d2; + dice[2] = d3; + dice[3] = d4; + dice[4] = _5; + } + + public int fours() + { + int sum; + sum = 0; + for (int at = 0; at != 5; at++) { + if (dice[at] == 4) { + sum += 4; + } + } + return sum; + } + + public int fives() + { + int s = 0; + int i; + for (i = 0; i < dice.length; i++) + if (dice[i] == 5) + s = s + 5; + return s; + } + + public int sixes() + { + int sum = 0; + for (int at = 0; at < dice.length; at++) + if (dice[at] == 6) + sum = sum + 6; + return sum; + } + + public static int score_pair(int d1, int d2, int d3, int d4, int d5) + { + int[] counts = new int[6]; + counts[d1-1]++; + counts[d2-1]++; + counts[d3-1]++; + counts[d4-1]++; + counts[d5-1]++; + int at; + for (at = 0; at != 6; at++) + if (counts[6-at-1] == 2) + return (6-at)*2; + return 0; + } + + public static int two_pair(int d1, int d2, int d3, int d4, int d5) + { + int[] counts = new int[6]; + counts[d1-1]++; + counts[d2-1]++; + counts[d3-1]++; + counts[d4-1]++; + counts[d5-1]++; + int n = 0; + int score = 0; + for (int i = 0; i < 6; i += 1) + if (counts[6-i-1] == 2) { + n++; + score += (6-i); + } + if (n == 2) + return score * 2; + else + return 0; + } + + public static int four_of_a_kind(int _1, int _2, int d3, int d4, int d5) + { + int[] tallies; + tallies = new int[6]; + tallies[_1-1]++; + tallies[_2-1]++; + tallies[d3-1]++; + tallies[d4-1]++; + tallies[d5-1]++; + for (int i = 0; i < 6; i++) + if (tallies[i] == 4) + return (i+1) * 4; + return 0; + } + + public static int three_of_a_kind(int d1, int d2, int d3, int d4, int d5) + { + int[] t; + t = new int[6]; + t[d1-1]++; + t[d2-1]++; + t[d3-1]++; + t[d4-1]++; + t[d5-1]++; + for (int i = 0; i < 6; i++) + if (t[i] == 3) + return (i+1) * 3; + return 0; + } + + public static int smallStraight(int d1, int d2, int d3, int d4, int d5) + { + int[] tallies; + tallies = new int[6]; + tallies[d1-1] += 1; + tallies[d2-1] += 1; + tallies[d3-1] += 1; + tallies[d4-1] += 1; + tallies[d5-1] += 1; + if (tallies[0] == 1 && + tallies[1] == 1 && + tallies[2] == 1 && + tallies[3] == 1 && + tallies[4] == 1) + return 15; + return 0; + } + + public static int largeStraight(int d1, int d2, int d3, int d4, int d5) + { + int[] tallies; + tallies = new int[6]; + tallies[d1-1] += 1; + tallies[d2-1] += 1; + tallies[d3-1] += 1; + tallies[d4-1] += 1; + tallies[d5-1] += 1; + if (tallies[1] == 1 && + tallies[2] == 1 && + tallies[3] == 1 && + tallies[4] == 1 + && tallies[5] == 1) + return 20; + return 0; + } + + public static int fullHouse(int d1, int d2, int d3, int d4, int d5) + { + int[] tallies; + boolean _2 = false; + int i; + int _2_at = 0; + boolean _3 = false; + int _3_at = 0; + + + + + tallies = new int[6]; + tallies[d1-1] += 1; + tallies[d2-1] += 1; + tallies[d3-1] += 1; + tallies[d4-1] += 1; + tallies[d5-1] += 1; + + for (i = 0; i != 6; i += 1) + if (tallies[i] == 2) { + _2 = true; + _2_at = i+1; + } + + for (i = 0; i != 6; i += 1) + if (tallies[i] == 3) { + _3 = true; + _3_at = i+1; + } + + if (_2 && _3) + return _2_at * 2 + _3_at * 3; + else + return 0; + } +} + + + diff --git a/Yahtzee/java/YahtzeeTest.java b/Yahtzee/java/YahtzeeTest.java new file mode 100644 index 00000000..15a20a69 --- /dev/null +++ b/Yahtzee/java/YahtzeeTest.java @@ -0,0 +1,110 @@ +import org.junit.*; +import static org.junit.Assert.*; + +public class YahtzeeTest { + + @Test + public void chance_scores_sum_of_all_dice() { + int expected = 15; + int actual = Yahtzee.chance(2,3,4,5,1); + assertEquals(expected, actual); + assertEquals(16, Yahtzee.chance(3,3,4,5,1)); + } + + @Test public void yahtzee_scores_50() { + int expected = 50; + int actual = Yahtzee.yahtzee(4,4,4,4,4); + assertEquals(expected, actual); + assertEquals(50, Yahtzee.yahtzee(6,6,6,6,6)); + assertEquals(0, Yahtzee.yahtzee(6,6,6,6,3)); + } + + @Test public void test_1s() { + assertTrue(Yahtzee.ones(1,2,3,4,5) == 1); + assertEquals(2, Yahtzee.ones(1,2,1,4,5)); + assertEquals(0, Yahtzee.ones(6,2,2,4,5)); + assertEquals(4, Yahtzee.ones(1,2,1,1,1)); + } + + @Test + public void test_2s() { + assertEquals(4, Yahtzee.twos(1,2,3,2,6)); + assertEquals(10, Yahtzee.twos(2,2,2,2,2)); + } + + @Test + public void test_threes() { + assertEquals(6, Yahtzee.threes(1,2,3,2,3)); + assertEquals(12, Yahtzee.threes(2,3,3,3,3)); + } + + @Test + public void fours_test() + { + assertEquals(12, new Yahtzee(4,4,4,5,5).fours()); + assertEquals(8, new Yahtzee(4,4,5,5,5).fours()); + assertEquals(4, new Yahtzee(4,5,5,5,5).fours()); + } + + @Test + public void fives() { + assertEquals(10, new Yahtzee(4,4,4,5,5).fives()); + assertEquals(15, new Yahtzee(4,4,5,5,5).fives()); + assertEquals(20, new Yahtzee(4,5,5,5,5).fives()); + } + + @Test + public void sixes_test() { + assertEquals(0, new Yahtzee(4,4,4,5,5).sixes()); + assertEquals(6, new Yahtzee(4,4,6,5,5).sixes()); + assertEquals(18, new Yahtzee(6,5,6,6,5).sixes()); + } + + @Test + public void one_pair() { + assertEquals(6, Yahtzee.score_pair(3,4,3,5,6)); + assertEquals(10, Yahtzee.score_pair(5,3,3,3,5)); + assertEquals(12, Yahtzee.score_pair(5,3,6,6,5)); + } + + @Test + public void two_Pair() { + assertEquals(16, Yahtzee.two_pair(3,3,5,4,5)); + assertEquals(0, Yahtzee.two_pair(3,3,5,5,5)); + } + + @Test + public void three_of_a_kind() + { + assertEquals(9, Yahtzee.three_of_a_kind(3,3,3,4,5)); + assertEquals(15, Yahtzee.three_of_a_kind(5,3,5,4,5)); + assertEquals(0, Yahtzee.three_of_a_kind(3,3,3,3,5)); + } + + @Test + public void four_of_a_knd() { + assertEquals(12, Yahtzee.four_of_a_kind(3,3,3,3,5)); + assertEquals(20, Yahtzee.four_of_a_kind(5,5,5,4,5)); + assertEquals(0, Yahtzee.three_of_a_kind(3,3,3,3,3)); + } + + @Test + public void smallStraight() { + assertEquals(15, Yahtzee.smallStraight(1,2,3,4,5)); + assertEquals(15, Yahtzee.smallStraight(2,3,4,5,1)); + assertEquals(0, Yahtzee.smallStraight(1,2,2,4,5)); + } + + @Test + public void largeStraight() { + assertEquals(20, Yahtzee.largeStraight(6,2,3,4,5)); + assertEquals(20, Yahtzee.largeStraight(2,3,4,5,6)); + assertEquals(0, Yahtzee.largeStraight(1,2,2,4,5)); + } + + @Test + public void fullHouse() { + assertEquals(18, Yahtzee.fullHouse(6,2,2,2,6)); + assertEquals(0, Yahtzee.fullHouse(2,3,4,5,6)); + } +} diff --git a/Yahtzee/python/test_yahtzee.py b/Yahtzee/python/test_yahtzee.py new file mode 100644 index 00000000..5a50b611 --- /dev/null +++ b/Yahtzee/python/test_yahtzee.py @@ -0,0 +1,94 @@ +from yahtzee import Yahtzee + +# These unit tests can be run using the py.test framework +# available from http://pytest.org/ + +def test_chance_scores_sum_of_all_dice(): + expected = 15 + actual = Yahtzee.chance(2,3,4,5,1) + assert expected == actual + assert 16 == Yahtzee.chance(3,3,4,5,1) + + +def test_yahtzee_scores_50(): + expected = 50 + actual = Yahtzee.yahtzee([4,4,4,4,4]) + assert expected == actual + assert 50 == Yahtzee.yahtzee([6,6,6,6,6]) + assert 0 == Yahtzee.yahtzee([6,6,6,6,3]) + + +def test_1s(): + assert Yahtzee.ones(1,2,3,4,5) == 1 + assert 2 == Yahtzee.ones(1,2,1,4,5) + assert 0 == Yahtzee.ones(6,2,2,4,5) + assert 4 == Yahtzee.ones(1,2,1,1,1) + + +def test_2s(): + assert 4 == Yahtzee.twos(1,2,3,2,6) + assert 10 == Yahtzee.twos(2,2,2,2,2) + + +def test_threes(): + assert 6 == Yahtzee.threes(1,2,3,2,3) + assert 12 == Yahtzee.threes(2,3,3,3,3) + + +def test_fours_test(): + assert 12 == Yahtzee(4,4,4,5,5).fours() + assert 8 == Yahtzee(4,4,5,5,5).fours() + assert 4 == Yahtzee(4,5,5,5,5).fours() + + +def test_fives(): + assert 10 == Yahtzee(4,4,4,5,5).fives() + assert 15 == Yahtzee(4,4,5,5,5).fives() + assert 20 == Yahtzee(4,5,5,5,5).fives() + + +def test_sixes_test(): + assert 0 == Yahtzee(4,4,4,5,5).sixes() + assert 6 == Yahtzee(4,4,6,5,5).sixes() + assert 18 == Yahtzee(6,5,6,6,5).sixes() + + +def test_one_pair(): + assert 6 == Yahtzee.score_pair(3,4,3,5,6) + assert 10 == Yahtzee.score_pair(5,3,3,3,5) + assert 12 == Yahtzee.score_pair(5,3,6,6,5) + + +def test_two_Pair(): + assert 16 == Yahtzee.two_pair(3,3,5,4,5) + assert 0 == Yahtzee.two_pair(3,3,5,5,5) + + +def test_three_of_a_kind(): + assert 9 == Yahtzee.three_of_a_kind(3,3,3,4,5) + assert 15 == Yahtzee.three_of_a_kind(5,3,5,4,5) + assert 0 == Yahtzee.three_of_a_kind(3,3,3,3,5) + + +def test_four_of_a_knd(): + assert 12 == Yahtzee.four_of_a_kind(3,3,3,3,5) + assert 20 == Yahtzee.four_of_a_kind(5,5,5,4,5) + assert 0 == Yahtzee.three_of_a_kind(3,3,3,3,3) + + +def test_smallStraight(): + assert 15 == Yahtzee.smallStraight(1,2,3,4,5) + assert 15 == Yahtzee.smallStraight(2,3,4,5,1) + assert 0 == Yahtzee.smallStraight(1,2,2,4,5) + + +def test_largeStraight(): + assert 20 == Yahtzee.largeStraight(6,2,3,4,5) + assert 20 == Yahtzee.largeStraight(2,3,4,5,6) + assert 0 == Yahtzee.largeStraight(1,2,2,4,5) + + +def test_fullHouse(): + assert 18 == Yahtzee.fullHouse(6,2,2,2,6) + assert 0 == Yahtzee.fullHouse(2,3,4,5,6) + diff --git a/Yahtzee/python/yahtzee.py b/Yahtzee/python/yahtzee.py new file mode 100644 index 00000000..3b6b4f15 --- /dev/null +++ b/Yahtzee/python/yahtzee.py @@ -0,0 +1,230 @@ +class Yahtzee: + + @staticmethod + def chance(d1, d2, d3, d4, d5): + total = 0 + total += d1 + total += d2 + total += d3 + total += d4 + total += d5 + return total + + @staticmethod + def yahtzee(dice): + counts = [0]*(len(dice)+1) + for die in dice: + counts[die-1] += 1 + for i in range(len(counts)): + if counts[i] == 5: + return 50 + return 0 + + @staticmethod + def ones( d1, d2, d3, d4, d5): + sum = 0 + if (d1 == 1): + sum += 1 + if (d2 == 1): + sum += 1 + if (d3 == 1): + sum += 1 + if (d4 == 1): + sum += 1 + if (d5 == 1): + sum += 1 + + return sum + + + @staticmethod + def twos( d1, d2, d3, d4, d5): + sum = 0 + if (d1 == 2): + sum += 2 + if (d2 == 2): + sum += 2 + if (d3 == 2): + sum += 2 + if (d4 == 2): + sum += 2 + if (d5 == 2): + sum += 2 + return sum + + @staticmethod + def threes( d1, d2, d3, d4, d5): + s = 0 + if (d1 == 3): + s += 3 + if (d2 == 3): + s += 3 + if (d3 == 3): + s += 3 + if (d4 == 3): + s += 3 + if (d5 == 3): + s += 3 + return s + + + def __init__(self, d1, d2, d3, d4, _5): + self.dice = [0]*5 + self.dice[0] = d1 + self.dice[1] = d2 + self.dice[2] = d3 + self.dice[3] = d4 + self.dice[4] = _5 + + def fours(self): + sum = 0 + for at in range(5): + if (self.dice[at] == 4): + sum += 4 + return sum + + + def fives(self): + s = 0 + i = 0 + for i in range(len(self.dice)): + if (self.dice[i] == 5): + s = s + 5 + return s + + + def sixes(self): + sum = 0 + for at in range(len(self.dice)): + if (self.dice[at] == 6): + sum = sum + 6 + return sum + + @staticmethod + def score_pair( d1, d2, d3, d4, d5): + counts = [0]*6 + counts[d1-1] += 1 + counts[d2-1] += 1 + counts[d3-1] += 1 + counts[d4-1] += 1 + counts[d5-1] += 1 + at = 0 + for at in range(6): + if (counts[6-at-1] == 2): + return (6-at)*2 + return 0 + + @staticmethod + def two_pair( d1, d2, d3, d4, d5): + counts = [0]*6 + counts[d1-1] += 1 + counts[d2-1] += 1 + counts[d3-1] += 1 + counts[d4-1] += 1 + counts[d5-1] += 1 + n = 0 + score = 0 + for i in range(6): + if (counts[6-i-1] == 2): + n = n+1 + score += (6-i) + + if (n == 2): + return score * 2 + else: + return 0 + + @staticmethod + def four_of_a_kind( _1, _2, d3, d4, d5): + tallies = [0]*6 + tallies[_1-1] += 1 + tallies[_2-1] += 1 + tallies[d3-1] += 1 + tallies[d4-1] += 1 + tallies[d5-1] += 1 + for i in range(6): + if (tallies[i] == 4): + return (i+1) * 4 + return 0 + + + @staticmethod + def three_of_a_kind( d1, d2, d3, d4, d5): + t = [0]*6 + t[d1-1] += 1 + t[d2-1] += 1 + t[d3-1] += 1 + t[d4-1] += 1 + t[d5-1] += 1 + for i in range(6): + if (t[i] == 3): + return (i+1) * 3 + return 0 + + + @staticmethod + def smallStraight( d1, d2, d3, d4, d5): + tallies = [0]*6 + tallies[d1-1] += 1 + tallies[d2-1] += 1 + tallies[d3-1] += 1 + tallies[d4-1] += 1 + tallies[d5-1] += 1 + if (tallies[0] == 1 and + tallies[1] == 1 and + tallies[2] == 1 and + tallies[3] == 1 and + tallies[4] == 1): + return 15 + return 0 + + + @staticmethod + def largeStraight( d1, d2, d3, d4, d5): + tallies = [0]*6 + tallies[d1-1] += 1 + tallies[d2-1] += 1 + tallies[d3-1] += 1 + tallies[d4-1] += 1 + tallies[d5-1] += 1 + if (tallies[1] == 1 and + tallies[2] == 1 and + tallies[3] == 1 and + tallies[4] == 1 + and tallies[5] == 1): + return 20 + return 0 + + + @staticmethod + def fullHouse( d1, d2, d3, d4, d5): + tallies = [] + _2 = False + i = 0 + _2_at = 0 + _3 = False + _3_at = 0 + + tallies = [0]*6 + tallies[d1-1] += 1 + tallies[d2-1] += 1 + tallies[d3-1] += 1 + tallies[d4-1] += 1 + tallies[d5-1] += 1 + + for i in range(6): + if (tallies[i] == 2): + _2 = True + _2_at = i+1 + + + for i in range(6): + if (tallies[i] == 3): + _3 = True + _3_at = i+1 + + + if (_2 and _3): + return _2_at * 2 + _3_at * 3 + else: + return 0 From b3509bc087beafc1318c4f48050d82387017ad80 Mon Sep 17 00:00:00 2001 From: Emily Bache Date: Thu, 14 Jun 2012 11:33:10 +0200 Subject: [PATCH 038/634] Added a new kata - Yahtzee - by Jon Jagger --- README | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README b/README index 310d3eb2..f2fc971c 100644 --- a/README +++ b/README @@ -5,4 +5,5 @@ This is a collection of starting files for when practicing refactoring. Contents so far: Tennis Kata in Java, Python and C++. -Gilded Rose Kata in C++, C#, Java, Python and Ruby. (a C# version together with a starting project is already available on github) \ No newline at end of file +Gilded Rose Kata in C++, C#, Java, Python and Ruby. (a C# version together with a starting project is already available on github) +Yahtzee Kata in C#, Java and Python (the C# and Java versions are also available in Jon Jagger's Cyberdojo) \ No newline at end of file From c6e4fbd20b60a7f27dd396e74c36d9d1860f3334 Mon Sep 17 00:00:00 2001 From: Samuel Ytterbrink Date: Mon, 25 Jun 2012 13:37:12 +0200 Subject: [PATCH 039/634] Fixed import error, by aliasing one off the impls. --- Tennis/python/tennis.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tennis/python/tennis.py b/Tennis/python/tennis.py index e7e33791..83a14c6d 100644 --- a/Tennis/python/tennis.py +++ b/Tennis/python/tennis.py @@ -173,4 +173,4 @@ class TennisGameDefactored3: return "Deuce" s = self.p1N if self.p1 > self.p2 else self.p2N return "Advantage " + s if ((self.p1-self.p2)*(self.p1-self.p2) == 1) else "Win for " + s - +TennisGame = TennisGameDefactored3 From d041b1ea8b289f9b27f3e19efb7cd18412704160 Mon Sep 17 00:00:00 2001 From: Samuel Ytterbrink Date: Mon, 25 Jun 2012 13:39:44 +0200 Subject: [PATCH 040/634] Changed the method to use the built in pytest.mark.parametrize --- Tennis/python/tennis_test.py | 94 +++++++++++++++--------------------- 1 file changed, 40 insertions(+), 54 deletions(-) diff --git a/Tennis/python/tennis_test.py b/Tennis/python/tennis_test.py index 2c5afe81..57bd0d70 100644 --- a/Tennis/python/tennis_test.py +++ b/Tennis/python/tennis_test.py @@ -1,68 +1,54 @@ - +import pytest from tennis import TennisGame -# test support code -def params(funcarglist): - def wrapper(function): - function.funcarglist = funcarglist - return function - return wrapper - -def pytest_generate_tests(metafunc): - for funcargs in getattr(metafunc.function, 'funcarglist', ()): - if "p1Name" not in funcargs: - funcargs["p1Name"] = "player1" - if "p2Name" not in funcargs: - funcargs["p2Name"] = "player2" - metafunc.addcall(funcargs=funcargs) - # actual test code class TestTennis: - @params([dict(p1Points=0, p2Points=0, score="Love-All"), - dict(p1Points=1, p2Points=1, score="Fifteen-All"), - dict(p1Points=2, p2Points=2, score="Thirty-All"), - dict(p1Points=3, p2Points=3, score="Forty-All"), - dict(p1Points=4, p2Points=4, score="Deuce"), + @pytest.mark.parametrize('p1Points p2Points score p1Name p2Name'.split(),[ + (0, 0, "Love-All", 'player1', 'player2'), + (1, 1, "Fifteen-All", 'player1', 'player2'), + (2, 2, "Thirty-All", 'player1', 'player2'), + (3, 3, "Forty-All", 'player1', 'player2'), + (4, 4, "Deuce", 'player1', 'player2'), - dict(p1Points=1, p2Points=0, score="Fifteen-Love"), - dict(p1Points=0, p2Points=1, score="Love-Fifteen"), - dict(p1Points=2, p2Points=0, score="Thirty-Love"), - dict(p1Points=0, p2Points=2, score="Love-Thirty"), - dict(p1Points=3, p2Points=0, score="Forty-Love"), - dict(p1Points=0, p2Points=3, score="Love-Forty"), - dict(p1Points=4, p2Points=0, score="Win for player1"), - dict(p1Points=0, p2Points=4, score="Win for player2"), + (1, 0, "Fifteen-Love", 'player1', 'player2'), + (0, 1, "Love-Fifteen", 'player1', 'player2'), + (2, 0, "Thirty-Love", 'player1', 'player2'), + (0, 2, "Love-Thirty", 'player1', 'player2'), + (3, 0, "Forty-Love", 'player1', 'player2'), + (0, 3, "Love-Forty", 'player1', 'player2'), + (4, 0, "Win for player1", 'player1', 'player2'), + (0, 4, "Win for player2", 'player1', 'player2'), - dict(p1Points=2, p2Points=1, score="Thirty-Fifteen"), - dict(p1Points=1, p2Points=2, score="Fifteen-Thirty"), - dict(p1Points=3, p2Points=1, score="Forty-Fifteen"), - dict(p1Points=1, p2Points=3, score="Fifteen-Forty"), - dict(p1Points=4, p2Points=1, score="Win for player1"), - dict(p1Points=1, p2Points=4, score="Win for player2"), + (2, 1, "Thirty-Fifteen", 'player1', 'player2'), + (1, 2, "Fifteen-Thirty", 'player1', 'player2'), + (3, 1, "Forty-Fifteen", 'player1', 'player2'), + (1, 3, "Fifteen-Forty", 'player1', 'player2'), + (4, 1, "Win for player1", 'player1', 'player2'), + (1, 4, "Win for player2", 'player1', 'player2'), - dict(p1Points=3, p2Points=2, score="Forty-Thirty"), - dict(p1Points=2, p2Points=3, score="Thirty-Forty"), - dict(p1Points=4, p2Points=2, score="Win for player1"), - dict(p1Points=2, p2Points=4, score="Win for player2"), + (3, 2, "Forty-Thirty", 'player1', 'player2'), + (2, 3, "Thirty-Forty", 'player1', 'player2'), + (4, 2, "Win for player1", 'player1', 'player2'), + (2, 4, "Win for player2", 'player1', 'player2'), - dict(p1Points=4, p2Points=3, score="Advantage player1"), - dict(p1Points=3, p2Points=4, score="Advantage player2"), - dict(p1Points=5, p2Points=4, score="Advantage player1"), - dict(p1Points=4, p2Points=5, score="Advantage player2"), - dict(p1Points=15, p2Points=14, score="Advantage player1"), - dict(p1Points=14, p2Points=15, score="Advantage player2"), + (4, 3, "Advantage player1", 'player1', 'player2'), + (3, 4, "Advantage player2", 'player1', 'player2'), + (5, 4, "Advantage player1", 'player1', 'player2'), + (4, 5, "Advantage player2", 'player1', 'player2'), + (15, 14, "Advantage player1", 'player1', 'player2'), + (14, 15, "Advantage player2", 'player1', 'player2'), - dict(p1Points=6, p2Points=4, score="Win for player1"), - dict(p1Points=4, p2Points=6, score="Win for player2"), - dict(p1Points=16, p2Points=14, score="Win for player1"), - dict(p1Points=14, p2Points=16, score="Win for player2"), + (6, 4, 'Win for player1', 'player1', 'player2'), + (4, 6, 'Win for player2', 'player1', 'player2'), + (16, 14, 'Win for player1', 'player1', 'player2'), + (14, 16, 'Win for player2', 'player1', 'player2'), - dict(p1Points=6, p2Points=4, score="Win for One", p1Name='One'), - dict(p1Points=4, p2Points=6, score="Win for Two", p2Name="Two"), - dict(p1Points=6, p2Points=5, score="Advantage One", p1Name='One'), - dict(p1Points=5, p2Points=6, score="Advantage Two", p2Name="Two"), - ]) + (6, 4, 'Win for One', 'One', 'player2'), + (4, 6, 'Win for Two', 'player1', 'Two'), + (6, 5, 'Advantage One', 'One', 'player2'), + (5, 6, 'Advantage Two', 'player1', 'Two') + ]) def test_get_score(self, p1Points, p2Points, score, p1Name, p2Name): game = TennisGame(p1Name, p2Name) for i in range(p1Points): From e48300e32e7889cd82341f0316a5b9f307910a17 Mon Sep 17 00:00:00 2001 From: Frederic Lepied Date: Fri, 17 Aug 2012 11:31:01 +0200 Subject: [PATCH 041/634] ported the C++ version in C --- GildedRose/C/GildedRose.c | 90 +++++++++++++++++++++++++++++ GildedRose/C/GildedRose.h | 9 +++ GildedRose/C/GildedRoseTextTests.c | 43 ++++++++++++++ GildedRose/C/GildedRoseUnitTests.cc | 43 ++++++++++++++ GildedRose/C/Makefile | 51 ++++++++++++++++ GildedRose/C/README | 5 ++ GildedRose/C/run-once.sh | 2 + 7 files changed, 243 insertions(+) create mode 100644 GildedRose/C/GildedRose.c create mode 100644 GildedRose/C/GildedRose.h create mode 100644 GildedRose/C/GildedRoseTextTests.c create mode 100644 GildedRose/C/GildedRoseUnitTests.cc create mode 100644 GildedRose/C/Makefile create mode 100644 GildedRose/C/README create mode 100755 GildedRose/C/run-once.sh diff --git a/GildedRose/C/GildedRose.c b/GildedRose/C/GildedRose.c new file mode 100644 index 00000000..afb97bbe --- /dev/null +++ b/GildedRose/C/GildedRose.c @@ -0,0 +1,90 @@ +#include +#include "GildedRose.h" + +Item* +init_item(Item* item, const char *name, int sellIn, int quality) +{ + item->sellIn = sellIn; + item->quality = quality; + item->name = strdup(name); + + return item; +} + +void update_quality(Item items[], int size) +{ + int i; + + for (i = 0; i < size; i++) + { + if (strcmp(items[i].name, "Aged Brie") && strcmp(items[i].name, "Backstage passes to a TAFKAL80ETC concert")) + { + if (items[i].quality > 0) + { + if (strcmp(items[i].name, "Sulfuras, Hand of Ragnaros")) + { + items[i].quality = items[i].quality - 1; + } + } + } + else + { + if (items[i].quality < 50) + { + items[i].quality = items[i].quality + 1; + + if (!strcmp(items[i].name, "Backstage passes to a TAFKAL80ETC concert")) + { + if (items[i].sellIn < 11) + { + if (items[i].quality < 50) + { + items[i].quality = items[i].quality + 1; + } + } + + if (items[i].sellIn < 6) + { + if (items[i].quality < 50) + { + items[i].quality = items[i].quality + 1; + } + } + } + } + } + + if (strcmp(items[i].name, "Sulfuras, Hand of Ragnaros")) + { + items[i].sellIn = items[i].sellIn - 1; + } + + if (items[i].sellIn < 0) + { + if (strcmp(items[i].name, "Aged Brie")) + { + if (strcmp(items[i].name, "Backstage passes to a TAFKAL80ETC concert")) + { + if (items[i].quality > 0) + { + if (strcmp(items[i].name, "Sulfuras, Hand of Ragnaros")) + { + items[i].quality = items[i].quality - 1; + } + } + } + else + { + items[i].quality = items[i].quality - items[i].quality; + } + } + else + { + if (items[i].quality < 50) + { + items[i].quality = items[i].quality + 1; + } + } + } + } +} diff --git a/GildedRose/C/GildedRose.h b/GildedRose/C/GildedRose.h new file mode 100644 index 00000000..78d54a08 --- /dev/null +++ b/GildedRose/C/GildedRose.h @@ -0,0 +1,9 @@ +typedef struct +{ + char *name; + int sellIn; + int quality; +} Item; + +extern Item* init_item(Item* item, const char *name, int sellIn, int quality); +extern void update_quality(Item items[], int size); diff --git a/GildedRose/C/GildedRoseTextTests.c b/GildedRose/C/GildedRoseTextTests.c new file mode 100644 index 00000000..d200ca0c --- /dev/null +++ b/GildedRose/C/GildedRoseTextTests.c @@ -0,0 +1,43 @@ +#include +#include "GildedRose.h" + +int +print_item(Item *item) +{ + return printf("%s, %d, %d\n", item->name, item->sellIn, item->quality); +} + +int main() +{ + Item items[9]; + int last = 0; + int day; + int index; + + init_item(items + last++, "+5 Dexterity Vest", 10, 20); + init_item(items + last++, "Aged Brie", 2, 0); + init_item(items + last++, "Elixir of the Mongoose", 5, 7); + init_item(items + last++, "Sulfuras, Hand of Ragnaros", 0, 80); + init_item(items + last++, "Sulfuras, Hand of Ragnaros", -1, 80); + init_item(items + last++, "Backstage passes to a TAFKAL80ETC concert", 15, 20); + init_item(items + last++, "Backstage passes to a TAFKAL80ETC concert", 10, 49); + init_item(items + last++, "Backstage passes to a TAFKAL80ETC concert", 5, 49); + // this Conjured item doesn't yet work properly + init_item(items + last++, "Conjured Mana Cake", 3, 6); + + puts("OMGHAI!"); + + for (day = 0; day <= 30; day++) + { + printf("-------- day %d --------\n", day); + printf("name, sellIn, quality\n"); + for(index = 0; index < last; index++) { + print_item(items + index); + } + + printf("\n"); + + update_quality(items, last); + } + return 0; +} diff --git a/GildedRose/C/GildedRoseUnitTests.cc b/GildedRose/C/GildedRoseUnitTests.cc new file mode 100644 index 00000000..6d06fdb7 --- /dev/null +++ b/GildedRose/C/GildedRoseUnitTests.cc @@ -0,0 +1,43 @@ +#include +#include +#include + +extern "C" { +#include "GildedRose.h" +} + +TEST_GROUP(TestGildedRoseGroup) +{ + void setup() { + } + void teardown() { + } +}; + +TEST(TestGildedRoseGroup, FirstTest) +{ + Item items[2]; + init_item(items, "Foo", 0, 0); + update_quality(items, 1); + STRCMP_EQUAL("fixme", items[0].name); +} + +void example() +{ + Item items[6]; + int last = 0; + + init_item(items + last++, "+5 Dexterity Vest", 10, 20); + init_item(items + last++, "Aged Brie", 2, 0); + init_item(items + last++, "Elixir of the Mongoose", 5, 7); + init_item(items + last++, "Sulfuras, Hand of Ragnaros", 0, 80); + init_item(items + last++, "Backstage passes to a TAFKAL80ETC concert", 15, 20); + init_item(items + last++, "Conjured Mana Cake", 3, 6); + update_quality(items, last); +} + +int +main(int ac, char** av) +{ + return CommandLineTestRunner::RunAllTests(ac, av); +} diff --git a/GildedRose/C/Makefile b/GildedRose/C/Makefile new file mode 100644 index 00000000..60d11871 --- /dev/null +++ b/GildedRose/C/Makefile @@ -0,0 +1,51 @@ +# Makefile for building the kata file with the Google Testing Framework +# +# SYNOPSIS: +# +# make [all] - makes everything. +# make TARGET - makes the given target. +# make clean - removes all files generated by make. + +# Please tweak the following variable definitions as needed by your +# project. + +# Points to the root of CppUTest, relative to where this file is. +# Remember to tweak this if you move this file. +CPPUTEST_HOME = CppUTest + +# Where to find user code. +USER_DIR = . + +# Flags passed to the preprocessor. +CPPFLAGS += -I$(CPPUTEST_HOME)/include + +# Flags passed to the C++ compiler. +CFLAGS += -g -Wall -Wextra + +LD_LIBRARIES = -L$(CPPUTEST_HOME)/lib -lCppUTest -lCppUTestExt + +# All tests produced by this Makefile. Remember to add new tests you +# created to the list. +TESTS = GildedRoseUnitTests + +TEXTTESTS = GildedRoseTextTests + +# House-keeping build targets. + +all : $(TESTS) $(TEXTTESTS) + +GildedRose.o : $(USER_DIR)/GildedRose.c + +GildedRoseUnitTests : $(USER_DIR)/GildedRoseUnitTests.cc GildedRose.o + $(CXX) $(CPPFLAGS) $(CFLAGS) -o $@ $(USER_DIR)/GildedRoseUnitTests.cc GildedRose.o $(LD_LIBRARIES) + +GildedRoseTextTests.o : $(USER_DIR)/GildedRoseTextTests.c + +GildedRoseTextTests : GildedRoseTextTests.o GildedRose.o + $(CC) $^ -o $@ + +clean : + rm -f $(TESTS) $(TEXTTESTS) *.o *~ + +check-syntax: + gcc $(CPPFLAGS) -o /dev/null -S ${CHK_SOURCES} diff --git a/GildedRose/C/README b/GildedRose/C/README new file mode 100644 index 00000000..2bc1f69b --- /dev/null +++ b/GildedRose/C/README @@ -0,0 +1,5 @@ +run-once.sh runs your tests once + +Assumptions: + - make and a C++ compiler (like gcc) is installed on your system and is in the PATH + - The CppUTest framework is in the directory CppUTest diff --git a/GildedRose/C/run-once.sh b/GildedRose/C/run-once.sh new file mode 100755 index 00000000..4f6b2303 --- /dev/null +++ b/GildedRose/C/run-once.sh @@ -0,0 +1,2 @@ +make +./GildedRoseTextTests From 406fac268103f4a5905c6813f4855bf0882359f9 Mon Sep 17 00:00:00 2001 From: emilybache Date: Tue, 9 Oct 2012 15:51:08 +0200 Subject: [PATCH 042/634] Added test case for unittest which is in the standard library, and therefore more people have it. It's a less good test though, because it is not properly parameterized. --- Tennis/python/tennis_test.py | 49 ++---------------------- Tennis/python/tennis_unittest.py | 66 ++++++++++++++++++++++++++++++++ 2 files changed, 69 insertions(+), 46 deletions(-) create mode 100644 Tennis/python/tennis_unittest.py diff --git a/Tennis/python/tennis_test.py b/Tennis/python/tennis_test.py index 57bd0d70..450b14b0 100644 --- a/Tennis/python/tennis_test.py +++ b/Tennis/python/tennis_test.py @@ -1,54 +1,11 @@ import pytest from tennis import TennisGame -# actual test code +from tennis_unittest import test_cases + class TestTennis: - @pytest.mark.parametrize('p1Points p2Points score p1Name p2Name'.split(),[ - (0, 0, "Love-All", 'player1', 'player2'), - (1, 1, "Fifteen-All", 'player1', 'player2'), - (2, 2, "Thirty-All", 'player1', 'player2'), - (3, 3, "Forty-All", 'player1', 'player2'), - (4, 4, "Deuce", 'player1', 'player2'), - - (1, 0, "Fifteen-Love", 'player1', 'player2'), - (0, 1, "Love-Fifteen", 'player1', 'player2'), - (2, 0, "Thirty-Love", 'player1', 'player2'), - (0, 2, "Love-Thirty", 'player1', 'player2'), - (3, 0, "Forty-Love", 'player1', 'player2'), - (0, 3, "Love-Forty", 'player1', 'player2'), - (4, 0, "Win for player1", 'player1', 'player2'), - (0, 4, "Win for player2", 'player1', 'player2'), - - (2, 1, "Thirty-Fifteen", 'player1', 'player2'), - (1, 2, "Fifteen-Thirty", 'player1', 'player2'), - (3, 1, "Forty-Fifteen", 'player1', 'player2'), - (1, 3, "Fifteen-Forty", 'player1', 'player2'), - (4, 1, "Win for player1", 'player1', 'player2'), - (1, 4, "Win for player2", 'player1', 'player2'), - - (3, 2, "Forty-Thirty", 'player1', 'player2'), - (2, 3, "Thirty-Forty", 'player1', 'player2'), - (4, 2, "Win for player1", 'player1', 'player2'), - (2, 4, "Win for player2", 'player1', 'player2'), - - (4, 3, "Advantage player1", 'player1', 'player2'), - (3, 4, "Advantage player2", 'player1', 'player2'), - (5, 4, "Advantage player1", 'player1', 'player2'), - (4, 5, "Advantage player2", 'player1', 'player2'), - (15, 14, "Advantage player1", 'player1', 'player2'), - (14, 15, "Advantage player2", 'player1', 'player2'), - - (6, 4, 'Win for player1', 'player1', 'player2'), - (4, 6, 'Win for player2', 'player1', 'player2'), - (16, 14, 'Win for player1', 'player1', 'player2'), - (14, 16, 'Win for player2', 'player1', 'player2'), - - (6, 4, 'Win for One', 'One', 'player2'), - (4, 6, 'Win for Two', 'player1', 'Two'), - (6, 5, 'Advantage One', 'One', 'player2'), - (5, 6, 'Advantage Two', 'player1', 'Two') - ]) + @pytest.mark.parametrize('p1Points p2Points score p1Name p2Name'.split(), test_cases) def test_get_score(self, p1Points, p2Points, score, p1Name, p2Name): game = TennisGame(p1Name, p2Name) for i in range(p1Points): diff --git a/Tennis/python/tennis_unittest.py b/Tennis/python/tennis_unittest.py new file mode 100644 index 00000000..f2eca430 --- /dev/null +++ b/Tennis/python/tennis_unittest.py @@ -0,0 +1,66 @@ +import unittest + +from tennis import TennisGame + +test_cases = [ + (0, 0, "Love-All", 'player1', 'player2'), + (1, 1, "Fifteen-All", 'player1', 'player2'), + (2, 2, "Thirty-All", 'player1', 'player2'), + (3, 3, "Forty-All", 'player1', 'player2'), + (4, 4, "Deuce", 'player1', 'player2'), + + (1, 0, "Fifteen-Love", 'player1', 'player2'), + (0, 1, "Love-Fifteen", 'player1', 'player2'), + (2, 0, "Thirty-Love", 'player1', 'player2'), + (0, 2, "Love-Thirty", 'player1', 'player2'), + (3, 0, "Forty-Love", 'player1', 'player2'), + (0, 3, "Love-Forty", 'player1', 'player2'), + (4, 0, "Win for player1", 'player1', 'player2'), + (0, 4, "Win for player2", 'player1', 'player2'), + + (2, 1, "Thirty-Fifteen", 'player1', 'player2'), + (1, 2, "Fifteen-Thirty", 'player1', 'player2'), + (3, 1, "Forty-Fifteen", 'player1', 'player2'), + (1, 3, "Fifteen-Forty", 'player1', 'player2'), + (4, 1, "Win for player1", 'player1', 'player2'), + (1, 4, "Win for player2", 'player1', 'player2'), + + (3, 2, "Forty-Thirty", 'player1', 'player2'), + (2, 3, "Thirty-Forty", 'player1', 'player2'), + (4, 2, "Win for player1", 'player1', 'player2'), + (2, 4, "Win for player2", 'player1', 'player2'), + + (4, 3, "Advantage player1", 'player1', 'player2'), + (3, 4, "Advantage player2", 'player1', 'player2'), + (5, 4, "Advantage player1", 'player1', 'player2'), + (4, 5, "Advantage player2", 'player1', 'player2'), + (15, 14, "Advantage player1", 'player1', 'player2'), + (14, 15, "Advantage player2", 'player1', 'player2'), + + (6, 4, 'Win for player1', 'player1', 'player2'), + (4, 6, 'Win for player2', 'player1', 'player2'), + (16, 14, 'Win for player1', 'player1', 'player2'), + (14, 16, 'Win for player2', 'player1', 'player2'), + + (6, 4, 'Win for One', 'One', 'player2'), + (4, 6, 'Win for Two', 'player1', 'Two'), + (6, 5, 'Advantage One', 'One', 'player2'), + (5, 6, 'Advantage Two', 'player1', 'Two'), + + ] + +class TestTennis(unittest.TestCase): + + def test_Score(self): + for testcase in test_cases: + (p1Points, p2Points, score, p1Name, p2Name) = testcase + game = TennisGame(p1Name, p2Name) + for i in range(p1Points): + game.won_point(p1Name) + for i in range(p2Points): + game.won_point(p2Name) + self.assertEquals(score, game.score()) + +if __name__ == "__main__": + unittest.main() + \ No newline at end of file From b6cd227450eb8eed0c7b2d928af03ebf44672109 Mon Sep 17 00:00:00 2001 From: emilybache Date: Fri, 12 Oct 2012 15:58:16 +0200 Subject: [PATCH 043/634] separate file with Gilded Rose requirements --- GildedRose/GildedRoseRequirements.txt | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 GildedRose/GildedRoseRequirements.txt diff --git a/GildedRose/GildedRoseRequirements.txt b/GildedRose/GildedRoseRequirements.txt new file mode 100644 index 00000000..80b6165f --- /dev/null +++ b/GildedRose/GildedRoseRequirements.txt @@ -0,0 +1,26 @@ +====================================== +Gilded Rose Requirements Specification +====================================== + +Hi and welcome to team Gilded Rose. As you know, we are a small inn with a prime location in a prominent city ran by a friendly innkeeper named Allison. We also buy and sell only the finest goods. Unfortunately, our goods are constantly degrading in quality as they approach their sell by date. We have a system in place that updates our inventory for us. It was developed by a no-nonsense type named Leeroy, who has moved on to new adventures. Your task is to add the new feature to our system so that we can begin selling a new category of items. First an introduction to our system: + + - All items have a SellIn value which denotes the number of days we have to sell the item + - All items have a Quality value which denotes how valuable the item is + - At the end of each day our system lowers both values for every item + +Pretty simple, right? Well this is where it gets interesting: + + - Once the sell by date has passed, Quality degrades twice as fast + - The Quality of an item is never negative + - "Aged Brie" actually increases in Quality the older it gets + - The Quality of an item is never more than 50 + - "Sulfuras", being a legendary item, never has to be sold or decreases in Quality + - "Backstage passes", like aged brie, increases in Quality as it's SellIn value approaches; Quality increases by 2 when there are 10 days or less and by 3 when there are 5 days or less but Quality drops to 0 after the concert + +We have recently signed a supplier of conjured items. This requires an update to our system: + + - "Conjured" items degrade in Quality twice as fast as normal items + +Feel free to make any changes to the UpdateQuality method and add any new code as long as everything still works correctly. + +Just for clarification, an item can never have its Quality increase above 50, however "Sulfuras" is a legendary item and as such its Quality is 80 and it never alters. \ No newline at end of file From 0dde408d01a2e4391a0a50535824891d55015bb2 Mon Sep 17 00:00:00 2001 From: emilybache Date: Fri, 12 Oct 2012 15:58:55 +0200 Subject: [PATCH 044/634] C++ version of Yahtzee Kata by Jon Jagger. Taken from http://cyber-dojo.com/?id=57FFF6CEE2 --- Yahtzee/cpp/makefile | 6 + Yahtzee/cpp/run.tests | Bin 0 -> 24820 bytes Yahtzee/cpp/yahtzee.cpp | 251 ++++++++++++++++++++++++++++++++++ Yahtzee/cpp/yahtzee.hpp | 33 +++++ Yahtzee/cpp/yahtzee.tests.cpp | 153 +++++++++++++++++++++ 5 files changed, 443 insertions(+) create mode 100644 Yahtzee/cpp/makefile create mode 100755 Yahtzee/cpp/run.tests create mode 100644 Yahtzee/cpp/yahtzee.cpp create mode 100644 Yahtzee/cpp/yahtzee.hpp create mode 100644 Yahtzee/cpp/yahtzee.tests.cpp diff --git a/Yahtzee/cpp/makefile b/Yahtzee/cpp/makefile new file mode 100644 index 00000000..29429df5 --- /dev/null +++ b/Yahtzee/cpp/makefile @@ -0,0 +1,6 @@ +run.tests.output : run.tests + ./run.tests + +run.tests : *.cpp + g++ -Wall -Werror -O *.cpp -o run.tests + diff --git a/Yahtzee/cpp/run.tests b/Yahtzee/cpp/run.tests new file mode 100755 index 0000000000000000000000000000000000000000..7f78da1fc3afbaf3b70df68ef0c7528c1873b89b GIT binary patch literal 24820 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 + +int Yahtzee::Chance(int d1, int d2, int d3, int d4, int d5) +{ + int total = 0; + total += d1; + total += d2; + total += d3; + total += d4; + total += d5; + return total; +} + + +int Yahtzee::yahtzee(int dice[]) +{ + int counts[6] = {0,0,0,0,0,0}; + for (int i = 0; i != 5; i++) + counts[dice[i]-1]++; + for (int i = 0; i != 6; i++) + if (counts[i] == 5) + return 50; + return 0; +} + +int Yahtzee::Ones(int d1, int d2, int d3, int d4, int d5) { + int sum = 0; + if (d1 == 1) sum++; + if (d2 == 1) sum++; + if (d3 == 1) sum++; + if (d4 == 1) sum++; + if (d5 == 1) + sum++; + + return sum; +} + +int Yahtzee::Twos(int d1, int d2, int d3, int d4, int d5) { + int sum = 0; + if (d1 == 2) sum += 2; + if (d2 == 2) sum += 2; + if (d3 == 2) sum += 2; + if (d4 == 2) sum += 2; + if (d5 == 2) sum += 2; + return sum; +} + + +int Yahtzee::Threes(int d1, int d2, int d3, int d4, int d5) { + int s; + s = 0; + if (d1 == 3) s += 3; + if (d2 == 3) s += 3; + if (d3 == 3) s += 3; + if (d4 == 3) s += 3; + if (d5 == 3) s += 3; + return s; +} + +Yahtzee::Yahtzee() +{ +} + +Yahtzee::Yahtzee(int d1, int d2, int d3, int d4, int _5) +{ + dice = new int[5]; + dice[0] = d1; + dice[1] = d2; + dice[2] = d3; + dice[3] = d4; + dice[4] = _5; +} + +int Yahtzee::Fours() +{ + int sum; + sum = 0; + for (int at = 0; at != 5; at++) { + if (dice[at] == 4) { + sum += 4; + } + } + return sum; +} + + +int Yahtzee::Fives() +{ + int s = 0; + int i; + for (i = 0; i < 5; i++) + if (dice[i] == 5) + s = s + 5; + return s; +} + +int Yahtzee::sixes() +{ + int sum = 0; + for (int at = 0; at < 5; at++) + if (dice[at] == 6) + sum = sum + 6; + return sum; +} + +int Yahtzee::ScorePair(int d1, int d2, int d3, int d4, int d5) +{ + int counts[6] = {0,0,0,0,0,0}; + counts[d1-1]++; + counts[d2-1]++; + counts[d3-1]++; + counts[d4-1]++; + counts[d5-1]++; + int at; + for (at = 0; at != 6; at++) + if (counts[6-at-1] == 2) + return (6-at)*2; + return 0; +} + +int Yahtzee::TwoPair(int d1, int d2, int d3, int d4, int d5) +{ + int counts[6] = {0}; + counts[d1-1]++; + counts[d2-1]++; + counts[d3-1]++; + counts[d4-1]++; + counts[d5-1]++; + int n = 0; + int score = 0; + for (int i = 0; i < 6; i += 1) + if (counts[6-i-1] == 2) { + n++; + score += (6-i); + } + if (n == 2) + return score * 2; + else + return 0; +} + +int Yahtzee::FourOfAKind(int _1, int _2, int d3, int d4, int d5) +{ + int * tallies; + tallies = new int[6]; + tallies[0] = tallies[1] = tallies[2] = 0; + tallies[3] = tallies[4] = tallies[5] = 0; + tallies[_1-1]++; + tallies[_2-1]++; + tallies[d3-1]++; + tallies[d4-1]++; + tallies[d5-1]++; + for (int i = 0; i < 6; i++) + if (tallies[i] == 4) + return (i+1) * 4; + return 0; +} + +int Yahtzee::ThreeOfAKind(int d1, int d2, int d3, int d4, int d5) +{ + int * t; + t = new int[6]; + t[0] = t[1] = t[2] = 0; + t[3] = t[4] = t[5] = 0; + t[d1-1]++; + t[d2-1]++; + t[d3-1]++; + t[d4-1]++; + t[d5-1]++; + for (int i = 0; i < 6; i++) + if (t[i] == 3) + return (i+1) * 3; + return 0; +} + + +int Yahtzee::SmallStraight(int d1, int d2, int d3, int d4, int d5) +{ + int* tallies =new int[6]; + memset(tallies, 0, sizeof(int)*6); + tallies[d1-1] += 1; + tallies[d2-1] += 1; + tallies[d3-1] += 1; + tallies[d4-1] += 1; + tallies[d5-1] += 1; + if (tallies[0] == 1 && + tallies[1] == 1 && + tallies[2] == 1 && + tallies[3] == 1 && + tallies[4] == 1) + return 15; + return 0; +} + +int Yahtzee::LargeStraight(int d1, int d2, int d3, int d4, int d5) +{ + int* tallies = new int[6]; + memset(tallies, 0, sizeof(*tallies)*6); + tallies[d1-1] += 1; + tallies[d2-1] += 1; + tallies[d3-1] += 1; + tallies[d4-1] += 1; + tallies[d5-1] += 1; + if (tallies[1] == 1 && + tallies[2] == 1 && + tallies[3] == 1 && + tallies[4] == 1 + && tallies[5] == 1) + return 20; + return 0; +} + + +int Yahtzee::FullHouse(int d1, int d2, int d3, int d4, int d5) +{ + int* tallies; + bool _2 = false; + int i; + int _2_at = 0; + bool _3 = false; + int _3_at = 0; + + + + + tallies = new int[6]; + memset(tallies, 0, sizeof(int)*6); + tallies[d1-1] += 1; + tallies[d2-1] += 1; + tallies[d3-1] += 1; + tallies[d4-1] += 1; + tallies[d5-1] += 1; + + for (i = 0; i != 6; i += 1) + if (tallies[i] == 2) { + _2 = true; + _2_at = i+1; + } + + for (i = 0; i != 6; i += 1) + if (tallies[i] == 3) { + _3 = true; + _3_at = i+1; + } + + if (_2 && _3) + return _2_at * 2 + _3_at * 3; + else + return 0; +} diff --git a/Yahtzee/cpp/yahtzee.hpp b/Yahtzee/cpp/yahtzee.hpp new file mode 100644 index 00000000..c79dce48 --- /dev/null +++ b/Yahtzee/cpp/yahtzee.hpp @@ -0,0 +1,33 @@ +#ifndef YAHTZEE_INCLUDED +#define YATHZEE_INCLUDED + +class Yahtzee +{ +public: + + static int Chance(int d1, int d2, int d3, int d4, int d5); + static int yahtzee(int dice[]); + static int Ones(int d1, int d2, int d3, int d4, int d5); + static int Twos(int d1, int d2, int d3, int d4, int d5); + static int Threes(int d1, int d2, int d3, int d4, int d5); + +protected: + int * dice; +public: + Yahtzee(); + Yahtzee(int d1, int d2, int d3, int d4, int _5); + int Fours(); + int Fives(); + int sixes(); + int ScorePair(int d1, int d2, int d3, int d4, int d5); + static int TwoPair(int d1, int d2, int d3, int d4, int d5); + static int FourOfAKind(int _1, int _2, int d3, int d4, int d5); + static int ThreeOfAKind(int d1, int d2, int d3, int d4, int d5); + + static int SmallStraight(int d1, int d2, int d3, int d4, int d5); + static int LargeStraight(int d1, int d2, int d3, int d4, int d5); + static int FullHouse(int d1, int d2, int d3, int d4, int d5); + +}; + +#endif \ No newline at end of file diff --git a/Yahtzee/cpp/yahtzee.tests.cpp b/Yahtzee/cpp/yahtzee.tests.cpp new file mode 100644 index 00000000..42878ea9 --- /dev/null +++ b/Yahtzee/cpp/yahtzee.tests.cpp @@ -0,0 +1,153 @@ +#include "yahtzee.hpp" +#include +#include + +static void Chance_scores_sum_of_all_dice(void) +{ + int expected = 15; + int actual = Yahtzee().Chance(2,3,4,5,1); + assert(expected == actual); + assert(16 == Yahtzee().Chance(3,3,4,5,1)); +} + +static int * ints(int a, int b, int c, int d, int e) +{ + int * r = new int[5]; + r[0] = a; + r[1] = b; + r[2] = c; + r[3] = d; + r[4] = e; + return r; +} + +static void Yahtzee_scores_50(void) +{ + int expected = 50; + int actual = Yahtzee().yahtzee(ints(4,4,4,4,4)); + assert(expected == actual); + assert(50 == Yahtzee().yahtzee(ints(6,6,6,6,6))); + assert(0 == Yahtzee().yahtzee(ints(6,6,6,6,3))); +} + +static void Test_1s() +{ + assert(Yahtzee().Ones(1,2,3,4,5) == 1); + assert(2 == Yahtzee().Ones(1,2,1,4,5)); + assert(0 == Yahtzee().Ones(6,2,2,4,5)); + assert(4 == Yahtzee().Ones(1,2,1,1,1)); +} + +static void test_2s() +{ + assert(4 == Yahtzee().Twos(1,2,3,2,6)); + assert(10 == Yahtzee().Twos(2,2,2,2,2)); +} + +static void test_threes() +{ + assert(6 == Yahtzee().Threes(1,2,3,2,3)); + assert(12 == Yahtzee().Threes(2,3,3,3,3)); +} + +static void fours_test() +{ + assert(12 == (new Yahtzee(4,4,4,5,5))->Fours()); + assert(8 == (new Yahtzee(4,4,5,5,5))->Fours()); + assert(4 == (*new Yahtzee(4,5,5,5,5)).Fours()); +} + +static void fives() { + assert(10 == (new Yahtzee(4,4,4,5,5))->Fives()); + assert(15 == Yahtzee(4,4,5,5,5).Fives()); + assert(20 == Yahtzee(4,5,5,5,5).Fives()); +} + +static void sixes_test() +{ + assert(0 == Yahtzee(4,4,4,5,5).sixes()); + assert(6 == Yahtzee(4,4,6,5,5).sixes()); + assert(18 == Yahtzee(6,5,6,6,5).sixes()); +} + +static void one_pair() +{ + assert(6 == Yahtzee().ScorePair(3,4,3,5,6)); + assert(10 == Yahtzee().ScorePair(5,3,3,3,5)); + assert(12 == Yahtzee().ScorePair(5,3,6,6,5)); +} + +static void two_Pair() +{ + assert(16 == Yahtzee().TwoPair(3,3,5,4,5)); + assert(0 == Yahtzee().TwoPair(3,3,5,5,5)); +} + +static void three_of_a_kind() +{ + assert(9 == Yahtzee().ThreeOfAKind(3,3,3,4,5)); + assert(15 == Yahtzee().ThreeOfAKind(5,3,5,4,5)); + assert(0 == Yahtzee::ThreeOfAKind(3,3,3,3,5)); +} + +static void four_of_a_knd() +{ + assert(12 == Yahtzee::FourOfAKind(3,3,3,3,5)); + assert(20 == Yahtzee::FourOfAKind(5,5,5,4,5)); + assert(0 == Yahtzee::FourOfAKind(3,3,3,3,3)); +} + +static void smallStraight() +{ + assert(15 == Yahtzee::SmallStraight(1,2,3,4,5)); + assert(15 == Yahtzee::SmallStraight(2,3,4,5,1)); + assert(0 == Yahtzee().SmallStraight(1,2,2,4,5)); +} + +static void largeStraight() +{ + assert(20 == Yahtzee::LargeStraight(6,2,3,4,5)); + assert(20 == Yahtzee().LargeStraight(2,3,4,5,6)); + assert(0== Yahtzee::LargeStraight(1,2,2,4,5)); +} + + +static void fullHouse() +{ + assert(18 == Yahtzee().FullHouse(6,2,2,2,6)); + assert(0 == Yahtzee().FullHouse(2,3,4,5,6)); +} + +typedef void test(); + +static test * tests[ ] = +{ + Chance_scores_sum_of_all_dice, + Yahtzee_scores_50, + Test_1s, + test_2s, + test_threes, + fours_test, + fives, + sixes_test, + one_pair, + two_Pair, + three_of_a_kind, + four_of_a_knd, + smallStraight, + largeStraight, + fullHouse, + static_cast(0), +}; + +int main() +{ + size_t at = 0; + while (tests[at]) + { + tests[at++](); + std::cout << '.'; + } + std::cout << std::endl << at << " tests passed" << std::endl; + return 0; +} \ No newline at end of file From f416ee371acc9f33127470a0bba70ee59f27bb9c Mon Sep 17 00:00:00 2001 From: emilybache Date: Fri, 12 Oct 2012 16:17:59 +0200 Subject: [PATCH 045/634] Updated the README files to markdown, improved the instructions. --- GildedRose/GildedRoseRequirements.txt | 2 +- GildedRose/README | 54 --------------------------- GildedRose/README.md | 24 ++++++++++++ README | 9 ----- README.md | 13 +++++++ Tennis/README.md | 18 +++++++++ Yahtzee/{README => README.md} | 18 +++------ 7 files changed, 62 insertions(+), 76 deletions(-) delete mode 100644 GildedRose/README create mode 100644 GildedRose/README.md delete mode 100644 README create mode 100644 README.md create mode 100644 Tennis/README.md rename Yahtzee/{README => README.md} (90%) diff --git a/GildedRose/GildedRoseRequirements.txt b/GildedRose/GildedRoseRequirements.txt index 80b6165f..a8f47b48 100644 --- a/GildedRose/GildedRoseRequirements.txt +++ b/GildedRose/GildedRoseRequirements.txt @@ -21,6 +21,6 @@ We have recently signed a supplier of conjured items. This requires an update to - "Conjured" items degrade in Quality twice as fast as normal items -Feel free to make any changes to the UpdateQuality method and add any new code as long as everything still works correctly. +Feel free to make any changes to the UpdateQuality method and add any new code as long as everything still works correctly. However, do not alter the Item class or Items property as those belong to the goblin in the corner who will insta-rage and one-shot you as he doesn't believe in shared code ownership (you can make the UpdateQuality method and Items property static if you like, we'll cover for you). Just for clarification, an item can never have its Quality increase above 50, however "Sulfuras" is a legendary item and as such its Quality is 80 and it never alters. \ No newline at end of file diff --git a/GildedRose/README b/GildedRose/README deleted file mode 100644 index 3ba18362..00000000 --- a/GildedRose/README +++ /dev/null @@ -1,54 +0,0 @@ -This Kata was originally created by Terry Hughes (http://twitter.com/#!/TerryHughes). It is already on GitHub as "GildedRose", a sample project for C#. I could have forked it again, but I thought other language users might not want to download a whole C# project environment. In this repository are starting code samples for Java, Python, Ruby, Smalltalk, C# and C++. - -See also http://iamnotmyself.com/2011/02/13/refactor-this-the-gilded-rose-kata/ - -==================== -How to use this Kata -==================== - -The simplest way is to just clone the code and start hacking away improving the design. You'll want to look at the "Gilded Rose Background Reading" (below) which explains what the code is for. I strongly advise you that you'll also need some tests if you want to make sure you don't break the code while you refactor. - -You could write some unit tests yourself, using the Kata Background Reading (below) to identify suitable test cases. I've provided a failing unit test in a popular test framework as a starting point for most languages. - -Alternatively, use the "Text-Based" tests provided in this repository. (Read more about that in the next section) - -Whichever testing approach you choose, the idea of the exercise is to do some deliberate practice, and improve your Refactoring skills. The idea is not to re-write the code from scratch, but rather to practice taking small steps, running the tests often, and incrementally improving the design. - -================== -Text-Based Testing -================== - -This is a testing approach which is very useful when refactoring legacy code. The basic idea is to create tests that use the text which the code produces. Before you change the code, you run it, and save the output as a "Golden Copy". Then after you change the code, you run it again, and compare the output against the Golden Copy. Any differences, and the test fails. - -It's basically the same idea as "assertEquals(expected, actual)" in a unit test, except the text you are comparing is typically much longer, and the "expected" value is saved from actual output, rather than being defined in advance. - -Typically a piece of legacy code may not produce suitable textual output from the start, so you may need to modify it before you can write your first text-based test. That could involve inserting log statements into the code, or just writing a "main" method that executes the code and prints out what the result is afterwards. It's this latter approach we are using here to test GildedRose. - -The Text-Based tests in this repository are designed to be used with the tool "TextTest" (http://texttest.org). This tool helps you to organize and run text-based tests. There is more information in the README file in the "texttests" subdirectory. - -=================================== -Gilded Rose Kata Background Reading -=================================== - -Hi and welcome to team Gilded Rose. As you know, we are a small inn with a prime location in a prominent city ran by a friendly innkeeper named Allison. We also buy and sell only the finest goods. Unfortunately, our goods are constantly degrading in quality as they approach their sell by date. We have a system in place that updates our inventory for us. It was developed by a no-nonsense type named Leeroy, who has moved on to new adventures. Your task is to add the new feature to our system so that we can begin selling a new category of items. First an introduction to our system: - - - All items have a SellIn value which denotes the number of days we have to sell the item - - All items have a Quality value which denotes how valuable the item is - - At the end of each day our system lowers both values for every item - -Pretty simple, right? Well this is where it gets interesting: - - - Once the sell by date has passed, Quality degrades twice as fast - - The Quality of an item is never negative - - "Aged Brie" actually increases in Quality the older it gets - - The Quality of an item is never more than 50 - - "Sulfuras", being a legendary item, never has to be sold or decreases in Quality - - "Backstage passes", like aged brie, increases in Quality as it's SellIn value approaches; Quality increases by 2 when there are 10 days or less and by 3 when there are 5 days or less but Quality drops to 0 after the concert - -We have recently signed a supplier of conjured items. This requires an update to our system: - - - "Conjured" items degrade in Quality twice as fast as normal items - -Feel free to make any changes to the UpdateQuality method and add any new code as long as everything still works correctly. However, do not alter the Item class or Items property as those belong to the goblin in the corner who will insta-rage and one-shot you as he doesn't believe in shared code ownership (you can make the UpdateQuality method and Items property static if you like, we'll cover for you). - -Just for clarification, an item can never have its Quality increase above 50, however "Sulfuras" is a legendary item and as such its Quality is 80 and it never alters. \ No newline at end of file diff --git a/GildedRose/README.md b/GildedRose/README.md new file mode 100644 index 00000000..1672283e --- /dev/null +++ b/GildedRose/README.md @@ -0,0 +1,24 @@ +This Kata was originally created by Terry Hughes (http://twitter.com/#!/TerryHughes). It is already on GitHub [here](https://github.com/NotMyself/GildedRose). I could have forked it again, but I thought other language users might not want to download a whole C# project environment. In this repository are starting code samples for Java, Python, Ruby, Smalltalk, C#, C and C++. + +See also http://iamnotmyself.com/2011/02/13/refactor-this-the-gilded-rose-kata/ + +## How to use this Kata + +The simplest way is to just clone the code and start hacking away improving the design. You'll want to look at the ["Gilded Rose Requirements"](https://github.com/emilybache/Refactoring-Katas/blob/master/GildedRose/GildedRoseRequirements.txt) which explains what the code is for. I strongly advise you that you'll also need some tests if you want to make sure you don't break the code while you refactor. + +You could write some unit tests yourself, using the requirements to identify suitable test cases. I've provided a failing unit test in a popular test framework as a starting point for most languages. + +Alternatively, use the "Text-Based" tests provided in this repository. (Read more about that in the next section) + +Whichever testing approach you choose, the idea of the exercise is to do some deliberate practice, and improve your Refactoring skills. The idea is not to re-write the code from scratch, but rather to practice taking small steps, running the tests often, and incrementally improving the design. + +## Text-Based Testing + +This is a testing approach which is very useful when refactoring legacy code. The basic idea is to create tests that use the text which the code produces. Before you change the code, you run it, and save the output as a "Golden Copy". Then after you change the code, you run it again, and compare the output against the Golden Copy. Any differences, and the test fails. + +It's basically the same idea as "assertEquals(expected, actual)" in a unit test, except the text you are comparing is typically much longer, and the "expected" value is saved from actual output, rather than being defined in advance. + +Typically a piece of legacy code may not produce suitable textual output from the start, so you may need to modify it before you can write your first text-based test. That could involve inserting log statements into the code, or just writing a "main" method that executes the code and prints out what the result is afterwards. It's this latter approach we are using here to test GildedRose. + +The Text-Based tests in this repository are designed to be used with the tool "TextTest" (http://texttest.org). This tool helps you to organize and run text-based tests. There is more information in the README file in the "texttests" subdirectory. + diff --git a/README b/README deleted file mode 100644 index f2fc971c..00000000 --- a/README +++ /dev/null @@ -1,9 +0,0 @@ -Can you refactor? In really small steps? Can you turn some, frankly, ugly code into a paradigm of elegant, readable, extensible design? - -This is a collection of starting files for when practicing refactoring. - -Contents so far: - -Tennis Kata in Java, Python and C++. -Gilded Rose Kata in C++, C#, Java, Python and Ruby. (a C# version together with a starting project is already available on github) -Yahtzee Kata in C#, Java and Python (the C# and Java versions are also available in Jon Jagger's Cyberdojo) \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 00000000..18fc3dee --- /dev/null +++ b/README.md @@ -0,0 +1,13 @@ +# Refactoring Katas + +Can you refactor? In really small steps? Can you turn some, frankly, ugly code into a paradigm of elegant, readable, extensible design? + +This is a collection of starting files for when practicing refactoring. + +Contents so far: + +- Tennis Kata in Java, Python and C++. +- Gilded Rose Kata in C++, C#, Java, Python, Smalltalk, C and Ruby. (a C# version together with a starting project is already available on github [here](https://github.com/NotMyself/GildedRose)) +- Yahtzee Kata in C#, Java, C++ and Python (the C#, C++ and Java versions are also available in Jon Jagger's Cyberdojo, see [his blog post](http://jonjagger.blogspot.co.uk/2012/05/yahtzee-cyber-dojo-refactoring-in-java.html)) + +For more information about these and other katas, you may be interested in my book [The Coding Dojo Handbook](http://leanpub.com/codingdojohandbook) \ No newline at end of file diff --git a/Tennis/README.md b/Tennis/README.md new file mode 100644 index 00000000..76aed18c --- /dev/null +++ b/Tennis/README.md @@ -0,0 +1,18 @@ +# Tennis Refactoring Kata + +There are three versions of this refactoring kata, each with their own design smells and challenges. Two have been written by junior programmers with a weak grasp of how to solve the problem. The third is by an evil genius who values compactness above all else. The test suite provided is fairly comprehensive, and fast to run. You should not need to change the tests, only run them often as you refactor. + +## Tennis Kata + +Tennis has a rather quirky scoring system, and to newcomers it can be a little difficult to keep track of. The tennis society has contracted you to build a scoreboard to display the current score during tennis games. + +Your task is to write a “TennisGame” class containing the logic which outputs the correct score as a string for display on the scoreboard. When a player scores a point, it triggers a method to be called on your class letting you know who scored the point. Later, you will get a call “currentScore()” from the scoreboard asking what it should display. This method should return a string with the current score. + +You can read more about Tennis scores [here](http://en.wikipedia.org/wiki/Tennis#Scoring) which is summarized below: + +1. A game is won by the first player to have won at least four points in total and at least two points more than the opponent. +2. The running score of each game is described in a manner peculiar to tennis: scores from zero to three points are described as "love", "fifteen", "thirty", and "forty" respectively. +3. If at least three points have been scored by each player, and the scores are equal, the score is "deuce". +4. If at least three points have been scored by each side and a player has one more point than his opponent, the score of the game is "advantage" for the player in the lead. + +You need only report the score for the current game. Sets and Matches are out of scope. diff --git a/Yahtzee/README b/Yahtzee/README.md similarity index 90% rename from Yahtzee/README rename to Yahtzee/README.md index c6a65a1b..e861ff50 100644 --- a/Yahtzee/README +++ b/Yahtzee/README.md @@ -1,19 +1,12 @@ -======================== -Yahtzee Refactoring Kata -======================== +# Yahtzee Refactoring Kata -This Refactoring Kata was designed by Jon Jagger and is available in his Cyber-Dojo on these urls: - -C#: http://cyber-dojo.com/diff/show/E4466E24B2?avatar=elephant&tag=26 -Java: http://cyber-dojo.com/diff/show/3D5589AA49?avatar=panda&tag=1 +This Refactoring Kata was designed by Jon Jagger and is available in his Cyber-Dojo. See [his blog post](http://jonjagger.blogspot.co.uk/2012/05/yahtzee-cyber-dojo-refactoring-in-java.html) The other language translations have been contributed by: Python: Emily Bache -============= -Yahtzee rules -============= +## Kata: Yahtzee rules The game of yahtzee is a simple dice game. Each player rolls five six-sided dice. They can re-roll some or all @@ -46,8 +39,9 @@ The game is NOT played by letting the computer choose the highest scoring category for a given roll. -Yahzee Categories and Scoring Rules -=================================== +## Kata: Yahzee Categories and Scoring Rules + +_Note these rules differ from the original (copyrighted) rules_ Chance: The player scores the sum of all dice, From 041c04db18b01951302b042d41d1c009689d8ba2 Mon Sep 17 00:00:00 2001 From: emilybache Date: Sun, 14 Oct 2012 11:01:20 +0200 Subject: [PATCH 046/634] updated README file to markdown syntax, added link to texttest mailing list --- GildedRose/texttests/{README => README.md} | 24 +++++++++++----------- 1 file changed, 12 insertions(+), 12 deletions(-) rename GildedRose/texttests/{README => README.md} (56%) diff --git a/GildedRose/texttests/README b/GildedRose/texttests/README.md similarity index 56% rename from GildedRose/texttests/README rename to GildedRose/texttests/README.md index fa903565..7f8a53ca 100644 --- a/GildedRose/texttests/README +++ b/GildedRose/texttests/README.md @@ -1,18 +1,16 @@ +# TextTest regression tests + This folder contains Text-Based tests for the GildedRose Refactoring Kata. These tests are designed to be used with the open source testing tool "TextTest", available from http://texttest.org You can run them without it too though, see below. -======================== -Running without TextTest -======================== +## Running without TextTest This should be perfectly possible, but is probably less convenient than using TextTest. Write a script that will execute the SUT (see "config.gr" for details of the executables), giving the commandline options listed in "options.gr". Collect the output from standard output in a file, and diff that against the golden copy "stdout.gr". Any diff is a test failure. -===================== -Running with TextTest -===================== +## Running with TextTest - Install TextTest (see http://texttest.org) - set $TEXTTEST_HOME environment variable to point at the "texttests" folder @@ -22,16 +20,18 @@ This should start the GUI for the TextTest tool. Each test case has it's own subdirectory. The name of the directory is the name of the test - in this case "ThirtyDays". The "Golden Copy" of the output for that test case is kept in that directory. In this case we have three files: -stderr.gr - the expected output to Standard Error (stderr) -stdout.gr - the expected output to Standard Output (stdout) -options.gr - the options to give on the command line when you run the System Under Test (SUT) +- __stderr.gr__ - the expected output to Standard Error (stderr) +- __stdout.gr__ - the expected output to Standard Output (stdout) +- __options.gr__ - the options to give on the command line when you run the System Under Test (SUT) In the directory above, there are configuration files for TextTest: -config.gr - this tells TextTest where to find the SUT executable, and sets up options for how it runs the SUT and interprets the output. -environment.gr - this file lists environment variables that will be set before TextTest runs the SUT. This is especially important for Java applications, that must set the CLASSPATH environment variable in order to run properly. -testsuite.gr - lists the constituent test cases of this suite. Change the order of the entries here to change the order they appear in the TextTest GUI. +- __config.gr__ - this tells TextTest where to find the SUT executable, and sets up options for how it runs the SUT and interprets the output. +- __environment.gr__ - this file lists environment variables that will be set before TextTest runs the SUT. This is especially important for Java applications, that must set the CLASSPATH environment variable in order to run properly. +- __testsuite.gr__ - lists the constituent test cases of this suite. Change the order of the entries here to change the order they appear in the TextTest GUI. To run a test, click on it in the GUI and select "Run". TextTest will run it in a temporary (sandbox) directory and report the results. If the test fails, you can double click on a file to see the diff against the Golden Copy. +If you run into difficulties with TextTest, there is documentation available on [texttest.org](http://texttest.org), or you can ask a question on the [mailing list](https://lists.sourceforge.net/lists/listinfo/texttest-users). + From ca6f1a5b555e579b8ec4f181df10ec878a69d9f8 Mon Sep 17 00:00:00 2001 From: emilybache Date: Mon, 5 Nov 2012 20:58:35 +0100 Subject: [PATCH 047/634] change to using unittest instead of py.test since it comes with the standard library --- GildedRose/python/test_gilded_rose.py | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/GildedRose/python/test_gilded_rose.py b/GildedRose/python/test_gilded_rose.py index 34304cdb..51e15ba5 100644 --- a/GildedRose/python/test_gilded_rose.py +++ b/GildedRose/python/test_gilded_rose.py @@ -1,6 +1,13 @@ +import unittest + from gilded_rose import Item, update_quality -def test_foo(): - items = [Item("foo", 0, 0)] - update_quality(items) - assert "fixme" == items[0].name \ No newline at end of file +class GildedRoseTest(unittest.TestCase): + def test_foo(self): + items = [Item("foo", 0, 0)] + update_quality(items) + self.assertEquals("fixme", items[0].name) + + +if __name__ == "__main__": + unittest.main() \ No newline at end of file From 5fb9f52b48630c2588b2c90093b4a99af412d5f7 Mon Sep 17 00:00:00 2001 From: emilybache Date: Wed, 21 Nov 2012 10:21:22 +0100 Subject: [PATCH 048/634] added encoding, fixed som PEP-8 issues. Thanks to apieum for these changes. --- GildedRose/python/gilded_rose.py | 22 ++++++++++++---------- GildedRose/python/test_gilded_rose.py | 5 +++-- GildedRose/python/texttest_fixture.py | 6 +++--- 3 files changed, 18 insertions(+), 15 deletions(-) diff --git a/GildedRose/python/gilded_rose.py b/GildedRose/python/gilded_rose.py index 334bec86..67ea3849 100755 --- a/GildedRose/python/gilded_rose.py +++ b/GildedRose/python/gilded_rose.py @@ -1,41 +1,43 @@ +# -*- coding: utf-8 -*- + def update_quality(items): for item in items: if item.name != "Aged Brie" and item.name != "Backstage passes to a TAFKAL80ETC concert": if item.quality > 0: if item.name != "Sulfuras, Hand of Ragnaros": - item.quality = item.quality - 1; + item.quality = item.quality - 1 else: if item.quality < 50: - item.quality = item.quality + 1; + item.quality = item.quality + 1 if item.name == "Backstage passes to a TAFKAL80ETC concert": if item.sell_in < 11: if item.quality < 50: - item.quality = item.quality + 1; + item.quality = item.quality + 1 if item.sell_in < 6: if item.quality < 50: - item.quality = item.quality + 1; + item.quality = item.quality + 1 if item.name != "Sulfuras, Hand of Ragnaros": - item.sell_in = item.sell_in - 1; + item.sell_in = item.sell_in - 1 if item.sell_in < 0: if item.name != "Aged Brie": if item.name != "Backstage passes to a TAFKAL80ETC concert": if item.quality > 0: if item.name != "Sulfuras, Hand of Ragnaros": - item.quality = item.quality - 1; + item.quality = item.quality - 1 else: - item.quality = item.quality - item.quality; + item.quality = item.quality - item.quality else: if item.quality < 50: - item.quality = item.quality + 1; + item.quality = item.quality + 1 return items + class Item: def __init__(self, name, sell_in, quality): self.name = name self.sell_in = sell_in self.quality = quality - + def __repr__(self): return "%s, %s, %s" % (self.name, self.sell_in, self.quality) - diff --git a/GildedRose/python/test_gilded_rose.py b/GildedRose/python/test_gilded_rose.py index 51e15ba5..e615c2ca 100644 --- a/GildedRose/python/test_gilded_rose.py +++ b/GildedRose/python/test_gilded_rose.py @@ -1,7 +1,8 @@ +# -*- coding: utf-8 -*- import unittest - from gilded_rose import Item, update_quality + class GildedRoseTest(unittest.TestCase): def test_foo(self): items = [Item("foo", 0, 0)] @@ -10,4 +11,4 @@ class GildedRoseTest(unittest.TestCase): if __name__ == "__main__": - unittest.main() \ No newline at end of file + unittest.main() diff --git a/GildedRose/python/texttest_fixture.py b/GildedRose/python/texttest_fixture.py index b85634c1..de921093 100644 --- a/GildedRose/python/texttest_fixture.py +++ b/GildedRose/python/texttest_fixture.py @@ -1,5 +1,5 @@ +# -*- coding: utf-8 -*- from __future__ import print_function - from gilded_rose import * if __name__ == "__main__": @@ -13,9 +13,9 @@ if __name__ == "__main__": Item(name="Backstage passes to a TAFKAL80ETC concert", sell_in=15, quality=20), Item(name="Backstage passes to a TAFKAL80ETC concert", sell_in=10, quality=49), Item(name="Backstage passes to a TAFKAL80ETC concert", sell_in=5, quality=49), - Item(name="Conjured Mana Cake", sell_in=3, quality=6), # <-- :O + Item(name="Conjured Mana Cake", sell_in=3, quality=6), # <-- :O ] - + days = 2 import sys if len(sys.argv) > 1: From 52fb51eede4d2488fb9e4304d920d0ff5e978424 Mon Sep 17 00:00:00 2001 From: emilybache Date: Wed, 21 Nov 2012 10:48:38 +0100 Subject: [PATCH 049/634] Fixed an issue where the tests weren't really doing a realistic game. Now the players exchange points instead of one player scoring all theirs, and the other player scoring all theirs. --- Tennis/python/tennis.py | 4 +++- Tennis/python/tennis_test.py | 9 ++------- Tennis/python/tennis_unittest.py | 16 +++++++++++----- 3 files changed, 16 insertions(+), 13 deletions(-) diff --git a/Tennis/python/tennis.py b/Tennis/python/tennis.py index 83a14c6d..7a4a3408 100644 --- a/Tennis/python/tennis.py +++ b/Tennis/python/tennis.py @@ -173,4 +173,6 @@ class TennisGameDefactored3: return "Deuce" s = self.p1N if self.p1 > self.p2 else self.p2N return "Advantage " + s if ((self.p1-self.p2)*(self.p1-self.p2) == 1) else "Win for " + s -TennisGame = TennisGameDefactored3 + +# NOTE: You must change this to point at the one of the three examples that you're working on! +TennisGame = TennisGameDefactored1 diff --git a/Tennis/python/tennis_test.py b/Tennis/python/tennis_test.py index 450b14b0..bfc64aba 100644 --- a/Tennis/python/tennis_test.py +++ b/Tennis/python/tennis_test.py @@ -1,16 +1,11 @@ import pytest from tennis import TennisGame -from tennis_unittest import test_cases +from tennis_unittest import test_cases, play_game class TestTennis: @pytest.mark.parametrize('p1Points p2Points score p1Name p2Name'.split(), test_cases) def test_get_score(self, p1Points, p2Points, score, p1Name, p2Name): - game = TennisGame(p1Name, p2Name) - for i in range(p1Points): - game.won_point(p1Name) - for i in range(p2Points): - game.won_point(p2Name) + game = play_game(p1Points, p2Points, p1Name, p2Name) assert score == game.score() - diff --git a/Tennis/python/tennis_unittest.py b/Tennis/python/tennis_unittest.py index f2eca430..3b181df5 100644 --- a/Tennis/python/tennis_unittest.py +++ b/Tennis/python/tennis_unittest.py @@ -1,4 +1,5 @@ import unittest +from itertools import izip_longest from tennis import TennisGame @@ -49,16 +50,21 @@ test_cases = [ ] +def play_game(p1Points, p2Points, p1Name, p2Name): + game = TennisGame(p1Name, p2Name) + for p1, p2 in izip_longest(range(p1Points), range(p2Points)): + if p1 is not None: + game.won_point(p1Name) + if p2 is not None: + game.won_point(p2Name) + return game + class TestTennis(unittest.TestCase): def test_Score(self): for testcase in test_cases: (p1Points, p2Points, score, p1Name, p2Name) = testcase - game = TennisGame(p1Name, p2Name) - for i in range(p1Points): - game.won_point(p1Name) - for i in range(p2Points): - game.won_point(p2Name) + game = play_game(p1Points, p2Points, p1Name, p2Name) self.assertEquals(score, game.score()) if __name__ == "__main__": From 1cf0963de5fe3ca6da6dd00a6eb72cffb6a85bf6 Mon Sep 17 00:00:00 2001 From: emilybache Date: Wed, 21 Nov 2012 10:59:47 +0100 Subject: [PATCH 050/634] made the test code more realistic - have each player score a point in turn instead of all at once. --- Tennis/java/defactored1/TennisTest.java | 11 +++++++---- Tennis/java/defactored2/TennisTest.java | 11 +++++++---- Tennis/java/defactored3/TennisTest.java | 11 +++++++---- Tennis/java/factored1/TennisTest.java | 11 +++++++---- 4 files changed, 28 insertions(+), 16 deletions(-) diff --git a/Tennis/java/defactored1/TennisTest.java b/Tennis/java/defactored1/TennisTest.java index 48c247bc..5fb105ea 100644 --- a/Tennis/java/defactored1/TennisTest.java +++ b/Tennis/java/defactored1/TennisTest.java @@ -71,10 +71,13 @@ public class TennisTest { @Test public void checkAllScores() { TennisGame game = new TennisGame("player1", "player2"); - for (int i = 0; i < this.player1Score; i++) - game.wonPoint("player1"); - for (int i = 0; i < this.player2Score; i++) - game.wonPoint("player2"); + int highestScore = Math.max(this.player1Score, this.player2Score); + for (int i = 0; i < highestScore; i++) { + if (i < this.player1Score) + game.wonPoint("player1"); + if (i < this.player2Score) + game.wonPoint("player2"); + } assertEquals(this.expectedScore, game.getScore()); } diff --git a/Tennis/java/defactored2/TennisTest.java b/Tennis/java/defactored2/TennisTest.java index 92807971..bbdd4a5e 100644 --- a/Tennis/java/defactored2/TennisTest.java +++ b/Tennis/java/defactored2/TennisTest.java @@ -71,10 +71,13 @@ public class TennisTest { @Test public void checkAllScores() { TennisGame game = new TennisGame("player1", "player2"); - for (int i = 0; i < this.player1Score; i++) - game.wonPoint("player1"); - for (int i = 0; i < this.player2Score; i++) - game.wonPoint("player2"); + int highestScore = Math.max(this.player1Score, this.player2Score); + for (int i = 0; i < highestScore; i++) { + if (i < this.player1Score) + game.wonPoint("player1"); + if (i < this.player2Score) + game.wonPoint("player2"); + } assertEquals(this.expectedScore, game.getScore()); } diff --git a/Tennis/java/defactored3/TennisTest.java b/Tennis/java/defactored3/TennisTest.java index 0780329a..c6fe5abd 100644 --- a/Tennis/java/defactored3/TennisTest.java +++ b/Tennis/java/defactored3/TennisTest.java @@ -71,10 +71,13 @@ public class TennisTest { @Test public void checkAllScores() { TennisGame game = new TennisGame("player1", "player2"); - for (int i = 0; i < this.player1Score; i++) - game.wonPoint("player1"); - for (int i = 0; i < this.player2Score; i++) - game.wonPoint("player2"); + int highestScore = Math.max(this.player1Score, this.player2Score); + for (int i = 0; i < highestScore; i++) { + if (i < this.player1Score) + game.wonPoint("player1"); + if (i < this.player2Score) + game.wonPoint("player2"); + } assertEquals(this.expectedScore, game.getScore()); } diff --git a/Tennis/java/factored1/TennisTest.java b/Tennis/java/factored1/TennisTest.java index e6e8b26e..2300a761 100644 --- a/Tennis/java/factored1/TennisTest.java +++ b/Tennis/java/factored1/TennisTest.java @@ -70,10 +70,13 @@ public class TennisTest { @Test public void checkAllScores() { TennisGame game = new TennisGame("player1", "player2"); - for (int i = 0; i < this.player1Score; i++) - game.wonPoint("player1"); - for (int i = 0; i < this.player2Score; i++) - game.wonPoint("player2"); + int highestScore = Math.max(this.player1Score, this.player2Score); + for (int i = 0; i < highestScore; i++) { + if (i < this.player1Score) + game.wonPoint("player1"); + if (i < this.player2Score) + game.wonPoint("player2"); + } assertEquals(this.expectedScore, game.getScore()); } From 7333fc844e6858fc4845eac3ebca4835a30717ed Mon Sep 17 00:00:00 2001 From: emilybache Date: Wed, 21 Nov 2012 11:11:46 +0100 Subject: [PATCH 051/634] added encoding. Decided itertools.zip_longest was overkill, refactored to use simpler method. --- Tennis/python/tennis.py | 2 +- Tennis/python/tennis_test.py | 2 ++ Tennis/python/tennis_unittest.py | 9 +++++---- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/Tennis/python/tennis.py b/Tennis/python/tennis.py index 7a4a3408..d052593a 100644 --- a/Tennis/python/tennis.py +++ b/Tennis/python/tennis.py @@ -1,4 +1,4 @@ - +# -*- coding: utf-8 -*- class TennisGameDefactored1: diff --git a/Tennis/python/tennis_test.py b/Tennis/python/tennis_test.py index bfc64aba..a6392b01 100644 --- a/Tennis/python/tennis_test.py +++ b/Tennis/python/tennis_test.py @@ -1,3 +1,5 @@ +# -*- coding: utf-8 -*- + import pytest from tennis import TennisGame diff --git a/Tennis/python/tennis_unittest.py b/Tennis/python/tennis_unittest.py index 3b181df5..7beb513e 100644 --- a/Tennis/python/tennis_unittest.py +++ b/Tennis/python/tennis_unittest.py @@ -1,5 +1,6 @@ +# -*- coding: utf-8 -*- + import unittest -from itertools import izip_longest from tennis import TennisGame @@ -52,10 +53,10 @@ test_cases = [ def play_game(p1Points, p2Points, p1Name, p2Name): game = TennisGame(p1Name, p2Name) - for p1, p2 in izip_longest(range(p1Points), range(p2Points)): - if p1 is not None: + for i in range(max(p1Points, p2Points)): + if i < p1Points: game.won_point(p1Name) - if p2 is not None: + if i < p2Points: game.won_point(p2Name) return game From 9042bba0a22a9329a10523bee56c3104ff66e463 Mon Sep 17 00:00:00 2001 From: David Vrensk Date: Thu, 6 Dec 2012 15:53:43 +0100 Subject: [PATCH 052/634] Bug fix: the sample spec did not run --- GildedRose/ruby/gilded_rose_spec.rb | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/GildedRose/ruby/gilded_rose_spec.rb b/GildedRose/ruby/gilded_rose_spec.rb index a84947d1..e6dce6f4 100644 --- a/GildedRose/ruby/gilded_rose_spec.rb +++ b/GildedRose/ruby/gilded_rose_spec.rb @@ -1,13 +1,13 @@ - require File.join(File.dirname(__FILE__), 'gilded_rose') - describe GildedRose do - describe "#update_quality" do - items = [Item.new("foo", 0, 0)] - GildedRose.new().update_quality(items) - items[0].name.should == "fixme" - end + describe "#update_quality" do + it "does not change the name" do + items = [Item.new("foo", 0, 0)] + GildedRose.new().update_quality(items) + items[0].name.should == "fixme" + end + end end From 75416894524890c9405cd5679df22dcc6b59b35e Mon Sep 17 00:00:00 2001 From: David Vrensk Date: Thu, 6 Dec 2012 15:54:52 +0100 Subject: [PATCH 053/634] Style fix: ruby always uses 2-space indentation --- GildedRose/ruby/gilded_rose.rb | 116 ++++++++++++++++----------------- 1 file changed, 57 insertions(+), 59 deletions(-) diff --git a/GildedRose/ruby/gilded_rose.rb b/GildedRose/ruby/gilded_rose.rb index 43b43a10..1107408a 100755 --- a/GildedRose/ruby/gilded_rose.rb +++ b/GildedRose/ruby/gilded_rose.rb @@ -1,67 +1,65 @@ class GildedRose - def update_quality(items) - items.each do |item| - if item.name != "Aged Brie" and item.name != "Backstage passes to a TAFKAL80ETC concert" - if item.quality > 0 - if item.name != "Sulfuras, Hand of Ragnaros" - item.quality = item.quality - 1 - end - end - else - if item.quality < 50 - item.quality = item.quality + 1 - if item.name == "Backstage passes to a TAFKAL80ETC concert" - if item.sell_in < 11 - if item.quality < 50 - item.quality = item.quality + 1 - end - end - if item.sell_in < 6 - if item.quality < 50 - item.quality = item.quality + 1 - end - end - end - end - end - if item.name != "Sulfuras, Hand of Ragnaros" - item.sell_in = item.sell_in - 1 - end - if item.sell_in < 0 - if item.name != "Aged Brie" - if item.name != "Backstage passes to a TAFKAL80ETC concert" - if item.quality > 0 - if item.name != "Sulfuras, Hand of Ragnaros" - item.quality = item.quality - 1 - end - end - else - item.quality = item.quality - item.quality - end - else - if item.quality < 50 - item.quality = item.quality + 1 - end - end - end + def update_quality(items) + items.each do |item| + if item.name != "Aged Brie" and item.name != "Backstage passes to a TAFKAL80ETC concert" + if item.quality > 0 + if item.name != "Sulfuras, Hand of Ragnaros" + item.quality = item.quality - 1 + end end - items + else + if item.quality < 50 + item.quality = item.quality + 1 + if item.name == "Backstage passes to a TAFKAL80ETC concert" + if item.sell_in < 11 + if item.quality < 50 + item.quality = item.quality + 1 + end + end + if item.sell_in < 6 + if item.quality < 50 + item.quality = item.quality + 1 + end + end + end + end + end + if item.name != "Sulfuras, Hand of Ragnaros" + item.sell_in = item.sell_in - 1 + end + if item.sell_in < 0 + if item.name != "Aged Brie" + if item.name != "Backstage passes to a TAFKAL80ETC concert" + if item.quality > 0 + if item.name != "Sulfuras, Hand of Ragnaros" + item.quality = item.quality - 1 + end + end + else + item.quality = item.quality - item.quality + end + else + if item.quality < 50 + item.quality = item.quality + 1 + end + end + end end + items + end end class Item - attr_accessor :name, :sell_in, :quality - - def initialize(name, sell_in, quality) - @name = name - @sell_in = sell_in - @quality = quality - end - - def to_s() - "#{@name}, #{@sell_in}, #{@quality}" - end -end - + attr_accessor :name, :sell_in, :quality + def initialize(name, sell_in, quality) + @name = name + @sell_in = sell_in + @quality = quality + end + + def to_s() + "#{@name}, #{@sell_in}, #{@quality}" + end +end From 1b30d88dbd749cc87a84064e7fd576a21da99d87 Mon Sep 17 00:00:00 2001 From: emilybache Date: Fri, 7 Dec 2012 19:10:05 +0100 Subject: [PATCH 054/634] First attempt at a ruby version of this kata --- Tennis/ruby/tennis.rb | 223 +++++++++++++++++++++++++++++++++++++ Tennis/ruby/tennis_test.rb | 73 ++++++++++++ 2 files changed, 296 insertions(+) create mode 100644 Tennis/ruby/tennis.rb create mode 100644 Tennis/ruby/tennis_test.rb diff --git a/Tennis/ruby/tennis.rb b/Tennis/ruby/tennis.rb new file mode 100644 index 00000000..a509b84e --- /dev/null +++ b/Tennis/ruby/tennis.rb @@ -0,0 +1,223 @@ + +class TennisGameDefactored1 + + def initialize(player1Name, player2Name) + @player1Name = player1Name + @player2Name = player2Name + @p1points = 0 + @p2points = 0 + end + + def won_point(playerName) + if playerName == @player1Name + @p1points += 1 + else + @p2points += 1 + end + end + + def score + result = "" + tempScore=0 + if (@p1points==@p2points) + result = { + 0 => "Love-All", + 1 => "Fifteen-All", + 2 => "Thirty-All", + 3 => "Forty-All", + }.fetch(@p1points, "Deuce") + elsif (@p1points>=4 or @p2points>=4) + minusResult = @p1points-@p2points + if (minusResult==1) + result ="Advantage " + @player1Name + elsif (minusResult ==-1) + result ="Advantage " + @player2Name + elsif (minusResult>=2) + result = "Win for " + @player1Name + else + result ="Win for " + @player2Name + end + else + (1...3).each do |i| + if (i==1) + tempScore = @p1points + else + result+="-" + tempScore = @p2points + end + result += { + 0 => "Love", + 1 => "Fifteen", + 2 => "Thirty", + 3 => "Forty", + }[tempScore] + end + end + result + end +end + +class TennisGameDefactored2 + def initialize(player1Name, player2Name) + @player1Name = player1Name + @player2Name = player2Name + @p1points = 0 + @p2points = 0 + end + + def won_point(playerName) + if playerName == @player1Name + p1Score() + else + p2Score() + end + end + + def score + result = "" + if (@p1points == @p2points and @p1points < 4) + if (@p1points==0) + result = "Love" + end + if (@p1points==1) + result = "Fifteen" + end + if (@p1points==2) + result = "Thirty" + end + if (@p1points==3) + result = "Forty" + end + result += "-All" + end + if (@p1points==@p2points and @p1points>3) + result = "Deuce" + end + + p1res = "" + p2res = "" + if (@p1points > 0 and @p2points==0) + if (@p1points==1) + p1res = "Fifteen" + end + if (@p1points==2) + p1res = "Thirty" + end + if (@p1points==3) + p1res = "Forty" + end + p2res = "Love" + result = p1res + "-" + p2res + end + if (@p2points > 0 and @p1points==0) + if (@p2points==1) + p2res = "Fifteen" + end + if (@p2points==2) + p2res = "Thirty" + end + if (@p2points==3) + p2res = "Forty" + end + + p1res = "Love" + result = p1res + "-" + p2res + end + + if (@p1points>@p2points and @p1points < 4) + if (@p1points==2) + p1res="Thirty" + end + if (@p1points==3) + p1res="Forty" + end + if (@p2points==1) + p2res="Fifteen" + end + if (@p2points==2) + p2res="Thirty" + end + result = p1res + "-" + p2res + end + if (@p2points>@p1points and @p2points < 4) + if (@p2points==2) + p2res="Thirty" + end + if (@p2points==3) + p2res="Forty" + end + if (@p1points==1) + p1res="Fifteen" + end + if (@p1points==2) + p1res="Thirty" + end + result = p1res + "-" + p2res + end + if (@p1points > @p2points and @p2points >= 3) + result = "Advantage " + @player1Name + end + if (@p2points > @p1points and @p1points >= 3) + result = "Advantage " + @player2Name + end + if (@p1points>=4 and @p2points>=0 and (@p1points-@p2points)>=2) + result = "Win for " + @player1Name + end + if (@p2points>=4 and @p1points>=0 and (@p2points-@p1points)>=2) + result = "Win for " + @player2Name + end + result + end + + def setp1Score(number) + (0..number).each do |i| + p1Score() + end + end + + def setp2Score(number) + (0..number).each do |i| + p2Score() + end + end + + def p1Score + @p1points +=1 + end + + def p2Score + @p2points +=1 + end +end + +class TennisGameDefactored3 + def initialize(player1Name, player2Name) + @p1N = player1Name + @p2N = player2Name + @p1 = 0 + @p2 = 0 + end + + def won_point(n) + if n == @p1N + @p1 += 1 + else + @p2 += 1 + end + end + + def score + if (@p1 < 4 and @p2 < 4) + p = ["Love", "Fifteen", "Thirty", "Forty"] + s = p[@p1] + @p1 == @p2 ? s + "-All" : s + "-" + p[@p2] + else + if (@p1 == @p2) + "Deuce" + else + s = @p1 > @p2 ? @p1N : @p2N + (@p1-@p2)*(@p1-@p2) == 1 ? "Advantage " + s : "Win for " + s + end + end + end +end diff --git a/Tennis/ruby/tennis_test.rb b/Tennis/ruby/tennis_test.rb new file mode 100644 index 00000000..d2b6fcf4 --- /dev/null +++ b/Tennis/ruby/tennis_test.rb @@ -0,0 +1,73 @@ + +require_relative("tennis") +require 'test/unit' + +TEST_CASES = [ + [0, 0, "Love-All", 'player1', 'player2'], + [1, 1, "Fifteen-All", 'player1', 'player2'], + [2, 2, "Thirty-All", 'player1', 'player2'], + [3, 3, "Forty-All", 'player1', 'player2'], + [4, 4, "Deuce", 'player1', 'player2'], + + [1, 0, "Fifteen-Love", 'player1', 'player2'], + [0, 1, "Love-Fifteen", 'player1', 'player2'], + [2, 0, "Thirty-Love", 'player1', 'player2'], + [0, 2, "Love-Thirty", 'player1', 'player2'], + [3, 0, "Forty-Love", 'player1', 'player2'], + [0, 3, "Love-Forty", 'player1', 'player2'], + [4, 0, "Win for player1", 'player1', 'player2'], + [0, 4, "Win for player2", 'player1', 'player2'], + + [2, 1, "Thirty-Fifteen", 'player1', 'player2'], + [1, 2, "Fifteen-Thirty", 'player1', 'player2'], + [3, 1, "Forty-Fifteen", 'player1', 'player2'], + [1, 3, "Fifteen-Forty", 'player1', 'player2'], + [4, 1, "Win for player1", 'player1', 'player2'], + [1, 4, "Win for player2", 'player1', 'player2'], + + [3, 2, "Forty-Thirty", 'player1', 'player2'], + [2, 3, "Thirty-Forty", 'player1', 'player2'], + [4, 2, "Win for player1", 'player1', 'player2'], + [2, 4, "Win for player2", 'player1', 'player2'], + + [4, 3, "Advantage player1", 'player1', 'player2'], + [3, 4, "Advantage player2", 'player1', 'player2'], + [5, 4, "Advantage player1", 'player1', 'player2'], + [4, 5, "Advantage player2", 'player1', 'player2'], + [15, 14, "Advantage player1", 'player1', 'player2'], + [14, 15, "Advantage player2", 'player1', 'player2'], + + [6, 4, 'Win for player1', 'player1', 'player2'], + [4, 6, 'Win for player2', 'player1', 'player2'], + [16, 14, 'Win for player1', 'player1', 'player2'], + [14, 16, 'Win for player2', 'player1', 'player2'], + + [6, 4, 'Win for One', 'One', 'player2'], + [4, 6, 'Win for Two', 'player1', 'Two'], + [6, 5, 'Advantage One', 'One', 'player2'], + [5, 6, 'Advantage Two', 'player1', 'Two'] +] + +class TestTennis < Test::Unit::TestCase + def play_game(p1Points, p2Points, p1Name, p2Name) + # NOTE: Change this to the class you want to work on! + game = TennisGameDefactored1.new(p1Name, p2Name) + (0..[p1Points, p2Points].max).each do |i| + if i < p1Points + game.won_point(p1Name) + end + if i < p2Points + game.won_point(p2Name) + end + end + game + end + + def test_Score + TEST_CASES.each do |testcase| + (p1Points, p2Points, score, p1Name, p2Name) = testcase + game = play_game(p1Points, p2Points, p1Name, p2Name) + assert_equal(score, game.score()) + end + end +end \ No newline at end of file From 8e3bd6076f610c2aeb86822058f1fbe926c43dff Mon Sep 17 00:00:00 2001 From: emilybache Date: Fri, 7 Dec 2012 21:10:59 +0100 Subject: [PATCH 055/634] converted tabs to spaces --- Tennis/java/defactored1/TennisGame.java | 146 +++++++------- Tennis/java/defactored1/TennisTest.java | 150 +++++++-------- Tennis/java/defactored2/TennisGame.java | 244 ++++++++++++------------ Tennis/java/defactored3/TennisGame.java | 60 +++--- 4 files changed, 300 insertions(+), 300 deletions(-) diff --git a/Tennis/java/defactored1/TennisGame.java b/Tennis/java/defactored1/TennisGame.java index fee379aa..cadb6fb5 100644 --- a/Tennis/java/defactored1/TennisGame.java +++ b/Tennis/java/defactored1/TennisGame.java @@ -1,80 +1,80 @@ package defactored1; public class TennisGame { - - private int m_score1 = 0; - private int m_score2 = 0; - private String player1Name; - private String player2Name; + + private int m_score1 = 0; + private int m_score2 = 0; + private String player1Name; + private String player2Name; - public TennisGame(String player1Name, String player2Name) { - this.player1Name = player1Name; - this.player2Name = player2Name; - } + public TennisGame(String player1Name, String player2Name) { + this.player1Name = player1Name; + this.player2Name = player2Name; + } - public void wonPoint(String playerName) { - if (playerName == "player1") - m_score1 += 1; - else - m_score2 += 1; - } + public void wonPoint(String playerName) { + if (playerName == "player1") + m_score1 += 1; + else + m_score2 += 1; + } - public String getScore() { - String score = ""; - int tempScore=0; - if (m_score1==m_score2) - { - switch (m_score1) - { - case 0: - score = "Love-All"; - break; - case 1: - score = "Fifteen-All"; - break; - case 2: - score = "Thirty-All"; - break; - case 3: - score = "Forty-All"; - break; - default: - score = "Deuce"; - break; - - } - } - else if (m_score1>=4 || m_score2>=4) - { - int minusResult = m_score1-m_score2; - if (minusResult==1) score ="Advantage player1"; - else if (minusResult ==-1) score ="Advantage player2"; - else if (minusResult>=2) score = "Win for player1"; - else score ="Win for player2"; - } - else - { - for (int i=1; i<3; i++) - { - if (i==1) tempScore = m_score1; - else { score+="-"; tempScore = m_score2;} - switch(tempScore) - { - case 0: - score+="Love"; - break; - case 1: - score+="Fifteen"; - break; - case 2: - score+="Thirty"; - break; - case 3: - score+="Forty"; - break; - } - } - } - return score; - } + public String getScore() { + String score = ""; + int tempScore=0; + if (m_score1==m_score2) + { + switch (m_score1) + { + case 0: + score = "Love-All"; + break; + case 1: + score = "Fifteen-All"; + break; + case 2: + score = "Thirty-All"; + break; + case 3: + score = "Forty-All"; + break; + default: + score = "Deuce"; + break; + + } + } + else if (m_score1>=4 || m_score2>=4) + { + int minusResult = m_score1-m_score2; + if (minusResult==1) score ="Advantage player1"; + else if (minusResult ==-1) score ="Advantage player2"; + else if (minusResult>=2) score = "Win for player1"; + else score ="Win for player2"; + } + else + { + for (int i=1; i<3; i++) + { + if (i==1) tempScore = m_score1; + else { score+="-"; tempScore = m_score2;} + switch(tempScore) + { + case 0: + score+="Love"; + break; + case 1: + score+="Fifteen"; + break; + case 2: + score+="Thirty"; + break; + case 3: + score+="Forty"; + break; + } + } + } + return score; + } } diff --git a/Tennis/java/defactored1/TennisTest.java b/Tennis/java/defactored1/TennisTest.java index 5fb105ea..a90fd303 100644 --- a/Tennis/java/defactored1/TennisTest.java +++ b/Tennis/java/defactored1/TennisTest.java @@ -14,84 +14,84 @@ import org.junit.runners.Parameterized.Parameters; @RunWith(Parameterized.class) public class TennisTest { - private int player1Score; - private int player2Score; - private String expectedScore; + private int player1Score; + private int player2Score; + private String expectedScore; - public TennisTest(int player1Score, int player2Score, String expectedScore) { - this.player1Score = player1Score; - this.player2Score = player2Score; - this.expectedScore = expectedScore; - } - - @Parameters - public static Collection getAllScores() { - return Arrays.asList(new Object[][] { - { 0, 0, "Love-All" }, - { 1, 1, "Fifteen-All" }, - { 2, 2, "Thirty-All"}, - { 3, 3, "Forty-All"}, - { 4, 4, "Deuce"}, - - { 1, 0, "Fifteen-Love"}, - { 0, 1, "Love-Fifteen"}, - { 2, 0, "Thirty-Love"}, - { 0, 2, "Love-Thirty"}, - { 3, 0, "Forty-Love"}, - { 0, 3, "Love-Forty"}, - { 4, 0, "Win for player1"}, - { 0, 4, "Win for player2"}, - - { 2, 1, "Thirty-Fifteen"}, - { 1, 2, "Fifteen-Thirty"}, - { 3, 1, "Forty-Fifteen"}, - { 1, 3, "Fifteen-Forty"}, - { 4, 1, "Win for player1"}, - { 1, 4, "Win for player2"}, + public TennisTest(int player1Score, int player2Score, String expectedScore) { + this.player1Score = player1Score; + this.player2Score = player2Score; + this.expectedScore = expectedScore; + } + + @Parameters + public static Collection getAllScores() { + return Arrays.asList(new Object[][] { + { 0, 0, "Love-All" }, + { 1, 1, "Fifteen-All" }, + { 2, 2, "Thirty-All"}, + { 3, 3, "Forty-All"}, + { 4, 4, "Deuce"}, + + { 1, 0, "Fifteen-Love"}, + { 0, 1, "Love-Fifteen"}, + { 2, 0, "Thirty-Love"}, + { 0, 2, "Love-Thirty"}, + { 3, 0, "Forty-Love"}, + { 0, 3, "Love-Forty"}, + { 4, 0, "Win for player1"}, + { 0, 4, "Win for player2"}, + + { 2, 1, "Thirty-Fifteen"}, + { 1, 2, "Fifteen-Thirty"}, + { 3, 1, "Forty-Fifteen"}, + { 1, 3, "Fifteen-Forty"}, + { 4, 1, "Win for player1"}, + { 1, 4, "Win for player2"}, - { 3, 2, "Forty-Thirty"}, - { 2, 3, "Thirty-Forty"}, - { 4, 2, "Win for player1"}, - { 2, 4, "Win for player2"}, - - { 4, 3, "Advantage player1"}, - { 3, 4, "Advantage player2"}, - { 5, 4, "Advantage player1"}, - { 4, 5, "Advantage player2"}, - { 15, 14, "Advantage player1"}, - { 14, 15, "Advantage player2"}, + { 3, 2, "Forty-Thirty"}, + { 2, 3, "Thirty-Forty"}, + { 4, 2, "Win for player1"}, + { 2, 4, "Win for player2"}, + + { 4, 3, "Advantage player1"}, + { 3, 4, "Advantage player2"}, + { 5, 4, "Advantage player1"}, + { 4, 5, "Advantage player2"}, + { 15, 14, "Advantage player1"}, + { 14, 15, "Advantage player2"}, - { 6, 4, "Win for player1"}, - { 4, 6, "Win for player2"}, - { 16, 14, "Win for player1"}, - { 14, 16, "Win for player2"}, - }); - } + { 6, 4, "Win for player1"}, + { 4, 6, "Win for player2"}, + { 16, 14, "Win for player1"}, + { 14, 16, "Win for player2"}, + }); + } - @Test - public void checkAllScores() { - TennisGame game = new TennisGame("player1", "player2"); - int highestScore = Math.max(this.player1Score, this.player2Score); - for (int i = 0; i < highestScore; i++) { - if (i < this.player1Score) - game.wonPoint("player1"); - if (i < this.player2Score) - game.wonPoint("player2"); - } - assertEquals(this.expectedScore, game.getScore()); - } - - @Test - public void realisticGame() { - TennisGame game = new TennisGame("player1", "player2"); - String[] points = {"player1", "player1", "player2", "player2", "player1", "player1"}; - String[] expected_scores = {"Fifteen-Love", "Thirty-Love", "Thirty-Fifteen", "Thirty-All", "Forty-Thirty", "Win for player1"}; - for (int i = 0; i < 6; i++) { - game.wonPoint(points[i]); - assertEquals(expected_scores[i], game.getScore()); - } - - - } + @Test + public void checkAllScores() { + TennisGame game = new TennisGame("player1", "player2"); + int highestScore = Math.max(this.player1Score, this.player2Score); + for (int i = 0; i < highestScore; i++) { + if (i < this.player1Score) + game.wonPoint("player1"); + if (i < this.player2Score) + game.wonPoint("player2"); + } + assertEquals(this.expectedScore, game.getScore()); + } + + @Test + public void realisticGame() { + TennisGame game = new TennisGame("player1", "player2"); + String[] points = {"player1", "player1", "player2", "player2", "player1", "player1"}; + String[] expected_scores = {"Fifteen-Love", "Thirty-Love", "Thirty-Fifteen", "Thirty-All", "Forty-Thirty", "Win for player1"}; + for (int i = 0; i < 6; i++) { + game.wonPoint(points[i]); + assertEquals(expected_scores[i], game.getScore()); + } + + + } } diff --git a/Tennis/java/defactored2/TennisGame.java b/Tennis/java/defactored2/TennisGame.java index 6d1ecd78..a7b913a4 100644 --- a/Tennis/java/defactored2/TennisGame.java +++ b/Tennis/java/defactored2/TennisGame.java @@ -2,137 +2,137 @@ package defactored2; public class TennisGame { - public int P1point = 0; - public int P2point = 0; - - public String P1res = ""; - public String P2res = ""; - private String player1Name; - private String player2Name; + public int P1point = 0; + public int P2point = 0; + + public String P1res = ""; + public String P2res = ""; + private String player1Name; + private String player2Name; - public TennisGame(String player1Name, String player2Name) { - this.player1Name = player1Name; - this.player2Name = player2Name; - } + public TennisGame(String player1Name, String player2Name) { + this.player1Name = player1Name; + this.player2Name = player2Name; + } public String getScore(){ - String score = ""; - if (P1point == P2point && P1point < 4) - { - if (P1point==0) - score = "Love"; - if (P1point==1) - score = "Fifteen"; - if (P1point==2) - score = "Thirty"; - if (P1point==3) - score = "Forty"; - score += "-All"; - } - if (P1point==P2point && P1point>3) - score = "Deuce"; - - if (P1point > 0 && P2point==0) - { - if (P1point==1) - P1res = "Fifteen"; - if (P1point==2) - P1res = "Thirty"; - if (P1point==3) - P1res = "Forty"; - - P2res = "Love"; - score = P1res + "-" + P2res; - } - if (P2point > 0 && P1point==0) - { - if (P2point==1) - P2res = "Fifteen"; - if (P2point==2) - P2res = "Thirty"; - if (P2point==3) - P2res = "Forty"; - - P1res = "Love"; - score = P1res + "-" + P2res; - } - - if (P1point>P2point && P1point < 4) - { - if (P1point==2) - P1res="Thirty"; - if (P1point==3) - P1res="Forty"; - if (P2point==1) - P2res="Fifteen"; - if (P2point==2) - P2res="Thirty"; - score = P1res + "-" + P2res; - } - if (P2point>P1point && P2point < 4) - { - if (P2point==2) - P2res="Thirty"; - if (P2point==3) - P2res="Forty"; - if (P1point==1) - P1res="Fifteen"; - if (P1point==2) - P1res="Thirty"; - score = P1res + "-" + P2res; - } - - if (P1point > P2point && P2point >= 3) - { - score = "Advantage player1"; - } - - if (P2point > P1point && P1point >= 3) - { - score = "Advantage player2"; - } - - if (P1point>=4 && P2point>=0 && (P1point-P2point)>=2) - { - score = "Win for player1"; - } - if (P2point>=4 && P1point>=0 && (P2point-P1point)>=2) - { - score = "Win for player2"; - } - return score; - } - - public void SetP1Score(int number){ + String score = ""; + if (P1point == P2point && P1point < 4) + { + if (P1point==0) + score = "Love"; + if (P1point==1) + score = "Fifteen"; + if (P1point==2) + score = "Thirty"; + if (P1point==3) + score = "Forty"; + score += "-All"; + } + if (P1point==P2point && P1point>3) + score = "Deuce"; - for (int i = 0; i < number; i++) - { - P1Score(); - } - - } - - public void SetP2Score(int number){ + if (P1point > 0 && P2point==0) + { + if (P1point==1) + P1res = "Fifteen"; + if (P1point==2) + P1res = "Thirty"; + if (P1point==3) + P1res = "Forty"; + + P2res = "Love"; + score = P1res + "-" + P2res; + } + if (P2point > 0 && P1point==0) + { + if (P2point==1) + P2res = "Fifteen"; + if (P2point==2) + P2res = "Thirty"; + if (P2point==3) + P2res = "Forty"; + + P1res = "Love"; + score = P1res + "-" + P2res; + } - for (int i = 0; i < number; i++) - { - P2Score(); - } - + if (P1point>P2point && P1point < 4) + { + if (P1point==2) + P1res="Thirty"; + if (P1point==3) + P1res="Forty"; + if (P2point==1) + P2res="Fifteen"; + if (P2point==2) + P2res="Thirty"; + score = P1res + "-" + P2res; + } + if (P2point>P1point && P2point < 4) + { + if (P2point==2) + P2res="Thirty"; + if (P2point==3) + P2res="Forty"; + if (P1point==1) + P1res="Fifteen"; + if (P1point==2) + P1res="Thirty"; + score = P1res + "-" + P2res; + } + + if (P1point > P2point && P2point >= 3) + { + score = "Advantage player1"; + } + + if (P2point > P1point && P1point >= 3) + { + score = "Advantage player2"; + } + + if (P1point>=4 && P2point>=0 && (P1point-P2point)>=2) + { + score = "Win for player1"; + } + if (P2point>=4 && P1point>=0 && (P2point-P1point)>=2) + { + score = "Win for player2"; + } + return score; } - - public void P1Score(){ + + public void SetP1Score(int number){ + + for (int i = 0; i < number; i++) + { + P1Score(); + } + + } + + public void SetP2Score(int number){ + + for (int i = 0; i < number; i++) + { + P2Score(); + } + + } + + public void P1Score(){ P1point++; } - - public void P2Score(){ + + public void P2Score(){ P2point++; } - public void wonPoint(String player) { - if (player == "player1") - P1Score(); - else - P2Score(); - } + public void wonPoint(String player) { + if (player == "player1") + P1Score(); + else + P2Score(); + } } \ No newline at end of file diff --git a/Tennis/java/defactored3/TennisGame.java b/Tennis/java/defactored3/TennisGame.java index e3fcf7bd..6c121586 100644 --- a/Tennis/java/defactored3/TennisGame.java +++ b/Tennis/java/defactored3/TennisGame.java @@ -1,37 +1,37 @@ package defactored3; public class TennisGame { - - private int p2; - private int p1; - private String p1N; - private String p2N; + + private int p2; + private int p1; + private String p1N; + private String p2N; - public TennisGame(String p1N, String p2N) { - this.p1N = p1N; - this.p2N = p2N; - } + public TennisGame(String p1N, String p2N) { + this.p1N = p1N; + this.p2N = p2N; + } - public String getScore() { - String s; - if (p1 < 4 && p2 < 4) { - String[] p = new String[]{"Love", "Fifteen", "Thirty", "Forty"}; - s = p[p1]; - return (p1 == p2) ? s + "-All" : s + "-" + p[p2]; - } else { - if (p1 == p2) - return "Deuce"; - s = p1 > p2 ? p1N : p2N; - return ((p1-p2)*(p1-p2) == 1) ? "Advantage " + s : "Win for " + s; - } - } - - public void wonPoint(String playerName) { - if (playerName == "player1") - this.p1 += 1; - else - this.p2 += 1; - - } + public String getScore() { + String s; + if (p1 < 4 && p2 < 4) { + String[] p = new String[]{"Love", "Fifteen", "Thirty", "Forty"}; + s = p[p1]; + return (p1 == p2) ? s + "-All" : s + "-" + p[p2]; + } else { + if (p1 == p2) + return "Deuce"; + s = p1 > p2 ? p1N : p2N; + return ((p1-p2)*(p1-p2) == 1) ? "Advantage " + s : "Win for " + s; + } + } + + public void wonPoint(String playerName) { + if (playerName == "player1") + this.p1 += 1; + else + this.p2 += 1; + + } } From 980953d974883e4b6af523d06221f30fc2354c41 Mon Sep 17 00:00:00 2001 From: emilybache Date: Fri, 7 Dec 2012 21:12:59 +0100 Subject: [PATCH 056/634] Added links to some cyber-dojo instances --- Tennis/README.md | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/Tennis/README.md b/Tennis/README.md index 76aed18c..3b1b52e0 100644 --- a/Tennis/README.md +++ b/Tennis/README.md @@ -6,7 +6,7 @@ There are three versions of this refactoring kata, each with their own design sm Tennis has a rather quirky scoring system, and to newcomers it can be a little difficult to keep track of. The tennis society has contracted you to build a scoreboard to display the current score during tennis games. -Your task is to write a “TennisGame” class containing the logic which outputs the correct score as a string for display on the scoreboard. When a player scores a point, it triggers a method to be called on your class letting you know who scored the point. Later, you will get a call “currentScore()” from the scoreboard asking what it should display. This method should return a string with the current score. +Your task is to write a “TennisGame” class containing the logic which outputs the correct score as a string for display on the scoreboard. When a player scores a point, it triggers a method to be called on your class letting you know who scored the point. Later, you will get a call “score()” from the scoreboard asking what it should display. This method should return a string with the current score. You can read more about Tennis scores [here](http://en.wikipedia.org/wiki/Tennis#Scoring) which is summarized below: @@ -16,3 +16,12 @@ You can read more about Tennis scores [here](http://en.wikipedia.org/wiki/Tennis 4. If at least three points have been scored by each side and a player has one more point than his opponent, the score of the game is "advantage" for the player in the lead. You need only report the score for the current game. Sets and Matches are out of scope. + +## Get going quickly with Cyber-dojo + +I have set up some cyber-dojos ready to fork with the starting code. Do __not__ go in and start coding in these cyber-dojo instances directly! Rather, in the "review" dashboard, click on the last traffic light icon to see the code. __Do not__ start coding yet! Click on the fork symbol, to start a __new__ cyber dojo to use. You can then have several pairs enter your new dojo and start coding, all with the same starting code. + +- [Python](http://www.cyber-dojo.com/dashboard/show/FFEB8EE18C) +- [Ruby](http://www.cyber-dojo.com/dashboard/show/9197D6B12C) +- [Java](http://www.cyber-dojo.com/dashboard/show/B22DCD17C3) +- I havn't done C++ yet, since cyber-dojo is using a different test framework. \ No newline at end of file From 690a14e48249ee579810fd3b71d6db24f3b067d7 Mon Sep 17 00:00:00 2001 From: emilybache Date: Mon, 10 Dec 2012 13:48:13 +0100 Subject: [PATCH 057/634] improved the cyber-dojo links --- Tennis/README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Tennis/README.md b/Tennis/README.md index 3b1b52e0..7cc82223 100644 --- a/Tennis/README.md +++ b/Tennis/README.md @@ -19,9 +19,9 @@ You need only report the score for the current game. Sets and Matches are out of ## Get going quickly with Cyber-dojo -I have set up some cyber-dojos ready to fork with the starting code. Do __not__ go in and start coding in these cyber-dojo instances directly! Rather, in the "review" dashboard, click on the last traffic light icon to see the code. __Do not__ start coding yet! Click on the fork symbol, to start a __new__ cyber dojo to use. You can then have several pairs enter your new dojo and start coding, all with the same starting code. +I have set up some cyber-dojos with the starting code. This should make it very quick to get started with the kata. The other advantage of cyber-dojo is that if you make a refactoring mistake, it's very easy to revert the code to the last green bar, and practice the refactoring again. Just click on the most recent green traffic light shown in the list above the code. -- [Python](http://www.cyber-dojo.com/dashboard/show/FFEB8EE18C) -- [Ruby](http://www.cyber-dojo.com/dashboard/show/9197D6B12C) -- [Java](http://www.cyber-dojo.com/dashboard/show/B22DCD17C3) +- [Python](http://cyber-dojo.com/forker/fork/FFEB8EE18C?avatar=cheetah&tag=3) +- [Ruby](http://cyber-dojo.com/forker/fork/9197D6B12C?avatar=cheetah&tag=3) +- [Java](http://cyber-dojo.com/forker/fork/B22DCD17C3?avatar=buffalo&tag=11) - I havn't done C++ yet, since cyber-dojo is using a different test framework. \ No newline at end of file From 91630a3a3482e211252efe2b784442126fb92463 Mon Sep 17 00:00:00 2001 From: emilybache Date: Mon, 10 Dec 2012 14:35:09 +0100 Subject: [PATCH 058/634] convert tabs to spaces --- Tennis/cpp/defactored1/Tennis.cc | 114 ++++++++++---------- Tennis/cpp/defactored2/Tennis.cc | 172 +++++++++++++++---------------- Tennis/cpp/defactored3/Tennis.cc | 22 ++-- 3 files changed, 154 insertions(+), 154 deletions(-) diff --git a/Tennis/cpp/defactored1/Tennis.cc b/Tennis/cpp/defactored1/Tennis.cc index eeac646d..0f340f5f 100644 --- a/Tennis/cpp/defactored1/Tennis.cc +++ b/Tennis/cpp/defactored1/Tennis.cc @@ -1,63 +1,63 @@ #include const std::string tennis_score(int p1Score, int p2Score) { - std::string score = ""; - int tempScore=0; - if (p1Score==p2Score) - { - switch (p1Score) - { - case 0: - score = "Love-All"; - break; - case 1: - score = "Fifteen-All"; - break; - case 2: - score = "Thirty-All"; - break; - case 3: - score = "Deuce"; - break; - default: - score = "Deuce"; - break; - - } - } - else if (p1Score>=4 || p2Score>=4) - { - int minusResult = p1Score-p2Score; - if (minusResult==1) score ="Advantage player1"; - else if (minusResult ==-1) score ="Advantage player2"; - else if (minusResult>=2) score = "Win for player1"; - else score ="Win for player2"; - } - else - { - for (int i=1; i<3; i++) - { - if (i==1) tempScore = p1Score; - else { score+="-"; tempScore = p2Score;} - switch(tempScore) - { - case 0: - score+="Love"; - break; - case 1: - score+="Fifteen"; - break; - case 2: - score+="Thirty"; - break; - case 3: - score+="Forty"; - break; - } - } - } - return score; - + std::string score = ""; + int tempScore=0; + if (p1Score==p2Score) + { + switch (p1Score) + { + case 0: + score = "Love-All"; + break; + case 1: + score = "Fifteen-All"; + break; + case 2: + score = "Thirty-All"; + break; + case 3: + score = "Deuce"; + break; + default: + score = "Deuce"; + break; + + } + } + else if (p1Score>=4 || p2Score>=4) + { + int minusResult = p1Score-p2Score; + if (minusResult==1) score ="Advantage player1"; + else if (minusResult ==-1) score ="Advantage player2"; + else if (minusResult>=2) score = "Win for player1"; + else score ="Win for player2"; + } + else + { + for (int i=1; i<3; i++) + { + if (i==1) tempScore = p1Score; + else { score+="-"; tempScore = p2Score;} + switch(tempScore) + { + case 0: + score+="Love"; + break; + case 1: + score+="Fifteen"; + break; + case 2: + score+="Thirty"; + break; + case 3: + score+="Forty"; + break; + } + } + } + return score; + } TEST(TennisTest, LoveAll_0_0) { diff --git a/Tennis/cpp/defactored2/Tennis.cc b/Tennis/cpp/defactored2/Tennis.cc index 5f193038..8ff36536 100644 --- a/Tennis/cpp/defactored2/Tennis.cc +++ b/Tennis/cpp/defactored2/Tennis.cc @@ -1,94 +1,94 @@ #include const std::string tennis_score(int p1Score, int p2Score) { - std::string score = ""; + std::string score = ""; std::string P1res = ""; std::string P2res = ""; - if (p1Score == p2Score && p1Score < 4) - { - if (p1Score==0) - score = "Love"; - if (p1Score==1) - score = "Fifteen"; - if (p1Score==2) - score = "Thirty"; - if (p1Score==3) - score = "Forty"; - score += "-All"; - } - if (p1Score==p2Score && p1Score>2) - score = "Deuce"; - - if (p1Score > 0 && p2Score==0) - { - if (p1Score==1) - P1res = "Fifteen"; - if (p1Score==2) - P1res = "Thirty"; - if (p1Score==3) - P1res = "Forty"; - - P2res = "Love"; - score = P1res + "-" + P2res; - } - if (p2Score > 0 && p1Score==0) - { - if (p2Score==1) - P2res = "Fifteen"; - if (p2Score==2) - P2res = "Thirty"; - if (p2Score==3) - P2res = "Forty"; - - P1res = "Love"; - score = P1res + "-" + P2res; - } - - if (p1Score>p2Score && p1Score < 4) - { - if (p1Score==2) - P1res="Thirty"; - if (p1Score==3) - P1res="Forty"; - if (p2Score==1) - P2res="Fifteen"; - if (p2Score==2) - P2res="Thirty"; - score = P1res + "-" + P2res; - } - if (p2Score>p1Score && p2Score < 4) - { - if (p2Score==2) - P2res="Thirty"; - if (p2Score==3) - P2res="Forty"; - if (p1Score==1) - P1res="Fifteen"; - if (p1Score==2) - P1res="Thirty"; - score = P1res + "-" + P2res; - } - - if (p1Score > p2Score && p2Score >= 3) - { - score = "Advantage player1"; - } - - if (p2Score > p1Score && p1Score >= 3) - { - score = "Advantage player2"; - } - - if (p1Score>=4 && p2Score>=0 && (p1Score-p2Score)>=2) - { - score = "Win for player1"; - } - if (p2Score>=4 && p1Score>=0 && (p2Score-p1Score)>=2) - { - score = "Win for player2"; - } - return score; - + if (p1Score == p2Score && p1Score < 4) + { + if (p1Score==0) + score = "Love"; + if (p1Score==1) + score = "Fifteen"; + if (p1Score==2) + score = "Thirty"; + if (p1Score==3) + score = "Forty"; + score += "-All"; + } + if (p1Score==p2Score && p1Score>2) + score = "Deuce"; + + if (p1Score > 0 && p2Score==0) + { + if (p1Score==1) + P1res = "Fifteen"; + if (p1Score==2) + P1res = "Thirty"; + if (p1Score==3) + P1res = "Forty"; + + P2res = "Love"; + score = P1res + "-" + P2res; + } + if (p2Score > 0 && p1Score==0) + { + if (p2Score==1) + P2res = "Fifteen"; + if (p2Score==2) + P2res = "Thirty"; + if (p2Score==3) + P2res = "Forty"; + + P1res = "Love"; + score = P1res + "-" + P2res; + } + + if (p1Score>p2Score && p1Score < 4) + { + if (p1Score==2) + P1res="Thirty"; + if (p1Score==3) + P1res="Forty"; + if (p2Score==1) + P2res="Fifteen"; + if (p2Score==2) + P2res="Thirty"; + score = P1res + "-" + P2res; + } + if (p2Score>p1Score && p2Score < 4) + { + if (p2Score==2) + P2res="Thirty"; + if (p2Score==3) + P2res="Forty"; + if (p1Score==1) + P1res="Fifteen"; + if (p1Score==2) + P1res="Thirty"; + score = P1res + "-" + P2res; + } + + if (p1Score > p2Score && p2Score >= 3) + { + score = "Advantage player1"; + } + + if (p2Score > p1Score && p1Score >= 3) + { + score = "Advantage player2"; + } + + if (p1Score>=4 && p2Score>=0 && (p1Score-p2Score)>=2) + { + score = "Win for player1"; + } + if (p2Score>=4 && p1Score>=0 && (p2Score-p1Score)>=2) + { + score = "Win for player2"; + } + return score; + } TEST(TennisTest, LoveAll_0_0) { diff --git a/Tennis/cpp/defactored3/Tennis.cc b/Tennis/cpp/defactored3/Tennis.cc index cb2fae89..4cce3d6a 100644 --- a/Tennis/cpp/defactored3/Tennis.cc +++ b/Tennis/cpp/defactored3/Tennis.cc @@ -1,19 +1,19 @@ #include const std::string tennis_score(int p1, int p2) { - std::string s; + std::string s; std::string p1N = "player1"; std::string p2N = "player2"; - if (p1 < 4 && p2 < 4 && !(p1 == 3 && p2 == 3)) { - std::string p[4] = {"Love", "Fifteen", "Thirty", "Forty"}; - s = p[p1]; - return (p1 == p2) ? s + "-All" : s + "-" + p[p2]; - } else { - if (p1 == p2) - return "Deuce"; - s = p1 > p2 ? p1N : p2N; - return ((p1-p2)*(p1-p2) == 1) ? "Advantage " + s : "Win for " + s; - } + if (p1 < 4 && p2 < 4 && !(p1 == 3 && p2 == 3)) { + std::string p[4] = {"Love", "Fifteen", "Thirty", "Forty"}; + s = p[p1]; + return (p1 == p2) ? s + "-All" : s + "-" + p[p2]; + } else { + if (p1 == p2) + return "Deuce"; + s = p1 > p2 ? p1N : p2N; + return ((p1-p2)*(p1-p2) == 1) ? "Advantage " + s : "Win for " + s; + } } TEST(TennisTest, LoveAll_0_0) { From 810ebd7d7eb27fd838f8738da74630e63c47a4bb Mon Sep 17 00:00:00 2001 From: emilybache Date: Mon, 10 Dec 2012 14:35:53 +0100 Subject: [PATCH 059/634] generate test cases for cyber-dojo --- Tennis/cpp/generate_tests.py | 49 ++++++++++++++++++++++++++---------- 1 file changed, 36 insertions(+), 13 deletions(-) diff --git a/Tennis/cpp/generate_tests.py b/Tennis/cpp/generate_tests.py index 78dcb928..bd8975b2 100644 --- a/Tennis/cpp/generate_tests.py +++ b/Tennis/cpp/generate_tests.py @@ -1,9 +1,4 @@ -template = """\ -TEST(TennisTest, %(testcase_name)s) { - EXPECT_EQ("%(score)s", tennis_score(%(p1Points)s, %(p2Points)s)); -} -""" test_cases = [dict(p1Points=0, p2Points=0, score="Love-All"), dict(p1Points=1, p2Points=1, score="Fifteen-All"), @@ -44,12 +39,40 @@ test_cases = [dict(p1Points=0, p2Points=0, score="Love-All"), dict(p1Points=16, p2Points=14, score="Win for player1"), dict(p1Points=14, p2Points=16, score="Win for player2"), ] - -for test in test_cases: - cleaned = test["score"] - cleaned = cleaned.replace("-", "") - cleaned = cleaned.replace(" ", "") - test["cleaned"] = cleaned - test["testcase_name"] = "%(cleaned)s_%(p1Points)s_%(p2Points)s" % test + +def create_testcase_dicts(): + testcase_dicts = [] + for test in test_cases: + cleaned = test["score"] + cleaned = cleaned.replace("-", "") + cleaned = cleaned.replace(" ", "") + test["cleaned"] = cleaned + test["testcase_name"] = "%(cleaned)s_%(p1Points)s_%(p2Points)s" % test + testcase_dicts.append(test) + return testcase_dicts + +testcase_dicts = create_testcase_dicts() + +gtest_template = """\ +TEST(TennisTest, %(testcase_name)s) { + EXPECT_EQ("%(score)s", tennis_score(%(p1Points)s, %(p2Points)s)); +} +""" + +template = """\ +void test_%(testcase_name)s() +{ + assert("%(score)s" == tennis_score(%(p1Points)s, %(p2Points)s)); +} +""" +# test cases +for test in testcase_dicts: print template % test - print \ No newline at end of file + +# all_tests.cpp +for test in testcase_dicts: + print " test_%(testcase_name)s," % test + +# all_tests.hpp +for test in testcase_dicts: + print "void test_%(testcase_name)s();" % test \ No newline at end of file From b2687a855d321a00e9534488c3cce0f7247af6ac Mon Sep 17 00:00:00 2001 From: emilybache Date: Mon, 10 Dec 2012 14:43:11 +0100 Subject: [PATCH 060/634] Added the C++ version in cyberdojo --- Tennis/README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Tennis/README.md b/Tennis/README.md index 7cc82223..6c5a7745 100644 --- a/Tennis/README.md +++ b/Tennis/README.md @@ -17,11 +17,11 @@ You can read more about Tennis scores [here](http://en.wikipedia.org/wiki/Tennis You need only report the score for the current game. Sets and Matches are out of scope. -## Get going quickly with Cyber-dojo +# Get going quickly with Cyber-dojo -I have set up some cyber-dojos with the starting code. This should make it very quick to get started with the kata. The other advantage of cyber-dojo is that if you make a refactoring mistake, it's very easy to revert the code to the last green bar, and practice the refactoring again. Just click on the most recent green traffic light shown in the list above the code. +As an alternative to downloading the code, click one of the links below to create a new cyber-dojo to work in, then press "start" to get going coding. - [Python](http://cyber-dojo.com/forker/fork/FFEB8EE18C?avatar=cheetah&tag=3) - [Ruby](http://cyber-dojo.com/forker/fork/9197D6B12C?avatar=cheetah&tag=3) - [Java](http://cyber-dojo.com/forker/fork/B22DCD17C3?avatar=buffalo&tag=11) -- I havn't done C++ yet, since cyber-dojo is using a different test framework. \ No newline at end of file +- [C++](http://cyber-dojo.com/forker/fork/CD6FC41518?avatar=deer&tag=44) \ No newline at end of file From 5c951978d7e0c93c5f238101fd2567428a23d478 Mon Sep 17 00:00:00 2001 From: emilybache Date: Mon, 10 Dec 2012 14:49:09 +0100 Subject: [PATCH 061/634] removed these since I switched over to the cyber-dojo structure --- Tennis/cpp/defactored1/Makefile | 75 --------- Tennis/cpp/defactored1/README | 14 -- Tennis/cpp/defactored1/Tennis.cc | 227 ------------------------- Tennis/cpp/defactored1/run-once.sh | 4 - Tennis/cpp/defactored2/Makefile | 75 --------- Tennis/cpp/defactored2/README | 14 -- Tennis/cpp/defactored2/Tennis.cc | 258 ----------------------------- Tennis/cpp/defactored2/run-once.sh | 4 - Tennis/cpp/defactored3/Makefile | 75 --------- Tennis/cpp/defactored3/README | 14 -- Tennis/cpp/defactored3/Tennis.cc | 183 -------------------- Tennis/cpp/defactored3/run-once.sh | 4 - Tennis/cpp/starting/Makefile | 75 --------- Tennis/cpp/starting/README | 14 -- Tennis/cpp/starting/Tennis.cc | 171 ------------------- Tennis/cpp/starting/run-once.sh | 4 - 16 files changed, 1211 deletions(-) delete mode 100644 Tennis/cpp/defactored1/Makefile delete mode 100644 Tennis/cpp/defactored1/README delete mode 100644 Tennis/cpp/defactored1/Tennis.cc delete mode 100755 Tennis/cpp/defactored1/run-once.sh delete mode 100644 Tennis/cpp/defactored2/Makefile delete mode 100644 Tennis/cpp/defactored2/README delete mode 100644 Tennis/cpp/defactored2/Tennis.cc delete mode 100755 Tennis/cpp/defactored2/run-once.sh delete mode 100644 Tennis/cpp/defactored3/Makefile delete mode 100644 Tennis/cpp/defactored3/README delete mode 100644 Tennis/cpp/defactored3/Tennis.cc delete mode 100755 Tennis/cpp/defactored3/run-once.sh delete mode 100644 Tennis/cpp/starting/Makefile delete mode 100644 Tennis/cpp/starting/README delete mode 100644 Tennis/cpp/starting/Tennis.cc delete mode 100755 Tennis/cpp/starting/run-once.sh diff --git a/Tennis/cpp/defactored1/Makefile b/Tennis/cpp/defactored1/Makefile deleted file mode 100644 index a97fcd8b..00000000 --- a/Tennis/cpp/defactored1/Makefile +++ /dev/null @@ -1,75 +0,0 @@ -# Makefile for building the kata file with the Google Testing Framework -# -# SYNOPSIS: -# -# make [all] - makes everything. -# make TARGET - makes the given target. -# make clean - removes all files generated by make. - -# Please tweak the following variable definitions as needed by your -# project, except GTEST_HEADERS, which you can use in your own targets -# but shouldn't modify. - -# Points to the root of Google Test, relative to where this file is. -# Remember to tweak this if you move this file. -GTEST_DIR = gtest - -# Where to find user code. -USER_DIR = . - -# Flags passed to the preprocessor. -CPPFLAGS += -I$(GTEST_DIR)/include - -# Flags passed to the C++ compiler. -CXXFLAGS += -g -Wall -Wextra - -# All tests produced by this Makefile. Remember to add new tests you -# created to the list. -TESTS = Tennis - -# All Google Test headers. Usually you shouldn't change this -# definition. -GTEST_HEADERS = $(GTEST_DIR)/include/gtest/*.h \ - $(GTEST_DIR)/include/gtest/internal/*.h - -# House-keeping build targets. - -all : $(TESTS) - -clean : - rm -f $(TESTS) gtest.a gtest_main.a *.o - -# Builds gtest.a and gtest_main.a. - -# Usually you shouldn't tweak such internal variables, indicated by a -# trailing _. -GTEST_SRCS_ = $(GTEST_DIR)/src/*.cc $(GTEST_DIR)/src/*.h $(GTEST_HEADERS) - -# For simplicity and to avoid depending on Google Test's -# implementation details, the dependencies specified below are -# conservative and not optimized. This is fine as Google Test -# compiles fast and for ordinary users its source rarely changes. -gtest-all.o : $(GTEST_SRCS_) - $(CXX) $(CPPFLAGS) -I$(GTEST_DIR) $(CXXFLAGS) -c \ - $(GTEST_DIR)/src/gtest-all.cc - -gtest_main.o : $(GTEST_SRCS_) - $(CXX) $(CPPFLAGS) -I$(GTEST_DIR) $(CXXFLAGS) -c \ - $(GTEST_DIR)/src/gtest_main.cc - -gtest.a : gtest-all.o - $(AR) $(ARFLAGS) $@ $^ - -gtest_main.a : gtest-all.o gtest_main.o - $(AR) $(ARFLAGS) $@ $^ - -# Builds a sample test. A test should link with either gtest.a or -# gtest_main.a, depending on whether it defines its own main() -# function. - -Tennis.o : $(USER_DIR)/Tennis.cc \ - $(GTEST_HEADERS) - $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/Tennis.cc - -Tennis : Tennis.o gtest_main.a - $(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@ diff --git a/Tennis/cpp/defactored1/README b/Tennis/cpp/defactored1/README deleted file mode 100644 index 59cd984e..00000000 --- a/Tennis/cpp/defactored1/README +++ /dev/null @@ -1,14 +0,0 @@ -These files were created: - README is what you are currently reading - run-once.sh runs your tests once - run-endless.sh runs your tests endlessly via run-once.sh - -Run run-endless.sh and start your kata. (On Mac/Linux you have to call ./run-endless.sh.) - -Assumptions: - - make and a C++ compiler (like gcc) is installed on your system and is in the PATH - - The GTest framework is in the directory gtest. - - If your IDE does the compilation and linking, you should remove the first 3 lines - in the run-once.sh file. - -The support for C++/GTest was contributed by Stefan Roock. diff --git a/Tennis/cpp/defactored1/Tennis.cc b/Tennis/cpp/defactored1/Tennis.cc deleted file mode 100644 index 0f340f5f..00000000 --- a/Tennis/cpp/defactored1/Tennis.cc +++ /dev/null @@ -1,227 +0,0 @@ -#include - -const std::string tennis_score(int p1Score, int p2Score) { - std::string score = ""; - int tempScore=0; - if (p1Score==p2Score) - { - switch (p1Score) - { - case 0: - score = "Love-All"; - break; - case 1: - score = "Fifteen-All"; - break; - case 2: - score = "Thirty-All"; - break; - case 3: - score = "Deuce"; - break; - default: - score = "Deuce"; - break; - - } - } - else if (p1Score>=4 || p2Score>=4) - { - int minusResult = p1Score-p2Score; - if (minusResult==1) score ="Advantage player1"; - else if (minusResult ==-1) score ="Advantage player2"; - else if (minusResult>=2) score = "Win for player1"; - else score ="Win for player2"; - } - else - { - for (int i=1; i<3; i++) - { - if (i==1) tempScore = p1Score; - else { score+="-"; tempScore = p2Score;} - switch(tempScore) - { - case 0: - score+="Love"; - break; - case 1: - score+="Fifteen"; - break; - case 2: - score+="Thirty"; - break; - case 3: - score+="Forty"; - break; - } - } - } - return score; - -} - -TEST(TennisTest, LoveAll_0_0) { - EXPECT_EQ("Love-All", tennis_score(0, 0)); -} - - -TEST(TennisTest, FifteenAll_1_1) { - EXPECT_EQ("Fifteen-All", tennis_score(1, 1)); -} - - -TEST(TennisTest, ThirtyAll_2_2) { - EXPECT_EQ("Thirty-All", tennis_score(2, 2)); -} - - -TEST(TennisTest, Deuce_3_3) { - EXPECT_EQ("Deuce", tennis_score(3, 3)); -} - - -TEST(TennisTest, Deuce_4_4) { - EXPECT_EQ("Deuce", tennis_score(4, 4)); -} - - -TEST(TennisTest, FifteenLove_1_0) { - EXPECT_EQ("Fifteen-Love", tennis_score(1, 0)); -} - - -TEST(TennisTest, LoveFifteen_0_1) { - EXPECT_EQ("Love-Fifteen", tennis_score(0, 1)); -} - - -TEST(TennisTest, ThirtyLove_2_0) { - EXPECT_EQ("Thirty-Love", tennis_score(2, 0)); -} - - -TEST(TennisTest, LoveThirty_0_2) { - EXPECT_EQ("Love-Thirty", tennis_score(0, 2)); -} - - -TEST(TennisTest, FortyLove_3_0) { - EXPECT_EQ("Forty-Love", tennis_score(3, 0)); -} - - -TEST(TennisTest, LoveForty_0_3) { - EXPECT_EQ("Love-Forty", tennis_score(0, 3)); -} - - -TEST(TennisTest, Winforplayer1_4_0) { - EXPECT_EQ("Win for player1", tennis_score(4, 0)); -} - - -TEST(TennisTest, Winforplayer2_0_4) { - EXPECT_EQ("Win for player2", tennis_score(0, 4)); -} - - -TEST(TennisTest, ThirtyFifteen_2_1) { - EXPECT_EQ("Thirty-Fifteen", tennis_score(2, 1)); -} - - -TEST(TennisTest, FifteenThirty_1_2) { - EXPECT_EQ("Fifteen-Thirty", tennis_score(1, 2)); -} - - -TEST(TennisTest, FortyFifteen_3_1) { - EXPECT_EQ("Forty-Fifteen", tennis_score(3, 1)); -} - - -TEST(TennisTest, FifteenForty_1_3) { - EXPECT_EQ("Fifteen-Forty", tennis_score(1, 3)); -} - - -TEST(TennisTest, Winforplayer1_4_1) { - EXPECT_EQ("Win for player1", tennis_score(4, 1)); -} - - -TEST(TennisTest, Winforplayer2_1_4) { - EXPECT_EQ("Win for player2", tennis_score(1, 4)); -} - - -TEST(TennisTest, FortyThirty_3_2) { - EXPECT_EQ("Forty-Thirty", tennis_score(3, 2)); -} - - -TEST(TennisTest, ThirtyForty_2_3) { - EXPECT_EQ("Thirty-Forty", tennis_score(2, 3)); -} - - -TEST(TennisTest, Winforplayer1_4_2) { - EXPECT_EQ("Win for player1", tennis_score(4, 2)); -} - - -TEST(TennisTest, Winforplayer2_2_4) { - EXPECT_EQ("Win for player2", tennis_score(2, 4)); -} - - -TEST(TennisTest, Advantageplayer1_4_3) { - EXPECT_EQ("Advantage player1", tennis_score(4, 3)); -} - - -TEST(TennisTest, Advantageplayer2_3_4) { - EXPECT_EQ("Advantage player2", tennis_score(3, 4)); -} - - -TEST(TennisTest, Advantageplayer1_5_4) { - EXPECT_EQ("Advantage player1", tennis_score(5, 4)); -} - - -TEST(TennisTest, Advantageplayer2_4_5) { - EXPECT_EQ("Advantage player2", tennis_score(4, 5)); -} - - -TEST(TennisTest, Advantageplayer1_15_14) { - EXPECT_EQ("Advantage player1", tennis_score(15, 14)); -} - - -TEST(TennisTest, Advantageplayer2_14_15) { - EXPECT_EQ("Advantage player2", tennis_score(14, 15)); -} - - -TEST(TennisTest, Winforplayer1_6_4) { - EXPECT_EQ("Win for player1", tennis_score(6, 4)); -} - - -TEST(TennisTest, Winforplayer2_4_6) { - EXPECT_EQ("Win for player2", tennis_score(4, 6)); -} - - -TEST(TennisTest, Winforplayer1_16_14) { - EXPECT_EQ("Win for player1", tennis_score(16, 14)); -} - - -TEST(TennisTest, Winforplayer2_14_16) { - EXPECT_EQ("Win for player2", tennis_score(14, 16)); -} - - diff --git a/Tennis/cpp/defactored1/run-once.sh b/Tennis/cpp/defactored1/run-once.sh deleted file mode 100755 index 1b1bffef..00000000 --- a/Tennis/cpp/defactored1/run-once.sh +++ /dev/null @@ -1,4 +0,0 @@ -rm Tennis -rm Tennis.o -make -./Tennis \ No newline at end of file diff --git a/Tennis/cpp/defactored2/Makefile b/Tennis/cpp/defactored2/Makefile deleted file mode 100644 index a97fcd8b..00000000 --- a/Tennis/cpp/defactored2/Makefile +++ /dev/null @@ -1,75 +0,0 @@ -# Makefile for building the kata file with the Google Testing Framework -# -# SYNOPSIS: -# -# make [all] - makes everything. -# make TARGET - makes the given target. -# make clean - removes all files generated by make. - -# Please tweak the following variable definitions as needed by your -# project, except GTEST_HEADERS, which you can use in your own targets -# but shouldn't modify. - -# Points to the root of Google Test, relative to where this file is. -# Remember to tweak this if you move this file. -GTEST_DIR = gtest - -# Where to find user code. -USER_DIR = . - -# Flags passed to the preprocessor. -CPPFLAGS += -I$(GTEST_DIR)/include - -# Flags passed to the C++ compiler. -CXXFLAGS += -g -Wall -Wextra - -# All tests produced by this Makefile. Remember to add new tests you -# created to the list. -TESTS = Tennis - -# All Google Test headers. Usually you shouldn't change this -# definition. -GTEST_HEADERS = $(GTEST_DIR)/include/gtest/*.h \ - $(GTEST_DIR)/include/gtest/internal/*.h - -# House-keeping build targets. - -all : $(TESTS) - -clean : - rm -f $(TESTS) gtest.a gtest_main.a *.o - -# Builds gtest.a and gtest_main.a. - -# Usually you shouldn't tweak such internal variables, indicated by a -# trailing _. -GTEST_SRCS_ = $(GTEST_DIR)/src/*.cc $(GTEST_DIR)/src/*.h $(GTEST_HEADERS) - -# For simplicity and to avoid depending on Google Test's -# implementation details, the dependencies specified below are -# conservative and not optimized. This is fine as Google Test -# compiles fast and for ordinary users its source rarely changes. -gtest-all.o : $(GTEST_SRCS_) - $(CXX) $(CPPFLAGS) -I$(GTEST_DIR) $(CXXFLAGS) -c \ - $(GTEST_DIR)/src/gtest-all.cc - -gtest_main.o : $(GTEST_SRCS_) - $(CXX) $(CPPFLAGS) -I$(GTEST_DIR) $(CXXFLAGS) -c \ - $(GTEST_DIR)/src/gtest_main.cc - -gtest.a : gtest-all.o - $(AR) $(ARFLAGS) $@ $^ - -gtest_main.a : gtest-all.o gtest_main.o - $(AR) $(ARFLAGS) $@ $^ - -# Builds a sample test. A test should link with either gtest.a or -# gtest_main.a, depending on whether it defines its own main() -# function. - -Tennis.o : $(USER_DIR)/Tennis.cc \ - $(GTEST_HEADERS) - $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/Tennis.cc - -Tennis : Tennis.o gtest_main.a - $(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@ diff --git a/Tennis/cpp/defactored2/README b/Tennis/cpp/defactored2/README deleted file mode 100644 index 59cd984e..00000000 --- a/Tennis/cpp/defactored2/README +++ /dev/null @@ -1,14 +0,0 @@ -These files were created: - README is what you are currently reading - run-once.sh runs your tests once - run-endless.sh runs your tests endlessly via run-once.sh - -Run run-endless.sh and start your kata. (On Mac/Linux you have to call ./run-endless.sh.) - -Assumptions: - - make and a C++ compiler (like gcc) is installed on your system and is in the PATH - - The GTest framework is in the directory gtest. - - If your IDE does the compilation and linking, you should remove the first 3 lines - in the run-once.sh file. - -The support for C++/GTest was contributed by Stefan Roock. diff --git a/Tennis/cpp/defactored2/Tennis.cc b/Tennis/cpp/defactored2/Tennis.cc deleted file mode 100644 index 8ff36536..00000000 --- a/Tennis/cpp/defactored2/Tennis.cc +++ /dev/null @@ -1,258 +0,0 @@ -#include - -const std::string tennis_score(int p1Score, int p2Score) { - std::string score = ""; - std::string P1res = ""; - std::string P2res = ""; - if (p1Score == p2Score && p1Score < 4) - { - if (p1Score==0) - score = "Love"; - if (p1Score==1) - score = "Fifteen"; - if (p1Score==2) - score = "Thirty"; - if (p1Score==3) - score = "Forty"; - score += "-All"; - } - if (p1Score==p2Score && p1Score>2) - score = "Deuce"; - - if (p1Score > 0 && p2Score==0) - { - if (p1Score==1) - P1res = "Fifteen"; - if (p1Score==2) - P1res = "Thirty"; - if (p1Score==3) - P1res = "Forty"; - - P2res = "Love"; - score = P1res + "-" + P2res; - } - if (p2Score > 0 && p1Score==0) - { - if (p2Score==1) - P2res = "Fifteen"; - if (p2Score==2) - P2res = "Thirty"; - if (p2Score==3) - P2res = "Forty"; - - P1res = "Love"; - score = P1res + "-" + P2res; - } - - if (p1Score>p2Score && p1Score < 4) - { - if (p1Score==2) - P1res="Thirty"; - if (p1Score==3) - P1res="Forty"; - if (p2Score==1) - P2res="Fifteen"; - if (p2Score==2) - P2res="Thirty"; - score = P1res + "-" + P2res; - } - if (p2Score>p1Score && p2Score < 4) - { - if (p2Score==2) - P2res="Thirty"; - if (p2Score==3) - P2res="Forty"; - if (p1Score==1) - P1res="Fifteen"; - if (p1Score==2) - P1res="Thirty"; - score = P1res + "-" + P2res; - } - - if (p1Score > p2Score && p2Score >= 3) - { - score = "Advantage player1"; - } - - if (p2Score > p1Score && p1Score >= 3) - { - score = "Advantage player2"; - } - - if (p1Score>=4 && p2Score>=0 && (p1Score-p2Score)>=2) - { - score = "Win for player1"; - } - if (p2Score>=4 && p1Score>=0 && (p2Score-p1Score)>=2) - { - score = "Win for player2"; - } - return score; - -} - -TEST(TennisTest, LoveAll_0_0) { - EXPECT_EQ("Love-All", tennis_score(0, 0)); -} - - -TEST(TennisTest, FifteenAll_1_1) { - EXPECT_EQ("Fifteen-All", tennis_score(1, 1)); -} - - -TEST(TennisTest, ThirtyAll_2_2) { - EXPECT_EQ("Thirty-All", tennis_score(2, 2)); -} - - -TEST(TennisTest, Deuce_3_3) { - EXPECT_EQ("Deuce", tennis_score(3, 3)); -} - - -TEST(TennisTest, Deuce_4_4) { - EXPECT_EQ("Deuce", tennis_score(4, 4)); -} - - -TEST(TennisTest, FifteenLove_1_0) { - EXPECT_EQ("Fifteen-Love", tennis_score(1, 0)); -} - - -TEST(TennisTest, LoveFifteen_0_1) { - EXPECT_EQ("Love-Fifteen", tennis_score(0, 1)); -} - - -TEST(TennisTest, ThirtyLove_2_0) { - EXPECT_EQ("Thirty-Love", tennis_score(2, 0)); -} - - -TEST(TennisTest, LoveThirty_0_2) { - EXPECT_EQ("Love-Thirty", tennis_score(0, 2)); -} - - -TEST(TennisTest, FortyLove_3_0) { - EXPECT_EQ("Forty-Love", tennis_score(3, 0)); -} - - -TEST(TennisTest, LoveForty_0_3) { - EXPECT_EQ("Love-Forty", tennis_score(0, 3)); -} - - -TEST(TennisTest, Winforplayer1_4_0) { - EXPECT_EQ("Win for player1", tennis_score(4, 0)); -} - - -TEST(TennisTest, Winforplayer2_0_4) { - EXPECT_EQ("Win for player2", tennis_score(0, 4)); -} - - -TEST(TennisTest, ThirtyFifteen_2_1) { - EXPECT_EQ("Thirty-Fifteen", tennis_score(2, 1)); -} - - -TEST(TennisTest, FifteenThirty_1_2) { - EXPECT_EQ("Fifteen-Thirty", tennis_score(1, 2)); -} - - -TEST(TennisTest, FortyFifteen_3_1) { - EXPECT_EQ("Forty-Fifteen", tennis_score(3, 1)); -} - - -TEST(TennisTest, FifteenForty_1_3) { - EXPECT_EQ("Fifteen-Forty", tennis_score(1, 3)); -} - - -TEST(TennisTest, Winforplayer1_4_1) { - EXPECT_EQ("Win for player1", tennis_score(4, 1)); -} - - -TEST(TennisTest, Winforplayer2_1_4) { - EXPECT_EQ("Win for player2", tennis_score(1, 4)); -} - - -TEST(TennisTest, FortyThirty_3_2) { - EXPECT_EQ("Forty-Thirty", tennis_score(3, 2)); -} - - -TEST(TennisTest, ThirtyForty_2_3) { - EXPECT_EQ("Thirty-Forty", tennis_score(2, 3)); -} - - -TEST(TennisTest, Winforplayer1_4_2) { - EXPECT_EQ("Win for player1", tennis_score(4, 2)); -} - - -TEST(TennisTest, Winforplayer2_2_4) { - EXPECT_EQ("Win for player2", tennis_score(2, 4)); -} - - -TEST(TennisTest, Advantageplayer1_4_3) { - EXPECT_EQ("Advantage player1", tennis_score(4, 3)); -} - - -TEST(TennisTest, Advantageplayer2_3_4) { - EXPECT_EQ("Advantage player2", tennis_score(3, 4)); -} - - -TEST(TennisTest, Advantageplayer1_5_4) { - EXPECT_EQ("Advantage player1", tennis_score(5, 4)); -} - - -TEST(TennisTest, Advantageplayer2_4_5) { - EXPECT_EQ("Advantage player2", tennis_score(4, 5)); -} - - -TEST(TennisTest, Advantageplayer1_15_14) { - EXPECT_EQ("Advantage player1", tennis_score(15, 14)); -} - - -TEST(TennisTest, Advantageplayer2_14_15) { - EXPECT_EQ("Advantage player2", tennis_score(14, 15)); -} - - -TEST(TennisTest, Winforplayer1_6_4) { - EXPECT_EQ("Win for player1", tennis_score(6, 4)); -} - - -TEST(TennisTest, Winforplayer2_4_6) { - EXPECT_EQ("Win for player2", tennis_score(4, 6)); -} - - -TEST(TennisTest, Winforplayer1_16_14) { - EXPECT_EQ("Win for player1", tennis_score(16, 14)); -} - - -TEST(TennisTest, Winforplayer2_14_16) { - EXPECT_EQ("Win for player2", tennis_score(14, 16)); -} - - diff --git a/Tennis/cpp/defactored2/run-once.sh b/Tennis/cpp/defactored2/run-once.sh deleted file mode 100755 index 1b1bffef..00000000 --- a/Tennis/cpp/defactored2/run-once.sh +++ /dev/null @@ -1,4 +0,0 @@ -rm Tennis -rm Tennis.o -make -./Tennis \ No newline at end of file diff --git a/Tennis/cpp/defactored3/Makefile b/Tennis/cpp/defactored3/Makefile deleted file mode 100644 index a97fcd8b..00000000 --- a/Tennis/cpp/defactored3/Makefile +++ /dev/null @@ -1,75 +0,0 @@ -# Makefile for building the kata file with the Google Testing Framework -# -# SYNOPSIS: -# -# make [all] - makes everything. -# make TARGET - makes the given target. -# make clean - removes all files generated by make. - -# Please tweak the following variable definitions as needed by your -# project, except GTEST_HEADERS, which you can use in your own targets -# but shouldn't modify. - -# Points to the root of Google Test, relative to where this file is. -# Remember to tweak this if you move this file. -GTEST_DIR = gtest - -# Where to find user code. -USER_DIR = . - -# Flags passed to the preprocessor. -CPPFLAGS += -I$(GTEST_DIR)/include - -# Flags passed to the C++ compiler. -CXXFLAGS += -g -Wall -Wextra - -# All tests produced by this Makefile. Remember to add new tests you -# created to the list. -TESTS = Tennis - -# All Google Test headers. Usually you shouldn't change this -# definition. -GTEST_HEADERS = $(GTEST_DIR)/include/gtest/*.h \ - $(GTEST_DIR)/include/gtest/internal/*.h - -# House-keeping build targets. - -all : $(TESTS) - -clean : - rm -f $(TESTS) gtest.a gtest_main.a *.o - -# Builds gtest.a and gtest_main.a. - -# Usually you shouldn't tweak such internal variables, indicated by a -# trailing _. -GTEST_SRCS_ = $(GTEST_DIR)/src/*.cc $(GTEST_DIR)/src/*.h $(GTEST_HEADERS) - -# For simplicity and to avoid depending on Google Test's -# implementation details, the dependencies specified below are -# conservative and not optimized. This is fine as Google Test -# compiles fast and for ordinary users its source rarely changes. -gtest-all.o : $(GTEST_SRCS_) - $(CXX) $(CPPFLAGS) -I$(GTEST_DIR) $(CXXFLAGS) -c \ - $(GTEST_DIR)/src/gtest-all.cc - -gtest_main.o : $(GTEST_SRCS_) - $(CXX) $(CPPFLAGS) -I$(GTEST_DIR) $(CXXFLAGS) -c \ - $(GTEST_DIR)/src/gtest_main.cc - -gtest.a : gtest-all.o - $(AR) $(ARFLAGS) $@ $^ - -gtest_main.a : gtest-all.o gtest_main.o - $(AR) $(ARFLAGS) $@ $^ - -# Builds a sample test. A test should link with either gtest.a or -# gtest_main.a, depending on whether it defines its own main() -# function. - -Tennis.o : $(USER_DIR)/Tennis.cc \ - $(GTEST_HEADERS) - $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/Tennis.cc - -Tennis : Tennis.o gtest_main.a - $(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@ diff --git a/Tennis/cpp/defactored3/README b/Tennis/cpp/defactored3/README deleted file mode 100644 index 59cd984e..00000000 --- a/Tennis/cpp/defactored3/README +++ /dev/null @@ -1,14 +0,0 @@ -These files were created: - README is what you are currently reading - run-once.sh runs your tests once - run-endless.sh runs your tests endlessly via run-once.sh - -Run run-endless.sh and start your kata. (On Mac/Linux you have to call ./run-endless.sh.) - -Assumptions: - - make and a C++ compiler (like gcc) is installed on your system and is in the PATH - - The GTest framework is in the directory gtest. - - If your IDE does the compilation and linking, you should remove the first 3 lines - in the run-once.sh file. - -The support for C++/GTest was contributed by Stefan Roock. diff --git a/Tennis/cpp/defactored3/Tennis.cc b/Tennis/cpp/defactored3/Tennis.cc deleted file mode 100644 index 4cce3d6a..00000000 --- a/Tennis/cpp/defactored3/Tennis.cc +++ /dev/null @@ -1,183 +0,0 @@ -#include - -const std::string tennis_score(int p1, int p2) { - std::string s; - std::string p1N = "player1"; - std::string p2N = "player2"; - if (p1 < 4 && p2 < 4 && !(p1 == 3 && p2 == 3)) { - std::string p[4] = {"Love", "Fifteen", "Thirty", "Forty"}; - s = p[p1]; - return (p1 == p2) ? s + "-All" : s + "-" + p[p2]; - } else { - if (p1 == p2) - return "Deuce"; - s = p1 > p2 ? p1N : p2N; - return ((p1-p2)*(p1-p2) == 1) ? "Advantage " + s : "Win for " + s; - } -} - -TEST(TennisTest, LoveAll_0_0) { - EXPECT_EQ("Love-All", tennis_score(0, 0)); -} - - -TEST(TennisTest, FifteenAll_1_1) { - EXPECT_EQ("Fifteen-All", tennis_score(1, 1)); -} - - -TEST(TennisTest, ThirtyAll_2_2) { - EXPECT_EQ("Thirty-All", tennis_score(2, 2)); -} - - -TEST(TennisTest, Deuce_3_3) { - EXPECT_EQ("Deuce", tennis_score(3, 3)); -} - - -TEST(TennisTest, Deuce_4_4) { - EXPECT_EQ("Deuce", tennis_score(4, 4)); -} - - -TEST(TennisTest, FifteenLove_1_0) { - EXPECT_EQ("Fifteen-Love", tennis_score(1, 0)); -} - - -TEST(TennisTest, LoveFifteen_0_1) { - EXPECT_EQ("Love-Fifteen", tennis_score(0, 1)); -} - - -TEST(TennisTest, ThirtyLove_2_0) { - EXPECT_EQ("Thirty-Love", tennis_score(2, 0)); -} - - -TEST(TennisTest, LoveThirty_0_2) { - EXPECT_EQ("Love-Thirty", tennis_score(0, 2)); -} - - -TEST(TennisTest, FortyLove_3_0) { - EXPECT_EQ("Forty-Love", tennis_score(3, 0)); -} - - -TEST(TennisTest, LoveForty_0_3) { - EXPECT_EQ("Love-Forty", tennis_score(0, 3)); -} - - -TEST(TennisTest, Winforplayer1_4_0) { - EXPECT_EQ("Win for player1", tennis_score(4, 0)); -} - - -TEST(TennisTest, Winforplayer2_0_4) { - EXPECT_EQ("Win for player2", tennis_score(0, 4)); -} - - -TEST(TennisTest, ThirtyFifteen_2_1) { - EXPECT_EQ("Thirty-Fifteen", tennis_score(2, 1)); -} - - -TEST(TennisTest, FifteenThirty_1_2) { - EXPECT_EQ("Fifteen-Thirty", tennis_score(1, 2)); -} - - -TEST(TennisTest, FortyFifteen_3_1) { - EXPECT_EQ("Forty-Fifteen", tennis_score(3, 1)); -} - - -TEST(TennisTest, FifteenForty_1_3) { - EXPECT_EQ("Fifteen-Forty", tennis_score(1, 3)); -} - - -TEST(TennisTest, Winforplayer1_4_1) { - EXPECT_EQ("Win for player1", tennis_score(4, 1)); -} - - -TEST(TennisTest, Winforplayer2_1_4) { - EXPECT_EQ("Win for player2", tennis_score(1, 4)); -} - - -TEST(TennisTest, FortyThirty_3_2) { - EXPECT_EQ("Forty-Thirty", tennis_score(3, 2)); -} - - -TEST(TennisTest, ThirtyForty_2_3) { - EXPECT_EQ("Thirty-Forty", tennis_score(2, 3)); -} - - -TEST(TennisTest, Winforplayer1_4_2) { - EXPECT_EQ("Win for player1", tennis_score(4, 2)); -} - - -TEST(TennisTest, Winforplayer2_2_4) { - EXPECT_EQ("Win for player2", tennis_score(2, 4)); -} - - -TEST(TennisTest, Advantageplayer1_4_3) { - EXPECT_EQ("Advantage player1", tennis_score(4, 3)); -} - - -TEST(TennisTest, Advantageplayer2_3_4) { - EXPECT_EQ("Advantage player2", tennis_score(3, 4)); -} - - -TEST(TennisTest, Advantageplayer1_5_4) { - EXPECT_EQ("Advantage player1", tennis_score(5, 4)); -} - - -TEST(TennisTest, Advantageplayer2_4_5) { - EXPECT_EQ("Advantage player2", tennis_score(4, 5)); -} - - -TEST(TennisTest, Advantageplayer1_15_14) { - EXPECT_EQ("Advantage player1", tennis_score(15, 14)); -} - - -TEST(TennisTest, Advantageplayer2_14_15) { - EXPECT_EQ("Advantage player2", tennis_score(14, 15)); -} - - -TEST(TennisTest, Winforplayer1_6_4) { - EXPECT_EQ("Win for player1", tennis_score(6, 4)); -} - - -TEST(TennisTest, Winforplayer2_4_6) { - EXPECT_EQ("Win for player2", tennis_score(4, 6)); -} - - -TEST(TennisTest, Winforplayer1_16_14) { - EXPECT_EQ("Win for player1", tennis_score(16, 14)); -} - - -TEST(TennisTest, Winforplayer2_14_16) { - EXPECT_EQ("Win for player2", tennis_score(14, 16)); -} - - diff --git a/Tennis/cpp/defactored3/run-once.sh b/Tennis/cpp/defactored3/run-once.sh deleted file mode 100755 index 1b1bffef..00000000 --- a/Tennis/cpp/defactored3/run-once.sh +++ /dev/null @@ -1,4 +0,0 @@ -rm Tennis -rm Tennis.o -make -./Tennis \ No newline at end of file diff --git a/Tennis/cpp/starting/Makefile b/Tennis/cpp/starting/Makefile deleted file mode 100644 index a97fcd8b..00000000 --- a/Tennis/cpp/starting/Makefile +++ /dev/null @@ -1,75 +0,0 @@ -# Makefile for building the kata file with the Google Testing Framework -# -# SYNOPSIS: -# -# make [all] - makes everything. -# make TARGET - makes the given target. -# make clean - removes all files generated by make. - -# Please tweak the following variable definitions as needed by your -# project, except GTEST_HEADERS, which you can use in your own targets -# but shouldn't modify. - -# Points to the root of Google Test, relative to where this file is. -# Remember to tweak this if you move this file. -GTEST_DIR = gtest - -# Where to find user code. -USER_DIR = . - -# Flags passed to the preprocessor. -CPPFLAGS += -I$(GTEST_DIR)/include - -# Flags passed to the C++ compiler. -CXXFLAGS += -g -Wall -Wextra - -# All tests produced by this Makefile. Remember to add new tests you -# created to the list. -TESTS = Tennis - -# All Google Test headers. Usually you shouldn't change this -# definition. -GTEST_HEADERS = $(GTEST_DIR)/include/gtest/*.h \ - $(GTEST_DIR)/include/gtest/internal/*.h - -# House-keeping build targets. - -all : $(TESTS) - -clean : - rm -f $(TESTS) gtest.a gtest_main.a *.o - -# Builds gtest.a and gtest_main.a. - -# Usually you shouldn't tweak such internal variables, indicated by a -# trailing _. -GTEST_SRCS_ = $(GTEST_DIR)/src/*.cc $(GTEST_DIR)/src/*.h $(GTEST_HEADERS) - -# For simplicity and to avoid depending on Google Test's -# implementation details, the dependencies specified below are -# conservative and not optimized. This is fine as Google Test -# compiles fast and for ordinary users its source rarely changes. -gtest-all.o : $(GTEST_SRCS_) - $(CXX) $(CPPFLAGS) -I$(GTEST_DIR) $(CXXFLAGS) -c \ - $(GTEST_DIR)/src/gtest-all.cc - -gtest_main.o : $(GTEST_SRCS_) - $(CXX) $(CPPFLAGS) -I$(GTEST_DIR) $(CXXFLAGS) -c \ - $(GTEST_DIR)/src/gtest_main.cc - -gtest.a : gtest-all.o - $(AR) $(ARFLAGS) $@ $^ - -gtest_main.a : gtest-all.o gtest_main.o - $(AR) $(ARFLAGS) $@ $^ - -# Builds a sample test. A test should link with either gtest.a or -# gtest_main.a, depending on whether it defines its own main() -# function. - -Tennis.o : $(USER_DIR)/Tennis.cc \ - $(GTEST_HEADERS) - $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/Tennis.cc - -Tennis : Tennis.o gtest_main.a - $(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@ diff --git a/Tennis/cpp/starting/README b/Tennis/cpp/starting/README deleted file mode 100644 index 59cd984e..00000000 --- a/Tennis/cpp/starting/README +++ /dev/null @@ -1,14 +0,0 @@ -These files were created: - README is what you are currently reading - run-once.sh runs your tests once - run-endless.sh runs your tests endlessly via run-once.sh - -Run run-endless.sh and start your kata. (On Mac/Linux you have to call ./run-endless.sh.) - -Assumptions: - - make and a C++ compiler (like gcc) is installed on your system and is in the PATH - - The GTest framework is in the directory gtest. - - If your IDE does the compilation and linking, you should remove the first 3 lines - in the run-once.sh file. - -The support for C++/GTest was contributed by Stefan Roock. diff --git a/Tennis/cpp/starting/Tennis.cc b/Tennis/cpp/starting/Tennis.cc deleted file mode 100644 index 87ce94ac..00000000 --- a/Tennis/cpp/starting/Tennis.cc +++ /dev/null @@ -1,171 +0,0 @@ -#include - -const std::string tennis_score(int p1Score, int p2Score) { - return "foo"; -} - -TEST(TennisTest, LoveAll_0_0) { - EXPECT_EQ("Love-All", tennis_score(0, 0)); -} - - -TEST(TennisTest, FifteenAll_1_1) { - EXPECT_EQ("Fifteen-All", tennis_score(1, 1)); -} - - -TEST(TennisTest, ThirtyAll_2_2) { - EXPECT_EQ("Thirty-All", tennis_score(2, 2)); -} - - -TEST(TennisTest, Deuce_3_3) { - EXPECT_EQ("Deuce", tennis_score(3, 3)); -} - - -TEST(TennisTest, Deuce_4_4) { - EXPECT_EQ("Deuce", tennis_score(4, 4)); -} - - -TEST(TennisTest, FifteenLove_1_0) { - EXPECT_EQ("Fifteen-Love", tennis_score(1, 0)); -} - - -TEST(TennisTest, LoveFifteen_0_1) { - EXPECT_EQ("Love-Fifteen", tennis_score(0, 1)); -} - - -TEST(TennisTest, ThirtyLove_2_0) { - EXPECT_EQ("Thirty-Love", tennis_score(2, 0)); -} - - -TEST(TennisTest, LoveThirty_0_2) { - EXPECT_EQ("Love-Thirty", tennis_score(0, 2)); -} - - -TEST(TennisTest, FortyLove_3_0) { - EXPECT_EQ("Forty-Love", tennis_score(3, 0)); -} - - -TEST(TennisTest, LoveForty_0_3) { - EXPECT_EQ("Love-Forty", tennis_score(0, 3)); -} - - -TEST(TennisTest, Winforplayer1_4_0) { - EXPECT_EQ("Win for player1", tennis_score(4, 0)); -} - - -TEST(TennisTest, Winforplayer2_0_4) { - EXPECT_EQ("Win for player2", tennis_score(0, 4)); -} - - -TEST(TennisTest, ThirtyFifteen_2_1) { - EXPECT_EQ("Thirty-Fifteen", tennis_score(2, 1)); -} - - -TEST(TennisTest, FifteenThirty_1_2) { - EXPECT_EQ("Fifteen-Thirty", tennis_score(1, 2)); -} - - -TEST(TennisTest, FortyFifteen_3_1) { - EXPECT_EQ("Forty-Fifteen", tennis_score(3, 1)); -} - - -TEST(TennisTest, FifteenForty_1_3) { - EXPECT_EQ("Fifteen-Forty", tennis_score(1, 3)); -} - - -TEST(TennisTest, Winforplayer1_4_1) { - EXPECT_EQ("Win for player1", tennis_score(4, 1)); -} - - -TEST(TennisTest, Winforplayer2_1_4) { - EXPECT_EQ("Win for player2", tennis_score(1, 4)); -} - - -TEST(TennisTest, FortyThirty_3_2) { - EXPECT_EQ("Forty-Thirty", tennis_score(3, 2)); -} - - -TEST(TennisTest, ThirtyForty_2_3) { - EXPECT_EQ("Thirty-Forty", tennis_score(2, 3)); -} - - -TEST(TennisTest, Winforplayer1_4_2) { - EXPECT_EQ("Win for player1", tennis_score(4, 2)); -} - - -TEST(TennisTest, Winforplayer2_2_4) { - EXPECT_EQ("Win for player2", tennis_score(2, 4)); -} - - -TEST(TennisTest, Advantageplayer1_4_3) { - EXPECT_EQ("Advantage player1", tennis_score(4, 3)); -} - - -TEST(TennisTest, Advantageplayer2_3_4) { - EXPECT_EQ("Advantage player2", tennis_score(3, 4)); -} - - -TEST(TennisTest, Advantageplayer1_5_4) { - EXPECT_EQ("Advantage player1", tennis_score(5, 4)); -} - - -TEST(TennisTest, Advantageplayer2_4_5) { - EXPECT_EQ("Advantage player2", tennis_score(4, 5)); -} - - -TEST(TennisTest, Advantageplayer1_15_14) { - EXPECT_EQ("Advantage player1", tennis_score(15, 14)); -} - - -TEST(TennisTest, Advantageplayer2_14_15) { - EXPECT_EQ("Advantage player2", tennis_score(14, 15)); -} - - -TEST(TennisTest, Winforplayer1_6_4) { - EXPECT_EQ("Win for player1", tennis_score(6, 4)); -} - - -TEST(TennisTest, Winforplayer2_4_6) { - EXPECT_EQ("Win for player2", tennis_score(4, 6)); -} - - -TEST(TennisTest, Winforplayer1_16_14) { - EXPECT_EQ("Win for player1", tennis_score(16, 14)); -} - - -TEST(TennisTest, Winforplayer2_14_16) { - EXPECT_EQ("Win for player2", tennis_score(14, 16)); -} - - diff --git a/Tennis/cpp/starting/run-once.sh b/Tennis/cpp/starting/run-once.sh deleted file mode 100755 index 1b1bffef..00000000 --- a/Tennis/cpp/starting/run-once.sh +++ /dev/null @@ -1,4 +0,0 @@ -rm Tennis -rm Tennis.o -make -./Tennis \ No newline at end of file From 7e52c0ddfe6f6dcaacec49233a51c377d9580ba3 Mon Sep 17 00:00:00 2001 From: emilybache Date: Mon, 10 Dec 2012 14:49:20 +0100 Subject: [PATCH 062/634] test cases and code that work in cyber-dojo --- Tennis/cpp/all_tests.cpp | 171 ++++++++++++++++++++++++++++++++ Tennis/cpp/all_tests.hpp | 33 ++++++ Tennis/cpp/generate_tests.py | 5 +- Tennis/cpp/makefile | 5 + Tennis/cpp/tennis1.cc | 61 ++++++++++++ Tennis/cpp/tennis2.cc | 92 +++++++++++++++++ Tennis/cpp/tennis3.cc | 17 ++++ Tennis/cpp/test_suite.tests.cpp | 55 ++++++++++ 8 files changed, 437 insertions(+), 2 deletions(-) create mode 100644 Tennis/cpp/all_tests.cpp create mode 100644 Tennis/cpp/all_tests.hpp create mode 100644 Tennis/cpp/makefile create mode 100644 Tennis/cpp/tennis1.cc create mode 100644 Tennis/cpp/tennis2.cc create mode 100644 Tennis/cpp/tennis3.cc create mode 100644 Tennis/cpp/test_suite.tests.cpp diff --git a/Tennis/cpp/all_tests.cpp b/Tennis/cpp/all_tests.cpp new file mode 100644 index 00000000..c677cfdc --- /dev/null +++ b/Tennis/cpp/all_tests.cpp @@ -0,0 +1,171 @@ +#include "all_tests.hpp" + +/* change this to the version of tennis you want to work on */ +#include "tennis1.cc" + +#include + +void test_LoveAll_0_0() +{ + assert("Love-All" == tennis_score(0, 0)); +} + +void test_FifteenAll_1_1() +{ + assert("Fifteen-All" == tennis_score(1, 1)); +} + +void test_ThirtyAll_2_2() +{ + assert("Thirty-All" == tennis_score(2, 2)); +} + +void test_Deuce_3_3() +{ + assert("Deuce" == tennis_score(3, 3)); +} + +void test_Deuce_4_4() +{ + assert("Deuce" == tennis_score(4, 4)); +} + +void test_FifteenLove_1_0() +{ + assert("Fifteen-Love" == tennis_score(1, 0)); +} + +void test_LoveFifteen_0_1() +{ + assert("Love-Fifteen" == tennis_score(0, 1)); +} + +void test_ThirtyLove_2_0() +{ + assert("Thirty-Love" == tennis_score(2, 0)); +} + +void test_LoveThirty_0_2() +{ + assert("Love-Thirty" == tennis_score(0, 2)); +} + +void test_FortyLove_3_0() +{ + assert("Forty-Love" == tennis_score(3, 0)); +} + +void test_LoveForty_0_3() +{ + assert("Love-Forty" == tennis_score(0, 3)); +} + +void test_Winforplayer1_4_0() +{ + assert("Win for player1" == tennis_score(4, 0)); +} + +void test_Winforplayer2_0_4() +{ + assert("Win for player2" == tennis_score(0, 4)); +} + +void test_ThirtyFifteen_2_1() +{ + assert("Thirty-Fifteen" == tennis_score(2, 1)); +} + +void test_FifteenThirty_1_2() +{ + assert("Fifteen-Thirty" == tennis_score(1, 2)); +} + +void test_FortyFifteen_3_1() +{ + assert("Forty-Fifteen" == tennis_score(3, 1)); +} + +void test_FifteenForty_1_3() +{ + assert("Fifteen-Forty" == tennis_score(1, 3)); +} + +void test_Winforplayer1_4_1() +{ + assert("Win for player1" == tennis_score(4, 1)); +} + +void test_Winforplayer2_1_4() +{ + assert("Win for player2" == tennis_score(1, 4)); +} + +void test_FortyThirty_3_2() +{ + assert("Forty-Thirty" == tennis_score(3, 2)); +} + +void test_ThirtyForty_2_3() +{ + assert("Thirty-Forty" == tennis_score(2, 3)); +} + +void test_Winforplayer1_4_2() +{ + assert("Win for player1" == tennis_score(4, 2)); +} + +void test_Winforplayer2_2_4() +{ + assert("Win for player2" == tennis_score(2, 4)); +} + +void test_Advantageplayer1_4_3() +{ + assert("Advantage player1" == tennis_score(4, 3)); +} + +void test_Advantageplayer2_3_4() +{ + assert("Advantage player2" == tennis_score(3, 4)); +} + +void test_Advantageplayer1_5_4() +{ + assert("Advantage player1" == tennis_score(5, 4)); +} + +void test_Advantageplayer2_4_5() +{ + assert("Advantage player2" == tennis_score(4, 5)); +} + +void test_Advantageplayer1_15_14() +{ + assert("Advantage player1" == tennis_score(15, 14)); +} + +void test_Advantageplayer2_14_15() +{ + assert("Advantage player2" == tennis_score(14, 15)); +} + +void test_Winforplayer1_6_4() +{ + assert("Win for player1" == tennis_score(6, 4)); +} + +void test_Winforplayer2_4_6() +{ + assert("Win for player2" == tennis_score(4, 6)); +} + +void test_Winforplayer1_16_14() +{ + assert("Win for player1" == tennis_score(16, 14)); +} + +void test_Winforplayer2_14_16() +{ + assert("Win for player2" == tennis_score(14, 16)); +} \ No newline at end of file diff --git a/Tennis/cpp/all_tests.hpp b/Tennis/cpp/all_tests.hpp new file mode 100644 index 00000000..b0fed07f --- /dev/null +++ b/Tennis/cpp/all_tests.hpp @@ -0,0 +1,33 @@ +void test_LoveAll_0_0(); +void test_FifteenAll_1_1(); +void test_ThirtyAll_2_2(); +void test_Deuce_3_3(); +void test_Deuce_4_4(); +void test_FifteenLove_1_0(); +void test_LoveFifteen_0_1(); +void test_ThirtyLove_2_0(); +void test_LoveThirty_0_2(); +void test_FortyLove_3_0(); +void test_LoveForty_0_3(); +void test_Winforplayer1_4_0(); +void test_Winforplayer2_0_4(); +void test_ThirtyFifteen_2_1(); +void test_FifteenThirty_1_2(); +void test_FortyFifteen_3_1(); +void test_FifteenForty_1_3(); +void test_Winforplayer1_4_1(); +void test_Winforplayer2_1_4(); +void test_FortyThirty_3_2(); +void test_ThirtyForty_2_3(); +void test_Winforplayer1_4_2(); +void test_Winforplayer2_2_4(); +void test_Advantageplayer1_4_3(); +void test_Advantageplayer2_3_4(); +void test_Advantageplayer1_5_4(); +void test_Advantageplayer2_4_5(); +void test_Advantageplayer1_15_14(); +void test_Advantageplayer2_14_15(); +void test_Winforplayer1_6_4(); +void test_Winforplayer2_4_6(); +void test_Winforplayer1_16_14(); +void test_Winforplayer2_14_16(); \ No newline at end of file diff --git a/Tennis/cpp/generate_tests.py b/Tennis/cpp/generate_tests.py index bd8975b2..d2f2c585 100644 --- a/Tennis/cpp/generate_tests.py +++ b/Tennis/cpp/generate_tests.py @@ -53,6 +53,7 @@ def create_testcase_dicts(): testcase_dicts = create_testcase_dicts() +# This is not currently being used gtest_template = """\ TEST(TennisTest, %(testcase_name)s) { EXPECT_EQ("%(score)s", tennis_score(%(p1Points)s, %(p2Points)s)); @@ -65,11 +66,11 @@ void test_%(testcase_name)s() assert("%(score)s" == tennis_score(%(p1Points)s, %(p2Points)s)); } """ -# test cases +# test cases for all_tests.cpp for test in testcase_dicts: print template % test -# all_tests.cpp +# test_suite.tests.cpp for test in testcase_dicts: print " test_%(testcase_name)s," % test diff --git a/Tennis/cpp/makefile b/Tennis/cpp/makefile new file mode 100644 index 00000000..cfd4c776 --- /dev/null +++ b/Tennis/cpp/makefile @@ -0,0 +1,5 @@ +run.tests.output : run.tests + ./run.tests + +run.tests : *.cpp + g++ -Wall -Werror -O *.cpp -o run.tests \ No newline at end of file diff --git a/Tennis/cpp/tennis1.cc b/Tennis/cpp/tennis1.cc new file mode 100644 index 00000000..10ff0805 --- /dev/null +++ b/Tennis/cpp/tennis1.cc @@ -0,0 +1,61 @@ +#include + +const std::string tennis_score(int p1Score, int p2Score) { + std::string score = ""; + int tempScore=0; + if (p1Score==p2Score) + { + switch (p1Score) + { + case 0: + score = "Love-All"; + break; + case 1: + score = "Fifteen-All"; + break; + case 2: + score = "Thirty-All"; + break; + case 3: + score = "Deuce"; + break; + default: + score = "Deuce"; + break; + + } + } + else if (p1Score>=4 || p2Score>=4) + { + int minusResult = p1Score-p2Score; + if (minusResult==1) score ="Advantage player1"; + else if (minusResult ==-1) score ="Advantage player2"; + else if (minusResult>=2) score = "Win for player1"; + else score ="Win for player2"; + } + else + { + for (int i=1; i<3; i++) + { + if (i==1) tempScore = p1Score; + else { score+="-"; tempScore = p2Score;} + switch(tempScore) + { + case 0: + score+="Love"; + break; + case 1: + score+="Fifteen"; + break; + case 2: + score+="Thirty"; + break; + case 3: + score+="Forty"; + break; + } + } + } + return score; + +} diff --git a/Tennis/cpp/tennis2.cc b/Tennis/cpp/tennis2.cc new file mode 100644 index 00000000..3735dfeb --- /dev/null +++ b/Tennis/cpp/tennis2.cc @@ -0,0 +1,92 @@ +#include + +const std::string tennis_score(int p1Score, int p2Score) { + std::string score = ""; + std::string P1res = ""; + std::string P2res = ""; + if (p1Score == p2Score && p1Score < 4) + { + if (p1Score==0) + score = "Love"; + if (p1Score==1) + score = "Fifteen"; + if (p1Score==2) + score = "Thirty"; + if (p1Score==3) + score = "Forty"; + score += "-All"; + } + if (p1Score==p2Score && p1Score>2) + score = "Deuce"; + + if (p1Score > 0 && p2Score==0) + { + if (p1Score==1) + P1res = "Fifteen"; + if (p1Score==2) + P1res = "Thirty"; + if (p1Score==3) + P1res = "Forty"; + + P2res = "Love"; + score = P1res + "-" + P2res; + } + if (p2Score > 0 && p1Score==0) + { + if (p2Score==1) + P2res = "Fifteen"; + if (p2Score==2) + P2res = "Thirty"; + if (p2Score==3) + P2res = "Forty"; + + P1res = "Love"; + score = P1res + "-" + P2res; + } + + if (p1Score>p2Score && p1Score < 4) + { + if (p1Score==2) + P1res="Thirty"; + if (p1Score==3) + P1res="Forty"; + if (p2Score==1) + P2res="Fifteen"; + if (p2Score==2) + P2res="Thirty"; + score = P1res + "-" + P2res; + } + if (p2Score>p1Score && p2Score < 4) + { + if (p2Score==2) + P2res="Thirty"; + if (p2Score==3) + P2res="Forty"; + if (p1Score==1) + P1res="Fifteen"; + if (p1Score==2) + P1res="Thirty"; + score = P1res + "-" + P2res; + } + + if (p1Score > p2Score && p2Score >= 3) + { + score = "Advantage player1"; + } + + if (p2Score > p1Score && p1Score >= 3) + { + score = "Advantage player2"; + } + + if (p1Score>=4 && p2Score>=0 && (p1Score-p2Score)>=2) + { + score = "Win for player1"; + } + if (p2Score>=4 && p1Score>=0 && (p2Score-p1Score)>=2) + { + score = "Win for player2"; + } + return score; + +} diff --git a/Tennis/cpp/tennis3.cc b/Tennis/cpp/tennis3.cc new file mode 100644 index 00000000..cc87f969 --- /dev/null +++ b/Tennis/cpp/tennis3.cc @@ -0,0 +1,17 @@ +#include + +const std::string tennis_score(int p1, int p2) { + std::string s; + std::string p1N = "player1"; + std::string p2N = "player2"; + if (p1 < 4 && p2 < 4 && !(p1 == 3 && p2 == 3)) { + std::string p[4] = {"Love", "Fifteen", "Thirty", "Forty"}; + s = p[p1]; + return (p1 == p2) ? s + "-All" : s + "-" + p[p2]; + } else { + if (p1 == p2) + return "Deuce"; + s = p1 > p2 ? p1N : p2N; + return ((p1-p2)*(p1-p2) == 1) ? "Advantage " + s : "Win for " + s; + } +} \ No newline at end of file diff --git a/Tennis/cpp/test_suite.tests.cpp b/Tennis/cpp/test_suite.tests.cpp new file mode 100644 index 00000000..cdadddfc --- /dev/null +++ b/Tennis/cpp/test_suite.tests.cpp @@ -0,0 +1,55 @@ +#include "all_tests.hpp" +#include +#include + +typedef void test(); + +static test * tests[ ] = +{ + test_LoveAll_0_0, + test_FifteenAll_1_1, + test_ThirtyAll_2_2, + test_Deuce_3_3, + test_Deuce_4_4, + test_FifteenLove_1_0, + test_LoveFifteen_0_1, + test_ThirtyLove_2_0, + test_LoveThirty_0_2, + test_FortyLove_3_0, + test_LoveForty_0_3, + test_Winforplayer1_4_0, + test_Winforplayer2_0_4, + test_ThirtyFifteen_2_1, + test_FifteenThirty_1_2, + test_FortyFifteen_3_1, + test_FifteenForty_1_3, + test_Winforplayer1_4_1, + test_Winforplayer2_1_4, + test_FortyThirty_3_2, + test_ThirtyForty_2_3, + test_Winforplayer1_4_2, + test_Winforplayer2_2_4, + test_Advantageplayer1_4_3, + test_Advantageplayer2_3_4, + test_Advantageplayer1_5_4, + test_Advantageplayer2_4_5, + test_Advantageplayer1_15_14, + test_Advantageplayer2_14_15, + test_Winforplayer1_6_4, + test_Winforplayer2_4_6, + test_Winforplayer1_16_14, + test_Winforplayer2_14_16, + static_cast(0), +}; + +int main() +{ + size_t at = 0; + while (tests[at]) + { + tests[at++](); + std::cout << '.'; + } + std::cout << std::endl << at << " tests passed" << std::endl; + return 0; +} From 2e7e36eda1aa567ae2c105fb0910328e533c6447 Mon Sep 17 00:00:00 2001 From: emilybache Date: Mon, 10 Dec 2012 14:49:40 +0100 Subject: [PATCH 063/634] tweak of url, so instructions will be correct --- Tennis/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tennis/README.md b/Tennis/README.md index 6c5a7745..89acad8e 100644 --- a/Tennis/README.md +++ b/Tennis/README.md @@ -24,4 +24,4 @@ As an alternative to downloading the code, click one of the links below to creat - [Python](http://cyber-dojo.com/forker/fork/FFEB8EE18C?avatar=cheetah&tag=3) - [Ruby](http://cyber-dojo.com/forker/fork/9197D6B12C?avatar=cheetah&tag=3) - [Java](http://cyber-dojo.com/forker/fork/B22DCD17C3?avatar=buffalo&tag=11) -- [C++](http://cyber-dojo.com/forker/fork/CD6FC41518?avatar=deer&tag=44) \ No newline at end of file +- [C++](http://cyber-dojo.com/forker/fork/CD6FC41518?avatar=deer&tag=45) \ No newline at end of file From 4bb96591902ba03890c6e27147e4cc5de2500bff Mon Sep 17 00:00:00 2001 From: Marco Emrich Date: Mon, 7 Jan 2013 02:53:21 +0100 Subject: [PATCH 064/634] added js version of Gilded Rose from git@github.com:guyroyse/gilded-rose-javascript.git --- GildedRose/js/.gitignore | 3 + GildedRose/js/README.md | 61 + GildedRose/js/SpecRunner.html | 56 + GildedRose/js/lib/jasmine-1.1.0/MIT.LICENSE | 20 + .../js/lib/jasmine-1.1.0/jasmine-html.js | 190 + GildedRose/js/lib/jasmine-1.1.0/jasmine.css | 166 + GildedRose/js/lib/jasmine-1.1.0/jasmine.js | 2476 +++++ .../js/lib/jasmine-1.1.0/jasmine_favicon.png | Bin 0 -> 905 bytes GildedRose/js/lib/jasmine-ajax/mock-ajax.js | 207 + .../jasmine-jquery-1.3.1.js | 288 + .../js/lib/jquery-1.7.1/jquery-1.7.1.js | 9266 +++++++++++++++++ GildedRose/js/spec/gilded_rose_spec.js | 7 + GildedRose/js/src/gilded_rose.js | 62 + 13 files changed, 12802 insertions(+) create mode 100644 GildedRose/js/.gitignore create mode 100644 GildedRose/js/README.md create mode 100644 GildedRose/js/SpecRunner.html create mode 100644 GildedRose/js/lib/jasmine-1.1.0/MIT.LICENSE create mode 100644 GildedRose/js/lib/jasmine-1.1.0/jasmine-html.js create mode 100644 GildedRose/js/lib/jasmine-1.1.0/jasmine.css create mode 100644 GildedRose/js/lib/jasmine-1.1.0/jasmine.js create mode 100644 GildedRose/js/lib/jasmine-1.1.0/jasmine_favicon.png create mode 100644 GildedRose/js/lib/jasmine-ajax/mock-ajax.js create mode 100644 GildedRose/js/lib/jasmine-jquery-1.3.1/jasmine-jquery-1.3.1.js create mode 100644 GildedRose/js/lib/jquery-1.7.1/jquery-1.7.1.js create mode 100644 GildedRose/js/spec/gilded_rose_spec.js create mode 100644 GildedRose/js/src/gilded_rose.js diff --git a/GildedRose/js/.gitignore b/GildedRose/js/.gitignore new file mode 100644 index 00000000..8447f276 --- /dev/null +++ b/GildedRose/js/.gitignore @@ -0,0 +1,3 @@ +*.swp +*~ +*.bak diff --git a/GildedRose/js/README.md b/GildedRose/js/README.md new file mode 100644 index 00000000..76868f59 --- /dev/null +++ b/GildedRose/js/README.md @@ -0,0 +1,61 @@ +If you want to get cracking on the JavaScript source then do this: + + git clone git@github.com:guyroyse/gilded-rose-javascript.git + +Hi and welcome to team Gilded Rose. + +As you know, we are a small inn with a prime location in a prominent city ran +by a friendly innkeeper named Allison. We also buy and sell only the finest +goods. Unfortunately, our goods are constantly degrading in quality as they +approach their sell by date. + +We have a system in place that updates our inventory for us. It was developed +by a no-nonsense type named Leeroy, who has moved on to new adventures. Your +task is to add the new feature to our system so that we can begin selling a +new category of items. + +First an introduction to our system: + + - All items have a *sell_in* value which denotes the number of days we have to + sell the item + + - All items have a *quality* value which denotes how valuable the item is + + - At the end of each day our system lowers both values for every item + +Pretty simple, right? Well this is where it gets interesting: + + - Once the *sell_in* days is less then zero, *quality* degrades twice as fast + + - The *quality* of an item is never negative + + - "Aged Brie" actually increases in *quality* the older it gets + + - The *quality* of an item is never more than 50 + + - "Sulfuras", being a legendary item, never has to be sold nor does it + decrease in *quality* + + - "Backstage passes", like aged brie, increases in *quality* as it's *sell_in* + value decreases; *quality* increases by 2 when there are 10 days or less + and by 3 when there are 5 days or less but *quality* drops to 0 after the + concert + +We have recently signed a supplier of conjured items. This requires an update +to our system: + + - "Conjured" items degrade in *quality* twice as fast as normal items + +Feel free to make any changes to the *update_quality* method and add any new +code as long as everything still works correctly. However, do not alter the +*Item* class or *items* property as those belong to the goblin in the corner +who will insta-rage and one-shot you as he doesn't believe in shared code +ownership. + +Just for clarification, an item can never have its *quality* increase above 50, +however "Sulfuras" is a legendary item and as such its *quality* is 80 and it +never alters. + +Sources: + + diff --git a/GildedRose/js/SpecRunner.html b/GildedRose/js/SpecRunner.html new file mode 100644 index 00000000..ba3e60d8 --- /dev/null +++ b/GildedRose/js/SpecRunner.html @@ -0,0 +1,56 @@ + + + + +Jasmine Spec Runner + + + + + + + + + + + + + + + + + + + + + + + diff --git a/GildedRose/js/lib/jasmine-1.1.0/MIT.LICENSE b/GildedRose/js/lib/jasmine-1.1.0/MIT.LICENSE new file mode 100644 index 00000000..7c435baa --- /dev/null +++ b/GildedRose/js/lib/jasmine-1.1.0/MIT.LICENSE @@ -0,0 +1,20 @@ +Copyright (c) 2008-2011 Pivotal Labs + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/GildedRose/js/lib/jasmine-1.1.0/jasmine-html.js b/GildedRose/js/lib/jasmine-1.1.0/jasmine-html.js new file mode 100644 index 00000000..73834010 --- /dev/null +++ b/GildedRose/js/lib/jasmine-1.1.0/jasmine-html.js @@ -0,0 +1,190 @@ +jasmine.TrivialReporter = function(doc) { + this.document = doc || document; + this.suiteDivs = {}; + this.logRunningSpecs = false; +}; + +jasmine.TrivialReporter.prototype.createDom = function(type, attrs, childrenVarArgs) { + var el = document.createElement(type); + + for (var i = 2; i < arguments.length; i++) { + var child = arguments[i]; + + if (typeof child === 'string') { + el.appendChild(document.createTextNode(child)); + } else { + if (child) { el.appendChild(child); } + } + } + + for (var attr in attrs) { + if (attr == "className") { + el[attr] = attrs[attr]; + } else { + el.setAttribute(attr, attrs[attr]); + } + } + + return el; +}; + +jasmine.TrivialReporter.prototype.reportRunnerStarting = function(runner) { + var showPassed, showSkipped; + + this.outerDiv = this.createDom('div', { className: 'jasmine_reporter' }, + this.createDom('div', { className: 'banner' }, + this.createDom('div', { className: 'logo' }, + this.createDom('span', { className: 'title' }, "Jasmine"), + this.createDom('span', { className: 'version' }, runner.env.versionString())), + this.createDom('div', { className: 'options' }, + "Show ", + showPassed = this.createDom('input', { id: "__jasmine_TrivialReporter_showPassed__", type: 'checkbox' }), + this.createDom('label', { "for": "__jasmine_TrivialReporter_showPassed__" }, " passed "), + showSkipped = this.createDom('input', { id: "__jasmine_TrivialReporter_showSkipped__", type: 'checkbox' }), + this.createDom('label', { "for": "__jasmine_TrivialReporter_showSkipped__" }, " skipped") + ) + ), + + this.runnerDiv = this.createDom('div', { className: 'runner running' }, + this.createDom('a', { className: 'run_spec', href: '?' }, "run all"), + this.runnerMessageSpan = this.createDom('span', {}, "Running..."), + this.finishedAtSpan = this.createDom('span', { className: 'finished-at' }, "")) + ); + + this.document.body.appendChild(this.outerDiv); + + var suites = runner.suites(); + for (var i = 0; i < suites.length; i++) { + var suite = suites[i]; + var suiteDiv = this.createDom('div', { className: 'suite' }, + this.createDom('a', { className: 'run_spec', href: '?spec=' + encodeURIComponent(suite.getFullName()) }, "run"), + this.createDom('a', { className: 'description', href: '?spec=' + encodeURIComponent(suite.getFullName()) }, suite.description)); + this.suiteDivs[suite.id] = suiteDiv; + var parentDiv = this.outerDiv; + if (suite.parentSuite) { + parentDiv = this.suiteDivs[suite.parentSuite.id]; + } + parentDiv.appendChild(suiteDiv); + } + + this.startedAt = new Date(); + + var self = this; + showPassed.onclick = function(evt) { + if (showPassed.checked) { + self.outerDiv.className += ' show-passed'; + } else { + self.outerDiv.className = self.outerDiv.className.replace(/ show-passed/, ''); + } + }; + + showSkipped.onclick = function(evt) { + if (showSkipped.checked) { + self.outerDiv.className += ' show-skipped'; + } else { + self.outerDiv.className = self.outerDiv.className.replace(/ show-skipped/, ''); + } + }; +}; + +jasmine.TrivialReporter.prototype.reportRunnerResults = function(runner) { + var results = runner.results(); + var className = (results.failedCount > 0) ? "runner failed" : "runner passed"; + this.runnerDiv.setAttribute("class", className); + //do it twice for IE + this.runnerDiv.setAttribute("className", className); + var specs = runner.specs(); + var specCount = 0; + for (var i = 0; i < specs.length; i++) { + if (this.specFilter(specs[i])) { + specCount++; + } + } + var message = "" + specCount + " spec" + (specCount == 1 ? "" : "s" ) + ", " + results.failedCount + " failure" + ((results.failedCount == 1) ? "" : "s"); + message += " in " + ((new Date().getTime() - this.startedAt.getTime()) / 1000) + "s"; + this.runnerMessageSpan.replaceChild(this.createDom('a', { className: 'description', href: '?'}, message), this.runnerMessageSpan.firstChild); + + this.finishedAtSpan.appendChild(document.createTextNode("Finished at " + new Date().toString())); +}; + +jasmine.TrivialReporter.prototype.reportSuiteResults = function(suite) { + var results = suite.results(); + var status = results.passed() ? 'passed' : 'failed'; + if (results.totalCount === 0) { // todo: change this to check results.skipped + status = 'skipped'; + } + this.suiteDivs[suite.id].className += " " + status; +}; + +jasmine.TrivialReporter.prototype.reportSpecStarting = function(spec) { + if (this.logRunningSpecs) { + this.log('>> Jasmine Running ' + spec.suite.description + ' ' + spec.description + '...'); + } +}; + +jasmine.TrivialReporter.prototype.reportSpecResults = function(spec) { + var results = spec.results(); + var status = results.passed() ? 'passed' : 'failed'; + if (results.skipped) { + status = 'skipped'; + } + var specDiv = this.createDom('div', { className: 'spec ' + status }, + this.createDom('a', { className: 'run_spec', href: '?spec=' + encodeURIComponent(spec.getFullName()) }, "run"), + this.createDom('a', { + className: 'description', + href: '?spec=' + encodeURIComponent(spec.getFullName()), + title: spec.getFullName() + }, spec.description)); + + + var resultItems = results.getItems(); + var messagesDiv = this.createDom('div', { className: 'messages' }); + for (var i = 0; i < resultItems.length; i++) { + var result = resultItems[i]; + + if (result.type == 'log') { + messagesDiv.appendChild(this.createDom('div', {className: 'resultMessage log'}, result.toString())); + } else if (result.type == 'expect' && result.passed && !result.passed()) { + messagesDiv.appendChild(this.createDom('div', {className: 'resultMessage fail'}, result.message)); + + if (result.trace.stack) { + messagesDiv.appendChild(this.createDom('div', {className: 'stackTrace'}, result.trace.stack)); + } + } + } + + if (messagesDiv.childNodes.length > 0) { + specDiv.appendChild(messagesDiv); + } + + this.suiteDivs[spec.suite.id].appendChild(specDiv); +}; + +jasmine.TrivialReporter.prototype.log = function() { + var console = jasmine.getGlobal().console; + if (console && console.log) { + if (console.log.apply) { + console.log.apply(console, arguments); + } else { + console.log(arguments); // ie fix: console.log.apply doesn't exist on ie + } + } +}; + +jasmine.TrivialReporter.prototype.getLocation = function() { + return this.document.location; +}; + +jasmine.TrivialReporter.prototype.specFilter = function(spec) { + var paramMap = {}; + var params = this.getLocation().search.substring(1).split('&'); + for (var i = 0; i < params.length; i++) { + var p = params[i].split('='); + paramMap[decodeURIComponent(p[0])] = decodeURIComponent(p[1]); + } + + if (!paramMap.spec) { + return true; + } + return spec.getFullName().indexOf(paramMap.spec) === 0; +}; diff --git a/GildedRose/js/lib/jasmine-1.1.0/jasmine.css b/GildedRose/js/lib/jasmine-1.1.0/jasmine.css new file mode 100644 index 00000000..6583fe7c --- /dev/null +++ b/GildedRose/js/lib/jasmine-1.1.0/jasmine.css @@ -0,0 +1,166 @@ +body { + font-family: "Helvetica Neue Light", "Lucida Grande", "Calibri", "Arial", sans-serif; +} + + +.jasmine_reporter a:visited, .jasmine_reporter a { + color: #303; +} + +.jasmine_reporter a:hover, .jasmine_reporter a:active { + color: blue; +} + +.run_spec { + float:right; + padding-right: 5px; + font-size: .8em; + text-decoration: none; +} + +.jasmine_reporter { + margin: 0 5px; +} + +.banner { + color: #303; + background-color: #fef; + padding: 5px; +} + +.logo { + float: left; + font-size: 1.1em; + padding-left: 5px; +} + +.logo .version { + font-size: .6em; + padding-left: 1em; +} + +.runner.running { + background-color: yellow; +} + + +.options { + text-align: right; + font-size: .8em; +} + + + + +.suite { + border: 1px outset gray; + margin: 5px 0; + padding-left: 1em; +} + +.suite .suite { + margin: 5px; +} + +.suite.passed { + background-color: #dfd; +} + +.suite.failed { + background-color: #fdd; +} + +.spec { + margin: 5px; + padding-left: 1em; + clear: both; +} + +.spec.failed, .spec.passed, .spec.skipped { + padding-bottom: 5px; + border: 1px solid gray; +} + +.spec.failed { + background-color: #fbb; + border-color: red; +} + +.spec.passed { + background-color: #bfb; + border-color: green; +} + +.spec.skipped { + background-color: #bbb; +} + +.messages { + border-left: 1px dashed gray; + padding-left: 1em; + padding-right: 1em; +} + +.passed { + background-color: #cfc; + display: none; +} + +.failed { + background-color: #fbb; +} + +.skipped { + color: #777; + background-color: #eee; + display: none; +} + + +/*.resultMessage {*/ + /*white-space: pre;*/ +/*}*/ + +.resultMessage span.result { + display: block; + line-height: 2em; + color: black; +} + +.resultMessage .mismatch { + color: black; +} + +.stackTrace { + white-space: pre; + font-size: .8em; + margin-left: 10px; + max-height: 5em; + overflow: auto; + border: 1px inset red; + padding: 1em; + background: #eef; +} + +.finished-at { + padding-left: 1em; + font-size: .6em; +} + +.show-passed .passed, +.show-skipped .skipped { + display: block; +} + + +#jasmine_content { + position:fixed; + right: 100%; +} + +.runner { + border: 1px solid gray; + display: block; + margin: 5px 0; + padding: 2px 0 2px 10px; +} diff --git a/GildedRose/js/lib/jasmine-1.1.0/jasmine.js b/GildedRose/js/lib/jasmine-1.1.0/jasmine.js new file mode 100644 index 00000000..c3d2dc7d --- /dev/null +++ b/GildedRose/js/lib/jasmine-1.1.0/jasmine.js @@ -0,0 +1,2476 @@ +var isCommonJS = typeof window == "undefined"; + +/** + * Top level namespace for Jasmine, a lightweight JavaScript BDD/spec/testing framework. + * + * @namespace + */ +var jasmine = {}; +if (isCommonJS) exports.jasmine = jasmine; +/** + * @private + */ +jasmine.unimplementedMethod_ = function() { + throw new Error("unimplemented method"); +}; + +/** + * Use jasmine.undefined instead of undefined, since undefined is just + * a plain old variable and may be redefined by somebody else. + * + * @private + */ +jasmine.undefined = jasmine.___undefined___; + +/** + * Show diagnostic messages in the console if set to true + * + */ +jasmine.VERBOSE = false; + +/** + * Default interval in milliseconds for event loop yields (e.g. to allow network activity or to refresh the screen with the HTML-based runner). Small values here may result in slow test running. Zero means no updates until all tests have completed. + * + */ +jasmine.DEFAULT_UPDATE_INTERVAL = 250; + +/** + * Default timeout interval in milliseconds for waitsFor() blocks. + */ +jasmine.DEFAULT_TIMEOUT_INTERVAL = 5000; + +jasmine.getGlobal = function() { + function getGlobal() { + return this; + } + + return getGlobal(); +}; + +/** + * Allows for bound functions to be compared. Internal use only. + * + * @ignore + * @private + * @param base {Object} bound 'this' for the function + * @param name {Function} function to find + */ +jasmine.bindOriginal_ = function(base, name) { + var original = base[name]; + if (original.apply) { + return function() { + return original.apply(base, arguments); + }; + } else { + // IE support + return jasmine.getGlobal()[name]; + } +}; + +jasmine.setTimeout = jasmine.bindOriginal_(jasmine.getGlobal(), 'setTimeout'); +jasmine.clearTimeout = jasmine.bindOriginal_(jasmine.getGlobal(), 'clearTimeout'); +jasmine.setInterval = jasmine.bindOriginal_(jasmine.getGlobal(), 'setInterval'); +jasmine.clearInterval = jasmine.bindOriginal_(jasmine.getGlobal(), 'clearInterval'); + +jasmine.MessageResult = function(values) { + this.type = 'log'; + this.values = values; + this.trace = new Error(); // todo: test better +}; + +jasmine.MessageResult.prototype.toString = function() { + var text = ""; + for (var i = 0; i < this.values.length; i++) { + if (i > 0) text += " "; + if (jasmine.isString_(this.values[i])) { + text += this.values[i]; + } else { + text += jasmine.pp(this.values[i]); + } + } + return text; +}; + +jasmine.ExpectationResult = function(params) { + this.type = 'expect'; + this.matcherName = params.matcherName; + this.passed_ = params.passed; + this.expected = params.expected; + this.actual = params.actual; + this.message = this.passed_ ? 'Passed.' : params.message; + + var trace = (params.trace || new Error(this.message)); + this.trace = this.passed_ ? '' : trace; +}; + +jasmine.ExpectationResult.prototype.toString = function () { + return this.message; +}; + +jasmine.ExpectationResult.prototype.passed = function () { + return this.passed_; +}; + +/** + * Getter for the Jasmine environment. Ensures one gets created + */ +jasmine.getEnv = function() { + var env = jasmine.currentEnv_ = jasmine.currentEnv_ || new jasmine.Env(); + return env; +}; + +/** + * @ignore + * @private + * @param value + * @returns {Boolean} + */ +jasmine.isArray_ = function(value) { + return jasmine.isA_("Array", value); +}; + +/** + * @ignore + * @private + * @param value + * @returns {Boolean} + */ +jasmine.isString_ = function(value) { + return jasmine.isA_("String", value); +}; + +/** + * @ignore + * @private + * @param value + * @returns {Boolean} + */ +jasmine.isNumber_ = function(value) { + return jasmine.isA_("Number", value); +}; + +/** + * @ignore + * @private + * @param {String} typeName + * @param value + * @returns {Boolean} + */ +jasmine.isA_ = function(typeName, value) { + return Object.prototype.toString.apply(value) === '[object ' + typeName + ']'; +}; + +/** + * Pretty printer for expecations. Takes any object and turns it into a human-readable string. + * + * @param value {Object} an object to be outputted + * @returns {String} + */ +jasmine.pp = function(value) { + var stringPrettyPrinter = new jasmine.StringPrettyPrinter(); + stringPrettyPrinter.format(value); + return stringPrettyPrinter.string; +}; + +/** + * Returns true if the object is a DOM Node. + * + * @param {Object} obj object to check + * @returns {Boolean} + */ +jasmine.isDomNode = function(obj) { + return obj.nodeType > 0; +}; + +/** + * Returns a matchable 'generic' object of the class type. For use in expecations of type when values don't matter. + * + * @example + * // don't care about which function is passed in, as long as it's a function + * expect(mySpy).toHaveBeenCalledWith(jasmine.any(Function)); + * + * @param {Class} clazz + * @returns matchable object of the type clazz + */ +jasmine.any = function(clazz) { + return new jasmine.Matchers.Any(clazz); +}; + +/** + * Jasmine Spies are test doubles that can act as stubs, spies, fakes or when used in an expecation, mocks. + * + * Spies should be created in test setup, before expectations. They can then be checked, using the standard Jasmine + * expectation syntax. Spies can be checked if they were called or not and what the calling params were. + * + * A Spy has the following fields: wasCalled, callCount, mostRecentCall, and argsForCall (see docs). + * + * Spies are torn down at the end of every spec. + * + * Note: Do not call new jasmine.Spy() directly - a spy must be created using spyOn, jasmine.createSpy or jasmine.createSpyObj. + * + * @example + * // a stub + * var myStub = jasmine.createSpy('myStub'); // can be used anywhere + * + * // spy example + * var foo = { + * not: function(bool) { return !bool; } + * } + * + * // actual foo.not will not be called, execution stops + * spyOn(foo, 'not'); + + // foo.not spied upon, execution will continue to implementation + * spyOn(foo, 'not').andCallThrough(); + * + * // fake example + * var foo = { + * not: function(bool) { return !bool; } + * } + * + * // foo.not(val) will return val + * spyOn(foo, 'not').andCallFake(function(value) {return value;}); + * + * // mock example + * foo.not(7 == 7); + * expect(foo.not).toHaveBeenCalled(); + * expect(foo.not).toHaveBeenCalledWith(true); + * + * @constructor + * @see spyOn, jasmine.createSpy, jasmine.createSpyObj + * @param {String} name + */ +jasmine.Spy = function(name) { + /** + * The name of the spy, if provided. + */ + this.identity = name || 'unknown'; + /** + * Is this Object a spy? + */ + this.isSpy = true; + /** + * The actual function this spy stubs. + */ + this.plan = function() { + }; + /** + * Tracking of the most recent call to the spy. + * @example + * var mySpy = jasmine.createSpy('foo'); + * mySpy(1, 2); + * mySpy.mostRecentCall.args = [1, 2]; + */ + this.mostRecentCall = {}; + + /** + * Holds arguments for each call to the spy, indexed by call count + * @example + * var mySpy = jasmine.createSpy('foo'); + * mySpy(1, 2); + * mySpy(7, 8); + * mySpy.mostRecentCall.args = [7, 8]; + * mySpy.argsForCall[0] = [1, 2]; + * mySpy.argsForCall[1] = [7, 8]; + */ + this.argsForCall = []; + this.calls = []; +}; + +/** + * Tells a spy to call through to the actual implemenatation. + * + * @example + * var foo = { + * bar: function() { // do some stuff } + * } + * + * // defining a spy on an existing property: foo.bar + * spyOn(foo, 'bar').andCallThrough(); + */ +jasmine.Spy.prototype.andCallThrough = function() { + this.plan = this.originalValue; + return this; +}; + +/** + * For setting the return value of a spy. + * + * @example + * // defining a spy from scratch: foo() returns 'baz' + * var foo = jasmine.createSpy('spy on foo').andReturn('baz'); + * + * // defining a spy on an existing property: foo.bar() returns 'baz' + * spyOn(foo, 'bar').andReturn('baz'); + * + * @param {Object} value + */ +jasmine.Spy.prototype.andReturn = function(value) { + this.plan = function() { + return value; + }; + return this; +}; + +/** + * For throwing an exception when a spy is called. + * + * @example + * // defining a spy from scratch: foo() throws an exception w/ message 'ouch' + * var foo = jasmine.createSpy('spy on foo').andThrow('baz'); + * + * // defining a spy on an existing property: foo.bar() throws an exception w/ message 'ouch' + * spyOn(foo, 'bar').andThrow('baz'); + * + * @param {String} exceptionMsg + */ +jasmine.Spy.prototype.andThrow = function(exceptionMsg) { + this.plan = function() { + throw exceptionMsg; + }; + return this; +}; + +/** + * Calls an alternate implementation when a spy is called. + * + * @example + * var baz = function() { + * // do some stuff, return something + * } + * // defining a spy from scratch: foo() calls the function baz + * var foo = jasmine.createSpy('spy on foo').andCall(baz); + * + * // defining a spy on an existing property: foo.bar() calls an anonymnous function + * spyOn(foo, 'bar').andCall(function() { return 'baz';} ); + * + * @param {Function} fakeFunc + */ +jasmine.Spy.prototype.andCallFake = function(fakeFunc) { + this.plan = fakeFunc; + return this; +}; + +/** + * Resets all of a spy's the tracking variables so that it can be used again. + * + * @example + * spyOn(foo, 'bar'); + * + * foo.bar(); + * + * expect(foo.bar.callCount).toEqual(1); + * + * foo.bar.reset(); + * + * expect(foo.bar.callCount).toEqual(0); + */ +jasmine.Spy.prototype.reset = function() { + this.wasCalled = false; + this.callCount = 0; + this.argsForCall = []; + this.calls = []; + this.mostRecentCall = {}; +}; + +jasmine.createSpy = function(name) { + + var spyObj = function() { + spyObj.wasCalled = true; + spyObj.callCount++; + var args = jasmine.util.argsToArray(arguments); + spyObj.mostRecentCall.object = this; + spyObj.mostRecentCall.args = args; + spyObj.argsForCall.push(args); + spyObj.calls.push({object: this, args: args}); + return spyObj.plan.apply(this, arguments); + }; + + var spy = new jasmine.Spy(name); + + for (var prop in spy) { + spyObj[prop] = spy[prop]; + } + + spyObj.reset(); + + return spyObj; +}; + +/** + * Determines whether an object is a spy. + * + * @param {jasmine.Spy|Object} putativeSpy + * @returns {Boolean} + */ +jasmine.isSpy = function(putativeSpy) { + return putativeSpy && putativeSpy.isSpy; +}; + +/** + * Creates a more complicated spy: an Object that has every property a function that is a spy. Used for stubbing something + * large in one call. + * + * @param {String} baseName name of spy class + * @param {Array} methodNames array of names of methods to make spies + */ +jasmine.createSpyObj = function(baseName, methodNames) { + if (!jasmine.isArray_(methodNames) || methodNames.length === 0) { + throw new Error('createSpyObj requires a non-empty array of method names to create spies for'); + } + var obj = {}; + for (var i = 0; i < methodNames.length; i++) { + obj[methodNames[i]] = jasmine.createSpy(baseName + '.' + methodNames[i]); + } + return obj; +}; + +/** + * All parameters are pretty-printed and concatenated together, then written to the current spec's output. + * + * Be careful not to leave calls to jasmine.log in production code. + */ +jasmine.log = function() { + var spec = jasmine.getEnv().currentSpec; + spec.log.apply(spec, arguments); +}; + +/** + * Function that installs a spy on an existing object's method name. Used within a Spec to create a spy. + * + * @example + * // spy example + * var foo = { + * not: function(bool) { return !bool; } + * } + * spyOn(foo, 'not'); // actual foo.not will not be called, execution stops + * + * @see jasmine.createSpy + * @param obj + * @param methodName + * @returns a Jasmine spy that can be chained with all spy methods + */ +var spyOn = function(obj, methodName) { + return jasmine.getEnv().currentSpec.spyOn(obj, methodName); +}; +if (isCommonJS) exports.spyOn = spyOn; + +/** + * Creates a Jasmine spec that will be added to the current suite. + * + * // TODO: pending tests + * + * @example + * it('should be true', function() { + * expect(true).toEqual(true); + * }); + * + * @param {String} desc description of this specification + * @param {Function} func defines the preconditions and expectations of the spec + */ +var it = function(desc, func) { + return jasmine.getEnv().it(desc, func); +}; +if (isCommonJS) exports.it = it; + +/** + * Creates a disabled Jasmine spec. + * + * A convenience method that allows existing specs to be disabled temporarily during development. + * + * @param {String} desc description of this specification + * @param {Function} func defines the preconditions and expectations of the spec + */ +var xit = function(desc, func) { + return jasmine.getEnv().xit(desc, func); +}; +if (isCommonJS) exports.xit = xit; + +/** + * Starts a chain for a Jasmine expectation. + * + * It is passed an Object that is the actual value and should chain to one of the many + * jasmine.Matchers functions. + * + * @param {Object} actual Actual value to test against and expected value + */ +var expect = function(actual) { + return jasmine.getEnv().currentSpec.expect(actual); +}; +if (isCommonJS) exports.expect = expect; + +/** + * Defines part of a jasmine spec. Used in cominbination with waits or waitsFor in asynchrnous specs. + * + * @param {Function} func Function that defines part of a jasmine spec. + */ +var runs = function(func) { + jasmine.getEnv().currentSpec.runs(func); +}; +if (isCommonJS) exports.runs = runs; + +/** + * Waits a fixed time period before moving to the next block. + * + * @deprecated Use waitsFor() instead + * @param {Number} timeout milliseconds to wait + */ +var waits = function(timeout) { + jasmine.getEnv().currentSpec.waits(timeout); +}; +if (isCommonJS) exports.waits = waits; + +/** + * Waits for the latchFunction to return true before proceeding to the next block. + * + * @param {Function} latchFunction + * @param {String} optional_timeoutMessage + * @param {Number} optional_timeout + */ +var waitsFor = function(latchFunction, optional_timeoutMessage, optional_timeout) { + jasmine.getEnv().currentSpec.waitsFor.apply(jasmine.getEnv().currentSpec, arguments); +}; +if (isCommonJS) exports.waitsFor = waitsFor; + +/** + * A function that is called before each spec in a suite. + * + * Used for spec setup, including validating assumptions. + * + * @param {Function} beforeEachFunction + */ +var beforeEach = function(beforeEachFunction) { + jasmine.getEnv().beforeEach(beforeEachFunction); +}; +if (isCommonJS) exports.beforeEach = beforeEach; + +/** + * A function that is called after each spec in a suite. + * + * Used for restoring any state that is hijacked during spec execution. + * + * @param {Function} afterEachFunction + */ +var afterEach = function(afterEachFunction) { + jasmine.getEnv().afterEach(afterEachFunction); +}; +if (isCommonJS) exports.afterEach = afterEach; + +/** + * Defines a suite of specifications. + * + * Stores the description and all defined specs in the Jasmine environment as one suite of specs. Variables declared + * are accessible by calls to beforeEach, it, and afterEach. Describe blocks can be nested, allowing for specialization + * of setup in some tests. + * + * @example + * // TODO: a simple suite + * + * // TODO: a simple suite with a nested describe block + * + * @param {String} description A string, usually the class under test. + * @param {Function} specDefinitions function that defines several specs. + */ +var describe = function(description, specDefinitions) { + return jasmine.getEnv().describe(description, specDefinitions); +}; +if (isCommonJS) exports.describe = describe; + +/** + * Disables a suite of specifications. Used to disable some suites in a file, or files, temporarily during development. + * + * @param {String} description A string, usually the class under test. + * @param {Function} specDefinitions function that defines several specs. + */ +var xdescribe = function(description, specDefinitions) { + return jasmine.getEnv().xdescribe(description, specDefinitions); +}; +if (isCommonJS) exports.xdescribe = xdescribe; + + +// Provide the XMLHttpRequest class for IE 5.x-6.x: +jasmine.XmlHttpRequest = (typeof XMLHttpRequest == "undefined") ? function() { + function tryIt(f) { + try { + return f(); + } catch(e) { + } + return null; + } + + var xhr = tryIt(function() { + return new ActiveXObject("Msxml2.XMLHTTP.6.0"); + }) || + tryIt(function() { + return new ActiveXObject("Msxml2.XMLHTTP.3.0"); + }) || + tryIt(function() { + return new ActiveXObject("Msxml2.XMLHTTP"); + }) || + tryIt(function() { + return new ActiveXObject("Microsoft.XMLHTTP"); + }); + + if (!xhr) throw new Error("This browser does not support XMLHttpRequest."); + + return xhr; +} : XMLHttpRequest; +/** + * @namespace + */ +jasmine.util = {}; + +/** + * Declare that a child class inherit it's prototype from the parent class. + * + * @private + * @param {Function} childClass + * @param {Function} parentClass + */ +jasmine.util.inherit = function(childClass, parentClass) { + /** + * @private + */ + var subclass = function() { + }; + subclass.prototype = parentClass.prototype; + childClass.prototype = new subclass(); +}; + +jasmine.util.formatException = function(e) { + var lineNumber; + if (e.line) { + lineNumber = e.line; + } + else if (e.lineNumber) { + lineNumber = e.lineNumber; + } + + var file; + + if (e.sourceURL) { + file = e.sourceURL; + } + else if (e.fileName) { + file = e.fileName; + } + + var message = (e.name && e.message) ? (e.name + ': ' + e.message) : e.toString(); + + if (file && lineNumber) { + message += ' in ' + file + ' (line ' + lineNumber + ')'; + } + + return message; +}; + +jasmine.util.htmlEscape = function(str) { + if (!str) return str; + return str.replace(/&/g, '&') + .replace(//g, '>'); +}; + +jasmine.util.argsToArray = function(args) { + var arrayOfArgs = []; + for (var i = 0; i < args.length; i++) arrayOfArgs.push(args[i]); + return arrayOfArgs; +}; + +jasmine.util.extend = function(destination, source) { + for (var property in source) destination[property] = source[property]; + return destination; +}; + +/** + * Environment for Jasmine + * + * @constructor + */ +jasmine.Env = function() { + this.currentSpec = null; + this.currentSuite = null; + this.currentRunner_ = new jasmine.Runner(this); + + this.reporter = new jasmine.MultiReporter(); + + this.updateInterval = jasmine.DEFAULT_UPDATE_INTERVAL; + this.defaultTimeoutInterval = jasmine.DEFAULT_TIMEOUT_INTERVAL; + this.lastUpdate = 0; + this.specFilter = function() { + return true; + }; + + this.nextSpecId_ = 0; + this.nextSuiteId_ = 0; + this.equalityTesters_ = []; + + // wrap matchers + this.matchersClass = function() { + jasmine.Matchers.apply(this, arguments); + }; + jasmine.util.inherit(this.matchersClass, jasmine.Matchers); + + jasmine.Matchers.wrapInto_(jasmine.Matchers.prototype, this.matchersClass); +}; + + +jasmine.Env.prototype.setTimeout = jasmine.setTimeout; +jasmine.Env.prototype.clearTimeout = jasmine.clearTimeout; +jasmine.Env.prototype.setInterval = jasmine.setInterval; +jasmine.Env.prototype.clearInterval = jasmine.clearInterval; + +/** + * @returns an object containing jasmine version build info, if set. + */ +jasmine.Env.prototype.version = function () { + if (jasmine.version_) { + return jasmine.version_; + } else { + throw new Error('Version not set'); + } +}; + +/** + * @returns string containing jasmine version build info, if set. + */ +jasmine.Env.prototype.versionString = function() { + if (!jasmine.version_) { + return "version unknown"; + } + + var version = this.version(); + var versionString = version.major + "." + version.minor + "." + version.build; + if (version.release_candidate) { + versionString += ".rc" + version.release_candidate; + } + versionString += " revision " + version.revision; + return versionString; +}; + +/** + * @returns a sequential integer starting at 0 + */ +jasmine.Env.prototype.nextSpecId = function () { + return this.nextSpecId_++; +}; + +/** + * @returns a sequential integer starting at 0 + */ +jasmine.Env.prototype.nextSuiteId = function () { + return this.nextSuiteId_++; +}; + +/** + * Register a reporter to receive status updates from Jasmine. + * @param {jasmine.Reporter} reporter An object which will receive status updates. + */ +jasmine.Env.prototype.addReporter = function(reporter) { + this.reporter.addReporter(reporter); +}; + +jasmine.Env.prototype.execute = function() { + this.currentRunner_.execute(); +}; + +jasmine.Env.prototype.describe = function(description, specDefinitions) { + var suite = new jasmine.Suite(this, description, specDefinitions, this.currentSuite); + + var parentSuite = this.currentSuite; + if (parentSuite) { + parentSuite.add(suite); + } else { + this.currentRunner_.add(suite); + } + + this.currentSuite = suite; + + var declarationError = null; + try { + specDefinitions.call(suite); + } catch(e) { + declarationError = e; + } + + if (declarationError) { + this.it("encountered a declaration exception", function() { + throw declarationError; + }); + } + + this.currentSuite = parentSuite; + + return suite; +}; + +jasmine.Env.prototype.beforeEach = function(beforeEachFunction) { + if (this.currentSuite) { + this.currentSuite.beforeEach(beforeEachFunction); + } else { + this.currentRunner_.beforeEach(beforeEachFunction); + } +}; + +jasmine.Env.prototype.currentRunner = function () { + return this.currentRunner_; +}; + +jasmine.Env.prototype.afterEach = function(afterEachFunction) { + if (this.currentSuite) { + this.currentSuite.afterEach(afterEachFunction); + } else { + this.currentRunner_.afterEach(afterEachFunction); + } + +}; + +jasmine.Env.prototype.xdescribe = function(desc, specDefinitions) { + return { + execute: function() { + } + }; +}; + +jasmine.Env.prototype.it = function(description, func) { + var spec = new jasmine.Spec(this, this.currentSuite, description); + this.currentSuite.add(spec); + this.currentSpec = spec; + + if (func) { + spec.runs(func); + } + + return spec; +}; + +jasmine.Env.prototype.xit = function(desc, func) { + return { + id: this.nextSpecId(), + runs: function() { + } + }; +}; + +jasmine.Env.prototype.compareObjects_ = function(a, b, mismatchKeys, mismatchValues) { + if (a.__Jasmine_been_here_before__ === b && b.__Jasmine_been_here_before__ === a) { + return true; + } + + a.__Jasmine_been_here_before__ = b; + b.__Jasmine_been_here_before__ = a; + + var hasKey = function(obj, keyName) { + return obj !== null && obj[keyName] !== jasmine.undefined; + }; + + for (var property in b) { + if (!hasKey(a, property) && hasKey(b, property)) { + mismatchKeys.push("expected has key '" + property + "', but missing from actual."); + } + } + for (property in a) { + if (!hasKey(b, property) && hasKey(a, property)) { + mismatchKeys.push("expected missing key '" + property + "', but present in actual."); + } + } + for (property in b) { + if (property == '__Jasmine_been_here_before__') continue; + if (!this.equals_(a[property], b[property], mismatchKeys, mismatchValues)) { + mismatchValues.push("'" + property + "' was '" + (b[property] ? jasmine.util.htmlEscape(b[property].toString()) : b[property]) + "' in expected, but was '" + (a[property] ? jasmine.util.htmlEscape(a[property].toString()) : a[property]) + "' in actual."); + } + } + + if (jasmine.isArray_(a) && jasmine.isArray_(b) && a.length != b.length) { + mismatchValues.push("arrays were not the same length"); + } + + delete a.__Jasmine_been_here_before__; + delete b.__Jasmine_been_here_before__; + return (mismatchKeys.length === 0 && mismatchValues.length === 0); +}; + +jasmine.Env.prototype.equals_ = function(a, b, mismatchKeys, mismatchValues) { + mismatchKeys = mismatchKeys || []; + mismatchValues = mismatchValues || []; + + for (var i = 0; i < this.equalityTesters_.length; i++) { + var equalityTester = this.equalityTesters_[i]; + var result = equalityTester(a, b, this, mismatchKeys, mismatchValues); + if (result !== jasmine.undefined) return result; + } + + if (a === b) return true; + + if (a === jasmine.undefined || a === null || b === jasmine.undefined || b === null) { + return (a == jasmine.undefined && b == jasmine.undefined); + } + + if (jasmine.isDomNode(a) && jasmine.isDomNode(b)) { + return a === b; + } + + if (a instanceof Date && b instanceof Date) { + return a.getTime() == b.getTime(); + } + + if (a instanceof jasmine.Matchers.Any) { + return a.matches(b); + } + + if (b instanceof jasmine.Matchers.Any) { + return b.matches(a); + } + + if (jasmine.isString_(a) && jasmine.isString_(b)) { + return (a == b); + } + + if (jasmine.isNumber_(a) && jasmine.isNumber_(b)) { + return (a == b); + } + + if (typeof a === "object" && typeof b === "object") { + return this.compareObjects_(a, b, mismatchKeys, mismatchValues); + } + + //Straight check + return (a === b); +}; + +jasmine.Env.prototype.contains_ = function(haystack, needle) { + if (jasmine.isArray_(haystack)) { + for (var i = 0; i < haystack.length; i++) { + if (this.equals_(haystack[i], needle)) return true; + } + return false; + } + return haystack.indexOf(needle) >= 0; +}; + +jasmine.Env.prototype.addEqualityTester = function(equalityTester) { + this.equalityTesters_.push(equalityTester); +}; +/** No-op base class for Jasmine reporters. + * + * @constructor + */ +jasmine.Reporter = function() { +}; + +//noinspection JSUnusedLocalSymbols +jasmine.Reporter.prototype.reportRunnerStarting = function(runner) { +}; + +//noinspection JSUnusedLocalSymbols +jasmine.Reporter.prototype.reportRunnerResults = function(runner) { +}; + +//noinspection JSUnusedLocalSymbols +jasmine.Reporter.prototype.reportSuiteResults = function(suite) { +}; + +//noinspection JSUnusedLocalSymbols +jasmine.Reporter.prototype.reportSpecStarting = function(spec) { +}; + +//noinspection JSUnusedLocalSymbols +jasmine.Reporter.prototype.reportSpecResults = function(spec) { +}; + +//noinspection JSUnusedLocalSymbols +jasmine.Reporter.prototype.log = function(str) { +}; + +/** + * Blocks are functions with executable code that make up a spec. + * + * @constructor + * @param {jasmine.Env} env + * @param {Function} func + * @param {jasmine.Spec} spec + */ +jasmine.Block = function(env, func, spec) { + this.env = env; + this.func = func; + this.spec = spec; +}; + +jasmine.Block.prototype.execute = function(onComplete) { + try { + this.func.apply(this.spec); + } catch (e) { + this.spec.fail(e); + } + onComplete(); +}; +/** JavaScript API reporter. + * + * @constructor + */ +jasmine.JsApiReporter = function() { + this.started = false; + this.finished = false; + this.suites_ = []; + this.results_ = {}; +}; + +jasmine.JsApiReporter.prototype.reportRunnerStarting = function(runner) { + this.started = true; + var suites = runner.topLevelSuites(); + for (var i = 0; i < suites.length; i++) { + var suite = suites[i]; + this.suites_.push(this.summarize_(suite)); + } +}; + +jasmine.JsApiReporter.prototype.suites = function() { + return this.suites_; +}; + +jasmine.JsApiReporter.prototype.summarize_ = function(suiteOrSpec) { + var isSuite = suiteOrSpec instanceof jasmine.Suite; + var summary = { + id: suiteOrSpec.id, + name: suiteOrSpec.description, + type: isSuite ? 'suite' : 'spec', + children: [] + }; + + if (isSuite) { + var children = suiteOrSpec.children(); + for (var i = 0; i < children.length; i++) { + summary.children.push(this.summarize_(children[i])); + } + } + return summary; +}; + +jasmine.JsApiReporter.prototype.results = function() { + return this.results_; +}; + +jasmine.JsApiReporter.prototype.resultsForSpec = function(specId) { + return this.results_[specId]; +}; + +//noinspection JSUnusedLocalSymbols +jasmine.JsApiReporter.prototype.reportRunnerResults = function(runner) { + this.finished = true; +}; + +//noinspection JSUnusedLocalSymbols +jasmine.JsApiReporter.prototype.reportSuiteResults = function(suite) { +}; + +//noinspection JSUnusedLocalSymbols +jasmine.JsApiReporter.prototype.reportSpecResults = function(spec) { + this.results_[spec.id] = { + messages: spec.results().getItems(), + result: spec.results().failedCount > 0 ? "failed" : "passed" + }; +}; + +//noinspection JSUnusedLocalSymbols +jasmine.JsApiReporter.prototype.log = function(str) { +}; + +jasmine.JsApiReporter.prototype.resultsForSpecs = function(specIds){ + var results = {}; + for (var i = 0; i < specIds.length; i++) { + var specId = specIds[i]; + results[specId] = this.summarizeResult_(this.results_[specId]); + } + return results; +}; + +jasmine.JsApiReporter.prototype.summarizeResult_ = function(result){ + var summaryMessages = []; + var messagesLength = result.messages.length; + for (var messageIndex = 0; messageIndex < messagesLength; messageIndex++) { + var resultMessage = result.messages[messageIndex]; + summaryMessages.push({ + text: resultMessage.type == 'log' ? resultMessage.toString() : jasmine.undefined, + passed: resultMessage.passed ? resultMessage.passed() : true, + type: resultMessage.type, + message: resultMessage.message, + trace: { + stack: resultMessage.passed && !resultMessage.passed() ? resultMessage.trace.stack : jasmine.undefined + } + }); + } + + return { + result : result.result, + messages : summaryMessages + }; +}; + +/** + * @constructor + * @param {jasmine.Env} env + * @param actual + * @param {jasmine.Spec} spec + */ +jasmine.Matchers = function(env, actual, spec, opt_isNot) { + this.env = env; + this.actual = actual; + this.spec = spec; + this.isNot = opt_isNot || false; + this.reportWasCalled_ = false; +}; + +// todo: @deprecated as of Jasmine 0.11, remove soon [xw] +jasmine.Matchers.pp = function(str) { + throw new Error("jasmine.Matchers.pp() is no longer supported, please use jasmine.pp() instead!"); +}; + +// todo: @deprecated Deprecated as of Jasmine 0.10. Rewrite your custom matchers to return true or false. [xw] +jasmine.Matchers.prototype.report = function(result, failing_message, details) { + throw new Error("As of jasmine 0.11, custom matchers must be implemented differently -- please see jasmine docs"); +}; + +jasmine.Matchers.wrapInto_ = function(prototype, matchersClass) { + for (var methodName in prototype) { + if (methodName == 'report') continue; + var orig = prototype[methodName]; + matchersClass.prototype[methodName] = jasmine.Matchers.matcherFn_(methodName, orig); + } +}; + +jasmine.Matchers.matcherFn_ = function(matcherName, matcherFunction) { + return function() { + var matcherArgs = jasmine.util.argsToArray(arguments); + var result = matcherFunction.apply(this, arguments); + + if (this.isNot) { + result = !result; + } + + if (this.reportWasCalled_) return result; + + var message; + if (!result) { + if (this.message) { + message = this.message.apply(this, arguments); + if (jasmine.isArray_(message)) { + message = message[this.isNot ? 1 : 0]; + } + } else { + var englishyPredicate = matcherName.replace(/[A-Z]/g, function(s) { return ' ' + s.toLowerCase(); }); + message = "Expected " + jasmine.pp(this.actual) + (this.isNot ? " not " : " ") + englishyPredicate; + if (matcherArgs.length > 0) { + for (var i = 0; i < matcherArgs.length; i++) { + if (i > 0) message += ","; + message += " " + jasmine.pp(matcherArgs[i]); + } + } + message += "."; + } + } + var expectationResult = new jasmine.ExpectationResult({ + matcherName: matcherName, + passed: result, + expected: matcherArgs.length > 1 ? matcherArgs : matcherArgs[0], + actual: this.actual, + message: message + }); + this.spec.addMatcherResult(expectationResult); + return jasmine.undefined; + }; +}; + + + + +/** + * toBe: compares the actual to the expected using === + * @param expected + */ +jasmine.Matchers.prototype.toBe = function(expected) { + return this.actual === expected; +}; + +/** + * toNotBe: compares the actual to the expected using !== + * @param expected + * @deprecated as of 1.0. Use not.toBe() instead. + */ +jasmine.Matchers.prototype.toNotBe = function(expected) { + return this.actual !== expected; +}; + +/** + * toEqual: compares the actual to the expected using common sense equality. Handles Objects, Arrays, etc. + * + * @param expected + */ +jasmine.Matchers.prototype.toEqual = function(expected) { + return this.env.equals_(this.actual, expected); +}; + +/** + * toNotEqual: compares the actual to the expected using the ! of jasmine.Matchers.toEqual + * @param expected + * @deprecated as of 1.0. Use not.toNotEqual() instead. + */ +jasmine.Matchers.prototype.toNotEqual = function(expected) { + return !this.env.equals_(this.actual, expected); +}; + +/** + * Matcher that compares the actual to the expected using a regular expression. Constructs a RegExp, so takes + * a pattern or a String. + * + * @param expected + */ +jasmine.Matchers.prototype.toMatch = function(expected) { + return new RegExp(expected).test(this.actual); +}; + +/** + * Matcher that compares the actual to the expected using the boolean inverse of jasmine.Matchers.toMatch + * @param expected + * @deprecated as of 1.0. Use not.toMatch() instead. + */ +jasmine.Matchers.prototype.toNotMatch = function(expected) { + return !(new RegExp(expected).test(this.actual)); +}; + +/** + * Matcher that compares the actual to jasmine.undefined. + */ +jasmine.Matchers.prototype.toBeDefined = function() { + return (this.actual !== jasmine.undefined); +}; + +/** + * Matcher that compares the actual to jasmine.undefined. + */ +jasmine.Matchers.prototype.toBeUndefined = function() { + return (this.actual === jasmine.undefined); +}; + +/** + * Matcher that compares the actual to null. + */ +jasmine.Matchers.prototype.toBeNull = function() { + return (this.actual === null); +}; + +/** + * Matcher that boolean not-nots the actual. + */ +jasmine.Matchers.prototype.toBeTruthy = function() { + return !!this.actual; +}; + + +/** + * Matcher that boolean nots the actual. + */ +jasmine.Matchers.prototype.toBeFalsy = function() { + return !this.actual; +}; + + +/** + * Matcher that checks to see if the actual, a Jasmine spy, was called. + */ +jasmine.Matchers.prototype.toHaveBeenCalled = function() { + if (arguments.length > 0) { + throw new Error('toHaveBeenCalled does not take arguments, use toHaveBeenCalledWith'); + } + + if (!jasmine.isSpy(this.actual)) { + throw new Error('Expected a spy, but got ' + jasmine.pp(this.actual) + '.'); + } + + this.message = function() { + return [ + "Expected spy " + this.actual.identity + " to have been called.", + "Expected spy " + this.actual.identity + " not to have been called." + ]; + }; + + return this.actual.wasCalled; +}; + +/** @deprecated Use expect(xxx).toHaveBeenCalled() instead */ +jasmine.Matchers.prototype.wasCalled = jasmine.Matchers.prototype.toHaveBeenCalled; + +/** + * Matcher that checks to see if the actual, a Jasmine spy, was not called. + * + * @deprecated Use expect(xxx).not.toHaveBeenCalled() instead + */ +jasmine.Matchers.prototype.wasNotCalled = function() { + if (arguments.length > 0) { + throw new Error('wasNotCalled does not take arguments'); + } + + if (!jasmine.isSpy(this.actual)) { + throw new Error('Expected a spy, but got ' + jasmine.pp(this.actual) + '.'); + } + + this.message = function() { + return [ + "Expected spy " + this.actual.identity + " to not have been called.", + "Expected spy " + this.actual.identity + " to have been called." + ]; + }; + + return !this.actual.wasCalled; +}; + +/** + * Matcher that checks to see if the actual, a Jasmine spy, was called with a set of parameters. + * + * @example + * + */ +jasmine.Matchers.prototype.toHaveBeenCalledWith = function() { + var expectedArgs = jasmine.util.argsToArray(arguments); + if (!jasmine.isSpy(this.actual)) { + throw new Error('Expected a spy, but got ' + jasmine.pp(this.actual) + '.'); + } + this.message = function() { + if (this.actual.callCount === 0) { + // todo: what should the failure message for .not.toHaveBeenCalledWith() be? is this right? test better. [xw] + return [ + "Expected spy " + this.actual.identity + " to have been called with " + jasmine.pp(expectedArgs) + " but it was never called.", + "Expected spy " + this.actual.identity + " not to have been called with " + jasmine.pp(expectedArgs) + " but it was." + ]; + } else { + return [ + "Expected spy " + this.actual.identity + " to have been called with " + jasmine.pp(expectedArgs) + " but was called with " + jasmine.pp(this.actual.argsForCall), + "Expected spy " + this.actual.identity + " not to have been called with " + jasmine.pp(expectedArgs) + " but was called with " + jasmine.pp(this.actual.argsForCall) + ]; + } + }; + + return this.env.contains_(this.actual.argsForCall, expectedArgs); +}; + +/** @deprecated Use expect(xxx).toHaveBeenCalledWith() instead */ +jasmine.Matchers.prototype.wasCalledWith = jasmine.Matchers.prototype.toHaveBeenCalledWith; + +/** @deprecated Use expect(xxx).not.toHaveBeenCalledWith() instead */ +jasmine.Matchers.prototype.wasNotCalledWith = function() { + var expectedArgs = jasmine.util.argsToArray(arguments); + if (!jasmine.isSpy(this.actual)) { + throw new Error('Expected a spy, but got ' + jasmine.pp(this.actual) + '.'); + } + + this.message = function() { + return [ + "Expected spy not to have been called with " + jasmine.pp(expectedArgs) + " but it was", + "Expected spy to have been called with " + jasmine.pp(expectedArgs) + " but it was" + ]; + }; + + return !this.env.contains_(this.actual.argsForCall, expectedArgs); +}; + +/** + * Matcher that checks that the expected item is an element in the actual Array. + * + * @param {Object} expected + */ +jasmine.Matchers.prototype.toContain = function(expected) { + return this.env.contains_(this.actual, expected); +}; + +/** + * Matcher that checks that the expected item is NOT an element in the actual Array. + * + * @param {Object} expected + * @deprecated as of 1.0. Use not.toNotContain() instead. + */ +jasmine.Matchers.prototype.toNotContain = function(expected) { + return !this.env.contains_(this.actual, expected); +}; + +jasmine.Matchers.prototype.toBeLessThan = function(expected) { + return this.actual < expected; +}; + +jasmine.Matchers.prototype.toBeGreaterThan = function(expected) { + return this.actual > expected; +}; + +/** + * Matcher that checks that the expected item is equal to the actual item + * up to a given level of decimal precision (default 2). + * + * @param {Number} expected + * @param {Number} precision + */ +jasmine.Matchers.prototype.toBeCloseTo = function(expected, precision) { + if (!(precision === 0)) { + precision = precision || 2; + } + var multiplier = Math.pow(10, precision); + var actual = Math.round(this.actual * multiplier); + expected = Math.round(expected * multiplier); + return expected == actual; +}; + +/** + * Matcher that checks that the expected exception was thrown by the actual. + * + * @param {String} expected + */ +jasmine.Matchers.prototype.toThrow = function(expected) { + var result = false; + var exception; + if (typeof this.actual != 'function') { + throw new Error('Actual is not a function'); + } + try { + this.actual(); + } catch (e) { + exception = e; + } + if (exception) { + result = (expected === jasmine.undefined || this.env.equals_(exception.message || exception, expected.message || expected)); + } + + var not = this.isNot ? "not " : ""; + + this.message = function() { + if (exception && (expected === jasmine.undefined || !this.env.equals_(exception.message || exception, expected.message || expected))) { + return ["Expected function " + not + "to throw", expected ? expected.message || expected : "an exception", ", but it threw", exception.message || exception].join(' '); + } else { + return "Expected function to throw an exception."; + } + }; + + return result; +}; + +jasmine.Matchers.Any = function(expectedClass) { + this.expectedClass = expectedClass; +}; + +jasmine.Matchers.Any.prototype.matches = function(other) { + if (this.expectedClass == String) { + return typeof other == 'string' || other instanceof String; + } + + if (this.expectedClass == Number) { + return typeof other == 'number' || other instanceof Number; + } + + if (this.expectedClass == Function) { + return typeof other == 'function' || other instanceof Function; + } + + if (this.expectedClass == Object) { + return typeof other == 'object'; + } + + return other instanceof this.expectedClass; +}; + +jasmine.Matchers.Any.prototype.toString = function() { + return ''; +}; + +/** + * @constructor + */ +jasmine.MultiReporter = function() { + this.subReporters_ = []; +}; +jasmine.util.inherit(jasmine.MultiReporter, jasmine.Reporter); + +jasmine.MultiReporter.prototype.addReporter = function(reporter) { + this.subReporters_.push(reporter); +}; + +(function() { + var functionNames = [ + "reportRunnerStarting", + "reportRunnerResults", + "reportSuiteResults", + "reportSpecStarting", + "reportSpecResults", + "log" + ]; + for (var i = 0; i < functionNames.length; i++) { + var functionName = functionNames[i]; + jasmine.MultiReporter.prototype[functionName] = (function(functionName) { + return function() { + for (var j = 0; j < this.subReporters_.length; j++) { + var subReporter = this.subReporters_[j]; + if (subReporter[functionName]) { + subReporter[functionName].apply(subReporter, arguments); + } + } + }; + })(functionName); + } +})(); +/** + * Holds results for a set of Jasmine spec. Allows for the results array to hold another jasmine.NestedResults + * + * @constructor + */ +jasmine.NestedResults = function() { + /** + * The total count of results + */ + this.totalCount = 0; + /** + * Number of passed results + */ + this.passedCount = 0; + /** + * Number of failed results + */ + this.failedCount = 0; + /** + * Was this suite/spec skipped? + */ + this.skipped = false; + /** + * @ignore + */ + this.items_ = []; +}; + +/** + * Roll up the result counts. + * + * @param result + */ +jasmine.NestedResults.prototype.rollupCounts = function(result) { + this.totalCount += result.totalCount; + this.passedCount += result.passedCount; + this.failedCount += result.failedCount; +}; + +/** + * Adds a log message. + * @param values Array of message parts which will be concatenated later. + */ +jasmine.NestedResults.prototype.log = function(values) { + this.items_.push(new jasmine.MessageResult(values)); +}; + +/** + * Getter for the results: message & results. + */ +jasmine.NestedResults.prototype.getItems = function() { + return this.items_; +}; + +/** + * Adds a result, tracking counts (total, passed, & failed) + * @param {jasmine.ExpectationResult|jasmine.NestedResults} result + */ +jasmine.NestedResults.prototype.addResult = function(result) { + if (result.type != 'log') { + if (result.items_) { + this.rollupCounts(result); + } else { + this.totalCount++; + if (result.passed()) { + this.passedCount++; + } else { + this.failedCount++; + } + } + } + this.items_.push(result); +}; + +/** + * @returns {Boolean} True if everything below passed + */ +jasmine.NestedResults.prototype.passed = function() { + return this.passedCount === this.totalCount; +}; +/** + * Base class for pretty printing for expectation results. + */ +jasmine.PrettyPrinter = function() { + this.ppNestLevel_ = 0; +}; + +/** + * Formats a value in a nice, human-readable string. + * + * @param value + */ +jasmine.PrettyPrinter.prototype.format = function(value) { + if (this.ppNestLevel_ > 40) { + throw new Error('jasmine.PrettyPrinter: format() nested too deeply!'); + } + + this.ppNestLevel_++; + try { + if (value === jasmine.undefined) { + this.emitScalar('undefined'); + } else if (value === null) { + this.emitScalar('null'); + } else if (value === jasmine.getGlobal()) { + this.emitScalar(''); + } else if (value instanceof jasmine.Matchers.Any) { + this.emitScalar(value.toString()); + } else if (typeof value === 'string') { + this.emitString(value); + } else if (jasmine.isSpy(value)) { + this.emitScalar("spy on " + value.identity); + } else if (value instanceof RegExp) { + this.emitScalar(value.toString()); + } else if (typeof value === 'function') { + this.emitScalar('Function'); + } else if (typeof value.nodeType === 'number') { + this.emitScalar('HTMLNode'); + } else if (value instanceof Date) { + this.emitScalar('Date(' + value + ')'); + } else if (value.__Jasmine_been_here_before__) { + this.emitScalar(''); + } else if (jasmine.isArray_(value) || typeof value == 'object') { + value.__Jasmine_been_here_before__ = true; + if (jasmine.isArray_(value)) { + this.emitArray(value); + } else { + this.emitObject(value); + } + delete value.__Jasmine_been_here_before__; + } else { + this.emitScalar(value.toString()); + } + } finally { + this.ppNestLevel_--; + } +}; + +jasmine.PrettyPrinter.prototype.iterateObject = function(obj, fn) { + for (var property in obj) { + if (property == '__Jasmine_been_here_before__') continue; + fn(property, obj.__lookupGetter__ ? (obj.__lookupGetter__(property) !== jasmine.undefined && + obj.__lookupGetter__(property) !== null) : false); + } +}; + +jasmine.PrettyPrinter.prototype.emitArray = jasmine.unimplementedMethod_; +jasmine.PrettyPrinter.prototype.emitObject = jasmine.unimplementedMethod_; +jasmine.PrettyPrinter.prototype.emitScalar = jasmine.unimplementedMethod_; +jasmine.PrettyPrinter.prototype.emitString = jasmine.unimplementedMethod_; + +jasmine.StringPrettyPrinter = function() { + jasmine.PrettyPrinter.call(this); + + this.string = ''; +}; +jasmine.util.inherit(jasmine.StringPrettyPrinter, jasmine.PrettyPrinter); + +jasmine.StringPrettyPrinter.prototype.emitScalar = function(value) { + this.append(value); +}; + +jasmine.StringPrettyPrinter.prototype.emitString = function(value) { + this.append("'" + value + "'"); +}; + +jasmine.StringPrettyPrinter.prototype.emitArray = function(array) { + this.append('[ '); + for (var i = 0; i < array.length; i++) { + if (i > 0) { + this.append(', '); + } + this.format(array[i]); + } + this.append(' ]'); +}; + +jasmine.StringPrettyPrinter.prototype.emitObject = function(obj) { + var self = this; + this.append('{ '); + var first = true; + + this.iterateObject(obj, function(property, isGetter) { + if (first) { + first = false; + } else { + self.append(', '); + } + + self.append(property); + self.append(' : '); + if (isGetter) { + self.append(''); + } else { + self.format(obj[property]); + } + }); + + this.append(' }'); +}; + +jasmine.StringPrettyPrinter.prototype.append = function(value) { + this.string += value; +}; +jasmine.Queue = function(env) { + this.env = env; + this.blocks = []; + this.running = false; + this.index = 0; + this.offset = 0; + this.abort = false; +}; + +jasmine.Queue.prototype.addBefore = function(block) { + this.blocks.unshift(block); +}; + +jasmine.Queue.prototype.add = function(block) { + this.blocks.push(block); +}; + +jasmine.Queue.prototype.insertNext = function(block) { + this.blocks.splice((this.index + this.offset + 1), 0, block); + this.offset++; +}; + +jasmine.Queue.prototype.start = function(onComplete) { + this.running = true; + this.onComplete = onComplete; + this.next_(); +}; + +jasmine.Queue.prototype.isRunning = function() { + return this.running; +}; + +jasmine.Queue.LOOP_DONT_RECURSE = true; + +jasmine.Queue.prototype.next_ = function() { + var self = this; + var goAgain = true; + + while (goAgain) { + goAgain = false; + + if (self.index < self.blocks.length && !this.abort) { + var calledSynchronously = true; + var completedSynchronously = false; + + var onComplete = function () { + if (jasmine.Queue.LOOP_DONT_RECURSE && calledSynchronously) { + completedSynchronously = true; + return; + } + + if (self.blocks[self.index].abort) { + self.abort = true; + } + + self.offset = 0; + self.index++; + + var now = new Date().getTime(); + if (self.env.updateInterval && now - self.env.lastUpdate > self.env.updateInterval) { + self.env.lastUpdate = now; + self.env.setTimeout(function() { + self.next_(); + }, 0); + } else { + if (jasmine.Queue.LOOP_DONT_RECURSE && completedSynchronously) { + goAgain = true; + } else { + self.next_(); + } + } + }; + self.blocks[self.index].execute(onComplete); + + calledSynchronously = false; + if (completedSynchronously) { + onComplete(); + } + + } else { + self.running = false; + if (self.onComplete) { + self.onComplete(); + } + } + } +}; + +jasmine.Queue.prototype.results = function() { + var results = new jasmine.NestedResults(); + for (var i = 0; i < this.blocks.length; i++) { + if (this.blocks[i].results) { + results.addResult(this.blocks[i].results()); + } + } + return results; +}; + + +/** + * Runner + * + * @constructor + * @param {jasmine.Env} env + */ +jasmine.Runner = function(env) { + var self = this; + self.env = env; + self.queue = new jasmine.Queue(env); + self.before_ = []; + self.after_ = []; + self.suites_ = []; +}; + +jasmine.Runner.prototype.execute = function() { + var self = this; + if (self.env.reporter.reportRunnerStarting) { + self.env.reporter.reportRunnerStarting(this); + } + self.queue.start(function () { + self.finishCallback(); + }); +}; + +jasmine.Runner.prototype.beforeEach = function(beforeEachFunction) { + beforeEachFunction.typeName = 'beforeEach'; + this.before_.splice(0,0,beforeEachFunction); +}; + +jasmine.Runner.prototype.afterEach = function(afterEachFunction) { + afterEachFunction.typeName = 'afterEach'; + this.after_.splice(0,0,afterEachFunction); +}; + + +jasmine.Runner.prototype.finishCallback = function() { + this.env.reporter.reportRunnerResults(this); +}; + +jasmine.Runner.prototype.addSuite = function(suite) { + this.suites_.push(suite); +}; + +jasmine.Runner.prototype.add = function(block) { + if (block instanceof jasmine.Suite) { + this.addSuite(block); + } + this.queue.add(block); +}; + +jasmine.Runner.prototype.specs = function () { + var suites = this.suites(); + var specs = []; + for (var i = 0; i < suites.length; i++) { + specs = specs.concat(suites[i].specs()); + } + return specs; +}; + +jasmine.Runner.prototype.suites = function() { + return this.suites_; +}; + +jasmine.Runner.prototype.topLevelSuites = function() { + var topLevelSuites = []; + for (var i = 0; i < this.suites_.length; i++) { + if (!this.suites_[i].parentSuite) { + topLevelSuites.push(this.suites_[i]); + } + } + return topLevelSuites; +}; + +jasmine.Runner.prototype.results = function() { + return this.queue.results(); +}; +/** + * Internal representation of a Jasmine specification, or test. + * + * @constructor + * @param {jasmine.Env} env + * @param {jasmine.Suite} suite + * @param {String} description + */ +jasmine.Spec = function(env, suite, description) { + if (!env) { + throw new Error('jasmine.Env() required'); + } + if (!suite) { + throw new Error('jasmine.Suite() required'); + } + var spec = this; + spec.id = env.nextSpecId ? env.nextSpecId() : null; + spec.env = env; + spec.suite = suite; + spec.description = description; + spec.queue = new jasmine.Queue(env); + + spec.afterCallbacks = []; + spec.spies_ = []; + + spec.results_ = new jasmine.NestedResults(); + spec.results_.description = description; + spec.matchersClass = null; +}; + +jasmine.Spec.prototype.getFullName = function() { + return this.suite.getFullName() + ' ' + this.description + '.'; +}; + + +jasmine.Spec.prototype.results = function() { + return this.results_; +}; + +/** + * All parameters are pretty-printed and concatenated together, then written to the spec's output. + * + * Be careful not to leave calls to jasmine.log in production code. + */ +jasmine.Spec.prototype.log = function() { + return this.results_.log(arguments); +}; + +jasmine.Spec.prototype.runs = function (func) { + var block = new jasmine.Block(this.env, func, this); + this.addToQueue(block); + return this; +}; + +jasmine.Spec.prototype.addToQueue = function (block) { + if (this.queue.isRunning()) { + this.queue.insertNext(block); + } else { + this.queue.add(block); + } +}; + +/** + * @param {jasmine.ExpectationResult} result + */ +jasmine.Spec.prototype.addMatcherResult = function(result) { + this.results_.addResult(result); +}; + +jasmine.Spec.prototype.expect = function(actual) { + var positive = new (this.getMatchersClass_())(this.env, actual, this); + positive.not = new (this.getMatchersClass_())(this.env, actual, this, true); + return positive; +}; + +/** + * Waits a fixed time period before moving to the next block. + * + * @deprecated Use waitsFor() instead + * @param {Number} timeout milliseconds to wait + */ +jasmine.Spec.prototype.waits = function(timeout) { + var waitsFunc = new jasmine.WaitsBlock(this.env, timeout, this); + this.addToQueue(waitsFunc); + return this; +}; + +/** + * Waits for the latchFunction to return true before proceeding to the next block. + * + * @param {Function} latchFunction + * @param {String} optional_timeoutMessage + * @param {Number} optional_timeout + */ +jasmine.Spec.prototype.waitsFor = function(latchFunction, optional_timeoutMessage, optional_timeout) { + var latchFunction_ = null; + var optional_timeoutMessage_ = null; + var optional_timeout_ = null; + + for (var i = 0; i < arguments.length; i++) { + var arg = arguments[i]; + switch (typeof arg) { + case 'function': + latchFunction_ = arg; + break; + case 'string': + optional_timeoutMessage_ = arg; + break; + case 'number': + optional_timeout_ = arg; + break; + } + } + + var waitsForFunc = new jasmine.WaitsForBlock(this.env, optional_timeout_, latchFunction_, optional_timeoutMessage_, this); + this.addToQueue(waitsForFunc); + return this; +}; + +jasmine.Spec.prototype.fail = function (e) { + var expectationResult = new jasmine.ExpectationResult({ + passed: false, + message: e ? jasmine.util.formatException(e) : 'Exception', + trace: { stack: e.stack } + }); + this.results_.addResult(expectationResult); +}; + +jasmine.Spec.prototype.getMatchersClass_ = function() { + return this.matchersClass || this.env.matchersClass; +}; + +jasmine.Spec.prototype.addMatchers = function(matchersPrototype) { + var parent = this.getMatchersClass_(); + var newMatchersClass = function() { + parent.apply(this, arguments); + }; + jasmine.util.inherit(newMatchersClass, parent); + jasmine.Matchers.wrapInto_(matchersPrototype, newMatchersClass); + this.matchersClass = newMatchersClass; +}; + +jasmine.Spec.prototype.finishCallback = function() { + this.env.reporter.reportSpecResults(this); +}; + +jasmine.Spec.prototype.finish = function(onComplete) { + this.removeAllSpies(); + this.finishCallback(); + if (onComplete) { + onComplete(); + } +}; + +jasmine.Spec.prototype.after = function(doAfter) { + if (this.queue.isRunning()) { + this.queue.add(new jasmine.Block(this.env, doAfter, this)); + } else { + this.afterCallbacks.unshift(doAfter); + } +}; + +jasmine.Spec.prototype.execute = function(onComplete) { + var spec = this; + if (!spec.env.specFilter(spec)) { + spec.results_.skipped = true; + spec.finish(onComplete); + return; + } + + this.env.reporter.reportSpecStarting(this); + + spec.env.currentSpec = spec; + + spec.addBeforesAndAftersToQueue(); + + spec.queue.start(function () { + spec.finish(onComplete); + }); +}; + +jasmine.Spec.prototype.addBeforesAndAftersToQueue = function() { + var runner = this.env.currentRunner(); + var i; + + for (var suite = this.suite; suite; suite = suite.parentSuite) { + for (i = 0; i < suite.before_.length; i++) { + this.queue.addBefore(new jasmine.Block(this.env, suite.before_[i], this)); + } + } + for (i = 0; i < runner.before_.length; i++) { + this.queue.addBefore(new jasmine.Block(this.env, runner.before_[i], this)); + } + for (i = 0; i < this.afterCallbacks.length; i++) { + this.queue.add(new jasmine.Block(this.env, this.afterCallbacks[i], this)); + } + for (suite = this.suite; suite; suite = suite.parentSuite) { + for (i = 0; i < suite.after_.length; i++) { + this.queue.add(new jasmine.Block(this.env, suite.after_[i], this)); + } + } + for (i = 0; i < runner.after_.length; i++) { + this.queue.add(new jasmine.Block(this.env, runner.after_[i], this)); + } +}; + +jasmine.Spec.prototype.explodes = function() { + throw 'explodes function should not have been called'; +}; + +jasmine.Spec.prototype.spyOn = function(obj, methodName, ignoreMethodDoesntExist) { + if (obj == jasmine.undefined) { + throw "spyOn could not find an object to spy upon for " + methodName + "()"; + } + + if (!ignoreMethodDoesntExist && obj[methodName] === jasmine.undefined) { + throw methodName + '() method does not exist'; + } + + if (!ignoreMethodDoesntExist && obj[methodName] && obj[methodName].isSpy) { + throw new Error(methodName + ' has already been spied upon'); + } + + var spyObj = jasmine.createSpy(methodName); + + this.spies_.push(spyObj); + spyObj.baseObj = obj; + spyObj.methodName = methodName; + spyObj.originalValue = obj[methodName]; + + obj[methodName] = spyObj; + + return spyObj; +}; + +jasmine.Spec.prototype.removeAllSpies = function() { + for (var i = 0; i < this.spies_.length; i++) { + var spy = this.spies_[i]; + spy.baseObj[spy.methodName] = spy.originalValue; + } + this.spies_ = []; +}; + +/** + * Internal representation of a Jasmine suite. + * + * @constructor + * @param {jasmine.Env} env + * @param {String} description + * @param {Function} specDefinitions + * @param {jasmine.Suite} parentSuite + */ +jasmine.Suite = function(env, description, specDefinitions, parentSuite) { + var self = this; + self.id = env.nextSuiteId ? env.nextSuiteId() : null; + self.description = description; + self.queue = new jasmine.Queue(env); + self.parentSuite = parentSuite; + self.env = env; + self.before_ = []; + self.after_ = []; + self.children_ = []; + self.suites_ = []; + self.specs_ = []; +}; + +jasmine.Suite.prototype.getFullName = function() { + var fullName = this.description; + for (var parentSuite = this.parentSuite; parentSuite; parentSuite = parentSuite.parentSuite) { + fullName = parentSuite.description + ' ' + fullName; + } + return fullName; +}; + +jasmine.Suite.prototype.finish = function(onComplete) { + this.env.reporter.reportSuiteResults(this); + this.finished = true; + if (typeof(onComplete) == 'function') { + onComplete(); + } +}; + +jasmine.Suite.prototype.beforeEach = function(beforeEachFunction) { + beforeEachFunction.typeName = 'beforeEach'; + this.before_.unshift(beforeEachFunction); +}; + +jasmine.Suite.prototype.afterEach = function(afterEachFunction) { + afterEachFunction.typeName = 'afterEach'; + this.after_.unshift(afterEachFunction); +}; + +jasmine.Suite.prototype.results = function() { + return this.queue.results(); +}; + +jasmine.Suite.prototype.add = function(suiteOrSpec) { + this.children_.push(suiteOrSpec); + if (suiteOrSpec instanceof jasmine.Suite) { + this.suites_.push(suiteOrSpec); + this.env.currentRunner().addSuite(suiteOrSpec); + } else { + this.specs_.push(suiteOrSpec); + } + this.queue.add(suiteOrSpec); +}; + +jasmine.Suite.prototype.specs = function() { + return this.specs_; +}; + +jasmine.Suite.prototype.suites = function() { + return this.suites_; +}; + +jasmine.Suite.prototype.children = function() { + return this.children_; +}; + +jasmine.Suite.prototype.execute = function(onComplete) { + var self = this; + this.queue.start(function () { + self.finish(onComplete); + }); +}; +jasmine.WaitsBlock = function(env, timeout, spec) { + this.timeout = timeout; + jasmine.Block.call(this, env, null, spec); +}; + +jasmine.util.inherit(jasmine.WaitsBlock, jasmine.Block); + +jasmine.WaitsBlock.prototype.execute = function (onComplete) { + if (jasmine.VERBOSE) { + this.env.reporter.log('>> Jasmine waiting for ' + this.timeout + ' ms...'); + } + this.env.setTimeout(function () { + onComplete(); + }, this.timeout); +}; +/** + * A block which waits for some condition to become true, with timeout. + * + * @constructor + * @extends jasmine.Block + * @param {jasmine.Env} env The Jasmine environment. + * @param {Number} timeout The maximum time in milliseconds to wait for the condition to become true. + * @param {Function} latchFunction A function which returns true when the desired condition has been met. + * @param {String} message The message to display if the desired condition hasn't been met within the given time period. + * @param {jasmine.Spec} spec The Jasmine spec. + */ +jasmine.WaitsForBlock = function(env, timeout, latchFunction, message, spec) { + this.timeout = timeout || env.defaultTimeoutInterval; + this.latchFunction = latchFunction; + this.message = message; + this.totalTimeSpentWaitingForLatch = 0; + jasmine.Block.call(this, env, null, spec); +}; +jasmine.util.inherit(jasmine.WaitsForBlock, jasmine.Block); + +jasmine.WaitsForBlock.TIMEOUT_INCREMENT = 10; + +jasmine.WaitsForBlock.prototype.execute = function(onComplete) { + if (jasmine.VERBOSE) { + this.env.reporter.log('>> Jasmine waiting for ' + (this.message || 'something to happen')); + } + var latchFunctionResult; + try { + latchFunctionResult = this.latchFunction.apply(this.spec); + } catch (e) { + this.spec.fail(e); + onComplete(); + return; + } + + if (latchFunctionResult) { + onComplete(); + } else if (this.totalTimeSpentWaitingForLatch >= this.timeout) { + var message = 'timed out after ' + this.timeout + ' msec waiting for ' + (this.message || 'something to happen'); + this.spec.fail({ + name: 'timeout', + message: message + }); + + this.abort = true; + onComplete(); + } else { + this.totalTimeSpentWaitingForLatch += jasmine.WaitsForBlock.TIMEOUT_INCREMENT; + var self = this; + this.env.setTimeout(function() { + self.execute(onComplete); + }, jasmine.WaitsForBlock.TIMEOUT_INCREMENT); + } +}; +// Mock setTimeout, clearTimeout +// Contributed by Pivotal Computer Systems, www.pivotalsf.com + +jasmine.FakeTimer = function() { + this.reset(); + + var self = this; + self.setTimeout = function(funcToCall, millis) { + self.timeoutsMade++; + self.scheduleFunction(self.timeoutsMade, funcToCall, millis, false); + return self.timeoutsMade; + }; + + self.setInterval = function(funcToCall, millis) { + self.timeoutsMade++; + self.scheduleFunction(self.timeoutsMade, funcToCall, millis, true); + return self.timeoutsMade; + }; + + self.clearTimeout = function(timeoutKey) { + self.scheduledFunctions[timeoutKey] = jasmine.undefined; + }; + + self.clearInterval = function(timeoutKey) { + self.scheduledFunctions[timeoutKey] = jasmine.undefined; + }; + +}; + +jasmine.FakeTimer.prototype.reset = function() { + this.timeoutsMade = 0; + this.scheduledFunctions = {}; + this.nowMillis = 0; +}; + +jasmine.FakeTimer.prototype.tick = function(millis) { + var oldMillis = this.nowMillis; + var newMillis = oldMillis + millis; + this.runFunctionsWithinRange(oldMillis, newMillis); + this.nowMillis = newMillis; +}; + +jasmine.FakeTimer.prototype.runFunctionsWithinRange = function(oldMillis, nowMillis) { + var scheduledFunc; + var funcsToRun = []; + for (var timeoutKey in this.scheduledFunctions) { + scheduledFunc = this.scheduledFunctions[timeoutKey]; + if (scheduledFunc != jasmine.undefined && + scheduledFunc.runAtMillis >= oldMillis && + scheduledFunc.runAtMillis <= nowMillis) { + funcsToRun.push(scheduledFunc); + this.scheduledFunctions[timeoutKey] = jasmine.undefined; + } + } + + if (funcsToRun.length > 0) { + funcsToRun.sort(function(a, b) { + return a.runAtMillis - b.runAtMillis; + }); + for (var i = 0; i < funcsToRun.length; ++i) { + try { + var funcToRun = funcsToRun[i]; + this.nowMillis = funcToRun.runAtMillis; + funcToRun.funcToCall(); + if (funcToRun.recurring) { + this.scheduleFunction(funcToRun.timeoutKey, + funcToRun.funcToCall, + funcToRun.millis, + true); + } + } catch(e) { + } + } + this.runFunctionsWithinRange(oldMillis, nowMillis); + } +}; + +jasmine.FakeTimer.prototype.scheduleFunction = function(timeoutKey, funcToCall, millis, recurring) { + this.scheduledFunctions[timeoutKey] = { + runAtMillis: this.nowMillis + millis, + funcToCall: funcToCall, + recurring: recurring, + timeoutKey: timeoutKey, + millis: millis + }; +}; + +/** + * @namespace + */ +jasmine.Clock = { + defaultFakeTimer: new jasmine.FakeTimer(), + + reset: function() { + jasmine.Clock.assertInstalled(); + jasmine.Clock.defaultFakeTimer.reset(); + }, + + tick: function(millis) { + jasmine.Clock.assertInstalled(); + jasmine.Clock.defaultFakeTimer.tick(millis); + }, + + runFunctionsWithinRange: function(oldMillis, nowMillis) { + jasmine.Clock.defaultFakeTimer.runFunctionsWithinRange(oldMillis, nowMillis); + }, + + scheduleFunction: function(timeoutKey, funcToCall, millis, recurring) { + jasmine.Clock.defaultFakeTimer.scheduleFunction(timeoutKey, funcToCall, millis, recurring); + }, + + useMock: function() { + if (!jasmine.Clock.isInstalled()) { + var spec = jasmine.getEnv().currentSpec; + spec.after(jasmine.Clock.uninstallMock); + + jasmine.Clock.installMock(); + } + }, + + installMock: function() { + jasmine.Clock.installed = jasmine.Clock.defaultFakeTimer; + }, + + uninstallMock: function() { + jasmine.Clock.assertInstalled(); + jasmine.Clock.installed = jasmine.Clock.real; + }, + + real: { + setTimeout: jasmine.getGlobal().setTimeout, + clearTimeout: jasmine.getGlobal().clearTimeout, + setInterval: jasmine.getGlobal().setInterval, + clearInterval: jasmine.getGlobal().clearInterval + }, + + assertInstalled: function() { + if (!jasmine.Clock.isInstalled()) { + throw new Error("Mock clock is not installed, use jasmine.Clock.useMock()"); + } + }, + + isInstalled: function() { + return jasmine.Clock.installed == jasmine.Clock.defaultFakeTimer; + }, + + installed: null +}; +jasmine.Clock.installed = jasmine.Clock.real; + +//else for IE support +jasmine.getGlobal().setTimeout = function(funcToCall, millis) { + if (jasmine.Clock.installed.setTimeout.apply) { + return jasmine.Clock.installed.setTimeout.apply(this, arguments); + } else { + return jasmine.Clock.installed.setTimeout(funcToCall, millis); + } +}; + +jasmine.getGlobal().setInterval = function(funcToCall, millis) { + if (jasmine.Clock.installed.setInterval.apply) { + return jasmine.Clock.installed.setInterval.apply(this, arguments); + } else { + return jasmine.Clock.installed.setInterval(funcToCall, millis); + } +}; + +jasmine.getGlobal().clearTimeout = function(timeoutKey) { + if (jasmine.Clock.installed.clearTimeout.apply) { + return jasmine.Clock.installed.clearTimeout.apply(this, arguments); + } else { + return jasmine.Clock.installed.clearTimeout(timeoutKey); + } +}; + +jasmine.getGlobal().clearInterval = function(timeoutKey) { + if (jasmine.Clock.installed.clearTimeout.apply) { + return jasmine.Clock.installed.clearInterval.apply(this, arguments); + } else { + return jasmine.Clock.installed.clearInterval(timeoutKey); + } +}; + +jasmine.version_= { + "major": 1, + "minor": 1, + "build": 0, + "revision": 1315677058 +}; diff --git a/GildedRose/js/lib/jasmine-1.1.0/jasmine_favicon.png b/GildedRose/js/lib/jasmine-1.1.0/jasmine_favicon.png new file mode 100644 index 0000000000000000000000000000000000000000..218f3b43713598fa5a3e78b57aceb909c33f46df GIT binary patch literal 905 zcmV;419tq0P)Px#AY({UO#lFTCIA3{ga82g0001h=l}q9FaQARU;qF* zm;eA5aGbhPJOBUy24YJ`L;(K){{a7>y{D4^000SaNLh0L01FcU01FcV0GgZ_0008u zNkl3{fod28|PjmA)7fYg4w8-(2my9xtBGOs}K`n&t1VzxMO^X)M zrW+Ln1udc?q6TP)z5gAjt)P&D!M$+HJK#x<`xnD030zwD?KrxxY!2tlA zGc-58?0D7SsT)7Km=v+tNVNUk`?s@;^OxCF)y6P}_mL;~7;S<@b|MzmKq)m8l@yky zT1~ECpxZw@64!nkI34QLiUsA%i%N>-$&zGYR7WJyi9ERMyS(%kf z7A_r)X>!90&m(FwDQZ>q;+nOa*KR2+E6Fz)QwU=W1Oyo*4>_qlm|~joa|{4_A_3W8 z#FFZzRp-xMIx5a7D_Fj3&#r^TbIY@cND1d0f*^qDIs{!pw!IWGQ_%l4#ASm_D5Vet z0%ek7^)@xPihX_G0&hIc9*14ca=D!8oG}vW?H%~w^F?f_s>zU|fKrNJXJ_d6{v!t( zpEoqMws_yQws>3o?VW8Txq~#->dJG^ELW5irR!s`(_JvD^6;r+ho~eIK@ia8_lH(h zt*-p?CFC1_h2MV=?jP){uW!7WjLjCaO&c1D+tf582!XEaoB#xWAYcN5f$sLtf$koW zQs{{>)ZTq?FC6|J_%n}AWbiFK(Bo-%^-{H`*)E(ucjo-r%SYm)W5f6tN=xz=S646E fNXW#U{x?4WXWJ 0) { + return ajaxRequests[ajaxRequests.length - 1]; + } else { + return null; + } +} + +function clearAjaxRequests() { + ajaxRequests = []; +} + +// Fake XHR for mocking Ajax Requests & Responses +function FakeXMLHttpRequest() { + var extend = Object.extend || $.extend; + extend(this, { + requestHeaders: {}, + + open: function() { + this.method = arguments[0]; + this.url = arguments[1]; + this.readyState = 1; + }, + + setRequestHeader: function(header, value) { + this.requestHeaders[header] = value; + }, + + abort: function() { + this.readyState = 0; + }, + + readyState: 0, + + onreadystatechange: function(isTimeout) { + }, + + status: null, + + send: function(data) { + this.params = data; + this.readyState = 2; + }, + + getResponseHeader: function(name) { + return this.responseHeaders[name]; + }, + + getAllResponseHeaders: function() { + var responseHeaders = []; + for (var i in this.responseHeaders) { + if (this.responseHeaders.hasOwnProperty(i)) { + responseHeaders.push(i + ': ' + this.responseHeaders[i]); + } + } + return responseHeaders.join('\r\n'); + }, + + responseText: null, + + response: function(response) { + this.status = response.status; + this.responseText = response.responseText || ""; + this.readyState = 4; + this.responseHeaders = response.responseHeaders || + {"Content-type": response.contentType || "application/json" }; + // uncomment for jquery 1.3.x support + // jasmine.Clock.tick(20); + + this.onreadystatechange(); + }, + responseTimeout: function() { + this.readyState = 4; + jasmine.Clock.tick(jQuery.ajaxSettings.timeout || 30000); + this.onreadystatechange('timeout'); + } + }); + + return this; +} + + +jasmine.Ajax = { + + isInstalled: function() { + return jasmine.Ajax.installed == true; + }, + + assertInstalled: function() { + if (!jasmine.Ajax.isInstalled()) { + throw new Error("Mock ajax is not installed, use jasmine.Ajax.useMock()") + } + }, + + useMock: function() { + if (!jasmine.Ajax.isInstalled()) { + var spec = jasmine.getEnv().currentSpec; + spec.after(jasmine.Ajax.uninstallMock); + + jasmine.Ajax.installMock(); + } + }, + + installMock: function() { + if (typeof jQuery != 'undefined') { + jasmine.Ajax.installJquery(); + } else if (typeof Prototype != 'undefined') { + jasmine.Ajax.installPrototype(); + } else { + throw new Error("jasmine.Ajax currently only supports jQuery and Prototype"); + } + jasmine.Ajax.installed = true; + }, + + installJquery: function() { + jasmine.Ajax.mode = 'jQuery'; + jasmine.Ajax.real = jQuery.ajaxSettings.xhr; + jQuery.ajaxSettings.xhr = jasmine.Ajax.jQueryMock; + + }, + + installPrototype: function() { + jasmine.Ajax.mode = 'Prototype'; + jasmine.Ajax.real = Ajax.getTransport; + + Ajax.getTransport = jasmine.Ajax.prototypeMock; + }, + + uninstallMock: function() { + jasmine.Ajax.assertInstalled(); + if (jasmine.Ajax.mode == 'jQuery') { + jQuery.ajaxSettings.xhr = jasmine.Ajax.real; + } else if (jasmine.Ajax.mode == 'Prototype') { + Ajax.getTransport = jasmine.Ajax.real; + } + jasmine.Ajax.reset(); + }, + + reset: function() { + jasmine.Ajax.installed = false; + jasmine.Ajax.mode = null; + jasmine.Ajax.real = null; + }, + + jQueryMock: function() { + var newXhr = new FakeXMLHttpRequest(); + ajaxRequests.push(newXhr); + return newXhr; + }, + + prototypeMock: function() { + return new FakeXMLHttpRequest(); + }, + + installed: false, + mode: null +} + + +// Jasmine-Ajax Glue code for Prototype.js +if (typeof Prototype != 'undefined' && Ajax && Ajax.Request) { + Ajax.Request.prototype.originalRequest = Ajax.Request.prototype.request; + Ajax.Request.prototype.request = function(url) { + this.originalRequest(url); + ajaxRequests.push(this); + }; + + Ajax.Request.prototype.response = function(responseOptions) { + return this.transport.response(responseOptions); + }; +} diff --git a/GildedRose/js/lib/jasmine-jquery-1.3.1/jasmine-jquery-1.3.1.js b/GildedRose/js/lib/jasmine-jquery-1.3.1/jasmine-jquery-1.3.1.js new file mode 100644 index 00000000..7e85548a --- /dev/null +++ b/GildedRose/js/lib/jasmine-jquery-1.3.1/jasmine-jquery-1.3.1.js @@ -0,0 +1,288 @@ +var readFixtures = function() { + return jasmine.getFixtures().proxyCallTo_('read', arguments); +}; + +var preloadFixtures = function() { + jasmine.getFixtures().proxyCallTo_('preload', arguments); +}; + +var loadFixtures = function() { + jasmine.getFixtures().proxyCallTo_('load', arguments); +}; + +var setFixtures = function(html) { + jasmine.getFixtures().set(html); +}; + +var sandbox = function(attributes) { + return jasmine.getFixtures().sandbox(attributes); +}; + +var spyOnEvent = function(selector, eventName) { + jasmine.JQuery.events.spyOn(selector, eventName); +} + +jasmine.getFixtures = function() { + return jasmine.currentFixtures_ = jasmine.currentFixtures_ || new jasmine.Fixtures(); +}; + +jasmine.Fixtures = function() { + this.containerId = 'jasmine-fixtures'; + this.fixturesCache_ = {}; + this.fixturesPath = 'spec/javascripts/fixtures'; +}; + +jasmine.Fixtures.prototype.set = function(html) { + this.cleanUp(); + this.createContainer_(html); +}; + +jasmine.Fixtures.prototype.preload = function() { + this.read.apply(this, arguments); +}; + +jasmine.Fixtures.prototype.load = function() { + this.cleanUp(); + this.createContainer_(this.read.apply(this, arguments)); +}; + +jasmine.Fixtures.prototype.read = function() { + var htmlChunks = []; + + var fixtureUrls = arguments; + for(var urlCount = fixtureUrls.length, urlIndex = 0; urlIndex < urlCount; urlIndex++) { + htmlChunks.push(this.getFixtureHtml_(fixtureUrls[urlIndex])); + } + + return htmlChunks.join(''); +}; + +jasmine.Fixtures.prototype.clearCache = function() { + this.fixturesCache_ = {}; +}; + +jasmine.Fixtures.prototype.cleanUp = function() { + jQuery('#' + this.containerId).remove(); +}; + +jasmine.Fixtures.prototype.sandbox = function(attributes) { + var attributesToSet = attributes || {}; + return jQuery('
').attr(attributesToSet); +}; + +jasmine.Fixtures.prototype.createContainer_ = function(html) { + var container; + if(html instanceof jQuery) { + container = jQuery('
'); + container.html(html); + } else { + container = '
' + html + '
' + } + jQuery('body').append(container); +}; + +jasmine.Fixtures.prototype.getFixtureHtml_ = function(url) { + if (typeof this.fixturesCache_[url] == 'undefined') { + this.loadFixtureIntoCache_(url); + } + return this.fixturesCache_[url]; +}; + +jasmine.Fixtures.prototype.loadFixtureIntoCache_ = function(relativeUrl) { + var self = this; + var url = this.fixturesPath.match('/$') ? this.fixturesPath + relativeUrl : this.fixturesPath + '/' + relativeUrl; + jQuery.ajax({ + async: false, // must be synchronous to guarantee that no tests are run before fixture is loaded + cache: false, + dataType: 'html', + url: url, + success: function(data) { + self.fixturesCache_[relativeUrl] = data; + }, + error: function(jqXHR, status, errorThrown) { + throw Error('Fixture could not be loaded: ' + url + ' (status: ' + status + ', message: ' + errorThrown.message + ')'); + } + }); +}; + +jasmine.Fixtures.prototype.proxyCallTo_ = function(methodName, passedArguments) { + return this[methodName].apply(this, passedArguments); +}; + + +jasmine.JQuery = function() {}; + +jasmine.JQuery.browserTagCaseIndependentHtml = function(html) { + return jQuery('
').append(html).html(); +}; + +jasmine.JQuery.elementToString = function(element) { + return jQuery('
').append(element.clone()).html(); +}; + +jasmine.JQuery.matchersClass = {}; + +(function(namespace) { + var data = { + spiedEvents: {}, + handlers: [] + }; + + namespace.events = { + spyOn: function(selector, eventName) { + var handler = function(e) { + data.spiedEvents[[selector, eventName]] = e; + }; + jQuery(selector).bind(eventName, handler); + data.handlers.push(handler); + }, + + wasTriggered: function(selector, eventName) { + return !!(data.spiedEvents[[selector, eventName]]); + }, + + cleanUp: function() { + data.spiedEvents = {}; + data.handlers = []; + } + } +})(jasmine.JQuery); + +(function(){ + var jQueryMatchers = { + toHaveClass: function(className) { + return this.actual.hasClass(className); + }, + + toBeVisible: function() { + return this.actual.is(':visible'); + }, + + toBeHidden: function() { + return this.actual.is(':hidden'); + }, + + toBeSelected: function() { + return this.actual.is(':selected'); + }, + + toBeChecked: function() { + return this.actual.is(':checked'); + }, + + toBeEmpty: function() { + return this.actual.is(':empty'); + }, + + toExist: function() { + return this.actual.size() > 0; + }, + + toHaveAttr: function(attributeName, expectedAttributeValue) { + return hasProperty(this.actual.attr(attributeName), expectedAttributeValue); + }, + + toHaveId: function(id) { + return this.actual.attr('id') == id; + }, + + toHaveHtml: function(html) { + return this.actual.html() == jasmine.JQuery.browserTagCaseIndependentHtml(html); + }, + + toHaveText: function(text) { + if (text && jQuery.isFunction(text.test)) { + return text.test(this.actual.text()); + } else { + return this.actual.text() == text; + } + }, + + toHaveValue: function(value) { + return this.actual.val() == value; + }, + + toHaveData: function(key, expectedValue) { + return hasProperty(this.actual.data(key), expectedValue); + }, + + toBe: function(selector) { + return this.actual.is(selector); + }, + + toContain: function(selector) { + return this.actual.find(selector).size() > 0; + }, + + toBeDisabled: function(selector){ + return this.actual.is(':disabled'); + }, + + // tests the existence of a specific event binding + toHandle: function(eventName) { + var events = this.actual.data("events"); + return events && events[eventName].length > 0; + }, + + // tests the existence of a specific event binding + handler + toHandleWith: function(eventName, eventHandler) { + var stack = this.actual.data("events")[eventName]; + var i; + for (i = 0; i < stack.length; i++) { + if (stack[i].handler == eventHandler) { + return true; + } + } + return false; + } + }; + + var hasProperty = function(actualValue, expectedValue) { + if (expectedValue === undefined) { + return actualValue !== undefined; + } + return actualValue == expectedValue; + }; + + var bindMatcher = function(methodName) { + var builtInMatcher = jasmine.Matchers.prototype[methodName]; + + jasmine.JQuery.matchersClass[methodName] = function() { + if (this.actual instanceof jQuery) { + var result = jQueryMatchers[methodName].apply(this, arguments); + this.actual = jasmine.JQuery.elementToString(this.actual); + return result; + } + + if (builtInMatcher) { + return builtInMatcher.apply(this, arguments); + } + + return false; + }; + }; + + for(var methodName in jQueryMatchers) { + bindMatcher(methodName); + } +})(); + +beforeEach(function() { + this.addMatchers(jasmine.JQuery.matchersClass); + this.addMatchers({ + toHaveBeenTriggeredOn: function(selector) { + this.message = function() { + return [ + "Expected event " + this.actual + " to have been triggered on" + selector, + "Expected event " + this.actual + " not to have been triggered on" + selector + ]; + }; + return jasmine.JQuery.events.wasTriggered(selector, this.actual); + } + }) +}); + +afterEach(function() { + jasmine.getFixtures().cleanUp(); + jasmine.JQuery.events.cleanUp(); +}); diff --git a/GildedRose/js/lib/jquery-1.7.1/jquery-1.7.1.js b/GildedRose/js/lib/jquery-1.7.1/jquery-1.7.1.js new file mode 100644 index 00000000..8ccd0ea7 --- /dev/null +++ b/GildedRose/js/lib/jquery-1.7.1/jquery-1.7.1.js @@ -0,0 +1,9266 @@ +/*! + * jQuery JavaScript Library v1.7.1 + * http://jquery.com/ + * + * Copyright 2011, John Resig + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * Includes Sizzle.js + * http://sizzlejs.com/ + * Copyright 2011, The Dojo Foundation + * Released under the MIT, BSD, and GPL Licenses. + * + * Date: Mon Nov 21 21:11:03 2011 -0500 + */ +(function( window, undefined ) { + +// Use the correct document accordingly with window argument (sandbox) +var document = window.document, + navigator = window.navigator, + location = window.location; +var jQuery = (function() { + +// Define a local copy of jQuery +var jQuery = function( selector, context ) { + // The jQuery object is actually just the init constructor 'enhanced' + return new jQuery.fn.init( selector, context, rootjQuery ); + }, + + // Map over jQuery in case of overwrite + _jQuery = window.jQuery, + + // Map over the $ in case of overwrite + _$ = window.$, + + // A central reference to the root jQuery(document) + rootjQuery, + + // A simple way to check for HTML strings or ID strings + // Prioritize #id over to avoid XSS via location.hash (#9521) + quickExpr = /^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/, + + // Check if a string has a non-whitespace character in it + rnotwhite = /\S/, + + // Used for trimming whitespace + trimLeft = /^\s+/, + trimRight = /\s+$/, + + // Match a standalone tag + rsingleTag = /^<(\w+)\s*\/?>(?:<\/\1>)?$/, + + // JSON RegExp + rvalidchars = /^[\],:{}\s]*$/, + rvalidescape = /\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, + rvalidtokens = /"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, + rvalidbraces = /(?:^|:|,)(?:\s*\[)+/g, + + // Useragent RegExp + rwebkit = /(webkit)[ \/]([\w.]+)/, + ropera = /(opera)(?:.*version)?[ \/]([\w.]+)/, + rmsie = /(msie) ([\w.]+)/, + rmozilla = /(mozilla)(?:.*? rv:([\w.]+))?/, + + // Matches dashed string for camelizing + rdashAlpha = /-([a-z]|[0-9])/ig, + rmsPrefix = /^-ms-/, + + // Used by jQuery.camelCase as callback to replace() + fcamelCase = function( all, letter ) { + return ( letter + "" ).toUpperCase(); + }, + + // Keep a UserAgent string for use with jQuery.browser + userAgent = navigator.userAgent, + + // For matching the engine and version of the browser + browserMatch, + + // The deferred used on DOM ready + readyList, + + // The ready event handler + DOMContentLoaded, + + // Save a reference to some core methods + toString = Object.prototype.toString, + hasOwn = Object.prototype.hasOwnProperty, + push = Array.prototype.push, + slice = Array.prototype.slice, + trim = String.prototype.trim, + indexOf = Array.prototype.indexOf, + + // [[Class]] -> type pairs + class2type = {}; + +jQuery.fn = jQuery.prototype = { + constructor: jQuery, + init: function( selector, context, rootjQuery ) { + var match, elem, ret, doc; + + // Handle $(""), $(null), or $(undefined) + if ( !selector ) { + return this; + } + + // Handle $(DOMElement) + if ( selector.nodeType ) { + this.context = this[0] = selector; + this.length = 1; + return this; + } + + // The body element only exists once, optimize finding it + if ( selector === "body" && !context && document.body ) { + this.context = document; + this[0] = document.body; + this.selector = selector; + this.length = 1; + return this; + } + + // Handle HTML strings + if ( typeof selector === "string" ) { + // Are we dealing with HTML string or an ID? + if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) { + // Assume that strings that start and end with <> are HTML and skip the regex check + match = [ null, selector, null ]; + + } else { + match = quickExpr.exec( selector ); + } + + // Verify a match, and that no context was specified for #id + if ( match && (match[1] || !context) ) { + + // HANDLE: $(html) -> $(array) + if ( match[1] ) { + context = context instanceof jQuery ? context[0] : context; + doc = ( context ? context.ownerDocument || context : document ); + + // If a single string is passed in and it's a single tag + // just do a createElement and skip the rest + ret = rsingleTag.exec( selector ); + + if ( ret ) { + if ( jQuery.isPlainObject( context ) ) { + selector = [ document.createElement( ret[1] ) ]; + jQuery.fn.attr.call( selector, context, true ); + + } else { + selector = [ doc.createElement( ret[1] ) ]; + } + + } else { + ret = jQuery.buildFragment( [ match[1] ], [ doc ] ); + selector = ( ret.cacheable ? jQuery.clone(ret.fragment) : ret.fragment ).childNodes; + } + + return jQuery.merge( this, selector ); + + // HANDLE: $("#id") + } else { + elem = document.getElementById( match[2] ); + + // Check parentNode to catch when Blackberry 4.6 returns + // nodes that are no longer in the document #6963 + if ( elem && elem.parentNode ) { + // Handle the case where IE and Opera return items + // by name instead of ID + if ( elem.id !== match[2] ) { + return rootjQuery.find( selector ); + } + + // Otherwise, we inject the element directly into the jQuery object + this.length = 1; + this[0] = elem; + } + + this.context = document; + this.selector = selector; + return this; + } + + // HANDLE: $(expr, $(...)) + } else if ( !context || context.jquery ) { + return ( context || rootjQuery ).find( selector ); + + // HANDLE: $(expr, context) + // (which is just equivalent to: $(context).find(expr) + } else { + return this.constructor( context ).find( selector ); + } + + // HANDLE: $(function) + // Shortcut for document ready + } else if ( jQuery.isFunction( selector ) ) { + return rootjQuery.ready( selector ); + } + + if ( selector.selector !== undefined ) { + this.selector = selector.selector; + this.context = selector.context; + } + + return jQuery.makeArray( selector, this ); + }, + + // Start with an empty selector + selector: "", + + // The current version of jQuery being used + jquery: "1.7.1", + + // The default length of a jQuery object is 0 + length: 0, + + // The number of elements contained in the matched element set + size: function() { + return this.length; + }, + + toArray: function() { + return slice.call( this, 0 ); + }, + + // Get the Nth element in the matched element set OR + // Get the whole matched element set as a clean array + get: function( num ) { + return num == null ? + + // Return a 'clean' array + this.toArray() : + + // Return just the object + ( num < 0 ? this[ this.length + num ] : this[ num ] ); + }, + + // Take an array of elements and push it onto the stack + // (returning the new matched element set) + pushStack: function( elems, name, selector ) { + // Build a new jQuery matched element set + var ret = this.constructor(); + + if ( jQuery.isArray( elems ) ) { + push.apply( ret, elems ); + + } else { + jQuery.merge( ret, elems ); + } + + // Add the old object onto the stack (as a reference) + ret.prevObject = this; + + ret.context = this.context; + + if ( name === "find" ) { + ret.selector = this.selector + ( this.selector ? " " : "" ) + selector; + } else if ( name ) { + ret.selector = this.selector + "." + name + "(" + selector + ")"; + } + + // Return the newly-formed element set + return ret; + }, + + // Execute a callback for every element in the matched set. + // (You can seed the arguments with an array of args, but this is + // only used internally.) + each: function( callback, args ) { + return jQuery.each( this, callback, args ); + }, + + ready: function( fn ) { + // Attach the listeners + jQuery.bindReady(); + + // Add the callback + readyList.add( fn ); + + return this; + }, + + eq: function( i ) { + i = +i; + return i === -1 ? + this.slice( i ) : + this.slice( i, i + 1 ); + }, + + first: function() { + return this.eq( 0 ); + }, + + last: function() { + return this.eq( -1 ); + }, + + slice: function() { + return this.pushStack( slice.apply( this, arguments ), + "slice", slice.call(arguments).join(",") ); + }, + + map: function( callback ) { + return this.pushStack( jQuery.map(this, function( elem, i ) { + return callback.call( elem, i, elem ); + })); + }, + + end: function() { + return this.prevObject || this.constructor(null); + }, + + // For internal use only. + // Behaves like an Array's method, not like a jQuery method. + push: push, + sort: [].sort, + splice: [].splice +}; + +// Give the init function the jQuery prototype for later instantiation +jQuery.fn.init.prototype = jQuery.fn; + +jQuery.extend = jQuery.fn.extend = function() { + var options, name, src, copy, copyIsArray, clone, + target = arguments[0] || {}, + i = 1, + length = arguments.length, + deep = false; + + // Handle a deep copy situation + if ( typeof target === "boolean" ) { + deep = target; + target = arguments[1] || {}; + // skip the boolean and the target + i = 2; + } + + // Handle case when target is a string or something (possible in deep copy) + if ( typeof target !== "object" && !jQuery.isFunction(target) ) { + target = {}; + } + + // extend jQuery itself if only one argument is passed + if ( length === i ) { + target = this; + --i; + } + + for ( ; i < length; i++ ) { + // Only deal with non-null/undefined values + if ( (options = arguments[ i ]) != null ) { + // Extend the base object + for ( name in options ) { + src = target[ name ]; + copy = options[ name ]; + + // Prevent never-ending loop + if ( target === copy ) { + continue; + } + + // Recurse if we're merging plain objects or arrays + if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) { + if ( copyIsArray ) { + copyIsArray = false; + clone = src && jQuery.isArray(src) ? src : []; + + } else { + clone = src && jQuery.isPlainObject(src) ? src : {}; + } + + // Never move original objects, clone them + target[ name ] = jQuery.extend( deep, clone, copy ); + + // Don't bring in undefined values + } else if ( copy !== undefined ) { + target[ name ] = copy; + } + } + } + } + + // Return the modified object + return target; +}; + +jQuery.extend({ + noConflict: function( deep ) { + if ( window.$ === jQuery ) { + window.$ = _$; + } + + if ( deep && window.jQuery === jQuery ) { + window.jQuery = _jQuery; + } + + return jQuery; + }, + + // Is the DOM ready to be used? Set to true once it occurs. + isReady: false, + + // A counter to track how many items to wait for before + // the ready event fires. See #6781 + readyWait: 1, + + // Hold (or release) the ready event + holdReady: function( hold ) { + if ( hold ) { + jQuery.readyWait++; + } else { + jQuery.ready( true ); + } + }, + + // Handle when the DOM is ready + ready: function( wait ) { + // Either a released hold or an DOMready/load event and not yet ready + if ( (wait === true && !--jQuery.readyWait) || (wait !== true && !jQuery.isReady) ) { + // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443). + if ( !document.body ) { + return setTimeout( jQuery.ready, 1 ); + } + + // Remember that the DOM is ready + jQuery.isReady = true; + + // If a normal DOM Ready event fired, decrement, and wait if need be + if ( wait !== true && --jQuery.readyWait > 0 ) { + return; + } + + // If there are functions bound, to execute + readyList.fireWith( document, [ jQuery ] ); + + // Trigger any bound ready events + if ( jQuery.fn.trigger ) { + jQuery( document ).trigger( "ready" ).off( "ready" ); + } + } + }, + + bindReady: function() { + if ( readyList ) { + return; + } + + readyList = jQuery.Callbacks( "once memory" ); + + // Catch cases where $(document).ready() is called after the + // browser event has already occurred. + if ( document.readyState === "complete" ) { + // Handle it asynchronously to allow scripts the opportunity to delay ready + return setTimeout( jQuery.ready, 1 ); + } + + // Mozilla, Opera and webkit nightlies currently support this event + if ( document.addEventListener ) { + // Use the handy event callback + document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false ); + + // A fallback to window.onload, that will always work + window.addEventListener( "load", jQuery.ready, false ); + + // If IE event model is used + } else if ( document.attachEvent ) { + // ensure firing before onload, + // maybe late but safe also for iframes + document.attachEvent( "onreadystatechange", DOMContentLoaded ); + + // A fallback to window.onload, that will always work + window.attachEvent( "onload", jQuery.ready ); + + // If IE and not a frame + // continually check to see if the document is ready + var toplevel = false; + + try { + toplevel = window.frameElement == null; + } catch(e) {} + + if ( document.documentElement.doScroll && toplevel ) { + doScrollCheck(); + } + } + }, + + // See test/unit/core.js for details concerning isFunction. + // Since version 1.3, DOM methods and functions like alert + // aren't supported. They return false on IE (#2968). + isFunction: function( obj ) { + return jQuery.type(obj) === "function"; + }, + + isArray: Array.isArray || function( obj ) { + return jQuery.type(obj) === "array"; + }, + + // A crude way of determining if an object is a window + isWindow: function( obj ) { + return obj && typeof obj === "object" && "setInterval" in obj; + }, + + isNumeric: function( obj ) { + return !isNaN( parseFloat(obj) ) && isFinite( obj ); + }, + + type: function( obj ) { + return obj == null ? + String( obj ) : + class2type[ toString.call(obj) ] || "object"; + }, + + isPlainObject: function( obj ) { + // Must be an Object. + // Because of IE, we also have to check the presence of the constructor property. + // Make sure that DOM nodes and window objects don't pass through, as well + if ( !obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) { + return false; + } + + try { + // Not own constructor property must be Object + if ( obj.constructor && + !hasOwn.call(obj, "constructor") && + !hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) { + return false; + } + } catch ( e ) { + // IE8,9 Will throw exceptions on certain host objects #9897 + return false; + } + + // Own properties are enumerated firstly, so to speed up, + // if last one is own, then all properties are own. + + var key; + for ( key in obj ) {} + + return key === undefined || hasOwn.call( obj, key ); + }, + + isEmptyObject: function( obj ) { + for ( var name in obj ) { + return false; + } + return true; + }, + + error: function( msg ) { + throw new Error( msg ); + }, + + parseJSON: function( data ) { + if ( typeof data !== "string" || !data ) { + return null; + } + + // Make sure leading/trailing whitespace is removed (IE can't handle it) + data = jQuery.trim( data ); + + // Attempt to parse using the native JSON parser first + if ( window.JSON && window.JSON.parse ) { + return window.JSON.parse( data ); + } + + // Make sure the incoming data is actual JSON + // Logic borrowed from http://json.org/json2.js + if ( rvalidchars.test( data.replace( rvalidescape, "@" ) + .replace( rvalidtokens, "]" ) + .replace( rvalidbraces, "")) ) { + + return ( new Function( "return " + data ) )(); + + } + jQuery.error( "Invalid JSON: " + data ); + }, + + // Cross-browser xml parsing + parseXML: function( data ) { + var xml, tmp; + try { + if ( window.DOMParser ) { // Standard + tmp = new DOMParser(); + xml = tmp.parseFromString( data , "text/xml" ); + } else { // IE + xml = new ActiveXObject( "Microsoft.XMLDOM" ); + xml.async = "false"; + xml.loadXML( data ); + } + } catch( e ) { + xml = undefined; + } + if ( !xml || !xml.documentElement || xml.getElementsByTagName( "parsererror" ).length ) { + jQuery.error( "Invalid XML: " + data ); + } + return xml; + }, + + noop: function() {}, + + // Evaluates a script in a global context + // Workarounds based on findings by Jim Driscoll + // http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context + globalEval: function( data ) { + if ( data && rnotwhite.test( data ) ) { + // We use execScript on Internet Explorer + // We use an anonymous function so that context is window + // rather than jQuery in Firefox + ( window.execScript || function( data ) { + window[ "eval" ].call( window, data ); + } )( data ); + } + }, + + // Convert dashed to camelCase; used by the css and data modules + // Microsoft forgot to hump their vendor prefix (#9572) + camelCase: function( string ) { + return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase ); + }, + + nodeName: function( elem, name ) { + return elem.nodeName && elem.nodeName.toUpperCase() === name.toUpperCase(); + }, + + // args is for internal usage only + each: function( object, callback, args ) { + var name, i = 0, + length = object.length, + isObj = length === undefined || jQuery.isFunction( object ); + + if ( args ) { + if ( isObj ) { + for ( name in object ) { + if ( callback.apply( object[ name ], args ) === false ) { + break; + } + } + } else { + for ( ; i < length; ) { + if ( callback.apply( object[ i++ ], args ) === false ) { + break; + } + } + } + + // A special, fast, case for the most common use of each + } else { + if ( isObj ) { + for ( name in object ) { + if ( callback.call( object[ name ], name, object[ name ] ) === false ) { + break; + } + } + } else { + for ( ; i < length; ) { + if ( callback.call( object[ i ], i, object[ i++ ] ) === false ) { + break; + } + } + } + } + + return object; + }, + + // Use native String.trim function wherever possible + trim: trim ? + function( text ) { + return text == null ? + "" : + trim.call( text ); + } : + + // Otherwise use our own trimming functionality + function( text ) { + return text == null ? + "" : + text.toString().replace( trimLeft, "" ).replace( trimRight, "" ); + }, + + // results is for internal usage only + makeArray: function( array, results ) { + var ret = results || []; + + if ( array != null ) { + // The window, strings (and functions) also have 'length' + // Tweaked logic slightly to handle Blackberry 4.7 RegExp issues #6930 + var type = jQuery.type( array ); + + if ( array.length == null || type === "string" || type === "function" || type === "regexp" || jQuery.isWindow( array ) ) { + push.call( ret, array ); + } else { + jQuery.merge( ret, array ); + } + } + + return ret; + }, + + inArray: function( elem, array, i ) { + var len; + + if ( array ) { + if ( indexOf ) { + return indexOf.call( array, elem, i ); + } + + len = array.length; + i = i ? i < 0 ? Math.max( 0, len + i ) : i : 0; + + for ( ; i < len; i++ ) { + // Skip accessing in sparse arrays + if ( i in array && array[ i ] === elem ) { + return i; + } + } + } + + return -1; + }, + + merge: function( first, second ) { + var i = first.length, + j = 0; + + if ( typeof second.length === "number" ) { + for ( var l = second.length; j < l; j++ ) { + first[ i++ ] = second[ j ]; + } + + } else { + while ( second[j] !== undefined ) { + first[ i++ ] = second[ j++ ]; + } + } + + first.length = i; + + return first; + }, + + grep: function( elems, callback, inv ) { + var ret = [], retVal; + inv = !!inv; + + // Go through the array, only saving the items + // that pass the validator function + for ( var i = 0, length = elems.length; i < length; i++ ) { + retVal = !!callback( elems[ i ], i ); + if ( inv !== retVal ) { + ret.push( elems[ i ] ); + } + } + + return ret; + }, + + // arg is for internal usage only + map: function( elems, callback, arg ) { + var value, key, ret = [], + i = 0, + length = elems.length, + // jquery objects are treated as arrays + isArray = elems instanceof jQuery || length !== undefined && typeof length === "number" && ( ( length > 0 && elems[ 0 ] && elems[ length -1 ] ) || length === 0 || jQuery.isArray( elems ) ) ; + + // Go through the array, translating each of the items to their + if ( isArray ) { + for ( ; i < length; i++ ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret[ ret.length ] = value; + } + } + + // Go through every key on the object, + } else { + for ( key in elems ) { + value = callback( elems[ key ], key, arg ); + + if ( value != null ) { + ret[ ret.length ] = value; + } + } + } + + // Flatten any nested arrays + return ret.concat.apply( [], ret ); + }, + + // A global GUID counter for objects + guid: 1, + + // Bind a function to a context, optionally partially applying any + // arguments. + proxy: function( fn, context ) { + if ( typeof context === "string" ) { + var tmp = fn[ context ]; + context = fn; + fn = tmp; + } + + // Quick check to determine if target is callable, in the spec + // this throws a TypeError, but we will just return undefined. + if ( !jQuery.isFunction( fn ) ) { + return undefined; + } + + // Simulated bind + var args = slice.call( arguments, 2 ), + proxy = function() { + return fn.apply( context, args.concat( slice.call( arguments ) ) ); + }; + + // Set the guid of unique handler to the same of original handler, so it can be removed + proxy.guid = fn.guid = fn.guid || proxy.guid || jQuery.guid++; + + return proxy; + }, + + // Mutifunctional method to get and set values to a collection + // The value/s can optionally be executed if it's a function + access: function( elems, key, value, exec, fn, pass ) { + var length = elems.length; + + // Setting many attributes + if ( typeof key === "object" ) { + for ( var k in key ) { + jQuery.access( elems, k, key[k], exec, fn, value ); + } + return elems; + } + + // Setting one attribute + if ( value !== undefined ) { + // Optionally, function values get executed if exec is true + exec = !pass && exec && jQuery.isFunction(value); + + for ( var i = 0; i < length; i++ ) { + fn( elems[i], key, exec ? value.call( elems[i], i, fn( elems[i], key ) ) : value, pass ); + } + + return elems; + } + + // Getting an attribute + return length ? fn( elems[0], key ) : undefined; + }, + + now: function() { + return ( new Date() ).getTime(); + }, + + // Use of jQuery.browser is frowned upon. + // More details: http://docs.jquery.com/Utilities/jQuery.browser + uaMatch: function( ua ) { + ua = ua.toLowerCase(); + + var match = rwebkit.exec( ua ) || + ropera.exec( ua ) || + rmsie.exec( ua ) || + ua.indexOf("compatible") < 0 && rmozilla.exec( ua ) || + []; + + return { browser: match[1] || "", version: match[2] || "0" }; + }, + + sub: function() { + function jQuerySub( selector, context ) { + return new jQuerySub.fn.init( selector, context ); + } + jQuery.extend( true, jQuerySub, this ); + jQuerySub.superclass = this; + jQuerySub.fn = jQuerySub.prototype = this(); + jQuerySub.fn.constructor = jQuerySub; + jQuerySub.sub = this.sub; + jQuerySub.fn.init = function init( selector, context ) { + if ( context && context instanceof jQuery && !(context instanceof jQuerySub) ) { + context = jQuerySub( context ); + } + + return jQuery.fn.init.call( this, selector, context, rootjQuerySub ); + }; + jQuerySub.fn.init.prototype = jQuerySub.fn; + var rootjQuerySub = jQuerySub(document); + return jQuerySub; + }, + + browser: {} +}); + +// Populate the class2type map +jQuery.each("Boolean Number String Function Array Date RegExp Object".split(" "), function(i, name) { + class2type[ "[object " + name + "]" ] = name.toLowerCase(); +}); + +browserMatch = jQuery.uaMatch( userAgent ); +if ( browserMatch.browser ) { + jQuery.browser[ browserMatch.browser ] = true; + jQuery.browser.version = browserMatch.version; +} + +// Deprecated, use jQuery.browser.webkit instead +if ( jQuery.browser.webkit ) { + jQuery.browser.safari = true; +} + +// IE doesn't match non-breaking spaces with \s +if ( rnotwhite.test( "\xA0" ) ) { + trimLeft = /^[\s\xA0]+/; + trimRight = /[\s\xA0]+$/; +} + +// All jQuery objects should point back to these +rootjQuery = jQuery(document); + +// Cleanup functions for the document ready method +if ( document.addEventListener ) { + DOMContentLoaded = function() { + document.removeEventListener( "DOMContentLoaded", DOMContentLoaded, false ); + jQuery.ready(); + }; + +} else if ( document.attachEvent ) { + DOMContentLoaded = function() { + // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443). + if ( document.readyState === "complete" ) { + document.detachEvent( "onreadystatechange", DOMContentLoaded ); + jQuery.ready(); + } + }; +} + +// The DOM ready check for Internet Explorer +function doScrollCheck() { + if ( jQuery.isReady ) { + return; + } + + try { + // If IE is used, use the trick by Diego Perini + // http://javascript.nwbox.com/IEContentLoaded/ + document.documentElement.doScroll("left"); + } catch(e) { + setTimeout( doScrollCheck, 1 ); + return; + } + + // and execute any waiting functions + jQuery.ready(); +} + +return jQuery; + +})(); + + +// String to Object flags format cache +var flagsCache = {}; + +// Convert String-formatted flags into Object-formatted ones and store in cache +function createFlags( flags ) { + var object = flagsCache[ flags ] = {}, + i, length; + flags = flags.split( /\s+/ ); + for ( i = 0, length = flags.length; i < length; i++ ) { + object[ flags[i] ] = true; + } + return object; +} + +/* + * Create a callback list using the following parameters: + * + * flags: an optional list of space-separated flags that will change how + * the callback list behaves + * + * By default a callback list will act like an event callback list and can be + * "fired" multiple times. + * + * Possible flags: + * + * once: will ensure the callback list can only be fired once (like a Deferred) + * + * memory: will keep track of previous values and will call any callback added + * after the list has been fired right away with the latest "memorized" + * values (like a Deferred) + * + * unique: will ensure a callback can only be added once (no duplicate in the list) + * + * stopOnFalse: interrupt callings when a callback returns false + * + */ +jQuery.Callbacks = function( flags ) { + + // Convert flags from String-formatted to Object-formatted + // (we check in cache first) + flags = flags ? ( flagsCache[ flags ] || createFlags( flags ) ) : {}; + + var // Actual callback list + list = [], + // Stack of fire calls for repeatable lists + stack = [], + // Last fire value (for non-forgettable lists) + memory, + // Flag to know if list is currently firing + firing, + // First callback to fire (used internally by add and fireWith) + firingStart, + // End of the loop when firing + firingLength, + // Index of currently firing callback (modified by remove if needed) + firingIndex, + // Add one or several callbacks to the list + add = function( args ) { + var i, + length, + elem, + type, + actual; + for ( i = 0, length = args.length; i < length; i++ ) { + elem = args[ i ]; + type = jQuery.type( elem ); + if ( type === "array" ) { + // Inspect recursively + add( elem ); + } else if ( type === "function" ) { + // Add if not in unique mode and callback is not in + if ( !flags.unique || !self.has( elem ) ) { + list.push( elem ); + } + } + } + }, + // Fire callbacks + fire = function( context, args ) { + args = args || []; + memory = !flags.memory || [ context, args ]; + firing = true; + firingIndex = firingStart || 0; + firingStart = 0; + firingLength = list.length; + for ( ; list && firingIndex < firingLength; firingIndex++ ) { + if ( list[ firingIndex ].apply( context, args ) === false && flags.stopOnFalse ) { + memory = true; // Mark as halted + break; + } + } + firing = false; + if ( list ) { + if ( !flags.once ) { + if ( stack && stack.length ) { + memory = stack.shift(); + self.fireWith( memory[ 0 ], memory[ 1 ] ); + } + } else if ( memory === true ) { + self.disable(); + } else { + list = []; + } + } + }, + // Actual Callbacks object + self = { + // Add a callback or a collection of callbacks to the list + add: function() { + if ( list ) { + var length = list.length; + add( arguments ); + // Do we need to add the callbacks to the + // current firing batch? + if ( firing ) { + firingLength = list.length; + // With memory, if we're not firing then + // we should call right away, unless previous + // firing was halted (stopOnFalse) + } else if ( memory && memory !== true ) { + firingStart = length; + fire( memory[ 0 ], memory[ 1 ] ); + } + } + return this; + }, + // Remove a callback from the list + remove: function() { + if ( list ) { + var args = arguments, + argIndex = 0, + argLength = args.length; + for ( ; argIndex < argLength ; argIndex++ ) { + for ( var i = 0; i < list.length; i++ ) { + if ( args[ argIndex ] === list[ i ] ) { + // Handle firingIndex and firingLength + if ( firing ) { + if ( i <= firingLength ) { + firingLength--; + if ( i <= firingIndex ) { + firingIndex--; + } + } + } + // Remove the element + list.splice( i--, 1 ); + // If we have some unicity property then + // we only need to do this once + if ( flags.unique ) { + break; + } + } + } + } + } + return this; + }, + // Control if a given callback is in the list + has: function( fn ) { + if ( list ) { + var i = 0, + length = list.length; + for ( ; i < length; i++ ) { + if ( fn === list[ i ] ) { + return true; + } + } + } + return false; + }, + // Remove all callbacks from the list + empty: function() { + list = []; + return this; + }, + // Have the list do nothing anymore + disable: function() { + list = stack = memory = undefined; + return this; + }, + // Is it disabled? + disabled: function() { + return !list; + }, + // Lock the list in its current state + lock: function() { + stack = undefined; + if ( !memory || memory === true ) { + self.disable(); + } + return this; + }, + // Is it locked? + locked: function() { + return !stack; + }, + // Call all callbacks with the given context and arguments + fireWith: function( context, args ) { + if ( stack ) { + if ( firing ) { + if ( !flags.once ) { + stack.push( [ context, args ] ); + } + } else if ( !( flags.once && memory ) ) { + fire( context, args ); + } + } + return this; + }, + // Call all the callbacks with the given arguments + fire: function() { + self.fireWith( this, arguments ); + return this; + }, + // To know if the callbacks have already been called at least once + fired: function() { + return !!memory; + } + }; + + return self; +}; + + + + +var // Static reference to slice + sliceDeferred = [].slice; + +jQuery.extend({ + + Deferred: function( func ) { + var doneList = jQuery.Callbacks( "once memory" ), + failList = jQuery.Callbacks( "once memory" ), + progressList = jQuery.Callbacks( "memory" ), + state = "pending", + lists = { + resolve: doneList, + reject: failList, + notify: progressList + }, + promise = { + done: doneList.add, + fail: failList.add, + progress: progressList.add, + + state: function() { + return state; + }, + + // Deprecated + isResolved: doneList.fired, + isRejected: failList.fired, + + then: function( doneCallbacks, failCallbacks, progressCallbacks ) { + deferred.done( doneCallbacks ).fail( failCallbacks ).progress( progressCallbacks ); + return this; + }, + always: function() { + deferred.done.apply( deferred, arguments ).fail.apply( deferred, arguments ); + return this; + }, + pipe: function( fnDone, fnFail, fnProgress ) { + return jQuery.Deferred(function( newDefer ) { + jQuery.each( { + done: [ fnDone, "resolve" ], + fail: [ fnFail, "reject" ], + progress: [ fnProgress, "notify" ] + }, function( handler, data ) { + var fn = data[ 0 ], + action = data[ 1 ], + returned; + if ( jQuery.isFunction( fn ) ) { + deferred[ handler ](function() { + returned = fn.apply( this, arguments ); + if ( returned && jQuery.isFunction( returned.promise ) ) { + returned.promise().then( newDefer.resolve, newDefer.reject, newDefer.notify ); + } else { + newDefer[ action + "With" ]( this === deferred ? newDefer : this, [ returned ] ); + } + }); + } else { + deferred[ handler ]( newDefer[ action ] ); + } + }); + }).promise(); + }, + // Get a promise for this deferred + // If obj is provided, the promise aspect is added to the object + promise: function( obj ) { + if ( obj == null ) { + obj = promise; + } else { + for ( var key in promise ) { + obj[ key ] = promise[ key ]; + } + } + return obj; + } + }, + deferred = promise.promise({}), + key; + + for ( key in lists ) { + deferred[ key ] = lists[ key ].fire; + deferred[ key + "With" ] = lists[ key ].fireWith; + } + + // Handle state + deferred.done( function() { + state = "resolved"; + }, failList.disable, progressList.lock ).fail( function() { + state = "rejected"; + }, doneList.disable, progressList.lock ); + + // Call given func if any + if ( func ) { + func.call( deferred, deferred ); + } + + // All done! + return deferred; + }, + + // Deferred helper + when: function( firstParam ) { + var args = sliceDeferred.call( arguments, 0 ), + i = 0, + length = args.length, + pValues = new Array( length ), + count = length, + pCount = length, + deferred = length <= 1 && firstParam && jQuery.isFunction( firstParam.promise ) ? + firstParam : + jQuery.Deferred(), + promise = deferred.promise(); + function resolveFunc( i ) { + return function( value ) { + args[ i ] = arguments.length > 1 ? sliceDeferred.call( arguments, 0 ) : value; + if ( !( --count ) ) { + deferred.resolveWith( deferred, args ); + } + }; + } + function progressFunc( i ) { + return function( value ) { + pValues[ i ] = arguments.length > 1 ? sliceDeferred.call( arguments, 0 ) : value; + deferred.notifyWith( promise, pValues ); + }; + } + if ( length > 1 ) { + for ( ; i < length; i++ ) { + if ( args[ i ] && args[ i ].promise && jQuery.isFunction( args[ i ].promise ) ) { + args[ i ].promise().then( resolveFunc(i), deferred.reject, progressFunc(i) ); + } else { + --count; + } + } + if ( !count ) { + deferred.resolveWith( deferred, args ); + } + } else if ( deferred !== firstParam ) { + deferred.resolveWith( deferred, length ? [ firstParam ] : [] ); + } + return promise; + } +}); + + + + +jQuery.support = (function() { + + var support, + all, + a, + select, + opt, + input, + marginDiv, + fragment, + tds, + events, + eventName, + i, + isSupported, + div = document.createElement( "div" ), + documentElement = document.documentElement; + + // Preliminary tests + div.setAttribute("className", "t"); + div.innerHTML = "
a"; + + all = div.getElementsByTagName( "*" ); + a = div.getElementsByTagName( "a" )[ 0 ]; + + // Can't get basic test support + if ( !all || !all.length || !a ) { + return {}; + } + + // First batch of supports tests + select = document.createElement( "select" ); + opt = select.appendChild( document.createElement("option") ); + input = div.getElementsByTagName( "input" )[ 0 ]; + + support = { + // IE strips leading whitespace when .innerHTML is used + leadingWhitespace: ( div.firstChild.nodeType === 3 ), + + // Make sure that tbody elements aren't automatically inserted + // IE will insert them into empty tables + tbody: !div.getElementsByTagName("tbody").length, + + // Make sure that link elements get serialized correctly by innerHTML + // This requires a wrapper element in IE + htmlSerialize: !!div.getElementsByTagName("link").length, + + // Get the style information from getAttribute + // (IE uses .cssText instead) + style: /top/.test( a.getAttribute("style") ), + + // Make sure that URLs aren't manipulated + // (IE normalizes it by default) + hrefNormalized: ( a.getAttribute("href") === "/a" ), + + // Make sure that element opacity exists + // (IE uses filter instead) + // Use a regex to work around a WebKit issue. See #5145 + opacity: /^0.55/.test( a.style.opacity ), + + // Verify style float existence + // (IE uses styleFloat instead of cssFloat) + cssFloat: !!a.style.cssFloat, + + // Make sure that if no value is specified for a checkbox + // that it defaults to "on". + // (WebKit defaults to "" instead) + checkOn: ( input.value === "on" ), + + // Make sure that a selected-by-default option has a working selected property. + // (WebKit defaults to false instead of true, IE too, if it's in an optgroup) + optSelected: opt.selected, + + // Test setAttribute on camelCase class. If it works, we need attrFixes when doing get/setAttribute (ie6/7) + getSetAttribute: div.className !== "t", + + // Tests for enctype support on a form(#6743) + enctype: !!document.createElement("form").enctype, + + // Makes sure cloning an html5 element does not cause problems + // Where outerHTML is undefined, this still works + html5Clone: document.createElement("nav").cloneNode( true ).outerHTML !== "<:nav>", + + // Will be defined later + submitBubbles: true, + changeBubbles: true, + focusinBubbles: false, + deleteExpando: true, + noCloneEvent: true, + inlineBlockNeedsLayout: false, + shrinkWrapBlocks: false, + reliableMarginRight: true + }; + + // Make sure checked status is properly cloned + input.checked = true; + support.noCloneChecked = input.cloneNode( true ).checked; + + // Make sure that the options inside disabled selects aren't marked as disabled + // (WebKit marks them as disabled) + select.disabled = true; + support.optDisabled = !opt.disabled; + + // Test to see if it's possible to delete an expando from an element + // Fails in Internet Explorer + try { + delete div.test; + } catch( e ) { + support.deleteExpando = false; + } + + if ( !div.addEventListener && div.attachEvent && div.fireEvent ) { + div.attachEvent( "onclick", function() { + // Cloning a node shouldn't copy over any + // bound event handlers (IE does this) + support.noCloneEvent = false; + }); + div.cloneNode( true ).fireEvent( "onclick" ); + } + + // Check if a radio maintains its value + // after being appended to the DOM + input = document.createElement("input"); + input.value = "t"; + input.setAttribute("type", "radio"); + support.radioValue = input.value === "t"; + + input.setAttribute("checked", "checked"); + div.appendChild( input ); + fragment = document.createDocumentFragment(); + fragment.appendChild( div.lastChild ); + + // WebKit doesn't clone checked state correctly in fragments + support.checkClone = fragment.cloneNode( true ).cloneNode( true ).lastChild.checked; + + // Check if a disconnected checkbox will retain its checked + // value of true after appended to the DOM (IE6/7) + support.appendChecked = input.checked; + + fragment.removeChild( input ); + fragment.appendChild( div ); + + div.innerHTML = ""; + + // Check if div with explicit width and no margin-right incorrectly + // gets computed margin-right based on width of container. For more + // info see bug #3333 + // Fails in WebKit before Feb 2011 nightlies + // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right + if ( window.getComputedStyle ) { + marginDiv = document.createElement( "div" ); + marginDiv.style.width = "0"; + marginDiv.style.marginRight = "0"; + div.style.width = "2px"; + div.appendChild( marginDiv ); + support.reliableMarginRight = + ( parseInt( ( window.getComputedStyle( marginDiv, null ) || { marginRight: 0 } ).marginRight, 10 ) || 0 ) === 0; + } + + // Technique from Juriy Zaytsev + // http://perfectionkills.com/detecting-event-support-without-browser-sniffing/ + // We only care about the case where non-standard event systems + // are used, namely in IE. Short-circuiting here helps us to + // avoid an eval call (in setAttribute) which can cause CSP + // to go haywire. See: https://developer.mozilla.org/en/Security/CSP + if ( div.attachEvent ) { + for( i in { + submit: 1, + change: 1, + focusin: 1 + }) { + eventName = "on" + i; + isSupported = ( eventName in div ); + if ( !isSupported ) { + div.setAttribute( eventName, "return;" ); + isSupported = ( typeof div[ eventName ] === "function" ); + } + support[ i + "Bubbles" ] = isSupported; + } + } + + fragment.removeChild( div ); + + // Null elements to avoid leaks in IE + fragment = select = opt = marginDiv = div = input = null; + + // Run tests that need a body at doc ready + jQuery(function() { + var container, outer, inner, table, td, offsetSupport, + conMarginTop, ptlm, vb, style, html, + body = document.getElementsByTagName("body")[0]; + + if ( !body ) { + // Return for frameset docs that don't have a body + return; + } + + conMarginTop = 1; + ptlm = "position:absolute;top:0;left:0;width:1px;height:1px;margin:0;"; + vb = "visibility:hidden;border:0;"; + style = "style='" + ptlm + "border:5px solid #000;padding:0;'"; + html = "
" + + "" + + "
"; + + container = document.createElement("div"); + container.style.cssText = vb + "width:0;height:0;position:static;top:0;margin-top:" + conMarginTop + "px"; + body.insertBefore( container, body.firstChild ); + + // Construct the test element + div = document.createElement("div"); + container.appendChild( div ); + + // Check if table cells still have offsetWidth/Height when they are set + // to display:none and there are still other visible table cells in a + // table row; if so, offsetWidth/Height are not reliable for use when + // determining if an element has been hidden directly using + // display:none (it is still safe to use offsets if a parent element is + // hidden; don safety goggles and see bug #4512 for more information). + // (only IE 8 fails this test) + div.innerHTML = "
t
"; + tds = div.getElementsByTagName( "td" ); + isSupported = ( tds[ 0 ].offsetHeight === 0 ); + + tds[ 0 ].style.display = ""; + tds[ 1 ].style.display = "none"; + + // Check if empty table cells still have offsetWidth/Height + // (IE <= 8 fail this test) + support.reliableHiddenOffsets = isSupported && ( tds[ 0 ].offsetHeight === 0 ); + + // Figure out if the W3C box model works as expected + div.innerHTML = ""; + div.style.width = div.style.paddingLeft = "1px"; + jQuery.boxModel = support.boxModel = div.offsetWidth === 2; + + if ( typeof div.style.zoom !== "undefined" ) { + // Check if natively block-level elements act like inline-block + // elements when setting their display to 'inline' and giving + // them layout + // (IE < 8 does this) + div.style.display = "inline"; + div.style.zoom = 1; + support.inlineBlockNeedsLayout = ( div.offsetWidth === 2 ); + + // Check if elements with layout shrink-wrap their children + // (IE 6 does this) + div.style.display = ""; + div.innerHTML = "
"; + support.shrinkWrapBlocks = ( div.offsetWidth !== 2 ); + } + + div.style.cssText = ptlm + vb; + div.innerHTML = html; + + outer = div.firstChild; + inner = outer.firstChild; + td = outer.nextSibling.firstChild.firstChild; + + offsetSupport = { + doesNotAddBorder: ( inner.offsetTop !== 5 ), + doesAddBorderForTableAndCells: ( td.offsetTop === 5 ) + }; + + inner.style.position = "fixed"; + inner.style.top = "20px"; + + // safari subtracts parent border width here which is 5px + offsetSupport.fixedPosition = ( inner.offsetTop === 20 || inner.offsetTop === 15 ); + inner.style.position = inner.style.top = ""; + + outer.style.overflow = "hidden"; + outer.style.position = "relative"; + + offsetSupport.subtractsBorderForOverflowNotVisible = ( inner.offsetTop === -5 ); + offsetSupport.doesNotIncludeMarginInBodyOffset = ( body.offsetTop !== conMarginTop ); + + body.removeChild( container ); + div = container = null; + + jQuery.extend( support, offsetSupport ); + }); + + return support; +})(); + + + + +var rbrace = /^(?:\{.*\}|\[.*\])$/, + rmultiDash = /([A-Z])/g; + +jQuery.extend({ + cache: {}, + + // Please use with caution + uuid: 0, + + // Unique for each copy of jQuery on the page + // Non-digits removed to match rinlinejQuery + expando: "jQuery" + ( jQuery.fn.jquery + Math.random() ).replace( /\D/g, "" ), + + // The following elements throw uncatchable exceptions if you + // attempt to add expando properties to them. + noData: { + "embed": true, + // Ban all objects except for Flash (which handle expandos) + "object": "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000", + "applet": true + }, + + hasData: function( elem ) { + elem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ]; + return !!elem && !isEmptyDataObject( elem ); + }, + + data: function( elem, name, data, pvt /* Internal Use Only */ ) { + if ( !jQuery.acceptData( elem ) ) { + return; + } + + var privateCache, thisCache, ret, + internalKey = jQuery.expando, + getByName = typeof name === "string", + + // We have to handle DOM nodes and JS objects differently because IE6-7 + // can't GC object references properly across the DOM-JS boundary + isNode = elem.nodeType, + + // Only DOM nodes need the global jQuery cache; JS object data is + // attached directly to the object so GC can occur automatically + cache = isNode ? jQuery.cache : elem, + + // Only defining an ID for JS objects if its cache already exists allows + // the code to shortcut on the same path as a DOM node with no cache + id = isNode ? elem[ internalKey ] : elem[ internalKey ] && internalKey, + isEvents = name === "events"; + + // Avoid doing any more work than we need to when trying to get data on an + // object that has no data at all + if ( (!id || !cache[id] || (!isEvents && !pvt && !cache[id].data)) && getByName && data === undefined ) { + return; + } + + if ( !id ) { + // Only DOM nodes need a new unique ID for each element since their data + // ends up in the global cache + if ( isNode ) { + elem[ internalKey ] = id = ++jQuery.uuid; + } else { + id = internalKey; + } + } + + if ( !cache[ id ] ) { + cache[ id ] = {}; + + // Avoids exposing jQuery metadata on plain JS objects when the object + // is serialized using JSON.stringify + if ( !isNode ) { + cache[ id ].toJSON = jQuery.noop; + } + } + + // An object can be passed to jQuery.data instead of a key/value pair; this gets + // shallow copied over onto the existing cache + if ( typeof name === "object" || typeof name === "function" ) { + if ( pvt ) { + cache[ id ] = jQuery.extend( cache[ id ], name ); + } else { + cache[ id ].data = jQuery.extend( cache[ id ].data, name ); + } + } + + privateCache = thisCache = cache[ id ]; + + // jQuery data() is stored in a separate object inside the object's internal data + // cache in order to avoid key collisions between internal data and user-defined + // data. + if ( !pvt ) { + if ( !thisCache.data ) { + thisCache.data = {}; + } + + thisCache = thisCache.data; + } + + if ( data !== undefined ) { + thisCache[ jQuery.camelCase( name ) ] = data; + } + + // Users should not attempt to inspect the internal events object using jQuery.data, + // it is undocumented and subject to change. But does anyone listen? No. + if ( isEvents && !thisCache[ name ] ) { + return privateCache.events; + } + + // Check for both converted-to-camel and non-converted data property names + // If a data property was specified + if ( getByName ) { + + // First Try to find as-is property data + ret = thisCache[ name ]; + + // Test for null|undefined property data + if ( ret == null ) { + + // Try to find the camelCased property + ret = thisCache[ jQuery.camelCase( name ) ]; + } + } else { + ret = thisCache; + } + + return ret; + }, + + removeData: function( elem, name, pvt /* Internal Use Only */ ) { + if ( !jQuery.acceptData( elem ) ) { + return; + } + + var thisCache, i, l, + + // Reference to internal data cache key + internalKey = jQuery.expando, + + isNode = elem.nodeType, + + // See jQuery.data for more information + cache = isNode ? jQuery.cache : elem, + + // See jQuery.data for more information + id = isNode ? elem[ internalKey ] : internalKey; + + // If there is already no cache entry for this object, there is no + // purpose in continuing + if ( !cache[ id ] ) { + return; + } + + if ( name ) { + + thisCache = pvt ? cache[ id ] : cache[ id ].data; + + if ( thisCache ) { + + // Support array or space separated string names for data keys + if ( !jQuery.isArray( name ) ) { + + // try the string as a key before any manipulation + if ( name in thisCache ) { + name = [ name ]; + } else { + + // split the camel cased version by spaces unless a key with the spaces exists + name = jQuery.camelCase( name ); + if ( name in thisCache ) { + name = [ name ]; + } else { + name = name.split( " " ); + } + } + } + + for ( i = 0, l = name.length; i < l; i++ ) { + delete thisCache[ name[i] ]; + } + + // If there is no data left in the cache, we want to continue + // and let the cache object itself get destroyed + if ( !( pvt ? isEmptyDataObject : jQuery.isEmptyObject )( thisCache ) ) { + return; + } + } + } + + // See jQuery.data for more information + if ( !pvt ) { + delete cache[ id ].data; + + // Don't destroy the parent cache unless the internal data object + // had been the only thing left in it + if ( !isEmptyDataObject(cache[ id ]) ) { + return; + } + } + + // Browsers that fail expando deletion also refuse to delete expandos on + // the window, but it will allow it on all other JS objects; other browsers + // don't care + // Ensure that `cache` is not a window object #10080 + if ( jQuery.support.deleteExpando || !cache.setInterval ) { + delete cache[ id ]; + } else { + cache[ id ] = null; + } + + // We destroyed the cache and need to eliminate the expando on the node to avoid + // false lookups in the cache for entries that no longer exist + if ( isNode ) { + // IE does not allow us to delete expando properties from nodes, + // nor does it have a removeAttribute function on Document nodes; + // we must handle all of these cases + if ( jQuery.support.deleteExpando ) { + delete elem[ internalKey ]; + } else if ( elem.removeAttribute ) { + elem.removeAttribute( internalKey ); + } else { + elem[ internalKey ] = null; + } + } + }, + + // For internal use only. + _data: function( elem, name, data ) { + return jQuery.data( elem, name, data, true ); + }, + + // A method for determining if a DOM node can handle the data expando + acceptData: function( elem ) { + if ( elem.nodeName ) { + var match = jQuery.noData[ elem.nodeName.toLowerCase() ]; + + if ( match ) { + return !(match === true || elem.getAttribute("classid") !== match); + } + } + + return true; + } +}); + +jQuery.fn.extend({ + data: function( key, value ) { + var parts, attr, name, + data = null; + + if ( typeof key === "undefined" ) { + if ( this.length ) { + data = jQuery.data( this[0] ); + + if ( this[0].nodeType === 1 && !jQuery._data( this[0], "parsedAttrs" ) ) { + attr = this[0].attributes; + for ( var i = 0, l = attr.length; i < l; i++ ) { + name = attr[i].name; + + if ( name.indexOf( "data-" ) === 0 ) { + name = jQuery.camelCase( name.substring(5) ); + + dataAttr( this[0], name, data[ name ] ); + } + } + jQuery._data( this[0], "parsedAttrs", true ); + } + } + + return data; + + } else if ( typeof key === "object" ) { + return this.each(function() { + jQuery.data( this, key ); + }); + } + + parts = key.split("."); + parts[1] = parts[1] ? "." + parts[1] : ""; + + if ( value === undefined ) { + data = this.triggerHandler("getData" + parts[1] + "!", [parts[0]]); + + // Try to fetch any internally stored data first + if ( data === undefined && this.length ) { + data = jQuery.data( this[0], key ); + data = dataAttr( this[0], key, data ); + } + + return data === undefined && parts[1] ? + this.data( parts[0] ) : + data; + + } else { + return this.each(function() { + var self = jQuery( this ), + args = [ parts[0], value ]; + + self.triggerHandler( "setData" + parts[1] + "!", args ); + jQuery.data( this, key, value ); + self.triggerHandler( "changeData" + parts[1] + "!", args ); + }); + } + }, + + removeData: function( key ) { + return this.each(function() { + jQuery.removeData( this, key ); + }); + } +}); + +function dataAttr( elem, key, data ) { + // If nothing was found internally, try to fetch any + // data from the HTML5 data-* attribute + if ( data === undefined && elem.nodeType === 1 ) { + + var name = "data-" + key.replace( rmultiDash, "-$1" ).toLowerCase(); + + data = elem.getAttribute( name ); + + if ( typeof data === "string" ) { + try { + data = data === "true" ? true : + data === "false" ? false : + data === "null" ? null : + jQuery.isNumeric( data ) ? parseFloat( data ) : + rbrace.test( data ) ? jQuery.parseJSON( data ) : + data; + } catch( e ) {} + + // Make sure we set the data so it isn't changed later + jQuery.data( elem, key, data ); + + } else { + data = undefined; + } + } + + return data; +} + +// checks a cache object for emptiness +function isEmptyDataObject( obj ) { + for ( var name in obj ) { + + // if the public data object is empty, the private is still empty + if ( name === "data" && jQuery.isEmptyObject( obj[name] ) ) { + continue; + } + if ( name !== "toJSON" ) { + return false; + } + } + + return true; +} + + + + +function handleQueueMarkDefer( elem, type, src ) { + var deferDataKey = type + "defer", + queueDataKey = type + "queue", + markDataKey = type + "mark", + defer = jQuery._data( elem, deferDataKey ); + if ( defer && + ( src === "queue" || !jQuery._data(elem, queueDataKey) ) && + ( src === "mark" || !jQuery._data(elem, markDataKey) ) ) { + // Give room for hard-coded callbacks to fire first + // and eventually mark/queue something else on the element + setTimeout( function() { + if ( !jQuery._data( elem, queueDataKey ) && + !jQuery._data( elem, markDataKey ) ) { + jQuery.removeData( elem, deferDataKey, true ); + defer.fire(); + } + }, 0 ); + } +} + +jQuery.extend({ + + _mark: function( elem, type ) { + if ( elem ) { + type = ( type || "fx" ) + "mark"; + jQuery._data( elem, type, (jQuery._data( elem, type ) || 0) + 1 ); + } + }, + + _unmark: function( force, elem, type ) { + if ( force !== true ) { + type = elem; + elem = force; + force = false; + } + if ( elem ) { + type = type || "fx"; + var key = type + "mark", + count = force ? 0 : ( (jQuery._data( elem, key ) || 1) - 1 ); + if ( count ) { + jQuery._data( elem, key, count ); + } else { + jQuery.removeData( elem, key, true ); + handleQueueMarkDefer( elem, type, "mark" ); + } + } + }, + + queue: function( elem, type, data ) { + var q; + if ( elem ) { + type = ( type || "fx" ) + "queue"; + q = jQuery._data( elem, type ); + + // Speed up dequeue by getting out quickly if this is just a lookup + if ( data ) { + if ( !q || jQuery.isArray(data) ) { + q = jQuery._data( elem, type, jQuery.makeArray(data) ); + } else { + q.push( data ); + } + } + return q || []; + } + }, + + dequeue: function( elem, type ) { + type = type || "fx"; + + var queue = jQuery.queue( elem, type ), + fn = queue.shift(), + hooks = {}; + + // If the fx queue is dequeued, always remove the progress sentinel + if ( fn === "inprogress" ) { + fn = queue.shift(); + } + + if ( fn ) { + // Add a progress sentinel to prevent the fx queue from being + // automatically dequeued + if ( type === "fx" ) { + queue.unshift( "inprogress" ); + } + + jQuery._data( elem, type + ".run", hooks ); + fn.call( elem, function() { + jQuery.dequeue( elem, type ); + }, hooks ); + } + + if ( !queue.length ) { + jQuery.removeData( elem, type + "queue " + type + ".run", true ); + handleQueueMarkDefer( elem, type, "queue" ); + } + } +}); + +jQuery.fn.extend({ + queue: function( type, data ) { + if ( typeof type !== "string" ) { + data = type; + type = "fx"; + } + + if ( data === undefined ) { + return jQuery.queue( this[0], type ); + } + return this.each(function() { + var queue = jQuery.queue( this, type, data ); + + if ( type === "fx" && queue[0] !== "inprogress" ) { + jQuery.dequeue( this, type ); + } + }); + }, + dequeue: function( type ) { + return this.each(function() { + jQuery.dequeue( this, type ); + }); + }, + // Based off of the plugin by Clint Helfers, with permission. + // http://blindsignals.com/index.php/2009/07/jquery-delay/ + delay: function( time, type ) { + time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time; + type = type || "fx"; + + return this.queue( type, function( next, hooks ) { + var timeout = setTimeout( next, time ); + hooks.stop = function() { + clearTimeout( timeout ); + }; + }); + }, + clearQueue: function( type ) { + return this.queue( type || "fx", [] ); + }, + // Get a promise resolved when queues of a certain type + // are emptied (fx is the type by default) + promise: function( type, object ) { + if ( typeof type !== "string" ) { + object = type; + type = undefined; + } + type = type || "fx"; + var defer = jQuery.Deferred(), + elements = this, + i = elements.length, + count = 1, + deferDataKey = type + "defer", + queueDataKey = type + "queue", + markDataKey = type + "mark", + tmp; + function resolve() { + if ( !( --count ) ) { + defer.resolveWith( elements, [ elements ] ); + } + } + while( i-- ) { + if (( tmp = jQuery.data( elements[ i ], deferDataKey, undefined, true ) || + ( jQuery.data( elements[ i ], queueDataKey, undefined, true ) || + jQuery.data( elements[ i ], markDataKey, undefined, true ) ) && + jQuery.data( elements[ i ], deferDataKey, jQuery.Callbacks( "once memory" ), true ) )) { + count++; + tmp.add( resolve ); + } + } + resolve(); + return defer.promise(); + } +}); + + + + +var rclass = /[\n\t\r]/g, + rspace = /\s+/, + rreturn = /\r/g, + rtype = /^(?:button|input)$/i, + rfocusable = /^(?:button|input|object|select|textarea)$/i, + rclickable = /^a(?:rea)?$/i, + rboolean = /^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i, + getSetAttribute = jQuery.support.getSetAttribute, + nodeHook, boolHook, fixSpecified; + +jQuery.fn.extend({ + attr: function( name, value ) { + return jQuery.access( this, name, value, true, jQuery.attr ); + }, + + removeAttr: function( name ) { + return this.each(function() { + jQuery.removeAttr( this, name ); + }); + }, + + prop: function( name, value ) { + return jQuery.access( this, name, value, true, jQuery.prop ); + }, + + removeProp: function( name ) { + name = jQuery.propFix[ name ] || name; + return this.each(function() { + // try/catch handles cases where IE balks (such as removing a property on window) + try { + this[ name ] = undefined; + delete this[ name ]; + } catch( e ) {} + }); + }, + + addClass: function( value ) { + var classNames, i, l, elem, + setClass, c, cl; + + if ( jQuery.isFunction( value ) ) { + return this.each(function( j ) { + jQuery( this ).addClass( value.call(this, j, this.className) ); + }); + } + + if ( value && typeof value === "string" ) { + classNames = value.split( rspace ); + + for ( i = 0, l = this.length; i < l; i++ ) { + elem = this[ i ]; + + if ( elem.nodeType === 1 ) { + if ( !elem.className && classNames.length === 1 ) { + elem.className = value; + + } else { + setClass = " " + elem.className + " "; + + for ( c = 0, cl = classNames.length; c < cl; c++ ) { + if ( !~setClass.indexOf( " " + classNames[ c ] + " " ) ) { + setClass += classNames[ c ] + " "; + } + } + elem.className = jQuery.trim( setClass ); + } + } + } + } + + return this; + }, + + removeClass: function( value ) { + var classNames, i, l, elem, className, c, cl; + + if ( jQuery.isFunction( value ) ) { + return this.each(function( j ) { + jQuery( this ).removeClass( value.call(this, j, this.className) ); + }); + } + + if ( (value && typeof value === "string") || value === undefined ) { + classNames = ( value || "" ).split( rspace ); + + for ( i = 0, l = this.length; i < l; i++ ) { + elem = this[ i ]; + + if ( elem.nodeType === 1 && elem.className ) { + if ( value ) { + className = (" " + elem.className + " ").replace( rclass, " " ); + for ( c = 0, cl = classNames.length; c < cl; c++ ) { + className = className.replace(" " + classNames[ c ] + " ", " "); + } + elem.className = jQuery.trim( className ); + + } else { + elem.className = ""; + } + } + } + } + + return this; + }, + + toggleClass: function( value, stateVal ) { + var type = typeof value, + isBool = typeof stateVal === "boolean"; + + if ( jQuery.isFunction( value ) ) { + return this.each(function( i ) { + jQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal ); + }); + } + + return this.each(function() { + if ( type === "string" ) { + // toggle individual class names + var className, + i = 0, + self = jQuery( this ), + state = stateVal, + classNames = value.split( rspace ); + + while ( (className = classNames[ i++ ]) ) { + // check each className given, space seperated list + state = isBool ? state : !self.hasClass( className ); + self[ state ? "addClass" : "removeClass" ]( className ); + } + + } else if ( type === "undefined" || type === "boolean" ) { + if ( this.className ) { + // store className if set + jQuery._data( this, "__className__", this.className ); + } + + // toggle whole className + this.className = this.className || value === false ? "" : jQuery._data( this, "__className__" ) || ""; + } + }); + }, + + hasClass: function( selector ) { + var className = " " + selector + " ", + i = 0, + l = this.length; + for ( ; i < l; i++ ) { + if ( this[i].nodeType === 1 && (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) > -1 ) { + return true; + } + } + + return false; + }, + + val: function( value ) { + var hooks, ret, isFunction, + elem = this[0]; + + if ( !arguments.length ) { + if ( elem ) { + hooks = jQuery.valHooks[ elem.nodeName.toLowerCase() ] || jQuery.valHooks[ elem.type ]; + + if ( hooks && "get" in hooks && (ret = hooks.get( elem, "value" )) !== undefined ) { + return ret; + } + + ret = elem.value; + + return typeof ret === "string" ? + // handle most common string cases + ret.replace(rreturn, "") : + // handle cases where value is null/undef or number + ret == null ? "" : ret; + } + + return; + } + + isFunction = jQuery.isFunction( value ); + + return this.each(function( i ) { + var self = jQuery(this), val; + + if ( this.nodeType !== 1 ) { + return; + } + + if ( isFunction ) { + val = value.call( this, i, self.val() ); + } else { + val = value; + } + + // Treat null/undefined as ""; convert numbers to string + if ( val == null ) { + val = ""; + } else if ( typeof val === "number" ) { + val += ""; + } else if ( jQuery.isArray( val ) ) { + val = jQuery.map(val, function ( value ) { + return value == null ? "" : value + ""; + }); + } + + hooks = jQuery.valHooks[ this.nodeName.toLowerCase() ] || jQuery.valHooks[ this.type ]; + + // If set returns undefined, fall back to normal setting + if ( !hooks || !("set" in hooks) || hooks.set( this, val, "value" ) === undefined ) { + this.value = val; + } + }); + } +}); + +jQuery.extend({ + valHooks: { + option: { + get: function( elem ) { + // attributes.value is undefined in Blackberry 4.7 but + // uses .value. See #6932 + var val = elem.attributes.value; + return !val || val.specified ? elem.value : elem.text; + } + }, + select: { + get: function( elem ) { + var value, i, max, option, + index = elem.selectedIndex, + values = [], + options = elem.options, + one = elem.type === "select-one"; + + // Nothing was selected + if ( index < 0 ) { + return null; + } + + // Loop through all the selected options + i = one ? index : 0; + max = one ? index + 1 : options.length; + for ( ; i < max; i++ ) { + option = options[ i ]; + + // Don't return options that are disabled or in a disabled optgroup + if ( option.selected && (jQuery.support.optDisabled ? !option.disabled : option.getAttribute("disabled") === null) && + (!option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" )) ) { + + // Get the specific value for the option + value = jQuery( option ).val(); + + // We don't need an array for one selects + if ( one ) { + return value; + } + + // Multi-Selects return an array + values.push( value ); + } + } + + // Fixes Bug #2551 -- select.val() broken in IE after form.reset() + if ( one && !values.length && options.length ) { + return jQuery( options[ index ] ).val(); + } + + return values; + }, + + set: function( elem, value ) { + var values = jQuery.makeArray( value ); + + jQuery(elem).find("option").each(function() { + this.selected = jQuery.inArray( jQuery(this).val(), values ) >= 0; + }); + + if ( !values.length ) { + elem.selectedIndex = -1; + } + return values; + } + } + }, + + attrFn: { + val: true, + css: true, + html: true, + text: true, + data: true, + width: true, + height: true, + offset: true + }, + + attr: function( elem, name, value, pass ) { + var ret, hooks, notxml, + nType = elem.nodeType; + + // don't get/set attributes on text, comment and attribute nodes + if ( !elem || nType === 3 || nType === 8 || nType === 2 ) { + return; + } + + if ( pass && name in jQuery.attrFn ) { + return jQuery( elem )[ name ]( value ); + } + + // Fallback to prop when attributes are not supported + if ( typeof elem.getAttribute === "undefined" ) { + return jQuery.prop( elem, name, value ); + } + + notxml = nType !== 1 || !jQuery.isXMLDoc( elem ); + + // All attributes are lowercase + // Grab necessary hook if one is defined + if ( notxml ) { + name = name.toLowerCase(); + hooks = jQuery.attrHooks[ name ] || ( rboolean.test( name ) ? boolHook : nodeHook ); + } + + if ( value !== undefined ) { + + if ( value === null ) { + jQuery.removeAttr( elem, name ); + return; + + } else if ( hooks && "set" in hooks && notxml && (ret = hooks.set( elem, value, name )) !== undefined ) { + return ret; + + } else { + elem.setAttribute( name, "" + value ); + return value; + } + + } else if ( hooks && "get" in hooks && notxml && (ret = hooks.get( elem, name )) !== null ) { + return ret; + + } else { + + ret = elem.getAttribute( name ); + + // Non-existent attributes return null, we normalize to undefined + return ret === null ? + undefined : + ret; + } + }, + + removeAttr: function( elem, value ) { + var propName, attrNames, name, l, + i = 0; + + if ( value && elem.nodeType === 1 ) { + attrNames = value.toLowerCase().split( rspace ); + l = attrNames.length; + + for ( ; i < l; i++ ) { + name = attrNames[ i ]; + + if ( name ) { + propName = jQuery.propFix[ name ] || name; + + // See #9699 for explanation of this approach (setting first, then removal) + jQuery.attr( elem, name, "" ); + elem.removeAttribute( getSetAttribute ? name : propName ); + + // Set corresponding property to false for boolean attributes + if ( rboolean.test( name ) && propName in elem ) { + elem[ propName ] = false; + } + } + } + } + }, + + attrHooks: { + type: { + set: function( elem, value ) { + // We can't allow the type property to be changed (since it causes problems in IE) + if ( rtype.test( elem.nodeName ) && elem.parentNode ) { + jQuery.error( "type property can't be changed" ); + } else if ( !jQuery.support.radioValue && value === "radio" && jQuery.nodeName(elem, "input") ) { + // Setting the type on a radio button after the value resets the value in IE6-9 + // Reset value to it's default in case type is set after value + // This is for element creation + var val = elem.value; + elem.setAttribute( "type", value ); + if ( val ) { + elem.value = val; + } + return value; + } + } + }, + // Use the value property for back compat + // Use the nodeHook for button elements in IE6/7 (#1954) + value: { + get: function( elem, name ) { + if ( nodeHook && jQuery.nodeName( elem, "button" ) ) { + return nodeHook.get( elem, name ); + } + return name in elem ? + elem.value : + null; + }, + set: function( elem, value, name ) { + if ( nodeHook && jQuery.nodeName( elem, "button" ) ) { + return nodeHook.set( elem, value, name ); + } + // Does not return so that setAttribute is also used + elem.value = value; + } + } + }, + + propFix: { + tabindex: "tabIndex", + readonly: "readOnly", + "for": "htmlFor", + "class": "className", + maxlength: "maxLength", + cellspacing: "cellSpacing", + cellpadding: "cellPadding", + rowspan: "rowSpan", + colspan: "colSpan", + usemap: "useMap", + frameborder: "frameBorder", + contenteditable: "contentEditable" + }, + + prop: function( elem, name, value ) { + var ret, hooks, notxml, + nType = elem.nodeType; + + // don't get/set properties on text, comment and attribute nodes + if ( !elem || nType === 3 || nType === 8 || nType === 2 ) { + return; + } + + notxml = nType !== 1 || !jQuery.isXMLDoc( elem ); + + if ( notxml ) { + // Fix name and attach hooks + name = jQuery.propFix[ name ] || name; + hooks = jQuery.propHooks[ name ]; + } + + if ( value !== undefined ) { + if ( hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) { + return ret; + + } else { + return ( elem[ name ] = value ); + } + + } else { + if ( hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ) { + return ret; + + } else { + return elem[ name ]; + } + } + }, + + propHooks: { + tabIndex: { + get: function( elem ) { + // elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set + // http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/ + var attributeNode = elem.getAttributeNode("tabindex"); + + return attributeNode && attributeNode.specified ? + parseInt( attributeNode.value, 10 ) : + rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ? + 0 : + undefined; + } + } + } +}); + +// Add the tabIndex propHook to attrHooks for back-compat (different case is intentional) +jQuery.attrHooks.tabindex = jQuery.propHooks.tabIndex; + +// Hook for boolean attributes +boolHook = { + get: function( elem, name ) { + // Align boolean attributes with corresponding properties + // Fall back to attribute presence where some booleans are not supported + var attrNode, + property = jQuery.prop( elem, name ); + return property === true || typeof property !== "boolean" && ( attrNode = elem.getAttributeNode(name) ) && attrNode.nodeValue !== false ? + name.toLowerCase() : + undefined; + }, + set: function( elem, value, name ) { + var propName; + if ( value === false ) { + // Remove boolean attributes when set to false + jQuery.removeAttr( elem, name ); + } else { + // value is true since we know at this point it's type boolean and not false + // Set boolean attributes to the same name and set the DOM property + propName = jQuery.propFix[ name ] || name; + if ( propName in elem ) { + // Only set the IDL specifically if it already exists on the element + elem[ propName ] = true; + } + + elem.setAttribute( name, name.toLowerCase() ); + } + return name; + } +}; + +// IE6/7 do not support getting/setting some attributes with get/setAttribute +if ( !getSetAttribute ) { + + fixSpecified = { + name: true, + id: true + }; + + // Use this for any attribute in IE6/7 + // This fixes almost every IE6/7 issue + nodeHook = jQuery.valHooks.button = { + get: function( elem, name ) { + var ret; + ret = elem.getAttributeNode( name ); + return ret && ( fixSpecified[ name ] ? ret.nodeValue !== "" : ret.specified ) ? + ret.nodeValue : + undefined; + }, + set: function( elem, value, name ) { + // Set the existing or create a new attribute node + var ret = elem.getAttributeNode( name ); + if ( !ret ) { + ret = document.createAttribute( name ); + elem.setAttributeNode( ret ); + } + return ( ret.nodeValue = value + "" ); + } + }; + + // Apply the nodeHook to tabindex + jQuery.attrHooks.tabindex.set = nodeHook.set; + + // Set width and height to auto instead of 0 on empty string( Bug #8150 ) + // This is for removals + jQuery.each([ "width", "height" ], function( i, name ) { + jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], { + set: function( elem, value ) { + if ( value === "" ) { + elem.setAttribute( name, "auto" ); + return value; + } + } + }); + }); + + // Set contenteditable to false on removals(#10429) + // Setting to empty string throws an error as an invalid value + jQuery.attrHooks.contenteditable = { + get: nodeHook.get, + set: function( elem, value, name ) { + if ( value === "" ) { + value = "false"; + } + nodeHook.set( elem, value, name ); + } + }; +} + + +// Some attributes require a special call on IE +if ( !jQuery.support.hrefNormalized ) { + jQuery.each([ "href", "src", "width", "height" ], function( i, name ) { + jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], { + get: function( elem ) { + var ret = elem.getAttribute( name, 2 ); + return ret === null ? undefined : ret; + } + }); + }); +} + +if ( !jQuery.support.style ) { + jQuery.attrHooks.style = { + get: function( elem ) { + // Return undefined in the case of empty string + // Normalize to lowercase since IE uppercases css property names + return elem.style.cssText.toLowerCase() || undefined; + }, + set: function( elem, value ) { + return ( elem.style.cssText = "" + value ); + } + }; +} + +// Safari mis-reports the default selected property of an option +// Accessing the parent's selectedIndex property fixes it +if ( !jQuery.support.optSelected ) { + jQuery.propHooks.selected = jQuery.extend( jQuery.propHooks.selected, { + get: function( elem ) { + var parent = elem.parentNode; + + if ( parent ) { + parent.selectedIndex; + + // Make sure that it also works with optgroups, see #5701 + if ( parent.parentNode ) { + parent.parentNode.selectedIndex; + } + } + return null; + } + }); +} + +// IE6/7 call enctype encoding +if ( !jQuery.support.enctype ) { + jQuery.propFix.enctype = "encoding"; +} + +// Radios and checkboxes getter/setter +if ( !jQuery.support.checkOn ) { + jQuery.each([ "radio", "checkbox" ], function() { + jQuery.valHooks[ this ] = { + get: function( elem ) { + // Handle the case where in Webkit "" is returned instead of "on" if a value isn't specified + return elem.getAttribute("value") === null ? "on" : elem.value; + } + }; + }); +} +jQuery.each([ "radio", "checkbox" ], function() { + jQuery.valHooks[ this ] = jQuery.extend( jQuery.valHooks[ this ], { + set: function( elem, value ) { + if ( jQuery.isArray( value ) ) { + return ( elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0 ); + } + } + }); +}); + + + + +var rformElems = /^(?:textarea|input|select)$/i, + rtypenamespace = /^([^\.]*)?(?:\.(.+))?$/, + rhoverHack = /\bhover(\.\S+)?\b/, + rkeyEvent = /^key/, + rmouseEvent = /^(?:mouse|contextmenu)|click/, + rfocusMorph = /^(?:focusinfocus|focusoutblur)$/, + rquickIs = /^(\w*)(?:#([\w\-]+))?(?:\.([\w\-]+))?$/, + quickParse = function( selector ) { + var quick = rquickIs.exec( selector ); + if ( quick ) { + // 0 1 2 3 + // [ _, tag, id, class ] + quick[1] = ( quick[1] || "" ).toLowerCase(); + quick[3] = quick[3] && new RegExp( "(?:^|\\s)" + quick[3] + "(?:\\s|$)" ); + } + return quick; + }, + quickIs = function( elem, m ) { + var attrs = elem.attributes || {}; + return ( + (!m[1] || elem.nodeName.toLowerCase() === m[1]) && + (!m[2] || (attrs.id || {}).value === m[2]) && + (!m[3] || m[3].test( (attrs[ "class" ] || {}).value )) + ); + }, + hoverHack = function( events ) { + return jQuery.event.special.hover ? events : events.replace( rhoverHack, "mouseenter$1 mouseleave$1" ); + }; + +/* + * Helper functions for managing events -- not part of the public interface. + * Props to Dean Edwards' addEvent library for many of the ideas. + */ +jQuery.event = { + + add: function( elem, types, handler, data, selector ) { + + var elemData, eventHandle, events, + t, tns, type, namespaces, handleObj, + handleObjIn, quick, handlers, special; + + // Don't attach events to noData or text/comment nodes (allow plain objects tho) + if ( elem.nodeType === 3 || elem.nodeType === 8 || !types || !handler || !(elemData = jQuery._data( elem )) ) { + return; + } + + // Caller can pass in an object of custom data in lieu of the handler + if ( handler.handler ) { + handleObjIn = handler; + handler = handleObjIn.handler; + } + + // Make sure that the handler has a unique ID, used to find/remove it later + if ( !handler.guid ) { + handler.guid = jQuery.guid++; + } + + // Init the element's event structure and main handler, if this is the first + events = elemData.events; + if ( !events ) { + elemData.events = events = {}; + } + eventHandle = elemData.handle; + if ( !eventHandle ) { + elemData.handle = eventHandle = function( e ) { + // Discard the second event of a jQuery.event.trigger() and + // when an event is called after a page has unloaded + return typeof jQuery !== "undefined" && (!e || jQuery.event.triggered !== e.type) ? + jQuery.event.dispatch.apply( eventHandle.elem, arguments ) : + undefined; + }; + // Add elem as a property of the handle fn to prevent a memory leak with IE non-native events + eventHandle.elem = elem; + } + + // Handle multiple events separated by a space + // jQuery(...).bind("mouseover mouseout", fn); + types = jQuery.trim( hoverHack(types) ).split( " " ); + for ( t = 0; t < types.length; t++ ) { + + tns = rtypenamespace.exec( types[t] ) || []; + type = tns[1]; + namespaces = ( tns[2] || "" ).split( "." ).sort(); + + // If event changes its type, use the special event handlers for the changed type + special = jQuery.event.special[ type ] || {}; + + // If selector defined, determine special event api type, otherwise given type + type = ( selector ? special.delegateType : special.bindType ) || type; + + // Update special based on newly reset type + special = jQuery.event.special[ type ] || {}; + + // handleObj is passed to all event handlers + handleObj = jQuery.extend({ + type: type, + origType: tns[1], + data: data, + handler: handler, + guid: handler.guid, + selector: selector, + quick: quickParse( selector ), + namespace: namespaces.join(".") + }, handleObjIn ); + + // Init the event handler queue if we're the first + handlers = events[ type ]; + if ( !handlers ) { + handlers = events[ type ] = []; + handlers.delegateCount = 0; + + // Only use addEventListener/attachEvent if the special events handler returns false + if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) { + // Bind the global event handler to the element + if ( elem.addEventListener ) { + elem.addEventListener( type, eventHandle, false ); + + } else if ( elem.attachEvent ) { + elem.attachEvent( "on" + type, eventHandle ); + } + } + } + + if ( special.add ) { + special.add.call( elem, handleObj ); + + if ( !handleObj.handler.guid ) { + handleObj.handler.guid = handler.guid; + } + } + + // Add to the element's handler list, delegates in front + if ( selector ) { + handlers.splice( handlers.delegateCount++, 0, handleObj ); + } else { + handlers.push( handleObj ); + } + + // Keep track of which events have ever been used, for event optimization + jQuery.event.global[ type ] = true; + } + + // Nullify elem to prevent memory leaks in IE + elem = null; + }, + + global: {}, + + // Detach an event or set of events from an element + remove: function( elem, types, handler, selector, mappedTypes ) { + + var elemData = jQuery.hasData( elem ) && jQuery._data( elem ), + t, tns, type, origType, namespaces, origCount, + j, events, special, handle, eventType, handleObj; + + if ( !elemData || !(events = elemData.events) ) { + return; + } + + // Once for each type.namespace in types; type may be omitted + types = jQuery.trim( hoverHack( types || "" ) ).split(" "); + for ( t = 0; t < types.length; t++ ) { + tns = rtypenamespace.exec( types[t] ) || []; + type = origType = tns[1]; + namespaces = tns[2]; + + // Unbind all events (on this namespace, if provided) for the element + if ( !type ) { + for ( type in events ) { + jQuery.event.remove( elem, type + types[ t ], handler, selector, true ); + } + continue; + } + + special = jQuery.event.special[ type ] || {}; + type = ( selector? special.delegateType : special.bindType ) || type; + eventType = events[ type ] || []; + origCount = eventType.length; + namespaces = namespaces ? new RegExp("(^|\\.)" + namespaces.split(".").sort().join("\\.(?:.*\\.)?") + "(\\.|$)") : null; + + // Remove matching events + for ( j = 0; j < eventType.length; j++ ) { + handleObj = eventType[ j ]; + + if ( ( mappedTypes || origType === handleObj.origType ) && + ( !handler || handler.guid === handleObj.guid ) && + ( !namespaces || namespaces.test( handleObj.namespace ) ) && + ( !selector || selector === handleObj.selector || selector === "**" && handleObj.selector ) ) { + eventType.splice( j--, 1 ); + + if ( handleObj.selector ) { + eventType.delegateCount--; + } + if ( special.remove ) { + special.remove.call( elem, handleObj ); + } + } + } + + // Remove generic event handler if we removed something and no more handlers exist + // (avoids potential for endless recursion during removal of special event handlers) + if ( eventType.length === 0 && origCount !== eventType.length ) { + if ( !special.teardown || special.teardown.call( elem, namespaces ) === false ) { + jQuery.removeEvent( elem, type, elemData.handle ); + } + + delete events[ type ]; + } + } + + // Remove the expando if it's no longer used + if ( jQuery.isEmptyObject( events ) ) { + handle = elemData.handle; + if ( handle ) { + handle.elem = null; + } + + // removeData also checks for emptiness and clears the expando if empty + // so use it instead of delete + jQuery.removeData( elem, [ "events", "handle" ], true ); + } + }, + + // Events that are safe to short-circuit if no handlers are attached. + // Native DOM events should not be added, they may have inline handlers. + customEvent: { + "getData": true, + "setData": true, + "changeData": true + }, + + trigger: function( event, data, elem, onlyHandlers ) { + // Don't do events on text and comment nodes + if ( elem && (elem.nodeType === 3 || elem.nodeType === 8) ) { + return; + } + + // Event object or event type + var type = event.type || event, + namespaces = [], + cache, exclusive, i, cur, old, ontype, special, handle, eventPath, bubbleType; + + // focus/blur morphs to focusin/out; ensure we're not firing them right now + if ( rfocusMorph.test( type + jQuery.event.triggered ) ) { + return; + } + + if ( type.indexOf( "!" ) >= 0 ) { + // Exclusive events trigger only for the exact event (no namespaces) + type = type.slice(0, -1); + exclusive = true; + } + + if ( type.indexOf( "." ) >= 0 ) { + // Namespaced trigger; create a regexp to match event type in handle() + namespaces = type.split("."); + type = namespaces.shift(); + namespaces.sort(); + } + + if ( (!elem || jQuery.event.customEvent[ type ]) && !jQuery.event.global[ type ] ) { + // No jQuery handlers for this event type, and it can't have inline handlers + return; + } + + // Caller can pass in an Event, Object, or just an event type string + event = typeof event === "object" ? + // jQuery.Event object + event[ jQuery.expando ] ? event : + // Object literal + new jQuery.Event( type, event ) : + // Just the event type (string) + new jQuery.Event( type ); + + event.type = type; + event.isTrigger = true; + event.exclusive = exclusive; + event.namespace = namespaces.join( "." ); + event.namespace_re = event.namespace? new RegExp("(^|\\.)" + namespaces.join("\\.(?:.*\\.)?") + "(\\.|$)") : null; + ontype = type.indexOf( ":" ) < 0 ? "on" + type : ""; + + // Handle a global trigger + if ( !elem ) { + + // TODO: Stop taunting the data cache; remove global events and always attach to document + cache = jQuery.cache; + for ( i in cache ) { + if ( cache[ i ].events && cache[ i ].events[ type ] ) { + jQuery.event.trigger( event, data, cache[ i ].handle.elem, true ); + } + } + return; + } + + // Clean up the event in case it is being reused + event.result = undefined; + if ( !event.target ) { + event.target = elem; + } + + // Clone any incoming data and prepend the event, creating the handler arg list + data = data != null ? jQuery.makeArray( data ) : []; + data.unshift( event ); + + // Allow special events to draw outside the lines + special = jQuery.event.special[ type ] || {}; + if ( special.trigger && special.trigger.apply( elem, data ) === false ) { + return; + } + + // Determine event propagation path in advance, per W3C events spec (#9951) + // Bubble up to document, then to window; watch for a global ownerDocument var (#9724) + eventPath = [[ elem, special.bindType || type ]]; + if ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) { + + bubbleType = special.delegateType || type; + cur = rfocusMorph.test( bubbleType + type ) ? elem : elem.parentNode; + old = null; + for ( ; cur; cur = cur.parentNode ) { + eventPath.push([ cur, bubbleType ]); + old = cur; + } + + // Only add window if we got to document (e.g., not plain obj or detached DOM) + if ( old && old === elem.ownerDocument ) { + eventPath.push([ old.defaultView || old.parentWindow || window, bubbleType ]); + } + } + + // Fire handlers on the event path + for ( i = 0; i < eventPath.length && !event.isPropagationStopped(); i++ ) { + + cur = eventPath[i][0]; + event.type = eventPath[i][1]; + + handle = ( jQuery._data( cur, "events" ) || {} )[ event.type ] && jQuery._data( cur, "handle" ); + if ( handle ) { + handle.apply( cur, data ); + } + // Note that this is a bare JS function and not a jQuery handler + handle = ontype && cur[ ontype ]; + if ( handle && jQuery.acceptData( cur ) && handle.apply( cur, data ) === false ) { + event.preventDefault(); + } + } + event.type = type; + + // If nobody prevented the default action, do it now + if ( !onlyHandlers && !event.isDefaultPrevented() ) { + + if ( (!special._default || special._default.apply( elem.ownerDocument, data ) === false) && + !(type === "click" && jQuery.nodeName( elem, "a" )) && jQuery.acceptData( elem ) ) { + + // Call a native DOM method on the target with the same name name as the event. + // Can't use an .isFunction() check here because IE6/7 fails that test. + // Don't do default actions on window, that's where global variables be (#6170) + // IE<9 dies on focus/blur to hidden element (#1486) + if ( ontype && elem[ type ] && ((type !== "focus" && type !== "blur") || event.target.offsetWidth !== 0) && !jQuery.isWindow( elem ) ) { + + // Don't re-trigger an onFOO event when we call its FOO() method + old = elem[ ontype ]; + + if ( old ) { + elem[ ontype ] = null; + } + + // Prevent re-triggering of the same event, since we already bubbled it above + jQuery.event.triggered = type; + elem[ type ](); + jQuery.event.triggered = undefined; + + if ( old ) { + elem[ ontype ] = old; + } + } + } + } + + return event.result; + }, + + dispatch: function( event ) { + + // Make a writable jQuery.Event from the native event object + event = jQuery.event.fix( event || window.event ); + + var handlers = ( (jQuery._data( this, "events" ) || {} )[ event.type ] || []), + delegateCount = handlers.delegateCount, + args = [].slice.call( arguments, 0 ), + run_all = !event.exclusive && !event.namespace, + handlerQueue = [], + i, j, cur, jqcur, ret, selMatch, matched, matches, handleObj, sel, related; + + // Use the fix-ed jQuery.Event rather than the (read-only) native event + args[0] = event; + event.delegateTarget = this; + + // Determine handlers that should run if there are delegated events + // Avoid disabled elements in IE (#6911) and non-left-click bubbling in Firefox (#3861) + if ( delegateCount && !event.target.disabled && !(event.button && event.type === "click") ) { + + // Pregenerate a single jQuery object for reuse with .is() + jqcur = jQuery(this); + jqcur.context = this.ownerDocument || this; + + for ( cur = event.target; cur != this; cur = cur.parentNode || this ) { + selMatch = {}; + matches = []; + jqcur[0] = cur; + for ( i = 0; i < delegateCount; i++ ) { + handleObj = handlers[ i ]; + sel = handleObj.selector; + + if ( selMatch[ sel ] === undefined ) { + selMatch[ sel ] = ( + handleObj.quick ? quickIs( cur, handleObj.quick ) : jqcur.is( sel ) + ); + } + if ( selMatch[ sel ] ) { + matches.push( handleObj ); + } + } + if ( matches.length ) { + handlerQueue.push({ elem: cur, matches: matches }); + } + } + } + + // Add the remaining (directly-bound) handlers + if ( handlers.length > delegateCount ) { + handlerQueue.push({ elem: this, matches: handlers.slice( delegateCount ) }); + } + + // Run delegates first; they may want to stop propagation beneath us + for ( i = 0; i < handlerQueue.length && !event.isPropagationStopped(); i++ ) { + matched = handlerQueue[ i ]; + event.currentTarget = matched.elem; + + for ( j = 0; j < matched.matches.length && !event.isImmediatePropagationStopped(); j++ ) { + handleObj = matched.matches[ j ]; + + // Triggered event must either 1) be non-exclusive and have no namespace, or + // 2) have namespace(s) a subset or equal to those in the bound event (both can have no namespace). + if ( run_all || (!event.namespace && !handleObj.namespace) || event.namespace_re && event.namespace_re.test( handleObj.namespace ) ) { + + event.data = handleObj.data; + event.handleObj = handleObj; + + ret = ( (jQuery.event.special[ handleObj.origType ] || {}).handle || handleObj.handler ) + .apply( matched.elem, args ); + + if ( ret !== undefined ) { + event.result = ret; + if ( ret === false ) { + event.preventDefault(); + event.stopPropagation(); + } + } + } + } + } + + return event.result; + }, + + // Includes some event props shared by KeyEvent and MouseEvent + // *** attrChange attrName relatedNode srcElement are not normalized, non-W3C, deprecated, will be removed in 1.8 *** + props: "attrChange attrName relatedNode srcElement altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "), + + fixHooks: {}, + + keyHooks: { + props: "char charCode key keyCode".split(" "), + filter: function( event, original ) { + + // Add which for key events + if ( event.which == null ) { + event.which = original.charCode != null ? original.charCode : original.keyCode; + } + + return event; + } + }, + + mouseHooks: { + props: "button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "), + filter: function( event, original ) { + var eventDoc, doc, body, + button = original.button, + fromElement = original.fromElement; + + // Calculate pageX/Y if missing and clientX/Y available + if ( event.pageX == null && original.clientX != null ) { + eventDoc = event.target.ownerDocument || document; + doc = eventDoc.documentElement; + body = eventDoc.body; + + event.pageX = original.clientX + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - ( doc && doc.clientLeft || body && body.clientLeft || 0 ); + event.pageY = original.clientY + ( doc && doc.scrollTop || body && body.scrollTop || 0 ) - ( doc && doc.clientTop || body && body.clientTop || 0 ); + } + + // Add relatedTarget, if necessary + if ( !event.relatedTarget && fromElement ) { + event.relatedTarget = fromElement === event.target ? original.toElement : fromElement; + } + + // Add which for click: 1 === left; 2 === middle; 3 === right + // Note: button is not normalized, so don't use it + if ( !event.which && button !== undefined ) { + event.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) ); + } + + return event; + } + }, + + fix: function( event ) { + if ( event[ jQuery.expando ] ) { + return event; + } + + // Create a writable copy of the event object and normalize some properties + var i, prop, + originalEvent = event, + fixHook = jQuery.event.fixHooks[ event.type ] || {}, + copy = fixHook.props ? this.props.concat( fixHook.props ) : this.props; + + event = jQuery.Event( originalEvent ); + + for ( i = copy.length; i; ) { + prop = copy[ --i ]; + event[ prop ] = originalEvent[ prop ]; + } + + // Fix target property, if necessary (#1925, IE 6/7/8 & Safari2) + if ( !event.target ) { + event.target = originalEvent.srcElement || document; + } + + // Target should not be a text node (#504, Safari) + if ( event.target.nodeType === 3 ) { + event.target = event.target.parentNode; + } + + // For mouse/key events; add metaKey if it's not there (#3368, IE6/7/8) + if ( event.metaKey === undefined ) { + event.metaKey = event.ctrlKey; + } + + return fixHook.filter? fixHook.filter( event, originalEvent ) : event; + }, + + special: { + ready: { + // Make sure the ready event is setup + setup: jQuery.bindReady + }, + + load: { + // Prevent triggered image.load events from bubbling to window.load + noBubble: true + }, + + focus: { + delegateType: "focusin" + }, + blur: { + delegateType: "focusout" + }, + + beforeunload: { + setup: function( data, namespaces, eventHandle ) { + // We only want to do this special case on windows + if ( jQuery.isWindow( this ) ) { + this.onbeforeunload = eventHandle; + } + }, + + teardown: function( namespaces, eventHandle ) { + if ( this.onbeforeunload === eventHandle ) { + this.onbeforeunload = null; + } + } + } + }, + + simulate: function( type, elem, event, bubble ) { + // Piggyback on a donor event to simulate a different one. + // Fake originalEvent to avoid donor's stopPropagation, but if the + // simulated event prevents default then we do the same on the donor. + var e = jQuery.extend( + new jQuery.Event(), + event, + { type: type, + isSimulated: true, + originalEvent: {} + } + ); + if ( bubble ) { + jQuery.event.trigger( e, null, elem ); + } else { + jQuery.event.dispatch.call( elem, e ); + } + if ( e.isDefaultPrevented() ) { + event.preventDefault(); + } + } +}; + +// Some plugins are using, but it's undocumented/deprecated and will be removed. +// The 1.7 special event interface should provide all the hooks needed now. +jQuery.event.handle = jQuery.event.dispatch; + +jQuery.removeEvent = document.removeEventListener ? + function( elem, type, handle ) { + if ( elem.removeEventListener ) { + elem.removeEventListener( type, handle, false ); + } + } : + function( elem, type, handle ) { + if ( elem.detachEvent ) { + elem.detachEvent( "on" + type, handle ); + } + }; + +jQuery.Event = function( src, props ) { + // Allow instantiation without the 'new' keyword + if ( !(this instanceof jQuery.Event) ) { + return new jQuery.Event( src, props ); + } + + // Event object + if ( src && src.type ) { + this.originalEvent = src; + this.type = src.type; + + // Events bubbling up the document may have been marked as prevented + // by a handler lower down the tree; reflect the correct value. + this.isDefaultPrevented = ( src.defaultPrevented || src.returnValue === false || + src.getPreventDefault && src.getPreventDefault() ) ? returnTrue : returnFalse; + + // Event type + } else { + this.type = src; + } + + // Put explicitly provided properties onto the event object + if ( props ) { + jQuery.extend( this, props ); + } + + // Create a timestamp if incoming event doesn't have one + this.timeStamp = src && src.timeStamp || jQuery.now(); + + // Mark it as fixed + this[ jQuery.expando ] = true; +}; + +function returnFalse() { + return false; +} +function returnTrue() { + return true; +} + +// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding +// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html +jQuery.Event.prototype = { + preventDefault: function() { + this.isDefaultPrevented = returnTrue; + + var e = this.originalEvent; + if ( !e ) { + return; + } + + // if preventDefault exists run it on the original event + if ( e.preventDefault ) { + e.preventDefault(); + + // otherwise set the returnValue property of the original event to false (IE) + } else { + e.returnValue = false; + } + }, + stopPropagation: function() { + this.isPropagationStopped = returnTrue; + + var e = this.originalEvent; + if ( !e ) { + return; + } + // if stopPropagation exists run it on the original event + if ( e.stopPropagation ) { + e.stopPropagation(); + } + // otherwise set the cancelBubble property of the original event to true (IE) + e.cancelBubble = true; + }, + stopImmediatePropagation: function() { + this.isImmediatePropagationStopped = returnTrue; + this.stopPropagation(); + }, + isDefaultPrevented: returnFalse, + isPropagationStopped: returnFalse, + isImmediatePropagationStopped: returnFalse +}; + +// Create mouseenter/leave events using mouseover/out and event-time checks +jQuery.each({ + mouseenter: "mouseover", + mouseleave: "mouseout" +}, function( orig, fix ) { + jQuery.event.special[ orig ] = { + delegateType: fix, + bindType: fix, + + handle: function( event ) { + var target = this, + related = event.relatedTarget, + handleObj = event.handleObj, + selector = handleObj.selector, + ret; + + // For mousenter/leave call the handler if related is outside the target. + // NB: No relatedTarget if the mouse left/entered the browser window + if ( !related || (related !== target && !jQuery.contains( target, related )) ) { + event.type = handleObj.origType; + ret = handleObj.handler.apply( this, arguments ); + event.type = fix; + } + return ret; + } + }; +}); + +// IE submit delegation +if ( !jQuery.support.submitBubbles ) { + + jQuery.event.special.submit = { + setup: function() { + // Only need this for delegated form submit events + if ( jQuery.nodeName( this, "form" ) ) { + return false; + } + + // Lazy-add a submit handler when a descendant form may potentially be submitted + jQuery.event.add( this, "click._submit keypress._submit", function( e ) { + // Node name check avoids a VML-related crash in IE (#9807) + var elem = e.target, + form = jQuery.nodeName( elem, "input" ) || jQuery.nodeName( elem, "button" ) ? elem.form : undefined; + if ( form && !form._submit_attached ) { + jQuery.event.add( form, "submit._submit", function( event ) { + // If form was submitted by the user, bubble the event up the tree + if ( this.parentNode && !event.isTrigger ) { + jQuery.event.simulate( "submit", this.parentNode, event, true ); + } + }); + form._submit_attached = true; + } + }); + // return undefined since we don't need an event listener + }, + + teardown: function() { + // Only need this for delegated form submit events + if ( jQuery.nodeName( this, "form" ) ) { + return false; + } + + // Remove delegated handlers; cleanData eventually reaps submit handlers attached above + jQuery.event.remove( this, "._submit" ); + } + }; +} + +// IE change delegation and checkbox/radio fix +if ( !jQuery.support.changeBubbles ) { + + jQuery.event.special.change = { + + setup: function() { + + if ( rformElems.test( this.nodeName ) ) { + // IE doesn't fire change on a check/radio until blur; trigger it on click + // after a propertychange. Eat the blur-change in special.change.handle. + // This still fires onchange a second time for check/radio after blur. + if ( this.type === "checkbox" || this.type === "radio" ) { + jQuery.event.add( this, "propertychange._change", function( event ) { + if ( event.originalEvent.propertyName === "checked" ) { + this._just_changed = true; + } + }); + jQuery.event.add( this, "click._change", function( event ) { + if ( this._just_changed && !event.isTrigger ) { + this._just_changed = false; + jQuery.event.simulate( "change", this, event, true ); + } + }); + } + return false; + } + // Delegated event; lazy-add a change handler on descendant inputs + jQuery.event.add( this, "beforeactivate._change", function( e ) { + var elem = e.target; + + if ( rformElems.test( elem.nodeName ) && !elem._change_attached ) { + jQuery.event.add( elem, "change._change", function( event ) { + if ( this.parentNode && !event.isSimulated && !event.isTrigger ) { + jQuery.event.simulate( "change", this.parentNode, event, true ); + } + }); + elem._change_attached = true; + } + }); + }, + + handle: function( event ) { + var elem = event.target; + + // Swallow native change events from checkbox/radio, we already triggered them above + if ( this !== elem || event.isSimulated || event.isTrigger || (elem.type !== "radio" && elem.type !== "checkbox") ) { + return event.handleObj.handler.apply( this, arguments ); + } + }, + + teardown: function() { + jQuery.event.remove( this, "._change" ); + + return rformElems.test( this.nodeName ); + } + }; +} + +// Create "bubbling" focus and blur events +if ( !jQuery.support.focusinBubbles ) { + jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) { + + // Attach a single capturing handler while someone wants focusin/focusout + var attaches = 0, + handler = function( event ) { + jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ), true ); + }; + + jQuery.event.special[ fix ] = { + setup: function() { + if ( attaches++ === 0 ) { + document.addEventListener( orig, handler, true ); + } + }, + teardown: function() { + if ( --attaches === 0 ) { + document.removeEventListener( orig, handler, true ); + } + } + }; + }); +} + +jQuery.fn.extend({ + + on: function( types, selector, data, fn, /*INTERNAL*/ one ) { + var origFn, type; + + // Types can be a map of types/handlers + if ( typeof types === "object" ) { + // ( types-Object, selector, data ) + if ( typeof selector !== "string" ) { + // ( types-Object, data ) + data = selector; + selector = undefined; + } + for ( type in types ) { + this.on( type, selector, data, types[ type ], one ); + } + return this; + } + + if ( data == null && fn == null ) { + // ( types, fn ) + fn = selector; + data = selector = undefined; + } else if ( fn == null ) { + if ( typeof selector === "string" ) { + // ( types, selector, fn ) + fn = data; + data = undefined; + } else { + // ( types, data, fn ) + fn = data; + data = selector; + selector = undefined; + } + } + if ( fn === false ) { + fn = returnFalse; + } else if ( !fn ) { + return this; + } + + if ( one === 1 ) { + origFn = fn; + fn = function( event ) { + // Can use an empty set, since event contains the info + jQuery().off( event ); + return origFn.apply( this, arguments ); + }; + // Use same guid so caller can remove using origFn + fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ ); + } + return this.each( function() { + jQuery.event.add( this, types, fn, data, selector ); + }); + }, + one: function( types, selector, data, fn ) { + return this.on.call( this, types, selector, data, fn, 1 ); + }, + off: function( types, selector, fn ) { + if ( types && types.preventDefault && types.handleObj ) { + // ( event ) dispatched jQuery.Event + var handleObj = types.handleObj; + jQuery( types.delegateTarget ).off( + handleObj.namespace? handleObj.type + "." + handleObj.namespace : handleObj.type, + handleObj.selector, + handleObj.handler + ); + return this; + } + if ( typeof types === "object" ) { + // ( types-object [, selector] ) + for ( var type in types ) { + this.off( type, selector, types[ type ] ); + } + return this; + } + if ( selector === false || typeof selector === "function" ) { + // ( types [, fn] ) + fn = selector; + selector = undefined; + } + if ( fn === false ) { + fn = returnFalse; + } + return this.each(function() { + jQuery.event.remove( this, types, fn, selector ); + }); + }, + + bind: function( types, data, fn ) { + return this.on( types, null, data, fn ); + }, + unbind: function( types, fn ) { + return this.off( types, null, fn ); + }, + + live: function( types, data, fn ) { + jQuery( this.context ).on( types, this.selector, data, fn ); + return this; + }, + die: function( types, fn ) { + jQuery( this.context ).off( types, this.selector || "**", fn ); + return this; + }, + + delegate: function( selector, types, data, fn ) { + return this.on( types, selector, data, fn ); + }, + undelegate: function( selector, types, fn ) { + // ( namespace ) or ( selector, types [, fn] ) + return arguments.length == 1? this.off( selector, "**" ) : this.off( types, selector, fn ); + }, + + trigger: function( type, data ) { + return this.each(function() { + jQuery.event.trigger( type, data, this ); + }); + }, + triggerHandler: function( type, data ) { + if ( this[0] ) { + return jQuery.event.trigger( type, data, this[0], true ); + } + }, + + toggle: function( fn ) { + // Save reference to arguments for access in closure + var args = arguments, + guid = fn.guid || jQuery.guid++, + i = 0, + toggler = function( event ) { + // Figure out which function to execute + var lastToggle = ( jQuery._data( this, "lastToggle" + fn.guid ) || 0 ) % i; + jQuery._data( this, "lastToggle" + fn.guid, lastToggle + 1 ); + + // Make sure that clicks stop + event.preventDefault(); + + // and execute the function + return args[ lastToggle ].apply( this, arguments ) || false; + }; + + // link all the functions, so any of them can unbind this click handler + toggler.guid = guid; + while ( i < args.length ) { + args[ i++ ].guid = guid; + } + + return this.click( toggler ); + }, + + hover: function( fnOver, fnOut ) { + return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver ); + } +}); + +jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " + + "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " + + "change select submit keydown keypress keyup error contextmenu").split(" "), function( i, name ) { + + // Handle event binding + jQuery.fn[ name ] = function( data, fn ) { + if ( fn == null ) { + fn = data; + data = null; + } + + return arguments.length > 0 ? + this.on( name, null, data, fn ) : + this.trigger( name ); + }; + + if ( jQuery.attrFn ) { + jQuery.attrFn[ name ] = true; + } + + if ( rkeyEvent.test( name ) ) { + jQuery.event.fixHooks[ name ] = jQuery.event.keyHooks; + } + + if ( rmouseEvent.test( name ) ) { + jQuery.event.fixHooks[ name ] = jQuery.event.mouseHooks; + } +}); + + + +/*! + * Sizzle CSS Selector Engine + * Copyright 2011, The Dojo Foundation + * Released under the MIT, BSD, and GPL Licenses. + * More information: http://sizzlejs.com/ + */ +(function(){ + +var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g, + expando = "sizcache" + (Math.random() + '').replace('.', ''), + done = 0, + toString = Object.prototype.toString, + hasDuplicate = false, + baseHasDuplicate = true, + rBackslash = /\\/g, + rReturn = /\r\n/g, + rNonWord = /\W/; + +// Here we check if the JavaScript engine is using some sort of +// optimization where it does not always call our comparision +// function. If that is the case, discard the hasDuplicate value. +// Thus far that includes Google Chrome. +[0, 0].sort(function() { + baseHasDuplicate = false; + return 0; +}); + +var Sizzle = function( selector, context, results, seed ) { + results = results || []; + context = context || document; + + var origContext = context; + + if ( context.nodeType !== 1 && context.nodeType !== 9 ) { + return []; + } + + if ( !selector || typeof selector !== "string" ) { + return results; + } + + var m, set, checkSet, extra, ret, cur, pop, i, + prune = true, + contextXML = Sizzle.isXML( context ), + parts = [], + soFar = selector; + + // Reset the position of the chunker regexp (start from head) + do { + chunker.exec( "" ); + m = chunker.exec( soFar ); + + if ( m ) { + soFar = m[3]; + + parts.push( m[1] ); + + if ( m[2] ) { + extra = m[3]; + break; + } + } + } while ( m ); + + if ( parts.length > 1 && origPOS.exec( selector ) ) { + + if ( parts.length === 2 && Expr.relative[ parts[0] ] ) { + set = posProcess( parts[0] + parts[1], context, seed ); + + } else { + set = Expr.relative[ parts[0] ] ? + [ context ] : + Sizzle( parts.shift(), context ); + + while ( parts.length ) { + selector = parts.shift(); + + if ( Expr.relative[ selector ] ) { + selector += parts.shift(); + } + + set = posProcess( selector, set, seed ); + } + } + + } else { + // Take a shortcut and set the context if the root selector is an ID + // (but not if it'll be faster if the inner selector is an ID) + if ( !seed && parts.length > 1 && context.nodeType === 9 && !contextXML && + Expr.match.ID.test(parts[0]) && !Expr.match.ID.test(parts[parts.length - 1]) ) { + + ret = Sizzle.find( parts.shift(), context, contextXML ); + context = ret.expr ? + Sizzle.filter( ret.expr, ret.set )[0] : + ret.set[0]; + } + + if ( context ) { + ret = seed ? + { expr: parts.pop(), set: makeArray(seed) } : + Sizzle.find( parts.pop(), parts.length === 1 && (parts[0] === "~" || parts[0] === "+") && context.parentNode ? context.parentNode : context, contextXML ); + + set = ret.expr ? + Sizzle.filter( ret.expr, ret.set ) : + ret.set; + + if ( parts.length > 0 ) { + checkSet = makeArray( set ); + + } else { + prune = false; + } + + while ( parts.length ) { + cur = parts.pop(); + pop = cur; + + if ( !Expr.relative[ cur ] ) { + cur = ""; + } else { + pop = parts.pop(); + } + + if ( pop == null ) { + pop = context; + } + + Expr.relative[ cur ]( checkSet, pop, contextXML ); + } + + } else { + checkSet = parts = []; + } + } + + if ( !checkSet ) { + checkSet = set; + } + + if ( !checkSet ) { + Sizzle.error( cur || selector ); + } + + if ( toString.call(checkSet) === "[object Array]" ) { + if ( !prune ) { + results.push.apply( results, checkSet ); + + } else if ( context && context.nodeType === 1 ) { + for ( i = 0; checkSet[i] != null; i++ ) { + if ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && Sizzle.contains(context, checkSet[i])) ) { + results.push( set[i] ); + } + } + + } else { + for ( i = 0; checkSet[i] != null; i++ ) { + if ( checkSet[i] && checkSet[i].nodeType === 1 ) { + results.push( set[i] ); + } + } + } + + } else { + makeArray( checkSet, results ); + } + + if ( extra ) { + Sizzle( extra, origContext, results, seed ); + Sizzle.uniqueSort( results ); + } + + return results; +}; + +Sizzle.uniqueSort = function( results ) { + if ( sortOrder ) { + hasDuplicate = baseHasDuplicate; + results.sort( sortOrder ); + + if ( hasDuplicate ) { + for ( var i = 1; i < results.length; i++ ) { + if ( results[i] === results[ i - 1 ] ) { + results.splice( i--, 1 ); + } + } + } + } + + return results; +}; + +Sizzle.matches = function( expr, set ) { + return Sizzle( expr, null, null, set ); +}; + +Sizzle.matchesSelector = function( node, expr ) { + return Sizzle( expr, null, null, [node] ).length > 0; +}; + +Sizzle.find = function( expr, context, isXML ) { + var set, i, len, match, type, left; + + if ( !expr ) { + return []; + } + + for ( i = 0, len = Expr.order.length; i < len; i++ ) { + type = Expr.order[i]; + + if ( (match = Expr.leftMatch[ type ].exec( expr )) ) { + left = match[1]; + match.splice( 1, 1 ); + + if ( left.substr( left.length - 1 ) !== "\\" ) { + match[1] = (match[1] || "").replace( rBackslash, "" ); + set = Expr.find[ type ]( match, context, isXML ); + + if ( set != null ) { + expr = expr.replace( Expr.match[ type ], "" ); + break; + } + } + } + } + + if ( !set ) { + set = typeof context.getElementsByTagName !== "undefined" ? + context.getElementsByTagName( "*" ) : + []; + } + + return { set: set, expr: expr }; +}; + +Sizzle.filter = function( expr, set, inplace, not ) { + var match, anyFound, + type, found, item, filter, left, + i, pass, + old = expr, + result = [], + curLoop = set, + isXMLFilter = set && set[0] && Sizzle.isXML( set[0] ); + + while ( expr && set.length ) { + for ( type in Expr.filter ) { + if ( (match = Expr.leftMatch[ type ].exec( expr )) != null && match[2] ) { + filter = Expr.filter[ type ]; + left = match[1]; + + anyFound = false; + + match.splice(1,1); + + if ( left.substr( left.length - 1 ) === "\\" ) { + continue; + } + + if ( curLoop === result ) { + result = []; + } + + if ( Expr.preFilter[ type ] ) { + match = Expr.preFilter[ type ]( match, curLoop, inplace, result, not, isXMLFilter ); + + if ( !match ) { + anyFound = found = true; + + } else if ( match === true ) { + continue; + } + } + + if ( match ) { + for ( i = 0; (item = curLoop[i]) != null; i++ ) { + if ( item ) { + found = filter( item, match, i, curLoop ); + pass = not ^ found; + + if ( inplace && found != null ) { + if ( pass ) { + anyFound = true; + + } else { + curLoop[i] = false; + } + + } else if ( pass ) { + result.push( item ); + anyFound = true; + } + } + } + } + + if ( found !== undefined ) { + if ( !inplace ) { + curLoop = result; + } + + expr = expr.replace( Expr.match[ type ], "" ); + + if ( !anyFound ) { + return []; + } + + break; + } + } + } + + // Improper expression + if ( expr === old ) { + if ( anyFound == null ) { + Sizzle.error( expr ); + + } else { + break; + } + } + + old = expr; + } + + return curLoop; +}; + +Sizzle.error = function( msg ) { + throw new Error( "Syntax error, unrecognized expression: " + msg ); +}; + +/** + * Utility function for retreiving the text value of an array of DOM nodes + * @param {Array|Element} elem + */ +var getText = Sizzle.getText = function( elem ) { + var i, node, + nodeType = elem.nodeType, + ret = ""; + + if ( nodeType ) { + if ( nodeType === 1 || nodeType === 9 ) { + // Use textContent || innerText for elements + if ( typeof elem.textContent === 'string' ) { + return elem.textContent; + } else if ( typeof elem.innerText === 'string' ) { + // Replace IE's carriage returns + return elem.innerText.replace( rReturn, '' ); + } else { + // Traverse it's children + for ( elem = elem.firstChild; elem; elem = elem.nextSibling) { + ret += getText( elem ); + } + } + } else if ( nodeType === 3 || nodeType === 4 ) { + return elem.nodeValue; + } + } else { + + // If no nodeType, this is expected to be an array + for ( i = 0; (node = elem[i]); i++ ) { + // Do not traverse comment nodes + if ( node.nodeType !== 8 ) { + ret += getText( node ); + } + } + } + return ret; +}; + +var Expr = Sizzle.selectors = { + order: [ "ID", "NAME", "TAG" ], + + match: { + ID: /#((?:[\w\u00c0-\uFFFF\-]|\\.)+)/, + CLASS: /\.((?:[\w\u00c0-\uFFFF\-]|\\.)+)/, + NAME: /\[name=['"]*((?:[\w\u00c0-\uFFFF\-]|\\.)+)['"]*\]/, + ATTR: /\[\s*((?:[\w\u00c0-\uFFFF\-]|\\.)+)\s*(?:(\S?=)\s*(?:(['"])(.*?)\3|(#?(?:[\w\u00c0-\uFFFF\-]|\\.)*)|)|)\s*\]/, + TAG: /^((?:[\w\u00c0-\uFFFF\*\-]|\\.)+)/, + CHILD: /:(only|nth|last|first)-child(?:\(\s*(even|odd|(?:[+\-]?\d+|(?:[+\-]?\d*)?n\s*(?:[+\-]\s*\d+)?))\s*\))?/, + POS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^\-]|$)/, + PSEUDO: /:((?:[\w\u00c0-\uFFFF\-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/ + }, + + leftMatch: {}, + + attrMap: { + "class": "className", + "for": "htmlFor" + }, + + attrHandle: { + href: function( elem ) { + return elem.getAttribute( "href" ); + }, + type: function( elem ) { + return elem.getAttribute( "type" ); + } + }, + + relative: { + "+": function(checkSet, part){ + var isPartStr = typeof part === "string", + isTag = isPartStr && !rNonWord.test( part ), + isPartStrNotTag = isPartStr && !isTag; + + if ( isTag ) { + part = part.toLowerCase(); + } + + for ( var i = 0, l = checkSet.length, elem; i < l; i++ ) { + if ( (elem = checkSet[i]) ) { + while ( (elem = elem.previousSibling) && elem.nodeType !== 1 ) {} + + checkSet[i] = isPartStrNotTag || elem && elem.nodeName.toLowerCase() === part ? + elem || false : + elem === part; + } + } + + if ( isPartStrNotTag ) { + Sizzle.filter( part, checkSet, true ); + } + }, + + ">": function( checkSet, part ) { + var elem, + isPartStr = typeof part === "string", + i = 0, + l = checkSet.length; + + if ( isPartStr && !rNonWord.test( part ) ) { + part = part.toLowerCase(); + + for ( ; i < l; i++ ) { + elem = checkSet[i]; + + if ( elem ) { + var parent = elem.parentNode; + checkSet[i] = parent.nodeName.toLowerCase() === part ? parent : false; + } + } + + } else { + for ( ; i < l; i++ ) { + elem = checkSet[i]; + + if ( elem ) { + checkSet[i] = isPartStr ? + elem.parentNode : + elem.parentNode === part; + } + } + + if ( isPartStr ) { + Sizzle.filter( part, checkSet, true ); + } + } + }, + + "": function(checkSet, part, isXML){ + var nodeCheck, + doneName = done++, + checkFn = dirCheck; + + if ( typeof part === "string" && !rNonWord.test( part ) ) { + part = part.toLowerCase(); + nodeCheck = part; + checkFn = dirNodeCheck; + } + + checkFn( "parentNode", part, doneName, checkSet, nodeCheck, isXML ); + }, + + "~": function( checkSet, part, isXML ) { + var nodeCheck, + doneName = done++, + checkFn = dirCheck; + + if ( typeof part === "string" && !rNonWord.test( part ) ) { + part = part.toLowerCase(); + nodeCheck = part; + checkFn = dirNodeCheck; + } + + checkFn( "previousSibling", part, doneName, checkSet, nodeCheck, isXML ); + } + }, + + find: { + ID: function( match, context, isXML ) { + if ( typeof context.getElementById !== "undefined" && !isXML ) { + var m = context.getElementById(match[1]); + // Check parentNode to catch when Blackberry 4.6 returns + // nodes that are no longer in the document #6963 + return m && m.parentNode ? [m] : []; + } + }, + + NAME: function( match, context ) { + if ( typeof context.getElementsByName !== "undefined" ) { + var ret = [], + results = context.getElementsByName( match[1] ); + + for ( var i = 0, l = results.length; i < l; i++ ) { + if ( results[i].getAttribute("name") === match[1] ) { + ret.push( results[i] ); + } + } + + return ret.length === 0 ? null : ret; + } + }, + + TAG: function( match, context ) { + if ( typeof context.getElementsByTagName !== "undefined" ) { + return context.getElementsByTagName( match[1] ); + } + } + }, + preFilter: { + CLASS: function( match, curLoop, inplace, result, not, isXML ) { + match = " " + match[1].replace( rBackslash, "" ) + " "; + + if ( isXML ) { + return match; + } + + for ( var i = 0, elem; (elem = curLoop[i]) != null; i++ ) { + if ( elem ) { + if ( not ^ (elem.className && (" " + elem.className + " ").replace(/[\t\n\r]/g, " ").indexOf(match) >= 0) ) { + if ( !inplace ) { + result.push( elem ); + } + + } else if ( inplace ) { + curLoop[i] = false; + } + } + } + + return false; + }, + + ID: function( match ) { + return match[1].replace( rBackslash, "" ); + }, + + TAG: function( match, curLoop ) { + return match[1].replace( rBackslash, "" ).toLowerCase(); + }, + + CHILD: function( match ) { + if ( match[1] === "nth" ) { + if ( !match[2] ) { + Sizzle.error( match[0] ); + } + + match[2] = match[2].replace(/^\+|\s*/g, ''); + + // parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6' + var test = /(-?)(\d*)(?:n([+\-]?\d*))?/.exec( + match[2] === "even" && "2n" || match[2] === "odd" && "2n+1" || + !/\D/.test( match[2] ) && "0n+" + match[2] || match[2]); + + // calculate the numbers (first)n+(last) including if they are negative + match[2] = (test[1] + (test[2] || 1)) - 0; + match[3] = test[3] - 0; + } + else if ( match[2] ) { + Sizzle.error( match[0] ); + } + + // TODO: Move to normal caching system + match[0] = done++; + + return match; + }, + + ATTR: function( match, curLoop, inplace, result, not, isXML ) { + var name = match[1] = match[1].replace( rBackslash, "" ); + + if ( !isXML && Expr.attrMap[name] ) { + match[1] = Expr.attrMap[name]; + } + + // Handle if an un-quoted value was used + match[4] = ( match[4] || match[5] || "" ).replace( rBackslash, "" ); + + if ( match[2] === "~=" ) { + match[4] = " " + match[4] + " "; + } + + return match; + }, + + PSEUDO: function( match, curLoop, inplace, result, not ) { + if ( match[1] === "not" ) { + // If we're dealing with a complex expression, or a simple one + if ( ( chunker.exec(match[3]) || "" ).length > 1 || /^\w/.test(match[3]) ) { + match[3] = Sizzle(match[3], null, null, curLoop); + + } else { + var ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not); + + if ( !inplace ) { + result.push.apply( result, ret ); + } + + return false; + } + + } else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) { + return true; + } + + return match; + }, + + POS: function( match ) { + match.unshift( true ); + + return match; + } + }, + + filters: { + enabled: function( elem ) { + return elem.disabled === false && elem.type !== "hidden"; + }, + + disabled: function( elem ) { + return elem.disabled === true; + }, + + checked: function( elem ) { + return elem.checked === true; + }, + + selected: function( elem ) { + // Accessing this property makes selected-by-default + // options in Safari work properly + if ( elem.parentNode ) { + elem.parentNode.selectedIndex; + } + + return elem.selected === true; + }, + + parent: function( elem ) { + return !!elem.firstChild; + }, + + empty: function( elem ) { + return !elem.firstChild; + }, + + has: function( elem, i, match ) { + return !!Sizzle( match[3], elem ).length; + }, + + header: function( elem ) { + return (/h\d/i).test( elem.nodeName ); + }, + + text: function( elem ) { + var attr = elem.getAttribute( "type" ), type = elem.type; + // IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc) + // use getAttribute instead to test this case + return elem.nodeName.toLowerCase() === "input" && "text" === type && ( attr === type || attr === null ); + }, + + radio: function( elem ) { + return elem.nodeName.toLowerCase() === "input" && "radio" === elem.type; + }, + + checkbox: function( elem ) { + return elem.nodeName.toLowerCase() === "input" && "checkbox" === elem.type; + }, + + file: function( elem ) { + return elem.nodeName.toLowerCase() === "input" && "file" === elem.type; + }, + + password: function( elem ) { + return elem.nodeName.toLowerCase() === "input" && "password" === elem.type; + }, + + submit: function( elem ) { + var name = elem.nodeName.toLowerCase(); + return (name === "input" || name === "button") && "submit" === elem.type; + }, + + image: function( elem ) { + return elem.nodeName.toLowerCase() === "input" && "image" === elem.type; + }, + + reset: function( elem ) { + var name = elem.nodeName.toLowerCase(); + return (name === "input" || name === "button") && "reset" === elem.type; + }, + + button: function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && "button" === elem.type || name === "button"; + }, + + input: function( elem ) { + return (/input|select|textarea|button/i).test( elem.nodeName ); + }, + + focus: function( elem ) { + return elem === elem.ownerDocument.activeElement; + } + }, + setFilters: { + first: function( elem, i ) { + return i === 0; + }, + + last: function( elem, i, match, array ) { + return i === array.length - 1; + }, + + even: function( elem, i ) { + return i % 2 === 0; + }, + + odd: function( elem, i ) { + return i % 2 === 1; + }, + + lt: function( elem, i, match ) { + return i < match[3] - 0; + }, + + gt: function( elem, i, match ) { + return i > match[3] - 0; + }, + + nth: function( elem, i, match ) { + return match[3] - 0 === i; + }, + + eq: function( elem, i, match ) { + return match[3] - 0 === i; + } + }, + filter: { + PSEUDO: function( elem, match, i, array ) { + var name = match[1], + filter = Expr.filters[ name ]; + + if ( filter ) { + return filter( elem, i, match, array ); + + } else if ( name === "contains" ) { + return (elem.textContent || elem.innerText || getText([ elem ]) || "").indexOf(match[3]) >= 0; + + } else if ( name === "not" ) { + var not = match[3]; + + for ( var j = 0, l = not.length; j < l; j++ ) { + if ( not[j] === elem ) { + return false; + } + } + + return true; + + } else { + Sizzle.error( name ); + } + }, + + CHILD: function( elem, match ) { + var first, last, + doneName, parent, cache, + count, diff, + type = match[1], + node = elem; + + switch ( type ) { + case "only": + case "first": + while ( (node = node.previousSibling) ) { + if ( node.nodeType === 1 ) { + return false; + } + } + + if ( type === "first" ) { + return true; + } + + node = elem; + + case "last": + while ( (node = node.nextSibling) ) { + if ( node.nodeType === 1 ) { + return false; + } + } + + return true; + + case "nth": + first = match[2]; + last = match[3]; + + if ( first === 1 && last === 0 ) { + return true; + } + + doneName = match[0]; + parent = elem.parentNode; + + if ( parent && (parent[ expando ] !== doneName || !elem.nodeIndex) ) { + count = 0; + + for ( node = parent.firstChild; node; node = node.nextSibling ) { + if ( node.nodeType === 1 ) { + node.nodeIndex = ++count; + } + } + + parent[ expando ] = doneName; + } + + diff = elem.nodeIndex - last; + + if ( first === 0 ) { + return diff === 0; + + } else { + return ( diff % first === 0 && diff / first >= 0 ); + } + } + }, + + ID: function( elem, match ) { + return elem.nodeType === 1 && elem.getAttribute("id") === match; + }, + + TAG: function( elem, match ) { + return (match === "*" && elem.nodeType === 1) || !!elem.nodeName && elem.nodeName.toLowerCase() === match; + }, + + CLASS: function( elem, match ) { + return (" " + (elem.className || elem.getAttribute("class")) + " ") + .indexOf( match ) > -1; + }, + + ATTR: function( elem, match ) { + var name = match[1], + result = Sizzle.attr ? + Sizzle.attr( elem, name ) : + Expr.attrHandle[ name ] ? + Expr.attrHandle[ name ]( elem ) : + elem[ name ] != null ? + elem[ name ] : + elem.getAttribute( name ), + value = result + "", + type = match[2], + check = match[4]; + + return result == null ? + type === "!=" : + !type && Sizzle.attr ? + result != null : + type === "=" ? + value === check : + type === "*=" ? + value.indexOf(check) >= 0 : + type === "~=" ? + (" " + value + " ").indexOf(check) >= 0 : + !check ? + value && result !== false : + type === "!=" ? + value !== check : + type === "^=" ? + value.indexOf(check) === 0 : + type === "$=" ? + value.substr(value.length - check.length) === check : + type === "|=" ? + value === check || value.substr(0, check.length + 1) === check + "-" : + false; + }, + + POS: function( elem, match, i, array ) { + var name = match[2], + filter = Expr.setFilters[ name ]; + + if ( filter ) { + return filter( elem, i, match, array ); + } + } + } +}; + +var origPOS = Expr.match.POS, + fescape = function(all, num){ + return "\\" + (num - 0 + 1); + }; + +for ( var type in Expr.match ) { + Expr.match[ type ] = new RegExp( Expr.match[ type ].source + (/(?![^\[]*\])(?![^\(]*\))/.source) ); + Expr.leftMatch[ type ] = new RegExp( /(^(?:.|\r|\n)*?)/.source + Expr.match[ type ].source.replace(/\\(\d+)/g, fescape) ); +} + +var makeArray = function( array, results ) { + array = Array.prototype.slice.call( array, 0 ); + + if ( results ) { + results.push.apply( results, array ); + return results; + } + + return array; +}; + +// Perform a simple check to determine if the browser is capable of +// converting a NodeList to an array using builtin methods. +// Also verifies that the returned array holds DOM nodes +// (which is not the case in the Blackberry browser) +try { + Array.prototype.slice.call( document.documentElement.childNodes, 0 )[0].nodeType; + +// Provide a fallback method if it does not work +} catch( e ) { + makeArray = function( array, results ) { + var i = 0, + ret = results || []; + + if ( toString.call(array) === "[object Array]" ) { + Array.prototype.push.apply( ret, array ); + + } else { + if ( typeof array.length === "number" ) { + for ( var l = array.length; i < l; i++ ) { + ret.push( array[i] ); + } + + } else { + for ( ; array[i]; i++ ) { + ret.push( array[i] ); + } + } + } + + return ret; + }; +} + +var sortOrder, siblingCheck; + +if ( document.documentElement.compareDocumentPosition ) { + sortOrder = function( a, b ) { + if ( a === b ) { + hasDuplicate = true; + return 0; + } + + if ( !a.compareDocumentPosition || !b.compareDocumentPosition ) { + return a.compareDocumentPosition ? -1 : 1; + } + + return a.compareDocumentPosition(b) & 4 ? -1 : 1; + }; + +} else { + sortOrder = function( a, b ) { + // The nodes are identical, we can exit early + if ( a === b ) { + hasDuplicate = true; + return 0; + + // Fallback to using sourceIndex (in IE) if it's available on both nodes + } else if ( a.sourceIndex && b.sourceIndex ) { + return a.sourceIndex - b.sourceIndex; + } + + var al, bl, + ap = [], + bp = [], + aup = a.parentNode, + bup = b.parentNode, + cur = aup; + + // If the nodes are siblings (or identical) we can do a quick check + if ( aup === bup ) { + return siblingCheck( a, b ); + + // If no parents were found then the nodes are disconnected + } else if ( !aup ) { + return -1; + + } else if ( !bup ) { + return 1; + } + + // Otherwise they're somewhere else in the tree so we need + // to build up a full list of the parentNodes for comparison + while ( cur ) { + ap.unshift( cur ); + cur = cur.parentNode; + } + + cur = bup; + + while ( cur ) { + bp.unshift( cur ); + cur = cur.parentNode; + } + + al = ap.length; + bl = bp.length; + + // Start walking down the tree looking for a discrepancy + for ( var i = 0; i < al && i < bl; i++ ) { + if ( ap[i] !== bp[i] ) { + return siblingCheck( ap[i], bp[i] ); + } + } + + // We ended someplace up the tree so do a sibling check + return i === al ? + siblingCheck( a, bp[i], -1 ) : + siblingCheck( ap[i], b, 1 ); + }; + + siblingCheck = function( a, b, ret ) { + if ( a === b ) { + return ret; + } + + var cur = a.nextSibling; + + while ( cur ) { + if ( cur === b ) { + return -1; + } + + cur = cur.nextSibling; + } + + return 1; + }; +} + +// Check to see if the browser returns elements by name when +// querying by getElementById (and provide a workaround) +(function(){ + // We're going to inject a fake input element with a specified name + var form = document.createElement("div"), + id = "script" + (new Date()).getTime(), + root = document.documentElement; + + form.innerHTML = ""; + + // Inject it into the root element, check its status, and remove it quickly + root.insertBefore( form, root.firstChild ); + + // The workaround has to do additional checks after a getElementById + // Which slows things down for other browsers (hence the branching) + if ( document.getElementById( id ) ) { + Expr.find.ID = function( match, context, isXML ) { + if ( typeof context.getElementById !== "undefined" && !isXML ) { + var m = context.getElementById(match[1]); + + return m ? + m.id === match[1] || typeof m.getAttributeNode !== "undefined" && m.getAttributeNode("id").nodeValue === match[1] ? + [m] : + undefined : + []; + } + }; + + Expr.filter.ID = function( elem, match ) { + var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id"); + + return elem.nodeType === 1 && node && node.nodeValue === match; + }; + } + + root.removeChild( form ); + + // release memory in IE + root = form = null; +})(); + +(function(){ + // Check to see if the browser returns only elements + // when doing getElementsByTagName("*") + + // Create a fake element + var div = document.createElement("div"); + div.appendChild( document.createComment("") ); + + // Make sure no comments are found + if ( div.getElementsByTagName("*").length > 0 ) { + Expr.find.TAG = function( match, context ) { + var results = context.getElementsByTagName( match[1] ); + + // Filter out possible comments + if ( match[1] === "*" ) { + var tmp = []; + + for ( var i = 0; results[i]; i++ ) { + if ( results[i].nodeType === 1 ) { + tmp.push( results[i] ); + } + } + + results = tmp; + } + + return results; + }; + } + + // Check to see if an attribute returns normalized href attributes + div.innerHTML = ""; + + if ( div.firstChild && typeof div.firstChild.getAttribute !== "undefined" && + div.firstChild.getAttribute("href") !== "#" ) { + + Expr.attrHandle.href = function( elem ) { + return elem.getAttribute( "href", 2 ); + }; + } + + // release memory in IE + div = null; +})(); + +if ( document.querySelectorAll ) { + (function(){ + var oldSizzle = Sizzle, + div = document.createElement("div"), + id = "__sizzle__"; + + div.innerHTML = "

"; + + // Safari can't handle uppercase or unicode characters when + // in quirks mode. + if ( div.querySelectorAll && div.querySelectorAll(".TEST").length === 0 ) { + return; + } + + Sizzle = function( query, context, extra, seed ) { + context = context || document; + + // Only use querySelectorAll on non-XML documents + // (ID selectors don't work in non-HTML documents) + if ( !seed && !Sizzle.isXML(context) ) { + // See if we find a selector to speed up + var match = /^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec( query ); + + if ( match && (context.nodeType === 1 || context.nodeType === 9) ) { + // Speed-up: Sizzle("TAG") + if ( match[1] ) { + return makeArray( context.getElementsByTagName( query ), extra ); + + // Speed-up: Sizzle(".CLASS") + } else if ( match[2] && Expr.find.CLASS && context.getElementsByClassName ) { + return makeArray( context.getElementsByClassName( match[2] ), extra ); + } + } + + if ( context.nodeType === 9 ) { + // Speed-up: Sizzle("body") + // The body element only exists once, optimize finding it + if ( query === "body" && context.body ) { + return makeArray( [ context.body ], extra ); + + // Speed-up: Sizzle("#ID") + } else if ( match && match[3] ) { + var elem = context.getElementById( match[3] ); + + // Check parentNode to catch when Blackberry 4.6 returns + // nodes that are no longer in the document #6963 + if ( elem && elem.parentNode ) { + // Handle the case where IE and Opera return items + // by name instead of ID + if ( elem.id === match[3] ) { + return makeArray( [ elem ], extra ); + } + + } else { + return makeArray( [], extra ); + } + } + + try { + return makeArray( context.querySelectorAll(query), extra ); + } catch(qsaError) {} + + // qSA works strangely on Element-rooted queries + // We can work around this by specifying an extra ID on the root + // and working up from there (Thanks to Andrew Dupont for the technique) + // IE 8 doesn't work on object elements + } else if ( context.nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) { + var oldContext = context, + old = context.getAttribute( "id" ), + nid = old || id, + hasParent = context.parentNode, + relativeHierarchySelector = /^\s*[+~]/.test( query ); + + if ( !old ) { + context.setAttribute( "id", nid ); + } else { + nid = nid.replace( /'/g, "\\$&" ); + } + if ( relativeHierarchySelector && hasParent ) { + context = context.parentNode; + } + + try { + if ( !relativeHierarchySelector || hasParent ) { + return makeArray( context.querySelectorAll( "[id='" + nid + "'] " + query ), extra ); + } + + } catch(pseudoError) { + } finally { + if ( !old ) { + oldContext.removeAttribute( "id" ); + } + } + } + } + + return oldSizzle(query, context, extra, seed); + }; + + for ( var prop in oldSizzle ) { + Sizzle[ prop ] = oldSizzle[ prop ]; + } + + // release memory in IE + div = null; + })(); +} + +(function(){ + var html = document.documentElement, + matches = html.matchesSelector || html.mozMatchesSelector || html.webkitMatchesSelector || html.msMatchesSelector; + + if ( matches ) { + // Check to see if it's possible to do matchesSelector + // on a disconnected node (IE 9 fails this) + var disconnectedMatch = !matches.call( document.createElement( "div" ), "div" ), + pseudoWorks = false; + + try { + // This should fail with an exception + // Gecko does not error, returns false instead + matches.call( document.documentElement, "[test!='']:sizzle" ); + + } catch( pseudoError ) { + pseudoWorks = true; + } + + Sizzle.matchesSelector = function( node, expr ) { + // Make sure that attribute selectors are quoted + expr = expr.replace(/\=\s*([^'"\]]*)\s*\]/g, "='$1']"); + + if ( !Sizzle.isXML( node ) ) { + try { + if ( pseudoWorks || !Expr.match.PSEUDO.test( expr ) && !/!=/.test( expr ) ) { + var ret = matches.call( node, expr ); + + // IE 9's matchesSelector returns false on disconnected nodes + if ( ret || !disconnectedMatch || + // As well, disconnected nodes are said to be in a document + // fragment in IE 9, so check for that + node.document && node.document.nodeType !== 11 ) { + return ret; + } + } + } catch(e) {} + } + + return Sizzle(expr, null, null, [node]).length > 0; + }; + } +})(); + +(function(){ + var div = document.createElement("div"); + + div.innerHTML = "
"; + + // Opera can't find a second classname (in 9.6) + // Also, make sure that getElementsByClassName actually exists + if ( !div.getElementsByClassName || div.getElementsByClassName("e").length === 0 ) { + return; + } + + // Safari caches class attributes, doesn't catch changes (in 3.2) + div.lastChild.className = "e"; + + if ( div.getElementsByClassName("e").length === 1 ) { + return; + } + + Expr.order.splice(1, 0, "CLASS"); + Expr.find.CLASS = function( match, context, isXML ) { + if ( typeof context.getElementsByClassName !== "undefined" && !isXML ) { + return context.getElementsByClassName(match[1]); + } + }; + + // release memory in IE + div = null; +})(); + +function dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) { + for ( var i = 0, l = checkSet.length; i < l; i++ ) { + var elem = checkSet[i]; + + if ( elem ) { + var match = false; + + elem = elem[dir]; + + while ( elem ) { + if ( elem[ expando ] === doneName ) { + match = checkSet[elem.sizset]; + break; + } + + if ( elem.nodeType === 1 && !isXML ){ + elem[ expando ] = doneName; + elem.sizset = i; + } + + if ( elem.nodeName.toLowerCase() === cur ) { + match = elem; + break; + } + + elem = elem[dir]; + } + + checkSet[i] = match; + } + } +} + +function dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) { + for ( var i = 0, l = checkSet.length; i < l; i++ ) { + var elem = checkSet[i]; + + if ( elem ) { + var match = false; + + elem = elem[dir]; + + while ( elem ) { + if ( elem[ expando ] === doneName ) { + match = checkSet[elem.sizset]; + break; + } + + if ( elem.nodeType === 1 ) { + if ( !isXML ) { + elem[ expando ] = doneName; + elem.sizset = i; + } + + if ( typeof cur !== "string" ) { + if ( elem === cur ) { + match = true; + break; + } + + } else if ( Sizzle.filter( cur, [elem] ).length > 0 ) { + match = elem; + break; + } + } + + elem = elem[dir]; + } + + checkSet[i] = match; + } + } +} + +if ( document.documentElement.contains ) { + Sizzle.contains = function( a, b ) { + return a !== b && (a.contains ? a.contains(b) : true); + }; + +} else if ( document.documentElement.compareDocumentPosition ) { + Sizzle.contains = function( a, b ) { + return !!(a.compareDocumentPosition(b) & 16); + }; + +} else { + Sizzle.contains = function() { + return false; + }; +} + +Sizzle.isXML = function( elem ) { + // documentElement is verified for cases where it doesn't yet exist + // (such as loading iframes in IE - #4833) + var documentElement = (elem ? elem.ownerDocument || elem : 0).documentElement; + + return documentElement ? documentElement.nodeName !== "HTML" : false; +}; + +var posProcess = function( selector, context, seed ) { + var match, + tmpSet = [], + later = "", + root = context.nodeType ? [context] : context; + + // Position selectors must be done after the filter + // And so must :not(positional) so we move all PSEUDOs to the end + while ( (match = Expr.match.PSEUDO.exec( selector )) ) { + later += match[0]; + selector = selector.replace( Expr.match.PSEUDO, "" ); + } + + selector = Expr.relative[selector] ? selector + "*" : selector; + + for ( var i = 0, l = root.length; i < l; i++ ) { + Sizzle( selector, root[i], tmpSet, seed ); + } + + return Sizzle.filter( later, tmpSet ); +}; + +// EXPOSE +// Override sizzle attribute retrieval +Sizzle.attr = jQuery.attr; +Sizzle.selectors.attrMap = {}; +jQuery.find = Sizzle; +jQuery.expr = Sizzle.selectors; +jQuery.expr[":"] = jQuery.expr.filters; +jQuery.unique = Sizzle.uniqueSort; +jQuery.text = Sizzle.getText; +jQuery.isXMLDoc = Sizzle.isXML; +jQuery.contains = Sizzle.contains; + + +})(); + + +var runtil = /Until$/, + rparentsprev = /^(?:parents|prevUntil|prevAll)/, + // Note: This RegExp should be improved, or likely pulled from Sizzle + rmultiselector = /,/, + isSimple = /^.[^:#\[\.,]*$/, + slice = Array.prototype.slice, + POS = jQuery.expr.match.POS, + // methods guaranteed to produce a unique set when starting from a unique set + guaranteedUnique = { + children: true, + contents: true, + next: true, + prev: true + }; + +jQuery.fn.extend({ + find: function( selector ) { + var self = this, + i, l; + + if ( typeof selector !== "string" ) { + return jQuery( selector ).filter(function() { + for ( i = 0, l = self.length; i < l; i++ ) { + if ( jQuery.contains( self[ i ], this ) ) { + return true; + } + } + }); + } + + var ret = this.pushStack( "", "find", selector ), + length, n, r; + + for ( i = 0, l = this.length; i < l; i++ ) { + length = ret.length; + jQuery.find( selector, this[i], ret ); + + if ( i > 0 ) { + // Make sure that the results are unique + for ( n = length; n < ret.length; n++ ) { + for ( r = 0; r < length; r++ ) { + if ( ret[r] === ret[n] ) { + ret.splice(n--, 1); + break; + } + } + } + } + } + + return ret; + }, + + has: function( target ) { + var targets = jQuery( target ); + return this.filter(function() { + for ( var i = 0, l = targets.length; i < l; i++ ) { + if ( jQuery.contains( this, targets[i] ) ) { + return true; + } + } + }); + }, + + not: function( selector ) { + return this.pushStack( winnow(this, selector, false), "not", selector); + }, + + filter: function( selector ) { + return this.pushStack( winnow(this, selector, true), "filter", selector ); + }, + + is: function( selector ) { + return !!selector && ( + typeof selector === "string" ? + // If this is a positional selector, check membership in the returned set + // so $("p:first").is("p:last") won't return true for a doc with two "p". + POS.test( selector ) ? + jQuery( selector, this.context ).index( this[0] ) >= 0 : + jQuery.filter( selector, this ).length > 0 : + this.filter( selector ).length > 0 ); + }, + + closest: function( selectors, context ) { + var ret = [], i, l, cur = this[0]; + + // Array (deprecated as of jQuery 1.7) + if ( jQuery.isArray( selectors ) ) { + var level = 1; + + while ( cur && cur.ownerDocument && cur !== context ) { + for ( i = 0; i < selectors.length; i++ ) { + + if ( jQuery( cur ).is( selectors[ i ] ) ) { + ret.push({ selector: selectors[ i ], elem: cur, level: level }); + } + } + + cur = cur.parentNode; + level++; + } + + return ret; + } + + // String + var pos = POS.test( selectors ) || typeof selectors !== "string" ? + jQuery( selectors, context || this.context ) : + 0; + + for ( i = 0, l = this.length; i < l; i++ ) { + cur = this[i]; + + while ( cur ) { + if ( pos ? pos.index(cur) > -1 : jQuery.find.matchesSelector(cur, selectors) ) { + ret.push( cur ); + break; + + } else { + cur = cur.parentNode; + if ( !cur || !cur.ownerDocument || cur === context || cur.nodeType === 11 ) { + break; + } + } + } + } + + ret = ret.length > 1 ? jQuery.unique( ret ) : ret; + + return this.pushStack( ret, "closest", selectors ); + }, + + // Determine the position of an element within + // the matched set of elements + index: function( elem ) { + + // No argument, return index in parent + if ( !elem ) { + return ( this[0] && this[0].parentNode ) ? this.prevAll().length : -1; + } + + // index in selector + if ( typeof elem === "string" ) { + return jQuery.inArray( this[0], jQuery( elem ) ); + } + + // Locate the position of the desired element + return jQuery.inArray( + // If it receives a jQuery object, the first element is used + elem.jquery ? elem[0] : elem, this ); + }, + + add: function( selector, context ) { + var set = typeof selector === "string" ? + jQuery( selector, context ) : + jQuery.makeArray( selector && selector.nodeType ? [ selector ] : selector ), + all = jQuery.merge( this.get(), set ); + + return this.pushStack( isDisconnected( set[0] ) || isDisconnected( all[0] ) ? + all : + jQuery.unique( all ) ); + }, + + andSelf: function() { + return this.add( this.prevObject ); + } +}); + +// A painfully simple check to see if an element is disconnected +// from a document (should be improved, where feasible). +function isDisconnected( node ) { + return !node || !node.parentNode || node.parentNode.nodeType === 11; +} + +jQuery.each({ + parent: function( elem ) { + var parent = elem.parentNode; + return parent && parent.nodeType !== 11 ? parent : null; + }, + parents: function( elem ) { + return jQuery.dir( elem, "parentNode" ); + }, + parentsUntil: function( elem, i, until ) { + return jQuery.dir( elem, "parentNode", until ); + }, + next: function( elem ) { + return jQuery.nth( elem, 2, "nextSibling" ); + }, + prev: function( elem ) { + return jQuery.nth( elem, 2, "previousSibling" ); + }, + nextAll: function( elem ) { + return jQuery.dir( elem, "nextSibling" ); + }, + prevAll: function( elem ) { + return jQuery.dir( elem, "previousSibling" ); + }, + nextUntil: function( elem, i, until ) { + return jQuery.dir( elem, "nextSibling", until ); + }, + prevUntil: function( elem, i, until ) { + return jQuery.dir( elem, "previousSibling", until ); + }, + siblings: function( elem ) { + return jQuery.sibling( elem.parentNode.firstChild, elem ); + }, + children: function( elem ) { + return jQuery.sibling( elem.firstChild ); + }, + contents: function( elem ) { + return jQuery.nodeName( elem, "iframe" ) ? + elem.contentDocument || elem.contentWindow.document : + jQuery.makeArray( elem.childNodes ); + } +}, function( name, fn ) { + jQuery.fn[ name ] = function( until, selector ) { + var ret = jQuery.map( this, fn, until ); + + if ( !runtil.test( name ) ) { + selector = until; + } + + if ( selector && typeof selector === "string" ) { + ret = jQuery.filter( selector, ret ); + } + + ret = this.length > 1 && !guaranteedUnique[ name ] ? jQuery.unique( ret ) : ret; + + if ( (this.length > 1 || rmultiselector.test( selector )) && rparentsprev.test( name ) ) { + ret = ret.reverse(); + } + + return this.pushStack( ret, name, slice.call( arguments ).join(",") ); + }; +}); + +jQuery.extend({ + filter: function( expr, elems, not ) { + if ( not ) { + expr = ":not(" + expr + ")"; + } + + return elems.length === 1 ? + jQuery.find.matchesSelector(elems[0], expr) ? [ elems[0] ] : [] : + jQuery.find.matches(expr, elems); + }, + + dir: function( elem, dir, until ) { + var matched = [], + cur = elem[ dir ]; + + while ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) { + if ( cur.nodeType === 1 ) { + matched.push( cur ); + } + cur = cur[dir]; + } + return matched; + }, + + nth: function( cur, result, dir, elem ) { + result = result || 1; + var num = 0; + + for ( ; cur; cur = cur[dir] ) { + if ( cur.nodeType === 1 && ++num === result ) { + break; + } + } + + return cur; + }, + + sibling: function( n, elem ) { + var r = []; + + for ( ; n; n = n.nextSibling ) { + if ( n.nodeType === 1 && n !== elem ) { + r.push( n ); + } + } + + return r; + } +}); + +// Implement the identical functionality for filter and not +function winnow( elements, qualifier, keep ) { + + // Can't pass null or undefined to indexOf in Firefox 4 + // Set to 0 to skip string check + qualifier = qualifier || 0; + + if ( jQuery.isFunction( qualifier ) ) { + return jQuery.grep(elements, function( elem, i ) { + var retVal = !!qualifier.call( elem, i, elem ); + return retVal === keep; + }); + + } else if ( qualifier.nodeType ) { + return jQuery.grep(elements, function( elem, i ) { + return ( elem === qualifier ) === keep; + }); + + } else if ( typeof qualifier === "string" ) { + var filtered = jQuery.grep(elements, function( elem ) { + return elem.nodeType === 1; + }); + + if ( isSimple.test( qualifier ) ) { + return jQuery.filter(qualifier, filtered, !keep); + } else { + qualifier = jQuery.filter( qualifier, filtered ); + } + } + + return jQuery.grep(elements, function( elem, i ) { + return ( jQuery.inArray( elem, qualifier ) >= 0 ) === keep; + }); +} + + + + +function createSafeFragment( document ) { + var list = nodeNames.split( "|" ), + safeFrag = document.createDocumentFragment(); + + if ( safeFrag.createElement ) { + while ( list.length ) { + safeFrag.createElement( + list.pop() + ); + } + } + return safeFrag; +} + +var nodeNames = "abbr|article|aside|audio|canvas|datalist|details|figcaption|figure|footer|" + + "header|hgroup|mark|meter|nav|output|progress|section|summary|time|video", + rinlinejQuery = / jQuery\d+="(?:\d+|null)"/g, + rleadingWhitespace = /^\s+/, + rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig, + rtagName = /<([\w:]+)/, + rtbody = /", "" ], + legend: [ 1, "
", "
" ], + thead: [ 1, "", "
" ], + tr: [ 2, "", "
" ], + td: [ 3, "", "
" ], + col: [ 2, "", "
" ], + area: [ 1, "", "" ], + _default: [ 0, "", "" ] + }, + safeFragment = createSafeFragment( document ); + +wrapMap.optgroup = wrapMap.option; +wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; +wrapMap.th = wrapMap.td; + +// IE can't serialize and + + + + + + + + + diff --git a/js/src/gilded_rose.js b/js/src/gilded_rose.js index c6517b3c..4d28da89 100644 --- a/js/src/gilded_rose.js +++ b/js/src/gilded_rose.js @@ -6,13 +6,6 @@ function Item(name, sell_in, quality) { var items = [] -items.push(new Item('+5 Dexterity Vest', 10, 20)); -items.push(new Item('Aged Brie', 2, 0)); -items.push(new Item('Elixir of the Mongoose', 5, 7)); -items.push(new Item('Sulfuras, Hand of Ragnaros', 0, 80)); -items.push(new Item('Backstage passes to a TAFKAL80ETC concert', 15, 20)); -items.push(new Item('Conjured Mana Cake', 3, 6)); - function update_quality() { for (var i = 0; i < items.length; i++) { if (items[i].name != 'Aged Brie' && items[i].name != 'Backstage passes to a TAFKAL80ETC concert') { From 316476a258d1bf873c495df4f3f450f6ff4aca81 Mon Sep 17 00:00:00 2001 From: Peter Kofler Date: Tue, 8 Jul 2014 23:50:04 +0200 Subject: [PATCH 127/634] wrap drop statements inside blocks to avoid exception when running first time --- plsql/item.sql | 13 ++++++++++++- plsql/item_with_id.sql | 37 ++++++++++++++++++++++++++++--------- 2 files changed, 40 insertions(+), 10 deletions(-) diff --git a/plsql/item.sql b/plsql/item.sql index 199acd73..97bd9e83 100644 --- a/plsql/item.sql +++ b/plsql/item.sql @@ -1,5 +1,14 @@ PROMPT Creating Table 'ITEM' -DROP TABLE item; + +BEGIN + EXECUTE IMMEDIATE 'DROP TABLE item'; +EXCEPTION + WHEN OTHERS THEN + IF SQLCODE != -942 THEN + RAISE; + END IF; +END; + CREATE TABLE item ( name VARCHAR2(100) NOT NULL, @@ -7,3 +16,5 @@ CREATE TABLE item quality NUMBER(6) NOT NULL ); / + +SHOW ERRORS; diff --git a/plsql/item_with_id.sql b/plsql/item_with_id.sql index 7d78aedf..8d431257 100644 --- a/plsql/item_with_id.sql +++ b/plsql/item_with_id.sql @@ -1,5 +1,14 @@ PROMPT Creating Table 'ITEM' with auto-increment primary key 'ID' -DROP TABLE item; + +BEGIN + EXECUTE IMMEDIATE 'DROP TABLE item'; +EXCEPTION + WHEN OTHERS THEN + IF SQLCODE != -942 THEN + RAISE; + END IF; +END; + CREATE TABLE item ( id NUMBER(6) NOT NULL, @@ -13,19 +22,29 @@ ALTER TABLE item ADD ( CONSTRAINT item_pk PRIMARY KEY (ID)); / -DROP SEQUENCE item_id_seq; -CREATE SEQUENCE item_id_seq - INCREMENT BY 1 - START WITH 1 +BEGIN + EXECUTE IMMEDIATE 'DROP SEQUENCE item_id_seq'; +EXCEPTION + WHEN OTHERS THEN + IF SQLCODE != -2289 THEN + RAISE; + END IF; +END; + +CREATE SEQUENCE item_id_seq + INCREMENT BY 1 + START WITH 1 MAXVALUE 999999 - MINVALUE 1 + MINVALUE 1 NOCYCLE; / -CREATE OR REPLACE TRIGGER item_bis_trg - BEFORE INSERT ON item - FOR EACH ROW +CREATE OR REPLACE TRIGGER item_bis_trg + BEFORE INSERT ON item + FOR EACH ROW BEGIN SELECT item_id_seq.NEXTVAL INTO :new.id FROM dual; END; / + +SHOW ERRORS; From 8aaf87ffad4b390d8aaa45a03aa099d96a8e6e3f Mon Sep 17 00:00:00 2001 From: Peter Kofler Date: Tue, 8 Jul 2014 23:51:33 +0200 Subject: [PATCH 128/634] replace != with lt;gt; because I was told it is more PL/SQL-ish --- plsql/update_quality.sql | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/plsql/update_quality.sql b/plsql/update_quality.sql index c1f2febe..372b6bdb 100644 --- a/plsql/update_quality.sql +++ b/plsql/update_quality.sql @@ -12,10 +12,10 @@ BEGIN l_name := l_item.name; l_sell_in := l_item.sell_in; l_quality := l_item.quality; - - IF l_name != 'Aged Brie' AND l_name != 'Backstage passes to a TAFKAL80ETC concert' THEN + + IF l_name <> 'Aged Brie' AND l_name <> 'Backstage passes to a TAFKAL80ETC concert' THEN IF l_quality > 0 THEN - IF l_name != 'Sulfuras, Hand of Ragnaros' THEN + IF l_name <> 'Sulfuras, Hand of Ragnaros' THEN l_quality := l_quality - 1; END IF; END IF; @@ -36,16 +36,16 @@ BEGIN END IF; END IF; END IF; - - IF l_name != 'Sulfuras, Hand of Ragnaros' THEN + + IF l_name <> 'Sulfuras, Hand of Ragnaros' THEN l_sell_in := l_sell_in - 1; END IF; - + IF l_sell_in < 0 THEN - IF l_name != 'Aged Brie' THEN - IF l_name != 'Backstage passes to a TAFKAL80ETC concert' THEN + IF l_name <> 'Aged Brie' THEN + IF l_name <> 'Backstage passes to a TAFKAL80ETC concert' THEN IF l_quality > 0 THEN - IF l_name != 'Sulfuras, Hand of Ragnaros' THEN + IF l_name <> 'Sulfuras, Hand of Ragnaros' THEN l_quality := l_quality - 1; END IF; END IF; @@ -58,7 +58,7 @@ BEGIN END IF; END IF; END IF; - + UPDATE item SET name = l_name, sell_in = l_sell_in, quality = l_quality WHERE CURRENT OF c_items; END LOOP; From fbea424fb7a92954943b6313782abc62b5fa713c Mon Sep 17 00:00:00 2001 From: Peter Kofler Date: Tue, 8 Jul 2014 23:52:20 +0200 Subject: [PATCH 129/634] turn serveroutput on so we see the results of the texttest fixture --- plsql/texttest_fixture.sql | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/plsql/texttest_fixture.sql b/plsql/texttest_fixture.sql index 59a8f39c..6d2bbeef 100644 --- a/plsql/texttest_fixture.sql +++ b/plsql/texttest_fixture.sql @@ -1,13 +1,15 @@ +SET SERVEROUTPUT ON; + DELETE FROM item; DECLARE l_days NUMBER(3); - CURSOR c_items IS + CURSOR c_items IS SELECT name, sell_in, quality FROM item; l_item c_items%ROWTYPE; BEGIN DBMS_OUTPUT.PUT_LINE('OMGHAI!'); - + new_item('+5 Dexterity Vest', 10, 20); new_item('Aged Brie', 2, 0); new_item('Elixir of the Mongoose', 5, 7); @@ -18,7 +20,7 @@ BEGIN new_item('Backstage passes to a TAFKAL80ETC concert', 5, 49); -- this conjured item does not work properly yet ; new_item('Conjured Mana Cake', 3, 6); - + l_days := 2; FOR i IN 0 .. l_days - 1 From 24271306f07a3094e23f13d48ed45e93ad218bc0 Mon Sep 17 00:00:00 2001 From: emilybache Date: Thu, 25 Sep 2014 21:18:39 +0200 Subject: [PATCH 130/634] added line breaks so it looks better on github --- GildedRoseRequirements.txt | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/GildedRoseRequirements.txt b/GildedRoseRequirements.txt index a8f47b48..a139b9f0 100644 --- a/GildedRoseRequirements.txt +++ b/GildedRoseRequirements.txt @@ -2,7 +2,12 @@ Gilded Rose Requirements Specification ====================================== -Hi and welcome to team Gilded Rose. As you know, we are a small inn with a prime location in a prominent city ran by a friendly innkeeper named Allison. We also buy and sell only the finest goods. Unfortunately, our goods are constantly degrading in quality as they approach their sell by date. We have a system in place that updates our inventory for us. It was developed by a no-nonsense type named Leeroy, who has moved on to new adventures. Your task is to add the new feature to our system so that we can begin selling a new category of items. First an introduction to our system: +Hi and welcome to team Gilded Rose. As you know, we are a small inn with a prime location in a +prominent city ran by a friendly innkeeper named Allison. We also buy and sell only the finest goods. +Unfortunately, our goods are constantly degrading in quality as they approach their sell by date. We +have a system in place that updates our inventory for us. It was developed by a no-nonsense type named +Leeroy, who has moved on to new adventures. Your task is to add the new feature to our system so that +we can begin selling a new category of items. First an introduction to our system: - All items have a SellIn value which denotes the number of days we have to sell the item - All items have a Quality value which denotes how valuable the item is @@ -21,6 +26,11 @@ We have recently signed a supplier of conjured items. This requires an update to - "Conjured" items degrade in Quality twice as fast as normal items -Feel free to make any changes to the UpdateQuality method and add any new code as long as everything still works correctly. However, do not alter the Item class or Items property as those belong to the goblin in the corner who will insta-rage and one-shot you as he doesn't believe in shared code ownership (you can make the UpdateQuality method and Items property static if you like, we'll cover for you). +Feel free to make any changes to the UpdateQuality method and add any new code as long as everything +still works correctly. However, do not alter the Item class or Items property as those belong to the +goblin in the corner who will insta-rage and one-shot you as he doesn't believe in shared code +ownership (you can make the UpdateQuality method and Items property static if you like, we'll cover +for you). -Just for clarification, an item can never have its Quality increase above 50, however "Sulfuras" is a legendary item and as such its Quality is 80 and it never alters. \ No newline at end of file +Just for clarification, an item can never have its Quality increase above 50, however "Sulfuras" is a +legendary item and as such its Quality is 80 and it never alters. \ No newline at end of file From 89e739e374de22860f0ec538ef257048cf1727be Mon Sep 17 00:00:00 2001 From: emilybache Date: Thu, 25 Sep 2014 21:20:32 +0200 Subject: [PATCH 131/634] added more line breaks so its easier to read on github --- GildedRoseRequirements.txt | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/GildedRoseRequirements.txt b/GildedRoseRequirements.txt index a139b9f0..e2bfd98a 100644 --- a/GildedRoseRequirements.txt +++ b/GildedRoseRequirements.txt @@ -20,7 +20,9 @@ Pretty simple, right? Well this is where it gets interesting: - "Aged Brie" actually increases in Quality the older it gets - The Quality of an item is never more than 50 - "Sulfuras", being a legendary item, never has to be sold or decreases in Quality - - "Backstage passes", like aged brie, increases in Quality as it's SellIn value approaches; Quality increases by 2 when there are 10 days or less and by 3 when there are 5 days or less but Quality drops to 0 after the concert + - "Backstage passes", like aged brie, increases in Quality as it's SellIn value approaches; + Quality increases by 2 when there are 10 days or less and by 3 when there are 5 days or less but + Quality drops to 0 after the concert We have recently signed a supplier of conjured items. This requires an update to our system: @@ -30,7 +32,7 @@ Feel free to make any changes to the UpdateQuality method and add any new code a still works correctly. However, do not alter the Item class or Items property as those belong to the goblin in the corner who will insta-rage and one-shot you as he doesn't believe in shared code ownership (you can make the UpdateQuality method and Items property static if you like, we'll cover -for you). +for you). Just for clarification, an item can never have its Quality increase above 50, however "Sulfuras" is a legendary item and as such its Quality is 80 and it never alters. \ No newline at end of file From f492b562df677d1a4317015232f69eacb26a6248 Mon Sep 17 00:00:00 2001 From: Peter Kofler Date: Fri, 28 Nov 2014 20:40:52 +0100 Subject: [PATCH 132/634] update IDEA settings to IDEA 13 --- .idea/copyright/profiles_settings.xml | 4 +--- Java/Java.iml | 11 +++++++++++ 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/.idea/copyright/profiles_settings.xml b/.idea/copyright/profiles_settings.xml index 3572571a..e7bedf33 100644 --- a/.idea/copyright/profiles_settings.xml +++ b/.idea/copyright/profiles_settings.xml @@ -1,5 +1,3 @@ - - - + \ No newline at end of file diff --git a/Java/Java.iml b/Java/Java.iml index 3dfffce3..9d782ec3 100644 --- a/Java/Java.iml +++ b/Java/Java.iml @@ -17,6 +17,17 @@ + + + + + + + + + + + From 14c06edeb6eb45a19369c7d5fbb886809f8bbd96 Mon Sep 17 00:00:00 2001 From: Peter Kofler Date: Fri, 5 Dec 2014 20:09:02 +0100 Subject: [PATCH 133/634] port GildedRose Java/Ruby to R language, add a RUnit test stub --- R/gilded_rose.R | 56 +++++++++++++++++++++++++++++++++++++++++++ R/item.R | 13 ++++++++++ R/runit_gilded_rose.R | 7 ++++++ R/test_setup.R | 7 ++++++ R/texttest_fixture.R | 33 +++++++++++++++++++++++++ 5 files changed, 116 insertions(+) create mode 100644 R/gilded_rose.R create mode 100644 R/item.R create mode 100644 R/runit_gilded_rose.R create mode 100644 R/test_setup.R create mode 100644 R/texttest_fixture.R diff --git a/R/gilded_rose.R b/R/gilded_rose.R new file mode 100644 index 00000000..3d639dda --- /dev/null +++ b/R/gilded_rose.R @@ -0,0 +1,56 @@ +source('item.R') + +update_quality <- function(items) { + lapply(items, + function(item) { + + if (item$name != "Aged Brie" && item$name != "Backstage passes to a TAFKAL80ETC concert") { + if (item$quality > 0) { + if (item$name != "Sulfuras, Hand of Ragnaros") { + item$quality <- item$quality - 1 + } + } + } else { + if (item$quality < 50) { + item$quality <- item$quality + 1 + if (item$name == "Backstage passes to a TAFKAL80ETC concert") { + if (item$sell_in < 11) { + if (item$quality < 50) { + item$quality = item$quality + 1 + } + } + if (item$sell_in < 6) { + if (item$quality < 50) { + item$quality = item$quality + 1 + } + } + } + } + } + + if (item$name != "Sulfuras, Hand of Ragnaros") { + item$sell_in <- item$sell_in - 1 + } + + if (item$sell_in < 0) { + if (item$name != "Aged Brie") { + if (item$name != "Backstage passes to a TAFKAL80ETC concert") { + if (item$quality > 0) { + if (item$name != "Sulfuras, Hand of Ragnaros") { + item$quality <- item$quality - 1 + } + } + } else { + item$quality <- item$quality - item$quality + } + } else { + if (item$quality < 50) { + item$quality <- item$quality + 1 + } + } + } + + item + } + ) +} diff --git a/R/item.R b/R/item.R new file mode 100644 index 00000000..51cc90dc --- /dev/null +++ b/R/item.R @@ -0,0 +1,13 @@ +item <- function(name, sell_in, quality) { + newItem <- list(name=name, sell_in=sell_in, quality=quality) + class(newItem) <- 'item' + newItem +} + +as.character.item <- function(item) { + paste(item$name, ", ", item$sell_in, ", ", item$quality, sep='') +} + +print.item <- function(item) { + print.default(as.character(item)) +} diff --git a/R/runit_gilded_rose.R b/R/runit_gilded_rose.R new file mode 100644 index 00000000..a0004b7c --- /dev/null +++ b/R/runit_gilded_rose.R @@ -0,0 +1,7 @@ +source('gilded_rose.R') + +test.foo <- function() { + items <- list( item('foo', 0, 0) ) + items <- update_quality(items) + checkEquals('fixme', items[[1]]$name); +} diff --git a/R/test_setup.R b/R/test_setup.R new file mode 100644 index 00000000..fc62610e --- /dev/null +++ b/R/test_setup.R @@ -0,0 +1,7 @@ +# A little helper script to get the testing infrastructure started + +# install.packages("RUnit") +require(RUnit) + +# execute single test file +runTestFile("runit_gilded_rose.R") diff --git a/R/texttest_fixture.R b/R/texttest_fixture.R new file mode 100644 index 00000000..ec635e6e --- /dev/null +++ b/R/texttest_fixture.R @@ -0,0 +1,33 @@ +rm(list=ls()) + +source('gilded_rose.R') + +writeLines('OMGHAI!') + +items <- list( + item('+5 Dexterity Vest', 10, 20), + item('Aged Brie', 2, 0), + item('Elixir of the Mongoose', 5, 7), + item('Sulfuras, Hand of Ragnaros', 0, 80), + item('Sulfuras, Hand of Ragnaros', -1, 80), + item('Backstage passes to a TAFKAL80ETC concert', 15, 20), + item('Backstage passes to a TAFKAL80ETC concert', 10, 49), + item('Backstage passes to a TAFKAL80ETC concert', 5, 49), + # This Conjured item does not work properly yet + item('Conjured Mana Cake', 3, 6) +) + +days <- 2 +for (day in 0:days) { + writeLines(paste('-------- day ', day, ' --------', sep='')) + writeLines('name, sellIn, quality') + lapply(items, + function(item) { + writeLines(as.character(item)) + } + ) + writeLines('') + items <- update_quality(items) +} + +rm('day', 'days', 'items') From 211ecae6892ec7b5f6c6e1bec8bc5e6b1ddb9a02 Mon Sep 17 00:00:00 2001 From: Peter Kofler Date: Fri, 5 Dec 2014 20:09:51 +0100 Subject: [PATCH 134/634] Eclipse/StatET R environment configuration (can be imported as existing project into StatET now) --- R/.project | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 R/.project diff --git a/R/.project b/R/.project new file mode 100644 index 00000000..62d08220 --- /dev/null +++ b/R/.project @@ -0,0 +1,18 @@ + + + GildedRose.R + + + + + + de.walware.statet.r.builders.RSupport + + + + + + de.walware.statet.base.StatetNature + de.walware.statet.r.RNature + + From df705663ac8305bb9657cbd83a771077e088b527 Mon Sep 17 00:00:00 2001 From: Bryan Thrall Date: Thu, 15 Jan 2015 08:53:33 -0600 Subject: [PATCH 135/634] Initial CMake support. --- cpp/CMakeLists.txt | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 cpp/CMakeLists.txt diff --git a/cpp/CMakeLists.txt b/cpp/CMakeLists.txt new file mode 100644 index 00000000..e704f0c5 --- /dev/null +++ b/cpp/CMakeLists.txt @@ -0,0 +1,30 @@ +cmake_minimum_required(VERSION 2.8.4) +project(cpp) + +# CMake FindThreads is broken until 3.1 +#find_package(Threads REQUIRED) +set(CMAKE_THREAD_LIBS_INIT pthread) + +enable_testing() +find_package(GTest REQUIRED) +include_directories(${GTEST_INCLUDE_DIRS}) + +set(GILDED_ROSE_SOURCE_FILES + GildedRose.cc + GildedRose.h + GildedRoseUnitTests.cc) + +set(GILDED_ROSE_TEXT_TESTS_SOURCE_FILES + GildedRose.cc + GildedRose.h + GildedRoseTextTests.cc) + +set(SOURCE_FILES + ${GILDED_ROSE_SOURCE_FILES} + ${GILDED_ROSE_TEXT_TESTS_SOURCE_FILES}) + +add_executable(GildedRose ${GILDED_ROSE_SOURCE_FILES}) +target_link_libraries(GildedRose ${GTEST_BOTH_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT}) + +add_executable(GildedRoseTextTests ${GILDED_ROSE_TEXT_TESTS_SOURCE_FILES}) +target_link_libraries(GildedRoseTextTests ${GTEST_BOTH_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT}) From 391e5c2e98b3aecc9a7ce6ad6f3ef799e88fd15f Mon Sep 17 00:00:00 2001 From: Sven Heyll Date: Tue, 24 Feb 2015 05:11:15 +0100 Subject: [PATCH 136/634] Add Haskell port --- haskell/.gitignore | 11 ++++++ haskell/README.md | 15 ++++++++ haskell/gilded-rose.cabal | 34 +++++++++++++++++ haskell/install_deps.sh | 8 ++++ haskell/run.sh | 8 ++++ haskell/src/GildedRose.hs | 70 ++++++++++++++++++++++++++++++++++ haskell/src/Main.hs | 44 +++++++++++++++++++++ haskell/test.sh | 9 +++++ haskell/test/GildedRoseSpec.hs | 14 +++++++ haskell/test/Spec.hs | 1 + 10 files changed, 214 insertions(+) create mode 100644 haskell/.gitignore create mode 100644 haskell/README.md create mode 100644 haskell/gilded-rose.cabal create mode 100755 haskell/install_deps.sh create mode 100755 haskell/run.sh create mode 100644 haskell/src/GildedRose.hs create mode 100644 haskell/src/Main.hs create mode 100755 haskell/test.sh create mode 100644 haskell/test/GildedRoseSpec.hs create mode 100644 haskell/test/Spec.hs diff --git a/haskell/.gitignore b/haskell/.gitignore new file mode 100644 index 00000000..1be183c3 --- /dev/null +++ b/haskell/.gitignore @@ -0,0 +1,11 @@ +*.hi +*.ho +TAGS +*.log +*.profile +/dist +/cabal.config + +/.cabal-sandbox/ +/cabal.sandbox.config + diff --git a/haskell/README.md b/haskell/README.md new file mode 100644 index 00000000..acc21af9 --- /dev/null +++ b/haskell/README.md @@ -0,0 +1,15 @@ +# Haskell port of the Gilded-Rose Kata + +This is a Haskell port of the *Gilded-Rose-Kata*. For updates and pull-request +on this haskell port go to https://github.com/sheyll/gilded-rose-haskell + +## Building and Running + +Run `./install_deps.sh` initially, then `./test.sh` to execute the tests after +each refactoring. + +To execute the program run `./run.sh [days]` where `[days]` denotes an optional +parameter for the number of days to simulate. + +Tests are in `test/GildedRoseSpec.hs`. Refer to http://hspec.github.io/ for +more information about writing tests using `Hspec`. diff --git a/haskell/gilded-rose.cabal b/haskell/gilded-rose.cabal new file mode 100644 index 00000000..a1071826 --- /dev/null +++ b/haskell/gilded-rose.cabal @@ -0,0 +1,34 @@ +name: gilded-rose +version: 0.1.0.0 +synopsis: Haskell-port of the gilded rose kata +license: GPL +author: Sven Heyll +maintainer: sven.heyll@gmail.com +category: System +build-type: Simple +cabal-version: >=1.10 + +library + exposed-modules: GildedRose + build-depends: base >=4.7 && <4.8 + hs-source-dirs: src + default-language: Haskell2010 + +executable gilded-rose + main-is: Main.hs + build-depends: gilded-rose, base >=4.7 && <4.8 + hs-source-dirs: src + default-language: Haskell2010 + +test-suite spec + type: exitcode-stdio-1.0 + ghc-options: -Wall + hs-source-dirs: test + default-language: Haskell2010 + main-is: Spec.hs + other-modules: GildedRoseSpec + build-depends: base >=4.7 && <4.8 + , gilded-rose + , hspec + , hspec-expectations + , QuickCheck diff --git a/haskell/install_deps.sh b/haskell/install_deps.sh new file mode 100755 index 00000000..68eabbbd --- /dev/null +++ b/haskell/install_deps.sh @@ -0,0 +1,8 @@ +#!/bin/bash +# +# Fetch and build all dependencies +# +set -eu + +cabal install --enable-tests --disable-optimization --dependencies-only +cabal -v0 configure --enable-tests --disable-optimization diff --git a/haskell/run.sh b/haskell/run.sh new file mode 100755 index 00000000..0a3c2158 --- /dev/null +++ b/haskell/run.sh @@ -0,0 +1,8 @@ +#!/bin/bash +# +# Rebuild the project and run Main.main with all arguments passed to this +# script. +# +set -eu + +cabal -v0 run $@ diff --git a/haskell/src/GildedRose.hs b/haskell/src/GildedRose.hs new file mode 100644 index 00000000..8e710c8e --- /dev/null +++ b/haskell/src/GildedRose.hs @@ -0,0 +1,70 @@ +module GildedRose where + +type GildedRose = [Item] + +data Item = Item String Int Int + deriving (Eq) + +instance Show Item where + show (Item name sellIn quality) = + name ++ ", " ++ show sellIn ++ ", " ++ show quality + +updateQuality :: GildedRose -> GildedRose +updateQuality = map updateQualityItem + where + updateQualityItem (Item name sellIn quality) = + let + quality' = + if name /= "Aged Brie" + && name /= "Backstage passes to a TAFKAL80ETC concert" + then + if quality > 0 + then + if name /= "Sulfuras, Hand of Ragnaros" + then quality - 1 + else quality + else quality + else + if quality < 50 + then + quality + 1 + + (if name == "Backstage passes to a TAFKAL80ETC concert" + then + if sellIn < 11 + then + if quality < 49 + then + 1 + (if sellIn < 6 + then + if quality < 48 + then 1 + else 0 + else 0) + else 0 + else 0 + else 0) + else quality + + sellIn' = + if name /= "Sulfuras, Hand of Ragnaros" + then sellIn - 1 + else sellIn + in + if sellIn' < 0 + then + if name /= "Aged Brie" + then + if name /= "Backstage passes to a TAFKAL80ETC concert" + then + if quality' > 0 + then + if name /= "Sulfuras, Hand of Ragnaros" + then (Item name sellIn' (quality' - 1)) + else (Item name sellIn' quality') + else (Item name sellIn' quality') + else (Item name sellIn' (quality' - quality')) + else + if quality' < 50 + then (Item name sellIn' (quality' + 1)) + else (Item name sellIn' quality') + else (Item name sellIn' quality') diff --git a/haskell/src/Main.hs b/haskell/src/Main.hs new file mode 100644 index 00000000..a5fad66c --- /dev/null +++ b/haskell/src/Main.hs @@ -0,0 +1,44 @@ +module Main where + +import System.Environment +import GildedRose + + +main :: IO () +main = do + putStrLn "OMGHAI!" + + let inventoriesWithDay = inventories `zip` [0..] + inventories = iterate updateQuality initialInventory + + numberOfDays <- daysFromArg + mapM_ printUpdate (take numberOfDays inventoriesWithDay) + + where + printUpdate :: (GildedRose, Int) -> IO () + printUpdate (items, day) = do + putStrLn ("-------- day " ++ show day ++ " --------") + putStrLn "name, sellIn, quality" + mapM_ (putStrLn . show) items + putStrLn "" + + daysFromArg :: IO Int + daysFromArg = do + args <- getArgs + return $ if length args > 0 + then read (head args) + else 20 + + initialInventory :: GildedRose + initialInventory = + [ Item "+5 Dexterity Vest" 10 20 + , Item "Aged Brie" 2 0 + , Item "Elixir of the Mongoose" 5 7 + , Item "Sulfuras, Hand of Ragnaros" 0 80 + , Item "Sulfuras, Hand of Ragnaros" (-1) 80 + , Item "Backstage passes to a TAFKAL80ETC concert" 15 20 + , Item "Backstage passes to a TAFKAL80ETC concert" 10 49 + , Item "Backstage passes to a TAFKAL80ETC concert" 5 49 + -- this conjured item does not work properly yet + , Item "Conjured Mana Cake" 3 6 + ] diff --git a/haskell/test.sh b/haskell/test.sh new file mode 100755 index 00000000..c88240cb --- /dev/null +++ b/haskell/test.sh @@ -0,0 +1,9 @@ +#!/bin/bash +# +# Rebuild the project and run the hspec based unit tests. This could have been +# achieved by 'cabal test' but then the output would not be as colorful. +# +set -eu + +cabal -v0 build +./dist/build/spec/spec $@ diff --git a/haskell/test/GildedRoseSpec.hs b/haskell/test/GildedRoseSpec.hs new file mode 100644 index 00000000..cdcaaddd --- /dev/null +++ b/haskell/test/GildedRoseSpec.hs @@ -0,0 +1,14 @@ +module GildedRoseSpec (spec) where + +import Test.Hspec +import GildedRose + +spec :: Spec +spec = + describe "updateQuality" $ do + + it "fixme" $ + let inventory = [Item "foo" 0 0] + actual = updateQuality inventory + expected = [] + in actual `shouldBe` expected diff --git a/haskell/test/Spec.hs b/haskell/test/Spec.hs new file mode 100644 index 00000000..a824f8c3 --- /dev/null +++ b/haskell/test/Spec.hs @@ -0,0 +1 @@ +{-# OPTIONS_GHC -F -pgmF hspec-discover #-} From 2f5f0edd548dfb1f3f420416020f335807e7c30e Mon Sep 17 00:00:00 2001 From: Andy Boughton Date: Sat, 14 Mar 2015 23:04:45 -0400 Subject: [PATCH 137/634] Update cyberdojo links to .org --- README.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index e823a9a5..aa060d73 100644 --- a/README.md +++ b/README.md @@ -32,9 +32,9 @@ The Text-Based tests in this repository are designed to be used with the tool "T I've also set this kata up on [cyber-dojo](http://cyber-dojo.com) for several languages, so you can get going really quickly: -- [JUnit, Java](http://cyber-dojo.com/forker/fork/751DD02C4C?avatar=snake&tag=4) -- [C#](http://cyber-dojo.com/forker/fork/107907AD1E?avatar=alligator&tag=13) -- [Ruby](http://cyber-dojo.com/forker/fork/A8943EAF92?avatar=hippo&tag=9) -- [RSpec, Ruby](http://cyber-dojo.com/forker/fork/8E58B0AD16?avatar=raccoon&tag=3) -- [Python](http://cyber-dojo.com/forker/fork/297041AA7A?avatar=lion&tag=4) -- [Cucumber, Java](http://cyber-dojo.com/forker/fork/0F82D4BA89?avatar=gorilla&tag=45) - for this one I've also written some step definitions for you +- [JUnit, Java](http://cyber-dojo.org/forker/fork/751DD02C4C?avatar=snake&tag=4) +- [C#](http://cyber-dojo.org/forker/fork/107907AD1E?avatar=alligator&tag=13) +- [Ruby](http://cyber-dojo.org/forker/fork/A8943EAF92?avatar=hippo&tag=9) +- [RSpec, Ruby](http://cyber-dojo.org/forker/fork/8E58B0AD16?avatar=raccoon&tag=3) +- [Python](http://cyber-dojo.org/forker/fork/297041AA7A?avatar=lion&tag=4) +- [Cucumber, Java](http://cyber-dojo.org/forker/fork/0F82D4BA89?avatar=gorilla&tag=45) - for this one I've also written some step definitions for you From 2d9d66485414236e638f43100475c5bb05e483e6 Mon Sep 17 00:00:00 2001 From: emilybache Date: Mon, 16 Mar 2015 20:42:50 +0100 Subject: [PATCH 138/634] fixed the link for the C# version in cyber-dojo --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index aa060d73..64c13365 100644 --- a/README.md +++ b/README.md @@ -33,7 +33,7 @@ The Text-Based tests in this repository are designed to be used with the tool "T I've also set this kata up on [cyber-dojo](http://cyber-dojo.com) for several languages, so you can get going really quickly: - [JUnit, Java](http://cyber-dojo.org/forker/fork/751DD02C4C?avatar=snake&tag=4) -- [C#](http://cyber-dojo.org/forker/fork/107907AD1E?avatar=alligator&tag=13) +- [C#](http://cyber-dojo.org/forker/fork/5C5AC766B0?avatar=koala&tag=1) - [Ruby](http://cyber-dojo.org/forker/fork/A8943EAF92?avatar=hippo&tag=9) - [RSpec, Ruby](http://cyber-dojo.org/forker/fork/8E58B0AD16?avatar=raccoon&tag=3) - [Python](http://cyber-dojo.org/forker/fork/297041AA7A?avatar=lion&tag=4) From 1a86feef30fbce80808960586ecea3101698d5f3 Mon Sep 17 00:00:00 2001 From: Radek Simko Date: Sat, 27 Jun 2015 07:34:14 +0100 Subject: [PATCH 139/634] Ignore *.pyc files --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 1cc4572e..cbda76fc 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ .idea/workspace.xml +*.pyc From 4a7ffc291e85c72e372100e00d03b23fce229111 Mon Sep 17 00:00:00 2001 From: Radek Simko Date: Sat, 27 Jun 2015 08:08:50 +0100 Subject: [PATCH 140/634] Remove extra whitespaces --- python/gilded_rose.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/gilded_rose.py b/python/gilded_rose.py index 69459ac3..4f21ea64 100755 --- a/python/gilded_rose.py +++ b/python/gilded_rose.py @@ -35,7 +35,7 @@ class GildedRose(object): if item.quality < 50: item.quality = item.quality + 1 - + class Item: def __init__(self, name, sell_in, quality): self.name = name From db89751cac2c4bf9f567e78e84de2ae4ac24ffca Mon Sep 17 00:00:00 2001 From: emilybache Date: Tue, 7 Jul 2015 19:46:17 +0200 Subject: [PATCH 141/634] added MIT license --- license.txt | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 license.txt diff --git a/license.txt b/license.txt new file mode 100644 index 00000000..1eebd817 --- /dev/null +++ b/license.txt @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2015 @emilybache + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. \ No newline at end of file From fef23beb31d3fa7c380fb29e27ddd94f600cd867 Mon Sep 17 00:00:00 2001 From: Makis Otman Date: Fri, 18 Sep 2015 16:52:18 +0100 Subject: [PATCH 142/634] Add Elixir version --- elixir/config/config.exs | 1 + elixir/lib/gilded_rose.ex | 48 ++++++++++++++++++++++++++++++++ elixir/lib/item.ex | 3 ++ elixir/mix.exs | 9 ++++++ elixir/test/gilded_rose_test.exs | 6 ++++ elixir/test/test_helper.exs | 1 + 6 files changed, 68 insertions(+) create mode 100644 elixir/config/config.exs create mode 100644 elixir/lib/gilded_rose.ex create mode 100644 elixir/lib/item.ex create mode 100644 elixir/mix.exs create mode 100644 elixir/test/gilded_rose_test.exs create mode 100644 elixir/test/test_helper.exs diff --git a/elixir/config/config.exs b/elixir/config/config.exs new file mode 100644 index 00000000..d2d855e6 --- /dev/null +++ b/elixir/config/config.exs @@ -0,0 +1 @@ +use Mix.Config diff --git a/elixir/lib/gilded_rose.ex b/elixir/lib/gilded_rose.ex new file mode 100644 index 00000000..20a3796c --- /dev/null +++ b/elixir/lib/gilded_rose.ex @@ -0,0 +1,48 @@ +defmodule GildedRose do + # Example + # update_quality([%Item{name: "Backstage passes to a TAFKAL80ETC concert", sell_in: 9, quality: 1}]) + # => [%Item{name: "Backstage passes to a TAFKAL80ETC concert", sell_in: 9, quality: 3}] + + def update_quality(items) do + Enum.map(items, &update_item/1) + end + + def update_item(item) do + cond do + item.quality == 0 -> + item + item.sell_in < 0 && item.name == "Backstage passes to a TAFKAL80ETC concert" -> + %{item | quality: 0} + item.name == "Aged Brie" || item.name == "Backstage passes to a TAFKAL80ETC concert" -> + if item.name == "Backstage passes to a TAFKAL80ETC concert" && item.sell_in > 5 && item.sell_in <= 10 do + %{item | quality: item.quality + 2} + else + if item.name == "Backstage passes to a TAFKAL80ETC concert" && item.sell_in >= 0 && item.sell_in <= 5 do + %{item | quality: item.quality + 3} + else + if item.quality < 50 do + %{item | quality: item.quality + 1} + else + item + end + end + end + item.sell_in < 0 -> + if item.name == "Backstage passes to a TAFKAL80ETC concert" do + %{item | quality: 0} + else + if item.name == "+5 Dexterity Vest" || item.name == "Elixir of the Mongoose" do + %{item | quality: item.quality - 2} + else + item + end + end + item.name == "+5 Dexterity Vest" || item.name == "Elixir of the Mongoose" -> + %{item | quality: item.quality - 1} + item.name != "Sulfuras, Hand of Ragnaros" -> + %{item | quality: item.quality - 1} + true -> + item + end + end +end diff --git a/elixir/lib/item.ex b/elixir/lib/item.ex new file mode 100644 index 00000000..0a20edbf --- /dev/null +++ b/elixir/lib/item.ex @@ -0,0 +1,3 @@ +defmodule Item do + defstruct name: nil, sell_in: nil, quality: nil +end diff --git a/elixir/mix.exs b/elixir/mix.exs new file mode 100644 index 00000000..c50af0d0 --- /dev/null +++ b/elixir/mix.exs @@ -0,0 +1,9 @@ +defmodule GildedRose.Mixfile do + use Mix.Project + + def project do + [app: :gilded_rose, + version: "0.0.1", + elixir: "~> 1.0"] + end +end diff --git a/elixir/test/gilded_rose_test.exs b/elixir/test/gilded_rose_test.exs new file mode 100644 index 00000000..b0db3381 --- /dev/null +++ b/elixir/test/gilded_rose_test.exs @@ -0,0 +1,6 @@ +defmodule GildedRoseTest do + use ExUnit.Case + + test "begin the journey of refactoring" do + end +end diff --git a/elixir/test/test_helper.exs b/elixir/test/test_helper.exs new file mode 100644 index 00000000..869559e7 --- /dev/null +++ b/elixir/test/test_helper.exs @@ -0,0 +1 @@ +ExUnit.start() From 52d3d5607abe62204cd9a057a9f8158dccd1de01 Mon Sep 17 00:00:00 2001 From: Michael Gerhaeuser Date: Sat, 3 Oct 2015 21:11:56 +0200 Subject: [PATCH 143/634] Add rust version --- rust/.gitignore | 1 + rust/Cargo.lock | 4 ++ rust/Cargo.toml | 4 ++ rust/src/gildedrose/mod.rs | 80 +++++++++++++++++++++++++++++++++++++ rust/src/gildedrose/test.rs | 10 +++++ rust/src/main.rs | 31 ++++++++++++++ 6 files changed, 130 insertions(+) create mode 100644 rust/.gitignore create mode 100644 rust/Cargo.lock create mode 100644 rust/Cargo.toml create mode 100644 rust/src/gildedrose/mod.rs create mode 100644 rust/src/gildedrose/test.rs create mode 100644 rust/src/main.rs diff --git a/rust/.gitignore b/rust/.gitignore new file mode 100644 index 00000000..2f7896d1 --- /dev/null +++ b/rust/.gitignore @@ -0,0 +1 @@ +target/ diff --git a/rust/Cargo.lock b/rust/Cargo.lock new file mode 100644 index 00000000..524f449a --- /dev/null +++ b/rust/Cargo.lock @@ -0,0 +1,4 @@ +[root] +name = "rust" +version = "0.1.0" + diff --git a/rust/Cargo.toml b/rust/Cargo.toml new file mode 100644 index 00000000..c0fef86b --- /dev/null +++ b/rust/Cargo.toml @@ -0,0 +1,4 @@ +[package] +name = "rust" +version = "0.1.0" +authors = ["Michael Gerhaeuser "] diff --git a/rust/src/gildedrose/mod.rs b/rust/src/gildedrose/mod.rs new file mode 100644 index 00000000..f055f99d --- /dev/null +++ b/rust/src/gildedrose/mod.rs @@ -0,0 +1,80 @@ +use std::string; +use std::vec; + +pub struct Item { + pub name: string::String, + pub sell_in: i32, + pub quality: i32 +} + +impl Item { + pub fn new(name: String, sell_in: i32, quality: i32) -> Item { + Item {name: name, sell_in: sell_in, quality: quality} + } +} + +pub struct GildedRose { + pub items: vec::Vec +} + +impl GildedRose { + pub fn new(items: vec::Vec) -> GildedRose { + GildedRose {items: items} + } + + pub fn update_quality(&mut self) { + for item in &mut self.items { + if item.name != "Aged Brie" && item.name != "Backstage passes to a TAFKAL80ETC concert" { + if item.quality > 0 { + if item.name != "Sulfuras, Hand of Ragnaros" { + item.quality = item.quality - 1; + } + } + } else { + if item.quality < 50 + { + item.quality = item.quality + 1; + + if item.name == "Backstage passes to a TAFKAL80ETC concert" { + if item.sell_in < 11 { + if item.quality < 50 { + item.quality = item.quality + 1; + } + } + + if item.sell_in < 6 { + if item.quality < 50 { + item.quality = item.quality + 1; + } + } + } + } + } + + if item.name != "Sulfuras, Hand of Ragnaros" { + item.sell_in = item.sell_in - 1; + } + + if item.sell_in < 0 { + if item.name != "Aged Brie" { + if item.name != "Backstage passes to a TAFKAL80ETC concert" { + if item.quality > 0 { + if item.name != "Sulfuras, Hand of Ragnaros" { + item.quality = item.quality - 1; + } + } + } else { + item.quality = item.quality - item.quality; + } + } else { + if item.quality < 50 { + item.quality = item.quality + 1; + } + } + } + } + } +} + +#[cfg(test)] +mod test; diff --git a/rust/src/gildedrose/test.rs b/rust/src/gildedrose/test.rs new file mode 100644 index 00000000..afc11c88 --- /dev/null +++ b/rust/src/gildedrose/test.rs @@ -0,0 +1,10 @@ +use super::{Item, GildedRose}; + +#[test] +pub fn foo() { + let items = vec![Item::new(String::from("foo"), 0, 0)]; + let mut rose = GildedRose::new(items); + rose.update_quality(); + + assert_eq!("fixme", rose.items[0].name); +} diff --git a/rust/src/main.rs b/rust/src/main.rs new file mode 100644 index 00000000..b56d07e6 --- /dev/null +++ b/rust/src/main.rs @@ -0,0 +1,31 @@ + +mod gildedrose; + +use gildedrose::{Item, GildedRose}; + +fn main() { + let items = vec![ + Item::new(String::from("+5 Dexterity Vest"), 10, 20), + Item::new(String::from("Aged Brie"), 2, 0), + Item::new(String::from("Elixir of the Mongoose"), 5, 7), + Item::new(String::from("Sulfuras, Hand of Ragnaros"), 0, 80), + Item::new(String::from("Sulfuras, Hand of Ragnaros"), -1, 80), + Item::new(String::from("Backstage passes to a TAFKAL80ETC concert"), 15, 20), + Item::new(String::from("Backstage passes to a TAFKAL80ETC concert"), 10, 49), + Item::new(String::from("Backstage passes to a TAFKAL80ETC concert"), 5, 49), + // this conjured item does not work properly yet + Item::new(String::from("Conjured Mana Cake"), 3, 6) + ]; + let mut rose = GildedRose::new(items); + + println!("OMGHAI!"); + for i in (0..30) { + println!("-------- day {} --------", i); + println!("name, sellIn, quality"); + for item in &rose.items { + println!("{}, {}, {}", item.name, item.sell_in, item.quality); + } + println!(""); + rose.update_quality(); + } +} From 011252b25ecf2c2c13c2f57e9d3321c438ad865f Mon Sep 17 00:00:00 2001 From: Michael Gerhaeuser Date: Sun, 4 Oct 2015 18:58:30 +0200 Subject: [PATCH 144/634] Fix link to cyber dojo website --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 64c13365..423c33da 100644 --- a/README.md +++ b/README.md @@ -30,7 +30,7 @@ The Text-Based tests in this repository are designed to be used with the tool "T ## Get going quickly using Cyber-Dojo -I've also set this kata up on [cyber-dojo](http://cyber-dojo.com) for several languages, so you can get going really quickly: +I've also set this kata up on [cyber-dojo](http://cyber-dojo.org) for several languages, so you can get going really quickly: - [JUnit, Java](http://cyber-dojo.org/forker/fork/751DD02C4C?avatar=snake&tag=4) - [C#](http://cyber-dojo.org/forker/fork/5C5AC766B0?avatar=koala&tag=1) From 5bf4ec635ea093fcedc812765f3495a173647107 Mon Sep 17 00:00:00 2001 From: Sylvain GOURNAY Date: Thu, 15 Oct 2015 16:35:01 +0200 Subject: [PATCH 145/634] Requirements translation in French --- GildedRoseRequirements_fr.txt | 41 +++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 GildedRoseRequirements_fr.txt diff --git a/GildedRoseRequirements_fr.txt b/GildedRoseRequirements_fr.txt new file mode 100644 index 00000000..13dd3e9b --- /dev/null +++ b/GildedRoseRequirements_fr.txt @@ -0,0 +1,41 @@ +============================================ +Spécification de la Rose dorée (Gilded Rose) +============================================ + +Bonjour et bienvenue dans l'équipe de la Rose dorée. Comme vous le savez déjà, notre petite taverne +située à proximité d'une cité importante est dirigée par l'amicale aubergiste Allison. Nous ne vendons +bien sûr que les produits de la meilleurs qualité. Malheureusement, la qualité de nos marchandises se +dégrade constamment à l'approche de leur date de péremption. Un système a été mis en place pour mettre +à jour notre inventaire. Il a été développé par Leeroy, une personne pleine de bon sens qui est reparti +pour de nouvelles aventures. Votre mission est d'ajouter une nouvelle fonctionnalité à notre système +pour que nous puissions commencer à vendre un nouveau type de produit. Mais d'abord, laissez-moi vous +présenter notre système : + + - Tous les produits ont une valeur qui compte le nombre de jours restant pour le vendre : la SellIn + - Tous les produits ont une valeur qui spécifie sa qualité : la Quality + - A la fin de chaque jour, le système diminue ces deux valeurs pour chaque produit + +Plutôt simple, non ? Attendez, ça devient intéressant : + + - Une fois la SellIn dépassée, la Quality diminue deux fois plus vite + - La Quality d'un produit ne peut jamais être négative + - "Aged Brie" (du vieux brie) s'améliore avec l'âge : sa Quality augmente + - La Quality d'un produit n'est jamais supérieure à 50 + - Le "Sulfuras", un objet légendaire, n'a pas de date de péremption et sa Quality ne diminue jamais + - Les "Backstage passes", comme le vieux brie, a sa Quality qui augmente quand sa date de péremption approche + - Sa Quality augmente de 2 quand il reste 10 jours ou moins et de 3 quand il reste 5 jours ou moins + - Sa Quality tombe à 0 après le concert + +Nous avons récemment signé un partenariat avec un fournisseur de produit invoqué ("Conjured"). Notre système a +donc besoin d'une mise à jour : + + - Les produit "Conjured" (invoqués) ont une Quality qui diminue deux fois plus vite que les autres + +Vous pouvez faire les changements que vous voulez à la méthode "updateQuality" et ajouter autant de code que +vous voulez, tant que tout fonctionne correctement. Cependant, nous devons vous prévenir, ne modifiez en aucun +cas la classe Item ou ses propriétés car cela appartient au gobelin de l'étage et il s'enragera et vous tura +sans délai : il ne croit pas dans le partage du code (si vous rendez la méthode "updateQuality" et les propriétés +de Item static, on vous couvrira). + +Just pour clarifier un point, un produit ne peut avoir une Quality supérieure à 50, bien sûr étant donné que le +"Sulfuras" est un objet légendaire, sa Quality est de 80 et n'est jamais altérée. From fd9d429f7dfef07f8766107aadfa3e2bdba075f7 Mon Sep 17 00:00:00 2001 From: Fernandez Ludovic Date: Thu, 15 Oct 2015 21:25:48 +0200 Subject: [PATCH 146/634] refactor: change french specification extention - Markdown --- ...nts_fr.txt => GildedRoseRequirements_fr.md | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) rename GildedRoseRequirements_fr.txt => GildedRoseRequirements_fr.md (63%) diff --git a/GildedRoseRequirements_fr.txt b/GildedRoseRequirements_fr.md similarity index 63% rename from GildedRoseRequirements_fr.txt rename to GildedRoseRequirements_fr.md index 13dd3e9b..8aec2020 100644 --- a/GildedRoseRequirements_fr.txt +++ b/GildedRoseRequirements_fr.md @@ -11,25 +11,25 @@ pour de nouvelles aventures. Votre mission est d'ajouter une nouvelle fonctionna pour que nous puissions commencer à vendre un nouveau type de produit. Mais d'abord, laissez-moi vous présenter notre système : - - Tous les produits ont une valeur qui compte le nombre de jours restant pour le vendre : la SellIn - - Tous les produits ont une valeur qui spécifie sa qualité : la Quality - - A la fin de chaque jour, le système diminue ces deux valeurs pour chaque produit + - Tous les produits ont une valeur qui compte le nombre de jours restant pour le vendre : la SellIn + - Tous les produits ont une valeur qui spécifie sa qualité : la Quality + - A la fin de chaque jour, le système diminue ces deux valeurs pour chaque produit Plutôt simple, non ? Attendez, ça devient intéressant : - - Une fois la SellIn dépassée, la Quality diminue deux fois plus vite - - La Quality d'un produit ne peut jamais être négative - - "Aged Brie" (du vieux brie) s'améliore avec l'âge : sa Quality augmente - - La Quality d'un produit n'est jamais supérieure à 50 - - Le "Sulfuras", un objet légendaire, n'a pas de date de péremption et sa Quality ne diminue jamais - - Les "Backstage passes", comme le vieux brie, a sa Quality qui augmente quand sa date de péremption approche - - Sa Quality augmente de 2 quand il reste 10 jours ou moins et de 3 quand il reste 5 jours ou moins - - Sa Quality tombe à 0 après le concert + - Une fois la SellIn dépassée, la Quality diminue deux fois plus vite + - La Quality d'un produit ne peut jamais être négative + - "Aged Brie" (du vieux brie) s'améliore avec l'âge : sa Quality augmente + - La Quality d'un produit n'est jamais supérieure à 50 + - Le "Sulfuras", un objet légendaire, n'a pas de date de péremption et sa Quality ne diminue jamais + - Les "Backstage passes", comme le vieux brie, a sa Quality qui augmente quand sa date de péremption approche + - Sa Quality augmente de 2 quand il reste 10 jours ou moins et de 3 quand il reste 5 jours ou moins + - Sa Quality tombe à 0 après le concert Nous avons récemment signé un partenariat avec un fournisseur de produit invoqué ("Conjured"). Notre système a donc besoin d'une mise à jour : - - Les produit "Conjured" (invoqués) ont une Quality qui diminue deux fois plus vite que les autres + - Les produit "Conjured" (invoqués) ont une Quality qui diminue deux fois plus vite que les autres Vous pouvez faire les changements que vous voulez à la méthode "updateQuality" et ajouter autant de code que vous voulez, tant que tout fonctionne correctement. Cependant, nous devons vous prévenir, ne modifiez en aucun From bbf8ff798f6e85c320e71a7ce5a468cbf25fc4f8 Mon Sep 17 00:00:00 2001 From: Fernandez Ludovic Date: Thu, 15 Oct 2015 21:26:38 +0200 Subject: [PATCH 147/634] refactor: french specification review --- GildedRoseRequirements_fr.md | 66 ++++++++++++++++++------------------ 1 file changed, 33 insertions(+), 33 deletions(-) diff --git a/GildedRoseRequirements_fr.md b/GildedRoseRequirements_fr.md index 8aec2020..3b5c4403 100644 --- a/GildedRoseRequirements_fr.md +++ b/GildedRoseRequirements_fr.md @@ -1,41 +1,41 @@ -============================================ -Spécification de la Rose dorée (Gilded Rose) -============================================ +# Spécification de la Rose dorée (Gilded Rose) -Bonjour et bienvenue dans l'équipe de la Rose dorée. Comme vous le savez déjà, notre petite taverne -située à proximité d'une cité importante est dirigée par l'amicale aubergiste Allison. Nous ne vendons -bien sûr que les produits de la meilleurs qualité. Malheureusement, la qualité de nos marchandises se -dégrade constamment à l'approche de leur date de péremption. Un système a été mis en place pour mettre -à jour notre inventaire. Il a été développé par Leeroy, une personne pleine de bon sens qui est reparti -pour de nouvelles aventures. Votre mission est d'ajouter une nouvelle fonctionnalité à notre système -pour que nous puissions commencer à vendre un nouveau type de produit. Mais d'abord, laissez-moi vous -présenter notre système : +Bonjour et bienvenue dans l'équipe de la Rose dorée. - - Tous les produits ont une valeur qui compte le nombre de jours restant pour le vendre : la SellIn - - Tous les produits ont une valeur qui spécifie sa qualité : la Quality - - A la fin de chaque jour, le système diminue ces deux valeurs pour chaque produit +Comme vous le savez, notre petite taverne située à proximité d'une cité importante est dirigée par l'amicale aubergiste Allison. -Plutôt simple, non ? Attendez, ça devient intéressant : +Nous achetons et vendons uniquement les meilleurs produits. +Malheureusement, la qualité de nos marchandises se dégrade constamment à l'approche de leur date de péremption. - - Une fois la SellIn dépassée, la Quality diminue deux fois plus vite - - La Quality d'un produit ne peut jamais être négative - - "Aged Brie" (du vieux brie) s'améliore avec l'âge : sa Quality augmente - - La Quality d'un produit n'est jamais supérieure à 50 - - Le "Sulfuras", un objet légendaire, n'a pas de date de péremption et sa Quality ne diminue jamais - - Les "Backstage passes", comme le vieux brie, a sa Quality qui augmente quand sa date de péremption approche - - Sa Quality augmente de 2 quand il reste 10 jours ou moins et de 3 quand il reste 5 jours ou moins - - Sa Quality tombe à 0 après le concert +Un système a été mis en place pour mettre à jour notre inventaire. +Il a été développé par Leeroy, une personne pleine de bon sens qui est parti pour de nouvelles aventures. -Nous avons récemment signé un partenariat avec un fournisseur de produit invoqué ("Conjured"). Notre système a -donc besoin d'une mise à jour : +Votre mission est d'ajouter une nouvelle fonctionnalité à notre système pour que nous puissions commencer à vendre un nouveau type de produit. - - Les produit "Conjured" (invoqués) ont une Quality qui diminue deux fois plus vite que les autres +Mais d'abord, laissez-moi vous présenter notre système : -Vous pouvez faire les changements que vous voulez à la méthode "updateQuality" et ajouter autant de code que -vous voulez, tant que tout fonctionne correctement. Cependant, nous devons vous prévenir, ne modifiez en aucun -cas la classe Item ou ses propriétés car cela appartient au gobelin de l'étage et il s'enragera et vous tura -sans délai : il ne croit pas dans le partage du code (si vous rendez la méthode "updateQuality" et les propriétés -de Item static, on vous couvrira). +- Tous les éléments ont une valeur `sellIn` qui désigne le nombre de jours restant pour vendre l'article. +- Tous les articles ont une valeur `quality` qui dénote combien l'article est précieux. +- A la fin de chaque journée, notre système diminue ces deux valeurs pour chaque produit. -Just pour clarifier un point, un produit ne peut avoir une Quality supérieure à 50, bien sûr étant donné que le -"Sulfuras" est un objet légendaire, sa Quality est de 80 et n'est jamais altérée. +Plutôt simple, non ? + +Attendez, ça devient intéressant : + +- Une fois que la date de péremption est passée, la qualité se dégrade deux fois plus rapidement. +- La qualité (`quality`) d'un produit ne peut jamais être négative. +- "Aged Brie" augmente sa qualité (`quality`) plus le temps passe. +- La qualité d'un produit n'est jamais de plus de 50. +- "Sulfuras", étant un objet légendaire, n'a pas de date de péremption et ne perd jamais en qualité (`quality`) +- "Backstage passes", comme le "Aged Brie", augmente sa qualité (`quality`) plus le temps passe (`sellIn`) ; La qualité augmente de 2 quand il reste 10 jours ou moins et de 3 quand il reste 5 jours ou moins, mais la qualité tombe à 0 après le concert. + +Nous avons récemment signé un partenariat avec un fournisseur de produit invoqué ("Conjured"). +Cela nécessite une mise à jour de notre système : + +- les éléments "Conjured" voient leur qualité se dégrader de deux fois plus vite que les objets normaux. + +Vous pouvez faire les changements que vous voulez à la méthode `updateQuality` et ajouter autant de code que vous voulez, tant que tout fonctionne correctement. +Cependant, nous devons vous prévenir, ne devez modifier en aucun cas la classe `Item` ou ses propriétés car cette classe appartient au gobelin de l'étage et il rentrera dans du rage instantanée et vous tuera sans délai : il ne croit pas dans le partage du code. +(Vous pouvez ajouter une méthode `updateQuality` et des propriétés statiques dans la classe `Item` si vous voulez, nous vous couvrirons) + +Juste une précision, un produit ne peut jamais voir sa qualité augmenter au-dessus de 50, cependant "Sulfuras" est un objet légendaire et comme tel sa qualité est de 80 et il ne change jamais. From 905f87901b199b9e7dac08af8d9e057946f5de2b Mon Sep 17 00:00:00 2001 From: Fernandez Ludovic Date: Thu, 15 Oct 2015 21:28:45 +0200 Subject: [PATCH 148/634] feat: add go version --- go/gilded-rose_test.go | 7 ++++ go/glided-rose.go | 75 ++++++++++++++++++++++++++++++++++++++++++ go/readme.md | 21 ++++++++++++ 3 files changed, 103 insertions(+) create mode 100644 go/gilded-rose_test.go create mode 100644 go/glided-rose.go create mode 100644 go/readme.md diff --git a/go/gilded-rose_test.go b/go/gilded-rose_test.go new file mode 100644 index 00000000..6b03bf25 --- /dev/null +++ b/go/gilded-rose_test.go @@ -0,0 +1,7 @@ +package main + +import "testing" + +func Test_GildedRose(t *testing.T) { + main() +} diff --git a/go/glided-rose.go b/go/glided-rose.go new file mode 100644 index 00000000..3aac5d37 --- /dev/null +++ b/go/glided-rose.go @@ -0,0 +1,75 @@ +package main + +import "fmt" + +type Item struct { + name string + sellIn, quality int +} + +var items = []Item{ + Item{"+5 Dexterity Vest", 10, 20}, + Item{"Aged Brie", 2, 0}, + Item{"Elixir of the Mongoose", 5, 7}, + Item{"Sulfuras, Hand of Ragnaros", 0, 80}, + Item{"Backstage passes to a TAFKAL80ETC concert", 15, 20}, + Item{"Conjured Mana Cake", 3, 6}, +} + +func main() { + fmt.Println("OMGHAI!") + // fmt.Print(items) + GlidedRose() +} + +func GlidedRose() { + for i := 0; i < len(items); i++ { + + if items[i].name != "Aged Brie" && items[i].name != "Backstage passes to a TAFKAL80ETC concert" { + if items[i].quality > 0 { + if items[i].name != "Sulfuras, Hand of Ragnaros" { + items[i].quality = items[i].quality - 1 + } + } + } else { + if items[i].quality < 50 { + items[i].quality = items[i].quality + 1 + if items[i].name == "Backstage passes to a TAFKAL80ETC concert" { + if items[i].sellIn < 11 { + if items[i].quality < 50 { + items[i].quality = items[i].quality + 1 + } + } + if items[i].sellIn < 6 { + if items[i].quality < 50 { + items[i].quality = items[i].quality + 1 + } + } + } + } + } + + if items[i].name != "Sulfuras, Hand of Ragnaros" { + items[i].sellIn = items[i].sellIn - 1 + } + + if items[i].sellIn < 0 { + if items[i].name != "Aged Brie" { + if items[i].name != "Backstage passes to a TAFKAL80ETC concert" { + if items[i].quality > 0 { + if items[i].name != "Sulfuras, Hand of Ragnaros" { + items[i].quality = items[i].quality - 1 + } + } + } else { + items[i].quality = items[i].quality - items[i].quality + } + } else { + if items[i].quality < 50 { + items[i].quality = items[i].quality + 1 + } + } + } + } + +} diff --git a/go/readme.md b/go/readme.md new file mode 100644 index 00000000..6b894ed4 --- /dev/null +++ b/go/readme.md @@ -0,0 +1,21 @@ +# GO Starter + +- Run : + +```shell +go run gilded-rose.go +``` + +- Run tests : + +```shell +go test +``` + +- Run tests and coverage : + +```shell +go test -coverprofile=coverage.out + +go tool cover -html=coverage.out +``` \ No newline at end of file From cb45ff3fe7d2d96d598df98818dea548f2cd579c Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 26 Oct 2015 13:38:45 +0100 Subject: [PATCH 149/634] add fsharp version --- .../GildedRose.Tests/GildedRose.Tests.fsproj | 97 +++++++++++++++++++ fsharp/GildedRose.Tests/GildedRoseTest.fs | 32 ++++++ fsharp/GildedRose.Tests/packages.config | 6 ++ fsharp/GildedRose.sln | 28 ++++++ fsharp/GildedRose/App.config | 6 ++ fsharp/GildedRose/GildedRose.fs | 63 ++++++++++++ fsharp/GildedRose/GildedRose.fsproj | 76 +++++++++++++++ 7 files changed, 308 insertions(+) create mode 100644 fsharp/GildedRose.Tests/GildedRose.Tests.fsproj create mode 100644 fsharp/GildedRose.Tests/GildedRoseTest.fs create mode 100644 fsharp/GildedRose.Tests/packages.config create mode 100644 fsharp/GildedRose.sln create mode 100644 fsharp/GildedRose/App.config create mode 100644 fsharp/GildedRose/GildedRose.fs create mode 100644 fsharp/GildedRose/GildedRose.fsproj diff --git a/fsharp/GildedRose.Tests/GildedRose.Tests.fsproj b/fsharp/GildedRose.Tests/GildedRose.Tests.fsproj new file mode 100644 index 00000000..f021553f --- /dev/null +++ b/fsharp/GildedRose.Tests/GildedRose.Tests.fsproj @@ -0,0 +1,97 @@ + + + + + Debug + AnyCPU + 2.0 + 9f9d20e1-cfc0-442c-870a-76e5abf0e7fe + Library + GildedRose.Tests + GildedRose.Tests + v4.5 + true + 4.3.1.0 + GildedRose.Tests + + + true + full + false + false + bin\Debug\ + DEBUG;TRACE + 3 + AnyCPU + bin\Debug\GildedRose.Tests.XML + true + + + pdbonly + true + true + bin\Release\ + TRACE + 3 + AnyCPU + bin\Release\GildedRose.Tests.XML + true + + + 11 + + + + + $(MSBuildExtensionsPath32)\..\Microsoft SDKs\F#\3.0\Framework\v4.0\Microsoft.FSharp.Targets + + + + + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\FSharp\Microsoft.FSharp.Targets + + + + + + + + + + + ..\packages\ApprovalTests.3.0.10\lib\net40\ApprovalTests.dll + True + + + ..\packages\ApprovalUtilities.3.0.10\lib\net45\ApprovalUtilities.dll + True + + + ..\packages\ApprovalUtilities.3.0.10\lib\net45\ApprovalUtilities.Net45.dll + True + + + + True + + + ..\packages\NUnit.2.6.4\lib\nunit.framework.dll + True + + + + + + GildedRose + {2660ef56-b4c1-4dcf-b106-278211bd26c6} + True + + + + \ No newline at end of file diff --git a/fsharp/GildedRose.Tests/GildedRoseTest.fs b/fsharp/GildedRose.Tests/GildedRoseTest.fs new file mode 100644 index 00000000..d29ed6d6 --- /dev/null +++ b/fsharp/GildedRose.Tests/GildedRoseTest.fs @@ -0,0 +1,32 @@ +module GildedRoseTest + +open GildedRose +open System +open System.IO +open System.Text +open NUnit.Framework +open System.Collections.Generic +open ApprovalTests +open ApprovalTests.Reporters + +[] +type GildedRoseTest () as this = + [] member this.Foo ()= + let Items = new List() + Items.Add({Name = "foo"; SellIn = 0; Quality = 0}) + let app = new GildedRose(Items) + app.UpdateQuality() + Assert.AreEqual("fixme", Items.[0].Name) + +[] +[)>] +type ApprovalTest () as this = + [] member this.ThirtyDays ()= + let fakeoutput = new StringBuilder() + Console.SetOut(new StringWriter(fakeoutput)) + Console.SetIn(new StringReader("a\n")) + + main Array.empty + let output = fakeoutput.ToString() + Approvals.Verify(output) + () \ No newline at end of file diff --git a/fsharp/GildedRose.Tests/packages.config b/fsharp/GildedRose.Tests/packages.config new file mode 100644 index 00000000..eff071b2 --- /dev/null +++ b/fsharp/GildedRose.Tests/packages.config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/fsharp/GildedRose.sln b/fsharp/GildedRose.sln new file mode 100644 index 00000000..027a29bf --- /dev/null +++ b/fsharp/GildedRose.sln @@ -0,0 +1,28 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2013 +VisualStudioVersion = 12.0.40629.0 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "GildedRose", "GildedRose\GildedRose.fsproj", "{2660EF56-B4C1-4DCF-B106-278211BD26C6}" +EndProject +Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "GildedRose.Tests", "GildedRose.Tests\GildedRose.Tests.fsproj", "{9F9D20E1-CFC0-442C-870A-76E5ABF0E7FE}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {2660EF56-B4C1-4DCF-B106-278211BD26C6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2660EF56-B4C1-4DCF-B106-278211BD26C6}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2660EF56-B4C1-4DCF-B106-278211BD26C6}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2660EF56-B4C1-4DCF-B106-278211BD26C6}.Release|Any CPU.Build.0 = Release|Any CPU + {9F9D20E1-CFC0-442C-870A-76E5ABF0E7FE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9F9D20E1-CFC0-442C-870A-76E5ABF0E7FE}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9F9D20E1-CFC0-442C-870A-76E5ABF0E7FE}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9F9D20E1-CFC0-442C-870A-76E5ABF0E7FE}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/fsharp/GildedRose/App.config b/fsharp/GildedRose/App.config new file mode 100644 index 00000000..8e156463 --- /dev/null +++ b/fsharp/GildedRose/App.config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/fsharp/GildedRose/GildedRose.fs b/fsharp/GildedRose/GildedRose.fs new file mode 100644 index 00000000..f14f4cc9 --- /dev/null +++ b/fsharp/GildedRose/GildedRose.fs @@ -0,0 +1,63 @@ +module GildedRose + +open System.Collections.Generic + +type Item = { Name: string; SellIn: int; Quality: int } + +type GildedRose(items:IList) as this = + let Items = items + + member this.UpdateQuality() = + for i = 0 to Items.Count - 1 do + if Items.[i].Name <> "Aged Brie" && Items.[i].Name <> "Backstage passes to a TAFKAL80ETC concert" then + if Items.[i].Quality > 0 then + if Items.[i].Name <> "Sulfuras, Hand of Ragnaros" then + Items.[i] <- { Items.[i] with Quality = (Items.[i].Quality - 1) } + else + if Items.[i].Quality < 50 then + Items.[i] <- { Items.[i] with Quality = (Items.[i].Quality + 1) } + if Items.[i].Name = "Backstage passes to a TAFKAL80ETC concert" then + if Items.[i].SellIn < 11 then + if Items.[i].Quality < 50 then + Items.[i] <- { Items.[i] with Quality = (Items.[i].Quality + 1) } + if Items.[i].SellIn < 6 then + if Items.[i].Quality < 50 then + Items.[i] <- { Items.[i] with Quality = (Items.[i].Quality + 1) } + if Items.[i].Name <> "Sulfuras, Hand of Ragnaros" then + Items.[i] <- { Items.[i] with SellIn = (Items.[i].SellIn - 1) } + if Items.[i].SellIn < 0 then + if Items.[i].Name <> "Aged Brie" then + if Items.[i].Name <> "Backstage passes to a TAFKAL80ETC concert" then + if Items.[i].Quality > 0 then + if Items.[i].Name <> "Sulfuras, Hand of Ragnaros" then + Items.[i] <- { Items.[i] with Quality = (Items.[i].Quality - 1) } + else + Items.[i] <- { Items.[i] with Quality = (Items.[i].Quality - Items.[i].Quality) } + else + if Items.[i].Quality < 50 then + Items.[i] <- { Items.[i] with Quality = (Items.[i].Quality + 1) } + () + +[] +let main argv = + printfn "OMGHAI!" + let Items = new List() + Items.Add({Name = "+5 Dexterity Vest"; SellIn = 10; Quality = 20}) + Items.Add({Name = "Aged Brie"; SellIn = 2; Quality = 0}) + Items.Add({Name = "Elixir of the Mongoose"; SellIn = 5; Quality = 7}) + Items.Add({Name = "Sulfuras, Hand of Ragnaros"; SellIn = 0; Quality = 80}) + Items.Add({Name = "Sulfuras, Hand of Ragnaros"; SellIn = -1; Quality = 80}) + Items.Add({Name = "Backstage passes to a TAFKAL80ETC concert"; SellIn = 15; Quality = 20}) + Items.Add({Name = "Backstage passes to a TAFKAL80ETC concert"; SellIn = 10; Quality = 49}) + Items.Add({Name = "Backstage passes to a TAFKAL80ETC concert"; SellIn = 5; Quality = 49}) + Items.Add({Name = "Conjured Mana Cake"; SellIn = 3; Quality = 6}) + + let app = new GildedRose(Items) + for i = 0 to 30 do + printfn "-------- day %d --------" i + printfn "name, sellIn, quality" + for j = 0 to Items.Count - 1 do + printfn "%s, %d, %d" Items.[j].Name Items.[j].SellIn Items.[j].Quality + printfn "" + app.UpdateQuality() + 0 \ No newline at end of file diff --git a/fsharp/GildedRose/GildedRose.fsproj b/fsharp/GildedRose/GildedRose.fsproj new file mode 100644 index 00000000..520dda6e --- /dev/null +++ b/fsharp/GildedRose/GildedRose.fsproj @@ -0,0 +1,76 @@ + + + + + Debug + AnyCPU + 2.0 + 2660ef56-b4c1-4dcf-b106-278211bd26c6 + Exe + GildedRose + GildedRose + v4.5 + true + 4.3.1.0 + GildedRose + + + true + full + false + false + bin\Debug\ + DEBUG;TRACE + 3 + AnyCPU + bin\Debug\GildedRose.XML + true + + + pdbonly + true + true + bin\Release\ + TRACE + 3 + AnyCPU + bin\Release\GildedRose.XML + true + + + + + True + + + + + + + + + + + 11 + + + + + $(MSBuildExtensionsPath32)\..\Microsoft SDKs\F#\3.0\Framework\v4.0\Microsoft.FSharp.Targets + + + + + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\FSharp\Microsoft.FSharp.Targets + + + + + + \ No newline at end of file From e19161a0cb72ae45a3dedb98bf7f21ad2640d1f4 Mon Sep 17 00:00:00 2001 From: Jacky Shen Date: Mon, 7 Dec 2015 23:23:14 +0800 Subject: [PATCH 150/634] Create GildedRoseRequirements_zh.txt --- GildedRoseRequirements_zh.txt | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 GildedRoseRequirements_zh.txt diff --git a/GildedRoseRequirements_zh.txt b/GildedRoseRequirements_zh.txt new file mode 100644 index 00000000..26b39a51 --- /dev/null +++ b/GildedRoseRequirements_zh.txt @@ -0,0 +1,32 @@ +====================================== +Gilded Rose 需求描述 +====================================== + + +欢迎来到镶金玫瑰(Gilded Rose)团队。如你所知,我们是主城中的一个小旅店,店主非常友好,名叫Allison。我们也售卖最好的物品。不幸的是,物品品质会随着销售期限的接近而不断下降。 +我们有一个系统来更新库存信息。系统是由一个无名之辈Leeroy所开发的,他已经不在这了。 +你的任务是添加新功能,这样我们就可以售卖新的物品。 + +先介绍一下我们的系统: + + - 每种物品都具备一个`SellIn`值,表示我们要在多少天之前把物品卖出去,即销售期 + - 每种的物品都具备一个`Quality`值,表示物品的品质 + - 每天结束时,系统会降低每种物品的这两个数值 + +很简单吧?这还有些更有意思的: + + - 一旦销售期限过期,品质`Quality`会以双倍速度加速下降 + - 物品的品质`Quality`永远不会为负值 + - "Aged Brie"的品质`Quality`会随着时间推移而提高 + - 物品的品质`Quality`永远不会超过50 + - 传奇物品"Sulfuras"永不到期,也不会降低品质`Quality` + - "Backstage passes"与aged brie类似,其品质`Quality`会随着时间推移而提高;当还剩10天或更少的时候,品质`Quality`每天提高2;当还剩5天或更少的时候,品质`Quality`每天提高3;但一旦过期,品质就会降为0 + + +我们最近签约了一个召唤物品供应商。这需要对我们的系统进行升级: + + - "Conjured"物品的品质`Quality`下降速度比正常物品快一倍 + +请随意对UpdateQuality函数进行修改和添加新代码,只要系统还能正常工作。然而,不要修改Item类或其属性,因为那属于角落里的地精,他会非常愤怒地爆你头,因为他不相信代码共享所有制(如果你愿意,你可以将UpdateQuality方面和Items属性改为静态的,我们会掩护你的)。 + +再次澄清,每种物品的品质不会超过50,然而"Sulfuras"是一个传奇物品,因此它的品质是80且永远不变。 From 03a51ec27338e6325cf6c81a7eb0c65a313362a9 Mon Sep 17 00:00:00 2001 From: Emily Bache Date: Fri, 22 Jan 2016 16:55:48 +0100 Subject: [PATCH 151/634] improved installation instructions --- cpp/README | 35 +++++++++++++++++++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) diff --git a/cpp/README b/cpp/README index 5d4673a4..bae8ca20 100644 --- a/cpp/README +++ b/cpp/README @@ -1,7 +1,38 @@ +TL;DR; +------- run-once.sh runs your tests once -Assumptions: +Before this will work you will need: - make and a C++ compiler (like gcc) is installed on your system and is in the PATH - - The GTest framework is in the directory gtest. + - The GTest framework in the directory gtest. - If your IDE does the compilation and linking, you should remove the first 3 lines in the run-once.sh file. + +More Verbose Instructions +------------------------- + +Create a clone of both GildedRose-Refactoring-Kata and googletest in a directory we'll call ${ROOT_INSTALL_DIR}: + + cd ${ROOT_INSTALL_DIR} + git clone https://github.com/emilybache/GildedRose-Refactoring-Kata + git clone https://github.com/google/googletest + +Make googletest by running make in subfolder googletest/googletest/make: + + cd googletest/googletest/make + make + +Create a softlink in the GildedRose-Refactoring-Kata clone pointing at the googletest code: + + cd ${ROOT_INSTALL_DIR}/GildedRose-Refactoring-Kata/cpp + ln -s ${ROOT_INSTALL_DIR}/googletest/googletest gtest + +Make the GildedRose-Refactoring-Kata: + + make + +Then you should be able to run the tests: + + ./run_once.sh + +If you have been successful, then you should see a failing test, "GildedRoseTest.Foo". From 0201d9ab7db8c519710094f6cdd3eb57b1bc9c44 Mon Sep 17 00:00:00 2001 From: Pietro Di Bello Date: Sun, 24 Jan 2016 22:58:21 +0100 Subject: [PATCH 152/634] Update URL for a blogpost linked in the README Update URL for the "Writing Good Tests for the Gilded Rose Kata" post --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 423c33da..2621bb30 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ As Bobby Johnson points out in his article ["Why Most Solutions to Gilded Rose M better practice at handling a legacy code situation if you do this Kata in the original C#. However, I think this kata is also really useful for practicing writing good tests using different frameworks and approaches, and the small changes I've made help with that. I think it's also interesting to compare what the refactored code and tests look like in different programming languages. -I wrote this article ["Writing Good Tests for the Gilded Rose Kata"](http://emilybache.blogspot.se/2013/03/writing-good-tests-for-gilded-rose-kata.html) about how you could use this kata in a [coding dojo](https://leanpub.com/codingdojohandbook). +I wrote this article ["Writing Good Tests for the Gilded Rose Kata"](http://coding-is-like-cooking.info/2013/03/writing-good-tests-for-the-gilded-rose-kata/) about how you could use this kata in a [coding dojo](https://leanpub.com/codingdojohandbook). ## How to use this Kata From 1599d45f689334d26541e7d4a97998bb80b4ecab Mon Sep 17 00:00:00 2001 From: Pietro Di Bello Date: Mon, 25 Jan 2016 20:42:55 +0100 Subject: [PATCH 153/634] fix typo in requirements --- GildedRoseRequirements.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/GildedRoseRequirements.txt b/GildedRoseRequirements.txt index e2bfd98a..2e74aae6 100644 --- a/GildedRoseRequirements.txt +++ b/GildedRoseRequirements.txt @@ -20,7 +20,7 @@ Pretty simple, right? Well this is where it gets interesting: - "Aged Brie" actually increases in Quality the older it gets - The Quality of an item is never more than 50 - "Sulfuras", being a legendary item, never has to be sold or decreases in Quality - - "Backstage passes", like aged brie, increases in Quality as it's SellIn value approaches; + - "Backstage passes", like aged brie, increases in Quality as its SellIn value approaches; Quality increases by 2 when there are 10 days or less and by 3 when there are 5 days or less but Quality drops to 0 after the concert @@ -35,4 +35,4 @@ ownership (you can make the UpdateQuality method and Items property static if yo for you). Just for clarification, an item can never have its Quality increase above 50, however "Sulfuras" is a -legendary item and as such its Quality is 80 and it never alters. \ No newline at end of file +legendary item and as such its Quality is 80 and it never alters. From 3d8c1f96bcc92a83d8e2998fc538ffec3d5c455f Mon Sep 17 00:00:00 2001 From: Pascal Batty Date: Tue, 26 Jan 2016 15:13:15 +0100 Subject: [PATCH 154/634] Add Swift port --- swift/GildedRose.swift | 61 ++++++++++++++++++++++++++++++++++++++ swift/GildedRoseTest.swift | 13 ++++++++ swift/Item.swift | 18 +++++++++++ swift/main.swift | 30 +++++++++++++++++++ 4 files changed, 122 insertions(+) create mode 100644 swift/GildedRose.swift create mode 100644 swift/GildedRoseTest.swift create mode 100644 swift/Item.swift create mode 100644 swift/main.swift diff --git a/swift/GildedRose.swift b/swift/GildedRose.swift new file mode 100644 index 00000000..649e97e4 --- /dev/null +++ b/swift/GildedRose.swift @@ -0,0 +1,61 @@ + +public class GildedRose { + var items:[Item] + + required public init(items:[Item]) { + self.items = items + } + + public func updateQuality() { + + for i in 0.. 0) { + if (items[i].name != "Sulfuras, Hand of Ragnaros") { + items[i].quality = items[i].quality - 1 + } + } + } else { + if (items[i].quality < 50) { + items[i].quality = items[i].quality + 1 + + if (items[i].name == "Backstage passes to a TAFKAL80ETC concert") { + if (items[i].sellIn < 11) { + if (items[i].quality < 50) { + items[i].quality = items[i].quality + 1 + } + } + + if (items[i].sellIn < 6) { + if (items[i].quality < 50) { + items[i].quality = items[i].quality + 1 + } + } + } + } + } + + if (items[i].name != "Sulfuras, Hand of Ragnaros") { + items[i].sellIn = items[i].sellIn - 1 + } + + if (items[i].sellIn < 0) { + if (items[i].name != "Aged Brie") { + if (items[i].name != "Backstage passes to a TAFKAL80ETC concert") { + if (items[i].quality > 0) { + if (items[i].name != "Sulfuras, Hand of Ragnaros") { + items[i].quality = items[i].quality - 1 + } + } + } else { + items[i].quality = items[i].quality - items[i].quality + } + } else { + if (items[i].quality < 50) { + items[i].quality = items[i].quality + 1 + } + } + } + } + } +} diff --git a/swift/GildedRoseTest.swift b/swift/GildedRoseTest.swift new file mode 100644 index 00000000..66b066dd --- /dev/null +++ b/swift/GildedRoseTest.swift @@ -0,0 +1,13 @@ + +import XCTest + +class GildedRoseTest: XCTestCase { + + func testFoo() { + let items = [Item(name: "foo", sellIn: 0, quality: 0)] + let app = GildedRose(items: items); + app.updateQuality(); + XCTAssertEqual("fixme", app.items[0].name); + } + +} diff --git a/swift/Item.swift b/swift/Item.swift new file mode 100644 index 00000000..1533a3da --- /dev/null +++ b/swift/Item.swift @@ -0,0 +1,18 @@ + +public class Item { + public var name: String + public var sellIn: Int + public var quality: Int + + public init(name: String, sellIn: Int, quality: Int) { + self.name = name + self.sellIn = sellIn + self.quality = quality + } +} + +extension Item: CustomStringConvertible { + public var description: String { + return self.name + ", " + String(self.sellIn) + ", " + String(self.quality); + } +} diff --git a/swift/main.swift b/swift/main.swift new file mode 100644 index 00000000..fb95ee9c --- /dev/null +++ b/swift/main.swift @@ -0,0 +1,30 @@ + +let items = [ + Item(name: "+5 Dexterity Vest", sellIn: 10, quality: 20), // + Item(name: "Aged Brie", sellIn: 2, quality: 0), // + Item(name: "Elixir of the Mongoosname: e", sellIn: 5, quality: 7), // + Item(name: "SulfursellIn: as,quality: Hand of Ragnaros", sellIn: 0, quality: 80), // + Item(name: "Sulfuras, Hand of Ragnaros", sellIn: -1, quality: 80), + Item(name: "Backstage passes to a TAFKAL80ETC concert", sellIn: 15, quality: 20), + Item(name: "Backstage passes to a TAFKAL80ETC concert", sellIn: 10, quality: 49), + Item(name: "Backstage passes to a TAFKAL80ETC concert", sellIn: 5, quality: 49), + // this conjured item does not work properly yet + Item(name: "Conjured Mana Cake", sellIn: 3, quality: 6)] + +let app = GildedRose(items: items); + +var days = 2; +if (Process.argc > 1) { + days = Int(Process.arguments[1])! + 1 +} + + +for i in 0.. Date: Mon, 29 Feb 2016 21:30:33 -0500 Subject: [PATCH 155/634] Initial Dart --- dart/.gitignore | 6 + dart/bin/main.dart | 35 ++++++ dart/lib/gilded_rose.dart | 68 +++++++++++ dart/pubspec.lock | 208 ++++++++++++++++++++++++++++++++ dart/pubspec.yaml | 6 + dart/test/gilded_rose_test.dart | 13 ++ 6 files changed, 336 insertions(+) create mode 100644 dart/.gitignore create mode 100644 dart/bin/main.dart create mode 100644 dart/lib/gilded_rose.dart create mode 100644 dart/pubspec.lock create mode 100644 dart/pubspec.yaml create mode 100644 dart/test/gilded_rose_test.dart diff --git a/dart/.gitignore b/dart/.gitignore new file mode 100644 index 00000000..33d0df0e --- /dev/null +++ b/dart/.gitignore @@ -0,0 +1,6 @@ +# Files and directories created by pub +.packages +.pub/ +packages +pubspec.lock # (Remove this pattern if you wish to check in your lock file) +.idea \ No newline at end of file diff --git a/dart/bin/main.dart b/dart/bin/main.dart new file mode 100644 index 00000000..240994c5 --- /dev/null +++ b/dart/bin/main.dart @@ -0,0 +1,35 @@ +import 'package:gilded_rose/gilded_rose.dart'; + +main(List args) { + print("OMGHAI!"); + + var items = [ + new Item("+5 Dexterity Vest", 10, 20), + new Item("Aged Brie", 2, 0), + new Item("Elixir of the Mongoose", 5, 7), + new Item("Sulfuras, Hand of Ragnaros", 0, 80), + new Item("Sulfuras, Hand of Ragnaros", -1, 80), + new Item("Backstage passes to a TAFKAL80ETC concert", 15, 20), + new Item("Backstage passes to a TAFKAL80ETC concert", 10, 49), + new Item("Backstage passes to a TAFKAL80ETC concert", 5, 49), + // this conjured item does not work properly yet + new Item("Conjured Mana Cake", 3, 6) + ]; + + GildedRose app = new GildedRose(items); + + int days = 2; + if (args.length > 0) { + days = int.parse(args[0]) + 1; + } + + for (int i = 0; i < days; i++) { + print("-------- day $i --------"); + print("name, sellIn, quality"); + for (var item in items) { + print(item); + } + print(''); + app.updateQuality(); + } +} diff --git a/dart/lib/gilded_rose.dart b/dart/lib/gilded_rose.dart new file mode 100644 index 00000000..94857b32 --- /dev/null +++ b/dart/lib/gilded_rose.dart @@ -0,0 +1,68 @@ +class GildedRose { + List items; + + GildedRose(this.items); + + void updateQuality() { + for (int i = 0; i < items.length; i++) { + if (items[i].name != "Aged Brie" && + items[i].name != "Backstage passes to a TAFKAL80ETC concert") { + if (items[i].quality > 0) { + if (items[i].name != "Sulfuras, Hand of Ragnaros") { + items[i].quality = items[i].quality - 1; + } + } + } else { + if (items[i].quality < 50) { + items[i].quality = items[i].quality + 1; + + if (items[i].name == "Backstage passes to a TAFKAL80ETC concert") { + if (items[i].sellIn < 11) { + if (items[i].quality < 50) { + items[i].quality = items[i].quality + 1; + } + } + + if (items[i].sellIn < 6) { + if (items[i].quality < 50) { + items[i].quality = items[i].quality + 1; + } + } + } + } + } + + if (items[i].name != "Sulfuras, Hand of Ragnaros") { + items[i].sellIn = items[i].sellIn - 1; + } + + if (items[i].sellIn < 0) { + if (items[i].name != "Aged Brie") { + if (items[i].name != "Backstage passes to a TAFKAL80ETC concert") { + if (items[i].quality > 0) { + if (items[i].name != "Sulfuras, Hand of Ragnaros") { + items[i].quality = items[i].quality - 1; + } + } + } else { + items[i].quality = items[i].quality - items[i].quality; + } + } else { + if (items[i].quality < 50) { + items[i].quality = items[i].quality + 1; + } + } + } + } + } +} + +class Item { + String name; + int sellIn; + int quality; + + Item(this.name, this.sellIn, this.quality); + + String toString() => '$name, $sellIn, $quality'; +} diff --git a/dart/pubspec.lock b/dart/pubspec.lock new file mode 100644 index 00000000..dcf8bbd3 --- /dev/null +++ b/dart/pubspec.lock @@ -0,0 +1,208 @@ +# Generated by pub +# See http://pub.dartlang.org/doc/glossary.html#lockfile +packages: + analyzer: + description: + name: analyzer + url: "https://pub.dartlang.org" + source: hosted + version: "0.27.2" + args: + description: + name: args + url: "https://pub.dartlang.org" + source: hosted + version: "0.13.3+4" + async: + description: + name: async + url: "https://pub.dartlang.org" + source: hosted + version: "1.8.0" + barback: + description: + name: barback + url: "https://pub.dartlang.org" + source: hosted + version: "0.15.2+7" + boolean_selector: + description: + name: boolean_selector + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.0" + charcode: + description: + name: charcode + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.0" + collection: + description: + name: collection + url: "https://pub.dartlang.org" + source: hosted + version: "1.4.0" + crypto: + description: + name: crypto + url: "https://pub.dartlang.org" + source: hosted + version: "0.9.1" + csslib: + description: + name: csslib + url: "https://pub.dartlang.org" + source: hosted + version: "0.12.2" + glob: + description: + name: glob + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.0" + html: + description: + name: html + url: "https://pub.dartlang.org" + source: hosted + version: "0.12.2+1" + http_multi_server: + description: + name: http_multi_server + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.0" + http_parser: + description: + name: http_parser + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.0" + logging: + description: + name: logging + url: "https://pub.dartlang.org" + source: hosted + version: "0.11.2" + matcher: + description: + name: matcher + url: "https://pub.dartlang.org" + source: hosted + version: "0.12.0+1" + mime: + description: + name: mime + url: "https://pub.dartlang.org" + source: hosted + version: "0.9.3" + package_config: + description: + name: package_config + url: "https://pub.dartlang.org" + source: hosted + version: "0.1.3" + path: + description: + name: path + url: "https://pub.dartlang.org" + source: hosted + version: "1.3.9" + plugin: + description: + name: plugin + url: "https://pub.dartlang.org" + source: hosted + version: "0.1.0" + pool: + description: + name: pool + url: "https://pub.dartlang.org" + source: hosted + version: "1.2.1" + pub_semver: + description: + name: pub_semver + url: "https://pub.dartlang.org" + source: hosted + version: "1.2.3" + shelf: + description: + name: shelf + url: "https://pub.dartlang.org" + source: hosted + version: "0.6.5" + shelf_static: + description: + name: shelf_static + url: "https://pub.dartlang.org" + source: hosted + version: "0.2.3+3" + shelf_web_socket: + description: + name: shelf_web_socket + url: "https://pub.dartlang.org" + source: hosted + version: "0.1.0" + source_map_stack_trace: + description: + name: source_map_stack_trace + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.4" + source_maps: + description: + name: source_maps + url: "https://pub.dartlang.org" + source: hosted + version: "0.10.1" + source_span: + description: + name: source_span + url: "https://pub.dartlang.org" + source: hosted + version: "1.2.1" + stack_trace: + description: + name: stack_trace + url: "https://pub.dartlang.org" + source: hosted + version: "1.6.1" + stream_channel: + description: + name: stream_channel + url: "https://pub.dartlang.org" + source: hosted + version: "1.3.1" + string_scanner: + description: + name: string_scanner + url: "https://pub.dartlang.org" + source: hosted + version: "0.1.4+1" + test: + description: + name: test + url: "https://pub.dartlang.org" + source: hosted + version: "0.12.11" + utf: + description: + name: utf + url: "https://pub.dartlang.org" + source: hosted + version: "0.9.0+3" + watcher: + description: + name: watcher + url: "https://pub.dartlang.org" + source: hosted + version: "0.9.7" + yaml: + description: + name: yaml + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.8" +sdk: ">=1.14.0 <1.16.0" diff --git a/dart/pubspec.yaml b/dart/pubspec.yaml new file mode 100644 index 00000000..06814a33 --- /dev/null +++ b/dart/pubspec.yaml @@ -0,0 +1,6 @@ +name: gilded_rose +version: 0.0.1 +description: A simple console application. + +dev_dependencies: + test: '>=0.12.11 <0.13.0' diff --git a/dart/test/gilded_rose_test.dart b/dart/test/gilded_rose_test.dart new file mode 100644 index 00000000..69e4a489 --- /dev/null +++ b/dart/test/gilded_rose_test.dart @@ -0,0 +1,13 @@ +import 'package:test/test.dart'; +import 'package:gilded_rose/gilded_rose.dart'; + +main() { + test('foo', () { + var item = new Item('foo', 0, 0); + var items = [item]; + + GildedRose app = new GildedRose(items); + app.updateQuality(); + expect("fixme", app.items[0].name); + }); +} From 63d80b152fb88766dcd97dc9251bb261fce30a9a Mon Sep 17 00:00:00 2001 From: Brett Rehberg Date: Fri, 18 Mar 2016 14:56:22 -0500 Subject: [PATCH 156/634] starting code and tests for ABAP --- abap/README.md | 16 ++++++++++++++++ abap/YY_PAO_GILDED_ROSE.abap | 1 + 2 files changed, 17 insertions(+) create mode 100644 abap/README.md create mode 100644 abap/YY_PAO_GILDED_ROSE.abap diff --git a/abap/README.md b/abap/README.md new file mode 100644 index 00000000..ebd18544 --- /dev/null +++ b/abap/README.md @@ -0,0 +1,16 @@ +# Gilded Rose Refactoring Kata in [ABAP](http://scn.sap.com/community/abap/) + +## Prerequisite + +Access to SAP NetWeaver server with at least ABAP 7.40 + +## Installation + +Assuming you have a proper developer key set up, run SE38 +* create a new Module Pool (type M) program as a Local Object +* paste the raw code from [YY_PAO_GILDED_ROSE.abap](https://raw.githubusercontent.com/brehberg/GildedRose-Refactoring-Kata/master/abap/YY_PAO_GILDED_ROSE.abap) +* save (Ctrl-S) and activate (Ctrl-F3) the program + +## Running Tests + +From the menus choose Program -> Execute -> Unit Tests (Ctrl+Shift+F10) diff --git a/abap/YY_PAO_GILDED_ROSE.abap b/abap/YY_PAO_GILDED_ROSE.abap new file mode 100644 index 00000000..258607d8 --- /dev/null +++ b/abap/YY_PAO_GILDED_ROSE.abap @@ -0,0 +1 @@ +*&---------------------------------------------------------------------* *& Gilded Rose Requirements Specification *&---------------------------------------------------------------------* *& *& Hi and welcome to team Gilded Rose. As you know, we are a small inn with *& a prime location in a prominent city ran by a friendly innkeeper named *& Allison. We also buy and sell only the finest goods. Unfortunately, our *& goods are constantly degrading in quality as they approach their sell by *& date. We have a system in place that updates our inventory for us. It *& was developed by a no-nonsense type named Leeroy, who has moved on to *& new adventures. Your task is to add the new feature to our system so that *& we can begin selling a new category of items. *& *& First an introduction to our system: *& *& - All items have a Sell In value which denotes the number of *& days we have to sell the item *& - All items have a Quality value which denotes how valuable the item is *& - At the end of each day our system lowers both values for every item *& *& Seems pretty simple, right? Well this is where it gets interesting: *& *& - Once the sell by date has passed, Quality degrades twice as fast *& - The Quality of an item is never negative *& - "Aged Brie" actually increases in Quality the older it gets *& - The Quality of an item is never more than 50 *& - "Sulfuras", being a legendary item, never has to be sold or *& decreases in Quality *& - "Backstage passes", like aged brie, increases in Quality as its *& Sell In value approaches; Quality increases by 2 when there *& are 10 days or less and by 3 when there are 5 days or less *& but Quality drops to 0 after the concert *& *& We have recently signed a supplier of conjured items. This requires an *& update to our system: *& *& - "Conjured" items degrade in Quality twice as fast as normal items *& *& Feel free to make any changes to the Update Quality method and add any new *& code as long as everything still works correctly. However, do not alter *& the Item class directly or Items table attribute as those belong to the *& goblin in the corner who will insta-rage and one-shot you as he doesn't *& believe in shared code ownership (you can make the Update Quality method *& and Items property static if you must, we'll cover for you). *& *& Just for clarification, an item can never have its Quality increase *& above 50, however "Sulfuras" is a legendary item and as such its Quality *& is 80 and it never alters. PROGRAM yy_pao_gilded_rose. *& Production Code - Class Library CLASS lcl_item DEFINITION DEFERRED. CLASS lcl_gilded_rose DEFINITION FINAL. PUBLIC SECTION. TYPES: tt_items TYPE STANDARD TABLE OF REF TO lcl_item WITH EMPTY KEY. METHODS: constructor IMPORTING it_items TYPE tt_items, update_quality. PRIVATE SECTION. DATA: mt_items TYPE tt_items. ENDCLASS. CLASS lcl_item DEFINITION FINAL. PUBLIC SECTION. METHODS: constructor IMPORTING iv_name TYPE string iv_sell_in TYPE i iv_quality TYPE i, description RETURNING VALUE(rv_string) TYPE string. DATA: mv_name TYPE string, mv_sell_in TYPE i, mv_quality TYPE i. ENDCLASS. CLASS lcl_gilded_rose IMPLEMENTATION. METHOD constructor. mt_items = it_items. ENDMETHOD. METHOD update_quality. LOOP AT mt_items INTO DATA(lo_item). IF lo_item->mv_name <> |Aged Brie| AND lo_item->mv_name <> |Backstage passes to a TAFKAL80ETC concert|. IF lo_item->mv_quality > 0. IF lo_item->mv_name <> |Sulfuras, Hand of Ragnaros|. lo_item->mv_quality = lo_item->mv_quality - 1. ENDIF. ENDIF. ELSE. IF lo_item->mv_quality < 50. lo_item->mv_quality = lo_item->mv_quality + 1. IF lo_item->mv_name = |Backstage passes to a TAFKAL80ETC concert|. IF lo_item->mv_sell_in < 11. IF lo_item->mv_quality < 50. lo_item->mv_quality = lo_item->mv_quality + 1. ENDIF. ENDIF. IF lo_item->mv_sell_in < 6. IF lo_item->mv_quality < 50. lo_item->mv_quality = lo_item->mv_quality + 1. ENDIF. ENDIF. ENDIF. ENDIF. ENDIF. IF lo_item->mv_name <> |Sulfuras, Hand of Ragnaros|. lo_item->mv_sell_in = lo_item->mv_sell_in - 1. ENDIF. IF lo_item->mv_sell_in < 0. IF lo_item->mv_name <> |Aged Brie|. IF lo_item->mv_name <> |Backstage passes to a TAFKAL80ETC concert|. IF lo_item->mv_quality > 0. IF lo_item->mv_name <> |Sulfuras, Hand of Ragnaros|. lo_item->mv_quality = lo_item->mv_quality - 1. ENDIF. ENDIF. ELSE. lo_item->mv_quality = lo_item->mv_quality - lo_item->mv_quality. ENDIF. ELSE. IF lo_item->mv_quality < 50. lo_item->mv_quality = lo_item->mv_quality + 1. ENDIF. ENDIF. ENDIF. ENDLOOP. ENDMETHOD. ENDCLASS. CLASS lcl_item IMPLEMENTATION. METHOD constructor. mv_name = iv_name. mv_sell_in = iv_sell_in. mv_quality = iv_quality. ENDMETHOD. METHOD description. rv_string = |{ mv_name }, { mv_sell_in }, { mv_quality }|. ENDMETHOD. ENDCLASS. *& Test Code - Executable Text Test Fixture CLASS lth_texttest_fixture DEFINITION FINAL. PUBLIC SECTION. CLASS-METHODS main. ENDCLASS. CLASS lth_texttest_fixture IMPLEMENTATION. METHOD main. DATA(lo_out) = cl_demo_output=>new( )->write_text( |OMGHAI!| ). DATA(lt_items) = VALUE lcl_gilded_rose=>tt_items( ( NEW #( iv_name = |+5 Dexterity Vest| iv_sell_in = 10 iv_quality = 20 ) ) ( NEW #( iv_name = |Aged Brie| iv_sell_in = 2 iv_quality = 0 ) ) ( NEW #( iv_name = |Elixir of the Mongoose| iv_sell_in = 5 iv_quality = 7 ) ) ( NEW #( iv_name = |Sulfuras, Hand of Ragnaros| iv_sell_in = 0 iv_quality = 80 ) ) ( NEW #( iv_name = |Backstage passes to a TAFKAL80ETC concert| iv_sell_in = 15 iv_quality = 20 ) ) ( NEW #( iv_name = |Backstage passes to a TAFKAL80ETC concert| iv_sell_in = 10 iv_quality = 49 ) ) ( NEW #( iv_name = |Backstage passes to a TAFKAL80ETC concert| iv_sell_in = 5 iv_quality = 49 ) ) "This conjured item does not work properly yet ( NEW #( iv_name = |Conjured Mana Cake| iv_sell_in = 3 iv_quality = 6 ) ) ). DATA(lo_app) = NEW lcl_gilded_rose( it_items = lt_items ). DATA(lv_days) = 2. cl_demo_input=>request( EXPORTING text = |Number of Days?| CHANGING field = lv_days ). DO lv_days TIMES. lo_out->next_section( |-------- day { sy-index } --------| ). lo_out->write_text( |Name, Sell_In, Quality| ). LOOP AT lt_items INTO DATA(lo_item). lo_out->write_text( lo_item->description( ) ). ENDLOOP. lo_app->update_quality( ). ENDDO. lo_out->display( ). ENDMETHOD. ENDCLASS. *& Test Code - Currently Broken CLASS ltc_gilded_rose DEFINITION FINAL FOR TESTING RISK LEVEL HARMLESS. PRIVATE SECTION. METHODS: foo FOR TESTING. ENDCLASS. CLASS ltc_gilded_rose IMPLEMENTATION. METHOD foo. DATA(lt_items) = VALUE lcl_gilded_rose=>tt_items( ( NEW #( iv_name = |foo| iv_sell_in = 0 iv_quality = 0 ) ) ). DATA(lo_app) = NEW lcl_gilded_rose( it_items = lt_items ). lo_app->update_quality( ). cl_abap_unit_assert=>assert_equals( act = CAST lcl_item( lt_items[ 1 ] )->mv_name exp = |fixme| ). ENDMETHOD. ENDCLASS. \ No newline at end of file From 028e85b433feb65674eb224e841d8af9921b8038 Mon Sep 17 00:00:00 2001 From: Joel Trottier-Hebert Date: Fri, 18 Mar 2016 22:39:31 -0400 Subject: [PATCH 157/634] removed pubspec.lock --- dart/pubspec.lock | 208 ---------------------------------------------- 1 file changed, 208 deletions(-) delete mode 100644 dart/pubspec.lock diff --git a/dart/pubspec.lock b/dart/pubspec.lock deleted file mode 100644 index dcf8bbd3..00000000 --- a/dart/pubspec.lock +++ /dev/null @@ -1,208 +0,0 @@ -# Generated by pub -# See http://pub.dartlang.org/doc/glossary.html#lockfile -packages: - analyzer: - description: - name: analyzer - url: "https://pub.dartlang.org" - source: hosted - version: "0.27.2" - args: - description: - name: args - url: "https://pub.dartlang.org" - source: hosted - version: "0.13.3+4" - async: - description: - name: async - url: "https://pub.dartlang.org" - source: hosted - version: "1.8.0" - barback: - description: - name: barback - url: "https://pub.dartlang.org" - source: hosted - version: "0.15.2+7" - boolean_selector: - description: - name: boolean_selector - url: "https://pub.dartlang.org" - source: hosted - version: "1.0.0" - charcode: - description: - name: charcode - url: "https://pub.dartlang.org" - source: hosted - version: "1.1.0" - collection: - description: - name: collection - url: "https://pub.dartlang.org" - source: hosted - version: "1.4.0" - crypto: - description: - name: crypto - url: "https://pub.dartlang.org" - source: hosted - version: "0.9.1" - csslib: - description: - name: csslib - url: "https://pub.dartlang.org" - source: hosted - version: "0.12.2" - glob: - description: - name: glob - url: "https://pub.dartlang.org" - source: hosted - version: "1.1.0" - html: - description: - name: html - url: "https://pub.dartlang.org" - source: hosted - version: "0.12.2+1" - http_multi_server: - description: - name: http_multi_server - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.0" - http_parser: - description: - name: http_parser - url: "https://pub.dartlang.org" - source: hosted - version: "2.1.0" - logging: - description: - name: logging - url: "https://pub.dartlang.org" - source: hosted - version: "0.11.2" - matcher: - description: - name: matcher - url: "https://pub.dartlang.org" - source: hosted - version: "0.12.0+1" - mime: - description: - name: mime - url: "https://pub.dartlang.org" - source: hosted - version: "0.9.3" - package_config: - description: - name: package_config - url: "https://pub.dartlang.org" - source: hosted - version: "0.1.3" - path: - description: - name: path - url: "https://pub.dartlang.org" - source: hosted - version: "1.3.9" - plugin: - description: - name: plugin - url: "https://pub.dartlang.org" - source: hosted - version: "0.1.0" - pool: - description: - name: pool - url: "https://pub.dartlang.org" - source: hosted - version: "1.2.1" - pub_semver: - description: - name: pub_semver - url: "https://pub.dartlang.org" - source: hosted - version: "1.2.3" - shelf: - description: - name: shelf - url: "https://pub.dartlang.org" - source: hosted - version: "0.6.5" - shelf_static: - description: - name: shelf_static - url: "https://pub.dartlang.org" - source: hosted - version: "0.2.3+3" - shelf_web_socket: - description: - name: shelf_web_socket - url: "https://pub.dartlang.org" - source: hosted - version: "0.1.0" - source_map_stack_trace: - description: - name: source_map_stack_trace - url: "https://pub.dartlang.org" - source: hosted - version: "1.0.4" - source_maps: - description: - name: source_maps - url: "https://pub.dartlang.org" - source: hosted - version: "0.10.1" - source_span: - description: - name: source_span - url: "https://pub.dartlang.org" - source: hosted - version: "1.2.1" - stack_trace: - description: - name: stack_trace - url: "https://pub.dartlang.org" - source: hosted - version: "1.6.1" - stream_channel: - description: - name: stream_channel - url: "https://pub.dartlang.org" - source: hosted - version: "1.3.1" - string_scanner: - description: - name: string_scanner - url: "https://pub.dartlang.org" - source: hosted - version: "0.1.4+1" - test: - description: - name: test - url: "https://pub.dartlang.org" - source: hosted - version: "0.12.11" - utf: - description: - name: utf - url: "https://pub.dartlang.org" - source: hosted - version: "0.9.0+3" - watcher: - description: - name: watcher - url: "https://pub.dartlang.org" - source: hosted - version: "0.9.7" - yaml: - description: - name: yaml - url: "https://pub.dartlang.org" - source: hosted - version: "2.1.8" -sdk: ">=1.14.0 <1.16.0" From 3ee903062511f9b8ac514c2d188f354069cf3011 Mon Sep 17 00:00:00 2001 From: Brett Rehberg Date: Mon, 21 Mar 2016 10:50:41 -0500 Subject: [PATCH 158/634] remove abap source code --- abap/YY_PAO_GILDED_ROSE.abap | 1 - 1 file changed, 1 deletion(-) delete mode 100644 abap/YY_PAO_GILDED_ROSE.abap diff --git a/abap/YY_PAO_GILDED_ROSE.abap b/abap/YY_PAO_GILDED_ROSE.abap deleted file mode 100644 index 258607d8..00000000 --- a/abap/YY_PAO_GILDED_ROSE.abap +++ /dev/null @@ -1 +0,0 @@ -*&---------------------------------------------------------------------* *& Gilded Rose Requirements Specification *&---------------------------------------------------------------------* *& *& Hi and welcome to team Gilded Rose. As you know, we are a small inn with *& a prime location in a prominent city ran by a friendly innkeeper named *& Allison. We also buy and sell only the finest goods. Unfortunately, our *& goods are constantly degrading in quality as they approach their sell by *& date. We have a system in place that updates our inventory for us. It *& was developed by a no-nonsense type named Leeroy, who has moved on to *& new adventures. Your task is to add the new feature to our system so that *& we can begin selling a new category of items. *& *& First an introduction to our system: *& *& - All items have a Sell In value which denotes the number of *& days we have to sell the item *& - All items have a Quality value which denotes how valuable the item is *& - At the end of each day our system lowers both values for every item *& *& Seems pretty simple, right? Well this is where it gets interesting: *& *& - Once the sell by date has passed, Quality degrades twice as fast *& - The Quality of an item is never negative *& - "Aged Brie" actually increases in Quality the older it gets *& - The Quality of an item is never more than 50 *& - "Sulfuras", being a legendary item, never has to be sold or *& decreases in Quality *& - "Backstage passes", like aged brie, increases in Quality as its *& Sell In value approaches; Quality increases by 2 when there *& are 10 days or less and by 3 when there are 5 days or less *& but Quality drops to 0 after the concert *& *& We have recently signed a supplier of conjured items. This requires an *& update to our system: *& *& - "Conjured" items degrade in Quality twice as fast as normal items *& *& Feel free to make any changes to the Update Quality method and add any new *& code as long as everything still works correctly. However, do not alter *& the Item class directly or Items table attribute as those belong to the *& goblin in the corner who will insta-rage and one-shot you as he doesn't *& believe in shared code ownership (you can make the Update Quality method *& and Items property static if you must, we'll cover for you). *& *& Just for clarification, an item can never have its Quality increase *& above 50, however "Sulfuras" is a legendary item and as such its Quality *& is 80 and it never alters. PROGRAM yy_pao_gilded_rose. *& Production Code - Class Library CLASS lcl_item DEFINITION DEFERRED. CLASS lcl_gilded_rose DEFINITION FINAL. PUBLIC SECTION. TYPES: tt_items TYPE STANDARD TABLE OF REF TO lcl_item WITH EMPTY KEY. METHODS: constructor IMPORTING it_items TYPE tt_items, update_quality. PRIVATE SECTION. DATA: mt_items TYPE tt_items. ENDCLASS. CLASS lcl_item DEFINITION FINAL. PUBLIC SECTION. METHODS: constructor IMPORTING iv_name TYPE string iv_sell_in TYPE i iv_quality TYPE i, description RETURNING VALUE(rv_string) TYPE string. DATA: mv_name TYPE string, mv_sell_in TYPE i, mv_quality TYPE i. ENDCLASS. CLASS lcl_gilded_rose IMPLEMENTATION. METHOD constructor. mt_items = it_items. ENDMETHOD. METHOD update_quality. LOOP AT mt_items INTO DATA(lo_item). IF lo_item->mv_name <> |Aged Brie| AND lo_item->mv_name <> |Backstage passes to a TAFKAL80ETC concert|. IF lo_item->mv_quality > 0. IF lo_item->mv_name <> |Sulfuras, Hand of Ragnaros|. lo_item->mv_quality = lo_item->mv_quality - 1. ENDIF. ENDIF. ELSE. IF lo_item->mv_quality < 50. lo_item->mv_quality = lo_item->mv_quality + 1. IF lo_item->mv_name = |Backstage passes to a TAFKAL80ETC concert|. IF lo_item->mv_sell_in < 11. IF lo_item->mv_quality < 50. lo_item->mv_quality = lo_item->mv_quality + 1. ENDIF. ENDIF. IF lo_item->mv_sell_in < 6. IF lo_item->mv_quality < 50. lo_item->mv_quality = lo_item->mv_quality + 1. ENDIF. ENDIF. ENDIF. ENDIF. ENDIF. IF lo_item->mv_name <> |Sulfuras, Hand of Ragnaros|. lo_item->mv_sell_in = lo_item->mv_sell_in - 1. ENDIF. IF lo_item->mv_sell_in < 0. IF lo_item->mv_name <> |Aged Brie|. IF lo_item->mv_name <> |Backstage passes to a TAFKAL80ETC concert|. IF lo_item->mv_quality > 0. IF lo_item->mv_name <> |Sulfuras, Hand of Ragnaros|. lo_item->mv_quality = lo_item->mv_quality - 1. ENDIF. ENDIF. ELSE. lo_item->mv_quality = lo_item->mv_quality - lo_item->mv_quality. ENDIF. ELSE. IF lo_item->mv_quality < 50. lo_item->mv_quality = lo_item->mv_quality + 1. ENDIF. ENDIF. ENDIF. ENDLOOP. ENDMETHOD. ENDCLASS. CLASS lcl_item IMPLEMENTATION. METHOD constructor. mv_name = iv_name. mv_sell_in = iv_sell_in. mv_quality = iv_quality. ENDMETHOD. METHOD description. rv_string = |{ mv_name }, { mv_sell_in }, { mv_quality }|. ENDMETHOD. ENDCLASS. *& Test Code - Executable Text Test Fixture CLASS lth_texttest_fixture DEFINITION FINAL. PUBLIC SECTION. CLASS-METHODS main. ENDCLASS. CLASS lth_texttest_fixture IMPLEMENTATION. METHOD main. DATA(lo_out) = cl_demo_output=>new( )->write_text( |OMGHAI!| ). DATA(lt_items) = VALUE lcl_gilded_rose=>tt_items( ( NEW #( iv_name = |+5 Dexterity Vest| iv_sell_in = 10 iv_quality = 20 ) ) ( NEW #( iv_name = |Aged Brie| iv_sell_in = 2 iv_quality = 0 ) ) ( NEW #( iv_name = |Elixir of the Mongoose| iv_sell_in = 5 iv_quality = 7 ) ) ( NEW #( iv_name = |Sulfuras, Hand of Ragnaros| iv_sell_in = 0 iv_quality = 80 ) ) ( NEW #( iv_name = |Backstage passes to a TAFKAL80ETC concert| iv_sell_in = 15 iv_quality = 20 ) ) ( NEW #( iv_name = |Backstage passes to a TAFKAL80ETC concert| iv_sell_in = 10 iv_quality = 49 ) ) ( NEW #( iv_name = |Backstage passes to a TAFKAL80ETC concert| iv_sell_in = 5 iv_quality = 49 ) ) "This conjured item does not work properly yet ( NEW #( iv_name = |Conjured Mana Cake| iv_sell_in = 3 iv_quality = 6 ) ) ). DATA(lo_app) = NEW lcl_gilded_rose( it_items = lt_items ). DATA(lv_days) = 2. cl_demo_input=>request( EXPORTING text = |Number of Days?| CHANGING field = lv_days ). DO lv_days TIMES. lo_out->next_section( |-------- day { sy-index } --------| ). lo_out->write_text( |Name, Sell_In, Quality| ). LOOP AT lt_items INTO DATA(lo_item). lo_out->write_text( lo_item->description( ) ). ENDLOOP. lo_app->update_quality( ). ENDDO. lo_out->display( ). ENDMETHOD. ENDCLASS. *& Test Code - Currently Broken CLASS ltc_gilded_rose DEFINITION FINAL FOR TESTING RISK LEVEL HARMLESS. PRIVATE SECTION. METHODS: foo FOR TESTING. ENDCLASS. CLASS ltc_gilded_rose IMPLEMENTATION. METHOD foo. DATA(lt_items) = VALUE lcl_gilded_rose=>tt_items( ( NEW #( iv_name = |foo| iv_sell_in = 0 iv_quality = 0 ) ) ). DATA(lo_app) = NEW lcl_gilded_rose( it_items = lt_items ). lo_app->update_quality( ). cl_abap_unit_assert=>assert_equals( act = CAST lcl_item( lt_items[ 1 ] )->mv_name exp = |fixme| ). ENDMETHOD. ENDCLASS. \ No newline at end of file From 15a4a245a724b9a702bd9720eda7804abfdea6e1 Mon Sep 17 00:00:00 2001 From: Brett Rehberg Date: Mon, 21 Mar 2016 10:57:47 -0500 Subject: [PATCH 159/634] starting code and tests for ABAP --- abap/YY_PAO_GILDED_ROSE.abap | 242 +++++++++++++++++++++++++++++++++++ 1 file changed, 242 insertions(+) create mode 100644 abap/YY_PAO_GILDED_ROSE.abap diff --git a/abap/YY_PAO_GILDED_ROSE.abap b/abap/YY_PAO_GILDED_ROSE.abap new file mode 100644 index 00000000..40e8f985 --- /dev/null +++ b/abap/YY_PAO_GILDED_ROSE.abap @@ -0,0 +1,242 @@ +*&---------------------------------------------------------------------* +*& Gilded Rose Requirements Specification +*&---------------------------------------------------------------------* +*& +*& Hi and welcome to team Gilded Rose. As you know, we are a small inn with +*& a prime location in a prominent city ran by a friendly innkeeper named +*& Allison. We also buy and sell only the finest goods. Unfortunately, our +*& goods are constantly degrading in quality as they approach their sell by +*& date. We have a system in place that updates our inventory for us. It +*& was developed by a no-nonsense type named Leeroy, who has moved on to +*& new adventures. Your task is to add the new feature to our system so that +*& we can begin selling a new category of items. +*& +*& First an introduction to our system: +*& +*& - All items have a Sell In value which denotes the number of +*& days we have to sell the item +*& - All items have a Quality value which denotes how valuable the item is +*& - At the end of each day our system lowers both values for every item +*& +*& Seems pretty simple, right? Well this is where it gets interesting: +*& +*& - Once the sell by date has passed, Quality degrades twice as fast +*& - The Quality of an item is never negative +*& - "Aged Brie" actually increases in Quality the older it gets +*& - The Quality of an item is never more than 50 +*& - "Sulfuras", being a legendary item, never has to be sold or +*& decreases in Quality +*& - "Backstage passes", like aged brie, increases in Quality as its +*& Sell In value approaches; Quality increases by 2 when there +*& are 10 days or less and by 3 when there are 5 days or less +*& but Quality drops to 0 after the concert +*& +*& We have recently signed a supplier of conjured items. This requires an +*& update to our system: +*& +*& - "Conjured" items degrade in Quality twice as fast as normal items +*& +*& Feel free to make any changes to the Update Quality method and add any new +*& code as long as everything still works correctly. However, do not alter +*& the Item class directly or Items table attribute as those belong to the +*& goblin in the corner who will insta-rage and one-shot you as he doesn't +*& believe in shared code ownership (you can make the Update Quality method +*& and Items property static if you must, we'll cover for you). +*& +*& Just for clarification, an item can never have its Quality increase +*& above 50, however "Sulfuras" is a legendary item and as such its Quality +*& is 80 and it never alters. + +PROGRAM yy_pao_gilded_rose. + + +*& Production Code - Class Library +CLASS lcl_item DEFINITION DEFERRED. + +CLASS lcl_gilded_rose DEFINITION FINAL. + PUBLIC SECTION. + TYPES: + tt_items TYPE STANDARD TABLE OF REF TO lcl_item WITH EMPTY KEY. + METHODS: + constructor + IMPORTING it_items TYPE tt_items, + update_quality. + + PRIVATE SECTION. + DATA: + mt_items TYPE tt_items. +ENDCLASS. + +CLASS lcl_item DEFINITION FINAL. + PUBLIC SECTION. + METHODS: + constructor + IMPORTING iv_name TYPE string + iv_sell_in TYPE i + iv_quality TYPE i, + description + RETURNING VALUE(rv_string) TYPE string. + DATA: + mv_name TYPE string, + mv_sell_in TYPE i, + mv_quality TYPE i. +ENDCLASS. + +CLASS lcl_gilded_rose IMPLEMENTATION. + + METHOD constructor. + mt_items = it_items. + ENDMETHOD. + + METHOD update_quality. + + LOOP AT mt_items INTO DATA(lo_item). + IF lo_item->mv_name <> |Aged Brie| AND + lo_item->mv_name <> |Backstage passes to a TAFKAL80ETC concert|. + IF lo_item->mv_quality > 0. + IF lo_item->mv_name <> |Sulfuras, Hand of Ragnaros|. + lo_item->mv_quality = lo_item->mv_quality - 1. + ENDIF. + ENDIF. + ELSE. + IF lo_item->mv_quality < 50. + lo_item->mv_quality = lo_item->mv_quality + 1. + + IF lo_item->mv_name = |Backstage passes to a TAFKAL80ETC concert|. + IF lo_item->mv_sell_in < 11. + IF lo_item->mv_quality < 50. + lo_item->mv_quality = lo_item->mv_quality + 1. + ENDIF. + ENDIF. + + IF lo_item->mv_sell_in < 6. + IF lo_item->mv_quality < 50. + lo_item->mv_quality = lo_item->mv_quality + 1. + ENDIF. + ENDIF. + ENDIF. + ENDIF. + ENDIF. + + IF lo_item->mv_name <> |Sulfuras, Hand of Ragnaros|. + lo_item->mv_sell_in = lo_item->mv_sell_in - 1. + ENDIF. + + IF lo_item->mv_sell_in < 0. + IF lo_item->mv_name <> |Aged Brie|. + IF lo_item->mv_name <> |Backstage passes to a TAFKAL80ETC concert|. + IF lo_item->mv_quality > 0. + IF lo_item->mv_name <> |Sulfuras, Hand of Ragnaros|. + lo_item->mv_quality = lo_item->mv_quality - 1. + ENDIF. + ENDIF. + ELSE. + lo_item->mv_quality = lo_item->mv_quality - lo_item->mv_quality. + ENDIF. + ELSE. + IF lo_item->mv_quality < 50. + lo_item->mv_quality = lo_item->mv_quality + 1. + ENDIF. + ENDIF. + ENDIF. + ENDLOOP. + + ENDMETHOD. + +ENDCLASS. + +CLASS lcl_item IMPLEMENTATION. + + METHOD constructor. + mv_name = iv_name. + mv_sell_in = iv_sell_in. + mv_quality = iv_quality. + ENDMETHOD. + + METHOD description. + rv_string = |{ mv_name }, { mv_sell_in }, { mv_quality }|. + ENDMETHOD. + +ENDCLASS. + + +*& Test Code - Executable Text Test Fixture +CLASS lth_texttest_fixture DEFINITION FINAL. + PUBLIC SECTION. + CLASS-METHODS main. +ENDCLASS. + +CLASS lth_texttest_fixture IMPLEMENTATION. + METHOD main. + DATA(lo_out) = cl_demo_output=>new( )->write_text( |OMGHAI!| ). + + DATA(lt_items) = VALUE lcl_gilded_rose=>tt_items( + ( NEW #( iv_name = |+5 Dexterity Vest| + iv_sell_in = 10 + iv_quality = 20 ) ) + ( NEW #( iv_name = |Aged Brie| + iv_sell_in = 2 + iv_quality = 0 ) ) + ( NEW #( iv_name = |Elixir of the Mongoose| + iv_sell_in = 5 + iv_quality = 7 ) ) + ( NEW #( iv_name = |Sulfuras, Hand of Ragnaros| + iv_sell_in = 0 + iv_quality = 80 ) ) + ( NEW #( iv_name = |Backstage passes to a TAFKAL80ETC concert| + iv_sell_in = 15 + iv_quality = 20 ) ) + ( NEW #( iv_name = |Backstage passes to a TAFKAL80ETC concert| + iv_sell_in = 10 + iv_quality = 49 ) ) + ( NEW #( iv_name = |Backstage passes to a TAFKAL80ETC concert| + iv_sell_in = 5 + iv_quality = 49 ) ) + "This conjured item does not work properly yet + ( NEW #( iv_name = |Conjured Mana Cake| + iv_sell_in = 3 + iv_quality = 6 ) ) ). + + DATA(lo_app) = NEW lcl_gilded_rose( it_items = lt_items ). + + DATA(lv_days) = 2. + cl_demo_input=>request( EXPORTING text = |Number of Days?| + CHANGING field = lv_days ). + + DO lv_days TIMES. + lo_out->next_section( |-------- day { sy-index } --------| ). + lo_out->write_text( |Name, Sell_In, Quality| ). + LOOP AT lt_items INTO DATA(lo_item). + lo_out->write_text( lo_item->description( ) ). + ENDLOOP. + lo_app->update_quality( ). + ENDDO. + + lo_out->display( ). + ENDMETHOD. +ENDCLASS. + + +*& Test Code - Currently Broken +CLASS ltc_gilded_rose DEFINITION FINAL FOR TESTING RISK LEVEL HARMLESS. + PRIVATE SECTION. + METHODS: + foo FOR TESTING. +ENDCLASS. + +CLASS ltc_gilded_rose IMPLEMENTATION. + + METHOD foo. + DATA(lt_items) = VALUE lcl_gilded_rose=>tt_items( ( NEW #( iv_name = |foo| + iv_sell_in = 0 + iv_quality = 0 ) ) ). + + DATA(lo_app) = NEW lcl_gilded_rose( it_items = lt_items ). + lo_app->update_quality( ). + + cl_abap_unit_assert=>assert_equals( + act = CAST lcl_item( lt_items[ 1 ] )->mv_name + exp = |fixme| ). + ENDMETHOD. + +ENDCLASS. From f00e363caafb740727b4cfe375990a20e0dcac1b Mon Sep 17 00:00:00 2001 From: Georg Berky Date: Sat, 14 May 2016 17:31:39 +0200 Subject: [PATCH 160/634] Add Groovy sources and IntelliJ project --- .idea/modules.xml | 3 +- Groovy/.gitignore | 124 ++++++++++++++++++ Groovy/.idea/compiler.xml | 22 ++++ Groovy/.idea/copyright/profiles_settings.xml | 3 + Groovy/.idea/misc.xml | 26 ++++ Groovy/.idea/modules.xml | 8 ++ Groovy/Groovy.iml | 12 ++ Groovy/readme.txt | 8 ++ Groovy/src/com/gildedrose/GildedRose.groovy | 62 +++++++++ .../src/com/gildedrose/GildedRoseTest.groovy | 15 +++ Groovy/src/com/gildedrose/Item.groovy | 21 +++ .../src/com/gildedrose/TexttestFixture.groovy | 32 +++++ 12 files changed, 334 insertions(+), 2 deletions(-) create mode 100644 Groovy/.gitignore create mode 100644 Groovy/.idea/compiler.xml create mode 100644 Groovy/.idea/copyright/profiles_settings.xml create mode 100644 Groovy/.idea/misc.xml create mode 100644 Groovy/.idea/modules.xml create mode 100644 Groovy/Groovy.iml create mode 100644 Groovy/readme.txt create mode 100644 Groovy/src/com/gildedrose/GildedRose.groovy create mode 100644 Groovy/src/com/gildedrose/GildedRoseTest.groovy create mode 100644 Groovy/src/com/gildedrose/Item.groovy create mode 100644 Groovy/src/com/gildedrose/TexttestFixture.groovy diff --git a/.idea/modules.xml b/.idea/modules.xml index 4278bcdd..75acca37 100644 --- a/.idea/modules.xml +++ b/.idea/modules.xml @@ -5,5 +5,4 @@ - - + \ No newline at end of file diff --git a/Groovy/.gitignore b/Groovy/.gitignore new file mode 100644 index 00000000..8f0aaba4 --- /dev/null +++ b/Groovy/.gitignore @@ -0,0 +1,124 @@ + +# Created by https://www.gitignore.io/api/groovy,intellij,eclipse,vim + +#!! ERROR: groovy is undefined. Use list command to see defined gitignore types !!# + +### Intellij ### +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm +# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 + +# User-specific stuff: +.idea/workspace.xml +.idea/tasks.xml +.idea/dictionaries +.idea/vcs.xml +.idea/jsLibraryMappings.xml + +# Sensitive or high-churn files: +.idea/dataSources.ids +.idea/dataSources.xml +.idea/dataSources.local.xml +.idea/sqlDataSources.xml +.idea/dynamic.xml +.idea/uiDesigner.xml + +# Gradle: +.idea/gradle.xml +.idea/libraries + +# Mongo Explorer plugin: +.idea/mongoSettings.xml + +## File-based project format: +*.iws + +## Plugin-specific files: + +# IntelliJ +/out/ + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Crashlytics plugin (for Android Studio and IntelliJ) +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-build.properties +fabric.properties + +### Intellij Patch ### +# Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721 + +# *.iml +# modules.xml + + +### Eclipse ### + +.metadata +bin/ +tmp/ +*.tmp +*.bak +*.swp +*~.nib +local.properties +.settings/ +.loadpath +.recommenders + +# Eclipse Core +.project + +# External tool builders +.externalToolBuilders/ + +# Locally stored "Eclipse launch configurations" +*.launch + +# PyDev specific (Python IDE for Eclipse) +*.pydevproject + +# CDT-specific (C/C++ Development Tooling) +.cproject + +# JDT-specific (Eclipse Java Development Tools) +.classpath + +# Java annotation processor (APT) +.factorypath + +# PDT-specific (PHP Development Tools) +.buildpath + +# sbteclipse plugin +.target + +# Tern plugin +.tern-project + +# TeXlipse plugin +.texlipse + +# STS (Spring Tool Suite) +.springBeans + +# Code Recommenders +.recommenders/ + + +### Vim ### +# swap +[._]*.s[a-w][a-z] +[._]s[a-w][a-z] +# session +Session.vim +# temporary +.netrwhist +*~ +# auto-generated tag files +tags + diff --git a/Groovy/.idea/compiler.xml b/Groovy/.idea/compiler.xml new file mode 100644 index 00000000..96cc43ef --- /dev/null +++ b/Groovy/.idea/compiler.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Groovy/.idea/copyright/profiles_settings.xml b/Groovy/.idea/copyright/profiles_settings.xml new file mode 100644 index 00000000..e7bedf33 --- /dev/null +++ b/Groovy/.idea/copyright/profiles_settings.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/Groovy/.idea/misc.xml b/Groovy/.idea/misc.xml new file mode 100644 index 00000000..c6d8fb73 --- /dev/null +++ b/Groovy/.idea/misc.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Groovy/.idea/modules.xml b/Groovy/.idea/modules.xml new file mode 100644 index 00000000..c1a39855 --- /dev/null +++ b/Groovy/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/Groovy/Groovy.iml b/Groovy/Groovy.iml new file mode 100644 index 00000000..85bea791 --- /dev/null +++ b/Groovy/Groovy.iml @@ -0,0 +1,12 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/Groovy/readme.txt b/Groovy/readme.txt new file mode 100644 index 00000000..1f869aac --- /dev/null +++ b/Groovy/readme.txt @@ -0,0 +1,8 @@ +Welcome to the Groovy Gilded Rose +================================= + +to run the tests, you can either: +- run them from your favorite IDE +- run them from the src/ folder in your shell: + - $ groovy com/gildedrose/GildedRoseTest.groovy + diff --git a/Groovy/src/com/gildedrose/GildedRose.groovy b/Groovy/src/com/gildedrose/GildedRose.groovy new file mode 100644 index 00000000..ba054cb6 --- /dev/null +++ b/Groovy/src/com/gildedrose/GildedRose.groovy @@ -0,0 +1,62 @@ +package com.gildedrose + +class GildedRose { + Item[] items + + GildedRose(Item[] items) { + this.items = items + } + + void updateQuality() { + for (int i = 0; i < items.length; i++) { + if (!items[i].name.equals("Aged Brie") + && !items[i].name.equals("Backstage passes to a TAFKAL80ETC concert")) { + if (items[i].quality > 0) { + if (!items[i].name.equals("Sulfuras, Hand of Ragnaros")) { + items[i].quality = items[i].quality - 1 + } + } + } else { + if (items[i].quality < 50) { + items[i].quality = items[i].quality + 1 + + if (items[i].name.equals("Backstage passes to a TAFKAL80ETC concert")) { + if (items[i].sellIn < 11) { + if (items[i].quality < 50) { + items[i].quality = items[i].quality + 1 + } + } + + if (items[i].sellIn < 6) { + if (items[i].quality < 50) { + items[i].quality = items[i].quality + 1 + } + } + } + } + } + + if (!items[i].name.equals("Sulfuras, Hand of Ragnaros")) { + items[i].sellIn = items[i].sellIn - 1 + } + + if (items[i].sellIn < 0) { + if (!items[i].name.equals("Aged Brie")) { + if (!items[i].name.equals("Backstage passes to a TAFKAL80ETC concert")) { + if (items[i].quality > 0) { + if (!items[i].name.equals("Sulfuras, Hand of Ragnaros")) { + items[i].quality = items[i].quality - 1 + } + } + } else { + items[i].quality = items[i].quality - items[i].quality + } + } else { + if (items[i].quality < 50) { + items[i].quality = items[i].quality + 1 + } + } + } + } + } +} diff --git a/Groovy/src/com/gildedrose/GildedRoseTest.groovy b/Groovy/src/com/gildedrose/GildedRoseTest.groovy new file mode 100644 index 00000000..d96202c0 --- /dev/null +++ b/Groovy/src/com/gildedrose/GildedRoseTest.groovy @@ -0,0 +1,15 @@ +package com.gildedrose + +import org.junit.Test + +class GildedRoseTest { + + @Test + void "foo"() { + def items = [ new Item("foo", 0, 0) ] as Item[] + def app = new GildedRose(items) + app.updateQuality() + assert "fixme" == app.items[0].name + } + +} diff --git a/Groovy/src/com/gildedrose/Item.groovy b/Groovy/src/com/gildedrose/Item.groovy new file mode 100644 index 00000000..c42d6cea --- /dev/null +++ b/Groovy/src/com/gildedrose/Item.groovy @@ -0,0 +1,21 @@ +package com.gildedrose + +class Item { + + String name + + int sellIn + + int quality + + Item(String name, int sellIn, int quality) { + this.name = name + this.sellIn = sellIn + this.quality = quality + } + + @Override + String toString() { + return this.name + ", " + this.sellIn + ", " + this.quality + } +} diff --git a/Groovy/src/com/gildedrose/TexttestFixture.groovy b/Groovy/src/com/gildedrose/TexttestFixture.groovy new file mode 100644 index 00000000..3c8b46e3 --- /dev/null +++ b/Groovy/src/com/gildedrose/TexttestFixture.groovy @@ -0,0 +1,32 @@ +package com.gildedrose + +println("OMGHAI!") + +Item[] items = [ + new Item("+5 Dexterity Vest", 10, 20), + new Item("Aged Brie", 2, 0), + new Item("Elixir of the Mongoose", 5, 7), + new Item("Sulfuras, Hand of Ragnaros", 0, 80), + new Item("Sulfuras, Hand of Ragnaros", -1, 80), + new Item("Backstage passes to a TAFKAL80ETC concert", 15, 20), + new Item("Backstage passes to a TAFKAL80ETC concert", 10, 49), + new Item("Backstage passes to a TAFKAL80ETC concert", 5, 49), + // this conjured item does not work properly yet + new Item("Conjured Mana Cake", 3, 6)] as Item[] + +GildedRose app = new GildedRose(items) + +int days = 2 +if (args.length > 0) { + days = Integer.parseInt(args[0]) + 1 +} + +for (int i = 0; i < days; i++) { + println("-------- day " + i + " --------") + println("name, sellIn, quality") + for (Item item in items) { + println(item) + } + println "" + app.updateQuality() +} From 8f18f8a1f9a07ac7799ff393716ce00a27f8910a Mon Sep 17 00:00:00 2001 From: Georg Berky Date: Sat, 14 May 2016 17:55:42 +0200 Subject: [PATCH 161/634] improve instructions for IDEs --- Groovy/readme.txt | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/Groovy/readme.txt b/Groovy/readme.txt index 1f869aac..664827d7 100644 --- a/Groovy/readme.txt +++ b/Groovy/readme.txt @@ -1,8 +1,17 @@ Welcome to the Groovy Gilded Rose ================================= -to run the tests, you can either: +to run the test, you can either: - run them from your favorite IDE -- run them from the src/ folder in your shell: + - make sure you have installed language support for Groovy + - IntelliJ: + - open project + - choose this folder (Groovy) + - Eclipse: + - new Groovy Project + - choose this folder (Groovy) as the project folder + - add JUnit to build path +- run the test from the src/ folder in your shell: + - $ cd src/ - $ groovy com/gildedrose/GildedRoseTest.groovy From 7bf5e95b5b59c8e5f1735f9451b39b3f08da3b4e Mon Sep 17 00:00:00 2001 From: Sandra Parsick Date: Mon, 23 May 2016 10:52:28 +0200 Subject: [PATCH 162/634] Fix link to blog post see issue #32 --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 2621bb30..6c77f88e 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ This Kata was originally created by Terry Hughes (http://twitter.com/#!/TerryHug I translated the original C# into a few other languages, (with a little help from my friends!), and slightly changed the starting position. This means I've actually done a small amount of refactoring already compared with the original form of the kata, and made it easier to get going with writing tests by giving you one failing unit test to start with. I also added test fixtures for Text-Based approval testing with TextTest (see [the TextTests](https://github.com/emilybache/GildedRose-Refactoring-Kata/tree/master/texttests)) -As Bobby Johnson points out in his article ["Why Most Solutions to Gilded Rose Miss The Bigger Picture"](http://iamnotmyself.com/2012/12/07/why-most-solutions-to-gilded-rose-miss-the-bigger-picture/), it'll actually give you +As Bobby Johnson points out in his article ["Why Most Solutions to Gilded Rose Miss The Bigger Picture"](http://iamnotmyself.com/2012/12/07/why-most-solutions-to-gilded-rose-miss-the-bigger-picture), it'll actually give you better practice at handling a legacy code situation if you do this Kata in the original C#. However, I think this kata is also really useful for practicing writing good tests using different frameworks and approaches, and the small changes I've made help with that. I think it's also interesting to compare what the refactored code and tests look like in different programming languages. From e8446e057ee8c483833d0d6e5a05d1f1da1a3d39 Mon Sep 17 00:00:00 2001 From: Georg Berky Date: Thu, 2 Jun 2016 21:21:32 +0200 Subject: [PATCH 163/634] Common Lisp version by Rainer Joswig --- clisp/gilded-rose.lisp | 140 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 140 insertions(+) create mode 100644 clisp/gilded-rose.lisp diff --git a/clisp/gilded-rose.lisp b/clisp/gilded-rose.lisp new file mode 100644 index 00000000..59143a42 --- /dev/null +++ b/clisp/gilded-rose.lisp @@ -0,0 +1,140 @@ +; Hi and welcome to team Gilded Rose. As you know, we are a small inn +; with a prime location in a prominent city ran by a friendly +; innkeeper named Allison. We also buy and sell only the finest goods. +; Unfortunately, our goods are constantly degrading in quality as they +; approach their sell by date. We have a system in place that updates +; our inventory for us. It was developed by a no-nonsense type named +; Leeroy, who has moved on to new adventures. Your task is to add the +; new feature to our system so that we can begin selling a new +; category of items. +; First an introduction to our system: +; All items have a SellIn value which denotes the number of days we have to sell the item +; All items have a Quality value which denotes how valuable the item is +; At the end of each day our system lowers both values for every item +; Pretty simple, right? Well this is where it gets interesting: +; Once the sell by date has passed, Quality degrades twice as fast +; The Quality of an item is never negative +; "Aged Brie" actually increases in Quality the older it gets +; The Quality of an item is never more than 50 +; "Sulfuras", being a legendary item, never has to be sold or decreases in Quality +; "Backstage passes", like aged brie, increases in Quality as it's +; SellIn value approaches; Quality increases by 2 when there are 10 +; days or less and by 3 when there are 5 days or less but Quality +; drops to 0 after the concert +; We have recently signed a supplier of conjured items. This requires an update to our system: +; "Conjured" items degrade in Quality twice as fast as normal items +; Feel free to make any changes to the UpdateQuality method and add +; any new code as long as everything still works correctly. However, +; do not alter the Item class or Items property as those belong to the +; goblin in the corner who will insta-rage and one-shot you as he +; doesn't believe in shared code ownership (you can make the +; UpdateQuality method and Items property static if you like, we'll +; cover for you). +; Just for clarification, an item can never have its Quality increase +; above 50, however "Sulfuras" is a legendary item and as such its +; Quality is 80 and it never alters. + +; https://github.com/emilybache/GildedRose-Refactoring-Kata + +; Common Lisp version: Rainer Joswig, joswig@lisp.de, 2016 + +; Example from the command line: +; sbcl --script gildedrose.lisp 10 + +;;; ================================================================ +;;; Code + +(defpackage "GILDED-ROSE" + (:use "CL")) + +(in-package "GILDED-ROSE") + + +;;; Class ITEM + +(defclass item () + ((name :initarg :name :type string) + (sell-in :initarg :sell-in :type integer) + (quality :initarg :quality :type integer))) + +(defmethod to-string ((i item)) + (with-slots (name quality sell-in) i + (format nil "~a, ~a, ~a" name sell-in quality))) + +;;; Class GILDED-ROSE + +(defclass gilded-rose () + ((items :initarg :items))) + +(defmethod update-quality ((gr gilded-rose)) + (with-slots (items) gr + (dotimes (i (length items)) + (with-slots (name quality sell-in) + (elt items i) + (if (and (not (equalp name "Aged Brie")) + (not (equalp name "Backstage passes to a TAFKAL80ETC concert"))) + (if (> quality 0) + (if (not (equalp name "Sulfuras, Hand of Ragnaros")) + (setf quality (- quality 1)))) + (when (< quality 50) + (setf quality (+ quality 1)) + (when (equalp name "Backstage passes to a TAFKAL80ETC concert") + (if (< sell-in 11) + (if (< quality 50) + (setf quality (+ quality 1)))) + (if (< sell-in 6) + (if (< quality 50) + (setf quality (+ quality 1))))))) + + (if (not (equalp name "Sulfuras, Hand of Ragnaros")) + (setf sell-in (- sell-in 1))) + + (if (< sell-in 0) + (if (not (equalp name "Aged Brie")) + (if (not (equalp name "Backstage passes to a TAFKAL80ETC concert")) + (if (> quality 0) + (if (not (equalp name "Sulfuras, Hand of Ragnaros")) + (setf quality (- quality 1)))) + (setf quality (- quality quality))) + (if (< quality 50) + (setf quality (+ quality 1))))))))) + +;;; Example + +(defun run-gilded-rose () + (write-line "OMGHAI!") + (let* ((descriptions '(("+5 Dexterity Vest" 10 20) + ("Aged Brie" 2 0) + ("Elixir of the Mongoose" 5 7) + ("Sulfuras, Hand of Ragnaros" 0 80) + ("Sulfuras, Hand of Ragnaros" -1 80) + ("Backstage passes to a TAFKAL80ETC concert" 15 20) + ("Backstage passes to a TAFKAL80ETC concert" 10 49) + ("Backstage passes to a TAFKAL80ETC concert" 5 49) + ;; this conjured item does not work properly yet + ("Conjured Mana Cake" 3 6))) + (items (loop for (name sell-in quality) in descriptions + collect (make-instance 'item + :name name + :sell-in sell-in + :quality quality))) + (app (make-instance 'gilded-rose :items items)) + (days 2)) + #+sbcl + (if (second sb-ext:*posix-argv*) + (setf days (parse-integer (second sb-ext:*posix-argv*)))) + #+lispworks + (if (fourth sys:*line-arguments-list*) + (setf days (parse-integer (fourth sys:*line-arguments-list*)))) + (dotimes (i days) + (format t "-------- day ~a --------~%" i) + (format t "name, sell-in, quality~%") + (dolist (item items) + (write-line (to-string item))) + (terpri) + (update-quality app)))) + +(run-gilded-rose) + +;;; ================================================================ +;;; EOF From ebf7487c70622ea4a248f86482274b0a764ad66a Mon Sep 17 00:00:00 2001 From: emilybache Date: Wed, 8 Jun 2016 07:59:52 +0200 Subject: [PATCH 164/634] added C++ cyber-dojo link --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 6c77f88e..c31395e9 100644 --- a/README.md +++ b/README.md @@ -34,6 +34,7 @@ I've also set this kata up on [cyber-dojo](http://cyber-dojo.org) for several la - [JUnit, Java](http://cyber-dojo.org/forker/fork/751DD02C4C?avatar=snake&tag=4) - [C#](http://cyber-dojo.org/forker/fork/5C5AC766B0?avatar=koala&tag=1) +- [C++](http://cyber-dojo.org/forker/fork/AA86ECBCC9?avatar=rhino&tag=7) - [Ruby](http://cyber-dojo.org/forker/fork/A8943EAF92?avatar=hippo&tag=9) - [RSpec, Ruby](http://cyber-dojo.org/forker/fork/8E58B0AD16?avatar=raccoon&tag=3) - [Python](http://cyber-dojo.org/forker/fork/297041AA7A?avatar=lion&tag=4) From 7cd39905b104a12d389d0202f2fc7ff90089c2b4 Mon Sep 17 00:00:00 2001 From: Sherbakov Oleg Date: Sat, 11 Jun 2016 23:53:18 +0400 Subject: [PATCH 165/634] Added requirements specification in russian language. --- GildedRoseRequirements_ru.txt | 43 +++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 GildedRoseRequirements_ru.txt diff --git a/GildedRoseRequirements_ru.txt b/GildedRoseRequirements_ru.txt new file mode 100644 index 00000000..cdb1355b --- /dev/null +++ b/GildedRoseRequirements_ru.txt @@ -0,0 +1,43 @@ +====================================== +Технические требования «Gilded Rose» +====================================== + +Привет и добро пожаловать в команду «Gilded Rose». Как вы знаете, мы небольшая гостиница удобно расположенная +в известном городе под руководством дружественного управляющего по имени Эллисон. Также мы занимаемся покупкой +и продажей только самых лучших товаров. К несчастью, качество наших товаров постоянно ухудшается по мере приближения +к максимальному сроку хранения. Существует информационная система, которая ведет переучет всех товаров. Система +была разработана рубаха-парнем, по имени Leeroy, который отправился за поисками новых приключений. Ваша задача +заключается в том, чтобы добавить новый функционал в нашу систему, чтобы мы могли начать продавать новую категорию +товаров. + +В общих чертах система работает следующим образом: + + - Все товары имеют свойство «sellIn» (срок хранения), которое обозначает количество + дней в течение которых мы должны продать товар; + - Все товары имеют свойство «Quality» (качество), которое обозначает насколько качественным является товар; + - В конце дня наша система снижает значение обоих свойств для каждого товара. + +Довольно просто, не правда ли? Тут-то и начинается самое интересное: + + - После того, как срок храния прошел, качество товара ухудшается в два раза быстрее; + - Качество товара никогда не может быть отрицательным; + - Для товара «Aged Brie» качество увеличивается пропорционально возрасту; + - Качество товара никогда не может быть больше, чем 50; + - «Sulfuras» является легендарным товаром, поэтому у него нет срока хранения и не подвержен ухудшению качества; + - Качество «Backstage passes» также, как и «Aged Brie», увеличивается по мере приближения к сроку хранения. + Качество увеличивается на 2, когда до истечения срока хранения 10 или менее дней и на 3, + если до истечения 5 или менее дней. При этом качество падает до 0 после даты проведения концерта. + +Недавно мы нашли поставщика магических товаров. Для того, чтобы продавать его товары необходимо обновить нашу +систему следующим образом: + + - «Conjured» товары теряют качество в два раза быстрее, чем обычные товары. + +Не стесняйтесь вносить любые изменения в метод «UpdateQuality» и добавлять любой новый код до тех пор, +пока система работает корректно. Тем не менее, не меняйте класс «Item» или его свойства, так как он принадлежит +сидящему в углу гоблину, который очень яростен и поэтому выстрелит в вас поскольку не верит в принцип +совместного владения кодом (вы можете сделать метод «UpdateQuality» и свойства класса «Item» статическими +если хотите, мы вас прикроем). + +Просто для уточнения, товар никогда не может иметь качество выше чем 50, однако легендарный товар «Sulfuras» +имеет качество 80 и оно никогда не меняется. From 32fb8fd9b84ee343454d42433c89bb411b97bdb2 Mon Sep 17 00:00:00 2001 From: Jacky Shen Date: Mon, 27 Jun 2016 15:23:25 +0800 Subject: [PATCH 166/634] Correct spelling of Chinese translation --- GildedRoseRequirements_zh.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/GildedRoseRequirements_zh.txt b/GildedRoseRequirements_zh.txt index 26b39a51..34564768 100644 --- a/GildedRoseRequirements_zh.txt +++ b/GildedRoseRequirements_zh.txt @@ -27,6 +27,6 @@ Gilded Rose 需求描述 - "Conjured"物品的品质`Quality`下降速度比正常物品快一倍 -请随意对UpdateQuality函数进行修改和添加新代码,只要系统还能正常工作。然而,不要修改Item类或其属性,因为那属于角落里的地精,他会非常愤怒地爆你头,因为他不相信代码共享所有制(如果你愿意,你可以将UpdateQuality方面和Items属性改为静态的,我们会掩护你的)。 +请随意对UpdateQuality()函数进行修改和添加新代码,只要系统还能正常工作。然而,不要修改Item类或其属性,因为那属于角落里的地精,他会非常愤怒地爆你头,因为他不相信代码共享所有制(如果你愿意,你可以将UpdateQuality方法和Items属性改为静态的,我们会掩护你的)。 再次澄清,每种物品的品质不会超过50,然而"Sulfuras"是一个传奇物品,因此它的品质是80且永远不变。 From 08a02157dcc3e4eb07fd2271c3b71b0154d55221 Mon Sep 17 00:00:00 2001 From: Kevin Wittek Date: Tue, 5 Jul 2016 09:47:02 +0200 Subject: [PATCH 167/634] + Add new project with pre-configured Gradle as build tool and Spock as testing framework --- Java - Spock/.gitignore | 3 + Java - Spock/build.gradle | 9 + .../gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 53636 bytes .../gradle/wrapper/gradle-wrapper.properties | 6 + Java - Spock/gradlew | 160 ++++++++++++++++++ Java - Spock/gradlew.bat | 90 ++++++++++ .../main/java/com/gildedrose/GildedRose.java | 62 +++++++ .../src/main/java/com/gildedrose/Item.java | 21 +++ .../java/com/gildedrose/TexttestFixture.java | 37 ++++ .../com/gildedrose/GildedRoseSpec.groovy | 25 +++ 10 files changed, 413 insertions(+) create mode 100644 Java - Spock/.gitignore create mode 100644 Java - Spock/build.gradle create mode 100644 Java - Spock/gradle/wrapper/gradle-wrapper.jar create mode 100644 Java - Spock/gradle/wrapper/gradle-wrapper.properties create mode 100644 Java - Spock/gradlew create mode 100644 Java - Spock/gradlew.bat create mode 100644 Java - Spock/src/main/java/com/gildedrose/GildedRose.java create mode 100644 Java - Spock/src/main/java/com/gildedrose/Item.java create mode 100644 Java - Spock/src/main/java/com/gildedrose/TexttestFixture.java create mode 100644 Java - Spock/src/test/groovy/com/gildedrose/GildedRoseSpec.groovy diff --git a/Java - Spock/.gitignore b/Java - Spock/.gitignore new file mode 100644 index 00000000..cd3d2f4b --- /dev/null +++ b/Java - Spock/.gitignore @@ -0,0 +1,3 @@ +.idea/ +.gradle/ +build/ \ No newline at end of file diff --git a/Java - Spock/build.gradle b/Java - Spock/build.gradle new file mode 100644 index 00000000..f3e0c1c1 --- /dev/null +++ b/Java - Spock/build.gradle @@ -0,0 +1,9 @@ +apply plugin: 'groovy' + +repositories { + mavenCentral() +} + +dependencies { + testCompile 'org.spockframework:spock-core:1.0-groovy-2.4' +} diff --git a/Java - Spock/gradle/wrapper/gradle-wrapper.jar b/Java - Spock/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000000000000000000000000000000000000..941144813d241db74e1bf25b6804c679fbe7f0a3 GIT binary patch literal 53636 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 DXC5Z7 literal 0 HcmV?d00001 diff --git a/Java - Spock/gradle/wrapper/gradle-wrapper.properties b/Java - Spock/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 00000000..29dd2bcf --- /dev/null +++ b/Java - Spock/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +#Tue Jul 05 09:24:35 CEST 2016 +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-2.9-bin.zip diff --git a/Java - Spock/gradlew b/Java - Spock/gradlew new file mode 100644 index 00000000..9d82f789 --- /dev/null +++ b/Java - Spock/gradlew @@ -0,0 +1,160 @@ +#!/usr/bin/env bash + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS="" + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn ( ) { + echo "$*" +} + +die ( ) { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; +esac + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin, switch paths to Windows format before running java +if $cygwin ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + JAVACMD=`cygpath --unix "$JAVACMD"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=$((i+1)) + done + case $i in + (0) set -- ;; + (1) set -- "$args0" ;; + (2) set -- "$args0" "$args1" ;; + (3) set -- "$args0" "$args1" "$args2" ;; + (4) set -- "$args0" "$args1" "$args2" "$args3" ;; + (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules +function splitJvmOpts() { + JVM_OPTS=("$@") +} +eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS +JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" + +exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" diff --git a/Java - Spock/gradlew.bat b/Java - Spock/gradlew.bat new file mode 100644 index 00000000..8a0b282a --- /dev/null +++ b/Java - Spock/gradlew.bat @@ -0,0 +1,90 @@ +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS= + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto init + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto init + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:init +@rem Get command-line arguments, handling Windowz variants + +if not "%OS%" == "Windows_NT" goto win9xME_args +if "%@eval[2+2]" == "4" goto 4NT_args + +:win9xME_args +@rem Slurp the command line arguments. +set CMD_LINE_ARGS= +set _SKIP=2 + +:win9xME_args_slurp +if "x%~1" == "x" goto execute + +set CMD_LINE_ARGS=%* +goto execute + +:4NT_args +@rem Get arguments from the 4NT Shell from JP Software +set CMD_LINE_ARGS=%$ + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/Java - Spock/src/main/java/com/gildedrose/GildedRose.java b/Java - Spock/src/main/java/com/gildedrose/GildedRose.java new file mode 100644 index 00000000..87a3b926 --- /dev/null +++ b/Java - Spock/src/main/java/com/gildedrose/GildedRose.java @@ -0,0 +1,62 @@ +package com.gildedrose; + +class GildedRose { + Item[] items; + + public GildedRose(Item[] items) { + this.items = items; + } + + public void updateQuality() { + for (int i = 0; i < items.length; i++) { + if (!items[i].name.equals("Aged Brie") + && !items[i].name.equals("Backstage passes to a TAFKAL80ETC concert")) { + if (items[i].quality > 0) { + if (!items[i].name.equals("Sulfuras, Hand of Ragnaros")) { + items[i].quality = items[i].quality - 1; + } + } + } else { + if (items[i].quality < 50) { + items[i].quality = items[i].quality + 1; + + if (items[i].name.equals("Backstage passes to a TAFKAL80ETC concert")) { + if (items[i].sellIn < 11) { + if (items[i].quality < 50) { + items[i].quality = items[i].quality + 1; + } + } + + if (items[i].sellIn < 6) { + if (items[i].quality < 50) { + items[i].quality = items[i].quality + 1; + } + } + } + } + } + + if (!items[i].name.equals("Sulfuras, Hand of Ragnaros")) { + items[i].sellIn = items[i].sellIn - 1; + } + + if (items[i].sellIn < 0) { + if (!items[i].name.equals("Aged Brie")) { + if (!items[i].name.equals("Backstage passes to a TAFKAL80ETC concert")) { + if (items[i].quality > 0) { + if (!items[i].name.equals("Sulfuras, Hand of Ragnaros")) { + items[i].quality = items[i].quality - 1; + } + } + } else { + items[i].quality = items[i].quality - items[i].quality; + } + } else { + if (items[i].quality < 50) { + items[i].quality = items[i].quality + 1; + } + } + } + } + } +} diff --git a/Java - Spock/src/main/java/com/gildedrose/Item.java b/Java - Spock/src/main/java/com/gildedrose/Item.java new file mode 100644 index 00000000..465729ec --- /dev/null +++ b/Java - Spock/src/main/java/com/gildedrose/Item.java @@ -0,0 +1,21 @@ +package com.gildedrose; + +public class Item { + + public String name; + + public int sellIn; + + public int quality; + + public Item(String name, int sellIn, int quality) { + this.name = name; + this.sellIn = sellIn; + this.quality = quality; + } + + @Override + public String toString() { + return this.name + ", " + this.sellIn + ", " + this.quality; + } +} diff --git a/Java - Spock/src/main/java/com/gildedrose/TexttestFixture.java b/Java - Spock/src/main/java/com/gildedrose/TexttestFixture.java new file mode 100644 index 00000000..d059c88f --- /dev/null +++ b/Java - Spock/src/main/java/com/gildedrose/TexttestFixture.java @@ -0,0 +1,37 @@ +package com.gildedrose; + +public class TexttestFixture { + public static void main(String[] args) { + System.out.println("OMGHAI!"); + + Item[] items = new Item[] { + new Item("+5 Dexterity Vest", 10, 20), // + new Item("Aged Brie", 2, 0), // + new Item("Elixir of the Mongoose", 5, 7), // + new Item("Sulfuras, Hand of Ragnaros", 0, 80), // + new Item("Sulfuras, Hand of Ragnaros", -1, 80), + new Item("Backstage passes to a TAFKAL80ETC concert", 15, 20), + new Item("Backstage passes to a TAFKAL80ETC concert", 10, 49), + new Item("Backstage passes to a TAFKAL80ETC concert", 5, 49), + // this conjured item does not work properly yet + new Item("Conjured Mana Cake", 3, 6) }; + + GildedRose app = new GildedRose(items); + + int days = 2; + if (args.length > 0) { + days = Integer.parseInt(args[0]) + 1; + } + + for (int i = 0; i < days; i++) { + System.out.println("-------- day " + i + " --------"); + System.out.println("name, sellIn, quality"); + for (Item item : items) { + System.out.println(item); + } + System.out.println(); + app.updateQuality(); + } + } + +} diff --git a/Java - Spock/src/test/groovy/com/gildedrose/GildedRoseSpec.groovy b/Java - Spock/src/test/groovy/com/gildedrose/GildedRoseSpec.groovy new file mode 100644 index 00000000..04276c03 --- /dev/null +++ b/Java - Spock/src/test/groovy/com/gildedrose/GildedRoseSpec.groovy @@ -0,0 +1,25 @@ +package com.gildedrose + +import spock.lang.Specification + +/** + * Spock unit tests. + */ +class GildedRoseSpec extends Specification { + + def "should update quality correctly"() { + + given: "some items" + Item[] items = [new Item("foo", 0, 0)]; + + and: "the application with these items" + GildedRose app = new GildedRose(items); + + when: "updating quality" + app.updateQuality(); + + then: "the quality is correct" + app.items[0].name == "fixme" + } + +} From 4dead49ba8ace2120cbe70e90a14f8b34063481e Mon Sep 17 00:00:00 2001 From: Dani Latorre Date: Tue, 2 Aug 2016 15:02:20 +0200 Subject: [PATCH 168/634] nested formatter was renamed to documentation --- ruby/.rspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ruby/.rspec b/ruby/.rspec index 0d9a0dd8..7438fbe5 100644 --- a/ruby/.rspec +++ b/ruby/.rspec @@ -1,2 +1,2 @@ --colour ---format nested +--format documentation From 778db32d9ebf863faa9bffcd3f0ad16a4a54f192 Mon Sep 17 00:00:00 2001 From: Dani Latorre Date: Tue, 2 Aug 2016 15:03:07 +0200 Subject: [PATCH 169/634] should syntax is deprecated, changed the first test to expect syntax --- ruby/gilded_rose_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ruby/gilded_rose_spec.rb b/ruby/gilded_rose_spec.rb index 9d86c230..269fe1b0 100644 --- a/ruby/gilded_rose_spec.rb +++ b/ruby/gilded_rose_spec.rb @@ -6,7 +6,7 @@ describe GildedRose do it "does not change the name" do items = [Item.new("foo", 0, 0)] GildedRose.new(items).update_quality() - items[0].name.should == "fixme" + expect(items[0].name).to eq "fixme" end end From f713ff10198d44f0e03ceedeb69ff8e358676e97 Mon Sep 17 00:00:00 2001 From: "Marco Beelen (Ximedes)" Date: Fri, 26 Aug 2016 10:55:09 +0200 Subject: [PATCH 170/634] Added Kotlin version of the Gilded Rose Kata --- Kotlin/Kotlin.iml | 22 ++++++++ Kotlin/src/com/gildedrose/GildedRose.kt | 58 ++++++++++++++++++++ Kotlin/src/com/gildedrose/GildedRoseTest.kt | 19 +++++++ Kotlin/src/com/gildedrose/Item.kt | 3 + Kotlin/src/com/gildedrose/TexttestFixture.kt | 36 ++++++++++++ 5 files changed, 138 insertions(+) create mode 100644 Kotlin/Kotlin.iml create mode 100644 Kotlin/src/com/gildedrose/GildedRose.kt create mode 100644 Kotlin/src/com/gildedrose/GildedRoseTest.kt create mode 100644 Kotlin/src/com/gildedrose/Item.kt create mode 100644 Kotlin/src/com/gildedrose/TexttestFixture.kt diff --git a/Kotlin/Kotlin.iml b/Kotlin/Kotlin.iml new file mode 100644 index 00000000..6ee397d4 --- /dev/null +++ b/Kotlin/Kotlin.iml @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Kotlin/src/com/gildedrose/GildedRose.kt b/Kotlin/src/com/gildedrose/GildedRose.kt new file mode 100644 index 00000000..a78cd532 --- /dev/null +++ b/Kotlin/src/com/gildedrose/GildedRose.kt @@ -0,0 +1,58 @@ +package com.gildedrose + +class GildedRose(var items: Array) { + + fun updateQuality() { + for (i in items.indices) { + if (!items[i].name.equals("Aged Brie") && !items[i].name.equals("Backstage passes to a TAFKAL80ETC concert")) { + if (items[i].quality > 0) { + if (!items[i].name.equals("Sulfuras, Hand of Ragnaros")) { + items[i].quality = items[i].quality - 1 + } + } + } else { + if (items[i].quality < 50) { + items[i].quality = items[i].quality + 1 + + if (items[i].name.equals("Backstage passes to a TAFKAL80ETC concert")) { + if (items[i].sellIn < 11) { + if (items[i].quality < 50) { + items[i].quality = items[i].quality + 1 + } + } + + if (items[i].sellIn < 6) { + if (items[i].quality < 50) { + items[i].quality = items[i].quality + 1 + } + } + } + } + } + + if (!items[i].name.equals("Sulfuras, Hand of Ragnaros")) { + items[i].sellIn = items[i].sellIn - 1 + } + + if (items[i].sellIn < 0) { + if (!items[i].name.equals("Aged Brie")) { + if (!items[i].name.equals("Backstage passes to a TAFKAL80ETC concert")) { + if (items[i].quality > 0) { + if (!items[i].name.equals("Sulfuras, Hand of Ragnaros")) { + items[i].quality = items[i].quality - 1 + } + } + } else { + items[i].quality = items[i].quality - items[i].quality + } + } else { + if (items[i].quality < 50) { + items[i].quality = items[i].quality + 1 + } + } + } + } + } + +} + diff --git a/Kotlin/src/com/gildedrose/GildedRoseTest.kt b/Kotlin/src/com/gildedrose/GildedRoseTest.kt new file mode 100644 index 00000000..5515dcdc --- /dev/null +++ b/Kotlin/src/com/gildedrose/GildedRoseTest.kt @@ -0,0 +1,19 @@ +package com.gildedrose + +import org.junit.Assert.* +import org.junit.Test + +class GildedRoseTest { + + @Test fun foo() { + val items = arrayOf(Item("foo", 0, 0)) + val app = GildedRose(items) + app.updateQuality() + assertEquals("fixme", app.items[0].name) + + } + + +} + + diff --git a/Kotlin/src/com/gildedrose/Item.kt b/Kotlin/src/com/gildedrose/Item.kt new file mode 100644 index 00000000..29d714ba --- /dev/null +++ b/Kotlin/src/com/gildedrose/Item.kt @@ -0,0 +1,3 @@ +package com.gildedrose + +data class Item(var name: String, var sellIn: Int, var quality: Int) \ No newline at end of file diff --git a/Kotlin/src/com/gildedrose/TexttestFixture.kt b/Kotlin/src/com/gildedrose/TexttestFixture.kt new file mode 100644 index 00000000..7eeac81e --- /dev/null +++ b/Kotlin/src/com/gildedrose/TexttestFixture.kt @@ -0,0 +1,36 @@ +package com.gildedrose + +fun main(args: Array) { + + println("OMGHAI!") + + val items = arrayOf(Item("+5 Dexterity Vest", 10, 20), // + Item("Aged Brie", 2, 0), // + Item("Elixir of the Mongoose", 5, 7), // + Item("Sulfuras, Hand of Ragnaros", 0, 80), // + Item("Sulfuras, Hand of Ragnaros", -1, 80), + Item("Backstage passes to a TAFKAL80ETC concert", 15, 20), + Item("Backstage passes to a TAFKAL80ETC concert", 10, 49), + Item("Backstage passes to a TAFKAL80ETC concert", 5, 49), + // this conjured item does not work properly yet + Item("Conjured Mana Cake", 3, 6)) + + val app = GildedRose(items) + + var days = 2 + if (args.size > 0) { + days = Integer.parseInt(args[0]) + 1 + } + + for (i in 0..days - 1) { + println("-------- day $i --------") + println("name, sellIn, quality") + for (item in items) { + println(item) + } + println() + app.updateQuality() + } + + +} From bfffd045d2932821500865cd889b3584e6bff297 Mon Sep 17 00:00:00 2001 From: "Marco Beelen (Ximedes)" Date: Fri, 26 Aug 2016 10:58:41 +0200 Subject: [PATCH 171/634] Ignored various idea files --- Kotlin/.gitignore | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 Kotlin/.gitignore diff --git a/Kotlin/.gitignore b/Kotlin/.gitignore new file mode 100644 index 00000000..d2d5712a --- /dev/null +++ b/Kotlin/.gitignore @@ -0,0 +1,3 @@ +.idea/ +out/ +*.class From 9c63a7732a6047a0c17af5d99e1d32444cdb31f3 Mon Sep 17 00:00:00 2001 From: Hamish Rickerby Date: Wed, 21 Sep 2016 20:53:52 +1000 Subject: [PATCH 172/634] Updated for Swift 3 Process enum has been replaced with CommandLine in Swift 3. Changed main.swift to reflect this. --- swift/main.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/swift/main.swift b/swift/main.swift index fb95ee9c..74a29dfe 100644 --- a/swift/main.swift +++ b/swift/main.swift @@ -14,8 +14,8 @@ let items = [ let app = GildedRose(items: items); var days = 2; -if (Process.argc > 1) { - days = Int(Process.arguments[1])! + 1 +if (CommandLine.argc > 1) { + days = Int(CommandLine.arguments[1])! + 1 } From 910e5d8a5972b57b3436d25550beba527b2ea407 Mon Sep 17 00:00:00 2001 From: Hamish Rickerby Date: Fri, 23 Sep 2016 15:04:52 +1000 Subject: [PATCH 173/634] Fixed copy/paste errors in test data - Fixed copy/paste errors in items - Removed unnecessary comment blocks --- swift/main.swift | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/swift/main.swift b/swift/main.swift index 74a29dfe..35cf52b1 100644 --- a/swift/main.swift +++ b/swift/main.swift @@ -1,9 +1,9 @@ let items = [ - Item(name: "+5 Dexterity Vest", sellIn: 10, quality: 20), // - Item(name: "Aged Brie", sellIn: 2, quality: 0), // - Item(name: "Elixir of the Mongoosname: e", sellIn: 5, quality: 7), // - Item(name: "SulfursellIn: as,quality: Hand of Ragnaros", sellIn: 0, quality: 80), // + Item(name: "+5 Dexterity Vest", sellIn: 10, quality: 20), + Item(name: "Aged Brie", sellIn: 2, quality: 0), + Item(name: "Elixir of the Mongoose", sellIn: 5, quality: 7), + Item(name: "Sulfuras, Hand of Ragnaros", sellIn: 0, quality: 80), Item(name: "Sulfuras, Hand of Ragnaros", sellIn: -1, quality: 80), Item(name: "Backstage passes to a TAFKAL80ETC concert", sellIn: 15, quality: 20), Item(name: "Backstage passes to a TAFKAL80ETC concert", sellIn: 10, quality: 49), From 9eeef2450fd1c2f0292a70422994db59e7ac0041 Mon Sep 17 00:00:00 2001 From: Alexander Korling Date: Sat, 15 Oct 2016 16:51:48 +0200 Subject: [PATCH 174/634] Implement a working version of the original code for the kata Why: - The current version isn't implemented properly. Additional information: - This is the result of my local test run (test omitted since they're a part of the kata): GildedRoseTest * test update_quality/1 Aged Brie actually increases in Quality the older it gets * test Backstage passes Quality increases by 2 when there are 10 days or less * test update_quality/1 the quality of an item is never negative * test update_quality/1 degrades the quality when a day passes * test Backstage passes Quality increases by 3 when there are 5 days or less * test update_quality/1 when sell date is passed it degrades twice as fast * test Backstage passes Quality increases by 1 when sell_in is larger than 10 * test update_quality/1 does not change the name * test update_quality/1 The Quality of an item is never more than 50 * test update_quality/1 Sulfuras, being a legendary item, never has to be sold or decreases in Quality * test Backstage passes Quality drops to 0 after the concert 11 tests, 0 failures --- elixir/lib/gilded_rose.ex | 97 ++++++++++++++++++++++++++------------- 1 file changed, 66 insertions(+), 31 deletions(-) diff --git a/elixir/lib/gilded_rose.ex b/elixir/lib/gilded_rose.ex index 20a3796c..7edd8c83 100644 --- a/elixir/lib/gilded_rose.ex +++ b/elixir/lib/gilded_rose.ex @@ -1,48 +1,83 @@ defmodule GildedRose do # Example # update_quality([%Item{name: "Backstage passes to a TAFKAL80ETC concert", sell_in: 9, quality: 1}]) - # => [%Item{name: "Backstage passes to a TAFKAL80ETC concert", sell_in: 9, quality: 3}] + # => [%Item{name: "Backstage passes to a TAFKAL80ETC concert", sell_in: 8, quality: 3}] def update_quality(items) do Enum.map(items, &update_item/1) end def update_item(item) do - cond do - item.quality == 0 -> - item - item.sell_in < 0 && item.name == "Backstage passes to a TAFKAL80ETC concert" -> - %{item | quality: 0} - item.name == "Aged Brie" || item.name == "Backstage passes to a TAFKAL80ETC concert" -> - if item.name == "Backstage passes to a TAFKAL80ETC concert" && item.sell_in > 5 && item.sell_in <= 10 do - %{item | quality: item.quality + 2} - else - if item.name == "Backstage passes to a TAFKAL80ETC concert" && item.sell_in >= 0 && item.sell_in <= 5 do - %{item | quality: item.quality + 3} - else - if item.quality < 50 do - %{item | quality: item.quality + 1} - else - item - end - end - end - item.sell_in < 0 -> - if item.name == "Backstage passes to a TAFKAL80ETC concert" do - %{item | quality: 0} - else - if item.name == "+5 Dexterity Vest" || item.name == "Elixir of the Mongoose" do - %{item | quality: item.quality - 2} + item = cond do + item.name != "Aged Brie" && item.name != "Backstage passes to a TAFKAL80ETC concert" -> + if item.quality > 0 do + if item.name != "Sulfuras, Hand of Ragnaros" do + %{item | quality: item.quality - 1} else item end + else + item end - item.name == "+5 Dexterity Vest" || item.name == "Elixir of the Mongoose" -> - %{item | quality: item.quality - 1} - item.name != "Sulfuras, Hand of Ragnaros" -> - %{item | quality: item.quality - 1} true -> - item + cond do + item.quality < 50 -> + item = %{item | quality: item.quality + 1} + cond do + item.name == "Backstage passes to a TAFKAL80ETC concert" -> + item = cond do + item.sell_in < 11 -> + cond do + item.quality < 50 -> + %{item | quality: item.quality + 1} + true -> item + end + true -> item + end + cond do + item.sell_in < 6 -> + cond do + item.quality < 50 -> + %{item | quality: item.quality + 1} + true -> item + end + true -> item + end + true -> item + end + true -> item + end + end + item = cond do + item.name != "Sulfuras, Hand of Ragnaros" -> + %{item | sell_in: item.sell_in - 1} + true -> item + end + cond do + item.sell_in < 0 -> + cond do + item.name != "Aged Brie" -> + cond do + item.name != "Backstage passes to a TAFKAL80ETC concert" -> + cond do + item.quality > 0 -> + cond do + item.name != "Sulfuras, Hand of Ragnaros" -> + %{item | quality: item.quality - 1} + true -> item + end + true -> item + end + true -> %{item | quality: item.quality - item.quality} + end + true -> + cond do + item.quality < 50 -> + %{item | quality: item.quality + 1} + true -> item + end + end + true -> item end end end From 1d3a8d887e0bc1bad3de59b9c132d900063c3450 Mon Sep 17 00:00:00 2001 From: Maciej Witaszek Date: Thu, 27 Oct 2016 13:08:11 +0700 Subject: [PATCH 175/634] Moved Swift code into package --- swift/.gitignore | 4 ++++ swift/Package.swift | 5 +++++ swift/{ => Sources}/GildedRose.swift | 0 swift/{ => Sources}/Item.swift | 0 swift/{ => Sources}/main.swift | 0 .../GildedRoseTests/GildedRoseTests.swift} | 13 +++++++++---- swift/Tests/LinuxMain.swift | 7 +++++++ swift/Tests/swiftTests/GildedRoseTests.swift | 18 ++++++++++++++++++ 8 files changed, 43 insertions(+), 4 deletions(-) create mode 100644 swift/.gitignore create mode 100644 swift/Package.swift rename swift/{ => Sources}/GildedRose.swift (100%) rename swift/{ => Sources}/Item.swift (100%) rename swift/{ => Sources}/main.swift (100%) rename swift/{GildedRoseTest.swift => Tests/GildedRoseTests/GildedRoseTests.swift} (52%) create mode 100644 swift/Tests/LinuxMain.swift create mode 100644 swift/Tests/swiftTests/GildedRoseTests.swift diff --git a/swift/.gitignore b/swift/.gitignore new file mode 100644 index 00000000..02c08753 --- /dev/null +++ b/swift/.gitignore @@ -0,0 +1,4 @@ +.DS_Store +/.build +/Packages +/*.xcodeproj diff --git a/swift/Package.swift b/swift/Package.swift new file mode 100644 index 00000000..3475d81e --- /dev/null +++ b/swift/Package.swift @@ -0,0 +1,5 @@ +import PackageDescription + +let package = Package( + name: "GildedRose" +) diff --git a/swift/GildedRose.swift b/swift/Sources/GildedRose.swift similarity index 100% rename from swift/GildedRose.swift rename to swift/Sources/GildedRose.swift diff --git a/swift/Item.swift b/swift/Sources/Item.swift similarity index 100% rename from swift/Item.swift rename to swift/Sources/Item.swift diff --git a/swift/main.swift b/swift/Sources/main.swift similarity index 100% rename from swift/main.swift rename to swift/Sources/main.swift diff --git a/swift/GildedRoseTest.swift b/swift/Tests/GildedRoseTests/GildedRoseTests.swift similarity index 52% rename from swift/GildedRoseTest.swift rename to swift/Tests/GildedRoseTests/GildedRoseTests.swift index 66b066dd..67a7c251 100644 --- a/swift/GildedRoseTest.swift +++ b/swift/Tests/GildedRoseTests/GildedRoseTests.swift @@ -1,13 +1,18 @@ - +@testable import GildedRose import XCTest -class GildedRoseTest: XCTestCase { - +class GildedRoseTests: XCTestCase { + func testFoo() { let items = [Item(name: "foo", sellIn: 0, quality: 0)] let app = GildedRose(items: items); app.updateQuality(); XCTAssertEqual("fixme", app.items[0].name); } - + + static var allTests : [(String, (GildedRoseTests) -> () throws -> Void)] { + return [ + ("testFoo", testFoo), + ] + } } diff --git a/swift/Tests/LinuxMain.swift b/swift/Tests/LinuxMain.swift new file mode 100644 index 00000000..b80b87f5 --- /dev/null +++ b/swift/Tests/LinuxMain.swift @@ -0,0 +1,7 @@ +@testable import GildedRoseTestSuit + +import XCTest + +XCTMain([ + testCase(GildedRoseTests.allTests), +]) diff --git a/swift/Tests/swiftTests/GildedRoseTests.swift b/swift/Tests/swiftTests/GildedRoseTests.swift new file mode 100644 index 00000000..67a7c251 --- /dev/null +++ b/swift/Tests/swiftTests/GildedRoseTests.swift @@ -0,0 +1,18 @@ +@testable import GildedRose +import XCTest + +class GildedRoseTests: XCTestCase { + + func testFoo() { + let items = [Item(name: "foo", sellIn: 0, quality: 0)] + let app = GildedRose(items: items); + app.updateQuality(); + XCTAssertEqual("fixme", app.items[0].name); + } + + static var allTests : [(String, (GildedRoseTests) -> () throws -> Void)] { + return [ + ("testFoo", testFoo), + ] + } +} From 9377d612dab8326b1cfa63afffa45ad0d13195b1 Mon Sep 17 00:00:00 2001 From: Caleb Champlin Date: Mon, 7 Nov 2016 15:51:40 -0500 Subject: [PATCH 176/634] Fix filename of gilded-rose.go --- go/{glided-rose.go => gilded-rose.go} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename go/{glided-rose.go => gilded-rose.go} (100%) diff --git a/go/glided-rose.go b/go/gilded-rose.go similarity index 100% rename from go/glided-rose.go rename to go/gilded-rose.go From 3289182cef00c4ea457997cd5ca5e074e182a0db Mon Sep 17 00:00:00 2001 From: Ton van Bart Date: Tue, 29 Nov 2016 12:36:54 +0100 Subject: [PATCH 177/634] reorganized to Maven project structure --- Java/.classpath | 7 - Java/.project | 17 --- Java/Java.iml | 33 ----- Java/pom.xml | 30 +++++ .../main/java/com.gildedrose}/GildedRose.java | 124 +++++++++--------- .../main/java/com.gildedrose}/Item.java | 42 +++--- .../java/com.gildedrose}/GildedRoseTest.java | 34 ++--- .../java/com.gildedrose}/TexttestFixture.java | 74 +++++------ 8 files changed, 167 insertions(+), 194 deletions(-) delete mode 100644 Java/.classpath delete mode 100644 Java/.project delete mode 100644 Java/Java.iml create mode 100644 Java/pom.xml rename Java/{com/gildedrose => src/main/java/com.gildedrose}/GildedRose.java (97%) rename Java/{com/gildedrose => src/main/java/com.gildedrose}/Item.java (94%) rename Java/{com/gildedrose => src/test/java/com.gildedrose}/GildedRoseTest.java (95%) rename Java/{com/gildedrose => src/test/java/com.gildedrose}/TexttestFixture.java (97%) diff --git a/Java/.classpath b/Java/.classpath deleted file mode 100644 index 3f0dbd34..00000000 --- a/Java/.classpath +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/Java/.project b/Java/.project deleted file mode 100644 index a27d7900..00000000 --- a/Java/.project +++ /dev/null @@ -1,17 +0,0 @@ - - - GildedRose.java - - - - - - org.eclipse.jdt.core.javabuilder - - - - - - org.eclipse.jdt.core.javanature - - diff --git a/Java/Java.iml b/Java/Java.iml deleted file mode 100644 index 9d782ec3..00000000 --- a/Java/Java.iml +++ /dev/null @@ -1,33 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Java/pom.xml b/Java/pom.xml new file mode 100644 index 00000000..5fb42af4 --- /dev/null +++ b/Java/pom.xml @@ -0,0 +1,30 @@ + + + + 4.0.0 + + com.gildedrose + gilded-rose-kata + 0.0.1-SNAPSHOT + + + 1.8 + + + + + junit + junit + 4.12 + test + + + + + + + + + \ No newline at end of file diff --git a/Java/com/gildedrose/GildedRose.java b/Java/src/main/java/com.gildedrose/GildedRose.java similarity index 97% rename from Java/com/gildedrose/GildedRose.java rename to Java/src/main/java/com.gildedrose/GildedRose.java index ff5e55ae..87a3b926 100644 --- a/Java/com/gildedrose/GildedRose.java +++ b/Java/src/main/java/com.gildedrose/GildedRose.java @@ -1,62 +1,62 @@ -package com.gildedrose; - -class GildedRose { - Item[] items; - - public GildedRose(Item[] items) { - this.items = items; - } - - public void updateQuality() { - for (int i = 0; i < items.length; i++) { - if (!items[i].name.equals("Aged Brie") - && !items[i].name.equals("Backstage passes to a TAFKAL80ETC concert")) { - if (items[i].quality > 0) { - if (!items[i].name.equals("Sulfuras, Hand of Ragnaros")) { - items[i].quality = items[i].quality - 1; - } - } - } else { - if (items[i].quality < 50) { - items[i].quality = items[i].quality + 1; - - if (items[i].name.equals("Backstage passes to a TAFKAL80ETC concert")) { - if (items[i].sellIn < 11) { - if (items[i].quality < 50) { - items[i].quality = items[i].quality + 1; - } - } - - if (items[i].sellIn < 6) { - if (items[i].quality < 50) { - items[i].quality = items[i].quality + 1; - } - } - } - } - } - - if (!items[i].name.equals("Sulfuras, Hand of Ragnaros")) { - items[i].sellIn = items[i].sellIn - 1; - } - - if (items[i].sellIn < 0) { - if (!items[i].name.equals("Aged Brie")) { - if (!items[i].name.equals("Backstage passes to a TAFKAL80ETC concert")) { - if (items[i].quality > 0) { - if (!items[i].name.equals("Sulfuras, Hand of Ragnaros")) { - items[i].quality = items[i].quality - 1; - } - } - } else { - items[i].quality = items[i].quality - items[i].quality; - } - } else { - if (items[i].quality < 50) { - items[i].quality = items[i].quality + 1; - } - } - } - } - } -} +package com.gildedrose; + +class GildedRose { + Item[] items; + + public GildedRose(Item[] items) { + this.items = items; + } + + public void updateQuality() { + for (int i = 0; i < items.length; i++) { + if (!items[i].name.equals("Aged Brie") + && !items[i].name.equals("Backstage passes to a TAFKAL80ETC concert")) { + if (items[i].quality > 0) { + if (!items[i].name.equals("Sulfuras, Hand of Ragnaros")) { + items[i].quality = items[i].quality - 1; + } + } + } else { + if (items[i].quality < 50) { + items[i].quality = items[i].quality + 1; + + if (items[i].name.equals("Backstage passes to a TAFKAL80ETC concert")) { + if (items[i].sellIn < 11) { + if (items[i].quality < 50) { + items[i].quality = items[i].quality + 1; + } + } + + if (items[i].sellIn < 6) { + if (items[i].quality < 50) { + items[i].quality = items[i].quality + 1; + } + } + } + } + } + + if (!items[i].name.equals("Sulfuras, Hand of Ragnaros")) { + items[i].sellIn = items[i].sellIn - 1; + } + + if (items[i].sellIn < 0) { + if (!items[i].name.equals("Aged Brie")) { + if (!items[i].name.equals("Backstage passes to a TAFKAL80ETC concert")) { + if (items[i].quality > 0) { + if (!items[i].name.equals("Sulfuras, Hand of Ragnaros")) { + items[i].quality = items[i].quality - 1; + } + } + } else { + items[i].quality = items[i].quality - items[i].quality; + } + } else { + if (items[i].quality < 50) { + items[i].quality = items[i].quality + 1; + } + } + } + } + } +} diff --git a/Java/com/gildedrose/Item.java b/Java/src/main/java/com.gildedrose/Item.java similarity index 94% rename from Java/com/gildedrose/Item.java rename to Java/src/main/java/com.gildedrose/Item.java index 65b02c6b..465729ec 100644 --- a/Java/com/gildedrose/Item.java +++ b/Java/src/main/java/com.gildedrose/Item.java @@ -1,21 +1,21 @@ -package com.gildedrose; - -public class Item { - - public String name; - - public int sellIn; - - public int quality; - - public Item(String name, int sellIn, int quality) { - this.name = name; - this.sellIn = sellIn; - this.quality = quality; - } - - @Override - public String toString() { - return this.name + ", " + this.sellIn + ", " + this.quality; - } -} +package com.gildedrose; + +public class Item { + + public String name; + + public int sellIn; + + public int quality; + + public Item(String name, int sellIn, int quality) { + this.name = name; + this.sellIn = sellIn; + this.quality = quality; + } + + @Override + public String toString() { + return this.name + ", " + this.sellIn + ", " + this.quality; + } +} diff --git a/Java/com/gildedrose/GildedRoseTest.java b/Java/src/test/java/com.gildedrose/GildedRoseTest.java similarity index 95% rename from Java/com/gildedrose/GildedRoseTest.java rename to Java/src/test/java/com.gildedrose/GildedRoseTest.java index d679c458..95bfddc4 100644 --- a/Java/com/gildedrose/GildedRoseTest.java +++ b/Java/src/test/java/com.gildedrose/GildedRoseTest.java @@ -1,17 +1,17 @@ -package com.gildedrose; - -import static org.junit.Assert.*; - -import org.junit.Test; - -public class GildedRoseTest { - - @Test - public void foo() { - Item[] items = new Item[] { new Item("foo", 0, 0) }; - GildedRose app = new GildedRose(items); - app.updateQuality(); - assertEquals("fixme", app.items[0].name); - } - -} +package com.gildedrose; + +import static org.junit.Assert.*; + +import org.junit.Test; + +public class GildedRoseTest { + + @Test + public void foo() { + Item[] items = new Item[] { new Item("foo", 0, 0) }; + GildedRose app = new GildedRose(items); + app.updateQuality(); + assertEquals("fixme", app.items[0].name); + } + +} diff --git a/Java/com/gildedrose/TexttestFixture.java b/Java/src/test/java/com.gildedrose/TexttestFixture.java similarity index 97% rename from Java/com/gildedrose/TexttestFixture.java rename to Java/src/test/java/com.gildedrose/TexttestFixture.java index 821b7f1d..d059c88f 100644 --- a/Java/com/gildedrose/TexttestFixture.java +++ b/Java/src/test/java/com.gildedrose/TexttestFixture.java @@ -1,37 +1,37 @@ -package com.gildedrose; - -public class TexttestFixture { - public static void main(String[] args) { - System.out.println("OMGHAI!"); - - Item[] items = new Item[] { - new Item("+5 Dexterity Vest", 10, 20), // - new Item("Aged Brie", 2, 0), // - new Item("Elixir of the Mongoose", 5, 7), // - new Item("Sulfuras, Hand of Ragnaros", 0, 80), // - new Item("Sulfuras, Hand of Ragnaros", -1, 80), - new Item("Backstage passes to a TAFKAL80ETC concert", 15, 20), - new Item("Backstage passes to a TAFKAL80ETC concert", 10, 49), - new Item("Backstage passes to a TAFKAL80ETC concert", 5, 49), - // this conjured item does not work properly yet - new Item("Conjured Mana Cake", 3, 6) }; - - GildedRose app = new GildedRose(items); - - int days = 2; - if (args.length > 0) { - days = Integer.parseInt(args[0]) + 1; - } - - for (int i = 0; i < days; i++) { - System.out.println("-------- day " + i + " --------"); - System.out.println("name, sellIn, quality"); - for (Item item : items) { - System.out.println(item); - } - System.out.println(); - app.updateQuality(); - } - } - -} +package com.gildedrose; + +public class TexttestFixture { + public static void main(String[] args) { + System.out.println("OMGHAI!"); + + Item[] items = new Item[] { + new Item("+5 Dexterity Vest", 10, 20), // + new Item("Aged Brie", 2, 0), // + new Item("Elixir of the Mongoose", 5, 7), // + new Item("Sulfuras, Hand of Ragnaros", 0, 80), // + new Item("Sulfuras, Hand of Ragnaros", -1, 80), + new Item("Backstage passes to a TAFKAL80ETC concert", 15, 20), + new Item("Backstage passes to a TAFKAL80ETC concert", 10, 49), + new Item("Backstage passes to a TAFKAL80ETC concert", 5, 49), + // this conjured item does not work properly yet + new Item("Conjured Mana Cake", 3, 6) }; + + GildedRose app = new GildedRose(items); + + int days = 2; + if (args.length > 0) { + days = Integer.parseInt(args[0]) + 1; + } + + for (int i = 0; i < days; i++) { + System.out.println("-------- day " + i + " --------"); + System.out.println("name, sellIn, quality"); + for (Item item : items) { + System.out.println(item); + } + System.out.println(); + app.updateQuality(); + } + } + +} From 62b3b2fdb9a68e6cef917cc8eb70f9fa9ef5fcef Mon Sep 17 00:00:00 2001 From: Ton van Bart Date: Tue, 29 Nov 2016 12:40:59 +0100 Subject: [PATCH 178/634] added IDEA project files to gitignore, set Maven java version to 8 --- Java/.gitignore | 6 +++++- Java/pom.xml | 7 +++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/Java/.gitignore b/Java/.gitignore index 2d7e4dc5..aab96b4c 100644 --- a/Java/.gitignore +++ b/Java/.gitignore @@ -1 +1,5 @@ -*.class +.idea/ +*.iml +target/ + +.classpath diff --git a/Java/pom.xml b/Java/pom.xml index 5fb42af4..6bc19860 100644 --- a/Java/pom.xml +++ b/Java/pom.xml @@ -24,6 +24,13 @@ + + maven-compiler-plugin + + 1.8 + 1.8 + + From dae358a1314ad3418687a57f5af0e8a80e17456d Mon Sep 17 00:00:00 2001 From: Ton van Bart Date: Thu, 1 Dec 2016 09:37:05 +0100 Subject: [PATCH 179/634] added Eclipse files to .gitignore --- Java/.gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Java/.gitignore b/Java/.gitignore index aab96b4c..69f580e0 100644 --- a/Java/.gitignore +++ b/Java/.gitignore @@ -3,3 +3,6 @@ target/ .classpath +.project +bin/ +.settings/ From 40e7ea75c6dc121b0e1ebbf60ca6cffba5ccd819 Mon Sep 17 00:00:00 2001 From: Ton van Bart Date: Thu, 1 Dec 2016 09:45:34 +0100 Subject: [PATCH 180/634] fixed directory structure --- .../main/java/com/gildedrose/GildedRose.java | 72 +++++++++++++++++++ Java/src/main/java/com/gildedrose/Item.java | 21 ++++++ .../java/com/gildedrose/GildedRoseTest.java | 17 +++++ .../java/com/gildedrose/TexttestFixture.java | 37 ++++++++++ 4 files changed, 147 insertions(+) create mode 100644 Java/src/main/java/com/gildedrose/GildedRose.java create mode 100644 Java/src/main/java/com/gildedrose/Item.java create mode 100644 Java/src/test/java/com/gildedrose/GildedRoseTest.java create mode 100644 Java/src/test/java/com/gildedrose/TexttestFixture.java diff --git a/Java/src/main/java/com/gildedrose/GildedRose.java b/Java/src/main/java/com/gildedrose/GildedRose.java new file mode 100644 index 00000000..a334fa0a --- /dev/null +++ b/Java/src/main/java/com/gildedrose/GildedRose.java @@ -0,0 +1,72 @@ +package com.gildedrose; + +class GildedRose { + Item[] items; + + public GildedRose(Item[] items) { + this.items = items; + } + + public void updateQuality() { + for (int i = 0; i < items.length; i++) { + if (!items[i].name.equals("Aged Brie") + && !items[i].name.equals("Backstage passes to a TAFKAL80ETC concert")) { + if (items[i].quality > 0) { + if (!items[i].name.equals("Sulfuras, Hand of Ragnaros")) { + items[i].quality = items[i].quality - 1; + } + } + } else increaseQuality(items[i]); + + if (!items[i].name.equals("Sulfuras, Hand of Ragnaros")) { + items[i].sellIn = items[i].sellIn - 1; + } + + if (items[i].sellIn < 0) { + handlePastSellin(items[i]); + } + } + } + + private void handlePastSellin(Item item) { + if (!item.name.equals("Aged Brie")) { + if (!item.name.equals("Backstage passes to a TAFKAL80ETC concert")) { + if (item.quality > 0) { + if (!item.name.equals("Sulfuras, Hand of Ragnaros")) { + item.quality = item.quality - 1; + } + } + } else { + item.quality = 0; + } + } else { + if (item.quality < 50) { + item.quality = item.quality + 1; + } + } + } + + private void increaseQuality(Item item) { + if (item.quality < 50) { + item.quality = item.quality + 1; + + if (item.name.equals("Backstage passes to a TAFKAL80ETC concert")) { + handleBackstagePass(item); + } + } + } + + private void handleBackstagePass(Item backstagePass) { + if (backstagePass.sellIn < 11) { + if (backstagePass.quality < 50) { + backstagePass.quality = backstagePass.quality + 1; + } + } + + if (backstagePass.sellIn < 6) { + if (backstagePass.quality < 50) { + backstagePass.quality = backstagePass.quality + 1; + } + } + } +} diff --git a/Java/src/main/java/com/gildedrose/Item.java b/Java/src/main/java/com/gildedrose/Item.java new file mode 100644 index 00000000..465729ec --- /dev/null +++ b/Java/src/main/java/com/gildedrose/Item.java @@ -0,0 +1,21 @@ +package com.gildedrose; + +public class Item { + + public String name; + + public int sellIn; + + public int quality; + + public Item(String name, int sellIn, int quality) { + this.name = name; + this.sellIn = sellIn; + this.quality = quality; + } + + @Override + public String toString() { + return this.name + ", " + this.sellIn + ", " + this.quality; + } +} diff --git a/Java/src/test/java/com/gildedrose/GildedRoseTest.java b/Java/src/test/java/com/gildedrose/GildedRoseTest.java new file mode 100644 index 00000000..95bfddc4 --- /dev/null +++ b/Java/src/test/java/com/gildedrose/GildedRoseTest.java @@ -0,0 +1,17 @@ +package com.gildedrose; + +import static org.junit.Assert.*; + +import org.junit.Test; + +public class GildedRoseTest { + + @Test + public void foo() { + Item[] items = new Item[] { new Item("foo", 0, 0) }; + GildedRose app = new GildedRose(items); + app.updateQuality(); + assertEquals("fixme", app.items[0].name); + } + +} diff --git a/Java/src/test/java/com/gildedrose/TexttestFixture.java b/Java/src/test/java/com/gildedrose/TexttestFixture.java new file mode 100644 index 00000000..d059c88f --- /dev/null +++ b/Java/src/test/java/com/gildedrose/TexttestFixture.java @@ -0,0 +1,37 @@ +package com.gildedrose; + +public class TexttestFixture { + public static void main(String[] args) { + System.out.println("OMGHAI!"); + + Item[] items = new Item[] { + new Item("+5 Dexterity Vest", 10, 20), // + new Item("Aged Brie", 2, 0), // + new Item("Elixir of the Mongoose", 5, 7), // + new Item("Sulfuras, Hand of Ragnaros", 0, 80), // + new Item("Sulfuras, Hand of Ragnaros", -1, 80), + new Item("Backstage passes to a TAFKAL80ETC concert", 15, 20), + new Item("Backstage passes to a TAFKAL80ETC concert", 10, 49), + new Item("Backstage passes to a TAFKAL80ETC concert", 5, 49), + // this conjured item does not work properly yet + new Item("Conjured Mana Cake", 3, 6) }; + + GildedRose app = new GildedRose(items); + + int days = 2; + if (args.length > 0) { + days = Integer.parseInt(args[0]) + 1; + } + + for (int i = 0; i < days; i++) { + System.out.println("-------- day " + i + " --------"); + System.out.println("name, sellIn, quality"); + for (Item item : items) { + System.out.println(item); + } + System.out.println(); + app.updateQuality(); + } + } + +} From 260dc830998d38aaf5961a0e464fdde563a42cb1 Mon Sep 17 00:00:00 2001 From: Ton van Bart Date: Thu, 1 Dec 2016 10:47:47 +0100 Subject: [PATCH 181/634] use java.version property in pom.xml --- Java/pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Java/pom.xml b/Java/pom.xml index 6bc19860..6add3690 100644 --- a/Java/pom.xml +++ b/Java/pom.xml @@ -27,8 +27,8 @@ maven-compiler-plugin - 1.8 - 1.8 + ${java.version} + ${java.version} From 2d353e1da943383df63c60e34d64354b3d2c3eb3 Mon Sep 17 00:00:00 2001 From: Kevin Wittek Date: Mon, 5 Dec 2016 14:57:59 +0100 Subject: [PATCH 182/634] Remove duplicate Java classes --- .../main/java/com.gildedrose/GildedRose.java | 62 ------------------- Java/src/main/java/com.gildedrose/Item.java | 21 ------- .../java/com.gildedrose/GildedRoseTest.java | 17 ----- .../java/com.gildedrose/TexttestFixture.java | 37 ----------- 4 files changed, 137 deletions(-) delete mode 100644 Java/src/main/java/com.gildedrose/GildedRose.java delete mode 100644 Java/src/main/java/com.gildedrose/Item.java delete mode 100644 Java/src/test/java/com.gildedrose/GildedRoseTest.java delete mode 100644 Java/src/test/java/com.gildedrose/TexttestFixture.java diff --git a/Java/src/main/java/com.gildedrose/GildedRose.java b/Java/src/main/java/com.gildedrose/GildedRose.java deleted file mode 100644 index 87a3b926..00000000 --- a/Java/src/main/java/com.gildedrose/GildedRose.java +++ /dev/null @@ -1,62 +0,0 @@ -package com.gildedrose; - -class GildedRose { - Item[] items; - - public GildedRose(Item[] items) { - this.items = items; - } - - public void updateQuality() { - for (int i = 0; i < items.length; i++) { - if (!items[i].name.equals("Aged Brie") - && !items[i].name.equals("Backstage passes to a TAFKAL80ETC concert")) { - if (items[i].quality > 0) { - if (!items[i].name.equals("Sulfuras, Hand of Ragnaros")) { - items[i].quality = items[i].quality - 1; - } - } - } else { - if (items[i].quality < 50) { - items[i].quality = items[i].quality + 1; - - if (items[i].name.equals("Backstage passes to a TAFKAL80ETC concert")) { - if (items[i].sellIn < 11) { - if (items[i].quality < 50) { - items[i].quality = items[i].quality + 1; - } - } - - if (items[i].sellIn < 6) { - if (items[i].quality < 50) { - items[i].quality = items[i].quality + 1; - } - } - } - } - } - - if (!items[i].name.equals("Sulfuras, Hand of Ragnaros")) { - items[i].sellIn = items[i].sellIn - 1; - } - - if (items[i].sellIn < 0) { - if (!items[i].name.equals("Aged Brie")) { - if (!items[i].name.equals("Backstage passes to a TAFKAL80ETC concert")) { - if (items[i].quality > 0) { - if (!items[i].name.equals("Sulfuras, Hand of Ragnaros")) { - items[i].quality = items[i].quality - 1; - } - } - } else { - items[i].quality = items[i].quality - items[i].quality; - } - } else { - if (items[i].quality < 50) { - items[i].quality = items[i].quality + 1; - } - } - } - } - } -} diff --git a/Java/src/main/java/com.gildedrose/Item.java b/Java/src/main/java/com.gildedrose/Item.java deleted file mode 100644 index 465729ec..00000000 --- a/Java/src/main/java/com.gildedrose/Item.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.gildedrose; - -public class Item { - - public String name; - - public int sellIn; - - public int quality; - - public Item(String name, int sellIn, int quality) { - this.name = name; - this.sellIn = sellIn; - this.quality = quality; - } - - @Override - public String toString() { - return this.name + ", " + this.sellIn + ", " + this.quality; - } -} diff --git a/Java/src/test/java/com.gildedrose/GildedRoseTest.java b/Java/src/test/java/com.gildedrose/GildedRoseTest.java deleted file mode 100644 index 95bfddc4..00000000 --- a/Java/src/test/java/com.gildedrose/GildedRoseTest.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.gildedrose; - -import static org.junit.Assert.*; - -import org.junit.Test; - -public class GildedRoseTest { - - @Test - public void foo() { - Item[] items = new Item[] { new Item("foo", 0, 0) }; - GildedRose app = new GildedRose(items); - app.updateQuality(); - assertEquals("fixme", app.items[0].name); - } - -} diff --git a/Java/src/test/java/com.gildedrose/TexttestFixture.java b/Java/src/test/java/com.gildedrose/TexttestFixture.java deleted file mode 100644 index d059c88f..00000000 --- a/Java/src/test/java/com.gildedrose/TexttestFixture.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.gildedrose; - -public class TexttestFixture { - public static void main(String[] args) { - System.out.println("OMGHAI!"); - - Item[] items = new Item[] { - new Item("+5 Dexterity Vest", 10, 20), // - new Item("Aged Brie", 2, 0), // - new Item("Elixir of the Mongoose", 5, 7), // - new Item("Sulfuras, Hand of Ragnaros", 0, 80), // - new Item("Sulfuras, Hand of Ragnaros", -1, 80), - new Item("Backstage passes to a TAFKAL80ETC concert", 15, 20), - new Item("Backstage passes to a TAFKAL80ETC concert", 10, 49), - new Item("Backstage passes to a TAFKAL80ETC concert", 5, 49), - // this conjured item does not work properly yet - new Item("Conjured Mana Cake", 3, 6) }; - - GildedRose app = new GildedRose(items); - - int days = 2; - if (args.length > 0) { - days = Integer.parseInt(args[0]) + 1; - } - - for (int i = 0; i < days; i++) { - System.out.println("-------- day " + i + " --------"); - System.out.println("name, sellIn, quality"); - for (Item item : items) { - System.out.println(item); - } - System.out.println(); - app.updateQuality(); - } - } - -} From d4b3a30334dd68ea689e43e26f7d2b105bfbc492 Mon Sep 17 00:00:00 2001 From: Ton van Bart Date: Mon, 9 Jan 2017 22:31:26 +0100 Subject: [PATCH 183/634] delete package with weird name --- .../main/java/com.gildedrose/GildedRose.java | 62 ------------------- Java/src/main/java/com.gildedrose/Item.java | 21 ------- 2 files changed, 83 deletions(-) delete mode 100644 Java/src/main/java/com.gildedrose/GildedRose.java delete mode 100644 Java/src/main/java/com.gildedrose/Item.java diff --git a/Java/src/main/java/com.gildedrose/GildedRose.java b/Java/src/main/java/com.gildedrose/GildedRose.java deleted file mode 100644 index 87a3b926..00000000 --- a/Java/src/main/java/com.gildedrose/GildedRose.java +++ /dev/null @@ -1,62 +0,0 @@ -package com.gildedrose; - -class GildedRose { - Item[] items; - - public GildedRose(Item[] items) { - this.items = items; - } - - public void updateQuality() { - for (int i = 0; i < items.length; i++) { - if (!items[i].name.equals("Aged Brie") - && !items[i].name.equals("Backstage passes to a TAFKAL80ETC concert")) { - if (items[i].quality > 0) { - if (!items[i].name.equals("Sulfuras, Hand of Ragnaros")) { - items[i].quality = items[i].quality - 1; - } - } - } else { - if (items[i].quality < 50) { - items[i].quality = items[i].quality + 1; - - if (items[i].name.equals("Backstage passes to a TAFKAL80ETC concert")) { - if (items[i].sellIn < 11) { - if (items[i].quality < 50) { - items[i].quality = items[i].quality + 1; - } - } - - if (items[i].sellIn < 6) { - if (items[i].quality < 50) { - items[i].quality = items[i].quality + 1; - } - } - } - } - } - - if (!items[i].name.equals("Sulfuras, Hand of Ragnaros")) { - items[i].sellIn = items[i].sellIn - 1; - } - - if (items[i].sellIn < 0) { - if (!items[i].name.equals("Aged Brie")) { - if (!items[i].name.equals("Backstage passes to a TAFKAL80ETC concert")) { - if (items[i].quality > 0) { - if (!items[i].name.equals("Sulfuras, Hand of Ragnaros")) { - items[i].quality = items[i].quality - 1; - } - } - } else { - items[i].quality = items[i].quality - items[i].quality; - } - } else { - if (items[i].quality < 50) { - items[i].quality = items[i].quality + 1; - } - } - } - } - } -} diff --git a/Java/src/main/java/com.gildedrose/Item.java b/Java/src/main/java/com.gildedrose/Item.java deleted file mode 100644 index 465729ec..00000000 --- a/Java/src/main/java/com.gildedrose/Item.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.gildedrose; - -public class Item { - - public String name; - - public int sellIn; - - public int quality; - - public Item(String name, int sellIn, int quality) { - this.name = name; - this.sellIn = sellIn; - this.quality = quality; - } - - @Override - public String toString() { - return this.name + ", " + this.sellIn + ", " + this.quality; - } -} From b2422cf733fca9803188a7c8f42e7bc5bf63c391 Mon Sep 17 00:00:00 2001 From: Ton van Bart Date: Mon, 9 Jan 2017 22:38:54 +0100 Subject: [PATCH 184/634] delete package with weird name --- .../java/com.gildedrose/GildedRoseTest.java | 17 --------- .../java/com.gildedrose/TexttestFixture.java | 37 ------------------- 2 files changed, 54 deletions(-) delete mode 100644 Java/src/test/java/com.gildedrose/GildedRoseTest.java delete mode 100644 Java/src/test/java/com.gildedrose/TexttestFixture.java diff --git a/Java/src/test/java/com.gildedrose/GildedRoseTest.java b/Java/src/test/java/com.gildedrose/GildedRoseTest.java deleted file mode 100644 index 95bfddc4..00000000 --- a/Java/src/test/java/com.gildedrose/GildedRoseTest.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.gildedrose; - -import static org.junit.Assert.*; - -import org.junit.Test; - -public class GildedRoseTest { - - @Test - public void foo() { - Item[] items = new Item[] { new Item("foo", 0, 0) }; - GildedRose app = new GildedRose(items); - app.updateQuality(); - assertEquals("fixme", app.items[0].name); - } - -} diff --git a/Java/src/test/java/com.gildedrose/TexttestFixture.java b/Java/src/test/java/com.gildedrose/TexttestFixture.java deleted file mode 100644 index d059c88f..00000000 --- a/Java/src/test/java/com.gildedrose/TexttestFixture.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.gildedrose; - -public class TexttestFixture { - public static void main(String[] args) { - System.out.println("OMGHAI!"); - - Item[] items = new Item[] { - new Item("+5 Dexterity Vest", 10, 20), // - new Item("Aged Brie", 2, 0), // - new Item("Elixir of the Mongoose", 5, 7), // - new Item("Sulfuras, Hand of Ragnaros", 0, 80), // - new Item("Sulfuras, Hand of Ragnaros", -1, 80), - new Item("Backstage passes to a TAFKAL80ETC concert", 15, 20), - new Item("Backstage passes to a TAFKAL80ETC concert", 10, 49), - new Item("Backstage passes to a TAFKAL80ETC concert", 5, 49), - // this conjured item does not work properly yet - new Item("Conjured Mana Cake", 3, 6) }; - - GildedRose app = new GildedRose(items); - - int days = 2; - if (args.length > 0) { - days = Integer.parseInt(args[0]) + 1; - } - - for (int i = 0; i < days; i++) { - System.out.println("-------- day " + i + " --------"); - System.out.println("name, sellIn, quality"); - for (Item item : items) { - System.out.println(item); - } - System.out.println(); - app.updateQuality(); - } - } - -} From 560517343930acab681120036de59a041f879174 Mon Sep 17 00:00:00 2001 From: Ton van Bart Date: Wed, 11 Jan 2017 21:32:08 +0100 Subject: [PATCH 185/634] reverted GildedRose to original code --- .../main/java/com/gildedrose/GildedRose.java | 76 ++++++++----------- 1 file changed, 33 insertions(+), 43 deletions(-) diff --git a/Java/src/main/java/com/gildedrose/GildedRose.java b/Java/src/main/java/com/gildedrose/GildedRose.java index a334fa0a..e6feb751 100644 --- a/Java/src/main/java/com/gildedrose/GildedRose.java +++ b/Java/src/main/java/com/gildedrose/GildedRose.java @@ -16,57 +16,47 @@ class GildedRose { items[i].quality = items[i].quality - 1; } } - } else increaseQuality(items[i]); + } else { + if (items[i].quality < 50) { + items[i].quality = items[i].quality + 1; + + if (items[i].name.equals("Backstage passes to a TAFKAL80ETC concert")) { + if (items[i].sellIn < 11) { + if (items[i].quality < 50) { + items[i].quality = items[i].quality + 1; + } + } + + if (items[i].sellIn < 6) { + if (items[i].quality < 50) { + items[i].quality = items[i].quality + 1; + } + } + } + } + } if (!items[i].name.equals("Sulfuras, Hand of Ragnaros")) { items[i].sellIn = items[i].sellIn - 1; } if (items[i].sellIn < 0) { - handlePastSellin(items[i]); - } - } - } - - private void handlePastSellin(Item item) { - if (!item.name.equals("Aged Brie")) { - if (!item.name.equals("Backstage passes to a TAFKAL80ETC concert")) { - if (item.quality > 0) { - if (!item.name.equals("Sulfuras, Hand of Ragnaros")) { - item.quality = item.quality - 1; + if (!items[i].name.equals("Aged Brie")) { + if (!items[i].name.equals("Backstage passes to a TAFKAL80ETC concert")) { + if (items[i].quality > 0) { + if (!items[i].name.equals("Sulfuras, Hand of Ragnaros")) { + items[i].quality = items[i].quality - 1; + } + } + } else { + items[i].quality = items[i].quality - items[i].quality; + } + } else { + if (items[i].quality < 50) { + items[i].quality = items[i].quality + 1; } } - } else { - item.quality = 0; - } - } else { - if (item.quality < 50) { - item.quality = item.quality + 1; } } } - - private void increaseQuality(Item item) { - if (item.quality < 50) { - item.quality = item.quality + 1; - - if (item.name.equals("Backstage passes to a TAFKAL80ETC concert")) { - handleBackstagePass(item); - } - } - } - - private void handleBackstagePass(Item backstagePass) { - if (backstagePass.sellIn < 11) { - if (backstagePass.quality < 50) { - backstagePass.quality = backstagePass.quality + 1; - } - } - - if (backstagePass.sellIn < 6) { - if (backstagePass.quality < 50) { - backstagePass.quality = backstagePass.quality + 1; - } - } - } -} +} \ No newline at end of file From e9aae0d7dbafee71b8bbad16caf325d4f76be932 Mon Sep 17 00:00:00 2001 From: Sergio Minutoli Date: Fri, 10 Feb 2017 18:02:15 -0300 Subject: [PATCH 186/634] Updates examples using ES2015 class syntax --- js/spec/gilded_rose_spec.js | 4 +- js/src/gilded_rose.js | 113 +++++++++++++++++++----------------- 2 files changed, 62 insertions(+), 55 deletions(-) diff --git a/js/spec/gilded_rose_spec.js b/js/spec/gilded_rose_spec.js index 4b60ad34..76cbb268 100644 --- a/js/spec/gilded_rose_spec.js +++ b/js/spec/gilded_rose_spec.js @@ -1,8 +1,8 @@ describe("Gilded Rose", function() { it("should foo", function() { - items = [ new Item("foo", 0, 0) ]; - update_quality(); + const gilgedRose = new Shop([ new Item("foo", 0, 0) ]); + const items = gilgedRose.updateQuality(); expect(items[0].name).toEqual("fixme"); }); diff --git a/js/src/gilded_rose.js b/js/src/gilded_rose.js index 4d28da89..0bbba286 100644 --- a/js/src/gilded_rose.js +++ b/js/src/gilded_rose.js @@ -1,55 +1,62 @@ -function Item(name, sell_in, quality) { - this.name = name; - this.sell_in = sell_in; - this.quality = quality; -} - -var items = [] - -function update_quality() { - for (var i = 0; i < items.length; i++) { - if (items[i].name != 'Aged Brie' && items[i].name != 'Backstage passes to a TAFKAL80ETC concert') { - if (items[i].quality > 0) { - if (items[i].name != 'Sulfuras, Hand of Ragnaros') { - items[i].quality = items[i].quality - 1 - } - } - } else { - if (items[i].quality < 50) { - items[i].quality = items[i].quality + 1 - if (items[i].name == 'Backstage passes to a TAFKAL80ETC concert') { - if (items[i].sell_in < 11) { - if (items[i].quality < 50) { - items[i].quality = items[i].quality + 1 - } - } - if (items[i].sell_in < 6) { - if (items[i].quality < 50) { - items[i].quality = items[i].quality + 1 - } - } - } - } - } - if (items[i].name != 'Sulfuras, Hand of Ragnaros') { - items[i].sell_in = items[i].sell_in - 1; - } - if (items[i].sell_in < 0) { - if (items[i].name != 'Aged Brie') { - if (items[i].name != 'Backstage passes to a TAFKAL80ETC concert') { - if (items[i].quality > 0) { - if (items[i].name != 'Sulfuras, Hand of Ragnaros') { - items[i].quality = items[i].quality - 1 - } - } - } else { - items[i].quality = items[i].quality - items[i].quality - } - } else { - if (items[i].quality < 50) { - items[i].quality = items[i].quality + 1 - } - } - } +class Item { + constructor(name, sellIn, quality){ + this.name = name; + this.sellIn = sellIn; + this.quality = quality; + } +} + +class Shop { + constructor(items=[]){ + this.items = items; + } + updateQuality() { + for (var i = 0; i < this.items.length; i++) { + if (this.items[i].name != 'Aged Brie' && this.items[i].name != 'Backstage passes to a TAFKAL80ETC concert') { + if (this.items[i].quality > 0) { + if (this.items[i].name != 'Sulfuras, Hand of Ragnaros') { + this.items[i].quality = this.items[i].quality - 1 + } + } + } else { + if (this.items[i].quality < 50) { + this.items[i].quality = this.items[i].quality + 1 + if (this.items[i].name == 'Backstage passes to a TAFKAL80ETC concert') { + if (this.items[i].sellIn < 11) { + if (this.items[i].quality < 50) { + this.items[i].quality = this.items[i].quality + 1 + } + } + if (this.items[i].sellIn < 6) { + if (this.items[i].quality < 50) { + this.items[i].quality = this.items[i].quality + 1 + } + } + } + } + } + if (this.items[i].name != 'Sulfuras, Hand of Ragnaros') { + this.items[i].sellIn = this.items[i].sellIn - 1; + } + if (this.items[i].sellIn < 0) { + if (this.items[i].name != 'Aged Brie') { + if (this.items[i].name != 'Backstage passes to a TAFKAL80ETC concert') { + if (this.items[i].quality > 0) { + if (this.items[i].name != 'Sulfuras, Hand of Ragnaros') { + this.items[i].quality = this.items[i].quality - 1 + } + } + } else { + this.items[i].quality = this.items[i].quality - this.items[i].quality + } + } else { + if (this.items[i].quality < 50) { + this.items[i].quality = this.items[i].quality + 1 + } + } + } + } + + return this.items; } } From 2f38071debcada8b6be1466386c2ea60703edc74 Mon Sep 17 00:00:00 2001 From: Sergio Minutoli Date: Fri, 10 Feb 2017 17:52:26 -0300 Subject: [PATCH 187/634] Adds the spanish translation --- GildedRoseRequirements_es.md | 45 ++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 GildedRoseRequirements_es.md diff --git a/GildedRoseRequirements_es.md b/GildedRoseRequirements_es.md new file mode 100644 index 00000000..50b2054d --- /dev/null +++ b/GildedRoseRequirements_es.md @@ -0,0 +1,45 @@ +# Especificaciones de la Rosa Dorada (Gilded Rose) + +Bienvenido al equipo de **Gilded Rose**. +Como quizá sabes, somos una pequeña posada ubicada estratégicamente en una prestigiosa ciudad, atendida por la amable **Allison**. +También compramos y vendemos mercadería de alta calidad. +Por desgracia, nuestra mercadería va bajando de calidad a medida que se aproxima la fecha de venta. + +Tenemos un sistema instalado que actualiza automáticamente el `inventario`. +Este sistema fue desarrollado por un muchacho con poco sentido común llamado Leeroy, que ahora se dedica a nuevas aventuras. +Tu tarea es agregar una nueva característica al sistema para que podamos comenzar a vender una nueva categoría de items. + +## Descripción preliminar + +Pero primero, vamos a introducir el sistema: + +* Todos los artículos (`Item`) tienen una propiedad `sellIn` que denota el número de días que tenemos para venderlo +* Todos los artículos tienen una propiedad `quality` que denota cúan valioso es el artículo +* Al final de cada día, nuestro sistema decrementa ambos valores para cada artículo mediante el método `updateQuality` + +Bastante simple, ¿no? Bueno, ahora es donde se pone interesante: + +* Una vez que la fecha recomendada de venta, la `calidad` se degrada al doble de velocidad +* La `calidad` de un artículo nunca es negativa +* El "Queso Brie envejecido" (`Aged brie`) incrementa su `calidad` a medida que se pone viejo + * Su `calidad` aumenta en `1` unidad cada día + * luego de la `fecha de venta` su `calidad` aumenta `2` unidades por día +* La `calidad` de un artículo nunca es mayor a `50` +* El artículo "Sulfuras" (`Sulfuras`), siendo un artículo legendario, no modifica su `fecha de venta` ni se degrada en `calidad` +* Una "Entrada al Backstage", como el queso brie, incrementa su `calidad` a medida que la `fecha de venta` se aproxima + * si faltan 10 días o menos para el concierto, la `calidad` se incrementa en `2` unidades + * si faltan 5 días o menos, la `calidad` se incrementa en `3` unidades + * luego de la `fecha de venta` la `calidad` cae a `0` + +## El requerimiento + +Hace poco contratamos a un proveedor de artículos *conjurados mágicamente*. +Esto requiere una actualización del sistema: + +* Los artículos `conjurados` degradan su `calidad` al doble de velocidad que los normales + +Siéntete libre de realizar cualquier cambio al mensaje `updateQuality` y agregar el código que sea necesario, mientras que todo siga funcionando correctamente. Sin embargo, **no alteres el objeto `Item` ni sus propiedades** ya que pertenecen al goblin que está en ese rincón, que en un ataque de ira te va a liquidar de un golpe porque no cree en la cultura de código compartido. + +## Notas finales + +Para aclarar: un artículo nunca puede tener una `calidad` superior a `50`, sin embargo las Sulfuras siendo un artículo legendario posee una calidad inmutable de `80`. From 267e4112c4c1cd9a3d0bb897e1233d1560086959 Mon Sep 17 00:00:00 2001 From: David Buschman Date: Sat, 11 Feb 2017 00:05:48 -0700 Subject: [PATCH 188/634] upgraded Scala version to latest versions --- scala/.gitignore | 19 +++++++++++++++++++ scala/build.sbt | 4 ++-- scala/project/.gitignore | 2 ++ scala/project/build.properties | 1 + 4 files changed, 24 insertions(+), 2 deletions(-) create mode 100644 scala/.gitignore create mode 100644 scala/project/.gitignore create mode 100644 scala/project/build.properties diff --git a/scala/.gitignore b/scala/.gitignore new file mode 100644 index 00000000..5534fac1 --- /dev/null +++ b/scala/.gitignore @@ -0,0 +1,19 @@ +/bin/ + +# OSX Finder +.DS_Store + +# IntelliJ +.idea +*.iml + +# Eclipse +.worksheet +.settings +.cache +.cache-main +.cache-tests +.project +.classpath + +target/ diff --git a/scala/build.sbt b/scala/build.sbt index c9cc5d59..6df3d754 100644 --- a/scala/build.sbt +++ b/scala/build.sbt @@ -2,6 +2,6 @@ name := "GildedRose" version := "1.0" -scalaVersion := "2.10.2" +scalaVersion := "2.12.1" -libraryDependencies += "org.scalatest" % "scalatest_2.10" % "2.0" +libraryDependencies += "org.scalatest" %% "scalatest" % "3.0.1" diff --git a/scala/project/.gitignore b/scala/project/.gitignore new file mode 100644 index 00000000..6ba19f7f --- /dev/null +++ b/scala/project/.gitignore @@ -0,0 +1,2 @@ +project/ +target/ diff --git a/scala/project/build.properties b/scala/project/build.properties new file mode 100644 index 00000000..27e88aa1 --- /dev/null +++ b/scala/project/build.properties @@ -0,0 +1 @@ +sbt.version=0.13.13 From 96d9751300a02dc3d6f4dbb6fdaa129a0e397ae3 Mon Sep 17 00:00:00 2001 From: Clay Dowling Date: Fri, 10 Mar 2017 19:22:12 -0500 Subject: [PATCH 189/634] Added C and check library version --- c-check/GildedRose.c | 90 ++++++++++++++++++++++++++++++++++ c-check/GildedRose.h | 9 ++++ c-check/GildedRose.o | Bin 0 -> 5560 bytes c-check/GildedRoseTextTests.c | 43 ++++++++++++++++ c-check/GildedRoseTextTests.o | Bin 0 -> 8408 bytes c-check/Makefile | 46 +++++++++++++++++ c-check/README | 5 ++ c-check/golden_rose | Bin 0 -> 16520 bytes c-check/run-once.sh | 2 + 9 files changed, 195 insertions(+) create mode 100644 c-check/GildedRose.c create mode 100644 c-check/GildedRose.h create mode 100644 c-check/GildedRose.o create mode 100644 c-check/GildedRoseTextTests.c create mode 100644 c-check/GildedRoseTextTests.o create mode 100644 c-check/Makefile create mode 100644 c-check/README create mode 100755 c-check/golden_rose create mode 100755 c-check/run-once.sh diff --git a/c-check/GildedRose.c b/c-check/GildedRose.c new file mode 100644 index 00000000..afb97bbe --- /dev/null +++ b/c-check/GildedRose.c @@ -0,0 +1,90 @@ +#include +#include "GildedRose.h" + +Item* +init_item(Item* item, const char *name, int sellIn, int quality) +{ + item->sellIn = sellIn; + item->quality = quality; + item->name = strdup(name); + + return item; +} + +void update_quality(Item items[], int size) +{ + int i; + + for (i = 0; i < size; i++) + { + if (strcmp(items[i].name, "Aged Brie") && strcmp(items[i].name, "Backstage passes to a TAFKAL80ETC concert")) + { + if (items[i].quality > 0) + { + if (strcmp(items[i].name, "Sulfuras, Hand of Ragnaros")) + { + items[i].quality = items[i].quality - 1; + } + } + } + else + { + if (items[i].quality < 50) + { + items[i].quality = items[i].quality + 1; + + if (!strcmp(items[i].name, "Backstage passes to a TAFKAL80ETC concert")) + { + if (items[i].sellIn < 11) + { + if (items[i].quality < 50) + { + items[i].quality = items[i].quality + 1; + } + } + + if (items[i].sellIn < 6) + { + if (items[i].quality < 50) + { + items[i].quality = items[i].quality + 1; + } + } + } + } + } + + if (strcmp(items[i].name, "Sulfuras, Hand of Ragnaros")) + { + items[i].sellIn = items[i].sellIn - 1; + } + + if (items[i].sellIn < 0) + { + if (strcmp(items[i].name, "Aged Brie")) + { + if (strcmp(items[i].name, "Backstage passes to a TAFKAL80ETC concert")) + { + if (items[i].quality > 0) + { + if (strcmp(items[i].name, "Sulfuras, Hand of Ragnaros")) + { + items[i].quality = items[i].quality - 1; + } + } + } + else + { + items[i].quality = items[i].quality - items[i].quality; + } + } + else + { + if (items[i].quality < 50) + { + items[i].quality = items[i].quality + 1; + } + } + } + } +} diff --git a/c-check/GildedRose.h b/c-check/GildedRose.h new file mode 100644 index 00000000..78d54a08 --- /dev/null +++ b/c-check/GildedRose.h @@ -0,0 +1,9 @@ +typedef struct +{ + char *name; + int sellIn; + int quality; +} Item; + +extern Item* init_item(Item* item, const char *name, int sellIn, int quality); +extern void update_quality(Item items[], int size); diff --git a/c-check/GildedRose.o b/c-check/GildedRose.o new file mode 100644 index 0000000000000000000000000000000000000000..37283c3a3ce974ab2c0ef781f53248918fe66eef GIT binary patch literal 5560 zcmb_fU2Ggz6}~gG-V9l1y|I%tAqb`dN+V_0Yqv2;+Jv>uI^)&8w?uY&Nf;z-(r)d-auwm(^zDt*gZ~ z)OzO+8e^^Ent8!|`He(qvuY}@n=NL3?Lg=!^!M1$yUu?HfK4ku8n4_cbb_m=z6}-F zw5!E<<<``iY5&G-{@Q%`&4k&Sg2Z2IO>{2(MS)tpbG(gFp>yeGU)R(7+lbrvyn;SA zoA6`5YBzR$>E_nOu^2y47D#I`A1C?`Q)(3;O2^^@ajwEB_r!_bE6R0cImRSzkp!C` zfzBsNk8unmfHl%Q96v>IVY|*>i7$Daa&Rs-CSRAo+`OBv^WThDe$RDzy&Mz#YM~Qc zvFrcOm9bP@Qy|oR#kabieE-_5Tg$J$f-x8yEITD*$g4Ub%Z4obv>#Yy$C$T#-|>y0 zZdk_T;K&|eoRe11mE`|sig6XEkS807yk&{R)mx^lIqGS;?R-0GMTC}B@@y$aQhUXd{9aU zs*5&4gmN*o=0bI)Lfj~b)s=^d3%z~rHtrN8uwD6Rx+kTj_olZi-CHtufXzo(Ds>bf z#xx>fOo=W)M|+?ycQNdeJxVHdICWo20cOiKrlpY??Kzl&66{)Mp$IwU6MI7G$M#^1 z!tQSj?Ln)p9qVf9ZpKpgGEEPiAln(W8|_)Qgi-Csk@3OvVsi>V(Rp46fp`giD!T{1 zit^9&Hu&-@5f+QWj#Xdl@2wm1MtNC5nX(hE^(LQXb`#@)BsJoAB`giN!*Dr%FRr|@J znpe2j<4Nrr`;n?anvXQBS~WPs{OVbU9eZHP7(R5!7|8YK@~FH4qvN*RPgc*tNJpTx-r@zEi7>y3DRv9;>?5V49owmAV()uH9Ry&pEwz%{tTj z#kzOepSNtMccZ@931`;AJgROvJ7xt|ubs6kj(wUn=1W%KOpDQvVoF$o;LJQ69LI)- z4;yz+%{1Jg5f&qRpuxGm{(Vw)_yodd2NBBI38pM$l)ar>^kta;4*-roYsOXCV8lRG?z66~+HWE^>z*fa6i|C^9s)q? z4?8|{m^a*kyqzT+j})9efq#W?ydke&6|ItSOIa-Rc{}&0D z^SOkI(1gD5{{rE%{w`Y5LSKycgM`ca!;-!j?^qlCCnSB5&ogcG#m>NMkl*QiG#gI_ z#PKIq_;!*De3tl~68=--_fU`JqmpoBAK~aHy4&&*9A#f7{^Js!qWL%~;V%+DA>kK^ zFG=_^@w80&STXL`3ICF$Pb_;{!jqKGwK^ZV-;Tary!mbz?dI z%v@m2Kp%KvUlEk&)T~_KECehE*QUjCGrrGqUOi;EwB*b*%F|VMwhlU+wq|BL=L?{Q z#sqnmTXxWN1FKbCN0>l7mb2?~a}K-&axOd~a_}U9M+7`7$jGTo&wBVq_+Og=4zQNd z8l%qwexS)OJ({ji2;aT%!?UFTzi3;aEA0Xqz$=u;5$g@_8EkjK4^`+GL5Q~}&}mGQ zm!X5PK#5`f zaE?TLQNQDW$vy#MchZEugiNH#x}OJ`jG_AP$UYyjMN-y11z24EC+UeI>@j~lkLCOy ziSY>#OVXwBLu4XNj$Z>=T>M8VzNiz%$0aGpKL;546nO&4+s`Qe4k@5uMgKTx$Jzgu z0^z$U+Jv3xS3oG}+w`KBS41G|K2P@Y`qjxE=O^04_yzVX5OMXp5Ho*x_6mDZSG>37 vy@$T9k^T3Oi8MKX +#include "GildedRose.h" + +int +print_item(Item *item) +{ + return printf("%s, %d, %d\n", item->name, item->sellIn, item->quality); +} + +int main() +{ + Item items[9]; + int last = 0; + int day; + int index; + + init_item(items + last++, "+5 Dexterity Vest", 10, 20); + init_item(items + last++, "Aged Brie", 2, 0); + init_item(items + last++, "Elixir of the Mongoose", 5, 7); + init_item(items + last++, "Sulfuras, Hand of Ragnaros", 0, 80); + init_item(items + last++, "Sulfuras, Hand of Ragnaros", -1, 80); + init_item(items + last++, "Backstage passes to a TAFKAL80ETC concert", 15, 20); + init_item(items + last++, "Backstage passes to a TAFKAL80ETC concert", 10, 49); + init_item(items + last++, "Backstage passes to a TAFKAL80ETC concert", 5, 49); + // this Conjured item doesn't yet work properly + init_item(items + last++, "Conjured Mana Cake", 3, 6); + + puts("OMGHAI!"); + + for (day = 0; day <= 30; day++) + { + printf("-------- day %d --------\n", day); + printf("name, sellIn, quality\n"); + for(index = 0; index < last; index++) { + print_item(items + index); + } + + printf("\n"); + + update_quality(items, last); + } + return 0; +} diff --git a/c-check/GildedRoseTextTests.o b/c-check/GildedRoseTextTests.o new file mode 100644 index 0000000000000000000000000000000000000000..e1981da6cf3d4fbbed07a94adc15d888405babdb GIT binary patch literal 8408 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 literal 0 HcmV?d00001 diff --git a/c-check/run-once.sh b/c-check/run-once.sh new file mode 100755 index 00000000..4f6b2303 --- /dev/null +++ b/c-check/run-once.sh @@ -0,0 +1,2 @@ +make +./GildedRoseTextTests From b635adc09661d3dbf27607e6423d0fd10cfd7f2c Mon Sep 17 00:00:00 2001 From: Clay Dowling Date: Fri, 10 Mar 2017 19:41:06 -0500 Subject: [PATCH 190/634] Added starting files for check unit tests --- c-check/.gitignore | 3 +++ c-check/Makefile | 2 +- c-check/test_main.c | 31 +++++++++++++++++++++++++++++++ c-check/test_rose.c | 34 ++++++++++++++++++++++++++++++++++ 4 files changed, 69 insertions(+), 1 deletion(-) create mode 100644 c-check/.gitignore create mode 100644 c-check/test_main.c create mode 100644 c-check/test_rose.c diff --git a/c-check/.gitignore b/c-check/.gitignore new file mode 100644 index 00000000..52fc06fa --- /dev/null +++ b/c-check/.gitignore @@ -0,0 +1,3 @@ +*.o +test_gildedrose +golden_rose diff --git a/c-check/Makefile b/c-check/Makefile index 6e077a88..1cc056b7 100644 --- a/c-check/Makefile +++ b/c-check/Makefile @@ -12,7 +12,7 @@ CFLAGS = `pkg-config --cflags check` -g --std=c99 -D_POSIX_C_SOURCE=200809L LIBS = `pkg-config --libs check` # All files that should be part of your test should start with 'test' -TEST_SRC = `ls test*.[c\|h]` +TEST_SRC = $(wildcard test*.[c\|h]) TEST_BASE = $(basename ${TEST_SRC}) TEST_OBJECTS = $(addsuffix .o, ${TEST_BASE}) diff --git a/c-check/test_main.c b/c-check/test_main.c new file mode 100644 index 00000000..0d5a0de0 --- /dev/null +++ b/c-check/test_main.c @@ -0,0 +1,31 @@ +#include +#include +#include + +Suite *suite_rose(void); + +int main(int argc, char **argv) +{ + Suite *s; + SRunner *runner; + int number_fails; + int forkme = 1; + + if (argc > 1 && strcmp(argv[1], "--nofork") == 0) { + forkme = 0; + } + + s = suite_rose(); + runner = srunner_create(s); + + if (0 == forkme) { + srunner_set_fork_status(runner, CK_NOFORK); + } + + srunner_run_all(runner, CK_NORMAL); + number_fails = srunner_ntests_failed(runner); + + srunner_free(runner); + + return number_fails; +} diff --git a/c-check/test_rose.c b/c-check/test_rose.c new file mode 100644 index 00000000..30cc7544 --- /dev/null +++ b/c-check/test_rose.c @@ -0,0 +1,34 @@ +#include +#include "GildedRose.h" + + + +START_TEST(roseFoo) +{ + Item items[1]; + init_item(items, "foo", 0, 0); + update_quality(items, 1); + + ck_assert_str_eq("fixme", items[0].name); +} +END_TEST + +TCase *tcase_rose(void) +{ + TCase *tc; + + tc = tcase_create("gilded-rose"); + tcase_add_test(tc, roseFoo); + + return tc; +} + +Suite *suite_rose(void) +{ + Suite *s; + + s = suite_create("characterization-tests"); + suite_add_tcase(s, tcase_rose()); + + return s; +} From a114047f8310a8b6f611add66db1f5f5848b7a50 Mon Sep 17 00:00:00 2001 From: Clay Dowling Date: Fri, 10 Mar 2017 19:47:41 -0500 Subject: [PATCH 191/634] Updated README to address some specifics of this version of the test --- c-check/README | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/c-check/README b/c-check/README index 2bc1f69b..19c992ed 100644 --- a/c-check/README +++ b/c-check/README @@ -1,5 +1,19 @@ run-once.sh runs your tests once Assumptions: - - make and a C++ compiler (like gcc) is installed on your system and is in the PATH - - The CppUTest framework is in the directory CppUTest + - gnu make and a C compiler (like gcc) is installed on your system and is in the PATH + - The check unit testing library is installed on your system (https://libcheck.github.io/check/) + - pkg-config is installed on your system + +Notes: + - This project is tweaked to run on Linux systems, and will mostly work on Macs. + With some changes to the Makefile it can be made to run on BSD systems with + BSD make. An adventurous person could also get it to run on Windows. + - If you are working on a Macintosh computer you cannot run the memtest target, + because valgrind and OS X don't play nice any more. If you want to use the + memory checker OS X does run docker as a first class citizen. + - If you don't have pkg-config on your system, the only changes you'll need to + make are for the requirements of the check library. Mostly you need to + set the appropriate flags for threaded binaries, which may include some + special linker flags. The libcheck documentation will cover what you need + if you want to undertake this change. From d4c62eb984d273f27d8b4023d9267045cc07e25a Mon Sep 17 00:00:00 2001 From: Clay Dowling Date: Fri, 10 Mar 2017 19:51:08 -0500 Subject: [PATCH 192/634] Updated docs, removed binaries --- c-check/GildedRose.o | Bin 5560 -> 0 bytes c-check/GildedRoseTextTests.o | Bin 8408 -> 0 bytes c-check/README | 4 +++- c-check/run-once.sh | 2 -- 4 files changed, 3 insertions(+), 3 deletions(-) delete mode 100644 c-check/GildedRose.o delete mode 100644 c-check/GildedRoseTextTests.o delete mode 100755 c-check/run-once.sh diff --git a/c-check/GildedRose.o b/c-check/GildedRose.o deleted file mode 100644 index 37283c3a3ce974ab2c0ef781f53248918fe66eef..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5560 zcmb_fU2Ggz6}~gG-V9l1y|I%tAqb`dN+V_0Yqv2;+Jv>uI^)&8w?uY&Nf;z-(r)d-auwm(^zDt*gZ~ z)OzO+8e^^Ent8!|`He(qvuY}@n=NL3?Lg=!^!M1$yUu?HfK4ku8n4_cbb_m=z6}-F zw5!E<<<``iY5&G-{@Q%`&4k&Sg2Z2IO>{2(MS)tpbG(gFp>yeGU)R(7+lbrvyn;SA zoA6`5YBzR$>E_nOu^2y47D#I`A1C?`Q)(3;O2^^@ajwEB_r!_bE6R0cImRSzkp!C` zfzBsNk8unmfHl%Q96v>IVY|*>i7$Daa&Rs-CSRAo+`OBv^WThDe$RDzy&Mz#YM~Qc zvFrcOm9bP@Qy|oR#kabieE-_5Tg$J$f-x8yEITD*$g4Ub%Z4obv>#Yy$C$T#-|>y0 zZdk_T;K&|eoRe11mE`|sig6XEkS807yk&{R)mx^lIqGS;?R-0GMTC}B@@y$aQhUXd{9aU zs*5&4gmN*o=0bI)Lfj~b)s=^d3%z~rHtrN8uwD6Rx+kTj_olZi-CHtufXzo(Ds>bf z#xx>fOo=W)M|+?ycQNdeJxVHdICWo20cOiKrlpY??Kzl&66{)Mp$IwU6MI7G$M#^1 z!tQSj?Ln)p9qVf9ZpKpgGEEPiAln(W8|_)Qgi-Csk@3OvVsi>V(Rp46fp`giD!T{1 zit^9&Hu&-@5f+QWj#Xdl@2wm1MtNC5nX(hE^(LQXb`#@)BsJoAB`giN!*Dr%FRr|@J znpe2j<4Nrr`;n?anvXQBS~WPs{OVbU9eZHP7(R5!7|8YK@~FH4qvN*RPgc*tNJpTx-r@zEi7>y3DRv9;>?5V49owmAV()uH9Ry&pEwz%{tTj z#kzOepSNtMccZ@931`;AJgROvJ7xt|ubs6kj(wUn=1W%KOpDQvVoF$o;LJQ69LI)- z4;yz+%{1Jg5f&qRpuxGm{(Vw)_yodd2NBBI38pM$l)ar>^kta;4*-roYsOXCV8lRG?z66~+HWE^>z*fa6i|C^9s)q? z4?8|{m^a*kyqzT+j})9efq#W?ydke&6|ItSOIa-Rc{}&0D z^SOkI(1gD5{{rE%{w`Y5LSKycgM`ca!;-!j?^qlCCnSB5&ogcG#m>NMkl*QiG#gI_ z#PKIq_;!*De3tl~68=--_fU`JqmpoBAK~aHy4&&*9A#f7{^Js!qWL%~;V%+DA>kK^ zFG=_^@w80&STXL`3ICF$Pb_;{!jqKGwK^ZV-;Tary!mbz?dI z%v@m2Kp%KvUlEk&)T~_KECehE*QUjCGrrGqUOi;EwB*b*%F|VMwhlU+wq|BL=L?{Q z#sqnmTXxWN1FKbCN0>l7mb2?~a}K-&axOd~a_}U9M+7`7$jGTo&wBVq_+Og=4zQNd z8l%qwexS)OJ({ji2;aT%!?UFTzi3;aEA0Xqz$=u;5$g@_8EkjK4^`+GL5Q~}&}mGQ zm!X5PK#5`f zaE?TLQNQDW$vy#MchZEugiNH#x}OJ`jG_AP$UYyjMN-y11z24EC+UeI>@j~lkLCOy ziSY>#OVXwBLu4XNj$Z>=T>M8VzNiz%$0aGpKL;546nO&4+s`Qe4k@5uMgKTx$Jzgu z0^z$U+Jv3xS3oG}+w`KBS41G|K2P@Y`qjxE=O^04_yzVX5OMXp5Ho*x_6mDZSG>37 vy@$T9k^T3Oi8MKXJNssM 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 Date: Fri, 10 Mar 2017 21:08:31 -0500 Subject: [PATCH 193/634] Removed binary that didn't belong here to begin with --- c-check/golden_rose | Bin 16520 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100755 c-check/golden_rose diff --git a/c-check/golden_rose b/c-check/golden_rose deleted file mode 100755 index a7b256d9196e4728c184819fac2be4a123df26a8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16520 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 From 51b045bc1c3dce3dc632f39cc6232b6effb0ef20 Mon Sep 17 00:00:00 2001 From: Clay Dowling Date: Fri, 10 Mar 2017 21:13:06 -0500 Subject: [PATCH 194/634] Added golden rule test --- c-check/golden-rule.sh | 6 + c-check/golden_rule.txt | 373 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 379 insertions(+) create mode 100755 c-check/golden-rule.sh create mode 100644 c-check/golden_rule.txt diff --git a/c-check/golden-rule.sh b/c-check/golden-rule.sh new file mode 100755 index 00000000..2ef885a7 --- /dev/null +++ b/c-check/golden-rule.sh @@ -0,0 +1,6 @@ +#!/bin/bash + +OUTFILE = /tmp/golden-dross.txt + +./golden_rose > $(OUTFILE) +diff $(OUTFILE) golden_rule.txt diff --git a/c-check/golden_rule.txt b/c-check/golden_rule.txt new file mode 100644 index 00000000..a04e48ac --- /dev/null +++ b/c-check/golden_rule.txt @@ -0,0 +1,373 @@ +OMGHAI! +-------- day 0 -------- +name, sellIn, quality ++5 Dexterity Vest, 10, 20 +Aged Brie, 2, 0 +Elixir of the Mongoose, 5, 7 +Sulfuras, Hand of Ragnaros, 0, 80 +Sulfuras, Hand of Ragnaros, -1, 80 +Backstage passes to a TAFKAL80ETC concert, 15, 20 +Backstage passes to a TAFKAL80ETC concert, 10, 49 +Backstage passes to a TAFKAL80ETC concert, 5, 49 +Conjured Mana Cake, 3, 6 + +-------- day 1 -------- +name, sellIn, quality ++5 Dexterity Vest, 9, 19 +Aged Brie, 1, 1 +Elixir of the Mongoose, 4, 6 +Sulfuras, Hand of Ragnaros, 0, 80 +Sulfuras, Hand of Ragnaros, -1, 80 +Backstage passes to a TAFKAL80ETC concert, 14, 21 +Backstage passes to a TAFKAL80ETC concert, 9, 50 +Backstage passes to a TAFKAL80ETC concert, 4, 50 +Conjured Mana Cake, 2, 5 + +-------- day 2 -------- +name, sellIn, quality ++5 Dexterity Vest, 8, 18 +Aged Brie, 0, 2 +Elixir of the Mongoose, 3, 5 +Sulfuras, Hand of Ragnaros, 0, 80 +Sulfuras, Hand of Ragnaros, -1, 80 +Backstage passes to a TAFKAL80ETC concert, 13, 22 +Backstage passes to a TAFKAL80ETC concert, 8, 50 +Backstage passes to a TAFKAL80ETC concert, 3, 50 +Conjured Mana Cake, 1, 4 + +-------- day 3 -------- +name, sellIn, quality ++5 Dexterity Vest, 7, 17 +Aged Brie, -1, 4 +Elixir of the Mongoose, 2, 4 +Sulfuras, Hand of Ragnaros, 0, 80 +Sulfuras, Hand of Ragnaros, -1, 80 +Backstage passes to a TAFKAL80ETC concert, 12, 23 +Backstage passes to a TAFKAL80ETC concert, 7, 50 +Backstage passes to a TAFKAL80ETC concert, 2, 50 +Conjured Mana Cake, 0, 3 + +-------- day 4 -------- +name, sellIn, quality ++5 Dexterity Vest, 6, 16 +Aged Brie, -2, 6 +Elixir of the Mongoose, 1, 3 +Sulfuras, Hand of Ragnaros, 0, 80 +Sulfuras, Hand of Ragnaros, -1, 80 +Backstage passes to a TAFKAL80ETC concert, 11, 24 +Backstage passes to a TAFKAL80ETC concert, 6, 50 +Backstage passes to a TAFKAL80ETC concert, 1, 50 +Conjured Mana Cake, -1, 1 + +-------- day 5 -------- +name, sellIn, quality ++5 Dexterity Vest, 5, 15 +Aged Brie, -3, 8 +Elixir of the Mongoose, 0, 2 +Sulfuras, Hand of Ragnaros, 0, 80 +Sulfuras, Hand of Ragnaros, -1, 80 +Backstage passes to a TAFKAL80ETC concert, 10, 25 +Backstage passes to a TAFKAL80ETC concert, 5, 50 +Backstage passes to a TAFKAL80ETC concert, 0, 50 +Conjured Mana Cake, -2, 0 + +-------- day 6 -------- +name, sellIn, quality ++5 Dexterity Vest, 4, 14 +Aged Brie, -4, 10 +Elixir of the Mongoose, -1, 0 +Sulfuras, Hand of Ragnaros, 0, 80 +Sulfuras, Hand of Ragnaros, -1, 80 +Backstage passes to a TAFKAL80ETC concert, 9, 27 +Backstage passes to a TAFKAL80ETC concert, 4, 50 +Backstage passes to a TAFKAL80ETC concert, -1, 0 +Conjured Mana Cake, -3, 0 + +-------- day 7 -------- +name, sellIn, quality ++5 Dexterity Vest, 3, 13 +Aged Brie, -5, 12 +Elixir of the Mongoose, -2, 0 +Sulfuras, Hand of Ragnaros, 0, 80 +Sulfuras, Hand of Ragnaros, -1, 80 +Backstage passes to a TAFKAL80ETC concert, 8, 29 +Backstage passes to a TAFKAL80ETC concert, 3, 50 +Backstage passes to a TAFKAL80ETC concert, -2, 0 +Conjured Mana Cake, -4, 0 + +-------- day 8 -------- +name, sellIn, quality ++5 Dexterity Vest, 2, 12 +Aged Brie, -6, 14 +Elixir of the Mongoose, -3, 0 +Sulfuras, Hand of Ragnaros, 0, 80 +Sulfuras, Hand of Ragnaros, -1, 80 +Backstage passes to a TAFKAL80ETC concert, 7, 31 +Backstage passes to a TAFKAL80ETC concert, 2, 50 +Backstage passes to a TAFKAL80ETC concert, -3, 0 +Conjured Mana Cake, -5, 0 + +-------- day 9 -------- +name, sellIn, quality ++5 Dexterity Vest, 1, 11 +Aged Brie, -7, 16 +Elixir of the Mongoose, -4, 0 +Sulfuras, Hand of Ragnaros, 0, 80 +Sulfuras, Hand of Ragnaros, -1, 80 +Backstage passes to a TAFKAL80ETC concert, 6, 33 +Backstage passes to a TAFKAL80ETC concert, 1, 50 +Backstage passes to a TAFKAL80ETC concert, -4, 0 +Conjured Mana Cake, -6, 0 + +-------- day 10 -------- +name, sellIn, quality ++5 Dexterity Vest, 0, 10 +Aged Brie, -8, 18 +Elixir of the Mongoose, -5, 0 +Sulfuras, Hand of Ragnaros, 0, 80 +Sulfuras, Hand of Ragnaros, -1, 80 +Backstage passes to a TAFKAL80ETC concert, 5, 35 +Backstage passes to a TAFKAL80ETC concert, 0, 50 +Backstage passes to a TAFKAL80ETC concert, -5, 0 +Conjured Mana Cake, -7, 0 + +-------- day 11 -------- +name, sellIn, quality ++5 Dexterity Vest, -1, 8 +Aged Brie, -9, 20 +Elixir of the Mongoose, -6, 0 +Sulfuras, Hand of Ragnaros, 0, 80 +Sulfuras, Hand of Ragnaros, -1, 80 +Backstage passes to a TAFKAL80ETC concert, 4, 38 +Backstage passes to a TAFKAL80ETC concert, -1, 0 +Backstage passes to a TAFKAL80ETC concert, -6, 0 +Conjured Mana Cake, -8, 0 + +-------- day 12 -------- +name, sellIn, quality ++5 Dexterity Vest, -2, 6 +Aged Brie, -10, 22 +Elixir of the Mongoose, -7, 0 +Sulfuras, Hand of Ragnaros, 0, 80 +Sulfuras, Hand of Ragnaros, -1, 80 +Backstage passes to a TAFKAL80ETC concert, 3, 41 +Backstage passes to a TAFKAL80ETC concert, -2, 0 +Backstage passes to a TAFKAL80ETC concert, -7, 0 +Conjured Mana Cake, -9, 0 + +-------- day 13 -------- +name, sellIn, quality ++5 Dexterity Vest, -3, 4 +Aged Brie, -11, 24 +Elixir of the Mongoose, -8, 0 +Sulfuras, Hand of Ragnaros, 0, 80 +Sulfuras, Hand of Ragnaros, -1, 80 +Backstage passes to a TAFKAL80ETC concert, 2, 44 +Backstage passes to a TAFKAL80ETC concert, -3, 0 +Backstage passes to a TAFKAL80ETC concert, -8, 0 +Conjured Mana Cake, -10, 0 + +-------- day 14 -------- +name, sellIn, quality ++5 Dexterity Vest, -4, 2 +Aged Brie, -12, 26 +Elixir of the Mongoose, -9, 0 +Sulfuras, Hand of Ragnaros, 0, 80 +Sulfuras, Hand of Ragnaros, -1, 80 +Backstage passes to a TAFKAL80ETC concert, 1, 47 +Backstage passes to a TAFKAL80ETC concert, -4, 0 +Backstage passes to a TAFKAL80ETC concert, -9, 0 +Conjured Mana Cake, -11, 0 + +-------- day 15 -------- +name, sellIn, quality ++5 Dexterity Vest, -5, 0 +Aged Brie, -13, 28 +Elixir of the Mongoose, -10, 0 +Sulfuras, Hand of Ragnaros, 0, 80 +Sulfuras, Hand of Ragnaros, -1, 80 +Backstage passes to a TAFKAL80ETC concert, 0, 50 +Backstage passes to a TAFKAL80ETC concert, -5, 0 +Backstage passes to a TAFKAL80ETC concert, -10, 0 +Conjured Mana Cake, -12, 0 + +-------- day 16 -------- +name, sellIn, quality ++5 Dexterity Vest, -6, 0 +Aged Brie, -14, 30 +Elixir of the Mongoose, -11, 0 +Sulfuras, Hand of Ragnaros, 0, 80 +Sulfuras, Hand of Ragnaros, -1, 80 +Backstage passes to a TAFKAL80ETC concert, -1, 0 +Backstage passes to a TAFKAL80ETC concert, -6, 0 +Backstage passes to a TAFKAL80ETC concert, -11, 0 +Conjured Mana Cake, -13, 0 + +-------- day 17 -------- +name, sellIn, quality ++5 Dexterity Vest, -7, 0 +Aged Brie, -15, 32 +Elixir of the Mongoose, -12, 0 +Sulfuras, Hand of Ragnaros, 0, 80 +Sulfuras, Hand of Ragnaros, -1, 80 +Backstage passes to a TAFKAL80ETC concert, -2, 0 +Backstage passes to a TAFKAL80ETC concert, -7, 0 +Backstage passes to a TAFKAL80ETC concert, -12, 0 +Conjured Mana Cake, -14, 0 + +-------- day 18 -------- +name, sellIn, quality ++5 Dexterity Vest, -8, 0 +Aged Brie, -16, 34 +Elixir of the Mongoose, -13, 0 +Sulfuras, Hand of Ragnaros, 0, 80 +Sulfuras, Hand of Ragnaros, -1, 80 +Backstage passes to a TAFKAL80ETC concert, -3, 0 +Backstage passes to a TAFKAL80ETC concert, -8, 0 +Backstage passes to a TAFKAL80ETC concert, -13, 0 +Conjured Mana Cake, -15, 0 + +-------- day 19 -------- +name, sellIn, quality ++5 Dexterity Vest, -9, 0 +Aged Brie, -17, 36 +Elixir of the Mongoose, -14, 0 +Sulfuras, Hand of Ragnaros, 0, 80 +Sulfuras, Hand of Ragnaros, -1, 80 +Backstage passes to a TAFKAL80ETC concert, -4, 0 +Backstage passes to a TAFKAL80ETC concert, -9, 0 +Backstage passes to a TAFKAL80ETC concert, -14, 0 +Conjured Mana Cake, -16, 0 + +-------- day 20 -------- +name, sellIn, quality ++5 Dexterity Vest, -10, 0 +Aged Brie, -18, 38 +Elixir of the Mongoose, -15, 0 +Sulfuras, Hand of Ragnaros, 0, 80 +Sulfuras, Hand of Ragnaros, -1, 80 +Backstage passes to a TAFKAL80ETC concert, -5, 0 +Backstage passes to a TAFKAL80ETC concert, -10, 0 +Backstage passes to a TAFKAL80ETC concert, -15, 0 +Conjured Mana Cake, -17, 0 + +-------- day 21 -------- +name, sellIn, quality ++5 Dexterity Vest, -11, 0 +Aged Brie, -19, 40 +Elixir of the Mongoose, -16, 0 +Sulfuras, Hand of Ragnaros, 0, 80 +Sulfuras, Hand of Ragnaros, -1, 80 +Backstage passes to a TAFKAL80ETC concert, -6, 0 +Backstage passes to a TAFKAL80ETC concert, -11, 0 +Backstage passes to a TAFKAL80ETC concert, -16, 0 +Conjured Mana Cake, -18, 0 + +-------- day 22 -------- +name, sellIn, quality ++5 Dexterity Vest, -12, 0 +Aged Brie, -20, 42 +Elixir of the Mongoose, -17, 0 +Sulfuras, Hand of Ragnaros, 0, 80 +Sulfuras, Hand of Ragnaros, -1, 80 +Backstage passes to a TAFKAL80ETC concert, -7, 0 +Backstage passes to a TAFKAL80ETC concert, -12, 0 +Backstage passes to a TAFKAL80ETC concert, -17, 0 +Conjured Mana Cake, -19, 0 + +-------- day 23 -------- +name, sellIn, quality ++5 Dexterity Vest, -13, 0 +Aged Brie, -21, 44 +Elixir of the Mongoose, -18, 0 +Sulfuras, Hand of Ragnaros, 0, 80 +Sulfuras, Hand of Ragnaros, -1, 80 +Backstage passes to a TAFKAL80ETC concert, -8, 0 +Backstage passes to a TAFKAL80ETC concert, -13, 0 +Backstage passes to a TAFKAL80ETC concert, -18, 0 +Conjured Mana Cake, -20, 0 + +-------- day 24 -------- +name, sellIn, quality ++5 Dexterity Vest, -14, 0 +Aged Brie, -22, 46 +Elixir of the Mongoose, -19, 0 +Sulfuras, Hand of Ragnaros, 0, 80 +Sulfuras, Hand of Ragnaros, -1, 80 +Backstage passes to a TAFKAL80ETC concert, -9, 0 +Backstage passes to a TAFKAL80ETC concert, -14, 0 +Backstage passes to a TAFKAL80ETC concert, -19, 0 +Conjured Mana Cake, -21, 0 + +-------- day 25 -------- +name, sellIn, quality ++5 Dexterity Vest, -15, 0 +Aged Brie, -23, 48 +Elixir of the Mongoose, -20, 0 +Sulfuras, Hand of Ragnaros, 0, 80 +Sulfuras, Hand of Ragnaros, -1, 80 +Backstage passes to a TAFKAL80ETC concert, -10, 0 +Backstage passes to a TAFKAL80ETC concert, -15, 0 +Backstage passes to a TAFKAL80ETC concert, -20, 0 +Conjured Mana Cake, -22, 0 + +-------- day 26 -------- +name, sellIn, quality ++5 Dexterity Vest, -16, 0 +Aged Brie, -24, 50 +Elixir of the Mongoose, -21, 0 +Sulfuras, Hand of Ragnaros, 0, 80 +Sulfuras, Hand of Ragnaros, -1, 80 +Backstage passes to a TAFKAL80ETC concert, -11, 0 +Backstage passes to a TAFKAL80ETC concert, -16, 0 +Backstage passes to a TAFKAL80ETC concert, -21, 0 +Conjured Mana Cake, -23, 0 + +-------- day 27 -------- +name, sellIn, quality ++5 Dexterity Vest, -17, 0 +Aged Brie, -25, 50 +Elixir of the Mongoose, -22, 0 +Sulfuras, Hand of Ragnaros, 0, 80 +Sulfuras, Hand of Ragnaros, -1, 80 +Backstage passes to a TAFKAL80ETC concert, -12, 0 +Backstage passes to a TAFKAL80ETC concert, -17, 0 +Backstage passes to a TAFKAL80ETC concert, -22, 0 +Conjured Mana Cake, -24, 0 + +-------- day 28 -------- +name, sellIn, quality ++5 Dexterity Vest, -18, 0 +Aged Brie, -26, 50 +Elixir of the Mongoose, -23, 0 +Sulfuras, Hand of Ragnaros, 0, 80 +Sulfuras, Hand of Ragnaros, -1, 80 +Backstage passes to a TAFKAL80ETC concert, -13, 0 +Backstage passes to a TAFKAL80ETC concert, -18, 0 +Backstage passes to a TAFKAL80ETC concert, -23, 0 +Conjured Mana Cake, -25, 0 + +-------- day 29 -------- +name, sellIn, quality ++5 Dexterity Vest, -19, 0 +Aged Brie, -27, 50 +Elixir of the Mongoose, -24, 0 +Sulfuras, Hand of Ragnaros, 0, 80 +Sulfuras, Hand of Ragnaros, -1, 80 +Backstage passes to a TAFKAL80ETC concert, -14, 0 +Backstage passes to a TAFKAL80ETC concert, -19, 0 +Backstage passes to a TAFKAL80ETC concert, -24, 0 +Conjured Mana Cake, -26, 0 + +-------- day 30 -------- +name, sellIn, quality ++5 Dexterity Vest, -20, 0 +Aged Brie, -28, 50 +Elixir of the Mongoose, -25, 0 +Sulfuras, Hand of Ragnaros, 0, 80 +Sulfuras, Hand of Ragnaros, -1, 80 +Backstage passes to a TAFKAL80ETC concert, -15, 0 +Backstage passes to a TAFKAL80ETC concert, -20, 0 +Backstage passes to a TAFKAL80ETC concert, -25, 0 +Conjured Mana Cake, -27, 0 + From 26a1251a61cb53f3b62a61e1ea481d86ea0b1483 Mon Sep 17 00:00:00 2001 From: Clay Dowling Date: Fri, 10 Mar 2017 21:16:02 -0500 Subject: [PATCH 195/634] Added test against changing Item --- c-check/golden-rule.sh | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/c-check/golden-rule.sh b/c-check/golden-rule.sh index 2ef885a7..342dba02 100755 --- a/c-check/golden-rule.sh +++ b/c-check/golden-rule.sh @@ -1,6 +1,7 @@ #!/bin/bash -OUTFILE = /tmp/golden-dross.txt +OUTFILE=/tmp/golden-dross.txt -./golden_rose > $(OUTFILE) -diff $(OUTFILE) golden_rule.txt +./golden_rose > $OUTFILE +diff $OUTFILE golden_rule.txt +git diff GildedRose.h From c01ba7bc7f9c54e5a17ddc28dfeedc2e5ad6a48b Mon Sep 17 00:00:00 2001 From: Clay Dowling Date: Fri, 10 Mar 2017 21:21:59 -0500 Subject: [PATCH 196/634] First check for normal items --- c-check/test_rose.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/c-check/test_rose.c b/c-check/test_rose.c index 30cc7544..cb91d270 100644 --- a/c-check/test_rose.c +++ b/c-check/test_rose.c @@ -1,15 +1,16 @@ #include #include "GildedRose.h" +#define NORMAL_ITEM "Elixer of Mongoose" -START_TEST(roseFoo) +START_TEST(normalitem_whenSellInPositive_decreasesQualityByOne) { Item items[1]; - init_item(items, "foo", 0, 0); + init_item(items, NORMAL_ITEM, 10, 15); update_quality(items, 1); - ck_assert_str_eq("fixme", items[0].name); + ck_assert_int_eq(14, items[0].quality); } END_TEST @@ -17,8 +18,8 @@ TCase *tcase_rose(void) { TCase *tc; - tc = tcase_create("gilded-rose"); - tcase_add_test(tc, roseFoo); + tc = tcase_create("normal-items"); + tcase_add_test(tc, normalitem_whenSellInPositive_decreasesQualityByOne); return tc; } From ccabf6e847702278099fa18811621c287e16df05 Mon Sep 17 00:00:00 2001 From: Clay Dowling Date: Fri, 10 Mar 2017 21:22:50 -0500 Subject: [PATCH 197/634] First check for normal items --- c-check/test_rose.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/c-check/test_rose.c b/c-check/test_rose.c index cb91d270..1bf3fa7d 100644 --- a/c-check/test_rose.c +++ b/c-check/test_rose.c @@ -14,6 +14,16 @@ START_TEST(normalitem_whenSellInPositive_decreasesQualityByOne) } END_TEST +START_TEST(normalitem_whenSellIsZero_decreasesQualityByOne) +{ + Item items[1]; + init_item(items, NORMAL_ITEM, 0, 15); + update_quality(items, 1); + + ck_assert_int_eq(70, items[0].quality); +} +END_TEST + TCase *tcase_rose(void) { TCase *tc; From fe0cad5a7276279d385fd5c7a69997d45efed129 Mon Sep 17 00:00:00 2001 From: Clay Dowling Date: Fri, 10 Mar 2017 21:24:09 -0500 Subject: [PATCH 198/634] Second test, normal item below zero --- c-check/test_rose.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/c-check/test_rose.c b/c-check/test_rose.c index 1bf3fa7d..9d340104 100644 --- a/c-check/test_rose.c +++ b/c-check/test_rose.c @@ -14,13 +14,13 @@ START_TEST(normalitem_whenSellInPositive_decreasesQualityByOne) } END_TEST -START_TEST(normalitem_whenSellIsZero_decreasesQualityByOne) +START_TEST(normalitem_whenSellIsZero_decreasesQualityByTwo) { Item items[1]; init_item(items, NORMAL_ITEM, 0, 15); update_quality(items, 1); - ck_assert_int_eq(70, items[0].quality); + ck_assert_int_eq(13, items[0].quality); } END_TEST @@ -30,6 +30,7 @@ TCase *tcase_rose(void) tc = tcase_create("normal-items"); tcase_add_test(tc, normalitem_whenSellInPositive_decreasesQualityByOne); + tcase_add_test(tc, normalitem_whenSellIsZero_decreasesQualityByTwo); return tc; } From 08cf17d6bcf9d2e0dba557632dd38d27d5548051 Mon Sep 17 00:00:00 2001 From: Clay Dowling Date: Fri, 10 Mar 2017 21:31:09 -0500 Subject: [PATCH 199/634] Renamed to reflect actual contents --- c-check/test_main.c | 4 ++-- c-check/test_rose.c | 13 ++++++++++++- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/c-check/test_main.c b/c-check/test_main.c index 0d5a0de0..3fb1a1db 100644 --- a/c-check/test_main.c +++ b/c-check/test_main.c @@ -2,7 +2,7 @@ #include #include -Suite *suite_rose(void); +Suite *suite_normal(void); int main(int argc, char **argv) { @@ -15,7 +15,7 @@ int main(int argc, char **argv) forkme = 0; } - s = suite_rose(); + s = suite_normal(); runner = srunner_create(s); if (0 == forkme) { diff --git a/c-check/test_rose.c b/c-check/test_rose.c index 9d340104..98fbab5b 100644 --- a/c-check/test_rose.c +++ b/c-check/test_rose.c @@ -24,6 +24,16 @@ START_TEST(normalitem_whenSellIsZero_decreasesQualityByTwo) } END_TEST +START_TEST(normalitem_whenQualityZero_doesNotDecrease) +{ + Item items[1]; + init_item(items, NORMAL_ITEM, 10, 0); + update_quality(items, 1); + + ck_assert_int_eq(0, items[0].quality); +} +END_TEST + TCase *tcase_rose(void) { TCase *tc; @@ -31,11 +41,12 @@ TCase *tcase_rose(void) tc = tcase_create("normal-items"); tcase_add_test(tc, normalitem_whenSellInPositive_decreasesQualityByOne); tcase_add_test(tc, normalitem_whenSellIsZero_decreasesQualityByTwo); + tcase_add_test(tc, normalitem_whenQualityZero_doesNotDecrease); return tc; } -Suite *suite_rose(void) +Suite *suite_normal(void) { Suite *s; From 438a5d661286daedfc44239fa996c6e09bac1f21 Mon Sep 17 00:00:00 2001 From: Clay Dowling Date: Fri, 10 Mar 2017 21:39:08 -0500 Subject: [PATCH 200/634] Actually rename the test suite --- c-check/{test_rose.c => test_normal.c} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename c-check/{test_rose.c => test_normal.c} (100%) diff --git a/c-check/test_rose.c b/c-check/test_normal.c similarity index 100% rename from c-check/test_rose.c rename to c-check/test_normal.c From cdb407461b7809771ff245759e5a27d4146c0584 Mon Sep 17 00:00:00 2001 From: Clay Dowling Date: Fri, 10 Mar 2017 21:50:17 -0500 Subject: [PATCH 201/634] Added tests for aged brie --- c-check/test_brie.c | 35 +++++++++++++++++++++++++++++++++++ c-check/test_normal.c | 6 ++++-- 2 files changed, 39 insertions(+), 2 deletions(-) create mode 100644 c-check/test_brie.c diff --git a/c-check/test_brie.c b/c-check/test_brie.c new file mode 100644 index 00000000..e0ef714b --- /dev/null +++ b/c-check/test_brie.c @@ -0,0 +1,35 @@ +#include +#include "GildedRose.h" + +#define CHEESE "Aged Brie" + +START_TEST(agedBrie_whenSellInPositive_increasesQualityByOne) +{ + Item items[1]; + init_item(items, CHEESE, 10, 15); + update_quality(items, 1); + + ck_assert_int_eq(16, items[0].quality); +} +END_TEST + +START_TEST(agedBrie_cannotIncreaseQualityAboveFifty) +{ + Item items[1]; + init_item(items, CHEESE, 10, 50); + update_quality(items, 1); + + ck_assert_int_eq(50, items[0].quality); +} +END_TEST + +TCase *tcase_brie(void) +{ + TCase *tc; + + tc = tcase_create("aged-brie"); + tcase_add_test(tc, agedBrie_whenSellInPositive_increasesQualityByOne); + tcase_add_test(tc, agedBrie_cannotIncreaseQualityAboveFifty); + + return tc; +} diff --git a/c-check/test_normal.c b/c-check/test_normal.c index 98fbab5b..f6af58c9 100644 --- a/c-check/test_normal.c +++ b/c-check/test_normal.c @@ -3,6 +3,7 @@ #define NORMAL_ITEM "Elixer of Mongoose" +TCase *tcase_brie(void); START_TEST(normalitem_whenSellInPositive_decreasesQualityByOne) { @@ -34,7 +35,7 @@ START_TEST(normalitem_whenQualityZero_doesNotDecrease) } END_TEST -TCase *tcase_rose(void) +TCase *tcase_normal(void) { TCase *tc; @@ -51,7 +52,8 @@ Suite *suite_normal(void) Suite *s; s = suite_create("characterization-tests"); - suite_add_tcase(s, tcase_rose()); + suite_add_tcase(s, tcase_normal()); + suite_add_tcase(s, tcase_brie()); return s; } From 38857a8dc9195707365d46340e5dd82d35a09738 Mon Sep 17 00:00:00 2001 From: Clay Dowling Date: Fri, 10 Mar 2017 21:52:33 -0500 Subject: [PATCH 202/634] Test for normal items with SellIn less than zero --- c-check/test_normal.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/c-check/test_normal.c b/c-check/test_normal.c index f6af58c9..acf0e0b8 100644 --- a/c-check/test_normal.c +++ b/c-check/test_normal.c @@ -35,6 +35,17 @@ START_TEST(normalitem_whenQualityZero_doesNotDecrease) } END_TEST + +START_TEST(normalitem_whenSellInNegative_decreasesByTwo) +{ + Item items[1]; + init_item(items, NORMAL_ITEM, -1, 20); + update_quality(items, 1); + + ck_assert_int_eq(18, items[0].quality); +} +END_TEST + TCase *tcase_normal(void) { TCase *tc; @@ -43,6 +54,7 @@ TCase *tcase_normal(void) tcase_add_test(tc, normalitem_whenSellInPositive_decreasesQualityByOne); tcase_add_test(tc, normalitem_whenSellIsZero_decreasesQualityByTwo); tcase_add_test(tc, normalitem_whenQualityZero_doesNotDecrease); + tcase_add_test(tc, normalitem_whenSellInNegative_decreasesByTwo); return tc; } From 19dcacbf7e3ea4651c8bf2362cad5439ebde92c9 Mon Sep 17 00:00:00 2001 From: Clay Dowling Date: Fri, 10 Mar 2017 21:53:40 -0500 Subject: [PATCH 203/634] Added test for zero --- c-check/test_normal.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/c-check/test_normal.c b/c-check/test_normal.c index acf0e0b8..30332830 100644 --- a/c-check/test_normal.c +++ b/c-check/test_normal.c @@ -46,6 +46,16 @@ START_TEST(normalitem_whenSellInNegative_decreasesByTwo) } END_TEST +START_TEST(normalitem_whenSellInZero_decreasesByTwo) +{ + Item items[1]; + init_item(items, NORMAL_ITEM, -1, 15); + update_quality(items, 1); + + ck_assert_int_eq(13, items[0].quality); +} +END_TEST + TCase *tcase_normal(void) { TCase *tc; @@ -55,6 +65,7 @@ TCase *tcase_normal(void) tcase_add_test(tc, normalitem_whenSellIsZero_decreasesQualityByTwo); tcase_add_test(tc, normalitem_whenQualityZero_doesNotDecrease); tcase_add_test(tc, normalitem_whenSellInNegative_decreasesByTwo); + tcase_add_test(tc, normalitem_whenSellInZero_decreasesByTwo); return tc; } From ceebe400c9aa7dfd0315ef5adf30135ec161f5e9 Mon Sep 17 00:00:00 2001 From: Clay Dowling Date: Fri, 10 Mar 2017 22:26:15 -0500 Subject: [PATCH 204/634] Added tests for backstage pass --- c-check/test_backstage.c | 37 +++++++++++++++++++++++++++++++++++++ c-check/test_normal.c | 2 ++ 2 files changed, 39 insertions(+) create mode 100644 c-check/test_backstage.c diff --git a/c-check/test_backstage.c b/c-check/test_backstage.c new file mode 100644 index 00000000..ae762be2 --- /dev/null +++ b/c-check/test_backstage.c @@ -0,0 +1,37 @@ +#include +#include "GildedRose.h" + +#define GOOD_BACKSTAGE "Backstage passes to a TAFKAL80ETC concert" +#define BAD_BACKSTAGE "Backstage passes to a Jeff Beck concert" + +START_TEST(backstage_whenMoreThan10Days_increasesByOne) +{ + Item items[1]; + init_item(items, GOOD_BACKSTAGE, 12, 15); + update_quality(items, 1); + + ck_assert_int_eq(16, items[0].quality); +} +END_TEST + +START_TEST(backstage_when10Days_increasesByTwo) +{ + Item items[1]; + init_item(items, GOOD_BACKSTAGE, 10, 15); + update_quality(items, 1); + + ck_assert_int_eq(17, items[0].quality); +} +END_TEST + + +TCase *tcase_backstage(void) +{ + TCase *tc; + + tc = tcase_create("backstage-pass"); + tcase_add_test(tc, backstage_whenMoreThan10Days_increasesByOne); + tcase_add_test(tc, backstage_when10Days_increasesByTwo); + + return tc; +} diff --git a/c-check/test_normal.c b/c-check/test_normal.c index 30332830..2a38e2f1 100644 --- a/c-check/test_normal.c +++ b/c-check/test_normal.c @@ -4,6 +4,7 @@ #define NORMAL_ITEM "Elixer of Mongoose" TCase *tcase_brie(void); +TCase *tcase_backstage(void); START_TEST(normalitem_whenSellInPositive_decreasesQualityByOne) { @@ -77,6 +78,7 @@ Suite *suite_normal(void) s = suite_create("characterization-tests"); suite_add_tcase(s, tcase_normal()); suite_add_tcase(s, tcase_brie()); + suite_add_tcase(s, tcase_backstage()); return s; } From 264ed0c974e68c4167847bf372f86d401d90ee72 Mon Sep 17 00:00:00 2001 From: Clay Dowling Date: Fri, 10 Mar 2017 22:42:52 -0500 Subject: [PATCH 205/634] Tests for backstage passes --- c-check/test_backstage.c | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/c-check/test_backstage.c b/c-check/test_backstage.c index ae762be2..07364a41 100644 --- a/c-check/test_backstage.c +++ b/c-check/test_backstage.c @@ -24,6 +24,35 @@ START_TEST(backstage_when10Days_increasesByTwo) } END_TEST +START_TEST(backstage_when5Days_increasesByThree) +{ + Item items[1]; + init_item(items, GOOD_BACKSTAGE, 5, 15); + update_quality(items, 1); + + ck_assert_int_eq(18, items[0].quality); +} +END_TEST + +START_TEST(backstage_when0Days_hasQualityZero) +{ + Item items[1]; + init_item(items, GOOD_BACKSTAGE, 0, 15); + update_quality(items, 1); + + ck_assert_int_eq(0, items[0].quality); +} +END_TEST + +START_TEST(otherBackstage_when12Days_decreasesByOne) +{ + Item items[1]; + init_item(items, BAD_BACKSTAGE, 12, 15); + update_quality(items, 1); + + ck_assert_int_eq(14, items[0].quality); +} +END_TEST TCase *tcase_backstage(void) { @@ -32,6 +61,9 @@ TCase *tcase_backstage(void) tc = tcase_create("backstage-pass"); tcase_add_test(tc, backstage_whenMoreThan10Days_increasesByOne); tcase_add_test(tc, backstage_when10Days_increasesByTwo); + tcase_add_test(tc, backstage_when5Days_increasesByThree); + tcase_add_test(tc, backstage_when0Days_hasQualityZero); + tcase_add_test(tc, otherBackstage_when12Days_decreasesByOne); return tc; } From 20178c8026cea61792d15655b63adba9b24a6ac7 Mon Sep 17 00:00:00 2001 From: Clay Dowling Date: Sat, 11 Mar 2017 09:06:34 -0500 Subject: [PATCH 206/634] Updated documentation and made Makefile easier for inexperienced C devs --- c-check/Makefile | 12 ++++++++---- c-check/{README => README.md} | 24 ++++++++++++++++++++++-- 2 files changed, 30 insertions(+), 6 deletions(-) rename c-check/{README => README.md} (54%) diff --git a/c-check/Makefile b/c-check/Makefile index 1cc056b7..dabcf6b1 100644 --- a/c-check/Makefile +++ b/c-check/Makefile @@ -11,13 +11,17 @@ CFLAGS = `pkg-config --cflags check` -g --std=c99 -D_POSIX_C_SOURCE=200809L LIBS = `pkg-config --libs check` -# All files that should be part of your test should start with 'test' -TEST_SRC = $(wildcard test*.[c\|h]) +# All files that should be part of your test should start with 'test_' +TEST_SRC = $(wildcard test_*.c) TEST_BASE = $(basename ${TEST_SRC}) TEST_OBJECTS = $(addsuffix .o, ${TEST_BASE}) -# If you add more implementation classes, add them to this variable -OBJECT_UNDER_TEST = GildedRose.o +# All files that should be part of your main program should start with 'gilded_' +PROG_SRC = $(wildcard gilded_*.c) +PROG_BASE = $(basename ${PROG_SRC}) +PROG_OBJECTS = $(addsuffix .o, ${PROG_BASE}) + +OBJECT_UNDER_TEST = GildedRose.o ${PROG_OBJECTS} # This is the test application. You can run this program to see your test output TEST_APP = test_gildedrose diff --git a/c-check/README b/c-check/README.md similarity index 54% rename from c-check/README rename to c-check/README.md index afb21a4e..ec2cd02e 100644 --- a/c-check/README +++ b/c-check/README.md @@ -1,13 +1,33 @@ +# Gilded Rose, C99 Edition + The command "make" will build and run your tests, as well as build the program golden_rose, which can serve as the basis for a golden-rule test. -Assumptions: +## Assumptions - gnu make and a C compiler (like gcc) is installed on your system and is in the PATH - The check unit testing library is installed on your system (https://libcheck.github.io/check/) - pkg-config is installed on your system -Notes: +## Usage + - Run `make` to build the program and run all tests + - Files which contain tests should be named `test_*.c` They will automatically + be included in your test suite. + - `GildedRose.h` should not be modified. The Goblin threat is real. + - New program logic may be included in files named `gilded_*.c` which will + automatically be included in both your tests and the final program. + +## Golden Rule tests + - The program `golden_rose` will generate text output. If you capture this + output after your first `make` you can use this as a reference for a golden + rule test. + - You can test your work against this reference by directing the output of your + current golden_rose to a file and using the `diff` utility to compare that + to the reference file you created above. + - To avoid the Goblin threat you can use `git diff GildedRose.h`, which should + have no output if you have left the precious Item structure unchanged. + +## Notes - This project is tweaked to run on Linux systems, and will mostly work on Macs. With some changes to the Makefile it can be made to run on BSD systems with BSD make. An adventurous person could also get it to run on Windows. From 3200f2e36ce743d7d63ad8ee154234e7454fd242 Mon Sep 17 00:00:00 2001 From: Clay Dowling Date: Mon, 13 Mar 2017 17:48:12 -0400 Subject: [PATCH 207/634] Reverted files to a useful starting point --- c-check/.gitignore | 7 ++++ c-check/test_backstage.c | 69 --------------------------------- c-check/test_brie.c | 35 ----------------- c-check/test_main.c | 4 +- c-check/test_normal.c | 84 ---------------------------------------- c-check/test_rose.c | 34 ++++++++++++++++ 6 files changed, 43 insertions(+), 190 deletions(-) delete mode 100644 c-check/test_backstage.c delete mode 100644 c-check/test_brie.c delete mode 100644 c-check/test_normal.c create mode 100644 c-check/test_rose.c diff --git a/c-check/.gitignore b/c-check/.gitignore index 52fc06fa..65962297 100644 --- a/c-check/.gitignore +++ b/c-check/.gitignore @@ -1,3 +1,10 @@ *.o +*.gch +*.config +*.creator +*.creator.user +*.files +*.includes +*.iml test_gildedrose golden_rose diff --git a/c-check/test_backstage.c b/c-check/test_backstage.c deleted file mode 100644 index 07364a41..00000000 --- a/c-check/test_backstage.c +++ /dev/null @@ -1,69 +0,0 @@ -#include -#include "GildedRose.h" - -#define GOOD_BACKSTAGE "Backstage passes to a TAFKAL80ETC concert" -#define BAD_BACKSTAGE "Backstage passes to a Jeff Beck concert" - -START_TEST(backstage_whenMoreThan10Days_increasesByOne) -{ - Item items[1]; - init_item(items, GOOD_BACKSTAGE, 12, 15); - update_quality(items, 1); - - ck_assert_int_eq(16, items[0].quality); -} -END_TEST - -START_TEST(backstage_when10Days_increasesByTwo) -{ - Item items[1]; - init_item(items, GOOD_BACKSTAGE, 10, 15); - update_quality(items, 1); - - ck_assert_int_eq(17, items[0].quality); -} -END_TEST - -START_TEST(backstage_when5Days_increasesByThree) -{ - Item items[1]; - init_item(items, GOOD_BACKSTAGE, 5, 15); - update_quality(items, 1); - - ck_assert_int_eq(18, items[0].quality); -} -END_TEST - -START_TEST(backstage_when0Days_hasQualityZero) -{ - Item items[1]; - init_item(items, GOOD_BACKSTAGE, 0, 15); - update_quality(items, 1); - - ck_assert_int_eq(0, items[0].quality); -} -END_TEST - -START_TEST(otherBackstage_when12Days_decreasesByOne) -{ - Item items[1]; - init_item(items, BAD_BACKSTAGE, 12, 15); - update_quality(items, 1); - - ck_assert_int_eq(14, items[0].quality); -} -END_TEST - -TCase *tcase_backstage(void) -{ - TCase *tc; - - tc = tcase_create("backstage-pass"); - tcase_add_test(tc, backstage_whenMoreThan10Days_increasesByOne); - tcase_add_test(tc, backstage_when10Days_increasesByTwo); - tcase_add_test(tc, backstage_when5Days_increasesByThree); - tcase_add_test(tc, backstage_when0Days_hasQualityZero); - tcase_add_test(tc, otherBackstage_when12Days_decreasesByOne); - - return tc; -} diff --git a/c-check/test_brie.c b/c-check/test_brie.c deleted file mode 100644 index e0ef714b..00000000 --- a/c-check/test_brie.c +++ /dev/null @@ -1,35 +0,0 @@ -#include -#include "GildedRose.h" - -#define CHEESE "Aged Brie" - -START_TEST(agedBrie_whenSellInPositive_increasesQualityByOne) -{ - Item items[1]; - init_item(items, CHEESE, 10, 15); - update_quality(items, 1); - - ck_assert_int_eq(16, items[0].quality); -} -END_TEST - -START_TEST(agedBrie_cannotIncreaseQualityAboveFifty) -{ - Item items[1]; - init_item(items, CHEESE, 10, 50); - update_quality(items, 1); - - ck_assert_int_eq(50, items[0].quality); -} -END_TEST - -TCase *tcase_brie(void) -{ - TCase *tc; - - tc = tcase_create("aged-brie"); - tcase_add_test(tc, agedBrie_whenSellInPositive_increasesQualityByOne); - tcase_add_test(tc, agedBrie_cannotIncreaseQualityAboveFifty); - - return tc; -} diff --git a/c-check/test_main.c b/c-check/test_main.c index 3fb1a1db..0d5a0de0 100644 --- a/c-check/test_main.c +++ b/c-check/test_main.c @@ -2,7 +2,7 @@ #include #include -Suite *suite_normal(void); +Suite *suite_rose(void); int main(int argc, char **argv) { @@ -15,7 +15,7 @@ int main(int argc, char **argv) forkme = 0; } - s = suite_normal(); + s = suite_rose(); runner = srunner_create(s); if (0 == forkme) { diff --git a/c-check/test_normal.c b/c-check/test_normal.c deleted file mode 100644 index 2a38e2f1..00000000 --- a/c-check/test_normal.c +++ /dev/null @@ -1,84 +0,0 @@ -#include -#include "GildedRose.h" - -#define NORMAL_ITEM "Elixer of Mongoose" - -TCase *tcase_brie(void); -TCase *tcase_backstage(void); - -START_TEST(normalitem_whenSellInPositive_decreasesQualityByOne) -{ - Item items[1]; - init_item(items, NORMAL_ITEM, 10, 15); - update_quality(items, 1); - - ck_assert_int_eq(14, items[0].quality); -} -END_TEST - -START_TEST(normalitem_whenSellIsZero_decreasesQualityByTwo) -{ - Item items[1]; - init_item(items, NORMAL_ITEM, 0, 15); - update_quality(items, 1); - - ck_assert_int_eq(13, items[0].quality); -} -END_TEST - -START_TEST(normalitem_whenQualityZero_doesNotDecrease) -{ - Item items[1]; - init_item(items, NORMAL_ITEM, 10, 0); - update_quality(items, 1); - - ck_assert_int_eq(0, items[0].quality); -} -END_TEST - - -START_TEST(normalitem_whenSellInNegative_decreasesByTwo) -{ - Item items[1]; - init_item(items, NORMAL_ITEM, -1, 20); - update_quality(items, 1); - - ck_assert_int_eq(18, items[0].quality); -} -END_TEST - -START_TEST(normalitem_whenSellInZero_decreasesByTwo) -{ - Item items[1]; - init_item(items, NORMAL_ITEM, -1, 15); - update_quality(items, 1); - - ck_assert_int_eq(13, items[0].quality); -} -END_TEST - -TCase *tcase_normal(void) -{ - TCase *tc; - - tc = tcase_create("normal-items"); - tcase_add_test(tc, normalitem_whenSellInPositive_decreasesQualityByOne); - tcase_add_test(tc, normalitem_whenSellIsZero_decreasesQualityByTwo); - tcase_add_test(tc, normalitem_whenQualityZero_doesNotDecrease); - tcase_add_test(tc, normalitem_whenSellInNegative_decreasesByTwo); - tcase_add_test(tc, normalitem_whenSellInZero_decreasesByTwo); - - return tc; -} - -Suite *suite_normal(void) -{ - Suite *s; - - s = suite_create("characterization-tests"); - suite_add_tcase(s, tcase_normal()); - suite_add_tcase(s, tcase_brie()); - suite_add_tcase(s, tcase_backstage()); - - return s; -} diff --git a/c-check/test_rose.c b/c-check/test_rose.c new file mode 100644 index 00000000..30cc7544 --- /dev/null +++ b/c-check/test_rose.c @@ -0,0 +1,34 @@ +#include +#include "GildedRose.h" + + + +START_TEST(roseFoo) +{ + Item items[1]; + init_item(items, "foo", 0, 0); + update_quality(items, 1); + + ck_assert_str_eq("fixme", items[0].name); +} +END_TEST + +TCase *tcase_rose(void) +{ + TCase *tc; + + tc = tcase_create("gilded-rose"); + tcase_add_test(tc, roseFoo); + + return tc; +} + +Suite *suite_rose(void) +{ + Suite *s; + + s = suite_create("characterization-tests"); + suite_add_tcase(s, tcase_rose()); + + return s; +} From 722d8f2bb1ba3f264e84add8c3557318aefef318 Mon Sep 17 00:00:00 2001 From: Clay Dowling Date: Mon, 13 Mar 2017 17:49:36 -0400 Subject: [PATCH 208/634] Removed files that didn't belong in version control --- c-check/golden-rule.sh | 7 - c-check/golden_rule.txt | 373 ---------------------------------------- 2 files changed, 380 deletions(-) delete mode 100755 c-check/golden-rule.sh delete mode 100644 c-check/golden_rule.txt diff --git a/c-check/golden-rule.sh b/c-check/golden-rule.sh deleted file mode 100755 index 342dba02..00000000 --- a/c-check/golden-rule.sh +++ /dev/null @@ -1,7 +0,0 @@ -#!/bin/bash - -OUTFILE=/tmp/golden-dross.txt - -./golden_rose > $OUTFILE -diff $OUTFILE golden_rule.txt -git diff GildedRose.h diff --git a/c-check/golden_rule.txt b/c-check/golden_rule.txt deleted file mode 100644 index a04e48ac..00000000 --- a/c-check/golden_rule.txt +++ /dev/null @@ -1,373 +0,0 @@ -OMGHAI! --------- day 0 -------- -name, sellIn, quality -+5 Dexterity Vest, 10, 20 -Aged Brie, 2, 0 -Elixir of the Mongoose, 5, 7 -Sulfuras, Hand of Ragnaros, 0, 80 -Sulfuras, Hand of Ragnaros, -1, 80 -Backstage passes to a TAFKAL80ETC concert, 15, 20 -Backstage passes to a TAFKAL80ETC concert, 10, 49 -Backstage passes to a TAFKAL80ETC concert, 5, 49 -Conjured Mana Cake, 3, 6 - --------- day 1 -------- -name, sellIn, quality -+5 Dexterity Vest, 9, 19 -Aged Brie, 1, 1 -Elixir of the Mongoose, 4, 6 -Sulfuras, Hand of Ragnaros, 0, 80 -Sulfuras, Hand of Ragnaros, -1, 80 -Backstage passes to a TAFKAL80ETC concert, 14, 21 -Backstage passes to a TAFKAL80ETC concert, 9, 50 -Backstage passes to a TAFKAL80ETC concert, 4, 50 -Conjured Mana Cake, 2, 5 - --------- day 2 -------- -name, sellIn, quality -+5 Dexterity Vest, 8, 18 -Aged Brie, 0, 2 -Elixir of the Mongoose, 3, 5 -Sulfuras, Hand of Ragnaros, 0, 80 -Sulfuras, Hand of Ragnaros, -1, 80 -Backstage passes to a TAFKAL80ETC concert, 13, 22 -Backstage passes to a TAFKAL80ETC concert, 8, 50 -Backstage passes to a TAFKAL80ETC concert, 3, 50 -Conjured Mana Cake, 1, 4 - --------- day 3 -------- -name, sellIn, quality -+5 Dexterity Vest, 7, 17 -Aged Brie, -1, 4 -Elixir of the Mongoose, 2, 4 -Sulfuras, Hand of Ragnaros, 0, 80 -Sulfuras, Hand of Ragnaros, -1, 80 -Backstage passes to a TAFKAL80ETC concert, 12, 23 -Backstage passes to a TAFKAL80ETC concert, 7, 50 -Backstage passes to a TAFKAL80ETC concert, 2, 50 -Conjured Mana Cake, 0, 3 - --------- day 4 -------- -name, sellIn, quality -+5 Dexterity Vest, 6, 16 -Aged Brie, -2, 6 -Elixir of the Mongoose, 1, 3 -Sulfuras, Hand of Ragnaros, 0, 80 -Sulfuras, Hand of Ragnaros, -1, 80 -Backstage passes to a TAFKAL80ETC concert, 11, 24 -Backstage passes to a TAFKAL80ETC concert, 6, 50 -Backstage passes to a TAFKAL80ETC concert, 1, 50 -Conjured Mana Cake, -1, 1 - --------- day 5 -------- -name, sellIn, quality -+5 Dexterity Vest, 5, 15 -Aged Brie, -3, 8 -Elixir of the Mongoose, 0, 2 -Sulfuras, Hand of Ragnaros, 0, 80 -Sulfuras, Hand of Ragnaros, -1, 80 -Backstage passes to a TAFKAL80ETC concert, 10, 25 -Backstage passes to a TAFKAL80ETC concert, 5, 50 -Backstage passes to a TAFKAL80ETC concert, 0, 50 -Conjured Mana Cake, -2, 0 - --------- day 6 -------- -name, sellIn, quality -+5 Dexterity Vest, 4, 14 -Aged Brie, -4, 10 -Elixir of the Mongoose, -1, 0 -Sulfuras, Hand of Ragnaros, 0, 80 -Sulfuras, Hand of Ragnaros, -1, 80 -Backstage passes to a TAFKAL80ETC concert, 9, 27 -Backstage passes to a TAFKAL80ETC concert, 4, 50 -Backstage passes to a TAFKAL80ETC concert, -1, 0 -Conjured Mana Cake, -3, 0 - --------- day 7 -------- -name, sellIn, quality -+5 Dexterity Vest, 3, 13 -Aged Brie, -5, 12 -Elixir of the Mongoose, -2, 0 -Sulfuras, Hand of Ragnaros, 0, 80 -Sulfuras, Hand of Ragnaros, -1, 80 -Backstage passes to a TAFKAL80ETC concert, 8, 29 -Backstage passes to a TAFKAL80ETC concert, 3, 50 -Backstage passes to a TAFKAL80ETC concert, -2, 0 -Conjured Mana Cake, -4, 0 - --------- day 8 -------- -name, sellIn, quality -+5 Dexterity Vest, 2, 12 -Aged Brie, -6, 14 -Elixir of the Mongoose, -3, 0 -Sulfuras, Hand of Ragnaros, 0, 80 -Sulfuras, Hand of Ragnaros, -1, 80 -Backstage passes to a TAFKAL80ETC concert, 7, 31 -Backstage passes to a TAFKAL80ETC concert, 2, 50 -Backstage passes to a TAFKAL80ETC concert, -3, 0 -Conjured Mana Cake, -5, 0 - --------- day 9 -------- -name, sellIn, quality -+5 Dexterity Vest, 1, 11 -Aged Brie, -7, 16 -Elixir of the Mongoose, -4, 0 -Sulfuras, Hand of Ragnaros, 0, 80 -Sulfuras, Hand of Ragnaros, -1, 80 -Backstage passes to a TAFKAL80ETC concert, 6, 33 -Backstage passes to a TAFKAL80ETC concert, 1, 50 -Backstage passes to a TAFKAL80ETC concert, -4, 0 -Conjured Mana Cake, -6, 0 - --------- day 10 -------- -name, sellIn, quality -+5 Dexterity Vest, 0, 10 -Aged Brie, -8, 18 -Elixir of the Mongoose, -5, 0 -Sulfuras, Hand of Ragnaros, 0, 80 -Sulfuras, Hand of Ragnaros, -1, 80 -Backstage passes to a TAFKAL80ETC concert, 5, 35 -Backstage passes to a TAFKAL80ETC concert, 0, 50 -Backstage passes to a TAFKAL80ETC concert, -5, 0 -Conjured Mana Cake, -7, 0 - --------- day 11 -------- -name, sellIn, quality -+5 Dexterity Vest, -1, 8 -Aged Brie, -9, 20 -Elixir of the Mongoose, -6, 0 -Sulfuras, Hand of Ragnaros, 0, 80 -Sulfuras, Hand of Ragnaros, -1, 80 -Backstage passes to a TAFKAL80ETC concert, 4, 38 -Backstage passes to a TAFKAL80ETC concert, -1, 0 -Backstage passes to a TAFKAL80ETC concert, -6, 0 -Conjured Mana Cake, -8, 0 - --------- day 12 -------- -name, sellIn, quality -+5 Dexterity Vest, -2, 6 -Aged Brie, -10, 22 -Elixir of the Mongoose, -7, 0 -Sulfuras, Hand of Ragnaros, 0, 80 -Sulfuras, Hand of Ragnaros, -1, 80 -Backstage passes to a TAFKAL80ETC concert, 3, 41 -Backstage passes to a TAFKAL80ETC concert, -2, 0 -Backstage passes to a TAFKAL80ETC concert, -7, 0 -Conjured Mana Cake, -9, 0 - --------- day 13 -------- -name, sellIn, quality -+5 Dexterity Vest, -3, 4 -Aged Brie, -11, 24 -Elixir of the Mongoose, -8, 0 -Sulfuras, Hand of Ragnaros, 0, 80 -Sulfuras, Hand of Ragnaros, -1, 80 -Backstage passes to a TAFKAL80ETC concert, 2, 44 -Backstage passes to a TAFKAL80ETC concert, -3, 0 -Backstage passes to a TAFKAL80ETC concert, -8, 0 -Conjured Mana Cake, -10, 0 - --------- day 14 -------- -name, sellIn, quality -+5 Dexterity Vest, -4, 2 -Aged Brie, -12, 26 -Elixir of the Mongoose, -9, 0 -Sulfuras, Hand of Ragnaros, 0, 80 -Sulfuras, Hand of Ragnaros, -1, 80 -Backstage passes to a TAFKAL80ETC concert, 1, 47 -Backstage passes to a TAFKAL80ETC concert, -4, 0 -Backstage passes to a TAFKAL80ETC concert, -9, 0 -Conjured Mana Cake, -11, 0 - --------- day 15 -------- -name, sellIn, quality -+5 Dexterity Vest, -5, 0 -Aged Brie, -13, 28 -Elixir of the Mongoose, -10, 0 -Sulfuras, Hand of Ragnaros, 0, 80 -Sulfuras, Hand of Ragnaros, -1, 80 -Backstage passes to a TAFKAL80ETC concert, 0, 50 -Backstage passes to a TAFKAL80ETC concert, -5, 0 -Backstage passes to a TAFKAL80ETC concert, -10, 0 -Conjured Mana Cake, -12, 0 - --------- day 16 -------- -name, sellIn, quality -+5 Dexterity Vest, -6, 0 -Aged Brie, -14, 30 -Elixir of the Mongoose, -11, 0 -Sulfuras, Hand of Ragnaros, 0, 80 -Sulfuras, Hand of Ragnaros, -1, 80 -Backstage passes to a TAFKAL80ETC concert, -1, 0 -Backstage passes to a TAFKAL80ETC concert, -6, 0 -Backstage passes to a TAFKAL80ETC concert, -11, 0 -Conjured Mana Cake, -13, 0 - --------- day 17 -------- -name, sellIn, quality -+5 Dexterity Vest, -7, 0 -Aged Brie, -15, 32 -Elixir of the Mongoose, -12, 0 -Sulfuras, Hand of Ragnaros, 0, 80 -Sulfuras, Hand of Ragnaros, -1, 80 -Backstage passes to a TAFKAL80ETC concert, -2, 0 -Backstage passes to a TAFKAL80ETC concert, -7, 0 -Backstage passes to a TAFKAL80ETC concert, -12, 0 -Conjured Mana Cake, -14, 0 - --------- day 18 -------- -name, sellIn, quality -+5 Dexterity Vest, -8, 0 -Aged Brie, -16, 34 -Elixir of the Mongoose, -13, 0 -Sulfuras, Hand of Ragnaros, 0, 80 -Sulfuras, Hand of Ragnaros, -1, 80 -Backstage passes to a TAFKAL80ETC concert, -3, 0 -Backstage passes to a TAFKAL80ETC concert, -8, 0 -Backstage passes to a TAFKAL80ETC concert, -13, 0 -Conjured Mana Cake, -15, 0 - --------- day 19 -------- -name, sellIn, quality -+5 Dexterity Vest, -9, 0 -Aged Brie, -17, 36 -Elixir of the Mongoose, -14, 0 -Sulfuras, Hand of Ragnaros, 0, 80 -Sulfuras, Hand of Ragnaros, -1, 80 -Backstage passes to a TAFKAL80ETC concert, -4, 0 -Backstage passes to a TAFKAL80ETC concert, -9, 0 -Backstage passes to a TAFKAL80ETC concert, -14, 0 -Conjured Mana Cake, -16, 0 - --------- day 20 -------- -name, sellIn, quality -+5 Dexterity Vest, -10, 0 -Aged Brie, -18, 38 -Elixir of the Mongoose, -15, 0 -Sulfuras, Hand of Ragnaros, 0, 80 -Sulfuras, Hand of Ragnaros, -1, 80 -Backstage passes to a TAFKAL80ETC concert, -5, 0 -Backstage passes to a TAFKAL80ETC concert, -10, 0 -Backstage passes to a TAFKAL80ETC concert, -15, 0 -Conjured Mana Cake, -17, 0 - --------- day 21 -------- -name, sellIn, quality -+5 Dexterity Vest, -11, 0 -Aged Brie, -19, 40 -Elixir of the Mongoose, -16, 0 -Sulfuras, Hand of Ragnaros, 0, 80 -Sulfuras, Hand of Ragnaros, -1, 80 -Backstage passes to a TAFKAL80ETC concert, -6, 0 -Backstage passes to a TAFKAL80ETC concert, -11, 0 -Backstage passes to a TAFKAL80ETC concert, -16, 0 -Conjured Mana Cake, -18, 0 - --------- day 22 -------- -name, sellIn, quality -+5 Dexterity Vest, -12, 0 -Aged Brie, -20, 42 -Elixir of the Mongoose, -17, 0 -Sulfuras, Hand of Ragnaros, 0, 80 -Sulfuras, Hand of Ragnaros, -1, 80 -Backstage passes to a TAFKAL80ETC concert, -7, 0 -Backstage passes to a TAFKAL80ETC concert, -12, 0 -Backstage passes to a TAFKAL80ETC concert, -17, 0 -Conjured Mana Cake, -19, 0 - --------- day 23 -------- -name, sellIn, quality -+5 Dexterity Vest, -13, 0 -Aged Brie, -21, 44 -Elixir of the Mongoose, -18, 0 -Sulfuras, Hand of Ragnaros, 0, 80 -Sulfuras, Hand of Ragnaros, -1, 80 -Backstage passes to a TAFKAL80ETC concert, -8, 0 -Backstage passes to a TAFKAL80ETC concert, -13, 0 -Backstage passes to a TAFKAL80ETC concert, -18, 0 -Conjured Mana Cake, -20, 0 - --------- day 24 -------- -name, sellIn, quality -+5 Dexterity Vest, -14, 0 -Aged Brie, -22, 46 -Elixir of the Mongoose, -19, 0 -Sulfuras, Hand of Ragnaros, 0, 80 -Sulfuras, Hand of Ragnaros, -1, 80 -Backstage passes to a TAFKAL80ETC concert, -9, 0 -Backstage passes to a TAFKAL80ETC concert, -14, 0 -Backstage passes to a TAFKAL80ETC concert, -19, 0 -Conjured Mana Cake, -21, 0 - --------- day 25 -------- -name, sellIn, quality -+5 Dexterity Vest, -15, 0 -Aged Brie, -23, 48 -Elixir of the Mongoose, -20, 0 -Sulfuras, Hand of Ragnaros, 0, 80 -Sulfuras, Hand of Ragnaros, -1, 80 -Backstage passes to a TAFKAL80ETC concert, -10, 0 -Backstage passes to a TAFKAL80ETC concert, -15, 0 -Backstage passes to a TAFKAL80ETC concert, -20, 0 -Conjured Mana Cake, -22, 0 - --------- day 26 -------- -name, sellIn, quality -+5 Dexterity Vest, -16, 0 -Aged Brie, -24, 50 -Elixir of the Mongoose, -21, 0 -Sulfuras, Hand of Ragnaros, 0, 80 -Sulfuras, Hand of Ragnaros, -1, 80 -Backstage passes to a TAFKAL80ETC concert, -11, 0 -Backstage passes to a TAFKAL80ETC concert, -16, 0 -Backstage passes to a TAFKAL80ETC concert, -21, 0 -Conjured Mana Cake, -23, 0 - --------- day 27 -------- -name, sellIn, quality -+5 Dexterity Vest, -17, 0 -Aged Brie, -25, 50 -Elixir of the Mongoose, -22, 0 -Sulfuras, Hand of Ragnaros, 0, 80 -Sulfuras, Hand of Ragnaros, -1, 80 -Backstage passes to a TAFKAL80ETC concert, -12, 0 -Backstage passes to a TAFKAL80ETC concert, -17, 0 -Backstage passes to a TAFKAL80ETC concert, -22, 0 -Conjured Mana Cake, -24, 0 - --------- day 28 -------- -name, sellIn, quality -+5 Dexterity Vest, -18, 0 -Aged Brie, -26, 50 -Elixir of the Mongoose, -23, 0 -Sulfuras, Hand of Ragnaros, 0, 80 -Sulfuras, Hand of Ragnaros, -1, 80 -Backstage passes to a TAFKAL80ETC concert, -13, 0 -Backstage passes to a TAFKAL80ETC concert, -18, 0 -Backstage passes to a TAFKAL80ETC concert, -23, 0 -Conjured Mana Cake, -25, 0 - --------- day 29 -------- -name, sellIn, quality -+5 Dexterity Vest, -19, 0 -Aged Brie, -27, 50 -Elixir of the Mongoose, -24, 0 -Sulfuras, Hand of Ragnaros, 0, 80 -Sulfuras, Hand of Ragnaros, -1, 80 -Backstage passes to a TAFKAL80ETC concert, -14, 0 -Backstage passes to a TAFKAL80ETC concert, -19, 0 -Backstage passes to a TAFKAL80ETC concert, -24, 0 -Conjured Mana Cake, -26, 0 - --------- day 30 -------- -name, sellIn, quality -+5 Dexterity Vest, -20, 0 -Aged Brie, -28, 50 -Elixir of the Mongoose, -25, 0 -Sulfuras, Hand of Ragnaros, 0, 80 -Sulfuras, Hand of Ragnaros, -1, 80 -Backstage passes to a TAFKAL80ETC concert, -15, 0 -Backstage passes to a TAFKAL80ETC concert, -20, 0 -Backstage passes to a TAFKAL80ETC concert, -25, 0 -Conjured Mana Cake, -27, 0 - From 45733a51292d5a903eb88d50d2c845c63e054636 Mon Sep 17 00:00:00 2001 From: Clay Dowling Date: Mon, 13 Mar 2017 21:28:39 -0400 Subject: [PATCH 209/634] Removed troublesome folder --- c-check/.gitignore | 10 ---- c-check/GildedRose.c | 90 ----------------------------------- c-check/GildedRose.h | 9 ---- c-check/GildedRoseTextTests.c | 43 ----------------- c-check/Makefile | 50 ------------------- c-check/README.md | 41 ---------------- c-check/test_main.c | 31 ------------ c-check/test_rose.c | 34 ------------- 8 files changed, 308 deletions(-) delete mode 100644 c-check/.gitignore delete mode 100644 c-check/GildedRose.c delete mode 100644 c-check/GildedRose.h delete mode 100644 c-check/GildedRoseTextTests.c delete mode 100644 c-check/Makefile delete mode 100644 c-check/README.md delete mode 100644 c-check/test_main.c delete mode 100644 c-check/test_rose.c diff --git a/c-check/.gitignore b/c-check/.gitignore deleted file mode 100644 index 65962297..00000000 --- a/c-check/.gitignore +++ /dev/null @@ -1,10 +0,0 @@ -*.o -*.gch -*.config -*.creator -*.creator.user -*.files -*.includes -*.iml -test_gildedrose -golden_rose diff --git a/c-check/GildedRose.c b/c-check/GildedRose.c deleted file mode 100644 index afb97bbe..00000000 --- a/c-check/GildedRose.c +++ /dev/null @@ -1,90 +0,0 @@ -#include -#include "GildedRose.h" - -Item* -init_item(Item* item, const char *name, int sellIn, int quality) -{ - item->sellIn = sellIn; - item->quality = quality; - item->name = strdup(name); - - return item; -} - -void update_quality(Item items[], int size) -{ - int i; - - for (i = 0; i < size; i++) - { - if (strcmp(items[i].name, "Aged Brie") && strcmp(items[i].name, "Backstage passes to a TAFKAL80ETC concert")) - { - if (items[i].quality > 0) - { - if (strcmp(items[i].name, "Sulfuras, Hand of Ragnaros")) - { - items[i].quality = items[i].quality - 1; - } - } - } - else - { - if (items[i].quality < 50) - { - items[i].quality = items[i].quality + 1; - - if (!strcmp(items[i].name, "Backstage passes to a TAFKAL80ETC concert")) - { - if (items[i].sellIn < 11) - { - if (items[i].quality < 50) - { - items[i].quality = items[i].quality + 1; - } - } - - if (items[i].sellIn < 6) - { - if (items[i].quality < 50) - { - items[i].quality = items[i].quality + 1; - } - } - } - } - } - - if (strcmp(items[i].name, "Sulfuras, Hand of Ragnaros")) - { - items[i].sellIn = items[i].sellIn - 1; - } - - if (items[i].sellIn < 0) - { - if (strcmp(items[i].name, "Aged Brie")) - { - if (strcmp(items[i].name, "Backstage passes to a TAFKAL80ETC concert")) - { - if (items[i].quality > 0) - { - if (strcmp(items[i].name, "Sulfuras, Hand of Ragnaros")) - { - items[i].quality = items[i].quality - 1; - } - } - } - else - { - items[i].quality = items[i].quality - items[i].quality; - } - } - else - { - if (items[i].quality < 50) - { - items[i].quality = items[i].quality + 1; - } - } - } - } -} diff --git a/c-check/GildedRose.h b/c-check/GildedRose.h deleted file mode 100644 index 78d54a08..00000000 --- a/c-check/GildedRose.h +++ /dev/null @@ -1,9 +0,0 @@ -typedef struct -{ - char *name; - int sellIn; - int quality; -} Item; - -extern Item* init_item(Item* item, const char *name, int sellIn, int quality); -extern void update_quality(Item items[], int size); diff --git a/c-check/GildedRoseTextTests.c b/c-check/GildedRoseTextTests.c deleted file mode 100644 index d200ca0c..00000000 --- a/c-check/GildedRoseTextTests.c +++ /dev/null @@ -1,43 +0,0 @@ -#include -#include "GildedRose.h" - -int -print_item(Item *item) -{ - return printf("%s, %d, %d\n", item->name, item->sellIn, item->quality); -} - -int main() -{ - Item items[9]; - int last = 0; - int day; - int index; - - init_item(items + last++, "+5 Dexterity Vest", 10, 20); - init_item(items + last++, "Aged Brie", 2, 0); - init_item(items + last++, "Elixir of the Mongoose", 5, 7); - init_item(items + last++, "Sulfuras, Hand of Ragnaros", 0, 80); - init_item(items + last++, "Sulfuras, Hand of Ragnaros", -1, 80); - init_item(items + last++, "Backstage passes to a TAFKAL80ETC concert", 15, 20); - init_item(items + last++, "Backstage passes to a TAFKAL80ETC concert", 10, 49); - init_item(items + last++, "Backstage passes to a TAFKAL80ETC concert", 5, 49); - // this Conjured item doesn't yet work properly - init_item(items + last++, "Conjured Mana Cake", 3, 6); - - puts("OMGHAI!"); - - for (day = 0; day <= 30; day++) - { - printf("-------- day %d --------\n", day); - printf("name, sellIn, quality\n"); - for(index = 0; index < last; index++) { - print_item(items + index); - } - - printf("\n"); - - update_quality(items, last); - } - return 0; -} diff --git a/c-check/Makefile b/c-check/Makefile deleted file mode 100644 index dabcf6b1..00000000 --- a/c-check/Makefile +++ /dev/null @@ -1,50 +0,0 @@ -# Makefile for building the kata file with the Google Testing Framework -# -# SYNOPSIS: -# -# make [all] - makes everything, runs tests -# make TARGET - makes the given target. -# make clean - removes all files generated by make. -# make memtest - run memory leak analysis - -# The _POSIX_C_SOURCE definition prevents the compiler from throwing warnings -CFLAGS = `pkg-config --cflags check` -g --std=c99 -D_POSIX_C_SOURCE=200809L -LIBS = `pkg-config --libs check` - -# All files that should be part of your test should start with 'test_' -TEST_SRC = $(wildcard test_*.c) -TEST_BASE = $(basename ${TEST_SRC}) -TEST_OBJECTS = $(addsuffix .o, ${TEST_BASE}) - -# All files that should be part of your main program should start with 'gilded_' -PROG_SRC = $(wildcard gilded_*.c) -PROG_BASE = $(basename ${PROG_SRC}) -PROG_OBJECTS = $(addsuffix .o, ${PROG_BASE}) - -OBJECT_UNDER_TEST = GildedRose.o ${PROG_OBJECTS} - -# This is the test application. You can run this program to see your test output -TEST_APP = test_gildedrose - - -# This will generate output for several products over a course of several days. -# You can run this application to build golden rule tests -GOLDEN_APP = golden_rose - -all: ${TEST_APP} ${GOLDEN_APP} - ./${TEST_APP} - -${TEST_APP}: ${TEST_OBJECTS} ${OBJECT_UNDER_TEST} - $(CC) $(CFLAGS) -o $@ $^ $(LIBS) - -${GOLDEN_APP}: GildedRoseTextTests.o ${OBJECT_UNDER_TEST} - $(CC) $(CFLAGS) -o $@ $^ - -# If you're not on a mac, you should run memtest (in fact, consider adding it to the 'all' target). -# If you're on a mac, complain to apple for breaking an important development tool. -memtest: ${TEST_APP} - valgrind --leak-check=full --error-exitcode=1 ./${TEST_APP} --nofork - -clean: - rm -f *.o - rm -f ${TEST_APP} diff --git a/c-check/README.md b/c-check/README.md deleted file mode 100644 index ec2cd02e..00000000 --- a/c-check/README.md +++ /dev/null @@ -1,41 +0,0 @@ -# Gilded Rose, C99 Edition - -The command "make" will build and run your tests, as well as build the program -golden_rose, which can serve as the basis for a golden-rule test. - - -## Assumptions - - gnu make and a C compiler (like gcc) is installed on your system and is in the PATH - - The check unit testing library is installed on your system (https://libcheck.github.io/check/) - - pkg-config is installed on your system - -## Usage - - Run `make` to build the program and run all tests - - Files which contain tests should be named `test_*.c` They will automatically - be included in your test suite. - - `GildedRose.h` should not be modified. The Goblin threat is real. - - New program logic may be included in files named `gilded_*.c` which will - automatically be included in both your tests and the final program. - -## Golden Rule tests - - The program `golden_rose` will generate text output. If you capture this - output after your first `make` you can use this as a reference for a golden - rule test. - - You can test your work against this reference by directing the output of your - current golden_rose to a file and using the `diff` utility to compare that - to the reference file you created above. - - To avoid the Goblin threat you can use `git diff GildedRose.h`, which should - have no output if you have left the precious Item structure unchanged. - -## Notes - - This project is tweaked to run on Linux systems, and will mostly work on Macs. - With some changes to the Makefile it can be made to run on BSD systems with - BSD make. An adventurous person could also get it to run on Windows. - - If you are working on a Macintosh computer you cannot run the memtest target, - because valgrind and OS X don't play nice any more. If you want to use the - memory checker OS X does run docker as a first class citizen. - - If you don't have pkg-config on your system, the only changes you'll need to - make are for the requirements of the check library. Mostly you need to - set the appropriate flags for threaded binaries, which may include some - special linker flags. The libcheck documentation will cover what you need - if you want to undertake this change. diff --git a/c-check/test_main.c b/c-check/test_main.c deleted file mode 100644 index 0d5a0de0..00000000 --- a/c-check/test_main.c +++ /dev/null @@ -1,31 +0,0 @@ -#include -#include -#include - -Suite *suite_rose(void); - -int main(int argc, char **argv) -{ - Suite *s; - SRunner *runner; - int number_fails; - int forkme = 1; - - if (argc > 1 && strcmp(argv[1], "--nofork") == 0) { - forkme = 0; - } - - s = suite_rose(); - runner = srunner_create(s); - - if (0 == forkme) { - srunner_set_fork_status(runner, CK_NOFORK); - } - - srunner_run_all(runner, CK_NORMAL); - number_fails = srunner_ntests_failed(runner); - - srunner_free(runner); - - return number_fails; -} diff --git a/c-check/test_rose.c b/c-check/test_rose.c deleted file mode 100644 index 30cc7544..00000000 --- a/c-check/test_rose.c +++ /dev/null @@ -1,34 +0,0 @@ -#include -#include "GildedRose.h" - - - -START_TEST(roseFoo) -{ - Item items[1]; - init_item(items, "foo", 0, 0); - update_quality(items, 1); - - ck_assert_str_eq("fixme", items[0].name); -} -END_TEST - -TCase *tcase_rose(void) -{ - TCase *tc; - - tc = tcase_create("gilded-rose"); - tcase_add_test(tc, roseFoo); - - return tc; -} - -Suite *suite_rose(void) -{ - Suite *s; - - s = suite_create("characterization-tests"); - suite_add_tcase(s, tcase_rose()); - - return s; -} From a8561778e964503223816ed1f9eb81d7bee69d73 Mon Sep 17 00:00:00 2001 From: Clay Dowling Date: Mon, 13 Mar 2017 21:30:37 -0400 Subject: [PATCH 210/634] Added C99 Solution --- c99/GildedRose.c | 90 +++++++++++++++++++++++++++++++++++++++ c99/GildedRose.h | 9 ++++ c99/GildedRoseTextTests.c | 43 +++++++++++++++++++ c99/Makefile | 51 ++++++++++++++++++++++ c99/README.md | 41 ++++++++++++++++++ c99/test_main.c | 31 ++++++++++++++ c99/test_rose.c | 34 +++++++++++++++ 7 files changed, 299 insertions(+) create mode 100644 c99/GildedRose.c create mode 100644 c99/GildedRose.h create mode 100644 c99/GildedRoseTextTests.c create mode 100644 c99/Makefile create mode 100644 c99/README.md create mode 100644 c99/test_main.c create mode 100644 c99/test_rose.c diff --git a/c99/GildedRose.c b/c99/GildedRose.c new file mode 100644 index 00000000..afb97bbe --- /dev/null +++ b/c99/GildedRose.c @@ -0,0 +1,90 @@ +#include +#include "GildedRose.h" + +Item* +init_item(Item* item, const char *name, int sellIn, int quality) +{ + item->sellIn = sellIn; + item->quality = quality; + item->name = strdup(name); + + return item; +} + +void update_quality(Item items[], int size) +{ + int i; + + for (i = 0; i < size; i++) + { + if (strcmp(items[i].name, "Aged Brie") && strcmp(items[i].name, "Backstage passes to a TAFKAL80ETC concert")) + { + if (items[i].quality > 0) + { + if (strcmp(items[i].name, "Sulfuras, Hand of Ragnaros")) + { + items[i].quality = items[i].quality - 1; + } + } + } + else + { + if (items[i].quality < 50) + { + items[i].quality = items[i].quality + 1; + + if (!strcmp(items[i].name, "Backstage passes to a TAFKAL80ETC concert")) + { + if (items[i].sellIn < 11) + { + if (items[i].quality < 50) + { + items[i].quality = items[i].quality + 1; + } + } + + if (items[i].sellIn < 6) + { + if (items[i].quality < 50) + { + items[i].quality = items[i].quality + 1; + } + } + } + } + } + + if (strcmp(items[i].name, "Sulfuras, Hand of Ragnaros")) + { + items[i].sellIn = items[i].sellIn - 1; + } + + if (items[i].sellIn < 0) + { + if (strcmp(items[i].name, "Aged Brie")) + { + if (strcmp(items[i].name, "Backstage passes to a TAFKAL80ETC concert")) + { + if (items[i].quality > 0) + { + if (strcmp(items[i].name, "Sulfuras, Hand of Ragnaros")) + { + items[i].quality = items[i].quality - 1; + } + } + } + else + { + items[i].quality = items[i].quality - items[i].quality; + } + } + else + { + if (items[i].quality < 50) + { + items[i].quality = items[i].quality + 1; + } + } + } + } +} diff --git a/c99/GildedRose.h b/c99/GildedRose.h new file mode 100644 index 00000000..78d54a08 --- /dev/null +++ b/c99/GildedRose.h @@ -0,0 +1,9 @@ +typedef struct +{ + char *name; + int sellIn; + int quality; +} Item; + +extern Item* init_item(Item* item, const char *name, int sellIn, int quality); +extern void update_quality(Item items[], int size); diff --git a/c99/GildedRoseTextTests.c b/c99/GildedRoseTextTests.c new file mode 100644 index 00000000..d200ca0c --- /dev/null +++ b/c99/GildedRoseTextTests.c @@ -0,0 +1,43 @@ +#include +#include "GildedRose.h" + +int +print_item(Item *item) +{ + return printf("%s, %d, %d\n", item->name, item->sellIn, item->quality); +} + +int main() +{ + Item items[9]; + int last = 0; + int day; + int index; + + init_item(items + last++, "+5 Dexterity Vest", 10, 20); + init_item(items + last++, "Aged Brie", 2, 0); + init_item(items + last++, "Elixir of the Mongoose", 5, 7); + init_item(items + last++, "Sulfuras, Hand of Ragnaros", 0, 80); + init_item(items + last++, "Sulfuras, Hand of Ragnaros", -1, 80); + init_item(items + last++, "Backstage passes to a TAFKAL80ETC concert", 15, 20); + init_item(items + last++, "Backstage passes to a TAFKAL80ETC concert", 10, 49); + init_item(items + last++, "Backstage passes to a TAFKAL80ETC concert", 5, 49); + // this Conjured item doesn't yet work properly + init_item(items + last++, "Conjured Mana Cake", 3, 6); + + puts("OMGHAI!"); + + for (day = 0; day <= 30; day++) + { + printf("-------- day %d --------\n", day); + printf("name, sellIn, quality\n"); + for(index = 0; index < last; index++) { + print_item(items + index); + } + + printf("\n"); + + update_quality(items, last); + } + return 0; +} diff --git a/c99/Makefile b/c99/Makefile new file mode 100644 index 00000000..113d1552 --- /dev/null +++ b/c99/Makefile @@ -0,0 +1,51 @@ +# Makefile for building the kata file with the Google Testing Framework +# +# SYNOPSIS: +# +# make [all] - makes everything, runs tests +# make TARGET - makes the given target. +# make clean - removes all files generated by make. +# make memtest - run memory leak analysis + +# The _POSIX_C_SOURCE definition prevents the compiler from throwing warnings +CFLAGS = `pkg-config --cflags check` -g --std=c99 -D_POSIX_C_SOURCE=200809L +LIBS = `pkg-config --libs check` + +# All files that should be part of your test should start with 'test_' +TEST_SRC = $(wildcard test_*.c) +TEST_BASE = $(basename ${TEST_SRC}) +TEST_OBJECTS = $(addsuffix .o, ${TEST_BASE}) + +# All files that should be part of your main program should start with 'gilded_' +PROG_SRC = $(wildcard gilded_*.c) +PROG_BASE = $(basename ${PROG_SRC}) +PROG_OBJECTS = $(addsuffix .o, ${PROG_BASE}) + +OBJECT_UNDER_TEST = GildedRose.o ${PROG_OBJECTS} + +# This is the test application. You can run this program to see your test output +TEST_APP = test_gildedrose + + +# This will generate output for several products over a course of several days. +# You can run this application to build golden rule tests +GOLDEN_APP = golden_rose + +all: ${TEST_APP} ${GOLDEN_APP} + ./${TEST_APP} + +${TEST_APP}: ${TEST_OBJECTS} ${OBJECT_UNDER_TEST} + $(CC) $(CFLAGS) -o $@ $^ $(LIBS) + +${GOLDEN_APP}: GildedRoseTextTests.o ${OBJECT_UNDER_TEST} + $(CC) $(CFLAGS) -o $@ $^ + +# If you're not on a mac, you should run memtest (in fact, consider adding it to the 'all' target). +# If you're on a mac, complain to apple for breaking an important development tool. +memtest: ${TEST_APP} + valgrind --leak-check=full --error-exitcode=1 ./${TEST_APP} --nofork + +clean: + rm -f *.o + rm -f ${TEST_APP} + rm -f ${GOLDEN_APP} diff --git a/c99/README.md b/c99/README.md new file mode 100644 index 00000000..ec2cd02e --- /dev/null +++ b/c99/README.md @@ -0,0 +1,41 @@ +# Gilded Rose, C99 Edition + +The command "make" will build and run your tests, as well as build the program +golden_rose, which can serve as the basis for a golden-rule test. + + +## Assumptions + - gnu make and a C compiler (like gcc) is installed on your system and is in the PATH + - The check unit testing library is installed on your system (https://libcheck.github.io/check/) + - pkg-config is installed on your system + +## Usage + - Run `make` to build the program and run all tests + - Files which contain tests should be named `test_*.c` They will automatically + be included in your test suite. + - `GildedRose.h` should not be modified. The Goblin threat is real. + - New program logic may be included in files named `gilded_*.c` which will + automatically be included in both your tests and the final program. + +## Golden Rule tests + - The program `golden_rose` will generate text output. If you capture this + output after your first `make` you can use this as a reference for a golden + rule test. + - You can test your work against this reference by directing the output of your + current golden_rose to a file and using the `diff` utility to compare that + to the reference file you created above. + - To avoid the Goblin threat you can use `git diff GildedRose.h`, which should + have no output if you have left the precious Item structure unchanged. + +## Notes + - This project is tweaked to run on Linux systems, and will mostly work on Macs. + With some changes to the Makefile it can be made to run on BSD systems with + BSD make. An adventurous person could also get it to run on Windows. + - If you are working on a Macintosh computer you cannot run the memtest target, + because valgrind and OS X don't play nice any more. If you want to use the + memory checker OS X does run docker as a first class citizen. + - If you don't have pkg-config on your system, the only changes you'll need to + make are for the requirements of the check library. Mostly you need to + set the appropriate flags for threaded binaries, which may include some + special linker flags. The libcheck documentation will cover what you need + if you want to undertake this change. diff --git a/c99/test_main.c b/c99/test_main.c new file mode 100644 index 00000000..0d5a0de0 --- /dev/null +++ b/c99/test_main.c @@ -0,0 +1,31 @@ +#include +#include +#include + +Suite *suite_rose(void); + +int main(int argc, char **argv) +{ + Suite *s; + SRunner *runner; + int number_fails; + int forkme = 1; + + if (argc > 1 && strcmp(argv[1], "--nofork") == 0) { + forkme = 0; + } + + s = suite_rose(); + runner = srunner_create(s); + + if (0 == forkme) { + srunner_set_fork_status(runner, CK_NOFORK); + } + + srunner_run_all(runner, CK_NORMAL); + number_fails = srunner_ntests_failed(runner); + + srunner_free(runner); + + return number_fails; +} diff --git a/c99/test_rose.c b/c99/test_rose.c new file mode 100644 index 00000000..30cc7544 --- /dev/null +++ b/c99/test_rose.c @@ -0,0 +1,34 @@ +#include +#include "GildedRose.h" + + + +START_TEST(roseFoo) +{ + Item items[1]; + init_item(items, "foo", 0, 0); + update_quality(items, 1); + + ck_assert_str_eq("fixme", items[0].name); +} +END_TEST + +TCase *tcase_rose(void) +{ + TCase *tc; + + tc = tcase_create("gilded-rose"); + tcase_add_test(tc, roseFoo); + + return tc; +} + +Suite *suite_rose(void) +{ + Suite *s; + + s = suite_create("characterization-tests"); + suite_add_tcase(s, tcase_rose()); + + return s; +} From 7613d0b921cd5dc59ea3aef8f605da9fee97aa05 Mon Sep 17 00:00:00 2001 From: emilybache Date: Fri, 12 May 2017 11:29:38 +0200 Subject: [PATCH 211/634] adding config file for bettercodehub so I can see how many refactoring targets it finds in this repo --- .bettercodehub.yml | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 .bettercodehub.yml diff --git a/.bettercodehub.yml b/.bettercodehub.yml new file mode 100644 index 00000000..5e00bdf0 --- /dev/null +++ b/.bettercodehub.yml @@ -0,0 +1,17 @@ +exclude: +- /js/lib/.* +component_depth: 1 +languages: +- cpp +- csharp +- go +- groovy +- java +- javascript +- perl +- php +- python +- ruby +- scala +- script +- swift From f76aff16c07a90fea6deb2a93b95e32522e3e64f Mon Sep 17 00:00:00 2001 From: emilybache Date: Fri, 12 May 2017 11:50:14 +0200 Subject: [PATCH 212/634] added better code hub badge to readme file --- README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/README.md b/README.md index c31395e9..83f8e59d 100644 --- a/README.md +++ b/README.md @@ -39,3 +39,9 @@ I've also set this kata up on [cyber-dojo](http://cyber-dojo.org) for several la - [RSpec, Ruby](http://cyber-dojo.org/forker/fork/8E58B0AD16?avatar=raccoon&tag=3) - [Python](http://cyber-dojo.org/forker/fork/297041AA7A?avatar=lion&tag=4) - [Cucumber, Java](http://cyber-dojo.org/forker/fork/0F82D4BA89?avatar=gorilla&tag=45) - for this one I've also written some step definitions for you + +# Better Code Hub + +I analysed this repo according to the clean code standards on [Better Code Hub](https://bettercodehub.com) just to get an independent opinion of how bad the code is. Perhaps unsurprisingly, the compliance score is low! + +[![BCH compliance](https://bettercodehub.com/edge/badge/emilybache/GildedRose-Refactoring-Kata?branch=master)](https://bettercodehub.com/) From 62276f5f0f40fa66f91bfb3a6678e62ef82e9885 Mon Sep 17 00:00:00 2001 From: emilybache Date: Fri, 12 May 2017 11:51:16 +0200 Subject: [PATCH 213/634] tweaked formatting --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 83f8e59d..c8c08088 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,5 @@ +# Gilded Rose Refactoring Kata + This Kata was originally created by Terry Hughes (http://twitter.com/#!/TerryHughes). It is already on GitHub [here](https://github.com/NotMyself/GildedRose). See also [Bobby Johnson's description of the kata](http://iamnotmyself.com/2011/02/13/refactor-this-the-gilded-rose-kata/). I translated the original C# into a few other languages, (with a little help from my friends!), and slightly changed the starting position. This means I've actually done a small amount of refactoring already compared with the original form of the kata, and made it easier to get going with writing tests by giving you one failing unit test to start with. I also added test fixtures for Text-Based approval testing with TextTest (see [the TextTests](https://github.com/emilybache/GildedRose-Refactoring-Kata/tree/master/texttests)) @@ -40,7 +42,7 @@ I've also set this kata up on [cyber-dojo](http://cyber-dojo.org) for several la - [Python](http://cyber-dojo.org/forker/fork/297041AA7A?avatar=lion&tag=4) - [Cucumber, Java](http://cyber-dojo.org/forker/fork/0F82D4BA89?avatar=gorilla&tag=45) - for this one I've also written some step definitions for you -# Better Code Hub +## Better Code Hub I analysed this repo according to the clean code standards on [Better Code Hub](https://bettercodehub.com) just to get an independent opinion of how bad the code is. Perhaps unsurprisingly, the compliance score is low! From fc22086f3ee43b4e996da1887796ac7c0329cbab Mon Sep 17 00:00:00 2001 From: Balthasar Biedermann Date: Tue, 6 Jun 2017 23:37:24 +0700 Subject: [PATCH 214/634] Fix JUnit/Java cyber-dojo The cyber-dojo.org java kata was broken, Probably because of an upgraded java or junit. I updated the cyber-dojo.sh and fixed the link in the README.md to use the new version. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index c8c08088..c6789577 100644 --- a/README.md +++ b/README.md @@ -34,7 +34,7 @@ The Text-Based tests in this repository are designed to be used with the tool "T I've also set this kata up on [cyber-dojo](http://cyber-dojo.org) for several languages, so you can get going really quickly: -- [JUnit, Java](http://cyber-dojo.org/forker/fork/751DD02C4C?avatar=snake&tag=4) +- [JUnit, Java](http://cyber-dojo.org/forker/fork/751DD02C4C?avatar=snake&tag=8) - [C#](http://cyber-dojo.org/forker/fork/5C5AC766B0?avatar=koala&tag=1) - [C++](http://cyber-dojo.org/forker/fork/AA86ECBCC9?avatar=rhino&tag=7) - [Ruby](http://cyber-dojo.org/forker/fork/A8943EAF92?avatar=hippo&tag=9) From c97e1600e5f9c60107e42e5f693bc355042de25d Mon Sep 17 00:00:00 2001 From: Balthasar Biedermann Date: Tue, 6 Jun 2017 23:44:08 +0700 Subject: [PATCH 215/634] Fix C# cyber-dojo --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index c6789577..226d5537 100644 --- a/README.md +++ b/README.md @@ -35,7 +35,7 @@ The Text-Based tests in this repository are designed to be used with the tool "T I've also set this kata up on [cyber-dojo](http://cyber-dojo.org) for several languages, so you can get going really quickly: - [JUnit, Java](http://cyber-dojo.org/forker/fork/751DD02C4C?avatar=snake&tag=8) -- [C#](http://cyber-dojo.org/forker/fork/5C5AC766B0?avatar=koala&tag=1) +- [C#](http://cyber-dojo.org/forker/fork/5C5AC766B0?avatar=koala&tag=3) - [C++](http://cyber-dojo.org/forker/fork/AA86ECBCC9?avatar=rhino&tag=7) - [Ruby](http://cyber-dojo.org/forker/fork/A8943EAF92?avatar=hippo&tag=9) - [RSpec, Ruby](http://cyber-dojo.org/forker/fork/8E58B0AD16?avatar=raccoon&tag=3) From c359f755c8bde6fe3fd4adcbd784962f1a772d90 Mon Sep 17 00:00:00 2001 From: Balthasar Biedermann Date: Tue, 6 Jun 2017 23:58:48 +0700 Subject: [PATCH 216/634] Fix Cucumber, Java cyber-dojo --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 226d5537..3549e936 100644 --- a/README.md +++ b/README.md @@ -40,7 +40,7 @@ I've also set this kata up on [cyber-dojo](http://cyber-dojo.org) for several la - [Ruby](http://cyber-dojo.org/forker/fork/A8943EAF92?avatar=hippo&tag=9) - [RSpec, Ruby](http://cyber-dojo.org/forker/fork/8E58B0AD16?avatar=raccoon&tag=3) - [Python](http://cyber-dojo.org/forker/fork/297041AA7A?avatar=lion&tag=4) -- [Cucumber, Java](http://cyber-dojo.org/forker/fork/0F82D4BA89?avatar=gorilla&tag=45) - for this one I've also written some step definitions for you +- [Cucumber, Java](http://cyber-dojo.org/forker/fork/0F82D4BA89?avatar=gorilla&tag=48) - for this one I've also written some step definitions for you ## Better Code Hub From 10346b66c81eda2879a9893ef02fbb4ecbf4a6c6 Mon Sep 17 00:00:00 2001 From: Paulo Clavijo Esteban Date: Fri, 30 Jun 2017 17:21:55 +0100 Subject: [PATCH 217/634] Added GildedRose for TypeScript --- TypeScript/.gitignore | 10 ++++ TypeScript/app/gilded-rose.ts | 69 ++++++++++++++++++++++++++++ TypeScript/package.json | 44 ++++++++++++++++++ TypeScript/test/guilded-rose.spec.ts | 12 +++++ TypeScript/test/mocha.opts | 4 ++ TypeScript/tsconfig.json | 11 +++++ 6 files changed, 150 insertions(+) create mode 100644 TypeScript/.gitignore create mode 100644 TypeScript/app/gilded-rose.ts create mode 100644 TypeScript/package.json create mode 100644 TypeScript/test/guilded-rose.spec.ts create mode 100644 TypeScript/test/mocha.opts create mode 100644 TypeScript/tsconfig.json diff --git a/TypeScript/.gitignore b/TypeScript/.gitignore new file mode 100644 index 00000000..7d7d75b0 --- /dev/null +++ b/TypeScript/.gitignore @@ -0,0 +1,10 @@ +.DS_Store +.idea +node_modules +typings +app/**/*.js +app/**/*.js.map +test/**/*.js +test/**/*.js.map +coverage +.nyc_output diff --git a/TypeScript/app/gilded-rose.ts b/TypeScript/app/gilded-rose.ts new file mode 100644 index 00000000..c7d58c65 --- /dev/null +++ b/TypeScript/app/gilded-rose.ts @@ -0,0 +1,69 @@ +export class Item { + name: string; + sellIn: number; + quality: number; + + constructor(name, sellIn, quality) { + this.name = name; + this.sellIn = sellIn; + this.quality = quality; + } +} + +export class GildedRose { + items: Array; + + constructor(items = []) { + this.items = items; + } + + updateQuality() { + for (let i = 0; i < this.items.length; i++) { + if (this.items[i].name != 'Aged Brie' && this.items[i].name != 'Backstage passes to a TAFKAL80ETC concert') { + if (this.items[i].quality > 0) { + if (this.items[i].name != 'Sulfuras, Hand of Ragnaros') { + this.items[i].quality = this.items[i].quality - 1 + } + } + } else { + if (this.items[i].quality < 50) { + this.items[i].quality = this.items[i].quality + 1 + if (this.items[i].name == 'Backstage passes to a TAFKAL80ETC concert') { + if (this.items[i].sellIn < 11) { + if (this.items[i].quality < 50) { + this.items[i].quality = this.items[i].quality + 1 + } + } + if (this.items[i].sellIn < 6) { + if (this.items[i].quality < 50) { + this.items[i].quality = this.items[i].quality + 1 + } + } + } + } + } + if (this.items[i].name != 'Sulfuras, Hand of Ragnaros') { + this.items[i].sellIn = this.items[i].sellIn - 1; + } + if (this.items[i].sellIn < 0) { + if (this.items[i].name != 'Aged Brie') { + if (this.items[i].name != 'Backstage passes to a TAFKAL80ETC concert') { + if (this.items[i].quality > 0) { + if (this.items[i].name != 'Sulfuras, Hand of Ragnaros') { + this.items[i].quality = this.items[i].quality - 1 + } + } + } else { + this.items[i].quality = this.items[i].quality - this.items[i].quality + } + } else { + if (this.items[i].quality < 50) { + this.items[i].quality = this.items[i].quality + 1 + } + } + } + } + + return this.items; + } +} diff --git a/TypeScript/package.json b/TypeScript/package.json new file mode 100644 index 00000000..28b6bb3f --- /dev/null +++ b/TypeScript/package.json @@ -0,0 +1,44 @@ +{ + "name": "typescript-mocha-kata-seed", + "version": "1.4.0", + "description": "Seed project for TDD code katas on TypeScript and mocha", + "main": "index.js", + "scripts": { + "precompile": "rimraf app/**/*.js test/**/*.js", + "compile": "tsc", + "pretest": "rimraf app/**/*.js test/**/*.js", + "test": "nyc mocha" + }, + "author": "paucls", + "homepage": "https://github.com/paucls/typescript-mocha-kata-seed", + "license": "ISC", + "private": true, + "devDependencies": { + "@types/chai": "~3.5.2", + "@types/mocha": "~2.2.41", + "@types/node": "~7.0.18", + "chai": "~3.5.0", + "mocha": "~3.2.0", + "nyc": "~11.0.3", + "rimraf": "~2.5.2", + "ts-node": "~3.1.0", + "typescript": "~2.2.0" + }, + "nyc": { + "extension": [ + ".ts" + ], + "exclude": [ + "**/*.d.ts", + "test/**" + ], + "require": [ + "ts-node/register" + ], + "reporter": [ + "html", + "text" + ] + } +} + diff --git a/TypeScript/test/guilded-rose.spec.ts b/TypeScript/test/guilded-rose.spec.ts new file mode 100644 index 00000000..02b4f154 --- /dev/null +++ b/TypeScript/test/guilded-rose.spec.ts @@ -0,0 +1,12 @@ +import { expect } from 'chai'; +import { Item, GildedRose } from '../app/gilded-rose'; + +describe('Gilded Rose', function () { + + it('should foo', function() { + const gilgedRose = new GildedRose([ new Item('foo', 0, 0) ]); + const items = gilgedRose.updateQuality(); + expect(items[0].name).to.equal('fixme'); + }); + +}); \ No newline at end of file diff --git a/TypeScript/test/mocha.opts b/TypeScript/test/mocha.opts new file mode 100644 index 00000000..bf3868c8 --- /dev/null +++ b/TypeScript/test/mocha.opts @@ -0,0 +1,4 @@ +--compilers ts-node/register +--require source-map-support/register +--recursive +test/**/*.ts diff --git a/TypeScript/tsconfig.json b/TypeScript/tsconfig.json new file mode 100644 index 00000000..4f713921 --- /dev/null +++ b/TypeScript/tsconfig.json @@ -0,0 +1,11 @@ +{ + "compilerOptions": { + "module": "commonjs", + "target": "es5", + "noImplicitAny": false, + "sourceMap": false + }, + "exclude": [ + "node_modules" + ] +} From 34c9b0bbcac8bac0946d1ec49061614dd7649eb5 Mon Sep 17 00:00:00 2001 From: Harry Dennen Date: Thu, 6 Jul 2017 10:16:37 +0200 Subject: [PATCH 218/634] fix(js and ts): typo - 'gilged' to 'gilded' in respective specs --- TypeScript/test/guilded-rose.spec.ts | 6 +++--- js/spec/gilded_rose_spec.js | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/TypeScript/test/guilded-rose.spec.ts b/TypeScript/test/guilded-rose.spec.ts index 02b4f154..0c192caf 100644 --- a/TypeScript/test/guilded-rose.spec.ts +++ b/TypeScript/test/guilded-rose.spec.ts @@ -4,9 +4,9 @@ import { Item, GildedRose } from '../app/gilded-rose'; describe('Gilded Rose', function () { it('should foo', function() { - const gilgedRose = new GildedRose([ new Item('foo', 0, 0) ]); - const items = gilgedRose.updateQuality(); + const gildedRose = new GildedRose([ new Item('foo', 0, 0) ]); + const items = gildedRose.updateQuality(); expect(items[0].name).to.equal('fixme'); }); -}); \ No newline at end of file +}); diff --git a/js/spec/gilded_rose_spec.js b/js/spec/gilded_rose_spec.js index 76cbb268..44c3838b 100644 --- a/js/spec/gilded_rose_spec.js +++ b/js/spec/gilded_rose_spec.js @@ -1,8 +1,8 @@ describe("Gilded Rose", function() { it("should foo", function() { - const gilgedRose = new Shop([ new Item("foo", 0, 0) ]); - const items = gilgedRose.updateQuality(); + const gildedRose = new Shop([ new Item("foo", 0, 0) ]); + const items = gildedRose.updateQuality(); expect(items[0].name).toEqual("fixme"); }); From 52e4b9aeff1569db9106867fae7ec34e3bedd112 Mon Sep 17 00:00:00 2001 From: y0m0 Date: Wed, 12 Jul 2017 22:23:26 +0100 Subject: [PATCH 219/634] Fix TexttestFixture - broken after last commit which updates gilded_rose.js to use ES2015 class syntax - creates instance of class Shop - creates items array - updates showItemsFor --- js/TexttestFixture.html | 13 +++++++++---- js/src/gilded_rose.js | 14 +++++++------- 2 files changed, 16 insertions(+), 11 deletions(-) diff --git a/js/TexttestFixture.html b/js/TexttestFixture.html index cf453495..0fa50cb9 100644 --- a/js/TexttestFixture.html +++ b/js/TexttestFixture.html @@ -12,6 +12,8 @@ $('body').append('

OMGHAI!

'); + items = []; + items.push(new Item('+5 Dexterity Vest', 10, 20)); items.push(new Item('Aged Brie', 2, 0)); items.push(new Item('Elixir of the Mongoose', 5, 7)); @@ -23,12 +25,15 @@ // this conjured item does not work properly yet items.push(new Item('Conjured Mana Cake', 3, 6)); + + gildedRose = new Shop(items); + var days = 2; for (var i = 0; i < days; i++) { showHeaderFor(i); showItemsFor(i); - update_quality(); + gildedRose.updateQuality(); } function showHeaderFor(day) { @@ -37,9 +42,9 @@ function showItemsFor(day) { $('body').append('

name, sellIn, quality

'); - for (var j = 0; j < items.length; j++) { - var item = items[j]; - $('body').append('

' + item.name + ', ' + item.sell_in + ', ' + item.quality + '

'); + for (var j = 0; j < gildedRose.items.length; j++) { + var item = gildedRose.items[j]; + $('body').append('

' + item.name + ', ' + item.sellIn + ', ' + item.quality + '

'); } $('body').append('
'); } diff --git a/js/src/gilded_rose.js b/js/src/gilded_rose.js index 0bbba286..5358125e 100644 --- a/js/src/gilded_rose.js +++ b/js/src/gilded_rose.js @@ -15,21 +15,21 @@ class Shop { if (this.items[i].name != 'Aged Brie' && this.items[i].name != 'Backstage passes to a TAFKAL80ETC concert') { if (this.items[i].quality > 0) { if (this.items[i].name != 'Sulfuras, Hand of Ragnaros') { - this.items[i].quality = this.items[i].quality - 1 + this.items[i].quality = this.items[i].quality - 1; } } } else { if (this.items[i].quality < 50) { - this.items[i].quality = this.items[i].quality + 1 + this.items[i].quality = this.items[i].quality + 1; if (this.items[i].name == 'Backstage passes to a TAFKAL80ETC concert') { if (this.items[i].sellIn < 11) { if (this.items[i].quality < 50) { - this.items[i].quality = this.items[i].quality + 1 + this.items[i].quality = this.items[i].quality + 1; } } if (this.items[i].sellIn < 6) { if (this.items[i].quality < 50) { - this.items[i].quality = this.items[i].quality + 1 + this.items[i].quality = this.items[i].quality + 1; } } } @@ -43,15 +43,15 @@ class Shop { if (this.items[i].name != 'Backstage passes to a TAFKAL80ETC concert') { if (this.items[i].quality > 0) { if (this.items[i].name != 'Sulfuras, Hand of Ragnaros') { - this.items[i].quality = this.items[i].quality - 1 + this.items[i].quality = this.items[i].quality - 1; } } } else { - this.items[i].quality = this.items[i].quality - this.items[i].quality + this.items[i].quality = this.items[i].quality - this.items[i].quality; } } else { if (this.items[i].quality < 50) { - this.items[i].quality = this.items[i].quality + 1 + this.items[i].quality = this.items[i].quality + 1; } } } From 03834be1cae373438d6903da1f69bf77b3b92ff5 Mon Sep 17 00:00:00 2001 From: Kewerson Hugo Date: Thu, 13 Jul 2017 18:29:44 -0300 Subject: [PATCH 220/634] Add the brazilian portuguese translation --- GildedRoseRequirements_pt-BR.md | 35 +++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 GildedRoseRequirements_pt-BR.md diff --git a/GildedRoseRequirements_pt-BR.md b/GildedRoseRequirements_pt-BR.md new file mode 100644 index 00000000..bfcb23cb --- /dev/null +++ b/GildedRoseRequirements_pt-BR.md @@ -0,0 +1,35 @@ +# Especificações de Requisitos de Gilded Rose + +Bem-vindo ao time Gilded Rose. Como você deve saber, nós somos uma pequena pousada estratégimante localizada em uma pretigiosa cidade, atendida pelo amigavel atendente Allison. Além de ser uma pousada, nós também compramos e vendemos as mercadorias de melhor qualidade. Infelizmente nossas mercadorias vão perdendo a qualidade conforme chegam próximo sua data de venda. + +Nós temos um sistema instalado que atualiza automaticamente os preços do nosso estoque. Esse sistema foi criado por um rapaz sem noção chamado Leeroy, que agora se dedica à novas aventuras. Seu trabalho será adicionar uma nova funcionalidade para o nosso sistema para que possamos vender uma nova categoria de itens. + +## Descrição preliminar + +Vamos dar uma breve introdução do nosso sistema: + +* Todos os itens (classe `Item`) possuem uma propriedade chamada `SellIn` que informa o número de dias que temos para vende-lo +* Todos os itens possuem uma propriedade chamada `quality` que informa o quão valioso é o item. +* No final do dia, nosso sistema decrementa os valores das propriedades `SellIn` e `quality` de cada um dos itens do estoque através do método `updateQuality`. + +Bastante simples, não é? Bem, agora que as coisas ficam interessantes: + +* Quando a data de venda do item tiver passado, a qualidade (`quality`) do item diminui duas vezes mais rapido. +* A qualidade (`quality`) do item não pode ser negativa +* O "Queijo Brie envelhecido" (`Aged Brie`), aumenta sua qualidade (`quality`) em `1` unidade a medida que envelhece. +* A qualidade (`quality`) de um item não pode ser maior que 50. +* O item "Sulfuras" (`Sulfuras`), por ser um item lendário, não precisa ter uma data de venda (`SellIn`) e sua qualidade (`quality`) não precisa ser diminuida. +* O item "Entrada para os Bastidores" (`Backstage Passes`), assim como o "Queijo Brie envelhecido", aumenta sua qualidade (`quality`) a medida que o dia da venda (`SellIn`) se aproxima; + * A qualidade (`quality`) aumenta em `2` unidades quando a data de venda (`SellIn`) é igual ou menor que `10`. + * A qualidade (`quality`) aumenta em `3` unidades quando a data de venda (`SellIn`) é igual ou menor que `5`. + * A qualidade (`quality`) do item vai direto à `0` quando a data de venda (`SellIn`) tiver passado. + +Nós recentemente assinamos um suplimento de itens Conjurados Magicamente. Isto requer que nós atualizemos nosso sistema: + +* Os itens "Conjurados" (`Conjured`) diminuem a qualidade (`quality`) duas vezes mais rápido que os outros itens. + +Sinta-se livre para fazer qualquer alteração no método `updateQuality` e adicionar código novo contanto que tudo continue funcionando perfeitamente. Entretanto, não altere o código da classe `Item` ou da propriedade `Items` na classe `GildedRose` pois elas pertencem ao Goblin que irá te matar com um golpe pois ele não acredita na cultura de código compartilhado. + +## Notas Finais + +Para esclarecer: Um item não pode ter uma qualidade (`quality`) maior que `50`, entretanto as "Sulfuras" por serem um item lendário vão ter uma qualidade imutavel de `80`. From 842cc81eb244e48b7753c97bb4479d5a83097a89 Mon Sep 17 00:00:00 2001 From: Kewerson Hugo Date: Thu, 13 Jul 2017 18:46:22 -0300 Subject: [PATCH 221/634] Update GildedRoseRequirements_pt-BR.md --- GildedRoseRequirements_pt-BR.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/GildedRoseRequirements_pt-BR.md b/GildedRoseRequirements_pt-BR.md index bfcb23cb..4498c1cb 100644 --- a/GildedRoseRequirements_pt-BR.md +++ b/GildedRoseRequirements_pt-BR.md @@ -1,6 +1,6 @@ # Especificações de Requisitos de Gilded Rose -Bem-vindo ao time Gilded Rose. Como você deve saber, nós somos uma pequena pousada estratégimante localizada em uma pretigiosa cidade, atendida pelo amigavel atendente Allison. Além de ser uma pousada, nós também compramos e vendemos as mercadorias de melhor qualidade. Infelizmente nossas mercadorias vão perdendo a qualidade conforme chegam próximo sua data de venda. +Bem-vindo ao time Gilded Rose. Como você deve saber, nós somos uma pequena pousada estrategicamente localizada em uma prestigiosa cidade, atendida pelo amigavel atendente Allison. Além de ser uma pousada, nós também compramos e vendemos as mercadorias de melhor qualidade. Infelizmente nossas mercadorias vão perdendo a qualidade conforme chegam próximo sua data de venda. Nós temos um sistema instalado que atualiza automaticamente os preços do nosso estoque. Esse sistema foi criado por um rapaz sem noção chamado Leeroy, que agora se dedica à novas aventuras. Seu trabalho será adicionar uma nova funcionalidade para o nosso sistema para que possamos vender uma nova categoria de itens. @@ -24,7 +24,7 @@ Bastante simples, não é? Bem, agora que as coisas ficam interessantes: * A qualidade (`quality`) aumenta em `3` unidades quando a data de venda (`SellIn`) é igual ou menor que `5`. * A qualidade (`quality`) do item vai direto à `0` quando a data de venda (`SellIn`) tiver passado. -Nós recentemente assinamos um suplimento de itens Conjurados Magicamente. Isto requer que nós atualizemos nosso sistema: +Nós recentemente assinamos um suprimento de itens Conjurados Magicamente. Isto requer que nós atualizemos nosso sistema: * Os itens "Conjurados" (`Conjured`) diminuem a qualidade (`quality`) duas vezes mais rápido que os outros itens. From a5309b3230b957cb0ee672b6d44f38ef63302b27 Mon Sep 17 00:00:00 2001 From: cono Date: Fri, 14 Jul 2017 16:27:14 +0300 Subject: [PATCH 222/634] Add Perl6 version --- .gitignore | 1 + perl6/lib/GildedRose.pm6 | 66 ++++++++++++++++++++++++++++++++++++ perl6/lib/Item.pm6 | 11 ++++++ perl6/test.p6 | 16 +++++++++ perl6/texttest_fixture.p6 | 70 +++++++++++++++++++++++++++++++++++++++ 5 files changed, 164 insertions(+) create mode 100644 perl6/lib/GildedRose.pm6 create mode 100644 perl6/lib/Item.pm6 create mode 100755 perl6/test.p6 create mode 100755 perl6/texttest_fixture.p6 diff --git a/.gitignore b/.gitignore index cbda76fc..b56f217b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ .idea/workspace.xml *.pyc +/perl6/lib/.precomp diff --git a/perl6/lib/GildedRose.pm6 b/perl6/lib/GildedRose.pm6 new file mode 100644 index 00000000..eae84d95 --- /dev/null +++ b/perl6/lib/GildedRose.pm6 @@ -0,0 +1,66 @@ +use v6; + +use Item; + +class GildedRose { + has Item @.items; + + method update_quality { + for @!items -> $item { + if ($item.name ne 'Aged Brie' && $item.name ne 'Backstage passes to a TAFKAL80ETC concert') { + if ( $item.quality > 0 ) { + if ( $item.name ne 'Sulfuras, Hand of Ragnaros' ) { + $item.quality = $item.quality - 1; + } + } + } + else { + if ( $item.quality < 50 ) { + $item.quality = $item.quality + 1; + + if ( $item.name eq 'Backstage passes to a TAFKAL80ETC concert' ) + { + if ( $item.sell_in < 11 ) { + if ( $item.quality < 50 ) { + $item.quality = $item.quality + 1; + } + } + + if ( $item.sell_in < 6 ) { + if ( $item.quality < 50 ) { + $item.quality = $item.quality + 1; + } + } + } + } + } + + if ( $item.name ne 'Sulfuras, Hand of Ragnaros' ) { + $item.sell_in = $item.sell_in - 1; + } + + if ( $item.sell_in < 0 ) { + if ( $item.name ne 'Aged Brie' ) { + if ( $item.name ne + 'Backstage passes to a TAFKAL80ETC concert' ) + { + if ( $item.quality > 0 ) { + if ( $item.name ne 'Sulfuras, Hand of Ragnaros' ) { + $item.quality = $item.quality - 1; + } + } + } + else { + $item.quality = $item.quality - $item.quality; + } + } + else { + if ( $item.quality < 50 ) { + $item.quality = $item.quality + 1; + } + } + } + } + return; + } +}; diff --git a/perl6/lib/Item.pm6 b/perl6/lib/Item.pm6 new file mode 100644 index 00000000..d2e5dd1a --- /dev/null +++ b/perl6/lib/Item.pm6 @@ -0,0 +1,11 @@ +use v6; + +class Item { + has Str $.name; + has Int $.sell_in is rw = 0; + has Int $.quality is rw = 0; + + method Str { + "{$!name}, {$!sell_in}, {$!quality}" + } +}; diff --git a/perl6/test.p6 b/perl6/test.p6 new file mode 100755 index 00000000..5bb61261 --- /dev/null +++ b/perl6/test.p6 @@ -0,0 +1,16 @@ +#!/usr/bin/env perl6 + +use v6; +use Test; +use lib 'lib'; + +use GildedRose; +use Item; + +my $item = Item.new(:name); +my $app = GildedRose.new(items => ($item)); + +$app.update_quality(); +is $app.items[0].name, 'fixme', "first day pass"; + +done-testing; diff --git a/perl6/texttest_fixture.p6 b/perl6/texttest_fixture.p6 new file mode 100755 index 00000000..d3e405d7 --- /dev/null +++ b/perl6/texttest_fixture.p6 @@ -0,0 +1,70 @@ +#!/usr/bin/env perl6 + +use v6; + +use lib 'lib'; + +use GildedRose; +use Item; + +print 'OMGHAI!', "\n"; +my @items = ( + Item.new( + name => '+5 Dexterity Vest', + sell_in => 10, + quality => 20 + ), + Item.new( + name => 'Aged Brie', + sell_in => 2, + quality => 0 + ), + Item.new( + name => 'Elixir of the Mongoose', + sell_in => 5, + quality => 7 + ), + Item.new( + name => 'Sulfuras, Hand of Ragnaros', + sell_in => 0, + quality => 80 + ), + Item.new( + name => 'Sulfuras, Hand of Ragnaros', + sell_in => -1, + quality => 80 + ), + Item.new( + name => 'Backstage passes to a TAFKAL80ETC concert', + sell_in => 15, + quality => 20 + ), + Item.new( + name => 'Backstage passes to a TAFKAL80ETC concert', + sell_in => 10, + quality => 49 + ), + Item.new( + name => 'Backstage passes to a TAFKAL80ETC concert', + sell_in => 5, + quality => 49 + ), + Item.new( # This Conjured item does not work properly yet + name => 'Conjured Mana Cake', + sell_in => 3, + quality => 6 + ), +); + +sub MAIN(Int $days = 2) { + my $gilded-rose = GildedRose.new( items => @items ); + for ^$days -> $day { + say "-------- day $day --------"; + say 'name, sellIn, quality'; + + .Str.say for $gilded-rose.items; + + "".say; + $gilded-rose.update_quality(); + } +} From 7a043f63fba3b79d4d4ae528f957938c316f6ed7 Mon Sep 17 00:00:00 2001 From: Daniele Megna Date: Sun, 20 Aug 2017 16:43:24 +0200 Subject: [PATCH 223/634] Added elixir build folder to ignored files --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index b56f217b..ab29156c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ .idea/workspace.xml *.pyc /perl6/lib/.precomp +/elixir/_build/ From 46c61e1f4e137ac12b7d2664d08a86192a83c0c6 Mon Sep 17 00:00:00 2001 From: Diego Sousa Date: Thu, 31 Aug 2017 23:51:11 -0300 Subject: [PATCH 224/634] Removing csharp project --- csharp/ApprovalTest.cs | 28 ----------- csharp/GildedRose.cs | 100 -------------------------------------- csharp/GildedRoseTest.cs | 19 -------- csharp/TextTestFixture.cs | 58 ---------------------- 4 files changed, 205 deletions(-) delete mode 100644 csharp/ApprovalTest.cs delete mode 100644 csharp/GildedRose.cs delete mode 100644 csharp/GildedRoseTest.cs delete mode 100644 csharp/TextTestFixture.cs diff --git a/csharp/ApprovalTest.cs b/csharp/ApprovalTest.cs deleted file mode 100644 index ad294419..00000000 --- a/csharp/ApprovalTest.cs +++ /dev/null @@ -1,28 +0,0 @@ -using System; -using System.IO; -using System.Text; -using GildedRose; -using NUnit.Framework; -using ApprovalTests; -using ApprovalTests.Reporters; - -namespace GildedRoseTests -{ - [TestFixture] - [UseReporter(typeof(NUnitReporter))] - public class ApprovalTest - { - [Test] - public void ThirtyDays() - { - StringBuilder fakeoutput = new StringBuilder(); - Console.SetOut(new StringWriter(fakeoutput)); - Console.SetIn(new StringReader("a\n")); - - Program.Main(new string[] { }); - String output = fakeoutput.ToString(); - Approvals.Verify(output); - } - } - -} \ No newline at end of file diff --git a/csharp/GildedRose.cs b/csharp/GildedRose.cs deleted file mode 100644 index a0017b2e..00000000 --- a/csharp/GildedRose.cs +++ /dev/null @@ -1,100 +0,0 @@ -using System.Collections.Generic; - -namespace GildedRose -{ - class GildedRose - { - IList Items; - public GildedRose(IList Items) - { - this.Items = Items; - } - - public void UpdateQuality() - { - for (var i = 0; i < Items.Count; i++) - { - if (Items[i].Name != "Aged Brie" && Items[i].Name != "Backstage passes to a TAFKAL80ETC concert") - { - if (Items[i].Quality > 0) - { - if (Items[i].Name != "Sulfuras, Hand of Ragnaros") - { - Items[i].Quality = Items[i].Quality - 1; - } - } - } - else - { - if (Items[i].Quality < 50) - { - Items[i].Quality = Items[i].Quality + 1; - - if (Items[i].Name == "Backstage passes to a TAFKAL80ETC concert") - { - if (Items[i].SellIn < 11) - { - if (Items[i].Quality < 50) - { - Items[i].Quality = Items[i].Quality + 1; - } - } - - if (Items[i].SellIn < 6) - { - if (Items[i].Quality < 50) - { - Items[i].Quality = Items[i].Quality + 1; - } - } - } - } - } - - if (Items[i].Name != "Sulfuras, Hand of Ragnaros") - { - Items[i].SellIn = Items[i].SellIn - 1; - } - - if (Items[i].SellIn < 0) - { - if (Items[i].Name != "Aged Brie") - { - if (Items[i].Name != "Backstage passes to a TAFKAL80ETC concert") - { - if (Items[i].Quality > 0) - { - if (Items[i].Name != "Sulfuras, Hand of Ragnaros") - { - Items[i].Quality = Items[i].Quality - 1; - } - } - } - else - { - Items[i].Quality = Items[i].Quality - Items[i].Quality; - } - } - else - { - if (Items[i].Quality < 50) - { - Items[i].Quality = Items[i].Quality + 1; - } - } - } - } - } - - } - - public class Item - { - public string Name { get; set; } - - public int SellIn { get; set; } - - public int Quality { get; set; } - } - -} diff --git a/csharp/GildedRoseTest.cs b/csharp/GildedRoseTest.cs deleted file mode 100644 index 02fd5b21..00000000 --- a/csharp/GildedRoseTest.cs +++ /dev/null @@ -1,19 +0,0 @@ -using System; -using NUnit.Framework; -using System.Collections.Generic; - -namespace GildedRose -{ - [TestFixture()] - public class GildedRoseTest - { - [Test()] - public void foo() { - IList Items = new List { new Item{Name = "foo", SellIn = 0, Quality = 0} }; - GildedRose app = new GildedRose(Items); - app.UpdateQuality(); - Assert.AreEqual("fixme", Items[0].Name); - } - } -} - diff --git a/csharp/TextTestFixture.cs b/csharp/TextTestFixture.cs deleted file mode 100644 index 3283aba9..00000000 --- a/csharp/TextTestFixture.cs +++ /dev/null @@ -1,58 +0,0 @@ -using System; -using System.Collections.Generic; - -namespace GildedRose -{ - class Program - { - public static void Main(string[] args) - { - System.Console.WriteLine("OMGHAI!"); - - IList Items = new List{ - new Item {Name = "+5 Dexterity Vest", SellIn = 10, Quality = 20}, - new Item {Name = "Aged Brie", SellIn = 2, Quality = 0}, - new Item {Name = "Elixir of the Mongoose", SellIn = 5, Quality = 7}, - new Item {Name = "Sulfuras, Hand of Ragnaros", SellIn = 0, Quality = 80}, - new Item {Name = "Sulfuras, Hand of Ragnaros", SellIn = -1, Quality = 80}, - new Item - { - Name = "Backstage passes to a TAFKAL80ETC concert", - SellIn = 15, - Quality = 20 - }, - new Item - { - Name = "Backstage passes to a TAFKAL80ETC concert", - SellIn = 10, - Quality = 49 - }, - new Item - { - Name = "Backstage passes to a TAFKAL80ETC concert", - SellIn = 5, - Quality = 49 - }, - // this conjured item does not work properly yet - new Item {Name = "Conjured Mana Cake", SellIn = 3, Quality = 6} - }; - - var app = new GildedRose(Items); - - - for (var i = 0; i < 31; i++) - { - System.Console.WriteLine("-------- day " + i + " --------"); - System.Console.WriteLine("name, sellIn, quality"); - for (var j = 0; j < Items.Count; j++) - { - System.Console.WriteLine(Items[j].Name + ", " + Items[j].SellIn + ", " + Items[j].Quality); - } - System.Console.WriteLine(""); - app.UpdateQuality(); - } - - } - - } -} From bfd451adc44cebb29a4a8771f6839e82f8487154 Mon Sep 17 00:00:00 2001 From: Diego Sousa Date: Thu, 31 Aug 2017 23:58:11 -0300 Subject: [PATCH 225/634] Added .gitignore file --- csharp/.gitignore | 299 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 299 insertions(+) create mode 100644 csharp/.gitignore diff --git a/csharp/.gitignore b/csharp/.gitignore new file mode 100644 index 00000000..c99ff6ab --- /dev/null +++ b/csharp/.gitignore @@ -0,0 +1,299 @@ +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. +## +## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore + +# User-specific files +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +bld/ +[Bb]in/ +[Oo]bj/ +[Ll]og/ + +# Visual Studio 2015 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUNIT +*.VisualState.xml +TestResult.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# Benchmark Results +BenchmarkDotNet.Artifacts/ + +# .NET Core +project.lock.json +project.fragment.lock.json +artifacts/ +**/Properties/launchSettings.json + +*_i.c +*_p.c +*_i.h +*.ilk +*.meta +*.obj +*.pch +*.pdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db +*.VC.VC.opendb + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# JustCode is a .NET coding add-in +.JustCode + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# AxoCover is a Code Coverage Tool +.axoCover/* +!.axoCover/settings.json + +# Visual Studio code coverage results +*.coverage +*.coveragexml + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# Note: Comment the next line if you want to checkin your web deploy settings, +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml +*.publishproj + +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ + +# NuGet Packages +*.nupkg +# The packages folder can be ignored because of Package Restore +**/packages/* +# except build/, which is used as an MSBuild target. +!**/packages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/packages/repositories.config +# NuGet v3's project.json files produces more ignorable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt +*.appx + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.jfm +*.pfx +*.publishsettings +orleans.codegen.cs + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm + +# SQL Server files +*.mdf +*.ldf +*.ndf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat +node_modules/ + +# Typescript v1 declaration files +typings/ + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) +*.vbw + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe +paket-files/ + +# FAKE - F# Make +.fake/ + +# JetBrains Rider +.idea/ +*.sln.iml + +# CodeRush +.cr/ + +# Python Tools for Visual Studio (PTVS) +__pycache__/ +*.pyc + +# Cake - Uncomment if you are using it +# tools/** +# !tools/packages.config + +# Tabs Studio +*.tss + +# Telerik's JustMock configuration file +*.jmconfig + +# BizTalk build output +*.btp.cs +*.btm.cs +*.odx.cs +*.xsd.cs \ No newline at end of file From 23166143a28514b5921229f1f0ee75b491b9f092 Mon Sep 17 00:00:00 2001 From: Diego Sousa Date: Fri, 1 Sep 2017 00:00:42 -0300 Subject: [PATCH 226/634] Added files needed to run the csharp project on VS15/17 --- csharp/App.config | 6 + csharp/ApprovalTest.ThirtyDays.received.txt | 373 ++++++++++++++++++++ csharp/ApprovalTest.cs | 26 ++ csharp/GildedRose.cs | 89 +++++ csharp/GildedRoseTest.cs | 18 + csharp/Item.cs | 9 + csharp/Program.cs | 56 +++ csharp/Properties/AssemblyInfo.cs | 36 ++ csharp/csharp.csproj | 86 +++++ csharp/csharp.sln | 22 ++ csharp/packages.config | 4 + 11 files changed, 725 insertions(+) create mode 100644 csharp/App.config create mode 100644 csharp/ApprovalTest.ThirtyDays.received.txt create mode 100644 csharp/ApprovalTest.cs create mode 100644 csharp/GildedRose.cs create mode 100644 csharp/GildedRoseTest.cs create mode 100644 csharp/Item.cs create mode 100644 csharp/Program.cs create mode 100644 csharp/Properties/AssemblyInfo.cs create mode 100644 csharp/csharp.csproj create mode 100644 csharp/csharp.sln create mode 100644 csharp/packages.config diff --git a/csharp/App.config b/csharp/App.config new file mode 100644 index 00000000..88fa4027 --- /dev/null +++ b/csharp/App.config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/csharp/ApprovalTest.ThirtyDays.received.txt b/csharp/ApprovalTest.ThirtyDays.received.txt new file mode 100644 index 00000000..cd66984f --- /dev/null +++ b/csharp/ApprovalTest.ThirtyDays.received.txt @@ -0,0 +1,373 @@ +OMGHAI! +-------- day 0 -------- +name, sellIn, quality ++5 Dexterity Vest, 10, 20 +Aged Brie, 2, 0 +Elixir of the Mongoose, 5, 7 +Sulfuras, Hand of Ragnaros, 0, 80 +Sulfuras, Hand of Ragnaros, -1, 80 +Backstage passes to a TAFKAL80ETC concert, 15, 20 +Backstage passes to a TAFKAL80ETC concert, 10, 49 +Backstage passes to a TAFKAL80ETC concert, 5, 49 +Conjured Mana Cake, 3, 6 + +-------- day 1 -------- +name, sellIn, quality ++5 Dexterity Vest, 9, 19 +Aged Brie, 1, 1 +Elixir of the Mongoose, 4, 6 +Sulfuras, Hand of Ragnaros, 0, 80 +Sulfuras, Hand of Ragnaros, -1, 80 +Backstage passes to a TAFKAL80ETC concert, 14, 21 +Backstage passes to a TAFKAL80ETC concert, 9, 50 +Backstage passes to a TAFKAL80ETC concert, 4, 50 +Conjured Mana Cake, 2, 5 + +-------- day 2 -------- +name, sellIn, quality ++5 Dexterity Vest, 8, 18 +Aged Brie, 0, 2 +Elixir of the Mongoose, 3, 5 +Sulfuras, Hand of Ragnaros, 0, 80 +Sulfuras, Hand of Ragnaros, -1, 80 +Backstage passes to a TAFKAL80ETC concert, 13, 22 +Backstage passes to a TAFKAL80ETC concert, 8, 50 +Backstage passes to a TAFKAL80ETC concert, 3, 50 +Conjured Mana Cake, 1, 4 + +-------- day 3 -------- +name, sellIn, quality ++5 Dexterity Vest, 7, 17 +Aged Brie, -1, 4 +Elixir of the Mongoose, 2, 4 +Sulfuras, Hand of Ragnaros, 0, 80 +Sulfuras, Hand of Ragnaros, -1, 80 +Backstage passes to a TAFKAL80ETC concert, 12, 23 +Backstage passes to a TAFKAL80ETC concert, 7, 50 +Backstage passes to a TAFKAL80ETC concert, 2, 50 +Conjured Mana Cake, 0, 3 + +-------- day 4 -------- +name, sellIn, quality ++5 Dexterity Vest, 6, 16 +Aged Brie, -2, 6 +Elixir of the Mongoose, 1, 3 +Sulfuras, Hand of Ragnaros, 0, 80 +Sulfuras, Hand of Ragnaros, -1, 80 +Backstage passes to a TAFKAL80ETC concert, 11, 24 +Backstage passes to a TAFKAL80ETC concert, 6, 50 +Backstage passes to a TAFKAL80ETC concert, 1, 50 +Conjured Mana Cake, -1, 1 + +-------- day 5 -------- +name, sellIn, quality ++5 Dexterity Vest, 5, 15 +Aged Brie, -3, 8 +Elixir of the Mongoose, 0, 2 +Sulfuras, Hand of Ragnaros, 0, 80 +Sulfuras, Hand of Ragnaros, -1, 80 +Backstage passes to a TAFKAL80ETC concert, 10, 25 +Backstage passes to a TAFKAL80ETC concert, 5, 50 +Backstage passes to a TAFKAL80ETC concert, 0, 50 +Conjured Mana Cake, -2, 0 + +-------- day 6 -------- +name, sellIn, quality ++5 Dexterity Vest, 4, 14 +Aged Brie, -4, 10 +Elixir of the Mongoose, -1, 0 +Sulfuras, Hand of Ragnaros, 0, 80 +Sulfuras, Hand of Ragnaros, -1, 80 +Backstage passes to a TAFKAL80ETC concert, 9, 27 +Backstage passes to a TAFKAL80ETC concert, 4, 50 +Backstage passes to a TAFKAL80ETC concert, -1, 0 +Conjured Mana Cake, -3, 0 + +-------- day 7 -------- +name, sellIn, quality ++5 Dexterity Vest, 3, 13 +Aged Brie, -5, 12 +Elixir of the Mongoose, -2, 0 +Sulfuras, Hand of Ragnaros, 0, 80 +Sulfuras, Hand of Ragnaros, -1, 80 +Backstage passes to a TAFKAL80ETC concert, 8, 29 +Backstage passes to a TAFKAL80ETC concert, 3, 50 +Backstage passes to a TAFKAL80ETC concert, -2, 0 +Conjured Mana Cake, -4, 0 + +-------- day 8 -------- +name, sellIn, quality ++5 Dexterity Vest, 2, 12 +Aged Brie, -6, 14 +Elixir of the Mongoose, -3, 0 +Sulfuras, Hand of Ragnaros, 0, 80 +Sulfuras, Hand of Ragnaros, -1, 80 +Backstage passes to a TAFKAL80ETC concert, 7, 31 +Backstage passes to a TAFKAL80ETC concert, 2, 50 +Backstage passes to a TAFKAL80ETC concert, -3, 0 +Conjured Mana Cake, -5, 0 + +-------- day 9 -------- +name, sellIn, quality ++5 Dexterity Vest, 1, 11 +Aged Brie, -7, 16 +Elixir of the Mongoose, -4, 0 +Sulfuras, Hand of Ragnaros, 0, 80 +Sulfuras, Hand of Ragnaros, -1, 80 +Backstage passes to a TAFKAL80ETC concert, 6, 33 +Backstage passes to a TAFKAL80ETC concert, 1, 50 +Backstage passes to a TAFKAL80ETC concert, -4, 0 +Conjured Mana Cake, -6, 0 + +-------- day 10 -------- +name, sellIn, quality ++5 Dexterity Vest, 0, 10 +Aged Brie, -8, 18 +Elixir of the Mongoose, -5, 0 +Sulfuras, Hand of Ragnaros, 0, 80 +Sulfuras, Hand of Ragnaros, -1, 80 +Backstage passes to a TAFKAL80ETC concert, 5, 35 +Backstage passes to a TAFKAL80ETC concert, 0, 50 +Backstage passes to a TAFKAL80ETC concert, -5, 0 +Conjured Mana Cake, -7, 0 + +-------- day 11 -------- +name, sellIn, quality ++5 Dexterity Vest, -1, 8 +Aged Brie, -9, 20 +Elixir of the Mongoose, -6, 0 +Sulfuras, Hand of Ragnaros, 0, 80 +Sulfuras, Hand of Ragnaros, -1, 80 +Backstage passes to a TAFKAL80ETC concert, 4, 38 +Backstage passes to a TAFKAL80ETC concert, -1, 0 +Backstage passes to a TAFKAL80ETC concert, -6, 0 +Conjured Mana Cake, -8, 0 + +-------- day 12 -------- +name, sellIn, quality ++5 Dexterity Vest, -2, 6 +Aged Brie, -10, 22 +Elixir of the Mongoose, -7, 0 +Sulfuras, Hand of Ragnaros, 0, 80 +Sulfuras, Hand of Ragnaros, -1, 80 +Backstage passes to a TAFKAL80ETC concert, 3, 41 +Backstage passes to a TAFKAL80ETC concert, -2, 0 +Backstage passes to a TAFKAL80ETC concert, -7, 0 +Conjured Mana Cake, -9, 0 + +-------- day 13 -------- +name, sellIn, quality ++5 Dexterity Vest, -3, 4 +Aged Brie, -11, 24 +Elixir of the Mongoose, -8, 0 +Sulfuras, Hand of Ragnaros, 0, 80 +Sulfuras, Hand of Ragnaros, -1, 80 +Backstage passes to a TAFKAL80ETC concert, 2, 44 +Backstage passes to a TAFKAL80ETC concert, -3, 0 +Backstage passes to a TAFKAL80ETC concert, -8, 0 +Conjured Mana Cake, -10, 0 + +-------- day 14 -------- +name, sellIn, quality ++5 Dexterity Vest, -4, 2 +Aged Brie, -12, 26 +Elixir of the Mongoose, -9, 0 +Sulfuras, Hand of Ragnaros, 0, 80 +Sulfuras, Hand of Ragnaros, -1, 80 +Backstage passes to a TAFKAL80ETC concert, 1, 47 +Backstage passes to a TAFKAL80ETC concert, -4, 0 +Backstage passes to a TAFKAL80ETC concert, -9, 0 +Conjured Mana Cake, -11, 0 + +-------- day 15 -------- +name, sellIn, quality ++5 Dexterity Vest, -5, 0 +Aged Brie, -13, 28 +Elixir of the Mongoose, -10, 0 +Sulfuras, Hand of Ragnaros, 0, 80 +Sulfuras, Hand of Ragnaros, -1, 80 +Backstage passes to a TAFKAL80ETC concert, 0, 50 +Backstage passes to a TAFKAL80ETC concert, -5, 0 +Backstage passes to a TAFKAL80ETC concert, -10, 0 +Conjured Mana Cake, -12, 0 + +-------- day 16 -------- +name, sellIn, quality ++5 Dexterity Vest, -6, 0 +Aged Brie, -14, 30 +Elixir of the Mongoose, -11, 0 +Sulfuras, Hand of Ragnaros, 0, 80 +Sulfuras, Hand of Ragnaros, -1, 80 +Backstage passes to a TAFKAL80ETC concert, -1, 0 +Backstage passes to a TAFKAL80ETC concert, -6, 0 +Backstage passes to a TAFKAL80ETC concert, -11, 0 +Conjured Mana Cake, -13, 0 + +-------- day 17 -------- +name, sellIn, quality ++5 Dexterity Vest, -7, 0 +Aged Brie, -15, 32 +Elixir of the Mongoose, -12, 0 +Sulfuras, Hand of Ragnaros, 0, 80 +Sulfuras, Hand of Ragnaros, -1, 80 +Backstage passes to a TAFKAL80ETC concert, -2, 0 +Backstage passes to a TAFKAL80ETC concert, -7, 0 +Backstage passes to a TAFKAL80ETC concert, -12, 0 +Conjured Mana Cake, -14, 0 + +-------- day 18 -------- +name, sellIn, quality ++5 Dexterity Vest, -8, 0 +Aged Brie, -16, 34 +Elixir of the Mongoose, -13, 0 +Sulfuras, Hand of Ragnaros, 0, 80 +Sulfuras, Hand of Ragnaros, -1, 80 +Backstage passes to a TAFKAL80ETC concert, -3, 0 +Backstage passes to a TAFKAL80ETC concert, -8, 0 +Backstage passes to a TAFKAL80ETC concert, -13, 0 +Conjured Mana Cake, -15, 0 + +-------- day 19 -------- +name, sellIn, quality ++5 Dexterity Vest, -9, 0 +Aged Brie, -17, 36 +Elixir of the Mongoose, -14, 0 +Sulfuras, Hand of Ragnaros, 0, 80 +Sulfuras, Hand of Ragnaros, -1, 80 +Backstage passes to a TAFKAL80ETC concert, -4, 0 +Backstage passes to a TAFKAL80ETC concert, -9, 0 +Backstage passes to a TAFKAL80ETC concert, -14, 0 +Conjured Mana Cake, -16, 0 + +-------- day 20 -------- +name, sellIn, quality ++5 Dexterity Vest, -10, 0 +Aged Brie, -18, 38 +Elixir of the Mongoose, -15, 0 +Sulfuras, Hand of Ragnaros, 0, 80 +Sulfuras, Hand of Ragnaros, -1, 80 +Backstage passes to a TAFKAL80ETC concert, -5, 0 +Backstage passes to a TAFKAL80ETC concert, -10, 0 +Backstage passes to a TAFKAL80ETC concert, -15, 0 +Conjured Mana Cake, -17, 0 + +-------- day 21 -------- +name, sellIn, quality ++5 Dexterity Vest, -11, 0 +Aged Brie, -19, 40 +Elixir of the Mongoose, -16, 0 +Sulfuras, Hand of Ragnaros, 0, 80 +Sulfuras, Hand of Ragnaros, -1, 80 +Backstage passes to a TAFKAL80ETC concert, -6, 0 +Backstage passes to a TAFKAL80ETC concert, -11, 0 +Backstage passes to a TAFKAL80ETC concert, -16, 0 +Conjured Mana Cake, -18, 0 + +-------- day 22 -------- +name, sellIn, quality ++5 Dexterity Vest, -12, 0 +Aged Brie, -20, 42 +Elixir of the Mongoose, -17, 0 +Sulfuras, Hand of Ragnaros, 0, 80 +Sulfuras, Hand of Ragnaros, -1, 80 +Backstage passes to a TAFKAL80ETC concert, -7, 0 +Backstage passes to a TAFKAL80ETC concert, -12, 0 +Backstage passes to a TAFKAL80ETC concert, -17, 0 +Conjured Mana Cake, -19, 0 + +-------- day 23 -------- +name, sellIn, quality ++5 Dexterity Vest, -13, 0 +Aged Brie, -21, 44 +Elixir of the Mongoose, -18, 0 +Sulfuras, Hand of Ragnaros, 0, 80 +Sulfuras, Hand of Ragnaros, -1, 80 +Backstage passes to a TAFKAL80ETC concert, -8, 0 +Backstage passes to a TAFKAL80ETC concert, -13, 0 +Backstage passes to a TAFKAL80ETC concert, -18, 0 +Conjured Mana Cake, -20, 0 + +-------- day 24 -------- +name, sellIn, quality ++5 Dexterity Vest, -14, 0 +Aged Brie, -22, 46 +Elixir of the Mongoose, -19, 0 +Sulfuras, Hand of Ragnaros, 0, 80 +Sulfuras, Hand of Ragnaros, -1, 80 +Backstage passes to a TAFKAL80ETC concert, -9, 0 +Backstage passes to a TAFKAL80ETC concert, -14, 0 +Backstage passes to a TAFKAL80ETC concert, -19, 0 +Conjured Mana Cake, -21, 0 + +-------- day 25 -------- +name, sellIn, quality ++5 Dexterity Vest, -15, 0 +Aged Brie, -23, 48 +Elixir of the Mongoose, -20, 0 +Sulfuras, Hand of Ragnaros, 0, 80 +Sulfuras, Hand of Ragnaros, -1, 80 +Backstage passes to a TAFKAL80ETC concert, -10, 0 +Backstage passes to a TAFKAL80ETC concert, -15, 0 +Backstage passes to a TAFKAL80ETC concert, -20, 0 +Conjured Mana Cake, -22, 0 + +-------- day 26 -------- +name, sellIn, quality ++5 Dexterity Vest, -16, 0 +Aged Brie, -24, 50 +Elixir of the Mongoose, -21, 0 +Sulfuras, Hand of Ragnaros, 0, 80 +Sulfuras, Hand of Ragnaros, -1, 80 +Backstage passes to a TAFKAL80ETC concert, -11, 0 +Backstage passes to a TAFKAL80ETC concert, -16, 0 +Backstage passes to a TAFKAL80ETC concert, -21, 0 +Conjured Mana Cake, -23, 0 + +-------- day 27 -------- +name, sellIn, quality ++5 Dexterity Vest, -17, 0 +Aged Brie, -25, 50 +Elixir of the Mongoose, -22, 0 +Sulfuras, Hand of Ragnaros, 0, 80 +Sulfuras, Hand of Ragnaros, -1, 80 +Backstage passes to a TAFKAL80ETC concert, -12, 0 +Backstage passes to a TAFKAL80ETC concert, -17, 0 +Backstage passes to a TAFKAL80ETC concert, -22, 0 +Conjured Mana Cake, -24, 0 + +-------- day 28 -------- +name, sellIn, quality ++5 Dexterity Vest, -18, 0 +Aged Brie, -26, 50 +Elixir of the Mongoose, -23, 0 +Sulfuras, Hand of Ragnaros, 0, 80 +Sulfuras, Hand of Ragnaros, -1, 80 +Backstage passes to a TAFKAL80ETC concert, -13, 0 +Backstage passes to a TAFKAL80ETC concert, -18, 0 +Backstage passes to a TAFKAL80ETC concert, -23, 0 +Conjured Mana Cake, -25, 0 + +-------- day 29 -------- +name, sellIn, quality ++5 Dexterity Vest, -19, 0 +Aged Brie, -27, 50 +Elixir of the Mongoose, -24, 0 +Sulfuras, Hand of Ragnaros, 0, 80 +Sulfuras, Hand of Ragnaros, -1, 80 +Backstage passes to a TAFKAL80ETC concert, -14, 0 +Backstage passes to a TAFKAL80ETC concert, -19, 0 +Backstage passes to a TAFKAL80ETC concert, -24, 0 +Conjured Mana Cake, -26, 0 + +-------- day 30 -------- +name, sellIn, quality ++5 Dexterity Vest, -20, 0 +Aged Brie, -28, 50 +Elixir of the Mongoose, -25, 0 +Sulfuras, Hand of Ragnaros, 0, 80 +Sulfuras, Hand of Ragnaros, -1, 80 +Backstage passes to a TAFKAL80ETC concert, -15, 0 +Backstage passes to a TAFKAL80ETC concert, -20, 0 +Backstage passes to a TAFKAL80ETC concert, -25, 0 +Conjured Mana Cake, -27, 0 + diff --git a/csharp/ApprovalTest.cs b/csharp/ApprovalTest.cs new file mode 100644 index 00000000..5931f934 --- /dev/null +++ b/csharp/ApprovalTest.cs @@ -0,0 +1,26 @@ +using ApprovalTests; +using ApprovalTests.Reporters; +using NUnit.Framework; +using System; +using System.IO; +using System.Text; + +namespace csharp +{ + [TestFixture] + [UseReporter(typeof(NUnitReporter))] + public class ApprovalTest + { + [Test] + public void ThirtyDays() + { + StringBuilder fakeoutput = new StringBuilder(); + Console.SetOut(new StringWriter(fakeoutput)); + Console.SetIn(new StringReader("a\n")); + + Program.Main(new string[] { }); + String output = fakeoutput.ToString(); + Approvals.Verify(output); + } + } +} diff --git a/csharp/GildedRose.cs b/csharp/GildedRose.cs new file mode 100644 index 00000000..c60d97a0 --- /dev/null +++ b/csharp/GildedRose.cs @@ -0,0 +1,89 @@ +using System.Collections.Generic; + +namespace csharp +{ + public class GildedRose + { + IList Items; + public GildedRose(IList Items) + { + this.Items = Items; + } + + public void UpdateQuality() + { + for (var i = 0; i < Items.Count; i++) + { + if (Items[i].Name != "Aged Brie" && Items[i].Name != "Backstage passes to a TAFKAL80ETC concert") + { + if (Items[i].Quality > 0) + { + if (Items[i].Name != "Sulfuras, Hand of Ragnaros") + { + Items[i].Quality = Items[i].Quality - 1; + } + } + } + else + { + if (Items[i].Quality < 50) + { + Items[i].Quality = Items[i].Quality + 1; + + if (Items[i].Name == "Backstage passes to a TAFKAL80ETC concert") + { + if (Items[i].SellIn < 11) + { + if (Items[i].Quality < 50) + { + Items[i].Quality = Items[i].Quality + 1; + } + } + + if (Items[i].SellIn < 6) + { + if (Items[i].Quality < 50) + { + Items[i].Quality = Items[i].Quality + 1; + } + } + } + } + } + + if (Items[i].Name != "Sulfuras, Hand of Ragnaros") + { + Items[i].SellIn = Items[i].SellIn - 1; + } + + if (Items[i].SellIn < 0) + { + if (Items[i].Name != "Aged Brie") + { + if (Items[i].Name != "Backstage passes to a TAFKAL80ETC concert") + { + if (Items[i].Quality > 0) + { + if (Items[i].Name != "Sulfuras, Hand of Ragnaros") + { + Items[i].Quality = Items[i].Quality - 1; + } + } + } + else + { + Items[i].Quality = Items[i].Quality - Items[i].Quality; + } + } + else + { + if (Items[i].Quality < 50) + { + Items[i].Quality = Items[i].Quality + 1; + } + } + } + } + } + } +} diff --git a/csharp/GildedRoseTest.cs b/csharp/GildedRoseTest.cs new file mode 100644 index 00000000..911df1be --- /dev/null +++ b/csharp/GildedRoseTest.cs @@ -0,0 +1,18 @@ +using NUnit.Framework; +using System.Collections.Generic; + +namespace csharp +{ + [TestFixture] + public class GildedRoseTest + { + [Test] + public void foo() + { + IList Items = new List { new Item { Name = "foo", SellIn = 0, Quality = 0 } }; + GildedRose app = new GildedRose(Items); + app.UpdateQuality(); + Assert.AreEqual("fixme", Items[0].Name); + } + } +} diff --git a/csharp/Item.cs b/csharp/Item.cs new file mode 100644 index 00000000..1707f3e3 --- /dev/null +++ b/csharp/Item.cs @@ -0,0 +1,9 @@ +namespace csharp +{ + public class Item + { + public string Name { get; set; } + public int SellIn { get; set; } + public int Quality { get; set; } + } +} diff --git a/csharp/Program.cs b/csharp/Program.cs new file mode 100644 index 00000000..4ae66100 --- /dev/null +++ b/csharp/Program.cs @@ -0,0 +1,56 @@ +using System; +using System.Collections.Generic; + +namespace csharp +{ + public class Program + { + public static void Main(string[] args) + { + Console.WriteLine("OMGHAI!"); + + IList Items = new List{ + new Item {Name = "+5 Dexterity Vest", SellIn = 10, Quality = 20}, + new Item {Name = "Aged Brie", SellIn = 2, Quality = 0}, + new Item {Name = "Elixir of the Mongoose", SellIn = 5, Quality = 7}, + new Item {Name = "Sulfuras, Hand of Ragnaros", SellIn = 0, Quality = 80}, + new Item {Name = "Sulfuras, Hand of Ragnaros", SellIn = -1, Quality = 80}, + new Item + { + Name = "Backstage passes to a TAFKAL80ETC concert", + SellIn = 15, + Quality = 20 + }, + new Item + { + Name = "Backstage passes to a TAFKAL80ETC concert", + SellIn = 10, + Quality = 49 + }, + new Item + { + Name = "Backstage passes to a TAFKAL80ETC concert", + SellIn = 5, + Quality = 49 + }, + // this conjured item does not work properly yet + new Item {Name = "Conjured Mana Cake", SellIn = 3, Quality = 6} + }; + + var app = new GildedRose(Items); + + + for (var i = 0; i < 31; i++) + { + Console.WriteLine("-------- day " + i + " --------"); + Console.WriteLine("name, sellIn, quality"); + for (var j = 0; j < Items.Count; j++) + { + System.Console.WriteLine(Items[j].Name + ", " + Items[j].SellIn + ", " + Items[j].Quality); + } + Console.WriteLine(""); + app.UpdateQuality(); + } + } + } +} diff --git a/csharp/Properties/AssemblyInfo.cs b/csharp/Properties/AssemblyInfo.cs new file mode 100644 index 00000000..dc5db47d --- /dev/null +++ b/csharp/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("csharp")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("csharp")] +[assembly: AssemblyCopyright("Copyright © 2017")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("176c0214-9136-4079-8dab-11d7420c3881")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/csharp/csharp.csproj b/csharp/csharp.csproj new file mode 100644 index 00000000..80350537 --- /dev/null +++ b/csharp/csharp.csproj @@ -0,0 +1,86 @@ + + + + + + Debug + AnyCPU + {176C0214-9136-4079-8DAB-11D7420C3881} + Exe + Properties + csharp + csharp + v4.5.2 + 512 + true + + + + + AnyCPU + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + AnyCPU + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + packages\ApprovalTests.dll + + + packages\ApprovalUtilities.dll + + + packages\nunit.framework.dll + + + + + + + + + + + + + + + + + + + + + + + + + + + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + + \ No newline at end of file diff --git a/csharp/csharp.sln b/csharp/csharp.sln new file mode 100644 index 00000000..62ff78a8 --- /dev/null +++ b/csharp/csharp.sln @@ -0,0 +1,22 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +VisualStudioVersion = 14.0.25420.1 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "csharp", "csharp.csproj", "{176C0214-9136-4079-8DAB-11D7420C3881}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {176C0214-9136-4079-8DAB-11D7420C3881}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {176C0214-9136-4079-8DAB-11D7420C3881}.Debug|Any CPU.Build.0 = Debug|Any CPU + {176C0214-9136-4079-8DAB-11D7420C3881}.Release|Any CPU.ActiveCfg = Release|Any CPU + {176C0214-9136-4079-8DAB-11D7420C3881}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/csharp/packages.config b/csharp/packages.config new file mode 100644 index 00000000..21223d2b --- /dev/null +++ b/csharp/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file From a5804b92c0099883cafc1159152059dfa00ea91f Mon Sep 17 00:00:00 2001 From: Diego Sousa Date: Fri, 1 Sep 2017 00:25:55 -0300 Subject: [PATCH 227/634] Added NUnit and ApprovalTests/Utilities --- csharp/csharp.csproj | 26 +++++++++++++------------- csharp/packages.config | 4 +++- 2 files changed, 16 insertions(+), 14 deletions(-) diff --git a/csharp/csharp.csproj b/csharp/csharp.csproj index 80350537..37813560 100644 --- a/csharp/csharp.csproj +++ b/csharp/csharp.csproj @@ -1,6 +1,5 @@  - Debug @@ -36,14 +35,21 @@ 4 - - packages\ApprovalTests.dll + + packages\ApprovalTests.3.0.13\lib\net40\ApprovalTests.dll + True - - packages\ApprovalUtilities.dll + + packages\ApprovalUtilities.3.0.13\lib\net45\ApprovalUtilities.dll + True - - packages\nunit.framework.dll + + packages\ApprovalUtilities.3.0.13\lib\net45\ApprovalUtilities.Net45.dll + True + + + packages\NUnit.3.8.1\lib\net45\nunit.framework.dll + True @@ -70,12 +76,6 @@ - - - This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - - - - - - - - - - - - - diff --git a/js/TexttestFixture.html b/js/TexttestFixture.html deleted file mode 100644 index 0fa50cb9..00000000 --- a/js/TexttestFixture.html +++ /dev/null @@ -1,59 +0,0 @@ - - - - -Gilded Rose Texttest Fixture - - - - - - - - - - - diff --git a/js/jasmine/.gitignore b/js/jasmine/.gitignore new file mode 100644 index 00000000..2ccbe465 --- /dev/null +++ b/js/jasmine/.gitignore @@ -0,0 +1 @@ +/node_modules/ diff --git a/js/jasmine/package-lock.json b/js/jasmine/package-lock.json new file mode 100644 index 00000000..be3709d4 --- /dev/null +++ b/js/jasmine/package-lock.json @@ -0,0 +1,112 @@ +{ + "name": "gilded-rose", + "version": "1.0.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "1.0.0", + "concat-map": "0.0.1" + } + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "glob": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "dev": true, + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "requires": { + "once": "1.4.0", + "wrappy": "1.0.2" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + }, + "jasmine": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/jasmine/-/jasmine-3.2.0.tgz", + "integrity": "sha512-qv6TZ32r+slrQz8fbx2EhGbD9zlJo3NwPrpLK1nE8inILtZO9Fap52pyHk7mNTh4tG50a+1+tOiWVT3jO5I0Sg==", + "dev": true, + "requires": { + "glob": "7.1.2", + "jasmine-core": "3.2.1" + } + }, + "jasmine-core": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-3.2.1.tgz", + "integrity": "sha512-pa9tbBWgU0EE4SWgc85T4sa886ufuQdsgruQANhECYjwqgV4z7Vw/499aCaP8ZH79JDS4vhm8doDG9HO4+e4sA==", + "dev": true + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "1.1.11" + } + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "requires": { + "wrappy": "1.0.2" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + } + } +} diff --git a/js/jasmine/package.json b/js/jasmine/package.json new file mode 100644 index 00000000..8f2ab748 --- /dev/null +++ b/js/jasmine/package.json @@ -0,0 +1,26 @@ +{ + "name": "gilded-rose", + "version": "1.0.0", + "description": "gilded rose kata in javascript", + "scripts": { + "test": "jasmine" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/emilybache/GildedRose-Refactoring-Kata.git" + }, + "keywords": [ + "kata", + "refactor", + "gilded-rose" + ], + "license": "MIT", + "private": true, + "bugs": { + "url": "https://github.com/emilybache/GildedRose-Refactoring-Kata/issues" + }, + "homepage": "https://github.com/emilybache/GildedRose-Refactoring-Kata#readme", + "devDependencies": { + "jasmine": "^3.2.0" + } +} diff --git a/js/spec/gilded_rose_spec.js b/js/jasmine/spec/gilded_rose_spec.js similarity index 81% rename from js/spec/gilded_rose_spec.js rename to js/jasmine/spec/gilded_rose_spec.js index 44c3838b..9f267c13 100644 --- a/js/spec/gilded_rose_spec.js +++ b/js/jasmine/spec/gilded_rose_spec.js @@ -1,3 +1,4 @@ +var {Shop, Item} = require('../src/gilded_rose.js'); describe("Gilded Rose", function() { it("should foo", function() { diff --git a/js/jasmine/spec/support/jasmine.json b/js/jasmine/spec/support/jasmine.json new file mode 100644 index 00000000..370fc446 --- /dev/null +++ b/js/jasmine/spec/support/jasmine.json @@ -0,0 +1,11 @@ +{ + "spec_dir": "spec", + "spec_files": [ + "**/*[sS]pec.js" + ], + "helpers": [ + "helpers/**/*.js" + ], + "stopSpecOnExpectationFailure": false, + "random": true +} diff --git a/js/src/gilded_rose.js b/js/jasmine/src/gilded_rose.js similarity index 98% rename from js/src/gilded_rose.js rename to js/jasmine/src/gilded_rose.js index 5358125e..acb33985 100644 --- a/js/src/gilded_rose.js +++ b/js/jasmine/src/gilded_rose.js @@ -60,3 +60,7 @@ class Shop { return this.items; } } +module.exports = { + Item, + Shop +} diff --git a/js/lib/jasmine-1.1.0/MIT.LICENSE b/js/lib/jasmine-1.1.0/MIT.LICENSE deleted file mode 100644 index 7c435baa..00000000 --- a/js/lib/jasmine-1.1.0/MIT.LICENSE +++ /dev/null @@ -1,20 +0,0 @@ -Copyright (c) 2008-2011 Pivotal Labs - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/js/lib/jasmine-1.1.0/jasmine-html.js b/js/lib/jasmine-1.1.0/jasmine-html.js deleted file mode 100644 index 73834010..00000000 --- a/js/lib/jasmine-1.1.0/jasmine-html.js +++ /dev/null @@ -1,190 +0,0 @@ -jasmine.TrivialReporter = function(doc) { - this.document = doc || document; - this.suiteDivs = {}; - this.logRunningSpecs = false; -}; - -jasmine.TrivialReporter.prototype.createDom = function(type, attrs, childrenVarArgs) { - var el = document.createElement(type); - - for (var i = 2; i < arguments.length; i++) { - var child = arguments[i]; - - if (typeof child === 'string') { - el.appendChild(document.createTextNode(child)); - } else { - if (child) { el.appendChild(child); } - } - } - - for (var attr in attrs) { - if (attr == "className") { - el[attr] = attrs[attr]; - } else { - el.setAttribute(attr, attrs[attr]); - } - } - - return el; -}; - -jasmine.TrivialReporter.prototype.reportRunnerStarting = function(runner) { - var showPassed, showSkipped; - - this.outerDiv = this.createDom('div', { className: 'jasmine_reporter' }, - this.createDom('div', { className: 'banner' }, - this.createDom('div', { className: 'logo' }, - this.createDom('span', { className: 'title' }, "Jasmine"), - this.createDom('span', { className: 'version' }, runner.env.versionString())), - this.createDom('div', { className: 'options' }, - "Show ", - showPassed = this.createDom('input', { id: "__jasmine_TrivialReporter_showPassed__", type: 'checkbox' }), - this.createDom('label', { "for": "__jasmine_TrivialReporter_showPassed__" }, " passed "), - showSkipped = this.createDom('input', { id: "__jasmine_TrivialReporter_showSkipped__", type: 'checkbox' }), - this.createDom('label', { "for": "__jasmine_TrivialReporter_showSkipped__" }, " skipped") - ) - ), - - this.runnerDiv = this.createDom('div', { className: 'runner running' }, - this.createDom('a', { className: 'run_spec', href: '?' }, "run all"), - this.runnerMessageSpan = this.createDom('span', {}, "Running..."), - this.finishedAtSpan = this.createDom('span', { className: 'finished-at' }, "")) - ); - - this.document.body.appendChild(this.outerDiv); - - var suites = runner.suites(); - for (var i = 0; i < suites.length; i++) { - var suite = suites[i]; - var suiteDiv = this.createDom('div', { className: 'suite' }, - this.createDom('a', { className: 'run_spec', href: '?spec=' + encodeURIComponent(suite.getFullName()) }, "run"), - this.createDom('a', { className: 'description', href: '?spec=' + encodeURIComponent(suite.getFullName()) }, suite.description)); - this.suiteDivs[suite.id] = suiteDiv; - var parentDiv = this.outerDiv; - if (suite.parentSuite) { - parentDiv = this.suiteDivs[suite.parentSuite.id]; - } - parentDiv.appendChild(suiteDiv); - } - - this.startedAt = new Date(); - - var self = this; - showPassed.onclick = function(evt) { - if (showPassed.checked) { - self.outerDiv.className += ' show-passed'; - } else { - self.outerDiv.className = self.outerDiv.className.replace(/ show-passed/, ''); - } - }; - - showSkipped.onclick = function(evt) { - if (showSkipped.checked) { - self.outerDiv.className += ' show-skipped'; - } else { - self.outerDiv.className = self.outerDiv.className.replace(/ show-skipped/, ''); - } - }; -}; - -jasmine.TrivialReporter.prototype.reportRunnerResults = function(runner) { - var results = runner.results(); - var className = (results.failedCount > 0) ? "runner failed" : "runner passed"; - this.runnerDiv.setAttribute("class", className); - //do it twice for IE - this.runnerDiv.setAttribute("className", className); - var specs = runner.specs(); - var specCount = 0; - for (var i = 0; i < specs.length; i++) { - if (this.specFilter(specs[i])) { - specCount++; - } - } - var message = "" + specCount + " spec" + (specCount == 1 ? "" : "s" ) + ", " + results.failedCount + " failure" + ((results.failedCount == 1) ? "" : "s"); - message += " in " + ((new Date().getTime() - this.startedAt.getTime()) / 1000) + "s"; - this.runnerMessageSpan.replaceChild(this.createDom('a', { className: 'description', href: '?'}, message), this.runnerMessageSpan.firstChild); - - this.finishedAtSpan.appendChild(document.createTextNode("Finished at " + new Date().toString())); -}; - -jasmine.TrivialReporter.prototype.reportSuiteResults = function(suite) { - var results = suite.results(); - var status = results.passed() ? 'passed' : 'failed'; - if (results.totalCount === 0) { // todo: change this to check results.skipped - status = 'skipped'; - } - this.suiteDivs[suite.id].className += " " + status; -}; - -jasmine.TrivialReporter.prototype.reportSpecStarting = function(spec) { - if (this.logRunningSpecs) { - this.log('>> Jasmine Running ' + spec.suite.description + ' ' + spec.description + '...'); - } -}; - -jasmine.TrivialReporter.prototype.reportSpecResults = function(spec) { - var results = spec.results(); - var status = results.passed() ? 'passed' : 'failed'; - if (results.skipped) { - status = 'skipped'; - } - var specDiv = this.createDom('div', { className: 'spec ' + status }, - this.createDom('a', { className: 'run_spec', href: '?spec=' + encodeURIComponent(spec.getFullName()) }, "run"), - this.createDom('a', { - className: 'description', - href: '?spec=' + encodeURIComponent(spec.getFullName()), - title: spec.getFullName() - }, spec.description)); - - - var resultItems = results.getItems(); - var messagesDiv = this.createDom('div', { className: 'messages' }); - for (var i = 0; i < resultItems.length; i++) { - var result = resultItems[i]; - - if (result.type == 'log') { - messagesDiv.appendChild(this.createDom('div', {className: 'resultMessage log'}, result.toString())); - } else if (result.type == 'expect' && result.passed && !result.passed()) { - messagesDiv.appendChild(this.createDom('div', {className: 'resultMessage fail'}, result.message)); - - if (result.trace.stack) { - messagesDiv.appendChild(this.createDom('div', {className: 'stackTrace'}, result.trace.stack)); - } - } - } - - if (messagesDiv.childNodes.length > 0) { - specDiv.appendChild(messagesDiv); - } - - this.suiteDivs[spec.suite.id].appendChild(specDiv); -}; - -jasmine.TrivialReporter.prototype.log = function() { - var console = jasmine.getGlobal().console; - if (console && console.log) { - if (console.log.apply) { - console.log.apply(console, arguments); - } else { - console.log(arguments); // ie fix: console.log.apply doesn't exist on ie - } - } -}; - -jasmine.TrivialReporter.prototype.getLocation = function() { - return this.document.location; -}; - -jasmine.TrivialReporter.prototype.specFilter = function(spec) { - var paramMap = {}; - var params = this.getLocation().search.substring(1).split('&'); - for (var i = 0; i < params.length; i++) { - var p = params[i].split('='); - paramMap[decodeURIComponent(p[0])] = decodeURIComponent(p[1]); - } - - if (!paramMap.spec) { - return true; - } - return spec.getFullName().indexOf(paramMap.spec) === 0; -}; diff --git a/js/lib/jasmine-1.1.0/jasmine.css b/js/lib/jasmine-1.1.0/jasmine.css deleted file mode 100644 index 6583fe7c..00000000 --- a/js/lib/jasmine-1.1.0/jasmine.css +++ /dev/null @@ -1,166 +0,0 @@ -body { - font-family: "Helvetica Neue Light", "Lucida Grande", "Calibri", "Arial", sans-serif; -} - - -.jasmine_reporter a:visited, .jasmine_reporter a { - color: #303; -} - -.jasmine_reporter a:hover, .jasmine_reporter a:active { - color: blue; -} - -.run_spec { - float:right; - padding-right: 5px; - font-size: .8em; - text-decoration: none; -} - -.jasmine_reporter { - margin: 0 5px; -} - -.banner { - color: #303; - background-color: #fef; - padding: 5px; -} - -.logo { - float: left; - font-size: 1.1em; - padding-left: 5px; -} - -.logo .version { - font-size: .6em; - padding-left: 1em; -} - -.runner.running { - background-color: yellow; -} - - -.options { - text-align: right; - font-size: .8em; -} - - - - -.suite { - border: 1px outset gray; - margin: 5px 0; - padding-left: 1em; -} - -.suite .suite { - margin: 5px; -} - -.suite.passed { - background-color: #dfd; -} - -.suite.failed { - background-color: #fdd; -} - -.spec { - margin: 5px; - padding-left: 1em; - clear: both; -} - -.spec.failed, .spec.passed, .spec.skipped { - padding-bottom: 5px; - border: 1px solid gray; -} - -.spec.failed { - background-color: #fbb; - border-color: red; -} - -.spec.passed { - background-color: #bfb; - border-color: green; -} - -.spec.skipped { - background-color: #bbb; -} - -.messages { - border-left: 1px dashed gray; - padding-left: 1em; - padding-right: 1em; -} - -.passed { - background-color: #cfc; - display: none; -} - -.failed { - background-color: #fbb; -} - -.skipped { - color: #777; - background-color: #eee; - display: none; -} - - -/*.resultMessage {*/ - /*white-space: pre;*/ -/*}*/ - -.resultMessage span.result { - display: block; - line-height: 2em; - color: black; -} - -.resultMessage .mismatch { - color: black; -} - -.stackTrace { - white-space: pre; - font-size: .8em; - margin-left: 10px; - max-height: 5em; - overflow: auto; - border: 1px inset red; - padding: 1em; - background: #eef; -} - -.finished-at { - padding-left: 1em; - font-size: .6em; -} - -.show-passed .passed, -.show-skipped .skipped { - display: block; -} - - -#jasmine_content { - position:fixed; - right: 100%; -} - -.runner { - border: 1px solid gray; - display: block; - margin: 5px 0; - padding: 2px 0 2px 10px; -} diff --git a/js/lib/jasmine-1.1.0/jasmine.js b/js/lib/jasmine-1.1.0/jasmine.js deleted file mode 100644 index c3d2dc7d..00000000 --- a/js/lib/jasmine-1.1.0/jasmine.js +++ /dev/null @@ -1,2476 +0,0 @@ -var isCommonJS = typeof window == "undefined"; - -/** - * Top level namespace for Jasmine, a lightweight JavaScript BDD/spec/testing framework. - * - * @namespace - */ -var jasmine = {}; -if (isCommonJS) exports.jasmine = jasmine; -/** - * @private - */ -jasmine.unimplementedMethod_ = function() { - throw new Error("unimplemented method"); -}; - -/** - * Use jasmine.undefined instead of undefined, since undefined is just - * a plain old variable and may be redefined by somebody else. - * - * @private - */ -jasmine.undefined = jasmine.___undefined___; - -/** - * Show diagnostic messages in the console if set to true - * - */ -jasmine.VERBOSE = false; - -/** - * Default interval in milliseconds for event loop yields (e.g. to allow network activity or to refresh the screen with the HTML-based runner). Small values here may result in slow test running. Zero means no updates until all tests have completed. - * - */ -jasmine.DEFAULT_UPDATE_INTERVAL = 250; - -/** - * Default timeout interval in milliseconds for waitsFor() blocks. - */ -jasmine.DEFAULT_TIMEOUT_INTERVAL = 5000; - -jasmine.getGlobal = function() { - function getGlobal() { - return this; - } - - return getGlobal(); -}; - -/** - * Allows for bound functions to be compared. Internal use only. - * - * @ignore - * @private - * @param base {Object} bound 'this' for the function - * @param name {Function} function to find - */ -jasmine.bindOriginal_ = function(base, name) { - var original = base[name]; - if (original.apply) { - return function() { - return original.apply(base, arguments); - }; - } else { - // IE support - return jasmine.getGlobal()[name]; - } -}; - -jasmine.setTimeout = jasmine.bindOriginal_(jasmine.getGlobal(), 'setTimeout'); -jasmine.clearTimeout = jasmine.bindOriginal_(jasmine.getGlobal(), 'clearTimeout'); -jasmine.setInterval = jasmine.bindOriginal_(jasmine.getGlobal(), 'setInterval'); -jasmine.clearInterval = jasmine.bindOriginal_(jasmine.getGlobal(), 'clearInterval'); - -jasmine.MessageResult = function(values) { - this.type = 'log'; - this.values = values; - this.trace = new Error(); // todo: test better -}; - -jasmine.MessageResult.prototype.toString = function() { - var text = ""; - for (var i = 0; i < this.values.length; i++) { - if (i > 0) text += " "; - if (jasmine.isString_(this.values[i])) { - text += this.values[i]; - } else { - text += jasmine.pp(this.values[i]); - } - } - return text; -}; - -jasmine.ExpectationResult = function(params) { - this.type = 'expect'; - this.matcherName = params.matcherName; - this.passed_ = params.passed; - this.expected = params.expected; - this.actual = params.actual; - this.message = this.passed_ ? 'Passed.' : params.message; - - var trace = (params.trace || new Error(this.message)); - this.trace = this.passed_ ? '' : trace; -}; - -jasmine.ExpectationResult.prototype.toString = function () { - return this.message; -}; - -jasmine.ExpectationResult.prototype.passed = function () { - return this.passed_; -}; - -/** - * Getter for the Jasmine environment. Ensures one gets created - */ -jasmine.getEnv = function() { - var env = jasmine.currentEnv_ = jasmine.currentEnv_ || new jasmine.Env(); - return env; -}; - -/** - * @ignore - * @private - * @param value - * @returns {Boolean} - */ -jasmine.isArray_ = function(value) { - return jasmine.isA_("Array", value); -}; - -/** - * @ignore - * @private - * @param value - * @returns {Boolean} - */ -jasmine.isString_ = function(value) { - return jasmine.isA_("String", value); -}; - -/** - * @ignore - * @private - * @param value - * @returns {Boolean} - */ -jasmine.isNumber_ = function(value) { - return jasmine.isA_("Number", value); -}; - -/** - * @ignore - * @private - * @param {String} typeName - * @param value - * @returns {Boolean} - */ -jasmine.isA_ = function(typeName, value) { - return Object.prototype.toString.apply(value) === '[object ' + typeName + ']'; -}; - -/** - * Pretty printer for expecations. Takes any object and turns it into a human-readable string. - * - * @param value {Object} an object to be outputted - * @returns {String} - */ -jasmine.pp = function(value) { - var stringPrettyPrinter = new jasmine.StringPrettyPrinter(); - stringPrettyPrinter.format(value); - return stringPrettyPrinter.string; -}; - -/** - * Returns true if the object is a DOM Node. - * - * @param {Object} obj object to check - * @returns {Boolean} - */ -jasmine.isDomNode = function(obj) { - return obj.nodeType > 0; -}; - -/** - * Returns a matchable 'generic' object of the class type. For use in expecations of type when values don't matter. - * - * @example - * // don't care about which function is passed in, as long as it's a function - * expect(mySpy).toHaveBeenCalledWith(jasmine.any(Function)); - * - * @param {Class} clazz - * @returns matchable object of the type clazz - */ -jasmine.any = function(clazz) { - return new jasmine.Matchers.Any(clazz); -}; - -/** - * Jasmine Spies are test doubles that can act as stubs, spies, fakes or when used in an expecation, mocks. - * - * Spies should be created in test setup, before expectations. They can then be checked, using the standard Jasmine - * expectation syntax. Spies can be checked if they were called or not and what the calling params were. - * - * A Spy has the following fields: wasCalled, callCount, mostRecentCall, and argsForCall (see docs). - * - * Spies are torn down at the end of every spec. - * - * Note: Do not call new jasmine.Spy() directly - a spy must be created using spyOn, jasmine.createSpy or jasmine.createSpyObj. - * - * @example - * // a stub - * var myStub = jasmine.createSpy('myStub'); // can be used anywhere - * - * // spy example - * var foo = { - * not: function(bool) { return !bool; } - * } - * - * // actual foo.not will not be called, execution stops - * spyOn(foo, 'not'); - - // foo.not spied upon, execution will continue to implementation - * spyOn(foo, 'not').andCallThrough(); - * - * // fake example - * var foo = { - * not: function(bool) { return !bool; } - * } - * - * // foo.not(val) will return val - * spyOn(foo, 'not').andCallFake(function(value) {return value;}); - * - * // mock example - * foo.not(7 == 7); - * expect(foo.not).toHaveBeenCalled(); - * expect(foo.not).toHaveBeenCalledWith(true); - * - * @constructor - * @see spyOn, jasmine.createSpy, jasmine.createSpyObj - * @param {String} name - */ -jasmine.Spy = function(name) { - /** - * The name of the spy, if provided. - */ - this.identity = name || 'unknown'; - /** - * Is this Object a spy? - */ - this.isSpy = true; - /** - * The actual function this spy stubs. - */ - this.plan = function() { - }; - /** - * Tracking of the most recent call to the spy. - * @example - * var mySpy = jasmine.createSpy('foo'); - * mySpy(1, 2); - * mySpy.mostRecentCall.args = [1, 2]; - */ - this.mostRecentCall = {}; - - /** - * Holds arguments for each call to the spy, indexed by call count - * @example - * var mySpy = jasmine.createSpy('foo'); - * mySpy(1, 2); - * mySpy(7, 8); - * mySpy.mostRecentCall.args = [7, 8]; - * mySpy.argsForCall[0] = [1, 2]; - * mySpy.argsForCall[1] = [7, 8]; - */ - this.argsForCall = []; - this.calls = []; -}; - -/** - * Tells a spy to call through to the actual implemenatation. - * - * @example - * var foo = { - * bar: function() { // do some stuff } - * } - * - * // defining a spy on an existing property: foo.bar - * spyOn(foo, 'bar').andCallThrough(); - */ -jasmine.Spy.prototype.andCallThrough = function() { - this.plan = this.originalValue; - return this; -}; - -/** - * For setting the return value of a spy. - * - * @example - * // defining a spy from scratch: foo() returns 'baz' - * var foo = jasmine.createSpy('spy on foo').andReturn('baz'); - * - * // defining a spy on an existing property: foo.bar() returns 'baz' - * spyOn(foo, 'bar').andReturn('baz'); - * - * @param {Object} value - */ -jasmine.Spy.prototype.andReturn = function(value) { - this.plan = function() { - return value; - }; - return this; -}; - -/** - * For throwing an exception when a spy is called. - * - * @example - * // defining a spy from scratch: foo() throws an exception w/ message 'ouch' - * var foo = jasmine.createSpy('spy on foo').andThrow('baz'); - * - * // defining a spy on an existing property: foo.bar() throws an exception w/ message 'ouch' - * spyOn(foo, 'bar').andThrow('baz'); - * - * @param {String} exceptionMsg - */ -jasmine.Spy.prototype.andThrow = function(exceptionMsg) { - this.plan = function() { - throw exceptionMsg; - }; - return this; -}; - -/** - * Calls an alternate implementation when a spy is called. - * - * @example - * var baz = function() { - * // do some stuff, return something - * } - * // defining a spy from scratch: foo() calls the function baz - * var foo = jasmine.createSpy('spy on foo').andCall(baz); - * - * // defining a spy on an existing property: foo.bar() calls an anonymnous function - * spyOn(foo, 'bar').andCall(function() { return 'baz';} ); - * - * @param {Function} fakeFunc - */ -jasmine.Spy.prototype.andCallFake = function(fakeFunc) { - this.plan = fakeFunc; - return this; -}; - -/** - * Resets all of a spy's the tracking variables so that it can be used again. - * - * @example - * spyOn(foo, 'bar'); - * - * foo.bar(); - * - * expect(foo.bar.callCount).toEqual(1); - * - * foo.bar.reset(); - * - * expect(foo.bar.callCount).toEqual(0); - */ -jasmine.Spy.prototype.reset = function() { - this.wasCalled = false; - this.callCount = 0; - this.argsForCall = []; - this.calls = []; - this.mostRecentCall = {}; -}; - -jasmine.createSpy = function(name) { - - var spyObj = function() { - spyObj.wasCalled = true; - spyObj.callCount++; - var args = jasmine.util.argsToArray(arguments); - spyObj.mostRecentCall.object = this; - spyObj.mostRecentCall.args = args; - spyObj.argsForCall.push(args); - spyObj.calls.push({object: this, args: args}); - return spyObj.plan.apply(this, arguments); - }; - - var spy = new jasmine.Spy(name); - - for (var prop in spy) { - spyObj[prop] = spy[prop]; - } - - spyObj.reset(); - - return spyObj; -}; - -/** - * Determines whether an object is a spy. - * - * @param {jasmine.Spy|Object} putativeSpy - * @returns {Boolean} - */ -jasmine.isSpy = function(putativeSpy) { - return putativeSpy && putativeSpy.isSpy; -}; - -/** - * Creates a more complicated spy: an Object that has every property a function that is a spy. Used for stubbing something - * large in one call. - * - * @param {String} baseName name of spy class - * @param {Array} methodNames array of names of methods to make spies - */ -jasmine.createSpyObj = function(baseName, methodNames) { - if (!jasmine.isArray_(methodNames) || methodNames.length === 0) { - throw new Error('createSpyObj requires a non-empty array of method names to create spies for'); - } - var obj = {}; - for (var i = 0; i < methodNames.length; i++) { - obj[methodNames[i]] = jasmine.createSpy(baseName + '.' + methodNames[i]); - } - return obj; -}; - -/** - * All parameters are pretty-printed and concatenated together, then written to the current spec's output. - * - * Be careful not to leave calls to jasmine.log in production code. - */ -jasmine.log = function() { - var spec = jasmine.getEnv().currentSpec; - spec.log.apply(spec, arguments); -}; - -/** - * Function that installs a spy on an existing object's method name. Used within a Spec to create a spy. - * - * @example - * // spy example - * var foo = { - * not: function(bool) { return !bool; } - * } - * spyOn(foo, 'not'); // actual foo.not will not be called, execution stops - * - * @see jasmine.createSpy - * @param obj - * @param methodName - * @returns a Jasmine spy that can be chained with all spy methods - */ -var spyOn = function(obj, methodName) { - return jasmine.getEnv().currentSpec.spyOn(obj, methodName); -}; -if (isCommonJS) exports.spyOn = spyOn; - -/** - * Creates a Jasmine spec that will be added to the current suite. - * - * // TODO: pending tests - * - * @example - * it('should be true', function() { - * expect(true).toEqual(true); - * }); - * - * @param {String} desc description of this specification - * @param {Function} func defines the preconditions and expectations of the spec - */ -var it = function(desc, func) { - return jasmine.getEnv().it(desc, func); -}; -if (isCommonJS) exports.it = it; - -/** - * Creates a disabled Jasmine spec. - * - * A convenience method that allows existing specs to be disabled temporarily during development. - * - * @param {String} desc description of this specification - * @param {Function} func defines the preconditions and expectations of the spec - */ -var xit = function(desc, func) { - return jasmine.getEnv().xit(desc, func); -}; -if (isCommonJS) exports.xit = xit; - -/** - * Starts a chain for a Jasmine expectation. - * - * It is passed an Object that is the actual value and should chain to one of the many - * jasmine.Matchers functions. - * - * @param {Object} actual Actual value to test against and expected value - */ -var expect = function(actual) { - return jasmine.getEnv().currentSpec.expect(actual); -}; -if (isCommonJS) exports.expect = expect; - -/** - * Defines part of a jasmine spec. Used in cominbination with waits or waitsFor in asynchrnous specs. - * - * @param {Function} func Function that defines part of a jasmine spec. - */ -var runs = function(func) { - jasmine.getEnv().currentSpec.runs(func); -}; -if (isCommonJS) exports.runs = runs; - -/** - * Waits a fixed time period before moving to the next block. - * - * @deprecated Use waitsFor() instead - * @param {Number} timeout milliseconds to wait - */ -var waits = function(timeout) { - jasmine.getEnv().currentSpec.waits(timeout); -}; -if (isCommonJS) exports.waits = waits; - -/** - * Waits for the latchFunction to return true before proceeding to the next block. - * - * @param {Function} latchFunction - * @param {String} optional_timeoutMessage - * @param {Number} optional_timeout - */ -var waitsFor = function(latchFunction, optional_timeoutMessage, optional_timeout) { - jasmine.getEnv().currentSpec.waitsFor.apply(jasmine.getEnv().currentSpec, arguments); -}; -if (isCommonJS) exports.waitsFor = waitsFor; - -/** - * A function that is called before each spec in a suite. - * - * Used for spec setup, including validating assumptions. - * - * @param {Function} beforeEachFunction - */ -var beforeEach = function(beforeEachFunction) { - jasmine.getEnv().beforeEach(beforeEachFunction); -}; -if (isCommonJS) exports.beforeEach = beforeEach; - -/** - * A function that is called after each spec in a suite. - * - * Used for restoring any state that is hijacked during spec execution. - * - * @param {Function} afterEachFunction - */ -var afterEach = function(afterEachFunction) { - jasmine.getEnv().afterEach(afterEachFunction); -}; -if (isCommonJS) exports.afterEach = afterEach; - -/** - * Defines a suite of specifications. - * - * Stores the description and all defined specs in the Jasmine environment as one suite of specs. Variables declared - * are accessible by calls to beforeEach, it, and afterEach. Describe blocks can be nested, allowing for specialization - * of setup in some tests. - * - * @example - * // TODO: a simple suite - * - * // TODO: a simple suite with a nested describe block - * - * @param {String} description A string, usually the class under test. - * @param {Function} specDefinitions function that defines several specs. - */ -var describe = function(description, specDefinitions) { - return jasmine.getEnv().describe(description, specDefinitions); -}; -if (isCommonJS) exports.describe = describe; - -/** - * Disables a suite of specifications. Used to disable some suites in a file, or files, temporarily during development. - * - * @param {String} description A string, usually the class under test. - * @param {Function} specDefinitions function that defines several specs. - */ -var xdescribe = function(description, specDefinitions) { - return jasmine.getEnv().xdescribe(description, specDefinitions); -}; -if (isCommonJS) exports.xdescribe = xdescribe; - - -// Provide the XMLHttpRequest class for IE 5.x-6.x: -jasmine.XmlHttpRequest = (typeof XMLHttpRequest == "undefined") ? function() { - function tryIt(f) { - try { - return f(); - } catch(e) { - } - return null; - } - - var xhr = tryIt(function() { - return new ActiveXObject("Msxml2.XMLHTTP.6.0"); - }) || - tryIt(function() { - return new ActiveXObject("Msxml2.XMLHTTP.3.0"); - }) || - tryIt(function() { - return new ActiveXObject("Msxml2.XMLHTTP"); - }) || - tryIt(function() { - return new ActiveXObject("Microsoft.XMLHTTP"); - }); - - if (!xhr) throw new Error("This browser does not support XMLHttpRequest."); - - return xhr; -} : XMLHttpRequest; -/** - * @namespace - */ -jasmine.util = {}; - -/** - * Declare that a child class inherit it's prototype from the parent class. - * - * @private - * @param {Function} childClass - * @param {Function} parentClass - */ -jasmine.util.inherit = function(childClass, parentClass) { - /** - * @private - */ - var subclass = function() { - }; - subclass.prototype = parentClass.prototype; - childClass.prototype = new subclass(); -}; - -jasmine.util.formatException = function(e) { - var lineNumber; - if (e.line) { - lineNumber = e.line; - } - else if (e.lineNumber) { - lineNumber = e.lineNumber; - } - - var file; - - if (e.sourceURL) { - file = e.sourceURL; - } - else if (e.fileName) { - file = e.fileName; - } - - var message = (e.name && e.message) ? (e.name + ': ' + e.message) : e.toString(); - - if (file && lineNumber) { - message += ' in ' + file + ' (line ' + lineNumber + ')'; - } - - return message; -}; - -jasmine.util.htmlEscape = function(str) { - if (!str) return str; - return str.replace(/&/g, '&') - .replace(//g, '>'); -}; - -jasmine.util.argsToArray = function(args) { - var arrayOfArgs = []; - for (var i = 0; i < args.length; i++) arrayOfArgs.push(args[i]); - return arrayOfArgs; -}; - -jasmine.util.extend = function(destination, source) { - for (var property in source) destination[property] = source[property]; - return destination; -}; - -/** - * Environment for Jasmine - * - * @constructor - */ -jasmine.Env = function() { - this.currentSpec = null; - this.currentSuite = null; - this.currentRunner_ = new jasmine.Runner(this); - - this.reporter = new jasmine.MultiReporter(); - - this.updateInterval = jasmine.DEFAULT_UPDATE_INTERVAL; - this.defaultTimeoutInterval = jasmine.DEFAULT_TIMEOUT_INTERVAL; - this.lastUpdate = 0; - this.specFilter = function() { - return true; - }; - - this.nextSpecId_ = 0; - this.nextSuiteId_ = 0; - this.equalityTesters_ = []; - - // wrap matchers - this.matchersClass = function() { - jasmine.Matchers.apply(this, arguments); - }; - jasmine.util.inherit(this.matchersClass, jasmine.Matchers); - - jasmine.Matchers.wrapInto_(jasmine.Matchers.prototype, this.matchersClass); -}; - - -jasmine.Env.prototype.setTimeout = jasmine.setTimeout; -jasmine.Env.prototype.clearTimeout = jasmine.clearTimeout; -jasmine.Env.prototype.setInterval = jasmine.setInterval; -jasmine.Env.prototype.clearInterval = jasmine.clearInterval; - -/** - * @returns an object containing jasmine version build info, if set. - */ -jasmine.Env.prototype.version = function () { - if (jasmine.version_) { - return jasmine.version_; - } else { - throw new Error('Version not set'); - } -}; - -/** - * @returns string containing jasmine version build info, if set. - */ -jasmine.Env.prototype.versionString = function() { - if (!jasmine.version_) { - return "version unknown"; - } - - var version = this.version(); - var versionString = version.major + "." + version.minor + "." + version.build; - if (version.release_candidate) { - versionString += ".rc" + version.release_candidate; - } - versionString += " revision " + version.revision; - return versionString; -}; - -/** - * @returns a sequential integer starting at 0 - */ -jasmine.Env.prototype.nextSpecId = function () { - return this.nextSpecId_++; -}; - -/** - * @returns a sequential integer starting at 0 - */ -jasmine.Env.prototype.nextSuiteId = function () { - return this.nextSuiteId_++; -}; - -/** - * Register a reporter to receive status updates from Jasmine. - * @param {jasmine.Reporter} reporter An object which will receive status updates. - */ -jasmine.Env.prototype.addReporter = function(reporter) { - this.reporter.addReporter(reporter); -}; - -jasmine.Env.prototype.execute = function() { - this.currentRunner_.execute(); -}; - -jasmine.Env.prototype.describe = function(description, specDefinitions) { - var suite = new jasmine.Suite(this, description, specDefinitions, this.currentSuite); - - var parentSuite = this.currentSuite; - if (parentSuite) { - parentSuite.add(suite); - } else { - this.currentRunner_.add(suite); - } - - this.currentSuite = suite; - - var declarationError = null; - try { - specDefinitions.call(suite); - } catch(e) { - declarationError = e; - } - - if (declarationError) { - this.it("encountered a declaration exception", function() { - throw declarationError; - }); - } - - this.currentSuite = parentSuite; - - return suite; -}; - -jasmine.Env.prototype.beforeEach = function(beforeEachFunction) { - if (this.currentSuite) { - this.currentSuite.beforeEach(beforeEachFunction); - } else { - this.currentRunner_.beforeEach(beforeEachFunction); - } -}; - -jasmine.Env.prototype.currentRunner = function () { - return this.currentRunner_; -}; - -jasmine.Env.prototype.afterEach = function(afterEachFunction) { - if (this.currentSuite) { - this.currentSuite.afterEach(afterEachFunction); - } else { - this.currentRunner_.afterEach(afterEachFunction); - } - -}; - -jasmine.Env.prototype.xdescribe = function(desc, specDefinitions) { - return { - execute: function() { - } - }; -}; - -jasmine.Env.prototype.it = function(description, func) { - var spec = new jasmine.Spec(this, this.currentSuite, description); - this.currentSuite.add(spec); - this.currentSpec = spec; - - if (func) { - spec.runs(func); - } - - return spec; -}; - -jasmine.Env.prototype.xit = function(desc, func) { - return { - id: this.nextSpecId(), - runs: function() { - } - }; -}; - -jasmine.Env.prototype.compareObjects_ = function(a, b, mismatchKeys, mismatchValues) { - if (a.__Jasmine_been_here_before__ === b && b.__Jasmine_been_here_before__ === a) { - return true; - } - - a.__Jasmine_been_here_before__ = b; - b.__Jasmine_been_here_before__ = a; - - var hasKey = function(obj, keyName) { - return obj !== null && obj[keyName] !== jasmine.undefined; - }; - - for (var property in b) { - if (!hasKey(a, property) && hasKey(b, property)) { - mismatchKeys.push("expected has key '" + property + "', but missing from actual."); - } - } - for (property in a) { - if (!hasKey(b, property) && hasKey(a, property)) { - mismatchKeys.push("expected missing key '" + property + "', but present in actual."); - } - } - for (property in b) { - if (property == '__Jasmine_been_here_before__') continue; - if (!this.equals_(a[property], b[property], mismatchKeys, mismatchValues)) { - mismatchValues.push("'" + property + "' was '" + (b[property] ? jasmine.util.htmlEscape(b[property].toString()) : b[property]) + "' in expected, but was '" + (a[property] ? jasmine.util.htmlEscape(a[property].toString()) : a[property]) + "' in actual."); - } - } - - if (jasmine.isArray_(a) && jasmine.isArray_(b) && a.length != b.length) { - mismatchValues.push("arrays were not the same length"); - } - - delete a.__Jasmine_been_here_before__; - delete b.__Jasmine_been_here_before__; - return (mismatchKeys.length === 0 && mismatchValues.length === 0); -}; - -jasmine.Env.prototype.equals_ = function(a, b, mismatchKeys, mismatchValues) { - mismatchKeys = mismatchKeys || []; - mismatchValues = mismatchValues || []; - - for (var i = 0; i < this.equalityTesters_.length; i++) { - var equalityTester = this.equalityTesters_[i]; - var result = equalityTester(a, b, this, mismatchKeys, mismatchValues); - if (result !== jasmine.undefined) return result; - } - - if (a === b) return true; - - if (a === jasmine.undefined || a === null || b === jasmine.undefined || b === null) { - return (a == jasmine.undefined && b == jasmine.undefined); - } - - if (jasmine.isDomNode(a) && jasmine.isDomNode(b)) { - return a === b; - } - - if (a instanceof Date && b instanceof Date) { - return a.getTime() == b.getTime(); - } - - if (a instanceof jasmine.Matchers.Any) { - return a.matches(b); - } - - if (b instanceof jasmine.Matchers.Any) { - return b.matches(a); - } - - if (jasmine.isString_(a) && jasmine.isString_(b)) { - return (a == b); - } - - if (jasmine.isNumber_(a) && jasmine.isNumber_(b)) { - return (a == b); - } - - if (typeof a === "object" && typeof b === "object") { - return this.compareObjects_(a, b, mismatchKeys, mismatchValues); - } - - //Straight check - return (a === b); -}; - -jasmine.Env.prototype.contains_ = function(haystack, needle) { - if (jasmine.isArray_(haystack)) { - for (var i = 0; i < haystack.length; i++) { - if (this.equals_(haystack[i], needle)) return true; - } - return false; - } - return haystack.indexOf(needle) >= 0; -}; - -jasmine.Env.prototype.addEqualityTester = function(equalityTester) { - this.equalityTesters_.push(equalityTester); -}; -/** No-op base class for Jasmine reporters. - * - * @constructor - */ -jasmine.Reporter = function() { -}; - -//noinspection JSUnusedLocalSymbols -jasmine.Reporter.prototype.reportRunnerStarting = function(runner) { -}; - -//noinspection JSUnusedLocalSymbols -jasmine.Reporter.prototype.reportRunnerResults = function(runner) { -}; - -//noinspection JSUnusedLocalSymbols -jasmine.Reporter.prototype.reportSuiteResults = function(suite) { -}; - -//noinspection JSUnusedLocalSymbols -jasmine.Reporter.prototype.reportSpecStarting = function(spec) { -}; - -//noinspection JSUnusedLocalSymbols -jasmine.Reporter.prototype.reportSpecResults = function(spec) { -}; - -//noinspection JSUnusedLocalSymbols -jasmine.Reporter.prototype.log = function(str) { -}; - -/** - * Blocks are functions with executable code that make up a spec. - * - * @constructor - * @param {jasmine.Env} env - * @param {Function} func - * @param {jasmine.Spec} spec - */ -jasmine.Block = function(env, func, spec) { - this.env = env; - this.func = func; - this.spec = spec; -}; - -jasmine.Block.prototype.execute = function(onComplete) { - try { - this.func.apply(this.spec); - } catch (e) { - this.spec.fail(e); - } - onComplete(); -}; -/** JavaScript API reporter. - * - * @constructor - */ -jasmine.JsApiReporter = function() { - this.started = false; - this.finished = false; - this.suites_ = []; - this.results_ = {}; -}; - -jasmine.JsApiReporter.prototype.reportRunnerStarting = function(runner) { - this.started = true; - var suites = runner.topLevelSuites(); - for (var i = 0; i < suites.length; i++) { - var suite = suites[i]; - this.suites_.push(this.summarize_(suite)); - } -}; - -jasmine.JsApiReporter.prototype.suites = function() { - return this.suites_; -}; - -jasmine.JsApiReporter.prototype.summarize_ = function(suiteOrSpec) { - var isSuite = suiteOrSpec instanceof jasmine.Suite; - var summary = { - id: suiteOrSpec.id, - name: suiteOrSpec.description, - type: isSuite ? 'suite' : 'spec', - children: [] - }; - - if (isSuite) { - var children = suiteOrSpec.children(); - for (var i = 0; i < children.length; i++) { - summary.children.push(this.summarize_(children[i])); - } - } - return summary; -}; - -jasmine.JsApiReporter.prototype.results = function() { - return this.results_; -}; - -jasmine.JsApiReporter.prototype.resultsForSpec = function(specId) { - return this.results_[specId]; -}; - -//noinspection JSUnusedLocalSymbols -jasmine.JsApiReporter.prototype.reportRunnerResults = function(runner) { - this.finished = true; -}; - -//noinspection JSUnusedLocalSymbols -jasmine.JsApiReporter.prototype.reportSuiteResults = function(suite) { -}; - -//noinspection JSUnusedLocalSymbols -jasmine.JsApiReporter.prototype.reportSpecResults = function(spec) { - this.results_[spec.id] = { - messages: spec.results().getItems(), - result: spec.results().failedCount > 0 ? "failed" : "passed" - }; -}; - -//noinspection JSUnusedLocalSymbols -jasmine.JsApiReporter.prototype.log = function(str) { -}; - -jasmine.JsApiReporter.prototype.resultsForSpecs = function(specIds){ - var results = {}; - for (var i = 0; i < specIds.length; i++) { - var specId = specIds[i]; - results[specId] = this.summarizeResult_(this.results_[specId]); - } - return results; -}; - -jasmine.JsApiReporter.prototype.summarizeResult_ = function(result){ - var summaryMessages = []; - var messagesLength = result.messages.length; - for (var messageIndex = 0; messageIndex < messagesLength; messageIndex++) { - var resultMessage = result.messages[messageIndex]; - summaryMessages.push({ - text: resultMessage.type == 'log' ? resultMessage.toString() : jasmine.undefined, - passed: resultMessage.passed ? resultMessage.passed() : true, - type: resultMessage.type, - message: resultMessage.message, - trace: { - stack: resultMessage.passed && !resultMessage.passed() ? resultMessage.trace.stack : jasmine.undefined - } - }); - } - - return { - result : result.result, - messages : summaryMessages - }; -}; - -/** - * @constructor - * @param {jasmine.Env} env - * @param actual - * @param {jasmine.Spec} spec - */ -jasmine.Matchers = function(env, actual, spec, opt_isNot) { - this.env = env; - this.actual = actual; - this.spec = spec; - this.isNot = opt_isNot || false; - this.reportWasCalled_ = false; -}; - -// todo: @deprecated as of Jasmine 0.11, remove soon [xw] -jasmine.Matchers.pp = function(str) { - throw new Error("jasmine.Matchers.pp() is no longer supported, please use jasmine.pp() instead!"); -}; - -// todo: @deprecated Deprecated as of Jasmine 0.10. Rewrite your custom matchers to return true or false. [xw] -jasmine.Matchers.prototype.report = function(result, failing_message, details) { - throw new Error("As of jasmine 0.11, custom matchers must be implemented differently -- please see jasmine docs"); -}; - -jasmine.Matchers.wrapInto_ = function(prototype, matchersClass) { - for (var methodName in prototype) { - if (methodName == 'report') continue; - var orig = prototype[methodName]; - matchersClass.prototype[methodName] = jasmine.Matchers.matcherFn_(methodName, orig); - } -}; - -jasmine.Matchers.matcherFn_ = function(matcherName, matcherFunction) { - return function() { - var matcherArgs = jasmine.util.argsToArray(arguments); - var result = matcherFunction.apply(this, arguments); - - if (this.isNot) { - result = !result; - } - - if (this.reportWasCalled_) return result; - - var message; - if (!result) { - if (this.message) { - message = this.message.apply(this, arguments); - if (jasmine.isArray_(message)) { - message = message[this.isNot ? 1 : 0]; - } - } else { - var englishyPredicate = matcherName.replace(/[A-Z]/g, function(s) { return ' ' + s.toLowerCase(); }); - message = "Expected " + jasmine.pp(this.actual) + (this.isNot ? " not " : " ") + englishyPredicate; - if (matcherArgs.length > 0) { - for (var i = 0; i < matcherArgs.length; i++) { - if (i > 0) message += ","; - message += " " + jasmine.pp(matcherArgs[i]); - } - } - message += "."; - } - } - var expectationResult = new jasmine.ExpectationResult({ - matcherName: matcherName, - passed: result, - expected: matcherArgs.length > 1 ? matcherArgs : matcherArgs[0], - actual: this.actual, - message: message - }); - this.spec.addMatcherResult(expectationResult); - return jasmine.undefined; - }; -}; - - - - -/** - * toBe: compares the actual to the expected using === - * @param expected - */ -jasmine.Matchers.prototype.toBe = function(expected) { - return this.actual === expected; -}; - -/** - * toNotBe: compares the actual to the expected using !== - * @param expected - * @deprecated as of 1.0. Use not.toBe() instead. - */ -jasmine.Matchers.prototype.toNotBe = function(expected) { - return this.actual !== expected; -}; - -/** - * toEqual: compares the actual to the expected using common sense equality. Handles Objects, Arrays, etc. - * - * @param expected - */ -jasmine.Matchers.prototype.toEqual = function(expected) { - return this.env.equals_(this.actual, expected); -}; - -/** - * toNotEqual: compares the actual to the expected using the ! of jasmine.Matchers.toEqual - * @param expected - * @deprecated as of 1.0. Use not.toNotEqual() instead. - */ -jasmine.Matchers.prototype.toNotEqual = function(expected) { - return !this.env.equals_(this.actual, expected); -}; - -/** - * Matcher that compares the actual to the expected using a regular expression. Constructs a RegExp, so takes - * a pattern or a String. - * - * @param expected - */ -jasmine.Matchers.prototype.toMatch = function(expected) { - return new RegExp(expected).test(this.actual); -}; - -/** - * Matcher that compares the actual to the expected using the boolean inverse of jasmine.Matchers.toMatch - * @param expected - * @deprecated as of 1.0. Use not.toMatch() instead. - */ -jasmine.Matchers.prototype.toNotMatch = function(expected) { - return !(new RegExp(expected).test(this.actual)); -}; - -/** - * Matcher that compares the actual to jasmine.undefined. - */ -jasmine.Matchers.prototype.toBeDefined = function() { - return (this.actual !== jasmine.undefined); -}; - -/** - * Matcher that compares the actual to jasmine.undefined. - */ -jasmine.Matchers.prototype.toBeUndefined = function() { - return (this.actual === jasmine.undefined); -}; - -/** - * Matcher that compares the actual to null. - */ -jasmine.Matchers.prototype.toBeNull = function() { - return (this.actual === null); -}; - -/** - * Matcher that boolean not-nots the actual. - */ -jasmine.Matchers.prototype.toBeTruthy = function() { - return !!this.actual; -}; - - -/** - * Matcher that boolean nots the actual. - */ -jasmine.Matchers.prototype.toBeFalsy = function() { - return !this.actual; -}; - - -/** - * Matcher that checks to see if the actual, a Jasmine spy, was called. - */ -jasmine.Matchers.prototype.toHaveBeenCalled = function() { - if (arguments.length > 0) { - throw new Error('toHaveBeenCalled does not take arguments, use toHaveBeenCalledWith'); - } - - if (!jasmine.isSpy(this.actual)) { - throw new Error('Expected a spy, but got ' + jasmine.pp(this.actual) + '.'); - } - - this.message = function() { - return [ - "Expected spy " + this.actual.identity + " to have been called.", - "Expected spy " + this.actual.identity + " not to have been called." - ]; - }; - - return this.actual.wasCalled; -}; - -/** @deprecated Use expect(xxx).toHaveBeenCalled() instead */ -jasmine.Matchers.prototype.wasCalled = jasmine.Matchers.prototype.toHaveBeenCalled; - -/** - * Matcher that checks to see if the actual, a Jasmine spy, was not called. - * - * @deprecated Use expect(xxx).not.toHaveBeenCalled() instead - */ -jasmine.Matchers.prototype.wasNotCalled = function() { - if (arguments.length > 0) { - throw new Error('wasNotCalled does not take arguments'); - } - - if (!jasmine.isSpy(this.actual)) { - throw new Error('Expected a spy, but got ' + jasmine.pp(this.actual) + '.'); - } - - this.message = function() { - return [ - "Expected spy " + this.actual.identity + " to not have been called.", - "Expected spy " + this.actual.identity + " to have been called." - ]; - }; - - return !this.actual.wasCalled; -}; - -/** - * Matcher that checks to see if the actual, a Jasmine spy, was called with a set of parameters. - * - * @example - * - */ -jasmine.Matchers.prototype.toHaveBeenCalledWith = function() { - var expectedArgs = jasmine.util.argsToArray(arguments); - if (!jasmine.isSpy(this.actual)) { - throw new Error('Expected a spy, but got ' + jasmine.pp(this.actual) + '.'); - } - this.message = function() { - if (this.actual.callCount === 0) { - // todo: what should the failure message for .not.toHaveBeenCalledWith() be? is this right? test better. [xw] - return [ - "Expected spy " + this.actual.identity + " to have been called with " + jasmine.pp(expectedArgs) + " but it was never called.", - "Expected spy " + this.actual.identity + " not to have been called with " + jasmine.pp(expectedArgs) + " but it was." - ]; - } else { - return [ - "Expected spy " + this.actual.identity + " to have been called with " + jasmine.pp(expectedArgs) + " but was called with " + jasmine.pp(this.actual.argsForCall), - "Expected spy " + this.actual.identity + " not to have been called with " + jasmine.pp(expectedArgs) + " but was called with " + jasmine.pp(this.actual.argsForCall) - ]; - } - }; - - return this.env.contains_(this.actual.argsForCall, expectedArgs); -}; - -/** @deprecated Use expect(xxx).toHaveBeenCalledWith() instead */ -jasmine.Matchers.prototype.wasCalledWith = jasmine.Matchers.prototype.toHaveBeenCalledWith; - -/** @deprecated Use expect(xxx).not.toHaveBeenCalledWith() instead */ -jasmine.Matchers.prototype.wasNotCalledWith = function() { - var expectedArgs = jasmine.util.argsToArray(arguments); - if (!jasmine.isSpy(this.actual)) { - throw new Error('Expected a spy, but got ' + jasmine.pp(this.actual) + '.'); - } - - this.message = function() { - return [ - "Expected spy not to have been called with " + jasmine.pp(expectedArgs) + " but it was", - "Expected spy to have been called with " + jasmine.pp(expectedArgs) + " but it was" - ]; - }; - - return !this.env.contains_(this.actual.argsForCall, expectedArgs); -}; - -/** - * Matcher that checks that the expected item is an element in the actual Array. - * - * @param {Object} expected - */ -jasmine.Matchers.prototype.toContain = function(expected) { - return this.env.contains_(this.actual, expected); -}; - -/** - * Matcher that checks that the expected item is NOT an element in the actual Array. - * - * @param {Object} expected - * @deprecated as of 1.0. Use not.toNotContain() instead. - */ -jasmine.Matchers.prototype.toNotContain = function(expected) { - return !this.env.contains_(this.actual, expected); -}; - -jasmine.Matchers.prototype.toBeLessThan = function(expected) { - return this.actual < expected; -}; - -jasmine.Matchers.prototype.toBeGreaterThan = function(expected) { - return this.actual > expected; -}; - -/** - * Matcher that checks that the expected item is equal to the actual item - * up to a given level of decimal precision (default 2). - * - * @param {Number} expected - * @param {Number} precision - */ -jasmine.Matchers.prototype.toBeCloseTo = function(expected, precision) { - if (!(precision === 0)) { - precision = precision || 2; - } - var multiplier = Math.pow(10, precision); - var actual = Math.round(this.actual * multiplier); - expected = Math.round(expected * multiplier); - return expected == actual; -}; - -/** - * Matcher that checks that the expected exception was thrown by the actual. - * - * @param {String} expected - */ -jasmine.Matchers.prototype.toThrow = function(expected) { - var result = false; - var exception; - if (typeof this.actual != 'function') { - throw new Error('Actual is not a function'); - } - try { - this.actual(); - } catch (e) { - exception = e; - } - if (exception) { - result = (expected === jasmine.undefined || this.env.equals_(exception.message || exception, expected.message || expected)); - } - - var not = this.isNot ? "not " : ""; - - this.message = function() { - if (exception && (expected === jasmine.undefined || !this.env.equals_(exception.message || exception, expected.message || expected))) { - return ["Expected function " + not + "to throw", expected ? expected.message || expected : "an exception", ", but it threw", exception.message || exception].join(' '); - } else { - return "Expected function to throw an exception."; - } - }; - - return result; -}; - -jasmine.Matchers.Any = function(expectedClass) { - this.expectedClass = expectedClass; -}; - -jasmine.Matchers.Any.prototype.matches = function(other) { - if (this.expectedClass == String) { - return typeof other == 'string' || other instanceof String; - } - - if (this.expectedClass == Number) { - return typeof other == 'number' || other instanceof Number; - } - - if (this.expectedClass == Function) { - return typeof other == 'function' || other instanceof Function; - } - - if (this.expectedClass == Object) { - return typeof other == 'object'; - } - - return other instanceof this.expectedClass; -}; - -jasmine.Matchers.Any.prototype.toString = function() { - return ''; -}; - -/** - * @constructor - */ -jasmine.MultiReporter = function() { - this.subReporters_ = []; -}; -jasmine.util.inherit(jasmine.MultiReporter, jasmine.Reporter); - -jasmine.MultiReporter.prototype.addReporter = function(reporter) { - this.subReporters_.push(reporter); -}; - -(function() { - var functionNames = [ - "reportRunnerStarting", - "reportRunnerResults", - "reportSuiteResults", - "reportSpecStarting", - "reportSpecResults", - "log" - ]; - for (var i = 0; i < functionNames.length; i++) { - var functionName = functionNames[i]; - jasmine.MultiReporter.prototype[functionName] = (function(functionName) { - return function() { - for (var j = 0; j < this.subReporters_.length; j++) { - var subReporter = this.subReporters_[j]; - if (subReporter[functionName]) { - subReporter[functionName].apply(subReporter, arguments); - } - } - }; - })(functionName); - } -})(); -/** - * Holds results for a set of Jasmine spec. Allows for the results array to hold another jasmine.NestedResults - * - * @constructor - */ -jasmine.NestedResults = function() { - /** - * The total count of results - */ - this.totalCount = 0; - /** - * Number of passed results - */ - this.passedCount = 0; - /** - * Number of failed results - */ - this.failedCount = 0; - /** - * Was this suite/spec skipped? - */ - this.skipped = false; - /** - * @ignore - */ - this.items_ = []; -}; - -/** - * Roll up the result counts. - * - * @param result - */ -jasmine.NestedResults.prototype.rollupCounts = function(result) { - this.totalCount += result.totalCount; - this.passedCount += result.passedCount; - this.failedCount += result.failedCount; -}; - -/** - * Adds a log message. - * @param values Array of message parts which will be concatenated later. - */ -jasmine.NestedResults.prototype.log = function(values) { - this.items_.push(new jasmine.MessageResult(values)); -}; - -/** - * Getter for the results: message & results. - */ -jasmine.NestedResults.prototype.getItems = function() { - return this.items_; -}; - -/** - * Adds a result, tracking counts (total, passed, & failed) - * @param {jasmine.ExpectationResult|jasmine.NestedResults} result - */ -jasmine.NestedResults.prototype.addResult = function(result) { - if (result.type != 'log') { - if (result.items_) { - this.rollupCounts(result); - } else { - this.totalCount++; - if (result.passed()) { - this.passedCount++; - } else { - this.failedCount++; - } - } - } - this.items_.push(result); -}; - -/** - * @returns {Boolean} True if everything below passed - */ -jasmine.NestedResults.prototype.passed = function() { - return this.passedCount === this.totalCount; -}; -/** - * Base class for pretty printing for expectation results. - */ -jasmine.PrettyPrinter = function() { - this.ppNestLevel_ = 0; -}; - -/** - * Formats a value in a nice, human-readable string. - * - * @param value - */ -jasmine.PrettyPrinter.prototype.format = function(value) { - if (this.ppNestLevel_ > 40) { - throw new Error('jasmine.PrettyPrinter: format() nested too deeply!'); - } - - this.ppNestLevel_++; - try { - if (value === jasmine.undefined) { - this.emitScalar('undefined'); - } else if (value === null) { - this.emitScalar('null'); - } else if (value === jasmine.getGlobal()) { - this.emitScalar(''); - } else if (value instanceof jasmine.Matchers.Any) { - this.emitScalar(value.toString()); - } else if (typeof value === 'string') { - this.emitString(value); - } else if (jasmine.isSpy(value)) { - this.emitScalar("spy on " + value.identity); - } else if (value instanceof RegExp) { - this.emitScalar(value.toString()); - } else if (typeof value === 'function') { - this.emitScalar('Function'); - } else if (typeof value.nodeType === 'number') { - this.emitScalar('HTMLNode'); - } else if (value instanceof Date) { - this.emitScalar('Date(' + value + ')'); - } else if (value.__Jasmine_been_here_before__) { - this.emitScalar(''); - } else if (jasmine.isArray_(value) || typeof value == 'object') { - value.__Jasmine_been_here_before__ = true; - if (jasmine.isArray_(value)) { - this.emitArray(value); - } else { - this.emitObject(value); - } - delete value.__Jasmine_been_here_before__; - } else { - this.emitScalar(value.toString()); - } - } finally { - this.ppNestLevel_--; - } -}; - -jasmine.PrettyPrinter.prototype.iterateObject = function(obj, fn) { - for (var property in obj) { - if (property == '__Jasmine_been_here_before__') continue; - fn(property, obj.__lookupGetter__ ? (obj.__lookupGetter__(property) !== jasmine.undefined && - obj.__lookupGetter__(property) !== null) : false); - } -}; - -jasmine.PrettyPrinter.prototype.emitArray = jasmine.unimplementedMethod_; -jasmine.PrettyPrinter.prototype.emitObject = jasmine.unimplementedMethod_; -jasmine.PrettyPrinter.prototype.emitScalar = jasmine.unimplementedMethod_; -jasmine.PrettyPrinter.prototype.emitString = jasmine.unimplementedMethod_; - -jasmine.StringPrettyPrinter = function() { - jasmine.PrettyPrinter.call(this); - - this.string = ''; -}; -jasmine.util.inherit(jasmine.StringPrettyPrinter, jasmine.PrettyPrinter); - -jasmine.StringPrettyPrinter.prototype.emitScalar = function(value) { - this.append(value); -}; - -jasmine.StringPrettyPrinter.prototype.emitString = function(value) { - this.append("'" + value + "'"); -}; - -jasmine.StringPrettyPrinter.prototype.emitArray = function(array) { - this.append('[ '); - for (var i = 0; i < array.length; i++) { - if (i > 0) { - this.append(', '); - } - this.format(array[i]); - } - this.append(' ]'); -}; - -jasmine.StringPrettyPrinter.prototype.emitObject = function(obj) { - var self = this; - this.append('{ '); - var first = true; - - this.iterateObject(obj, function(property, isGetter) { - if (first) { - first = false; - } else { - self.append(', '); - } - - self.append(property); - self.append(' : '); - if (isGetter) { - self.append(''); - } else { - self.format(obj[property]); - } - }); - - this.append(' }'); -}; - -jasmine.StringPrettyPrinter.prototype.append = function(value) { - this.string += value; -}; -jasmine.Queue = function(env) { - this.env = env; - this.blocks = []; - this.running = false; - this.index = 0; - this.offset = 0; - this.abort = false; -}; - -jasmine.Queue.prototype.addBefore = function(block) { - this.blocks.unshift(block); -}; - -jasmine.Queue.prototype.add = function(block) { - this.blocks.push(block); -}; - -jasmine.Queue.prototype.insertNext = function(block) { - this.blocks.splice((this.index + this.offset + 1), 0, block); - this.offset++; -}; - -jasmine.Queue.prototype.start = function(onComplete) { - this.running = true; - this.onComplete = onComplete; - this.next_(); -}; - -jasmine.Queue.prototype.isRunning = function() { - return this.running; -}; - -jasmine.Queue.LOOP_DONT_RECURSE = true; - -jasmine.Queue.prototype.next_ = function() { - var self = this; - var goAgain = true; - - while (goAgain) { - goAgain = false; - - if (self.index < self.blocks.length && !this.abort) { - var calledSynchronously = true; - var completedSynchronously = false; - - var onComplete = function () { - if (jasmine.Queue.LOOP_DONT_RECURSE && calledSynchronously) { - completedSynchronously = true; - return; - } - - if (self.blocks[self.index].abort) { - self.abort = true; - } - - self.offset = 0; - self.index++; - - var now = new Date().getTime(); - if (self.env.updateInterval && now - self.env.lastUpdate > self.env.updateInterval) { - self.env.lastUpdate = now; - self.env.setTimeout(function() { - self.next_(); - }, 0); - } else { - if (jasmine.Queue.LOOP_DONT_RECURSE && completedSynchronously) { - goAgain = true; - } else { - self.next_(); - } - } - }; - self.blocks[self.index].execute(onComplete); - - calledSynchronously = false; - if (completedSynchronously) { - onComplete(); - } - - } else { - self.running = false; - if (self.onComplete) { - self.onComplete(); - } - } - } -}; - -jasmine.Queue.prototype.results = function() { - var results = new jasmine.NestedResults(); - for (var i = 0; i < this.blocks.length; i++) { - if (this.blocks[i].results) { - results.addResult(this.blocks[i].results()); - } - } - return results; -}; - - -/** - * Runner - * - * @constructor - * @param {jasmine.Env} env - */ -jasmine.Runner = function(env) { - var self = this; - self.env = env; - self.queue = new jasmine.Queue(env); - self.before_ = []; - self.after_ = []; - self.suites_ = []; -}; - -jasmine.Runner.prototype.execute = function() { - var self = this; - if (self.env.reporter.reportRunnerStarting) { - self.env.reporter.reportRunnerStarting(this); - } - self.queue.start(function () { - self.finishCallback(); - }); -}; - -jasmine.Runner.prototype.beforeEach = function(beforeEachFunction) { - beforeEachFunction.typeName = 'beforeEach'; - this.before_.splice(0,0,beforeEachFunction); -}; - -jasmine.Runner.prototype.afterEach = function(afterEachFunction) { - afterEachFunction.typeName = 'afterEach'; - this.after_.splice(0,0,afterEachFunction); -}; - - -jasmine.Runner.prototype.finishCallback = function() { - this.env.reporter.reportRunnerResults(this); -}; - -jasmine.Runner.prototype.addSuite = function(suite) { - this.suites_.push(suite); -}; - -jasmine.Runner.prototype.add = function(block) { - if (block instanceof jasmine.Suite) { - this.addSuite(block); - } - this.queue.add(block); -}; - -jasmine.Runner.prototype.specs = function () { - var suites = this.suites(); - var specs = []; - for (var i = 0; i < suites.length; i++) { - specs = specs.concat(suites[i].specs()); - } - return specs; -}; - -jasmine.Runner.prototype.suites = function() { - return this.suites_; -}; - -jasmine.Runner.prototype.topLevelSuites = function() { - var topLevelSuites = []; - for (var i = 0; i < this.suites_.length; i++) { - if (!this.suites_[i].parentSuite) { - topLevelSuites.push(this.suites_[i]); - } - } - return topLevelSuites; -}; - -jasmine.Runner.prototype.results = function() { - return this.queue.results(); -}; -/** - * Internal representation of a Jasmine specification, or test. - * - * @constructor - * @param {jasmine.Env} env - * @param {jasmine.Suite} suite - * @param {String} description - */ -jasmine.Spec = function(env, suite, description) { - if (!env) { - throw new Error('jasmine.Env() required'); - } - if (!suite) { - throw new Error('jasmine.Suite() required'); - } - var spec = this; - spec.id = env.nextSpecId ? env.nextSpecId() : null; - spec.env = env; - spec.suite = suite; - spec.description = description; - spec.queue = new jasmine.Queue(env); - - spec.afterCallbacks = []; - spec.spies_ = []; - - spec.results_ = new jasmine.NestedResults(); - spec.results_.description = description; - spec.matchersClass = null; -}; - -jasmine.Spec.prototype.getFullName = function() { - return this.suite.getFullName() + ' ' + this.description + '.'; -}; - - -jasmine.Spec.prototype.results = function() { - return this.results_; -}; - -/** - * All parameters are pretty-printed and concatenated together, then written to the spec's output. - * - * Be careful not to leave calls to jasmine.log in production code. - */ -jasmine.Spec.prototype.log = function() { - return this.results_.log(arguments); -}; - -jasmine.Spec.prototype.runs = function (func) { - var block = new jasmine.Block(this.env, func, this); - this.addToQueue(block); - return this; -}; - -jasmine.Spec.prototype.addToQueue = function (block) { - if (this.queue.isRunning()) { - this.queue.insertNext(block); - } else { - this.queue.add(block); - } -}; - -/** - * @param {jasmine.ExpectationResult} result - */ -jasmine.Spec.prototype.addMatcherResult = function(result) { - this.results_.addResult(result); -}; - -jasmine.Spec.prototype.expect = function(actual) { - var positive = new (this.getMatchersClass_())(this.env, actual, this); - positive.not = new (this.getMatchersClass_())(this.env, actual, this, true); - return positive; -}; - -/** - * Waits a fixed time period before moving to the next block. - * - * @deprecated Use waitsFor() instead - * @param {Number} timeout milliseconds to wait - */ -jasmine.Spec.prototype.waits = function(timeout) { - var waitsFunc = new jasmine.WaitsBlock(this.env, timeout, this); - this.addToQueue(waitsFunc); - return this; -}; - -/** - * Waits for the latchFunction to return true before proceeding to the next block. - * - * @param {Function} latchFunction - * @param {String} optional_timeoutMessage - * @param {Number} optional_timeout - */ -jasmine.Spec.prototype.waitsFor = function(latchFunction, optional_timeoutMessage, optional_timeout) { - var latchFunction_ = null; - var optional_timeoutMessage_ = null; - var optional_timeout_ = null; - - for (var i = 0; i < arguments.length; i++) { - var arg = arguments[i]; - switch (typeof arg) { - case 'function': - latchFunction_ = arg; - break; - case 'string': - optional_timeoutMessage_ = arg; - break; - case 'number': - optional_timeout_ = arg; - break; - } - } - - var waitsForFunc = new jasmine.WaitsForBlock(this.env, optional_timeout_, latchFunction_, optional_timeoutMessage_, this); - this.addToQueue(waitsForFunc); - return this; -}; - -jasmine.Spec.prototype.fail = function (e) { - var expectationResult = new jasmine.ExpectationResult({ - passed: false, - message: e ? jasmine.util.formatException(e) : 'Exception', - trace: { stack: e.stack } - }); - this.results_.addResult(expectationResult); -}; - -jasmine.Spec.prototype.getMatchersClass_ = function() { - return this.matchersClass || this.env.matchersClass; -}; - -jasmine.Spec.prototype.addMatchers = function(matchersPrototype) { - var parent = this.getMatchersClass_(); - var newMatchersClass = function() { - parent.apply(this, arguments); - }; - jasmine.util.inherit(newMatchersClass, parent); - jasmine.Matchers.wrapInto_(matchersPrototype, newMatchersClass); - this.matchersClass = newMatchersClass; -}; - -jasmine.Spec.prototype.finishCallback = function() { - this.env.reporter.reportSpecResults(this); -}; - -jasmine.Spec.prototype.finish = function(onComplete) { - this.removeAllSpies(); - this.finishCallback(); - if (onComplete) { - onComplete(); - } -}; - -jasmine.Spec.prototype.after = function(doAfter) { - if (this.queue.isRunning()) { - this.queue.add(new jasmine.Block(this.env, doAfter, this)); - } else { - this.afterCallbacks.unshift(doAfter); - } -}; - -jasmine.Spec.prototype.execute = function(onComplete) { - var spec = this; - if (!spec.env.specFilter(spec)) { - spec.results_.skipped = true; - spec.finish(onComplete); - return; - } - - this.env.reporter.reportSpecStarting(this); - - spec.env.currentSpec = spec; - - spec.addBeforesAndAftersToQueue(); - - spec.queue.start(function () { - spec.finish(onComplete); - }); -}; - -jasmine.Spec.prototype.addBeforesAndAftersToQueue = function() { - var runner = this.env.currentRunner(); - var i; - - for (var suite = this.suite; suite; suite = suite.parentSuite) { - for (i = 0; i < suite.before_.length; i++) { - this.queue.addBefore(new jasmine.Block(this.env, suite.before_[i], this)); - } - } - for (i = 0; i < runner.before_.length; i++) { - this.queue.addBefore(new jasmine.Block(this.env, runner.before_[i], this)); - } - for (i = 0; i < this.afterCallbacks.length; i++) { - this.queue.add(new jasmine.Block(this.env, this.afterCallbacks[i], this)); - } - for (suite = this.suite; suite; suite = suite.parentSuite) { - for (i = 0; i < suite.after_.length; i++) { - this.queue.add(new jasmine.Block(this.env, suite.after_[i], this)); - } - } - for (i = 0; i < runner.after_.length; i++) { - this.queue.add(new jasmine.Block(this.env, runner.after_[i], this)); - } -}; - -jasmine.Spec.prototype.explodes = function() { - throw 'explodes function should not have been called'; -}; - -jasmine.Spec.prototype.spyOn = function(obj, methodName, ignoreMethodDoesntExist) { - if (obj == jasmine.undefined) { - throw "spyOn could not find an object to spy upon for " + methodName + "()"; - } - - if (!ignoreMethodDoesntExist && obj[methodName] === jasmine.undefined) { - throw methodName + '() method does not exist'; - } - - if (!ignoreMethodDoesntExist && obj[methodName] && obj[methodName].isSpy) { - throw new Error(methodName + ' has already been spied upon'); - } - - var spyObj = jasmine.createSpy(methodName); - - this.spies_.push(spyObj); - spyObj.baseObj = obj; - spyObj.methodName = methodName; - spyObj.originalValue = obj[methodName]; - - obj[methodName] = spyObj; - - return spyObj; -}; - -jasmine.Spec.prototype.removeAllSpies = function() { - for (var i = 0; i < this.spies_.length; i++) { - var spy = this.spies_[i]; - spy.baseObj[spy.methodName] = spy.originalValue; - } - this.spies_ = []; -}; - -/** - * Internal representation of a Jasmine suite. - * - * @constructor - * @param {jasmine.Env} env - * @param {String} description - * @param {Function} specDefinitions - * @param {jasmine.Suite} parentSuite - */ -jasmine.Suite = function(env, description, specDefinitions, parentSuite) { - var self = this; - self.id = env.nextSuiteId ? env.nextSuiteId() : null; - self.description = description; - self.queue = new jasmine.Queue(env); - self.parentSuite = parentSuite; - self.env = env; - self.before_ = []; - self.after_ = []; - self.children_ = []; - self.suites_ = []; - self.specs_ = []; -}; - -jasmine.Suite.prototype.getFullName = function() { - var fullName = this.description; - for (var parentSuite = this.parentSuite; parentSuite; parentSuite = parentSuite.parentSuite) { - fullName = parentSuite.description + ' ' + fullName; - } - return fullName; -}; - -jasmine.Suite.prototype.finish = function(onComplete) { - this.env.reporter.reportSuiteResults(this); - this.finished = true; - if (typeof(onComplete) == 'function') { - onComplete(); - } -}; - -jasmine.Suite.prototype.beforeEach = function(beforeEachFunction) { - beforeEachFunction.typeName = 'beforeEach'; - this.before_.unshift(beforeEachFunction); -}; - -jasmine.Suite.prototype.afterEach = function(afterEachFunction) { - afterEachFunction.typeName = 'afterEach'; - this.after_.unshift(afterEachFunction); -}; - -jasmine.Suite.prototype.results = function() { - return this.queue.results(); -}; - -jasmine.Suite.prototype.add = function(suiteOrSpec) { - this.children_.push(suiteOrSpec); - if (suiteOrSpec instanceof jasmine.Suite) { - this.suites_.push(suiteOrSpec); - this.env.currentRunner().addSuite(suiteOrSpec); - } else { - this.specs_.push(suiteOrSpec); - } - this.queue.add(suiteOrSpec); -}; - -jasmine.Suite.prototype.specs = function() { - return this.specs_; -}; - -jasmine.Suite.prototype.suites = function() { - return this.suites_; -}; - -jasmine.Suite.prototype.children = function() { - return this.children_; -}; - -jasmine.Suite.prototype.execute = function(onComplete) { - var self = this; - this.queue.start(function () { - self.finish(onComplete); - }); -}; -jasmine.WaitsBlock = function(env, timeout, spec) { - this.timeout = timeout; - jasmine.Block.call(this, env, null, spec); -}; - -jasmine.util.inherit(jasmine.WaitsBlock, jasmine.Block); - -jasmine.WaitsBlock.prototype.execute = function (onComplete) { - if (jasmine.VERBOSE) { - this.env.reporter.log('>> Jasmine waiting for ' + this.timeout + ' ms...'); - } - this.env.setTimeout(function () { - onComplete(); - }, this.timeout); -}; -/** - * A block which waits for some condition to become true, with timeout. - * - * @constructor - * @extends jasmine.Block - * @param {jasmine.Env} env The Jasmine environment. - * @param {Number} timeout The maximum time in milliseconds to wait for the condition to become true. - * @param {Function} latchFunction A function which returns true when the desired condition has been met. - * @param {String} message The message to display if the desired condition hasn't been met within the given time period. - * @param {jasmine.Spec} spec The Jasmine spec. - */ -jasmine.WaitsForBlock = function(env, timeout, latchFunction, message, spec) { - this.timeout = timeout || env.defaultTimeoutInterval; - this.latchFunction = latchFunction; - this.message = message; - this.totalTimeSpentWaitingForLatch = 0; - jasmine.Block.call(this, env, null, spec); -}; -jasmine.util.inherit(jasmine.WaitsForBlock, jasmine.Block); - -jasmine.WaitsForBlock.TIMEOUT_INCREMENT = 10; - -jasmine.WaitsForBlock.prototype.execute = function(onComplete) { - if (jasmine.VERBOSE) { - this.env.reporter.log('>> Jasmine waiting for ' + (this.message || 'something to happen')); - } - var latchFunctionResult; - try { - latchFunctionResult = this.latchFunction.apply(this.spec); - } catch (e) { - this.spec.fail(e); - onComplete(); - return; - } - - if (latchFunctionResult) { - onComplete(); - } else if (this.totalTimeSpentWaitingForLatch >= this.timeout) { - var message = 'timed out after ' + this.timeout + ' msec waiting for ' + (this.message || 'something to happen'); - this.spec.fail({ - name: 'timeout', - message: message - }); - - this.abort = true; - onComplete(); - } else { - this.totalTimeSpentWaitingForLatch += jasmine.WaitsForBlock.TIMEOUT_INCREMENT; - var self = this; - this.env.setTimeout(function() { - self.execute(onComplete); - }, jasmine.WaitsForBlock.TIMEOUT_INCREMENT); - } -}; -// Mock setTimeout, clearTimeout -// Contributed by Pivotal Computer Systems, www.pivotalsf.com - -jasmine.FakeTimer = function() { - this.reset(); - - var self = this; - self.setTimeout = function(funcToCall, millis) { - self.timeoutsMade++; - self.scheduleFunction(self.timeoutsMade, funcToCall, millis, false); - return self.timeoutsMade; - }; - - self.setInterval = function(funcToCall, millis) { - self.timeoutsMade++; - self.scheduleFunction(self.timeoutsMade, funcToCall, millis, true); - return self.timeoutsMade; - }; - - self.clearTimeout = function(timeoutKey) { - self.scheduledFunctions[timeoutKey] = jasmine.undefined; - }; - - self.clearInterval = function(timeoutKey) { - self.scheduledFunctions[timeoutKey] = jasmine.undefined; - }; - -}; - -jasmine.FakeTimer.prototype.reset = function() { - this.timeoutsMade = 0; - this.scheduledFunctions = {}; - this.nowMillis = 0; -}; - -jasmine.FakeTimer.prototype.tick = function(millis) { - var oldMillis = this.nowMillis; - var newMillis = oldMillis + millis; - this.runFunctionsWithinRange(oldMillis, newMillis); - this.nowMillis = newMillis; -}; - -jasmine.FakeTimer.prototype.runFunctionsWithinRange = function(oldMillis, nowMillis) { - var scheduledFunc; - var funcsToRun = []; - for (var timeoutKey in this.scheduledFunctions) { - scheduledFunc = this.scheduledFunctions[timeoutKey]; - if (scheduledFunc != jasmine.undefined && - scheduledFunc.runAtMillis >= oldMillis && - scheduledFunc.runAtMillis <= nowMillis) { - funcsToRun.push(scheduledFunc); - this.scheduledFunctions[timeoutKey] = jasmine.undefined; - } - } - - if (funcsToRun.length > 0) { - funcsToRun.sort(function(a, b) { - return a.runAtMillis - b.runAtMillis; - }); - for (var i = 0; i < funcsToRun.length; ++i) { - try { - var funcToRun = funcsToRun[i]; - this.nowMillis = funcToRun.runAtMillis; - funcToRun.funcToCall(); - if (funcToRun.recurring) { - this.scheduleFunction(funcToRun.timeoutKey, - funcToRun.funcToCall, - funcToRun.millis, - true); - } - } catch(e) { - } - } - this.runFunctionsWithinRange(oldMillis, nowMillis); - } -}; - -jasmine.FakeTimer.prototype.scheduleFunction = function(timeoutKey, funcToCall, millis, recurring) { - this.scheduledFunctions[timeoutKey] = { - runAtMillis: this.nowMillis + millis, - funcToCall: funcToCall, - recurring: recurring, - timeoutKey: timeoutKey, - millis: millis - }; -}; - -/** - * @namespace - */ -jasmine.Clock = { - defaultFakeTimer: new jasmine.FakeTimer(), - - reset: function() { - jasmine.Clock.assertInstalled(); - jasmine.Clock.defaultFakeTimer.reset(); - }, - - tick: function(millis) { - jasmine.Clock.assertInstalled(); - jasmine.Clock.defaultFakeTimer.tick(millis); - }, - - runFunctionsWithinRange: function(oldMillis, nowMillis) { - jasmine.Clock.defaultFakeTimer.runFunctionsWithinRange(oldMillis, nowMillis); - }, - - scheduleFunction: function(timeoutKey, funcToCall, millis, recurring) { - jasmine.Clock.defaultFakeTimer.scheduleFunction(timeoutKey, funcToCall, millis, recurring); - }, - - useMock: function() { - if (!jasmine.Clock.isInstalled()) { - var spec = jasmine.getEnv().currentSpec; - spec.after(jasmine.Clock.uninstallMock); - - jasmine.Clock.installMock(); - } - }, - - installMock: function() { - jasmine.Clock.installed = jasmine.Clock.defaultFakeTimer; - }, - - uninstallMock: function() { - jasmine.Clock.assertInstalled(); - jasmine.Clock.installed = jasmine.Clock.real; - }, - - real: { - setTimeout: jasmine.getGlobal().setTimeout, - clearTimeout: jasmine.getGlobal().clearTimeout, - setInterval: jasmine.getGlobal().setInterval, - clearInterval: jasmine.getGlobal().clearInterval - }, - - assertInstalled: function() { - if (!jasmine.Clock.isInstalled()) { - throw new Error("Mock clock is not installed, use jasmine.Clock.useMock()"); - } - }, - - isInstalled: function() { - return jasmine.Clock.installed == jasmine.Clock.defaultFakeTimer; - }, - - installed: null -}; -jasmine.Clock.installed = jasmine.Clock.real; - -//else for IE support -jasmine.getGlobal().setTimeout = function(funcToCall, millis) { - if (jasmine.Clock.installed.setTimeout.apply) { - return jasmine.Clock.installed.setTimeout.apply(this, arguments); - } else { - return jasmine.Clock.installed.setTimeout(funcToCall, millis); - } -}; - -jasmine.getGlobal().setInterval = function(funcToCall, millis) { - if (jasmine.Clock.installed.setInterval.apply) { - return jasmine.Clock.installed.setInterval.apply(this, arguments); - } else { - return jasmine.Clock.installed.setInterval(funcToCall, millis); - } -}; - -jasmine.getGlobal().clearTimeout = function(timeoutKey) { - if (jasmine.Clock.installed.clearTimeout.apply) { - return jasmine.Clock.installed.clearTimeout.apply(this, arguments); - } else { - return jasmine.Clock.installed.clearTimeout(timeoutKey); - } -}; - -jasmine.getGlobal().clearInterval = function(timeoutKey) { - if (jasmine.Clock.installed.clearTimeout.apply) { - return jasmine.Clock.installed.clearInterval.apply(this, arguments); - } else { - return jasmine.Clock.installed.clearInterval(timeoutKey); - } -}; - -jasmine.version_= { - "major": 1, - "minor": 1, - "build": 0, - "revision": 1315677058 -}; diff --git a/js/lib/jasmine-1.1.0/jasmine_favicon.png b/js/lib/jasmine-1.1.0/jasmine_favicon.png deleted file mode 100644 index 218f3b43713598fa5a3e78b57aceb909c33f46df..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 905 zcmV;419tq0P)Px#AY({UO#lFTCIA3{ga82g0001h=l}q9FaQARU;qF* zm;eA5aGbhPJOBUy24YJ`L;(K){{a7>y{D4^000SaNLh0L01FcU01FcV0GgZ_0008u zNkl3{fod28|PjmA)7fYg4w8-(2my9xtBGOs}K`n&t1VzxMO^X)M zrW+Ln1udc?q6TP)z5gAjt)P&D!M$+HJK#x<`xnD030zwD?KrxxY!2tlA zGc-58?0D7SsT)7Km=v+tNVNUk`?s@;^OxCF)y6P}_mL;~7;S<@b|MzmKq)m8l@yky zT1~ECpxZw@64!nkI34QLiUsA%i%N>-$&zGYR7WJyi9ERMyS(%kf z7A_r)X>!90&m(FwDQZ>q;+nOa*KR2+E6Fz)QwU=W1Oyo*4>_qlm|~joa|{4_A_3W8 z#FFZzRp-xMIx5a7D_Fj3&#r^TbIY@cND1d0f*^qDIs{!pw!IWGQ_%l4#ASm_D5Vet z0%ek7^)@xPihX_G0&hIc9*14ca=D!8oG}vW?H%~w^F?f_s>zU|fKrNJXJ_d6{v!t( zpEoqMws_yQws>3o?VW8Txq~#->dJG^ELW5irR!s`(_JvD^6;r+ho~eIK@ia8_lH(h zt*-p?CFC1_h2MV=?jP){uW!7WjLjCaO&c1D+tf582!XEaoB#xWAYcN5f$sLtf$koW zQs{{>)ZTq?FC6|J_%n}AWbiFK(Bo-%^-{H`*)E(ucjo-r%SYm)W5f6tN=xz=S646E fNXW#U{x?4WXWJ 0) { - return ajaxRequests[ajaxRequests.length - 1]; - } else { - return null; - } -} - -function clearAjaxRequests() { - ajaxRequests = []; -} - -// Fake XHR for mocking Ajax Requests & Responses -function FakeXMLHttpRequest() { - var extend = Object.extend || $.extend; - extend(this, { - requestHeaders: {}, - - open: function() { - this.method = arguments[0]; - this.url = arguments[1]; - this.readyState = 1; - }, - - setRequestHeader: function(header, value) { - this.requestHeaders[header] = value; - }, - - abort: function() { - this.readyState = 0; - }, - - readyState: 0, - - onreadystatechange: function(isTimeout) { - }, - - status: null, - - send: function(data) { - this.params = data; - this.readyState = 2; - }, - - getResponseHeader: function(name) { - return this.responseHeaders[name]; - }, - - getAllResponseHeaders: function() { - var responseHeaders = []; - for (var i in this.responseHeaders) { - if (this.responseHeaders.hasOwnProperty(i)) { - responseHeaders.push(i + ': ' + this.responseHeaders[i]); - } - } - return responseHeaders.join('\r\n'); - }, - - responseText: null, - - response: function(response) { - this.status = response.status; - this.responseText = response.responseText || ""; - this.readyState = 4; - this.responseHeaders = response.responseHeaders || - {"Content-type": response.contentType || "application/json" }; - // uncomment for jquery 1.3.x support - // jasmine.Clock.tick(20); - - this.onreadystatechange(); - }, - responseTimeout: function() { - this.readyState = 4; - jasmine.Clock.tick(jQuery.ajaxSettings.timeout || 30000); - this.onreadystatechange('timeout'); - } - }); - - return this; -} - - -jasmine.Ajax = { - - isInstalled: function() { - return jasmine.Ajax.installed == true; - }, - - assertInstalled: function() { - if (!jasmine.Ajax.isInstalled()) { - throw new Error("Mock ajax is not installed, use jasmine.Ajax.useMock()") - } - }, - - useMock: function() { - if (!jasmine.Ajax.isInstalled()) { - var spec = jasmine.getEnv().currentSpec; - spec.after(jasmine.Ajax.uninstallMock); - - jasmine.Ajax.installMock(); - } - }, - - installMock: function() { - if (typeof jQuery != 'undefined') { - jasmine.Ajax.installJquery(); - } else if (typeof Prototype != 'undefined') { - jasmine.Ajax.installPrototype(); - } else { - throw new Error("jasmine.Ajax currently only supports jQuery and Prototype"); - } - jasmine.Ajax.installed = true; - }, - - installJquery: function() { - jasmine.Ajax.mode = 'jQuery'; - jasmine.Ajax.real = jQuery.ajaxSettings.xhr; - jQuery.ajaxSettings.xhr = jasmine.Ajax.jQueryMock; - - }, - - installPrototype: function() { - jasmine.Ajax.mode = 'Prototype'; - jasmine.Ajax.real = Ajax.getTransport; - - Ajax.getTransport = jasmine.Ajax.prototypeMock; - }, - - uninstallMock: function() { - jasmine.Ajax.assertInstalled(); - if (jasmine.Ajax.mode == 'jQuery') { - jQuery.ajaxSettings.xhr = jasmine.Ajax.real; - } else if (jasmine.Ajax.mode == 'Prototype') { - Ajax.getTransport = jasmine.Ajax.real; - } - jasmine.Ajax.reset(); - }, - - reset: function() { - jasmine.Ajax.installed = false; - jasmine.Ajax.mode = null; - jasmine.Ajax.real = null; - }, - - jQueryMock: function() { - var newXhr = new FakeXMLHttpRequest(); - ajaxRequests.push(newXhr); - return newXhr; - }, - - prototypeMock: function() { - return new FakeXMLHttpRequest(); - }, - - installed: false, - mode: null -} - - -// Jasmine-Ajax Glue code for Prototype.js -if (typeof Prototype != 'undefined' && Ajax && Ajax.Request) { - Ajax.Request.prototype.originalRequest = Ajax.Request.prototype.request; - Ajax.Request.prototype.request = function(url) { - this.originalRequest(url); - ajaxRequests.push(this); - }; - - Ajax.Request.prototype.response = function(responseOptions) { - return this.transport.response(responseOptions); - }; -} diff --git a/js/lib/jasmine-jquery-1.3.1/jasmine-jquery-1.3.1.js b/js/lib/jasmine-jquery-1.3.1/jasmine-jquery-1.3.1.js deleted file mode 100644 index 7e85548a..00000000 --- a/js/lib/jasmine-jquery-1.3.1/jasmine-jquery-1.3.1.js +++ /dev/null @@ -1,288 +0,0 @@ -var readFixtures = function() { - return jasmine.getFixtures().proxyCallTo_('read', arguments); -}; - -var preloadFixtures = function() { - jasmine.getFixtures().proxyCallTo_('preload', arguments); -}; - -var loadFixtures = function() { - jasmine.getFixtures().proxyCallTo_('load', arguments); -}; - -var setFixtures = function(html) { - jasmine.getFixtures().set(html); -}; - -var sandbox = function(attributes) { - return jasmine.getFixtures().sandbox(attributes); -}; - -var spyOnEvent = function(selector, eventName) { - jasmine.JQuery.events.spyOn(selector, eventName); -} - -jasmine.getFixtures = function() { - return jasmine.currentFixtures_ = jasmine.currentFixtures_ || new jasmine.Fixtures(); -}; - -jasmine.Fixtures = function() { - this.containerId = 'jasmine-fixtures'; - this.fixturesCache_ = {}; - this.fixturesPath = 'spec/javascripts/fixtures'; -}; - -jasmine.Fixtures.prototype.set = function(html) { - this.cleanUp(); - this.createContainer_(html); -}; - -jasmine.Fixtures.prototype.preload = function() { - this.read.apply(this, arguments); -}; - -jasmine.Fixtures.prototype.load = function() { - this.cleanUp(); - this.createContainer_(this.read.apply(this, arguments)); -}; - -jasmine.Fixtures.prototype.read = function() { - var htmlChunks = []; - - var fixtureUrls = arguments; - for(var urlCount = fixtureUrls.length, urlIndex = 0; urlIndex < urlCount; urlIndex++) { - htmlChunks.push(this.getFixtureHtml_(fixtureUrls[urlIndex])); - } - - return htmlChunks.join(''); -}; - -jasmine.Fixtures.prototype.clearCache = function() { - this.fixturesCache_ = {}; -}; - -jasmine.Fixtures.prototype.cleanUp = function() { - jQuery('#' + this.containerId).remove(); -}; - -jasmine.Fixtures.prototype.sandbox = function(attributes) { - var attributesToSet = attributes || {}; - return jQuery('
').attr(attributesToSet); -}; - -jasmine.Fixtures.prototype.createContainer_ = function(html) { - var container; - if(html instanceof jQuery) { - container = jQuery('
'); - container.html(html); - } else { - container = '
' + html + '
' - } - jQuery('body').append(container); -}; - -jasmine.Fixtures.prototype.getFixtureHtml_ = function(url) { - if (typeof this.fixturesCache_[url] == 'undefined') { - this.loadFixtureIntoCache_(url); - } - return this.fixturesCache_[url]; -}; - -jasmine.Fixtures.prototype.loadFixtureIntoCache_ = function(relativeUrl) { - var self = this; - var url = this.fixturesPath.match('/$') ? this.fixturesPath + relativeUrl : this.fixturesPath + '/' + relativeUrl; - jQuery.ajax({ - async: false, // must be synchronous to guarantee that no tests are run before fixture is loaded - cache: false, - dataType: 'html', - url: url, - success: function(data) { - self.fixturesCache_[relativeUrl] = data; - }, - error: function(jqXHR, status, errorThrown) { - throw Error('Fixture could not be loaded: ' + url + ' (status: ' + status + ', message: ' + errorThrown.message + ')'); - } - }); -}; - -jasmine.Fixtures.prototype.proxyCallTo_ = function(methodName, passedArguments) { - return this[methodName].apply(this, passedArguments); -}; - - -jasmine.JQuery = function() {}; - -jasmine.JQuery.browserTagCaseIndependentHtml = function(html) { - return jQuery('
').append(html).html(); -}; - -jasmine.JQuery.elementToString = function(element) { - return jQuery('
').append(element.clone()).html(); -}; - -jasmine.JQuery.matchersClass = {}; - -(function(namespace) { - var data = { - spiedEvents: {}, - handlers: [] - }; - - namespace.events = { - spyOn: function(selector, eventName) { - var handler = function(e) { - data.spiedEvents[[selector, eventName]] = e; - }; - jQuery(selector).bind(eventName, handler); - data.handlers.push(handler); - }, - - wasTriggered: function(selector, eventName) { - return !!(data.spiedEvents[[selector, eventName]]); - }, - - cleanUp: function() { - data.spiedEvents = {}; - data.handlers = []; - } - } -})(jasmine.JQuery); - -(function(){ - var jQueryMatchers = { - toHaveClass: function(className) { - return this.actual.hasClass(className); - }, - - toBeVisible: function() { - return this.actual.is(':visible'); - }, - - toBeHidden: function() { - return this.actual.is(':hidden'); - }, - - toBeSelected: function() { - return this.actual.is(':selected'); - }, - - toBeChecked: function() { - return this.actual.is(':checked'); - }, - - toBeEmpty: function() { - return this.actual.is(':empty'); - }, - - toExist: function() { - return this.actual.size() > 0; - }, - - toHaveAttr: function(attributeName, expectedAttributeValue) { - return hasProperty(this.actual.attr(attributeName), expectedAttributeValue); - }, - - toHaveId: function(id) { - return this.actual.attr('id') == id; - }, - - toHaveHtml: function(html) { - return this.actual.html() == jasmine.JQuery.browserTagCaseIndependentHtml(html); - }, - - toHaveText: function(text) { - if (text && jQuery.isFunction(text.test)) { - return text.test(this.actual.text()); - } else { - return this.actual.text() == text; - } - }, - - toHaveValue: function(value) { - return this.actual.val() == value; - }, - - toHaveData: function(key, expectedValue) { - return hasProperty(this.actual.data(key), expectedValue); - }, - - toBe: function(selector) { - return this.actual.is(selector); - }, - - toContain: function(selector) { - return this.actual.find(selector).size() > 0; - }, - - toBeDisabled: function(selector){ - return this.actual.is(':disabled'); - }, - - // tests the existence of a specific event binding - toHandle: function(eventName) { - var events = this.actual.data("events"); - return events && events[eventName].length > 0; - }, - - // tests the existence of a specific event binding + handler - toHandleWith: function(eventName, eventHandler) { - var stack = this.actual.data("events")[eventName]; - var i; - for (i = 0; i < stack.length; i++) { - if (stack[i].handler == eventHandler) { - return true; - } - } - return false; - } - }; - - var hasProperty = function(actualValue, expectedValue) { - if (expectedValue === undefined) { - return actualValue !== undefined; - } - return actualValue == expectedValue; - }; - - var bindMatcher = function(methodName) { - var builtInMatcher = jasmine.Matchers.prototype[methodName]; - - jasmine.JQuery.matchersClass[methodName] = function() { - if (this.actual instanceof jQuery) { - var result = jQueryMatchers[methodName].apply(this, arguments); - this.actual = jasmine.JQuery.elementToString(this.actual); - return result; - } - - if (builtInMatcher) { - return builtInMatcher.apply(this, arguments); - } - - return false; - }; - }; - - for(var methodName in jQueryMatchers) { - bindMatcher(methodName); - } -})(); - -beforeEach(function() { - this.addMatchers(jasmine.JQuery.matchersClass); - this.addMatchers({ - toHaveBeenTriggeredOn: function(selector) { - this.message = function() { - return [ - "Expected event " + this.actual + " to have been triggered on" + selector, - "Expected event " + this.actual + " not to have been triggered on" + selector - ]; - }; - return jasmine.JQuery.events.wasTriggered(selector, this.actual); - } - }) -}); - -afterEach(function() { - jasmine.getFixtures().cleanUp(); - jasmine.JQuery.events.cleanUp(); -}); diff --git a/js/lib/jquery-1.7.1/jquery-1.7.1.js b/js/lib/jquery-1.7.1/jquery-1.7.1.js deleted file mode 100644 index 8ccd0ea7..00000000 --- a/js/lib/jquery-1.7.1/jquery-1.7.1.js +++ /dev/null @@ -1,9266 +0,0 @@ -/*! - * jQuery JavaScript Library v1.7.1 - * http://jquery.com/ - * - * Copyright 2011, John Resig - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * Includes Sizzle.js - * http://sizzlejs.com/ - * Copyright 2011, The Dojo Foundation - * Released under the MIT, BSD, and GPL Licenses. - * - * Date: Mon Nov 21 21:11:03 2011 -0500 - */ -(function( window, undefined ) { - -// Use the correct document accordingly with window argument (sandbox) -var document = window.document, - navigator = window.navigator, - location = window.location; -var jQuery = (function() { - -// Define a local copy of jQuery -var jQuery = function( selector, context ) { - // The jQuery object is actually just the init constructor 'enhanced' - return new jQuery.fn.init( selector, context, rootjQuery ); - }, - - // Map over jQuery in case of overwrite - _jQuery = window.jQuery, - - // Map over the $ in case of overwrite - _$ = window.$, - - // A central reference to the root jQuery(document) - rootjQuery, - - // A simple way to check for HTML strings or ID strings - // Prioritize #id over to avoid XSS via location.hash (#9521) - quickExpr = /^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/, - - // Check if a string has a non-whitespace character in it - rnotwhite = /\S/, - - // Used for trimming whitespace - trimLeft = /^\s+/, - trimRight = /\s+$/, - - // Match a standalone tag - rsingleTag = /^<(\w+)\s*\/?>(?:<\/\1>)?$/, - - // JSON RegExp - rvalidchars = /^[\],:{}\s]*$/, - rvalidescape = /\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, - rvalidtokens = /"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, - rvalidbraces = /(?:^|:|,)(?:\s*\[)+/g, - - // Useragent RegExp - rwebkit = /(webkit)[ \/]([\w.]+)/, - ropera = /(opera)(?:.*version)?[ \/]([\w.]+)/, - rmsie = /(msie) ([\w.]+)/, - rmozilla = /(mozilla)(?:.*? rv:([\w.]+))?/, - - // Matches dashed string for camelizing - rdashAlpha = /-([a-z]|[0-9])/ig, - rmsPrefix = /^-ms-/, - - // Used by jQuery.camelCase as callback to replace() - fcamelCase = function( all, letter ) { - return ( letter + "" ).toUpperCase(); - }, - - // Keep a UserAgent string for use with jQuery.browser - userAgent = navigator.userAgent, - - // For matching the engine and version of the browser - browserMatch, - - // The deferred used on DOM ready - readyList, - - // The ready event handler - DOMContentLoaded, - - // Save a reference to some core methods - toString = Object.prototype.toString, - hasOwn = Object.prototype.hasOwnProperty, - push = Array.prototype.push, - slice = Array.prototype.slice, - trim = String.prototype.trim, - indexOf = Array.prototype.indexOf, - - // [[Class]] -> type pairs - class2type = {}; - -jQuery.fn = jQuery.prototype = { - constructor: jQuery, - init: function( selector, context, rootjQuery ) { - var match, elem, ret, doc; - - // Handle $(""), $(null), or $(undefined) - if ( !selector ) { - return this; - } - - // Handle $(DOMElement) - if ( selector.nodeType ) { - this.context = this[0] = selector; - this.length = 1; - return this; - } - - // The body element only exists once, optimize finding it - if ( selector === "body" && !context && document.body ) { - this.context = document; - this[0] = document.body; - this.selector = selector; - this.length = 1; - return this; - } - - // Handle HTML strings - if ( typeof selector === "string" ) { - // Are we dealing with HTML string or an ID? - if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) { - // Assume that strings that start and end with <> are HTML and skip the regex check - match = [ null, selector, null ]; - - } else { - match = quickExpr.exec( selector ); - } - - // Verify a match, and that no context was specified for #id - if ( match && (match[1] || !context) ) { - - // HANDLE: $(html) -> $(array) - if ( match[1] ) { - context = context instanceof jQuery ? context[0] : context; - doc = ( context ? context.ownerDocument || context : document ); - - // If a single string is passed in and it's a single tag - // just do a createElement and skip the rest - ret = rsingleTag.exec( selector ); - - if ( ret ) { - if ( jQuery.isPlainObject( context ) ) { - selector = [ document.createElement( ret[1] ) ]; - jQuery.fn.attr.call( selector, context, true ); - - } else { - selector = [ doc.createElement( ret[1] ) ]; - } - - } else { - ret = jQuery.buildFragment( [ match[1] ], [ doc ] ); - selector = ( ret.cacheable ? jQuery.clone(ret.fragment) : ret.fragment ).childNodes; - } - - return jQuery.merge( this, selector ); - - // HANDLE: $("#id") - } else { - elem = document.getElementById( match[2] ); - - // Check parentNode to catch when Blackberry 4.6 returns - // nodes that are no longer in the document #6963 - if ( elem && elem.parentNode ) { - // Handle the case where IE and Opera return items - // by name instead of ID - if ( elem.id !== match[2] ) { - return rootjQuery.find( selector ); - } - - // Otherwise, we inject the element directly into the jQuery object - this.length = 1; - this[0] = elem; - } - - this.context = document; - this.selector = selector; - return this; - } - - // HANDLE: $(expr, $(...)) - } else if ( !context || context.jquery ) { - return ( context || rootjQuery ).find( selector ); - - // HANDLE: $(expr, context) - // (which is just equivalent to: $(context).find(expr) - } else { - return this.constructor( context ).find( selector ); - } - - // HANDLE: $(function) - // Shortcut for document ready - } else if ( jQuery.isFunction( selector ) ) { - return rootjQuery.ready( selector ); - } - - if ( selector.selector !== undefined ) { - this.selector = selector.selector; - this.context = selector.context; - } - - return jQuery.makeArray( selector, this ); - }, - - // Start with an empty selector - selector: "", - - // The current version of jQuery being used - jquery: "1.7.1", - - // The default length of a jQuery object is 0 - length: 0, - - // The number of elements contained in the matched element set - size: function() { - return this.length; - }, - - toArray: function() { - return slice.call( this, 0 ); - }, - - // Get the Nth element in the matched element set OR - // Get the whole matched element set as a clean array - get: function( num ) { - return num == null ? - - // Return a 'clean' array - this.toArray() : - - // Return just the object - ( num < 0 ? this[ this.length + num ] : this[ num ] ); - }, - - // Take an array of elements and push it onto the stack - // (returning the new matched element set) - pushStack: function( elems, name, selector ) { - // Build a new jQuery matched element set - var ret = this.constructor(); - - if ( jQuery.isArray( elems ) ) { - push.apply( ret, elems ); - - } else { - jQuery.merge( ret, elems ); - } - - // Add the old object onto the stack (as a reference) - ret.prevObject = this; - - ret.context = this.context; - - if ( name === "find" ) { - ret.selector = this.selector + ( this.selector ? " " : "" ) + selector; - } else if ( name ) { - ret.selector = this.selector + "." + name + "(" + selector + ")"; - } - - // Return the newly-formed element set - return ret; - }, - - // Execute a callback for every element in the matched set. - // (You can seed the arguments with an array of args, but this is - // only used internally.) - each: function( callback, args ) { - return jQuery.each( this, callback, args ); - }, - - ready: function( fn ) { - // Attach the listeners - jQuery.bindReady(); - - // Add the callback - readyList.add( fn ); - - return this; - }, - - eq: function( i ) { - i = +i; - return i === -1 ? - this.slice( i ) : - this.slice( i, i + 1 ); - }, - - first: function() { - return this.eq( 0 ); - }, - - last: function() { - return this.eq( -1 ); - }, - - slice: function() { - return this.pushStack( slice.apply( this, arguments ), - "slice", slice.call(arguments).join(",") ); - }, - - map: function( callback ) { - return this.pushStack( jQuery.map(this, function( elem, i ) { - return callback.call( elem, i, elem ); - })); - }, - - end: function() { - return this.prevObject || this.constructor(null); - }, - - // For internal use only. - // Behaves like an Array's method, not like a jQuery method. - push: push, - sort: [].sort, - splice: [].splice -}; - -// Give the init function the jQuery prototype for later instantiation -jQuery.fn.init.prototype = jQuery.fn; - -jQuery.extend = jQuery.fn.extend = function() { - var options, name, src, copy, copyIsArray, clone, - target = arguments[0] || {}, - i = 1, - length = arguments.length, - deep = false; - - // Handle a deep copy situation - if ( typeof target === "boolean" ) { - deep = target; - target = arguments[1] || {}; - // skip the boolean and the target - i = 2; - } - - // Handle case when target is a string or something (possible in deep copy) - if ( typeof target !== "object" && !jQuery.isFunction(target) ) { - target = {}; - } - - // extend jQuery itself if only one argument is passed - if ( length === i ) { - target = this; - --i; - } - - for ( ; i < length; i++ ) { - // Only deal with non-null/undefined values - if ( (options = arguments[ i ]) != null ) { - // Extend the base object - for ( name in options ) { - src = target[ name ]; - copy = options[ name ]; - - // Prevent never-ending loop - if ( target === copy ) { - continue; - } - - // Recurse if we're merging plain objects or arrays - if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) { - if ( copyIsArray ) { - copyIsArray = false; - clone = src && jQuery.isArray(src) ? src : []; - - } else { - clone = src && jQuery.isPlainObject(src) ? src : {}; - } - - // Never move original objects, clone them - target[ name ] = jQuery.extend( deep, clone, copy ); - - // Don't bring in undefined values - } else if ( copy !== undefined ) { - target[ name ] = copy; - } - } - } - } - - // Return the modified object - return target; -}; - -jQuery.extend({ - noConflict: function( deep ) { - if ( window.$ === jQuery ) { - window.$ = _$; - } - - if ( deep && window.jQuery === jQuery ) { - window.jQuery = _jQuery; - } - - return jQuery; - }, - - // Is the DOM ready to be used? Set to true once it occurs. - isReady: false, - - // A counter to track how many items to wait for before - // the ready event fires. See #6781 - readyWait: 1, - - // Hold (or release) the ready event - holdReady: function( hold ) { - if ( hold ) { - jQuery.readyWait++; - } else { - jQuery.ready( true ); - } - }, - - // Handle when the DOM is ready - ready: function( wait ) { - // Either a released hold or an DOMready/load event and not yet ready - if ( (wait === true && !--jQuery.readyWait) || (wait !== true && !jQuery.isReady) ) { - // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443). - if ( !document.body ) { - return setTimeout( jQuery.ready, 1 ); - } - - // Remember that the DOM is ready - jQuery.isReady = true; - - // If a normal DOM Ready event fired, decrement, and wait if need be - if ( wait !== true && --jQuery.readyWait > 0 ) { - return; - } - - // If there are functions bound, to execute - readyList.fireWith( document, [ jQuery ] ); - - // Trigger any bound ready events - if ( jQuery.fn.trigger ) { - jQuery( document ).trigger( "ready" ).off( "ready" ); - } - } - }, - - bindReady: function() { - if ( readyList ) { - return; - } - - readyList = jQuery.Callbacks( "once memory" ); - - // Catch cases where $(document).ready() is called after the - // browser event has already occurred. - if ( document.readyState === "complete" ) { - // Handle it asynchronously to allow scripts the opportunity to delay ready - return setTimeout( jQuery.ready, 1 ); - } - - // Mozilla, Opera and webkit nightlies currently support this event - if ( document.addEventListener ) { - // Use the handy event callback - document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false ); - - // A fallback to window.onload, that will always work - window.addEventListener( "load", jQuery.ready, false ); - - // If IE event model is used - } else if ( document.attachEvent ) { - // ensure firing before onload, - // maybe late but safe also for iframes - document.attachEvent( "onreadystatechange", DOMContentLoaded ); - - // A fallback to window.onload, that will always work - window.attachEvent( "onload", jQuery.ready ); - - // If IE and not a frame - // continually check to see if the document is ready - var toplevel = false; - - try { - toplevel = window.frameElement == null; - } catch(e) {} - - if ( document.documentElement.doScroll && toplevel ) { - doScrollCheck(); - } - } - }, - - // See test/unit/core.js for details concerning isFunction. - // Since version 1.3, DOM methods and functions like alert - // aren't supported. They return false on IE (#2968). - isFunction: function( obj ) { - return jQuery.type(obj) === "function"; - }, - - isArray: Array.isArray || function( obj ) { - return jQuery.type(obj) === "array"; - }, - - // A crude way of determining if an object is a window - isWindow: function( obj ) { - return obj && typeof obj === "object" && "setInterval" in obj; - }, - - isNumeric: function( obj ) { - return !isNaN( parseFloat(obj) ) && isFinite( obj ); - }, - - type: function( obj ) { - return obj == null ? - String( obj ) : - class2type[ toString.call(obj) ] || "object"; - }, - - isPlainObject: function( obj ) { - // Must be an Object. - // Because of IE, we also have to check the presence of the constructor property. - // Make sure that DOM nodes and window objects don't pass through, as well - if ( !obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) { - return false; - } - - try { - // Not own constructor property must be Object - if ( obj.constructor && - !hasOwn.call(obj, "constructor") && - !hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) { - return false; - } - } catch ( e ) { - // IE8,9 Will throw exceptions on certain host objects #9897 - return false; - } - - // Own properties are enumerated firstly, so to speed up, - // if last one is own, then all properties are own. - - var key; - for ( key in obj ) {} - - return key === undefined || hasOwn.call( obj, key ); - }, - - isEmptyObject: function( obj ) { - for ( var name in obj ) { - return false; - } - return true; - }, - - error: function( msg ) { - throw new Error( msg ); - }, - - parseJSON: function( data ) { - if ( typeof data !== "string" || !data ) { - return null; - } - - // Make sure leading/trailing whitespace is removed (IE can't handle it) - data = jQuery.trim( data ); - - // Attempt to parse using the native JSON parser first - if ( window.JSON && window.JSON.parse ) { - return window.JSON.parse( data ); - } - - // Make sure the incoming data is actual JSON - // Logic borrowed from http://json.org/json2.js - if ( rvalidchars.test( data.replace( rvalidescape, "@" ) - .replace( rvalidtokens, "]" ) - .replace( rvalidbraces, "")) ) { - - return ( new Function( "return " + data ) )(); - - } - jQuery.error( "Invalid JSON: " + data ); - }, - - // Cross-browser xml parsing - parseXML: function( data ) { - var xml, tmp; - try { - if ( window.DOMParser ) { // Standard - tmp = new DOMParser(); - xml = tmp.parseFromString( data , "text/xml" ); - } else { // IE - xml = new ActiveXObject( "Microsoft.XMLDOM" ); - xml.async = "false"; - xml.loadXML( data ); - } - } catch( e ) { - xml = undefined; - } - if ( !xml || !xml.documentElement || xml.getElementsByTagName( "parsererror" ).length ) { - jQuery.error( "Invalid XML: " + data ); - } - return xml; - }, - - noop: function() {}, - - // Evaluates a script in a global context - // Workarounds based on findings by Jim Driscoll - // http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context - globalEval: function( data ) { - if ( data && rnotwhite.test( data ) ) { - // We use execScript on Internet Explorer - // We use an anonymous function so that context is window - // rather than jQuery in Firefox - ( window.execScript || function( data ) { - window[ "eval" ].call( window, data ); - } )( data ); - } - }, - - // Convert dashed to camelCase; used by the css and data modules - // Microsoft forgot to hump their vendor prefix (#9572) - camelCase: function( string ) { - return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase ); - }, - - nodeName: function( elem, name ) { - return elem.nodeName && elem.nodeName.toUpperCase() === name.toUpperCase(); - }, - - // args is for internal usage only - each: function( object, callback, args ) { - var name, i = 0, - length = object.length, - isObj = length === undefined || jQuery.isFunction( object ); - - if ( args ) { - if ( isObj ) { - for ( name in object ) { - if ( callback.apply( object[ name ], args ) === false ) { - break; - } - } - } else { - for ( ; i < length; ) { - if ( callback.apply( object[ i++ ], args ) === false ) { - break; - } - } - } - - // A special, fast, case for the most common use of each - } else { - if ( isObj ) { - for ( name in object ) { - if ( callback.call( object[ name ], name, object[ name ] ) === false ) { - break; - } - } - } else { - for ( ; i < length; ) { - if ( callback.call( object[ i ], i, object[ i++ ] ) === false ) { - break; - } - } - } - } - - return object; - }, - - // Use native String.trim function wherever possible - trim: trim ? - function( text ) { - return text == null ? - "" : - trim.call( text ); - } : - - // Otherwise use our own trimming functionality - function( text ) { - return text == null ? - "" : - text.toString().replace( trimLeft, "" ).replace( trimRight, "" ); - }, - - // results is for internal usage only - makeArray: function( array, results ) { - var ret = results || []; - - if ( array != null ) { - // The window, strings (and functions) also have 'length' - // Tweaked logic slightly to handle Blackberry 4.7 RegExp issues #6930 - var type = jQuery.type( array ); - - if ( array.length == null || type === "string" || type === "function" || type === "regexp" || jQuery.isWindow( array ) ) { - push.call( ret, array ); - } else { - jQuery.merge( ret, array ); - } - } - - return ret; - }, - - inArray: function( elem, array, i ) { - var len; - - if ( array ) { - if ( indexOf ) { - return indexOf.call( array, elem, i ); - } - - len = array.length; - i = i ? i < 0 ? Math.max( 0, len + i ) : i : 0; - - for ( ; i < len; i++ ) { - // Skip accessing in sparse arrays - if ( i in array && array[ i ] === elem ) { - return i; - } - } - } - - return -1; - }, - - merge: function( first, second ) { - var i = first.length, - j = 0; - - if ( typeof second.length === "number" ) { - for ( var l = second.length; j < l; j++ ) { - first[ i++ ] = second[ j ]; - } - - } else { - while ( second[j] !== undefined ) { - first[ i++ ] = second[ j++ ]; - } - } - - first.length = i; - - return first; - }, - - grep: function( elems, callback, inv ) { - var ret = [], retVal; - inv = !!inv; - - // Go through the array, only saving the items - // that pass the validator function - for ( var i = 0, length = elems.length; i < length; i++ ) { - retVal = !!callback( elems[ i ], i ); - if ( inv !== retVal ) { - ret.push( elems[ i ] ); - } - } - - return ret; - }, - - // arg is for internal usage only - map: function( elems, callback, arg ) { - var value, key, ret = [], - i = 0, - length = elems.length, - // jquery objects are treated as arrays - isArray = elems instanceof jQuery || length !== undefined && typeof length === "number" && ( ( length > 0 && elems[ 0 ] && elems[ length -1 ] ) || length === 0 || jQuery.isArray( elems ) ) ; - - // Go through the array, translating each of the items to their - if ( isArray ) { - for ( ; i < length; i++ ) { - value = callback( elems[ i ], i, arg ); - - if ( value != null ) { - ret[ ret.length ] = value; - } - } - - // Go through every key on the object, - } else { - for ( key in elems ) { - value = callback( elems[ key ], key, arg ); - - if ( value != null ) { - ret[ ret.length ] = value; - } - } - } - - // Flatten any nested arrays - return ret.concat.apply( [], ret ); - }, - - // A global GUID counter for objects - guid: 1, - - // Bind a function to a context, optionally partially applying any - // arguments. - proxy: function( fn, context ) { - if ( typeof context === "string" ) { - var tmp = fn[ context ]; - context = fn; - fn = tmp; - } - - // Quick check to determine if target is callable, in the spec - // this throws a TypeError, but we will just return undefined. - if ( !jQuery.isFunction( fn ) ) { - return undefined; - } - - // Simulated bind - var args = slice.call( arguments, 2 ), - proxy = function() { - return fn.apply( context, args.concat( slice.call( arguments ) ) ); - }; - - // Set the guid of unique handler to the same of original handler, so it can be removed - proxy.guid = fn.guid = fn.guid || proxy.guid || jQuery.guid++; - - return proxy; - }, - - // Mutifunctional method to get and set values to a collection - // The value/s can optionally be executed if it's a function - access: function( elems, key, value, exec, fn, pass ) { - var length = elems.length; - - // Setting many attributes - if ( typeof key === "object" ) { - for ( var k in key ) { - jQuery.access( elems, k, key[k], exec, fn, value ); - } - return elems; - } - - // Setting one attribute - if ( value !== undefined ) { - // Optionally, function values get executed if exec is true - exec = !pass && exec && jQuery.isFunction(value); - - for ( var i = 0; i < length; i++ ) { - fn( elems[i], key, exec ? value.call( elems[i], i, fn( elems[i], key ) ) : value, pass ); - } - - return elems; - } - - // Getting an attribute - return length ? fn( elems[0], key ) : undefined; - }, - - now: function() { - return ( new Date() ).getTime(); - }, - - // Use of jQuery.browser is frowned upon. - // More details: http://docs.jquery.com/Utilities/jQuery.browser - uaMatch: function( ua ) { - ua = ua.toLowerCase(); - - var match = rwebkit.exec( ua ) || - ropera.exec( ua ) || - rmsie.exec( ua ) || - ua.indexOf("compatible") < 0 && rmozilla.exec( ua ) || - []; - - return { browser: match[1] || "", version: match[2] || "0" }; - }, - - sub: function() { - function jQuerySub( selector, context ) { - return new jQuerySub.fn.init( selector, context ); - } - jQuery.extend( true, jQuerySub, this ); - jQuerySub.superclass = this; - jQuerySub.fn = jQuerySub.prototype = this(); - jQuerySub.fn.constructor = jQuerySub; - jQuerySub.sub = this.sub; - jQuerySub.fn.init = function init( selector, context ) { - if ( context && context instanceof jQuery && !(context instanceof jQuerySub) ) { - context = jQuerySub( context ); - } - - return jQuery.fn.init.call( this, selector, context, rootjQuerySub ); - }; - jQuerySub.fn.init.prototype = jQuerySub.fn; - var rootjQuerySub = jQuerySub(document); - return jQuerySub; - }, - - browser: {} -}); - -// Populate the class2type map -jQuery.each("Boolean Number String Function Array Date RegExp Object".split(" "), function(i, name) { - class2type[ "[object " + name + "]" ] = name.toLowerCase(); -}); - -browserMatch = jQuery.uaMatch( userAgent ); -if ( browserMatch.browser ) { - jQuery.browser[ browserMatch.browser ] = true; - jQuery.browser.version = browserMatch.version; -} - -// Deprecated, use jQuery.browser.webkit instead -if ( jQuery.browser.webkit ) { - jQuery.browser.safari = true; -} - -// IE doesn't match non-breaking spaces with \s -if ( rnotwhite.test( "\xA0" ) ) { - trimLeft = /^[\s\xA0]+/; - trimRight = /[\s\xA0]+$/; -} - -// All jQuery objects should point back to these -rootjQuery = jQuery(document); - -// Cleanup functions for the document ready method -if ( document.addEventListener ) { - DOMContentLoaded = function() { - document.removeEventListener( "DOMContentLoaded", DOMContentLoaded, false ); - jQuery.ready(); - }; - -} else if ( document.attachEvent ) { - DOMContentLoaded = function() { - // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443). - if ( document.readyState === "complete" ) { - document.detachEvent( "onreadystatechange", DOMContentLoaded ); - jQuery.ready(); - } - }; -} - -// The DOM ready check for Internet Explorer -function doScrollCheck() { - if ( jQuery.isReady ) { - return; - } - - try { - // If IE is used, use the trick by Diego Perini - // http://javascript.nwbox.com/IEContentLoaded/ - document.documentElement.doScroll("left"); - } catch(e) { - setTimeout( doScrollCheck, 1 ); - return; - } - - // and execute any waiting functions - jQuery.ready(); -} - -return jQuery; - -})(); - - -// String to Object flags format cache -var flagsCache = {}; - -// Convert String-formatted flags into Object-formatted ones and store in cache -function createFlags( flags ) { - var object = flagsCache[ flags ] = {}, - i, length; - flags = flags.split( /\s+/ ); - for ( i = 0, length = flags.length; i < length; i++ ) { - object[ flags[i] ] = true; - } - return object; -} - -/* - * Create a callback list using the following parameters: - * - * flags: an optional list of space-separated flags that will change how - * the callback list behaves - * - * By default a callback list will act like an event callback list and can be - * "fired" multiple times. - * - * Possible flags: - * - * once: will ensure the callback list can only be fired once (like a Deferred) - * - * memory: will keep track of previous values and will call any callback added - * after the list has been fired right away with the latest "memorized" - * values (like a Deferred) - * - * unique: will ensure a callback can only be added once (no duplicate in the list) - * - * stopOnFalse: interrupt callings when a callback returns false - * - */ -jQuery.Callbacks = function( flags ) { - - // Convert flags from String-formatted to Object-formatted - // (we check in cache first) - flags = flags ? ( flagsCache[ flags ] || createFlags( flags ) ) : {}; - - var // Actual callback list - list = [], - // Stack of fire calls for repeatable lists - stack = [], - // Last fire value (for non-forgettable lists) - memory, - // Flag to know if list is currently firing - firing, - // First callback to fire (used internally by add and fireWith) - firingStart, - // End of the loop when firing - firingLength, - // Index of currently firing callback (modified by remove if needed) - firingIndex, - // Add one or several callbacks to the list - add = function( args ) { - var i, - length, - elem, - type, - actual; - for ( i = 0, length = args.length; i < length; i++ ) { - elem = args[ i ]; - type = jQuery.type( elem ); - if ( type === "array" ) { - // Inspect recursively - add( elem ); - } else if ( type === "function" ) { - // Add if not in unique mode and callback is not in - if ( !flags.unique || !self.has( elem ) ) { - list.push( elem ); - } - } - } - }, - // Fire callbacks - fire = function( context, args ) { - args = args || []; - memory = !flags.memory || [ context, args ]; - firing = true; - firingIndex = firingStart || 0; - firingStart = 0; - firingLength = list.length; - for ( ; list && firingIndex < firingLength; firingIndex++ ) { - if ( list[ firingIndex ].apply( context, args ) === false && flags.stopOnFalse ) { - memory = true; // Mark as halted - break; - } - } - firing = false; - if ( list ) { - if ( !flags.once ) { - if ( stack && stack.length ) { - memory = stack.shift(); - self.fireWith( memory[ 0 ], memory[ 1 ] ); - } - } else if ( memory === true ) { - self.disable(); - } else { - list = []; - } - } - }, - // Actual Callbacks object - self = { - // Add a callback or a collection of callbacks to the list - add: function() { - if ( list ) { - var length = list.length; - add( arguments ); - // Do we need to add the callbacks to the - // current firing batch? - if ( firing ) { - firingLength = list.length; - // With memory, if we're not firing then - // we should call right away, unless previous - // firing was halted (stopOnFalse) - } else if ( memory && memory !== true ) { - firingStart = length; - fire( memory[ 0 ], memory[ 1 ] ); - } - } - return this; - }, - // Remove a callback from the list - remove: function() { - if ( list ) { - var args = arguments, - argIndex = 0, - argLength = args.length; - for ( ; argIndex < argLength ; argIndex++ ) { - for ( var i = 0; i < list.length; i++ ) { - if ( args[ argIndex ] === list[ i ] ) { - // Handle firingIndex and firingLength - if ( firing ) { - if ( i <= firingLength ) { - firingLength--; - if ( i <= firingIndex ) { - firingIndex--; - } - } - } - // Remove the element - list.splice( i--, 1 ); - // If we have some unicity property then - // we only need to do this once - if ( flags.unique ) { - break; - } - } - } - } - } - return this; - }, - // Control if a given callback is in the list - has: function( fn ) { - if ( list ) { - var i = 0, - length = list.length; - for ( ; i < length; i++ ) { - if ( fn === list[ i ] ) { - return true; - } - } - } - return false; - }, - // Remove all callbacks from the list - empty: function() { - list = []; - return this; - }, - // Have the list do nothing anymore - disable: function() { - list = stack = memory = undefined; - return this; - }, - // Is it disabled? - disabled: function() { - return !list; - }, - // Lock the list in its current state - lock: function() { - stack = undefined; - if ( !memory || memory === true ) { - self.disable(); - } - return this; - }, - // Is it locked? - locked: function() { - return !stack; - }, - // Call all callbacks with the given context and arguments - fireWith: function( context, args ) { - if ( stack ) { - if ( firing ) { - if ( !flags.once ) { - stack.push( [ context, args ] ); - } - } else if ( !( flags.once && memory ) ) { - fire( context, args ); - } - } - return this; - }, - // Call all the callbacks with the given arguments - fire: function() { - self.fireWith( this, arguments ); - return this; - }, - // To know if the callbacks have already been called at least once - fired: function() { - return !!memory; - } - }; - - return self; -}; - - - - -var // Static reference to slice - sliceDeferred = [].slice; - -jQuery.extend({ - - Deferred: function( func ) { - var doneList = jQuery.Callbacks( "once memory" ), - failList = jQuery.Callbacks( "once memory" ), - progressList = jQuery.Callbacks( "memory" ), - state = "pending", - lists = { - resolve: doneList, - reject: failList, - notify: progressList - }, - promise = { - done: doneList.add, - fail: failList.add, - progress: progressList.add, - - state: function() { - return state; - }, - - // Deprecated - isResolved: doneList.fired, - isRejected: failList.fired, - - then: function( doneCallbacks, failCallbacks, progressCallbacks ) { - deferred.done( doneCallbacks ).fail( failCallbacks ).progress( progressCallbacks ); - return this; - }, - always: function() { - deferred.done.apply( deferred, arguments ).fail.apply( deferred, arguments ); - return this; - }, - pipe: function( fnDone, fnFail, fnProgress ) { - return jQuery.Deferred(function( newDefer ) { - jQuery.each( { - done: [ fnDone, "resolve" ], - fail: [ fnFail, "reject" ], - progress: [ fnProgress, "notify" ] - }, function( handler, data ) { - var fn = data[ 0 ], - action = data[ 1 ], - returned; - if ( jQuery.isFunction( fn ) ) { - deferred[ handler ](function() { - returned = fn.apply( this, arguments ); - if ( returned && jQuery.isFunction( returned.promise ) ) { - returned.promise().then( newDefer.resolve, newDefer.reject, newDefer.notify ); - } else { - newDefer[ action + "With" ]( this === deferred ? newDefer : this, [ returned ] ); - } - }); - } else { - deferred[ handler ]( newDefer[ action ] ); - } - }); - }).promise(); - }, - // Get a promise for this deferred - // If obj is provided, the promise aspect is added to the object - promise: function( obj ) { - if ( obj == null ) { - obj = promise; - } else { - for ( var key in promise ) { - obj[ key ] = promise[ key ]; - } - } - return obj; - } - }, - deferred = promise.promise({}), - key; - - for ( key in lists ) { - deferred[ key ] = lists[ key ].fire; - deferred[ key + "With" ] = lists[ key ].fireWith; - } - - // Handle state - deferred.done( function() { - state = "resolved"; - }, failList.disable, progressList.lock ).fail( function() { - state = "rejected"; - }, doneList.disable, progressList.lock ); - - // Call given func if any - if ( func ) { - func.call( deferred, deferred ); - } - - // All done! - return deferred; - }, - - // Deferred helper - when: function( firstParam ) { - var args = sliceDeferred.call( arguments, 0 ), - i = 0, - length = args.length, - pValues = new Array( length ), - count = length, - pCount = length, - deferred = length <= 1 && firstParam && jQuery.isFunction( firstParam.promise ) ? - firstParam : - jQuery.Deferred(), - promise = deferred.promise(); - function resolveFunc( i ) { - return function( value ) { - args[ i ] = arguments.length > 1 ? sliceDeferred.call( arguments, 0 ) : value; - if ( !( --count ) ) { - deferred.resolveWith( deferred, args ); - } - }; - } - function progressFunc( i ) { - return function( value ) { - pValues[ i ] = arguments.length > 1 ? sliceDeferred.call( arguments, 0 ) : value; - deferred.notifyWith( promise, pValues ); - }; - } - if ( length > 1 ) { - for ( ; i < length; i++ ) { - if ( args[ i ] && args[ i ].promise && jQuery.isFunction( args[ i ].promise ) ) { - args[ i ].promise().then( resolveFunc(i), deferred.reject, progressFunc(i) ); - } else { - --count; - } - } - if ( !count ) { - deferred.resolveWith( deferred, args ); - } - } else if ( deferred !== firstParam ) { - deferred.resolveWith( deferred, length ? [ firstParam ] : [] ); - } - return promise; - } -}); - - - - -jQuery.support = (function() { - - var support, - all, - a, - select, - opt, - input, - marginDiv, - fragment, - tds, - events, - eventName, - i, - isSupported, - div = document.createElement( "div" ), - documentElement = document.documentElement; - - // Preliminary tests - div.setAttribute("className", "t"); - div.innerHTML = "
a"; - - all = div.getElementsByTagName( "*" ); - a = div.getElementsByTagName( "a" )[ 0 ]; - - // Can't get basic test support - if ( !all || !all.length || !a ) { - return {}; - } - - // First batch of supports tests - select = document.createElement( "select" ); - opt = select.appendChild( document.createElement("option") ); - input = div.getElementsByTagName( "input" )[ 0 ]; - - support = { - // IE strips leading whitespace when .innerHTML is used - leadingWhitespace: ( div.firstChild.nodeType === 3 ), - - // Make sure that tbody elements aren't automatically inserted - // IE will insert them into empty tables - tbody: !div.getElementsByTagName("tbody").length, - - // Make sure that link elements get serialized correctly by innerHTML - // This requires a wrapper element in IE - htmlSerialize: !!div.getElementsByTagName("link").length, - - // Get the style information from getAttribute - // (IE uses .cssText instead) - style: /top/.test( a.getAttribute("style") ), - - // Make sure that URLs aren't manipulated - // (IE normalizes it by default) - hrefNormalized: ( a.getAttribute("href") === "/a" ), - - // Make sure that element opacity exists - // (IE uses filter instead) - // Use a regex to work around a WebKit issue. See #5145 - opacity: /^0.55/.test( a.style.opacity ), - - // Verify style float existence - // (IE uses styleFloat instead of cssFloat) - cssFloat: !!a.style.cssFloat, - - // Make sure that if no value is specified for a checkbox - // that it defaults to "on". - // (WebKit defaults to "" instead) - checkOn: ( input.value === "on" ), - - // Make sure that a selected-by-default option has a working selected property. - // (WebKit defaults to false instead of true, IE too, if it's in an optgroup) - optSelected: opt.selected, - - // Test setAttribute on camelCase class. If it works, we need attrFixes when doing get/setAttribute (ie6/7) - getSetAttribute: div.className !== "t", - - // Tests for enctype support on a form(#6743) - enctype: !!document.createElement("form").enctype, - - // Makes sure cloning an html5 element does not cause problems - // Where outerHTML is undefined, this still works - html5Clone: document.createElement("nav").cloneNode( true ).outerHTML !== "<:nav>", - - // Will be defined later - submitBubbles: true, - changeBubbles: true, - focusinBubbles: false, - deleteExpando: true, - noCloneEvent: true, - inlineBlockNeedsLayout: false, - shrinkWrapBlocks: false, - reliableMarginRight: true - }; - - // Make sure checked status is properly cloned - input.checked = true; - support.noCloneChecked = input.cloneNode( true ).checked; - - // Make sure that the options inside disabled selects aren't marked as disabled - // (WebKit marks them as disabled) - select.disabled = true; - support.optDisabled = !opt.disabled; - - // Test to see if it's possible to delete an expando from an element - // Fails in Internet Explorer - try { - delete div.test; - } catch( e ) { - support.deleteExpando = false; - } - - if ( !div.addEventListener && div.attachEvent && div.fireEvent ) { - div.attachEvent( "onclick", function() { - // Cloning a node shouldn't copy over any - // bound event handlers (IE does this) - support.noCloneEvent = false; - }); - div.cloneNode( true ).fireEvent( "onclick" ); - } - - // Check if a radio maintains its value - // after being appended to the DOM - input = document.createElement("input"); - input.value = "t"; - input.setAttribute("type", "radio"); - support.radioValue = input.value === "t"; - - input.setAttribute("checked", "checked"); - div.appendChild( input ); - fragment = document.createDocumentFragment(); - fragment.appendChild( div.lastChild ); - - // WebKit doesn't clone checked state correctly in fragments - support.checkClone = fragment.cloneNode( true ).cloneNode( true ).lastChild.checked; - - // Check if a disconnected checkbox will retain its checked - // value of true after appended to the DOM (IE6/7) - support.appendChecked = input.checked; - - fragment.removeChild( input ); - fragment.appendChild( div ); - - div.innerHTML = ""; - - // Check if div with explicit width and no margin-right incorrectly - // gets computed margin-right based on width of container. For more - // info see bug #3333 - // Fails in WebKit before Feb 2011 nightlies - // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right - if ( window.getComputedStyle ) { - marginDiv = document.createElement( "div" ); - marginDiv.style.width = "0"; - marginDiv.style.marginRight = "0"; - div.style.width = "2px"; - div.appendChild( marginDiv ); - support.reliableMarginRight = - ( parseInt( ( window.getComputedStyle( marginDiv, null ) || { marginRight: 0 } ).marginRight, 10 ) || 0 ) === 0; - } - - // Technique from Juriy Zaytsev - // http://perfectionkills.com/detecting-event-support-without-browser-sniffing/ - // We only care about the case where non-standard event systems - // are used, namely in IE. Short-circuiting here helps us to - // avoid an eval call (in setAttribute) which can cause CSP - // to go haywire. See: https://developer.mozilla.org/en/Security/CSP - if ( div.attachEvent ) { - for( i in { - submit: 1, - change: 1, - focusin: 1 - }) { - eventName = "on" + i; - isSupported = ( eventName in div ); - if ( !isSupported ) { - div.setAttribute( eventName, "return;" ); - isSupported = ( typeof div[ eventName ] === "function" ); - } - support[ i + "Bubbles" ] = isSupported; - } - } - - fragment.removeChild( div ); - - // Null elements to avoid leaks in IE - fragment = select = opt = marginDiv = div = input = null; - - // Run tests that need a body at doc ready - jQuery(function() { - var container, outer, inner, table, td, offsetSupport, - conMarginTop, ptlm, vb, style, html, - body = document.getElementsByTagName("body")[0]; - - if ( !body ) { - // Return for frameset docs that don't have a body - return; - } - - conMarginTop = 1; - ptlm = "position:absolute;top:0;left:0;width:1px;height:1px;margin:0;"; - vb = "visibility:hidden;border:0;"; - style = "style='" + ptlm + "border:5px solid #000;padding:0;'"; - html = "
" + - "" + - "
"; - - container = document.createElement("div"); - container.style.cssText = vb + "width:0;height:0;position:static;top:0;margin-top:" + conMarginTop + "px"; - body.insertBefore( container, body.firstChild ); - - // Construct the test element - div = document.createElement("div"); - container.appendChild( div ); - - // Check if table cells still have offsetWidth/Height when they are set - // to display:none and there are still other visible table cells in a - // table row; if so, offsetWidth/Height are not reliable for use when - // determining if an element has been hidden directly using - // display:none (it is still safe to use offsets if a parent element is - // hidden; don safety goggles and see bug #4512 for more information). - // (only IE 8 fails this test) - div.innerHTML = "
t
"; - tds = div.getElementsByTagName( "td" ); - isSupported = ( tds[ 0 ].offsetHeight === 0 ); - - tds[ 0 ].style.display = ""; - tds[ 1 ].style.display = "none"; - - // Check if empty table cells still have offsetWidth/Height - // (IE <= 8 fail this test) - support.reliableHiddenOffsets = isSupported && ( tds[ 0 ].offsetHeight === 0 ); - - // Figure out if the W3C box model works as expected - div.innerHTML = ""; - div.style.width = div.style.paddingLeft = "1px"; - jQuery.boxModel = support.boxModel = div.offsetWidth === 2; - - if ( typeof div.style.zoom !== "undefined" ) { - // Check if natively block-level elements act like inline-block - // elements when setting their display to 'inline' and giving - // them layout - // (IE < 8 does this) - div.style.display = "inline"; - div.style.zoom = 1; - support.inlineBlockNeedsLayout = ( div.offsetWidth === 2 ); - - // Check if elements with layout shrink-wrap their children - // (IE 6 does this) - div.style.display = ""; - div.innerHTML = "
"; - support.shrinkWrapBlocks = ( div.offsetWidth !== 2 ); - } - - div.style.cssText = ptlm + vb; - div.innerHTML = html; - - outer = div.firstChild; - inner = outer.firstChild; - td = outer.nextSibling.firstChild.firstChild; - - offsetSupport = { - doesNotAddBorder: ( inner.offsetTop !== 5 ), - doesAddBorderForTableAndCells: ( td.offsetTop === 5 ) - }; - - inner.style.position = "fixed"; - inner.style.top = "20px"; - - // safari subtracts parent border width here which is 5px - offsetSupport.fixedPosition = ( inner.offsetTop === 20 || inner.offsetTop === 15 ); - inner.style.position = inner.style.top = ""; - - outer.style.overflow = "hidden"; - outer.style.position = "relative"; - - offsetSupport.subtractsBorderForOverflowNotVisible = ( inner.offsetTop === -5 ); - offsetSupport.doesNotIncludeMarginInBodyOffset = ( body.offsetTop !== conMarginTop ); - - body.removeChild( container ); - div = container = null; - - jQuery.extend( support, offsetSupport ); - }); - - return support; -})(); - - - - -var rbrace = /^(?:\{.*\}|\[.*\])$/, - rmultiDash = /([A-Z])/g; - -jQuery.extend({ - cache: {}, - - // Please use with caution - uuid: 0, - - // Unique for each copy of jQuery on the page - // Non-digits removed to match rinlinejQuery - expando: "jQuery" + ( jQuery.fn.jquery + Math.random() ).replace( /\D/g, "" ), - - // The following elements throw uncatchable exceptions if you - // attempt to add expando properties to them. - noData: { - "embed": true, - // Ban all objects except for Flash (which handle expandos) - "object": "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000", - "applet": true - }, - - hasData: function( elem ) { - elem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ]; - return !!elem && !isEmptyDataObject( elem ); - }, - - data: function( elem, name, data, pvt /* Internal Use Only */ ) { - if ( !jQuery.acceptData( elem ) ) { - return; - } - - var privateCache, thisCache, ret, - internalKey = jQuery.expando, - getByName = typeof name === "string", - - // We have to handle DOM nodes and JS objects differently because IE6-7 - // can't GC object references properly across the DOM-JS boundary - isNode = elem.nodeType, - - // Only DOM nodes need the global jQuery cache; JS object data is - // attached directly to the object so GC can occur automatically - cache = isNode ? jQuery.cache : elem, - - // Only defining an ID for JS objects if its cache already exists allows - // the code to shortcut on the same path as a DOM node with no cache - id = isNode ? elem[ internalKey ] : elem[ internalKey ] && internalKey, - isEvents = name === "events"; - - // Avoid doing any more work than we need to when trying to get data on an - // object that has no data at all - if ( (!id || !cache[id] || (!isEvents && !pvt && !cache[id].data)) && getByName && data === undefined ) { - return; - } - - if ( !id ) { - // Only DOM nodes need a new unique ID for each element since their data - // ends up in the global cache - if ( isNode ) { - elem[ internalKey ] = id = ++jQuery.uuid; - } else { - id = internalKey; - } - } - - if ( !cache[ id ] ) { - cache[ id ] = {}; - - // Avoids exposing jQuery metadata on plain JS objects when the object - // is serialized using JSON.stringify - if ( !isNode ) { - cache[ id ].toJSON = jQuery.noop; - } - } - - // An object can be passed to jQuery.data instead of a key/value pair; this gets - // shallow copied over onto the existing cache - if ( typeof name === "object" || typeof name === "function" ) { - if ( pvt ) { - cache[ id ] = jQuery.extend( cache[ id ], name ); - } else { - cache[ id ].data = jQuery.extend( cache[ id ].data, name ); - } - } - - privateCache = thisCache = cache[ id ]; - - // jQuery data() is stored in a separate object inside the object's internal data - // cache in order to avoid key collisions between internal data and user-defined - // data. - if ( !pvt ) { - if ( !thisCache.data ) { - thisCache.data = {}; - } - - thisCache = thisCache.data; - } - - if ( data !== undefined ) { - thisCache[ jQuery.camelCase( name ) ] = data; - } - - // Users should not attempt to inspect the internal events object using jQuery.data, - // it is undocumented and subject to change. But does anyone listen? No. - if ( isEvents && !thisCache[ name ] ) { - return privateCache.events; - } - - // Check for both converted-to-camel and non-converted data property names - // If a data property was specified - if ( getByName ) { - - // First Try to find as-is property data - ret = thisCache[ name ]; - - // Test for null|undefined property data - if ( ret == null ) { - - // Try to find the camelCased property - ret = thisCache[ jQuery.camelCase( name ) ]; - } - } else { - ret = thisCache; - } - - return ret; - }, - - removeData: function( elem, name, pvt /* Internal Use Only */ ) { - if ( !jQuery.acceptData( elem ) ) { - return; - } - - var thisCache, i, l, - - // Reference to internal data cache key - internalKey = jQuery.expando, - - isNode = elem.nodeType, - - // See jQuery.data for more information - cache = isNode ? jQuery.cache : elem, - - // See jQuery.data for more information - id = isNode ? elem[ internalKey ] : internalKey; - - // If there is already no cache entry for this object, there is no - // purpose in continuing - if ( !cache[ id ] ) { - return; - } - - if ( name ) { - - thisCache = pvt ? cache[ id ] : cache[ id ].data; - - if ( thisCache ) { - - // Support array or space separated string names for data keys - if ( !jQuery.isArray( name ) ) { - - // try the string as a key before any manipulation - if ( name in thisCache ) { - name = [ name ]; - } else { - - // split the camel cased version by spaces unless a key with the spaces exists - name = jQuery.camelCase( name ); - if ( name in thisCache ) { - name = [ name ]; - } else { - name = name.split( " " ); - } - } - } - - for ( i = 0, l = name.length; i < l; i++ ) { - delete thisCache[ name[i] ]; - } - - // If there is no data left in the cache, we want to continue - // and let the cache object itself get destroyed - if ( !( pvt ? isEmptyDataObject : jQuery.isEmptyObject )( thisCache ) ) { - return; - } - } - } - - // See jQuery.data for more information - if ( !pvt ) { - delete cache[ id ].data; - - // Don't destroy the parent cache unless the internal data object - // had been the only thing left in it - if ( !isEmptyDataObject(cache[ id ]) ) { - return; - } - } - - // Browsers that fail expando deletion also refuse to delete expandos on - // the window, but it will allow it on all other JS objects; other browsers - // don't care - // Ensure that `cache` is not a window object #10080 - if ( jQuery.support.deleteExpando || !cache.setInterval ) { - delete cache[ id ]; - } else { - cache[ id ] = null; - } - - // We destroyed the cache and need to eliminate the expando on the node to avoid - // false lookups in the cache for entries that no longer exist - if ( isNode ) { - // IE does not allow us to delete expando properties from nodes, - // nor does it have a removeAttribute function on Document nodes; - // we must handle all of these cases - if ( jQuery.support.deleteExpando ) { - delete elem[ internalKey ]; - } else if ( elem.removeAttribute ) { - elem.removeAttribute( internalKey ); - } else { - elem[ internalKey ] = null; - } - } - }, - - // For internal use only. - _data: function( elem, name, data ) { - return jQuery.data( elem, name, data, true ); - }, - - // A method for determining if a DOM node can handle the data expando - acceptData: function( elem ) { - if ( elem.nodeName ) { - var match = jQuery.noData[ elem.nodeName.toLowerCase() ]; - - if ( match ) { - return !(match === true || elem.getAttribute("classid") !== match); - } - } - - return true; - } -}); - -jQuery.fn.extend({ - data: function( key, value ) { - var parts, attr, name, - data = null; - - if ( typeof key === "undefined" ) { - if ( this.length ) { - data = jQuery.data( this[0] ); - - if ( this[0].nodeType === 1 && !jQuery._data( this[0], "parsedAttrs" ) ) { - attr = this[0].attributes; - for ( var i = 0, l = attr.length; i < l; i++ ) { - name = attr[i].name; - - if ( name.indexOf( "data-" ) === 0 ) { - name = jQuery.camelCase( name.substring(5) ); - - dataAttr( this[0], name, data[ name ] ); - } - } - jQuery._data( this[0], "parsedAttrs", true ); - } - } - - return data; - - } else if ( typeof key === "object" ) { - return this.each(function() { - jQuery.data( this, key ); - }); - } - - parts = key.split("."); - parts[1] = parts[1] ? "." + parts[1] : ""; - - if ( value === undefined ) { - data = this.triggerHandler("getData" + parts[1] + "!", [parts[0]]); - - // Try to fetch any internally stored data first - if ( data === undefined && this.length ) { - data = jQuery.data( this[0], key ); - data = dataAttr( this[0], key, data ); - } - - return data === undefined && parts[1] ? - this.data( parts[0] ) : - data; - - } else { - return this.each(function() { - var self = jQuery( this ), - args = [ parts[0], value ]; - - self.triggerHandler( "setData" + parts[1] + "!", args ); - jQuery.data( this, key, value ); - self.triggerHandler( "changeData" + parts[1] + "!", args ); - }); - } - }, - - removeData: function( key ) { - return this.each(function() { - jQuery.removeData( this, key ); - }); - } -}); - -function dataAttr( elem, key, data ) { - // If nothing was found internally, try to fetch any - // data from the HTML5 data-* attribute - if ( data === undefined && elem.nodeType === 1 ) { - - var name = "data-" + key.replace( rmultiDash, "-$1" ).toLowerCase(); - - data = elem.getAttribute( name ); - - if ( typeof data === "string" ) { - try { - data = data === "true" ? true : - data === "false" ? false : - data === "null" ? null : - jQuery.isNumeric( data ) ? parseFloat( data ) : - rbrace.test( data ) ? jQuery.parseJSON( data ) : - data; - } catch( e ) {} - - // Make sure we set the data so it isn't changed later - jQuery.data( elem, key, data ); - - } else { - data = undefined; - } - } - - return data; -} - -// checks a cache object for emptiness -function isEmptyDataObject( obj ) { - for ( var name in obj ) { - - // if the public data object is empty, the private is still empty - if ( name === "data" && jQuery.isEmptyObject( obj[name] ) ) { - continue; - } - if ( name !== "toJSON" ) { - return false; - } - } - - return true; -} - - - - -function handleQueueMarkDefer( elem, type, src ) { - var deferDataKey = type + "defer", - queueDataKey = type + "queue", - markDataKey = type + "mark", - defer = jQuery._data( elem, deferDataKey ); - if ( defer && - ( src === "queue" || !jQuery._data(elem, queueDataKey) ) && - ( src === "mark" || !jQuery._data(elem, markDataKey) ) ) { - // Give room for hard-coded callbacks to fire first - // and eventually mark/queue something else on the element - setTimeout( function() { - if ( !jQuery._data( elem, queueDataKey ) && - !jQuery._data( elem, markDataKey ) ) { - jQuery.removeData( elem, deferDataKey, true ); - defer.fire(); - } - }, 0 ); - } -} - -jQuery.extend({ - - _mark: function( elem, type ) { - if ( elem ) { - type = ( type || "fx" ) + "mark"; - jQuery._data( elem, type, (jQuery._data( elem, type ) || 0) + 1 ); - } - }, - - _unmark: function( force, elem, type ) { - if ( force !== true ) { - type = elem; - elem = force; - force = false; - } - if ( elem ) { - type = type || "fx"; - var key = type + "mark", - count = force ? 0 : ( (jQuery._data( elem, key ) || 1) - 1 ); - if ( count ) { - jQuery._data( elem, key, count ); - } else { - jQuery.removeData( elem, key, true ); - handleQueueMarkDefer( elem, type, "mark" ); - } - } - }, - - queue: function( elem, type, data ) { - var q; - if ( elem ) { - type = ( type || "fx" ) + "queue"; - q = jQuery._data( elem, type ); - - // Speed up dequeue by getting out quickly if this is just a lookup - if ( data ) { - if ( !q || jQuery.isArray(data) ) { - q = jQuery._data( elem, type, jQuery.makeArray(data) ); - } else { - q.push( data ); - } - } - return q || []; - } - }, - - dequeue: function( elem, type ) { - type = type || "fx"; - - var queue = jQuery.queue( elem, type ), - fn = queue.shift(), - hooks = {}; - - // If the fx queue is dequeued, always remove the progress sentinel - if ( fn === "inprogress" ) { - fn = queue.shift(); - } - - if ( fn ) { - // Add a progress sentinel to prevent the fx queue from being - // automatically dequeued - if ( type === "fx" ) { - queue.unshift( "inprogress" ); - } - - jQuery._data( elem, type + ".run", hooks ); - fn.call( elem, function() { - jQuery.dequeue( elem, type ); - }, hooks ); - } - - if ( !queue.length ) { - jQuery.removeData( elem, type + "queue " + type + ".run", true ); - handleQueueMarkDefer( elem, type, "queue" ); - } - } -}); - -jQuery.fn.extend({ - queue: function( type, data ) { - if ( typeof type !== "string" ) { - data = type; - type = "fx"; - } - - if ( data === undefined ) { - return jQuery.queue( this[0], type ); - } - return this.each(function() { - var queue = jQuery.queue( this, type, data ); - - if ( type === "fx" && queue[0] !== "inprogress" ) { - jQuery.dequeue( this, type ); - } - }); - }, - dequeue: function( type ) { - return this.each(function() { - jQuery.dequeue( this, type ); - }); - }, - // Based off of the plugin by Clint Helfers, with permission. - // http://blindsignals.com/index.php/2009/07/jquery-delay/ - delay: function( time, type ) { - time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time; - type = type || "fx"; - - return this.queue( type, function( next, hooks ) { - var timeout = setTimeout( next, time ); - hooks.stop = function() { - clearTimeout( timeout ); - }; - }); - }, - clearQueue: function( type ) { - return this.queue( type || "fx", [] ); - }, - // Get a promise resolved when queues of a certain type - // are emptied (fx is the type by default) - promise: function( type, object ) { - if ( typeof type !== "string" ) { - object = type; - type = undefined; - } - type = type || "fx"; - var defer = jQuery.Deferred(), - elements = this, - i = elements.length, - count = 1, - deferDataKey = type + "defer", - queueDataKey = type + "queue", - markDataKey = type + "mark", - tmp; - function resolve() { - if ( !( --count ) ) { - defer.resolveWith( elements, [ elements ] ); - } - } - while( i-- ) { - if (( tmp = jQuery.data( elements[ i ], deferDataKey, undefined, true ) || - ( jQuery.data( elements[ i ], queueDataKey, undefined, true ) || - jQuery.data( elements[ i ], markDataKey, undefined, true ) ) && - jQuery.data( elements[ i ], deferDataKey, jQuery.Callbacks( "once memory" ), true ) )) { - count++; - tmp.add( resolve ); - } - } - resolve(); - return defer.promise(); - } -}); - - - - -var rclass = /[\n\t\r]/g, - rspace = /\s+/, - rreturn = /\r/g, - rtype = /^(?:button|input)$/i, - rfocusable = /^(?:button|input|object|select|textarea)$/i, - rclickable = /^a(?:rea)?$/i, - rboolean = /^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i, - getSetAttribute = jQuery.support.getSetAttribute, - nodeHook, boolHook, fixSpecified; - -jQuery.fn.extend({ - attr: function( name, value ) { - return jQuery.access( this, name, value, true, jQuery.attr ); - }, - - removeAttr: function( name ) { - return this.each(function() { - jQuery.removeAttr( this, name ); - }); - }, - - prop: function( name, value ) { - return jQuery.access( this, name, value, true, jQuery.prop ); - }, - - removeProp: function( name ) { - name = jQuery.propFix[ name ] || name; - return this.each(function() { - // try/catch handles cases where IE balks (such as removing a property on window) - try { - this[ name ] = undefined; - delete this[ name ]; - } catch( e ) {} - }); - }, - - addClass: function( value ) { - var classNames, i, l, elem, - setClass, c, cl; - - if ( jQuery.isFunction( value ) ) { - return this.each(function( j ) { - jQuery( this ).addClass( value.call(this, j, this.className) ); - }); - } - - if ( value && typeof value === "string" ) { - classNames = value.split( rspace ); - - for ( i = 0, l = this.length; i < l; i++ ) { - elem = this[ i ]; - - if ( elem.nodeType === 1 ) { - if ( !elem.className && classNames.length === 1 ) { - elem.className = value; - - } else { - setClass = " " + elem.className + " "; - - for ( c = 0, cl = classNames.length; c < cl; c++ ) { - if ( !~setClass.indexOf( " " + classNames[ c ] + " " ) ) { - setClass += classNames[ c ] + " "; - } - } - elem.className = jQuery.trim( setClass ); - } - } - } - } - - return this; - }, - - removeClass: function( value ) { - var classNames, i, l, elem, className, c, cl; - - if ( jQuery.isFunction( value ) ) { - return this.each(function( j ) { - jQuery( this ).removeClass( value.call(this, j, this.className) ); - }); - } - - if ( (value && typeof value === "string") || value === undefined ) { - classNames = ( value || "" ).split( rspace ); - - for ( i = 0, l = this.length; i < l; i++ ) { - elem = this[ i ]; - - if ( elem.nodeType === 1 && elem.className ) { - if ( value ) { - className = (" " + elem.className + " ").replace( rclass, " " ); - for ( c = 0, cl = classNames.length; c < cl; c++ ) { - className = className.replace(" " + classNames[ c ] + " ", " "); - } - elem.className = jQuery.trim( className ); - - } else { - elem.className = ""; - } - } - } - } - - return this; - }, - - toggleClass: function( value, stateVal ) { - var type = typeof value, - isBool = typeof stateVal === "boolean"; - - if ( jQuery.isFunction( value ) ) { - return this.each(function( i ) { - jQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal ); - }); - } - - return this.each(function() { - if ( type === "string" ) { - // toggle individual class names - var className, - i = 0, - self = jQuery( this ), - state = stateVal, - classNames = value.split( rspace ); - - while ( (className = classNames[ i++ ]) ) { - // check each className given, space seperated list - state = isBool ? state : !self.hasClass( className ); - self[ state ? "addClass" : "removeClass" ]( className ); - } - - } else if ( type === "undefined" || type === "boolean" ) { - if ( this.className ) { - // store className if set - jQuery._data( this, "__className__", this.className ); - } - - // toggle whole className - this.className = this.className || value === false ? "" : jQuery._data( this, "__className__" ) || ""; - } - }); - }, - - hasClass: function( selector ) { - var className = " " + selector + " ", - i = 0, - l = this.length; - for ( ; i < l; i++ ) { - if ( this[i].nodeType === 1 && (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) > -1 ) { - return true; - } - } - - return false; - }, - - val: function( value ) { - var hooks, ret, isFunction, - elem = this[0]; - - if ( !arguments.length ) { - if ( elem ) { - hooks = jQuery.valHooks[ elem.nodeName.toLowerCase() ] || jQuery.valHooks[ elem.type ]; - - if ( hooks && "get" in hooks && (ret = hooks.get( elem, "value" )) !== undefined ) { - return ret; - } - - ret = elem.value; - - return typeof ret === "string" ? - // handle most common string cases - ret.replace(rreturn, "") : - // handle cases where value is null/undef or number - ret == null ? "" : ret; - } - - return; - } - - isFunction = jQuery.isFunction( value ); - - return this.each(function( i ) { - var self = jQuery(this), val; - - if ( this.nodeType !== 1 ) { - return; - } - - if ( isFunction ) { - val = value.call( this, i, self.val() ); - } else { - val = value; - } - - // Treat null/undefined as ""; convert numbers to string - if ( val == null ) { - val = ""; - } else if ( typeof val === "number" ) { - val += ""; - } else if ( jQuery.isArray( val ) ) { - val = jQuery.map(val, function ( value ) { - return value == null ? "" : value + ""; - }); - } - - hooks = jQuery.valHooks[ this.nodeName.toLowerCase() ] || jQuery.valHooks[ this.type ]; - - // If set returns undefined, fall back to normal setting - if ( !hooks || !("set" in hooks) || hooks.set( this, val, "value" ) === undefined ) { - this.value = val; - } - }); - } -}); - -jQuery.extend({ - valHooks: { - option: { - get: function( elem ) { - // attributes.value is undefined in Blackberry 4.7 but - // uses .value. See #6932 - var val = elem.attributes.value; - return !val || val.specified ? elem.value : elem.text; - } - }, - select: { - get: function( elem ) { - var value, i, max, option, - index = elem.selectedIndex, - values = [], - options = elem.options, - one = elem.type === "select-one"; - - // Nothing was selected - if ( index < 0 ) { - return null; - } - - // Loop through all the selected options - i = one ? index : 0; - max = one ? index + 1 : options.length; - for ( ; i < max; i++ ) { - option = options[ i ]; - - // Don't return options that are disabled or in a disabled optgroup - if ( option.selected && (jQuery.support.optDisabled ? !option.disabled : option.getAttribute("disabled") === null) && - (!option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" )) ) { - - // Get the specific value for the option - value = jQuery( option ).val(); - - // We don't need an array for one selects - if ( one ) { - return value; - } - - // Multi-Selects return an array - values.push( value ); - } - } - - // Fixes Bug #2551 -- select.val() broken in IE after form.reset() - if ( one && !values.length && options.length ) { - return jQuery( options[ index ] ).val(); - } - - return values; - }, - - set: function( elem, value ) { - var values = jQuery.makeArray( value ); - - jQuery(elem).find("option").each(function() { - this.selected = jQuery.inArray( jQuery(this).val(), values ) >= 0; - }); - - if ( !values.length ) { - elem.selectedIndex = -1; - } - return values; - } - } - }, - - attrFn: { - val: true, - css: true, - html: true, - text: true, - data: true, - width: true, - height: true, - offset: true - }, - - attr: function( elem, name, value, pass ) { - var ret, hooks, notxml, - nType = elem.nodeType; - - // don't get/set attributes on text, comment and attribute nodes - if ( !elem || nType === 3 || nType === 8 || nType === 2 ) { - return; - } - - if ( pass && name in jQuery.attrFn ) { - return jQuery( elem )[ name ]( value ); - } - - // Fallback to prop when attributes are not supported - if ( typeof elem.getAttribute === "undefined" ) { - return jQuery.prop( elem, name, value ); - } - - notxml = nType !== 1 || !jQuery.isXMLDoc( elem ); - - // All attributes are lowercase - // Grab necessary hook if one is defined - if ( notxml ) { - name = name.toLowerCase(); - hooks = jQuery.attrHooks[ name ] || ( rboolean.test( name ) ? boolHook : nodeHook ); - } - - if ( value !== undefined ) { - - if ( value === null ) { - jQuery.removeAttr( elem, name ); - return; - - } else if ( hooks && "set" in hooks && notxml && (ret = hooks.set( elem, value, name )) !== undefined ) { - return ret; - - } else { - elem.setAttribute( name, "" + value ); - return value; - } - - } else if ( hooks && "get" in hooks && notxml && (ret = hooks.get( elem, name )) !== null ) { - return ret; - - } else { - - ret = elem.getAttribute( name ); - - // Non-existent attributes return null, we normalize to undefined - return ret === null ? - undefined : - ret; - } - }, - - removeAttr: function( elem, value ) { - var propName, attrNames, name, l, - i = 0; - - if ( value && elem.nodeType === 1 ) { - attrNames = value.toLowerCase().split( rspace ); - l = attrNames.length; - - for ( ; i < l; i++ ) { - name = attrNames[ i ]; - - if ( name ) { - propName = jQuery.propFix[ name ] || name; - - // See #9699 for explanation of this approach (setting first, then removal) - jQuery.attr( elem, name, "" ); - elem.removeAttribute( getSetAttribute ? name : propName ); - - // Set corresponding property to false for boolean attributes - if ( rboolean.test( name ) && propName in elem ) { - elem[ propName ] = false; - } - } - } - } - }, - - attrHooks: { - type: { - set: function( elem, value ) { - // We can't allow the type property to be changed (since it causes problems in IE) - if ( rtype.test( elem.nodeName ) && elem.parentNode ) { - jQuery.error( "type property can't be changed" ); - } else if ( !jQuery.support.radioValue && value === "radio" && jQuery.nodeName(elem, "input") ) { - // Setting the type on a radio button after the value resets the value in IE6-9 - // Reset value to it's default in case type is set after value - // This is for element creation - var val = elem.value; - elem.setAttribute( "type", value ); - if ( val ) { - elem.value = val; - } - return value; - } - } - }, - // Use the value property for back compat - // Use the nodeHook for button elements in IE6/7 (#1954) - value: { - get: function( elem, name ) { - if ( nodeHook && jQuery.nodeName( elem, "button" ) ) { - return nodeHook.get( elem, name ); - } - return name in elem ? - elem.value : - null; - }, - set: function( elem, value, name ) { - if ( nodeHook && jQuery.nodeName( elem, "button" ) ) { - return nodeHook.set( elem, value, name ); - } - // Does not return so that setAttribute is also used - elem.value = value; - } - } - }, - - propFix: { - tabindex: "tabIndex", - readonly: "readOnly", - "for": "htmlFor", - "class": "className", - maxlength: "maxLength", - cellspacing: "cellSpacing", - cellpadding: "cellPadding", - rowspan: "rowSpan", - colspan: "colSpan", - usemap: "useMap", - frameborder: "frameBorder", - contenteditable: "contentEditable" - }, - - prop: function( elem, name, value ) { - var ret, hooks, notxml, - nType = elem.nodeType; - - // don't get/set properties on text, comment and attribute nodes - if ( !elem || nType === 3 || nType === 8 || nType === 2 ) { - return; - } - - notxml = nType !== 1 || !jQuery.isXMLDoc( elem ); - - if ( notxml ) { - // Fix name and attach hooks - name = jQuery.propFix[ name ] || name; - hooks = jQuery.propHooks[ name ]; - } - - if ( value !== undefined ) { - if ( hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) { - return ret; - - } else { - return ( elem[ name ] = value ); - } - - } else { - if ( hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ) { - return ret; - - } else { - return elem[ name ]; - } - } - }, - - propHooks: { - tabIndex: { - get: function( elem ) { - // elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set - // http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/ - var attributeNode = elem.getAttributeNode("tabindex"); - - return attributeNode && attributeNode.specified ? - parseInt( attributeNode.value, 10 ) : - rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ? - 0 : - undefined; - } - } - } -}); - -// Add the tabIndex propHook to attrHooks for back-compat (different case is intentional) -jQuery.attrHooks.tabindex = jQuery.propHooks.tabIndex; - -// Hook for boolean attributes -boolHook = { - get: function( elem, name ) { - // Align boolean attributes with corresponding properties - // Fall back to attribute presence where some booleans are not supported - var attrNode, - property = jQuery.prop( elem, name ); - return property === true || typeof property !== "boolean" && ( attrNode = elem.getAttributeNode(name) ) && attrNode.nodeValue !== false ? - name.toLowerCase() : - undefined; - }, - set: function( elem, value, name ) { - var propName; - if ( value === false ) { - // Remove boolean attributes when set to false - jQuery.removeAttr( elem, name ); - } else { - // value is true since we know at this point it's type boolean and not false - // Set boolean attributes to the same name and set the DOM property - propName = jQuery.propFix[ name ] || name; - if ( propName in elem ) { - // Only set the IDL specifically if it already exists on the element - elem[ propName ] = true; - } - - elem.setAttribute( name, name.toLowerCase() ); - } - return name; - } -}; - -// IE6/7 do not support getting/setting some attributes with get/setAttribute -if ( !getSetAttribute ) { - - fixSpecified = { - name: true, - id: true - }; - - // Use this for any attribute in IE6/7 - // This fixes almost every IE6/7 issue - nodeHook = jQuery.valHooks.button = { - get: function( elem, name ) { - var ret; - ret = elem.getAttributeNode( name ); - return ret && ( fixSpecified[ name ] ? ret.nodeValue !== "" : ret.specified ) ? - ret.nodeValue : - undefined; - }, - set: function( elem, value, name ) { - // Set the existing or create a new attribute node - var ret = elem.getAttributeNode( name ); - if ( !ret ) { - ret = document.createAttribute( name ); - elem.setAttributeNode( ret ); - } - return ( ret.nodeValue = value + "" ); - } - }; - - // Apply the nodeHook to tabindex - jQuery.attrHooks.tabindex.set = nodeHook.set; - - // Set width and height to auto instead of 0 on empty string( Bug #8150 ) - // This is for removals - jQuery.each([ "width", "height" ], function( i, name ) { - jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], { - set: function( elem, value ) { - if ( value === "" ) { - elem.setAttribute( name, "auto" ); - return value; - } - } - }); - }); - - // Set contenteditable to false on removals(#10429) - // Setting to empty string throws an error as an invalid value - jQuery.attrHooks.contenteditable = { - get: nodeHook.get, - set: function( elem, value, name ) { - if ( value === "" ) { - value = "false"; - } - nodeHook.set( elem, value, name ); - } - }; -} - - -// Some attributes require a special call on IE -if ( !jQuery.support.hrefNormalized ) { - jQuery.each([ "href", "src", "width", "height" ], function( i, name ) { - jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], { - get: function( elem ) { - var ret = elem.getAttribute( name, 2 ); - return ret === null ? undefined : ret; - } - }); - }); -} - -if ( !jQuery.support.style ) { - jQuery.attrHooks.style = { - get: function( elem ) { - // Return undefined in the case of empty string - // Normalize to lowercase since IE uppercases css property names - return elem.style.cssText.toLowerCase() || undefined; - }, - set: function( elem, value ) { - return ( elem.style.cssText = "" + value ); - } - }; -} - -// Safari mis-reports the default selected property of an option -// Accessing the parent's selectedIndex property fixes it -if ( !jQuery.support.optSelected ) { - jQuery.propHooks.selected = jQuery.extend( jQuery.propHooks.selected, { - get: function( elem ) { - var parent = elem.parentNode; - - if ( parent ) { - parent.selectedIndex; - - // Make sure that it also works with optgroups, see #5701 - if ( parent.parentNode ) { - parent.parentNode.selectedIndex; - } - } - return null; - } - }); -} - -// IE6/7 call enctype encoding -if ( !jQuery.support.enctype ) { - jQuery.propFix.enctype = "encoding"; -} - -// Radios and checkboxes getter/setter -if ( !jQuery.support.checkOn ) { - jQuery.each([ "radio", "checkbox" ], function() { - jQuery.valHooks[ this ] = { - get: function( elem ) { - // Handle the case where in Webkit "" is returned instead of "on" if a value isn't specified - return elem.getAttribute("value") === null ? "on" : elem.value; - } - }; - }); -} -jQuery.each([ "radio", "checkbox" ], function() { - jQuery.valHooks[ this ] = jQuery.extend( jQuery.valHooks[ this ], { - set: function( elem, value ) { - if ( jQuery.isArray( value ) ) { - return ( elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0 ); - } - } - }); -}); - - - - -var rformElems = /^(?:textarea|input|select)$/i, - rtypenamespace = /^([^\.]*)?(?:\.(.+))?$/, - rhoverHack = /\bhover(\.\S+)?\b/, - rkeyEvent = /^key/, - rmouseEvent = /^(?:mouse|contextmenu)|click/, - rfocusMorph = /^(?:focusinfocus|focusoutblur)$/, - rquickIs = /^(\w*)(?:#([\w\-]+))?(?:\.([\w\-]+))?$/, - quickParse = function( selector ) { - var quick = rquickIs.exec( selector ); - if ( quick ) { - // 0 1 2 3 - // [ _, tag, id, class ] - quick[1] = ( quick[1] || "" ).toLowerCase(); - quick[3] = quick[3] && new RegExp( "(?:^|\\s)" + quick[3] + "(?:\\s|$)" ); - } - return quick; - }, - quickIs = function( elem, m ) { - var attrs = elem.attributes || {}; - return ( - (!m[1] || elem.nodeName.toLowerCase() === m[1]) && - (!m[2] || (attrs.id || {}).value === m[2]) && - (!m[3] || m[3].test( (attrs[ "class" ] || {}).value )) - ); - }, - hoverHack = function( events ) { - return jQuery.event.special.hover ? events : events.replace( rhoverHack, "mouseenter$1 mouseleave$1" ); - }; - -/* - * Helper functions for managing events -- not part of the public interface. - * Props to Dean Edwards' addEvent library for many of the ideas. - */ -jQuery.event = { - - add: function( elem, types, handler, data, selector ) { - - var elemData, eventHandle, events, - t, tns, type, namespaces, handleObj, - handleObjIn, quick, handlers, special; - - // Don't attach events to noData or text/comment nodes (allow plain objects tho) - if ( elem.nodeType === 3 || elem.nodeType === 8 || !types || !handler || !(elemData = jQuery._data( elem )) ) { - return; - } - - // Caller can pass in an object of custom data in lieu of the handler - if ( handler.handler ) { - handleObjIn = handler; - handler = handleObjIn.handler; - } - - // Make sure that the handler has a unique ID, used to find/remove it later - if ( !handler.guid ) { - handler.guid = jQuery.guid++; - } - - // Init the element's event structure and main handler, if this is the first - events = elemData.events; - if ( !events ) { - elemData.events = events = {}; - } - eventHandle = elemData.handle; - if ( !eventHandle ) { - elemData.handle = eventHandle = function( e ) { - // Discard the second event of a jQuery.event.trigger() and - // when an event is called after a page has unloaded - return typeof jQuery !== "undefined" && (!e || jQuery.event.triggered !== e.type) ? - jQuery.event.dispatch.apply( eventHandle.elem, arguments ) : - undefined; - }; - // Add elem as a property of the handle fn to prevent a memory leak with IE non-native events - eventHandle.elem = elem; - } - - // Handle multiple events separated by a space - // jQuery(...).bind("mouseover mouseout", fn); - types = jQuery.trim( hoverHack(types) ).split( " " ); - for ( t = 0; t < types.length; t++ ) { - - tns = rtypenamespace.exec( types[t] ) || []; - type = tns[1]; - namespaces = ( tns[2] || "" ).split( "." ).sort(); - - // If event changes its type, use the special event handlers for the changed type - special = jQuery.event.special[ type ] || {}; - - // If selector defined, determine special event api type, otherwise given type - type = ( selector ? special.delegateType : special.bindType ) || type; - - // Update special based on newly reset type - special = jQuery.event.special[ type ] || {}; - - // handleObj is passed to all event handlers - handleObj = jQuery.extend({ - type: type, - origType: tns[1], - data: data, - handler: handler, - guid: handler.guid, - selector: selector, - quick: quickParse( selector ), - namespace: namespaces.join(".") - }, handleObjIn ); - - // Init the event handler queue if we're the first - handlers = events[ type ]; - if ( !handlers ) { - handlers = events[ type ] = []; - handlers.delegateCount = 0; - - // Only use addEventListener/attachEvent if the special events handler returns false - if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) { - // Bind the global event handler to the element - if ( elem.addEventListener ) { - elem.addEventListener( type, eventHandle, false ); - - } else if ( elem.attachEvent ) { - elem.attachEvent( "on" + type, eventHandle ); - } - } - } - - if ( special.add ) { - special.add.call( elem, handleObj ); - - if ( !handleObj.handler.guid ) { - handleObj.handler.guid = handler.guid; - } - } - - // Add to the element's handler list, delegates in front - if ( selector ) { - handlers.splice( handlers.delegateCount++, 0, handleObj ); - } else { - handlers.push( handleObj ); - } - - // Keep track of which events have ever been used, for event optimization - jQuery.event.global[ type ] = true; - } - - // Nullify elem to prevent memory leaks in IE - elem = null; - }, - - global: {}, - - // Detach an event or set of events from an element - remove: function( elem, types, handler, selector, mappedTypes ) { - - var elemData = jQuery.hasData( elem ) && jQuery._data( elem ), - t, tns, type, origType, namespaces, origCount, - j, events, special, handle, eventType, handleObj; - - if ( !elemData || !(events = elemData.events) ) { - return; - } - - // Once for each type.namespace in types; type may be omitted - types = jQuery.trim( hoverHack( types || "" ) ).split(" "); - for ( t = 0; t < types.length; t++ ) { - tns = rtypenamespace.exec( types[t] ) || []; - type = origType = tns[1]; - namespaces = tns[2]; - - // Unbind all events (on this namespace, if provided) for the element - if ( !type ) { - for ( type in events ) { - jQuery.event.remove( elem, type + types[ t ], handler, selector, true ); - } - continue; - } - - special = jQuery.event.special[ type ] || {}; - type = ( selector? special.delegateType : special.bindType ) || type; - eventType = events[ type ] || []; - origCount = eventType.length; - namespaces = namespaces ? new RegExp("(^|\\.)" + namespaces.split(".").sort().join("\\.(?:.*\\.)?") + "(\\.|$)") : null; - - // Remove matching events - for ( j = 0; j < eventType.length; j++ ) { - handleObj = eventType[ j ]; - - if ( ( mappedTypes || origType === handleObj.origType ) && - ( !handler || handler.guid === handleObj.guid ) && - ( !namespaces || namespaces.test( handleObj.namespace ) ) && - ( !selector || selector === handleObj.selector || selector === "**" && handleObj.selector ) ) { - eventType.splice( j--, 1 ); - - if ( handleObj.selector ) { - eventType.delegateCount--; - } - if ( special.remove ) { - special.remove.call( elem, handleObj ); - } - } - } - - // Remove generic event handler if we removed something and no more handlers exist - // (avoids potential for endless recursion during removal of special event handlers) - if ( eventType.length === 0 && origCount !== eventType.length ) { - if ( !special.teardown || special.teardown.call( elem, namespaces ) === false ) { - jQuery.removeEvent( elem, type, elemData.handle ); - } - - delete events[ type ]; - } - } - - // Remove the expando if it's no longer used - if ( jQuery.isEmptyObject( events ) ) { - handle = elemData.handle; - if ( handle ) { - handle.elem = null; - } - - // removeData also checks for emptiness and clears the expando if empty - // so use it instead of delete - jQuery.removeData( elem, [ "events", "handle" ], true ); - } - }, - - // Events that are safe to short-circuit if no handlers are attached. - // Native DOM events should not be added, they may have inline handlers. - customEvent: { - "getData": true, - "setData": true, - "changeData": true - }, - - trigger: function( event, data, elem, onlyHandlers ) { - // Don't do events on text and comment nodes - if ( elem && (elem.nodeType === 3 || elem.nodeType === 8) ) { - return; - } - - // Event object or event type - var type = event.type || event, - namespaces = [], - cache, exclusive, i, cur, old, ontype, special, handle, eventPath, bubbleType; - - // focus/blur morphs to focusin/out; ensure we're not firing them right now - if ( rfocusMorph.test( type + jQuery.event.triggered ) ) { - return; - } - - if ( type.indexOf( "!" ) >= 0 ) { - // Exclusive events trigger only for the exact event (no namespaces) - type = type.slice(0, -1); - exclusive = true; - } - - if ( type.indexOf( "." ) >= 0 ) { - // Namespaced trigger; create a regexp to match event type in handle() - namespaces = type.split("."); - type = namespaces.shift(); - namespaces.sort(); - } - - if ( (!elem || jQuery.event.customEvent[ type ]) && !jQuery.event.global[ type ] ) { - // No jQuery handlers for this event type, and it can't have inline handlers - return; - } - - // Caller can pass in an Event, Object, or just an event type string - event = typeof event === "object" ? - // jQuery.Event object - event[ jQuery.expando ] ? event : - // Object literal - new jQuery.Event( type, event ) : - // Just the event type (string) - new jQuery.Event( type ); - - event.type = type; - event.isTrigger = true; - event.exclusive = exclusive; - event.namespace = namespaces.join( "." ); - event.namespace_re = event.namespace? new RegExp("(^|\\.)" + namespaces.join("\\.(?:.*\\.)?") + "(\\.|$)") : null; - ontype = type.indexOf( ":" ) < 0 ? "on" + type : ""; - - // Handle a global trigger - if ( !elem ) { - - // TODO: Stop taunting the data cache; remove global events and always attach to document - cache = jQuery.cache; - for ( i in cache ) { - if ( cache[ i ].events && cache[ i ].events[ type ] ) { - jQuery.event.trigger( event, data, cache[ i ].handle.elem, true ); - } - } - return; - } - - // Clean up the event in case it is being reused - event.result = undefined; - if ( !event.target ) { - event.target = elem; - } - - // Clone any incoming data and prepend the event, creating the handler arg list - data = data != null ? jQuery.makeArray( data ) : []; - data.unshift( event ); - - // Allow special events to draw outside the lines - special = jQuery.event.special[ type ] || {}; - if ( special.trigger && special.trigger.apply( elem, data ) === false ) { - return; - } - - // Determine event propagation path in advance, per W3C events spec (#9951) - // Bubble up to document, then to window; watch for a global ownerDocument var (#9724) - eventPath = [[ elem, special.bindType || type ]]; - if ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) { - - bubbleType = special.delegateType || type; - cur = rfocusMorph.test( bubbleType + type ) ? elem : elem.parentNode; - old = null; - for ( ; cur; cur = cur.parentNode ) { - eventPath.push([ cur, bubbleType ]); - old = cur; - } - - // Only add window if we got to document (e.g., not plain obj or detached DOM) - if ( old && old === elem.ownerDocument ) { - eventPath.push([ old.defaultView || old.parentWindow || window, bubbleType ]); - } - } - - // Fire handlers on the event path - for ( i = 0; i < eventPath.length && !event.isPropagationStopped(); i++ ) { - - cur = eventPath[i][0]; - event.type = eventPath[i][1]; - - handle = ( jQuery._data( cur, "events" ) || {} )[ event.type ] && jQuery._data( cur, "handle" ); - if ( handle ) { - handle.apply( cur, data ); - } - // Note that this is a bare JS function and not a jQuery handler - handle = ontype && cur[ ontype ]; - if ( handle && jQuery.acceptData( cur ) && handle.apply( cur, data ) === false ) { - event.preventDefault(); - } - } - event.type = type; - - // If nobody prevented the default action, do it now - if ( !onlyHandlers && !event.isDefaultPrevented() ) { - - if ( (!special._default || special._default.apply( elem.ownerDocument, data ) === false) && - !(type === "click" && jQuery.nodeName( elem, "a" )) && jQuery.acceptData( elem ) ) { - - // Call a native DOM method on the target with the same name name as the event. - // Can't use an .isFunction() check here because IE6/7 fails that test. - // Don't do default actions on window, that's where global variables be (#6170) - // IE<9 dies on focus/blur to hidden element (#1486) - if ( ontype && elem[ type ] && ((type !== "focus" && type !== "blur") || event.target.offsetWidth !== 0) && !jQuery.isWindow( elem ) ) { - - // Don't re-trigger an onFOO event when we call its FOO() method - old = elem[ ontype ]; - - if ( old ) { - elem[ ontype ] = null; - } - - // Prevent re-triggering of the same event, since we already bubbled it above - jQuery.event.triggered = type; - elem[ type ](); - jQuery.event.triggered = undefined; - - if ( old ) { - elem[ ontype ] = old; - } - } - } - } - - return event.result; - }, - - dispatch: function( event ) { - - // Make a writable jQuery.Event from the native event object - event = jQuery.event.fix( event || window.event ); - - var handlers = ( (jQuery._data( this, "events" ) || {} )[ event.type ] || []), - delegateCount = handlers.delegateCount, - args = [].slice.call( arguments, 0 ), - run_all = !event.exclusive && !event.namespace, - handlerQueue = [], - i, j, cur, jqcur, ret, selMatch, matched, matches, handleObj, sel, related; - - // Use the fix-ed jQuery.Event rather than the (read-only) native event - args[0] = event; - event.delegateTarget = this; - - // Determine handlers that should run if there are delegated events - // Avoid disabled elements in IE (#6911) and non-left-click bubbling in Firefox (#3861) - if ( delegateCount && !event.target.disabled && !(event.button && event.type === "click") ) { - - // Pregenerate a single jQuery object for reuse with .is() - jqcur = jQuery(this); - jqcur.context = this.ownerDocument || this; - - for ( cur = event.target; cur != this; cur = cur.parentNode || this ) { - selMatch = {}; - matches = []; - jqcur[0] = cur; - for ( i = 0; i < delegateCount; i++ ) { - handleObj = handlers[ i ]; - sel = handleObj.selector; - - if ( selMatch[ sel ] === undefined ) { - selMatch[ sel ] = ( - handleObj.quick ? quickIs( cur, handleObj.quick ) : jqcur.is( sel ) - ); - } - if ( selMatch[ sel ] ) { - matches.push( handleObj ); - } - } - if ( matches.length ) { - handlerQueue.push({ elem: cur, matches: matches }); - } - } - } - - // Add the remaining (directly-bound) handlers - if ( handlers.length > delegateCount ) { - handlerQueue.push({ elem: this, matches: handlers.slice( delegateCount ) }); - } - - // Run delegates first; they may want to stop propagation beneath us - for ( i = 0; i < handlerQueue.length && !event.isPropagationStopped(); i++ ) { - matched = handlerQueue[ i ]; - event.currentTarget = matched.elem; - - for ( j = 0; j < matched.matches.length && !event.isImmediatePropagationStopped(); j++ ) { - handleObj = matched.matches[ j ]; - - // Triggered event must either 1) be non-exclusive and have no namespace, or - // 2) have namespace(s) a subset or equal to those in the bound event (both can have no namespace). - if ( run_all || (!event.namespace && !handleObj.namespace) || event.namespace_re && event.namespace_re.test( handleObj.namespace ) ) { - - event.data = handleObj.data; - event.handleObj = handleObj; - - ret = ( (jQuery.event.special[ handleObj.origType ] || {}).handle || handleObj.handler ) - .apply( matched.elem, args ); - - if ( ret !== undefined ) { - event.result = ret; - if ( ret === false ) { - event.preventDefault(); - event.stopPropagation(); - } - } - } - } - } - - return event.result; - }, - - // Includes some event props shared by KeyEvent and MouseEvent - // *** attrChange attrName relatedNode srcElement are not normalized, non-W3C, deprecated, will be removed in 1.8 *** - props: "attrChange attrName relatedNode srcElement altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "), - - fixHooks: {}, - - keyHooks: { - props: "char charCode key keyCode".split(" "), - filter: function( event, original ) { - - // Add which for key events - if ( event.which == null ) { - event.which = original.charCode != null ? original.charCode : original.keyCode; - } - - return event; - } - }, - - mouseHooks: { - props: "button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "), - filter: function( event, original ) { - var eventDoc, doc, body, - button = original.button, - fromElement = original.fromElement; - - // Calculate pageX/Y if missing and clientX/Y available - if ( event.pageX == null && original.clientX != null ) { - eventDoc = event.target.ownerDocument || document; - doc = eventDoc.documentElement; - body = eventDoc.body; - - event.pageX = original.clientX + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - ( doc && doc.clientLeft || body && body.clientLeft || 0 ); - event.pageY = original.clientY + ( doc && doc.scrollTop || body && body.scrollTop || 0 ) - ( doc && doc.clientTop || body && body.clientTop || 0 ); - } - - // Add relatedTarget, if necessary - if ( !event.relatedTarget && fromElement ) { - event.relatedTarget = fromElement === event.target ? original.toElement : fromElement; - } - - // Add which for click: 1 === left; 2 === middle; 3 === right - // Note: button is not normalized, so don't use it - if ( !event.which && button !== undefined ) { - event.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) ); - } - - return event; - } - }, - - fix: function( event ) { - if ( event[ jQuery.expando ] ) { - return event; - } - - // Create a writable copy of the event object and normalize some properties - var i, prop, - originalEvent = event, - fixHook = jQuery.event.fixHooks[ event.type ] || {}, - copy = fixHook.props ? this.props.concat( fixHook.props ) : this.props; - - event = jQuery.Event( originalEvent ); - - for ( i = copy.length; i; ) { - prop = copy[ --i ]; - event[ prop ] = originalEvent[ prop ]; - } - - // Fix target property, if necessary (#1925, IE 6/7/8 & Safari2) - if ( !event.target ) { - event.target = originalEvent.srcElement || document; - } - - // Target should not be a text node (#504, Safari) - if ( event.target.nodeType === 3 ) { - event.target = event.target.parentNode; - } - - // For mouse/key events; add metaKey if it's not there (#3368, IE6/7/8) - if ( event.metaKey === undefined ) { - event.metaKey = event.ctrlKey; - } - - return fixHook.filter? fixHook.filter( event, originalEvent ) : event; - }, - - special: { - ready: { - // Make sure the ready event is setup - setup: jQuery.bindReady - }, - - load: { - // Prevent triggered image.load events from bubbling to window.load - noBubble: true - }, - - focus: { - delegateType: "focusin" - }, - blur: { - delegateType: "focusout" - }, - - beforeunload: { - setup: function( data, namespaces, eventHandle ) { - // We only want to do this special case on windows - if ( jQuery.isWindow( this ) ) { - this.onbeforeunload = eventHandle; - } - }, - - teardown: function( namespaces, eventHandle ) { - if ( this.onbeforeunload === eventHandle ) { - this.onbeforeunload = null; - } - } - } - }, - - simulate: function( type, elem, event, bubble ) { - // Piggyback on a donor event to simulate a different one. - // Fake originalEvent to avoid donor's stopPropagation, but if the - // simulated event prevents default then we do the same on the donor. - var e = jQuery.extend( - new jQuery.Event(), - event, - { type: type, - isSimulated: true, - originalEvent: {} - } - ); - if ( bubble ) { - jQuery.event.trigger( e, null, elem ); - } else { - jQuery.event.dispatch.call( elem, e ); - } - if ( e.isDefaultPrevented() ) { - event.preventDefault(); - } - } -}; - -// Some plugins are using, but it's undocumented/deprecated and will be removed. -// The 1.7 special event interface should provide all the hooks needed now. -jQuery.event.handle = jQuery.event.dispatch; - -jQuery.removeEvent = document.removeEventListener ? - function( elem, type, handle ) { - if ( elem.removeEventListener ) { - elem.removeEventListener( type, handle, false ); - } - } : - function( elem, type, handle ) { - if ( elem.detachEvent ) { - elem.detachEvent( "on" + type, handle ); - } - }; - -jQuery.Event = function( src, props ) { - // Allow instantiation without the 'new' keyword - if ( !(this instanceof jQuery.Event) ) { - return new jQuery.Event( src, props ); - } - - // Event object - if ( src && src.type ) { - this.originalEvent = src; - this.type = src.type; - - // Events bubbling up the document may have been marked as prevented - // by a handler lower down the tree; reflect the correct value. - this.isDefaultPrevented = ( src.defaultPrevented || src.returnValue === false || - src.getPreventDefault && src.getPreventDefault() ) ? returnTrue : returnFalse; - - // Event type - } else { - this.type = src; - } - - // Put explicitly provided properties onto the event object - if ( props ) { - jQuery.extend( this, props ); - } - - // Create a timestamp if incoming event doesn't have one - this.timeStamp = src && src.timeStamp || jQuery.now(); - - // Mark it as fixed - this[ jQuery.expando ] = true; -}; - -function returnFalse() { - return false; -} -function returnTrue() { - return true; -} - -// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding -// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html -jQuery.Event.prototype = { - preventDefault: function() { - this.isDefaultPrevented = returnTrue; - - var e = this.originalEvent; - if ( !e ) { - return; - } - - // if preventDefault exists run it on the original event - if ( e.preventDefault ) { - e.preventDefault(); - - // otherwise set the returnValue property of the original event to false (IE) - } else { - e.returnValue = false; - } - }, - stopPropagation: function() { - this.isPropagationStopped = returnTrue; - - var e = this.originalEvent; - if ( !e ) { - return; - } - // if stopPropagation exists run it on the original event - if ( e.stopPropagation ) { - e.stopPropagation(); - } - // otherwise set the cancelBubble property of the original event to true (IE) - e.cancelBubble = true; - }, - stopImmediatePropagation: function() { - this.isImmediatePropagationStopped = returnTrue; - this.stopPropagation(); - }, - isDefaultPrevented: returnFalse, - isPropagationStopped: returnFalse, - isImmediatePropagationStopped: returnFalse -}; - -// Create mouseenter/leave events using mouseover/out and event-time checks -jQuery.each({ - mouseenter: "mouseover", - mouseleave: "mouseout" -}, function( orig, fix ) { - jQuery.event.special[ orig ] = { - delegateType: fix, - bindType: fix, - - handle: function( event ) { - var target = this, - related = event.relatedTarget, - handleObj = event.handleObj, - selector = handleObj.selector, - ret; - - // For mousenter/leave call the handler if related is outside the target. - // NB: No relatedTarget if the mouse left/entered the browser window - if ( !related || (related !== target && !jQuery.contains( target, related )) ) { - event.type = handleObj.origType; - ret = handleObj.handler.apply( this, arguments ); - event.type = fix; - } - return ret; - } - }; -}); - -// IE submit delegation -if ( !jQuery.support.submitBubbles ) { - - jQuery.event.special.submit = { - setup: function() { - // Only need this for delegated form submit events - if ( jQuery.nodeName( this, "form" ) ) { - return false; - } - - // Lazy-add a submit handler when a descendant form may potentially be submitted - jQuery.event.add( this, "click._submit keypress._submit", function( e ) { - // Node name check avoids a VML-related crash in IE (#9807) - var elem = e.target, - form = jQuery.nodeName( elem, "input" ) || jQuery.nodeName( elem, "button" ) ? elem.form : undefined; - if ( form && !form._submit_attached ) { - jQuery.event.add( form, "submit._submit", function( event ) { - // If form was submitted by the user, bubble the event up the tree - if ( this.parentNode && !event.isTrigger ) { - jQuery.event.simulate( "submit", this.parentNode, event, true ); - } - }); - form._submit_attached = true; - } - }); - // return undefined since we don't need an event listener - }, - - teardown: function() { - // Only need this for delegated form submit events - if ( jQuery.nodeName( this, "form" ) ) { - return false; - } - - // Remove delegated handlers; cleanData eventually reaps submit handlers attached above - jQuery.event.remove( this, "._submit" ); - } - }; -} - -// IE change delegation and checkbox/radio fix -if ( !jQuery.support.changeBubbles ) { - - jQuery.event.special.change = { - - setup: function() { - - if ( rformElems.test( this.nodeName ) ) { - // IE doesn't fire change on a check/radio until blur; trigger it on click - // after a propertychange. Eat the blur-change in special.change.handle. - // This still fires onchange a second time for check/radio after blur. - if ( this.type === "checkbox" || this.type === "radio" ) { - jQuery.event.add( this, "propertychange._change", function( event ) { - if ( event.originalEvent.propertyName === "checked" ) { - this._just_changed = true; - } - }); - jQuery.event.add( this, "click._change", function( event ) { - if ( this._just_changed && !event.isTrigger ) { - this._just_changed = false; - jQuery.event.simulate( "change", this, event, true ); - } - }); - } - return false; - } - // Delegated event; lazy-add a change handler on descendant inputs - jQuery.event.add( this, "beforeactivate._change", function( e ) { - var elem = e.target; - - if ( rformElems.test( elem.nodeName ) && !elem._change_attached ) { - jQuery.event.add( elem, "change._change", function( event ) { - if ( this.parentNode && !event.isSimulated && !event.isTrigger ) { - jQuery.event.simulate( "change", this.parentNode, event, true ); - } - }); - elem._change_attached = true; - } - }); - }, - - handle: function( event ) { - var elem = event.target; - - // Swallow native change events from checkbox/radio, we already triggered them above - if ( this !== elem || event.isSimulated || event.isTrigger || (elem.type !== "radio" && elem.type !== "checkbox") ) { - return event.handleObj.handler.apply( this, arguments ); - } - }, - - teardown: function() { - jQuery.event.remove( this, "._change" ); - - return rformElems.test( this.nodeName ); - } - }; -} - -// Create "bubbling" focus and blur events -if ( !jQuery.support.focusinBubbles ) { - jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) { - - // Attach a single capturing handler while someone wants focusin/focusout - var attaches = 0, - handler = function( event ) { - jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ), true ); - }; - - jQuery.event.special[ fix ] = { - setup: function() { - if ( attaches++ === 0 ) { - document.addEventListener( orig, handler, true ); - } - }, - teardown: function() { - if ( --attaches === 0 ) { - document.removeEventListener( orig, handler, true ); - } - } - }; - }); -} - -jQuery.fn.extend({ - - on: function( types, selector, data, fn, /*INTERNAL*/ one ) { - var origFn, type; - - // Types can be a map of types/handlers - if ( typeof types === "object" ) { - // ( types-Object, selector, data ) - if ( typeof selector !== "string" ) { - // ( types-Object, data ) - data = selector; - selector = undefined; - } - for ( type in types ) { - this.on( type, selector, data, types[ type ], one ); - } - return this; - } - - if ( data == null && fn == null ) { - // ( types, fn ) - fn = selector; - data = selector = undefined; - } else if ( fn == null ) { - if ( typeof selector === "string" ) { - // ( types, selector, fn ) - fn = data; - data = undefined; - } else { - // ( types, data, fn ) - fn = data; - data = selector; - selector = undefined; - } - } - if ( fn === false ) { - fn = returnFalse; - } else if ( !fn ) { - return this; - } - - if ( one === 1 ) { - origFn = fn; - fn = function( event ) { - // Can use an empty set, since event contains the info - jQuery().off( event ); - return origFn.apply( this, arguments ); - }; - // Use same guid so caller can remove using origFn - fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ ); - } - return this.each( function() { - jQuery.event.add( this, types, fn, data, selector ); - }); - }, - one: function( types, selector, data, fn ) { - return this.on.call( this, types, selector, data, fn, 1 ); - }, - off: function( types, selector, fn ) { - if ( types && types.preventDefault && types.handleObj ) { - // ( event ) dispatched jQuery.Event - var handleObj = types.handleObj; - jQuery( types.delegateTarget ).off( - handleObj.namespace? handleObj.type + "." + handleObj.namespace : handleObj.type, - handleObj.selector, - handleObj.handler - ); - return this; - } - if ( typeof types === "object" ) { - // ( types-object [, selector] ) - for ( var type in types ) { - this.off( type, selector, types[ type ] ); - } - return this; - } - if ( selector === false || typeof selector === "function" ) { - // ( types [, fn] ) - fn = selector; - selector = undefined; - } - if ( fn === false ) { - fn = returnFalse; - } - return this.each(function() { - jQuery.event.remove( this, types, fn, selector ); - }); - }, - - bind: function( types, data, fn ) { - return this.on( types, null, data, fn ); - }, - unbind: function( types, fn ) { - return this.off( types, null, fn ); - }, - - live: function( types, data, fn ) { - jQuery( this.context ).on( types, this.selector, data, fn ); - return this; - }, - die: function( types, fn ) { - jQuery( this.context ).off( types, this.selector || "**", fn ); - return this; - }, - - delegate: function( selector, types, data, fn ) { - return this.on( types, selector, data, fn ); - }, - undelegate: function( selector, types, fn ) { - // ( namespace ) or ( selector, types [, fn] ) - return arguments.length == 1? this.off( selector, "**" ) : this.off( types, selector, fn ); - }, - - trigger: function( type, data ) { - return this.each(function() { - jQuery.event.trigger( type, data, this ); - }); - }, - triggerHandler: function( type, data ) { - if ( this[0] ) { - return jQuery.event.trigger( type, data, this[0], true ); - } - }, - - toggle: function( fn ) { - // Save reference to arguments for access in closure - var args = arguments, - guid = fn.guid || jQuery.guid++, - i = 0, - toggler = function( event ) { - // Figure out which function to execute - var lastToggle = ( jQuery._data( this, "lastToggle" + fn.guid ) || 0 ) % i; - jQuery._data( this, "lastToggle" + fn.guid, lastToggle + 1 ); - - // Make sure that clicks stop - event.preventDefault(); - - // and execute the function - return args[ lastToggle ].apply( this, arguments ) || false; - }; - - // link all the functions, so any of them can unbind this click handler - toggler.guid = guid; - while ( i < args.length ) { - args[ i++ ].guid = guid; - } - - return this.click( toggler ); - }, - - hover: function( fnOver, fnOut ) { - return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver ); - } -}); - -jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " + - "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " + - "change select submit keydown keypress keyup error contextmenu").split(" "), function( i, name ) { - - // Handle event binding - jQuery.fn[ name ] = function( data, fn ) { - if ( fn == null ) { - fn = data; - data = null; - } - - return arguments.length > 0 ? - this.on( name, null, data, fn ) : - this.trigger( name ); - }; - - if ( jQuery.attrFn ) { - jQuery.attrFn[ name ] = true; - } - - if ( rkeyEvent.test( name ) ) { - jQuery.event.fixHooks[ name ] = jQuery.event.keyHooks; - } - - if ( rmouseEvent.test( name ) ) { - jQuery.event.fixHooks[ name ] = jQuery.event.mouseHooks; - } -}); - - - -/*! - * Sizzle CSS Selector Engine - * Copyright 2011, The Dojo Foundation - * Released under the MIT, BSD, and GPL Licenses. - * More information: http://sizzlejs.com/ - */ -(function(){ - -var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g, - expando = "sizcache" + (Math.random() + '').replace('.', ''), - done = 0, - toString = Object.prototype.toString, - hasDuplicate = false, - baseHasDuplicate = true, - rBackslash = /\\/g, - rReturn = /\r\n/g, - rNonWord = /\W/; - -// Here we check if the JavaScript engine is using some sort of -// optimization where it does not always call our comparision -// function. If that is the case, discard the hasDuplicate value. -// Thus far that includes Google Chrome. -[0, 0].sort(function() { - baseHasDuplicate = false; - return 0; -}); - -var Sizzle = function( selector, context, results, seed ) { - results = results || []; - context = context || document; - - var origContext = context; - - if ( context.nodeType !== 1 && context.nodeType !== 9 ) { - return []; - } - - if ( !selector || typeof selector !== "string" ) { - return results; - } - - var m, set, checkSet, extra, ret, cur, pop, i, - prune = true, - contextXML = Sizzle.isXML( context ), - parts = [], - soFar = selector; - - // Reset the position of the chunker regexp (start from head) - do { - chunker.exec( "" ); - m = chunker.exec( soFar ); - - if ( m ) { - soFar = m[3]; - - parts.push( m[1] ); - - if ( m[2] ) { - extra = m[3]; - break; - } - } - } while ( m ); - - if ( parts.length > 1 && origPOS.exec( selector ) ) { - - if ( parts.length === 2 && Expr.relative[ parts[0] ] ) { - set = posProcess( parts[0] + parts[1], context, seed ); - - } else { - set = Expr.relative[ parts[0] ] ? - [ context ] : - Sizzle( parts.shift(), context ); - - while ( parts.length ) { - selector = parts.shift(); - - if ( Expr.relative[ selector ] ) { - selector += parts.shift(); - } - - set = posProcess( selector, set, seed ); - } - } - - } else { - // Take a shortcut and set the context if the root selector is an ID - // (but not if it'll be faster if the inner selector is an ID) - if ( !seed && parts.length > 1 && context.nodeType === 9 && !contextXML && - Expr.match.ID.test(parts[0]) && !Expr.match.ID.test(parts[parts.length - 1]) ) { - - ret = Sizzle.find( parts.shift(), context, contextXML ); - context = ret.expr ? - Sizzle.filter( ret.expr, ret.set )[0] : - ret.set[0]; - } - - if ( context ) { - ret = seed ? - { expr: parts.pop(), set: makeArray(seed) } : - Sizzle.find( parts.pop(), parts.length === 1 && (parts[0] === "~" || parts[0] === "+") && context.parentNode ? context.parentNode : context, contextXML ); - - set = ret.expr ? - Sizzle.filter( ret.expr, ret.set ) : - ret.set; - - if ( parts.length > 0 ) { - checkSet = makeArray( set ); - - } else { - prune = false; - } - - while ( parts.length ) { - cur = parts.pop(); - pop = cur; - - if ( !Expr.relative[ cur ] ) { - cur = ""; - } else { - pop = parts.pop(); - } - - if ( pop == null ) { - pop = context; - } - - Expr.relative[ cur ]( checkSet, pop, contextXML ); - } - - } else { - checkSet = parts = []; - } - } - - if ( !checkSet ) { - checkSet = set; - } - - if ( !checkSet ) { - Sizzle.error( cur || selector ); - } - - if ( toString.call(checkSet) === "[object Array]" ) { - if ( !prune ) { - results.push.apply( results, checkSet ); - - } else if ( context && context.nodeType === 1 ) { - for ( i = 0; checkSet[i] != null; i++ ) { - if ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && Sizzle.contains(context, checkSet[i])) ) { - results.push( set[i] ); - } - } - - } else { - for ( i = 0; checkSet[i] != null; i++ ) { - if ( checkSet[i] && checkSet[i].nodeType === 1 ) { - results.push( set[i] ); - } - } - } - - } else { - makeArray( checkSet, results ); - } - - if ( extra ) { - Sizzle( extra, origContext, results, seed ); - Sizzle.uniqueSort( results ); - } - - return results; -}; - -Sizzle.uniqueSort = function( results ) { - if ( sortOrder ) { - hasDuplicate = baseHasDuplicate; - results.sort( sortOrder ); - - if ( hasDuplicate ) { - for ( var i = 1; i < results.length; i++ ) { - if ( results[i] === results[ i - 1 ] ) { - results.splice( i--, 1 ); - } - } - } - } - - return results; -}; - -Sizzle.matches = function( expr, set ) { - return Sizzle( expr, null, null, set ); -}; - -Sizzle.matchesSelector = function( node, expr ) { - return Sizzle( expr, null, null, [node] ).length > 0; -}; - -Sizzle.find = function( expr, context, isXML ) { - var set, i, len, match, type, left; - - if ( !expr ) { - return []; - } - - for ( i = 0, len = Expr.order.length; i < len; i++ ) { - type = Expr.order[i]; - - if ( (match = Expr.leftMatch[ type ].exec( expr )) ) { - left = match[1]; - match.splice( 1, 1 ); - - if ( left.substr( left.length - 1 ) !== "\\" ) { - match[1] = (match[1] || "").replace( rBackslash, "" ); - set = Expr.find[ type ]( match, context, isXML ); - - if ( set != null ) { - expr = expr.replace( Expr.match[ type ], "" ); - break; - } - } - } - } - - if ( !set ) { - set = typeof context.getElementsByTagName !== "undefined" ? - context.getElementsByTagName( "*" ) : - []; - } - - return { set: set, expr: expr }; -}; - -Sizzle.filter = function( expr, set, inplace, not ) { - var match, anyFound, - type, found, item, filter, left, - i, pass, - old = expr, - result = [], - curLoop = set, - isXMLFilter = set && set[0] && Sizzle.isXML( set[0] ); - - while ( expr && set.length ) { - for ( type in Expr.filter ) { - if ( (match = Expr.leftMatch[ type ].exec( expr )) != null && match[2] ) { - filter = Expr.filter[ type ]; - left = match[1]; - - anyFound = false; - - match.splice(1,1); - - if ( left.substr( left.length - 1 ) === "\\" ) { - continue; - } - - if ( curLoop === result ) { - result = []; - } - - if ( Expr.preFilter[ type ] ) { - match = Expr.preFilter[ type ]( match, curLoop, inplace, result, not, isXMLFilter ); - - if ( !match ) { - anyFound = found = true; - - } else if ( match === true ) { - continue; - } - } - - if ( match ) { - for ( i = 0; (item = curLoop[i]) != null; i++ ) { - if ( item ) { - found = filter( item, match, i, curLoop ); - pass = not ^ found; - - if ( inplace && found != null ) { - if ( pass ) { - anyFound = true; - - } else { - curLoop[i] = false; - } - - } else if ( pass ) { - result.push( item ); - anyFound = true; - } - } - } - } - - if ( found !== undefined ) { - if ( !inplace ) { - curLoop = result; - } - - expr = expr.replace( Expr.match[ type ], "" ); - - if ( !anyFound ) { - return []; - } - - break; - } - } - } - - // Improper expression - if ( expr === old ) { - if ( anyFound == null ) { - Sizzle.error( expr ); - - } else { - break; - } - } - - old = expr; - } - - return curLoop; -}; - -Sizzle.error = function( msg ) { - throw new Error( "Syntax error, unrecognized expression: " + msg ); -}; - -/** - * Utility function for retreiving the text value of an array of DOM nodes - * @param {Array|Element} elem - */ -var getText = Sizzle.getText = function( elem ) { - var i, node, - nodeType = elem.nodeType, - ret = ""; - - if ( nodeType ) { - if ( nodeType === 1 || nodeType === 9 ) { - // Use textContent || innerText for elements - if ( typeof elem.textContent === 'string' ) { - return elem.textContent; - } else if ( typeof elem.innerText === 'string' ) { - // Replace IE's carriage returns - return elem.innerText.replace( rReturn, '' ); - } else { - // Traverse it's children - for ( elem = elem.firstChild; elem; elem = elem.nextSibling) { - ret += getText( elem ); - } - } - } else if ( nodeType === 3 || nodeType === 4 ) { - return elem.nodeValue; - } - } else { - - // If no nodeType, this is expected to be an array - for ( i = 0; (node = elem[i]); i++ ) { - // Do not traverse comment nodes - if ( node.nodeType !== 8 ) { - ret += getText( node ); - } - } - } - return ret; -}; - -var Expr = Sizzle.selectors = { - order: [ "ID", "NAME", "TAG" ], - - match: { - ID: /#((?:[\w\u00c0-\uFFFF\-]|\\.)+)/, - CLASS: /\.((?:[\w\u00c0-\uFFFF\-]|\\.)+)/, - NAME: /\[name=['"]*((?:[\w\u00c0-\uFFFF\-]|\\.)+)['"]*\]/, - ATTR: /\[\s*((?:[\w\u00c0-\uFFFF\-]|\\.)+)\s*(?:(\S?=)\s*(?:(['"])(.*?)\3|(#?(?:[\w\u00c0-\uFFFF\-]|\\.)*)|)|)\s*\]/, - TAG: /^((?:[\w\u00c0-\uFFFF\*\-]|\\.)+)/, - CHILD: /:(only|nth|last|first)-child(?:\(\s*(even|odd|(?:[+\-]?\d+|(?:[+\-]?\d*)?n\s*(?:[+\-]\s*\d+)?))\s*\))?/, - POS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^\-]|$)/, - PSEUDO: /:((?:[\w\u00c0-\uFFFF\-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/ - }, - - leftMatch: {}, - - attrMap: { - "class": "className", - "for": "htmlFor" - }, - - attrHandle: { - href: function( elem ) { - return elem.getAttribute( "href" ); - }, - type: function( elem ) { - return elem.getAttribute( "type" ); - } - }, - - relative: { - "+": function(checkSet, part){ - var isPartStr = typeof part === "string", - isTag = isPartStr && !rNonWord.test( part ), - isPartStrNotTag = isPartStr && !isTag; - - if ( isTag ) { - part = part.toLowerCase(); - } - - for ( var i = 0, l = checkSet.length, elem; i < l; i++ ) { - if ( (elem = checkSet[i]) ) { - while ( (elem = elem.previousSibling) && elem.nodeType !== 1 ) {} - - checkSet[i] = isPartStrNotTag || elem && elem.nodeName.toLowerCase() === part ? - elem || false : - elem === part; - } - } - - if ( isPartStrNotTag ) { - Sizzle.filter( part, checkSet, true ); - } - }, - - ">": function( checkSet, part ) { - var elem, - isPartStr = typeof part === "string", - i = 0, - l = checkSet.length; - - if ( isPartStr && !rNonWord.test( part ) ) { - part = part.toLowerCase(); - - for ( ; i < l; i++ ) { - elem = checkSet[i]; - - if ( elem ) { - var parent = elem.parentNode; - checkSet[i] = parent.nodeName.toLowerCase() === part ? parent : false; - } - } - - } else { - for ( ; i < l; i++ ) { - elem = checkSet[i]; - - if ( elem ) { - checkSet[i] = isPartStr ? - elem.parentNode : - elem.parentNode === part; - } - } - - if ( isPartStr ) { - Sizzle.filter( part, checkSet, true ); - } - } - }, - - "": function(checkSet, part, isXML){ - var nodeCheck, - doneName = done++, - checkFn = dirCheck; - - if ( typeof part === "string" && !rNonWord.test( part ) ) { - part = part.toLowerCase(); - nodeCheck = part; - checkFn = dirNodeCheck; - } - - checkFn( "parentNode", part, doneName, checkSet, nodeCheck, isXML ); - }, - - "~": function( checkSet, part, isXML ) { - var nodeCheck, - doneName = done++, - checkFn = dirCheck; - - if ( typeof part === "string" && !rNonWord.test( part ) ) { - part = part.toLowerCase(); - nodeCheck = part; - checkFn = dirNodeCheck; - } - - checkFn( "previousSibling", part, doneName, checkSet, nodeCheck, isXML ); - } - }, - - find: { - ID: function( match, context, isXML ) { - if ( typeof context.getElementById !== "undefined" && !isXML ) { - var m = context.getElementById(match[1]); - // Check parentNode to catch when Blackberry 4.6 returns - // nodes that are no longer in the document #6963 - return m && m.parentNode ? [m] : []; - } - }, - - NAME: function( match, context ) { - if ( typeof context.getElementsByName !== "undefined" ) { - var ret = [], - results = context.getElementsByName( match[1] ); - - for ( var i = 0, l = results.length; i < l; i++ ) { - if ( results[i].getAttribute("name") === match[1] ) { - ret.push( results[i] ); - } - } - - return ret.length === 0 ? null : ret; - } - }, - - TAG: function( match, context ) { - if ( typeof context.getElementsByTagName !== "undefined" ) { - return context.getElementsByTagName( match[1] ); - } - } - }, - preFilter: { - CLASS: function( match, curLoop, inplace, result, not, isXML ) { - match = " " + match[1].replace( rBackslash, "" ) + " "; - - if ( isXML ) { - return match; - } - - for ( var i = 0, elem; (elem = curLoop[i]) != null; i++ ) { - if ( elem ) { - if ( not ^ (elem.className && (" " + elem.className + " ").replace(/[\t\n\r]/g, " ").indexOf(match) >= 0) ) { - if ( !inplace ) { - result.push( elem ); - } - - } else if ( inplace ) { - curLoop[i] = false; - } - } - } - - return false; - }, - - ID: function( match ) { - return match[1].replace( rBackslash, "" ); - }, - - TAG: function( match, curLoop ) { - return match[1].replace( rBackslash, "" ).toLowerCase(); - }, - - CHILD: function( match ) { - if ( match[1] === "nth" ) { - if ( !match[2] ) { - Sizzle.error( match[0] ); - } - - match[2] = match[2].replace(/^\+|\s*/g, ''); - - // parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6' - var test = /(-?)(\d*)(?:n([+\-]?\d*))?/.exec( - match[2] === "even" && "2n" || match[2] === "odd" && "2n+1" || - !/\D/.test( match[2] ) && "0n+" + match[2] || match[2]); - - // calculate the numbers (first)n+(last) including if they are negative - match[2] = (test[1] + (test[2] || 1)) - 0; - match[3] = test[3] - 0; - } - else if ( match[2] ) { - Sizzle.error( match[0] ); - } - - // TODO: Move to normal caching system - match[0] = done++; - - return match; - }, - - ATTR: function( match, curLoop, inplace, result, not, isXML ) { - var name = match[1] = match[1].replace( rBackslash, "" ); - - if ( !isXML && Expr.attrMap[name] ) { - match[1] = Expr.attrMap[name]; - } - - // Handle if an un-quoted value was used - match[4] = ( match[4] || match[5] || "" ).replace( rBackslash, "" ); - - if ( match[2] === "~=" ) { - match[4] = " " + match[4] + " "; - } - - return match; - }, - - PSEUDO: function( match, curLoop, inplace, result, not ) { - if ( match[1] === "not" ) { - // If we're dealing with a complex expression, or a simple one - if ( ( chunker.exec(match[3]) || "" ).length > 1 || /^\w/.test(match[3]) ) { - match[3] = Sizzle(match[3], null, null, curLoop); - - } else { - var ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not); - - if ( !inplace ) { - result.push.apply( result, ret ); - } - - return false; - } - - } else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) { - return true; - } - - return match; - }, - - POS: function( match ) { - match.unshift( true ); - - return match; - } - }, - - filters: { - enabled: function( elem ) { - return elem.disabled === false && elem.type !== "hidden"; - }, - - disabled: function( elem ) { - return elem.disabled === true; - }, - - checked: function( elem ) { - return elem.checked === true; - }, - - selected: function( elem ) { - // Accessing this property makes selected-by-default - // options in Safari work properly - if ( elem.parentNode ) { - elem.parentNode.selectedIndex; - } - - return elem.selected === true; - }, - - parent: function( elem ) { - return !!elem.firstChild; - }, - - empty: function( elem ) { - return !elem.firstChild; - }, - - has: function( elem, i, match ) { - return !!Sizzle( match[3], elem ).length; - }, - - header: function( elem ) { - return (/h\d/i).test( elem.nodeName ); - }, - - text: function( elem ) { - var attr = elem.getAttribute( "type" ), type = elem.type; - // IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc) - // use getAttribute instead to test this case - return elem.nodeName.toLowerCase() === "input" && "text" === type && ( attr === type || attr === null ); - }, - - radio: function( elem ) { - return elem.nodeName.toLowerCase() === "input" && "radio" === elem.type; - }, - - checkbox: function( elem ) { - return elem.nodeName.toLowerCase() === "input" && "checkbox" === elem.type; - }, - - file: function( elem ) { - return elem.nodeName.toLowerCase() === "input" && "file" === elem.type; - }, - - password: function( elem ) { - return elem.nodeName.toLowerCase() === "input" && "password" === elem.type; - }, - - submit: function( elem ) { - var name = elem.nodeName.toLowerCase(); - return (name === "input" || name === "button") && "submit" === elem.type; - }, - - image: function( elem ) { - return elem.nodeName.toLowerCase() === "input" && "image" === elem.type; - }, - - reset: function( elem ) { - var name = elem.nodeName.toLowerCase(); - return (name === "input" || name === "button") && "reset" === elem.type; - }, - - button: function( elem ) { - var name = elem.nodeName.toLowerCase(); - return name === "input" && "button" === elem.type || name === "button"; - }, - - input: function( elem ) { - return (/input|select|textarea|button/i).test( elem.nodeName ); - }, - - focus: function( elem ) { - return elem === elem.ownerDocument.activeElement; - } - }, - setFilters: { - first: function( elem, i ) { - return i === 0; - }, - - last: function( elem, i, match, array ) { - return i === array.length - 1; - }, - - even: function( elem, i ) { - return i % 2 === 0; - }, - - odd: function( elem, i ) { - return i % 2 === 1; - }, - - lt: function( elem, i, match ) { - return i < match[3] - 0; - }, - - gt: function( elem, i, match ) { - return i > match[3] - 0; - }, - - nth: function( elem, i, match ) { - return match[3] - 0 === i; - }, - - eq: function( elem, i, match ) { - return match[3] - 0 === i; - } - }, - filter: { - PSEUDO: function( elem, match, i, array ) { - var name = match[1], - filter = Expr.filters[ name ]; - - if ( filter ) { - return filter( elem, i, match, array ); - - } else if ( name === "contains" ) { - return (elem.textContent || elem.innerText || getText([ elem ]) || "").indexOf(match[3]) >= 0; - - } else if ( name === "not" ) { - var not = match[3]; - - for ( var j = 0, l = not.length; j < l; j++ ) { - if ( not[j] === elem ) { - return false; - } - } - - return true; - - } else { - Sizzle.error( name ); - } - }, - - CHILD: function( elem, match ) { - var first, last, - doneName, parent, cache, - count, diff, - type = match[1], - node = elem; - - switch ( type ) { - case "only": - case "first": - while ( (node = node.previousSibling) ) { - if ( node.nodeType === 1 ) { - return false; - } - } - - if ( type === "first" ) { - return true; - } - - node = elem; - - case "last": - while ( (node = node.nextSibling) ) { - if ( node.nodeType === 1 ) { - return false; - } - } - - return true; - - case "nth": - first = match[2]; - last = match[3]; - - if ( first === 1 && last === 0 ) { - return true; - } - - doneName = match[0]; - parent = elem.parentNode; - - if ( parent && (parent[ expando ] !== doneName || !elem.nodeIndex) ) { - count = 0; - - for ( node = parent.firstChild; node; node = node.nextSibling ) { - if ( node.nodeType === 1 ) { - node.nodeIndex = ++count; - } - } - - parent[ expando ] = doneName; - } - - diff = elem.nodeIndex - last; - - if ( first === 0 ) { - return diff === 0; - - } else { - return ( diff % first === 0 && diff / first >= 0 ); - } - } - }, - - ID: function( elem, match ) { - return elem.nodeType === 1 && elem.getAttribute("id") === match; - }, - - TAG: function( elem, match ) { - return (match === "*" && elem.nodeType === 1) || !!elem.nodeName && elem.nodeName.toLowerCase() === match; - }, - - CLASS: function( elem, match ) { - return (" " + (elem.className || elem.getAttribute("class")) + " ") - .indexOf( match ) > -1; - }, - - ATTR: function( elem, match ) { - var name = match[1], - result = Sizzle.attr ? - Sizzle.attr( elem, name ) : - Expr.attrHandle[ name ] ? - Expr.attrHandle[ name ]( elem ) : - elem[ name ] != null ? - elem[ name ] : - elem.getAttribute( name ), - value = result + "", - type = match[2], - check = match[4]; - - return result == null ? - type === "!=" : - !type && Sizzle.attr ? - result != null : - type === "=" ? - value === check : - type === "*=" ? - value.indexOf(check) >= 0 : - type === "~=" ? - (" " + value + " ").indexOf(check) >= 0 : - !check ? - value && result !== false : - type === "!=" ? - value !== check : - type === "^=" ? - value.indexOf(check) === 0 : - type === "$=" ? - value.substr(value.length - check.length) === check : - type === "|=" ? - value === check || value.substr(0, check.length + 1) === check + "-" : - false; - }, - - POS: function( elem, match, i, array ) { - var name = match[2], - filter = Expr.setFilters[ name ]; - - if ( filter ) { - return filter( elem, i, match, array ); - } - } - } -}; - -var origPOS = Expr.match.POS, - fescape = function(all, num){ - return "\\" + (num - 0 + 1); - }; - -for ( var type in Expr.match ) { - Expr.match[ type ] = new RegExp( Expr.match[ type ].source + (/(?![^\[]*\])(?![^\(]*\))/.source) ); - Expr.leftMatch[ type ] = new RegExp( /(^(?:.|\r|\n)*?)/.source + Expr.match[ type ].source.replace(/\\(\d+)/g, fescape) ); -} - -var makeArray = function( array, results ) { - array = Array.prototype.slice.call( array, 0 ); - - if ( results ) { - results.push.apply( results, array ); - return results; - } - - return array; -}; - -// Perform a simple check to determine if the browser is capable of -// converting a NodeList to an array using builtin methods. -// Also verifies that the returned array holds DOM nodes -// (which is not the case in the Blackberry browser) -try { - Array.prototype.slice.call( document.documentElement.childNodes, 0 )[0].nodeType; - -// Provide a fallback method if it does not work -} catch( e ) { - makeArray = function( array, results ) { - var i = 0, - ret = results || []; - - if ( toString.call(array) === "[object Array]" ) { - Array.prototype.push.apply( ret, array ); - - } else { - if ( typeof array.length === "number" ) { - for ( var l = array.length; i < l; i++ ) { - ret.push( array[i] ); - } - - } else { - for ( ; array[i]; i++ ) { - ret.push( array[i] ); - } - } - } - - return ret; - }; -} - -var sortOrder, siblingCheck; - -if ( document.documentElement.compareDocumentPosition ) { - sortOrder = function( a, b ) { - if ( a === b ) { - hasDuplicate = true; - return 0; - } - - if ( !a.compareDocumentPosition || !b.compareDocumentPosition ) { - return a.compareDocumentPosition ? -1 : 1; - } - - return a.compareDocumentPosition(b) & 4 ? -1 : 1; - }; - -} else { - sortOrder = function( a, b ) { - // The nodes are identical, we can exit early - if ( a === b ) { - hasDuplicate = true; - return 0; - - // Fallback to using sourceIndex (in IE) if it's available on both nodes - } else if ( a.sourceIndex && b.sourceIndex ) { - return a.sourceIndex - b.sourceIndex; - } - - var al, bl, - ap = [], - bp = [], - aup = a.parentNode, - bup = b.parentNode, - cur = aup; - - // If the nodes are siblings (or identical) we can do a quick check - if ( aup === bup ) { - return siblingCheck( a, b ); - - // If no parents were found then the nodes are disconnected - } else if ( !aup ) { - return -1; - - } else if ( !bup ) { - return 1; - } - - // Otherwise they're somewhere else in the tree so we need - // to build up a full list of the parentNodes for comparison - while ( cur ) { - ap.unshift( cur ); - cur = cur.parentNode; - } - - cur = bup; - - while ( cur ) { - bp.unshift( cur ); - cur = cur.parentNode; - } - - al = ap.length; - bl = bp.length; - - // Start walking down the tree looking for a discrepancy - for ( var i = 0; i < al && i < bl; i++ ) { - if ( ap[i] !== bp[i] ) { - return siblingCheck( ap[i], bp[i] ); - } - } - - // We ended someplace up the tree so do a sibling check - return i === al ? - siblingCheck( a, bp[i], -1 ) : - siblingCheck( ap[i], b, 1 ); - }; - - siblingCheck = function( a, b, ret ) { - if ( a === b ) { - return ret; - } - - var cur = a.nextSibling; - - while ( cur ) { - if ( cur === b ) { - return -1; - } - - cur = cur.nextSibling; - } - - return 1; - }; -} - -// Check to see if the browser returns elements by name when -// querying by getElementById (and provide a workaround) -(function(){ - // We're going to inject a fake input element with a specified name - var form = document.createElement("div"), - id = "script" + (new Date()).getTime(), - root = document.documentElement; - - form.innerHTML = ""; - - // Inject it into the root element, check its status, and remove it quickly - root.insertBefore( form, root.firstChild ); - - // The workaround has to do additional checks after a getElementById - // Which slows things down for other browsers (hence the branching) - if ( document.getElementById( id ) ) { - Expr.find.ID = function( match, context, isXML ) { - if ( typeof context.getElementById !== "undefined" && !isXML ) { - var m = context.getElementById(match[1]); - - return m ? - m.id === match[1] || typeof m.getAttributeNode !== "undefined" && m.getAttributeNode("id").nodeValue === match[1] ? - [m] : - undefined : - []; - } - }; - - Expr.filter.ID = function( elem, match ) { - var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id"); - - return elem.nodeType === 1 && node && node.nodeValue === match; - }; - } - - root.removeChild( form ); - - // release memory in IE - root = form = null; -})(); - -(function(){ - // Check to see if the browser returns only elements - // when doing getElementsByTagName("*") - - // Create a fake element - var div = document.createElement("div"); - div.appendChild( document.createComment("") ); - - // Make sure no comments are found - if ( div.getElementsByTagName("*").length > 0 ) { - Expr.find.TAG = function( match, context ) { - var results = context.getElementsByTagName( match[1] ); - - // Filter out possible comments - if ( match[1] === "*" ) { - var tmp = []; - - for ( var i = 0; results[i]; i++ ) { - if ( results[i].nodeType === 1 ) { - tmp.push( results[i] ); - } - } - - results = tmp; - } - - return results; - }; - } - - // Check to see if an attribute returns normalized href attributes - div.innerHTML = ""; - - if ( div.firstChild && typeof div.firstChild.getAttribute !== "undefined" && - div.firstChild.getAttribute("href") !== "#" ) { - - Expr.attrHandle.href = function( elem ) { - return elem.getAttribute( "href", 2 ); - }; - } - - // release memory in IE - div = null; -})(); - -if ( document.querySelectorAll ) { - (function(){ - var oldSizzle = Sizzle, - div = document.createElement("div"), - id = "__sizzle__"; - - div.innerHTML = "

"; - - // Safari can't handle uppercase or unicode characters when - // in quirks mode. - if ( div.querySelectorAll && div.querySelectorAll(".TEST").length === 0 ) { - return; - } - - Sizzle = function( query, context, extra, seed ) { - context = context || document; - - // Only use querySelectorAll on non-XML documents - // (ID selectors don't work in non-HTML documents) - if ( !seed && !Sizzle.isXML(context) ) { - // See if we find a selector to speed up - var match = /^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec( query ); - - if ( match && (context.nodeType === 1 || context.nodeType === 9) ) { - // Speed-up: Sizzle("TAG") - if ( match[1] ) { - return makeArray( context.getElementsByTagName( query ), extra ); - - // Speed-up: Sizzle(".CLASS") - } else if ( match[2] && Expr.find.CLASS && context.getElementsByClassName ) { - return makeArray( context.getElementsByClassName( match[2] ), extra ); - } - } - - if ( context.nodeType === 9 ) { - // Speed-up: Sizzle("body") - // The body element only exists once, optimize finding it - if ( query === "body" && context.body ) { - return makeArray( [ context.body ], extra ); - - // Speed-up: Sizzle("#ID") - } else if ( match && match[3] ) { - var elem = context.getElementById( match[3] ); - - // Check parentNode to catch when Blackberry 4.6 returns - // nodes that are no longer in the document #6963 - if ( elem && elem.parentNode ) { - // Handle the case where IE and Opera return items - // by name instead of ID - if ( elem.id === match[3] ) { - return makeArray( [ elem ], extra ); - } - - } else { - return makeArray( [], extra ); - } - } - - try { - return makeArray( context.querySelectorAll(query), extra ); - } catch(qsaError) {} - - // qSA works strangely on Element-rooted queries - // We can work around this by specifying an extra ID on the root - // and working up from there (Thanks to Andrew Dupont for the technique) - // IE 8 doesn't work on object elements - } else if ( context.nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) { - var oldContext = context, - old = context.getAttribute( "id" ), - nid = old || id, - hasParent = context.parentNode, - relativeHierarchySelector = /^\s*[+~]/.test( query ); - - if ( !old ) { - context.setAttribute( "id", nid ); - } else { - nid = nid.replace( /'/g, "\\$&" ); - } - if ( relativeHierarchySelector && hasParent ) { - context = context.parentNode; - } - - try { - if ( !relativeHierarchySelector || hasParent ) { - return makeArray( context.querySelectorAll( "[id='" + nid + "'] " + query ), extra ); - } - - } catch(pseudoError) { - } finally { - if ( !old ) { - oldContext.removeAttribute( "id" ); - } - } - } - } - - return oldSizzle(query, context, extra, seed); - }; - - for ( var prop in oldSizzle ) { - Sizzle[ prop ] = oldSizzle[ prop ]; - } - - // release memory in IE - div = null; - })(); -} - -(function(){ - var html = document.documentElement, - matches = html.matchesSelector || html.mozMatchesSelector || html.webkitMatchesSelector || html.msMatchesSelector; - - if ( matches ) { - // Check to see if it's possible to do matchesSelector - // on a disconnected node (IE 9 fails this) - var disconnectedMatch = !matches.call( document.createElement( "div" ), "div" ), - pseudoWorks = false; - - try { - // This should fail with an exception - // Gecko does not error, returns false instead - matches.call( document.documentElement, "[test!='']:sizzle" ); - - } catch( pseudoError ) { - pseudoWorks = true; - } - - Sizzle.matchesSelector = function( node, expr ) { - // Make sure that attribute selectors are quoted - expr = expr.replace(/\=\s*([^'"\]]*)\s*\]/g, "='$1']"); - - if ( !Sizzle.isXML( node ) ) { - try { - if ( pseudoWorks || !Expr.match.PSEUDO.test( expr ) && !/!=/.test( expr ) ) { - var ret = matches.call( node, expr ); - - // IE 9's matchesSelector returns false on disconnected nodes - if ( ret || !disconnectedMatch || - // As well, disconnected nodes are said to be in a document - // fragment in IE 9, so check for that - node.document && node.document.nodeType !== 11 ) { - return ret; - } - } - } catch(e) {} - } - - return Sizzle(expr, null, null, [node]).length > 0; - }; - } -})(); - -(function(){ - var div = document.createElement("div"); - - div.innerHTML = "
"; - - // Opera can't find a second classname (in 9.6) - // Also, make sure that getElementsByClassName actually exists - if ( !div.getElementsByClassName || div.getElementsByClassName("e").length === 0 ) { - return; - } - - // Safari caches class attributes, doesn't catch changes (in 3.2) - div.lastChild.className = "e"; - - if ( div.getElementsByClassName("e").length === 1 ) { - return; - } - - Expr.order.splice(1, 0, "CLASS"); - Expr.find.CLASS = function( match, context, isXML ) { - if ( typeof context.getElementsByClassName !== "undefined" && !isXML ) { - return context.getElementsByClassName(match[1]); - } - }; - - // release memory in IE - div = null; -})(); - -function dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) { - for ( var i = 0, l = checkSet.length; i < l; i++ ) { - var elem = checkSet[i]; - - if ( elem ) { - var match = false; - - elem = elem[dir]; - - while ( elem ) { - if ( elem[ expando ] === doneName ) { - match = checkSet[elem.sizset]; - break; - } - - if ( elem.nodeType === 1 && !isXML ){ - elem[ expando ] = doneName; - elem.sizset = i; - } - - if ( elem.nodeName.toLowerCase() === cur ) { - match = elem; - break; - } - - elem = elem[dir]; - } - - checkSet[i] = match; - } - } -} - -function dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) { - for ( var i = 0, l = checkSet.length; i < l; i++ ) { - var elem = checkSet[i]; - - if ( elem ) { - var match = false; - - elem = elem[dir]; - - while ( elem ) { - if ( elem[ expando ] === doneName ) { - match = checkSet[elem.sizset]; - break; - } - - if ( elem.nodeType === 1 ) { - if ( !isXML ) { - elem[ expando ] = doneName; - elem.sizset = i; - } - - if ( typeof cur !== "string" ) { - if ( elem === cur ) { - match = true; - break; - } - - } else if ( Sizzle.filter( cur, [elem] ).length > 0 ) { - match = elem; - break; - } - } - - elem = elem[dir]; - } - - checkSet[i] = match; - } - } -} - -if ( document.documentElement.contains ) { - Sizzle.contains = function( a, b ) { - return a !== b && (a.contains ? a.contains(b) : true); - }; - -} else if ( document.documentElement.compareDocumentPosition ) { - Sizzle.contains = function( a, b ) { - return !!(a.compareDocumentPosition(b) & 16); - }; - -} else { - Sizzle.contains = function() { - return false; - }; -} - -Sizzle.isXML = function( elem ) { - // documentElement is verified for cases where it doesn't yet exist - // (such as loading iframes in IE - #4833) - var documentElement = (elem ? elem.ownerDocument || elem : 0).documentElement; - - return documentElement ? documentElement.nodeName !== "HTML" : false; -}; - -var posProcess = function( selector, context, seed ) { - var match, - tmpSet = [], - later = "", - root = context.nodeType ? [context] : context; - - // Position selectors must be done after the filter - // And so must :not(positional) so we move all PSEUDOs to the end - while ( (match = Expr.match.PSEUDO.exec( selector )) ) { - later += match[0]; - selector = selector.replace( Expr.match.PSEUDO, "" ); - } - - selector = Expr.relative[selector] ? selector + "*" : selector; - - for ( var i = 0, l = root.length; i < l; i++ ) { - Sizzle( selector, root[i], tmpSet, seed ); - } - - return Sizzle.filter( later, tmpSet ); -}; - -// EXPOSE -// Override sizzle attribute retrieval -Sizzle.attr = jQuery.attr; -Sizzle.selectors.attrMap = {}; -jQuery.find = Sizzle; -jQuery.expr = Sizzle.selectors; -jQuery.expr[":"] = jQuery.expr.filters; -jQuery.unique = Sizzle.uniqueSort; -jQuery.text = Sizzle.getText; -jQuery.isXMLDoc = Sizzle.isXML; -jQuery.contains = Sizzle.contains; - - -})(); - - -var runtil = /Until$/, - rparentsprev = /^(?:parents|prevUntil|prevAll)/, - // Note: This RegExp should be improved, or likely pulled from Sizzle - rmultiselector = /,/, - isSimple = /^.[^:#\[\.,]*$/, - slice = Array.prototype.slice, - POS = jQuery.expr.match.POS, - // methods guaranteed to produce a unique set when starting from a unique set - guaranteedUnique = { - children: true, - contents: true, - next: true, - prev: true - }; - -jQuery.fn.extend({ - find: function( selector ) { - var self = this, - i, l; - - if ( typeof selector !== "string" ) { - return jQuery( selector ).filter(function() { - for ( i = 0, l = self.length; i < l; i++ ) { - if ( jQuery.contains( self[ i ], this ) ) { - return true; - } - } - }); - } - - var ret = this.pushStack( "", "find", selector ), - length, n, r; - - for ( i = 0, l = this.length; i < l; i++ ) { - length = ret.length; - jQuery.find( selector, this[i], ret ); - - if ( i > 0 ) { - // Make sure that the results are unique - for ( n = length; n < ret.length; n++ ) { - for ( r = 0; r < length; r++ ) { - if ( ret[r] === ret[n] ) { - ret.splice(n--, 1); - break; - } - } - } - } - } - - return ret; - }, - - has: function( target ) { - var targets = jQuery( target ); - return this.filter(function() { - for ( var i = 0, l = targets.length; i < l; i++ ) { - if ( jQuery.contains( this, targets[i] ) ) { - return true; - } - } - }); - }, - - not: function( selector ) { - return this.pushStack( winnow(this, selector, false), "not", selector); - }, - - filter: function( selector ) { - return this.pushStack( winnow(this, selector, true), "filter", selector ); - }, - - is: function( selector ) { - return !!selector && ( - typeof selector === "string" ? - // If this is a positional selector, check membership in the returned set - // so $("p:first").is("p:last") won't return true for a doc with two "p". - POS.test( selector ) ? - jQuery( selector, this.context ).index( this[0] ) >= 0 : - jQuery.filter( selector, this ).length > 0 : - this.filter( selector ).length > 0 ); - }, - - closest: function( selectors, context ) { - var ret = [], i, l, cur = this[0]; - - // Array (deprecated as of jQuery 1.7) - if ( jQuery.isArray( selectors ) ) { - var level = 1; - - while ( cur && cur.ownerDocument && cur !== context ) { - for ( i = 0; i < selectors.length; i++ ) { - - if ( jQuery( cur ).is( selectors[ i ] ) ) { - ret.push({ selector: selectors[ i ], elem: cur, level: level }); - } - } - - cur = cur.parentNode; - level++; - } - - return ret; - } - - // String - var pos = POS.test( selectors ) || typeof selectors !== "string" ? - jQuery( selectors, context || this.context ) : - 0; - - for ( i = 0, l = this.length; i < l; i++ ) { - cur = this[i]; - - while ( cur ) { - if ( pos ? pos.index(cur) > -1 : jQuery.find.matchesSelector(cur, selectors) ) { - ret.push( cur ); - break; - - } else { - cur = cur.parentNode; - if ( !cur || !cur.ownerDocument || cur === context || cur.nodeType === 11 ) { - break; - } - } - } - } - - ret = ret.length > 1 ? jQuery.unique( ret ) : ret; - - return this.pushStack( ret, "closest", selectors ); - }, - - // Determine the position of an element within - // the matched set of elements - index: function( elem ) { - - // No argument, return index in parent - if ( !elem ) { - return ( this[0] && this[0].parentNode ) ? this.prevAll().length : -1; - } - - // index in selector - if ( typeof elem === "string" ) { - return jQuery.inArray( this[0], jQuery( elem ) ); - } - - // Locate the position of the desired element - return jQuery.inArray( - // If it receives a jQuery object, the first element is used - elem.jquery ? elem[0] : elem, this ); - }, - - add: function( selector, context ) { - var set = typeof selector === "string" ? - jQuery( selector, context ) : - jQuery.makeArray( selector && selector.nodeType ? [ selector ] : selector ), - all = jQuery.merge( this.get(), set ); - - return this.pushStack( isDisconnected( set[0] ) || isDisconnected( all[0] ) ? - all : - jQuery.unique( all ) ); - }, - - andSelf: function() { - return this.add( this.prevObject ); - } -}); - -// A painfully simple check to see if an element is disconnected -// from a document (should be improved, where feasible). -function isDisconnected( node ) { - return !node || !node.parentNode || node.parentNode.nodeType === 11; -} - -jQuery.each({ - parent: function( elem ) { - var parent = elem.parentNode; - return parent && parent.nodeType !== 11 ? parent : null; - }, - parents: function( elem ) { - return jQuery.dir( elem, "parentNode" ); - }, - parentsUntil: function( elem, i, until ) { - return jQuery.dir( elem, "parentNode", until ); - }, - next: function( elem ) { - return jQuery.nth( elem, 2, "nextSibling" ); - }, - prev: function( elem ) { - return jQuery.nth( elem, 2, "previousSibling" ); - }, - nextAll: function( elem ) { - return jQuery.dir( elem, "nextSibling" ); - }, - prevAll: function( elem ) { - return jQuery.dir( elem, "previousSibling" ); - }, - nextUntil: function( elem, i, until ) { - return jQuery.dir( elem, "nextSibling", until ); - }, - prevUntil: function( elem, i, until ) { - return jQuery.dir( elem, "previousSibling", until ); - }, - siblings: function( elem ) { - return jQuery.sibling( elem.parentNode.firstChild, elem ); - }, - children: function( elem ) { - return jQuery.sibling( elem.firstChild ); - }, - contents: function( elem ) { - return jQuery.nodeName( elem, "iframe" ) ? - elem.contentDocument || elem.contentWindow.document : - jQuery.makeArray( elem.childNodes ); - } -}, function( name, fn ) { - jQuery.fn[ name ] = function( until, selector ) { - var ret = jQuery.map( this, fn, until ); - - if ( !runtil.test( name ) ) { - selector = until; - } - - if ( selector && typeof selector === "string" ) { - ret = jQuery.filter( selector, ret ); - } - - ret = this.length > 1 && !guaranteedUnique[ name ] ? jQuery.unique( ret ) : ret; - - if ( (this.length > 1 || rmultiselector.test( selector )) && rparentsprev.test( name ) ) { - ret = ret.reverse(); - } - - return this.pushStack( ret, name, slice.call( arguments ).join(",") ); - }; -}); - -jQuery.extend({ - filter: function( expr, elems, not ) { - if ( not ) { - expr = ":not(" + expr + ")"; - } - - return elems.length === 1 ? - jQuery.find.matchesSelector(elems[0], expr) ? [ elems[0] ] : [] : - jQuery.find.matches(expr, elems); - }, - - dir: function( elem, dir, until ) { - var matched = [], - cur = elem[ dir ]; - - while ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) { - if ( cur.nodeType === 1 ) { - matched.push( cur ); - } - cur = cur[dir]; - } - return matched; - }, - - nth: function( cur, result, dir, elem ) { - result = result || 1; - var num = 0; - - for ( ; cur; cur = cur[dir] ) { - if ( cur.nodeType === 1 && ++num === result ) { - break; - } - } - - return cur; - }, - - sibling: function( n, elem ) { - var r = []; - - for ( ; n; n = n.nextSibling ) { - if ( n.nodeType === 1 && n !== elem ) { - r.push( n ); - } - } - - return r; - } -}); - -// Implement the identical functionality for filter and not -function winnow( elements, qualifier, keep ) { - - // Can't pass null or undefined to indexOf in Firefox 4 - // Set to 0 to skip string check - qualifier = qualifier || 0; - - if ( jQuery.isFunction( qualifier ) ) { - return jQuery.grep(elements, function( elem, i ) { - var retVal = !!qualifier.call( elem, i, elem ); - return retVal === keep; - }); - - } else if ( qualifier.nodeType ) { - return jQuery.grep(elements, function( elem, i ) { - return ( elem === qualifier ) === keep; - }); - - } else if ( typeof qualifier === "string" ) { - var filtered = jQuery.grep(elements, function( elem ) { - return elem.nodeType === 1; - }); - - if ( isSimple.test( qualifier ) ) { - return jQuery.filter(qualifier, filtered, !keep); - } else { - qualifier = jQuery.filter( qualifier, filtered ); - } - } - - return jQuery.grep(elements, function( elem, i ) { - return ( jQuery.inArray( elem, qualifier ) >= 0 ) === keep; - }); -} - - - - -function createSafeFragment( document ) { - var list = nodeNames.split( "|" ), - safeFrag = document.createDocumentFragment(); - - if ( safeFrag.createElement ) { - while ( list.length ) { - safeFrag.createElement( - list.pop() - ); - } - } - return safeFrag; -} - -var nodeNames = "abbr|article|aside|audio|canvas|datalist|details|figcaption|figure|footer|" + - "header|hgroup|mark|meter|nav|output|progress|section|summary|time|video", - rinlinejQuery = / jQuery\d+="(?:\d+|null)"/g, - rleadingWhitespace = /^\s+/, - rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig, - rtagName = /<([\w:]+)/, - rtbody = /", "" ], - legend: [ 1, "
", "
" ], - thead: [ 1, "", "
" ], - tr: [ 2, "", "
" ], - td: [ 3, "", "
" ], - col: [ 2, "", "
" ], - area: [ 1, "", "" ], - _default: [ 0, "", "" ] - }, - safeFragment = createSafeFragment( document ); - -wrapMap.optgroup = wrapMap.option; -wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; -wrapMap.th = wrapMap.td; - -// IE can't serialize and