From 0d41aa77c951b9832bf55e3402a2b53057e58e72 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Arild=20M=C3=A6land?= Date: Fri, 15 Mar 2013 08:42:03 +0100 Subject: [PATCH 01/11] Add a .rspec file for colours and nested output --- GildedRose/ruby/.rspec | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 GildedRose/ruby/.rspec diff --git a/GildedRose/ruby/.rspec b/GildedRose/ruby/.rspec new file mode 100644 index 00000000..0d9a0dd8 --- /dev/null +++ b/GildedRose/ruby/.rspec @@ -0,0 +1,2 @@ +--colour +--format nested From c623ea5b2393c319afc2c8f2decf3e6cf52c0cc5 Mon Sep 17 00:00:00 2001 From: emilybache Date: Wed, 20 Mar 2013 08:14:18 +0100 Subject: [PATCH 02/11] minor text change --- GildedRose/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/GildedRose/README.md b/GildedRose/README.md index fbc25ad8..fba63187 100644 --- a/GildedRose/README.md +++ b/GildedRose/README.md @@ -10,7 +10,7 @@ You could write some unit tests yourself, using the requirements to identify sui Alternatively, use the "Text-Based" tests provided in this repository. (Read more about that in the next section) -I've also set this kata up on [cyber-dojo](http://cyber-dojo.com) in Java using both JUnit and Cucumber, so you can get going really quickly: +I've also set this kata up on [cyber-dojo](http://cyber-dojo.com), so you can get going really quickly for the following languages and test frameworks: - [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.com/forker/fork/751DD02C4C?avatar=snake&tag=4) From 0319c8a5f7e8bf7fb7bb1558716638703e62d9e6 Mon Sep 17 00:00:00 2001 From: emilybache Date: Wed, 20 Mar 2013 09:33:53 +0100 Subject: [PATCH 03/11] I changed the starting position for the C# version to match the other translations, especially the Java version. 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. It also makes it easier to do text-based approval testing with this code. --- GildedRose/csharp/ApprovalTest.cs | 28 +++++ GildedRose/csharp/GildedRose.cs | 100 ++++++++++++++++++ GildedRose/csharp/GildedRoseTest.cs | 19 ++++ GildedRose/csharp/Program.cs | 147 --------------------------- GildedRose/csharp/TextTestFixture.cs | 58 +++++++++++ GildedRose/texttests/config.gr | 2 +- 6 files changed, 206 insertions(+), 148 deletions(-) create mode 100644 GildedRose/csharp/ApprovalTest.cs create mode 100644 GildedRose/csharp/GildedRose.cs create mode 100644 GildedRose/csharp/GildedRoseTest.cs delete mode 100644 GildedRose/csharp/Program.cs create mode 100644 GildedRose/csharp/TextTestFixture.cs diff --git a/GildedRose/csharp/ApprovalTest.cs b/GildedRose/csharp/ApprovalTest.cs new file mode 100644 index 00000000..ad294419 --- /dev/null +++ b/GildedRose/csharp/ApprovalTest.cs @@ -0,0 +1,28 @@ +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/GildedRose/csharp/GildedRose.cs b/GildedRose/csharp/GildedRose.cs new file mode 100644 index 00000000..a0017b2e --- /dev/null +++ b/GildedRose/csharp/GildedRose.cs @@ -0,0 +1,100 @@ +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/GildedRose/csharp/GildedRoseTest.cs b/GildedRose/csharp/GildedRoseTest.cs new file mode 100644 index 00000000..02fd5b21 --- /dev/null +++ b/GildedRose/csharp/GildedRoseTest.cs @@ -0,0 +1,19 @@ +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/GildedRose/csharp/Program.cs b/GildedRose/csharp/Program.cs deleted file mode 100644 index 3ba8371e..00000000 --- a/GildedRose/csharp/Program.cs +++ /dev/null @@ -1,147 +0,0 @@ -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 = "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} - } - - }; - - 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(); - - } - - 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/GildedRose/csharp/TextTestFixture.cs b/GildedRose/csharp/TextTestFixture.cs new file mode 100644 index 00000000..3283aba9 --- /dev/null +++ b/GildedRose/csharp/TextTestFixture.cs @@ -0,0 +1,58 @@ +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(); + } + + } + + } +} diff --git a/GildedRose/texttests/config.gr b/GildedRose/texttests/config.gr index e7b88344..b301079d 100755 --- a/GildedRose/texttests/config.gr +++ b/GildedRose/texttests/config.gr @@ -20,7 +20,7 @@ interpreter:java #interpreter:ruby # Settings for the C# version -#executable:${TEXTTEST_CHECKOUT}/csharp/Program.exe +#executable:${TEXTTEST_CHECKOUT}/GildedRose.exe # turn on one of these if you prefer them to notepad or emacs. [view_program] From 21cc3a3e8522645db5e641871512d204ff984b93 Mon Sep 17 00:00:00 2001 From: emilybache Date: Wed, 20 Mar 2013 09:43:14 +0100 Subject: [PATCH 04/11] Updated the read me with a justification of why I changed the starting position for this kata. --- GildedRose/README.md | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/GildedRose/README.md b/GildedRose/README.md index 09d6f98e..1fc1be21 100644 --- a/GildedRose/README.md +++ b/GildedRose/README.md @@ -1,6 +1,12 @@ -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++. +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/). -See also 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/Refactoring-Katas/tree/master/GildedRose/texttests)) + +As Bobby Johnson points out in his [article](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. + +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). ## How to use this Kata @@ -19,8 +25,6 @@ I've also set this kata up on [cyber-dojo](http://cyber-dojo.com) for several la - [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) - - Whichever testing approach you choose, the idea of the exercise is to do some deliberate practice, and improve your skills at designing test cases and refactoring. The idea is not to re-write the code from scratch, but rather to practice designing tests, taking small steps, running the tests often, and incrementally improving the design. ## Text-Based Approval Testing From 5b90bc7d6a9ecbb6d2916ff13ef545bb4e1899c0 Mon Sep 17 00:00:00 2001 From: emilybache Date: Wed, 20 Mar 2013 09:46:57 +0100 Subject: [PATCH 05/11] Make instructions even clearer --- GildedRose/README.md | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/GildedRose/README.md b/GildedRose/README.md index 1fc1be21..39e1616e 100644 --- a/GildedRose/README.md +++ b/GildedRose/README.md @@ -2,11 +2,11 @@ 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/Refactoring-Katas/tree/master/GildedRose/texttests)) -As Bobby Johnson points out in his [article](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. -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://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). ## How to use this Kata @@ -16,15 +16,6 @@ You could write some unit tests yourself, using the requirements to identify sui Alternatively, use the "Text-Based" tests provided in this repository. (Read more about that in the next section) -I've also set this kata up on [cyber-dojo](http://cyber-dojo.com) for several languages, so you can get going really quickly: - -- [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.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) - Whichever testing approach you choose, the idea of the exercise is to do some deliberate practice, and improve your skills at designing test cases and refactoring. The idea is not to re-write the code from scratch, but rather to practice designing tests, taking small steps, running the tests often, and incrementally improving the design. ## Text-Based Approval Testing @@ -37,3 +28,13 @@ Typically a piece of legacy code may not produce suitable textual output from th 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. +## 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: + +- [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 From f95ce38b81f6f4bca3b8d8c9b1be5c39d8bc7978 Mon Sep 17 00:00:00 2001 From: Ian Date: Wed, 27 Mar 2013 10:20:59 +0000 Subject: [PATCH 06/11] Update the tests to work with the code that was changed in rev 4dab932c94f144fb4c49e68e53302a0c5065c0f4 to be more like the original c# --- GildedRose/ruby/texttest_fixture.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/GildedRose/ruby/texttest_fixture.rb b/GildedRose/ruby/texttest_fixture.rb index c639c06b..b9d26c28 100644 --- a/GildedRose/ruby/texttest_fixture.rb +++ b/GildedRose/ruby/texttest_fixture.rb @@ -21,7 +21,7 @@ if ARGV.size > 0 days = ARGV[0].to_i + 1 end -gilded_rose = GildedRose.new +gilded_rose = GildedRose.new items (0...days).each do |day| puts "-------- day #{day} --------" puts "name, sellIn, quality" @@ -29,5 +29,5 @@ gilded_rose = GildedRose.new puts item end puts "" - gilded_rose.update_quality(items) + gilded_rose.update_quality end From a2241624283ed1c60e199e1c2477f1832c30312a Mon Sep 17 00:00:00 2001 From: Ian Date: Wed, 27 Mar 2013 10:30:17 +0000 Subject: [PATCH 07/11] Update the tests to work with the code that was changed in rev 4dab932c94f144fb4c49e68e53302a0c5065c0f4 to be more like the original c# --- GildedRose/python/texttest_fixture.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/GildedRose/python/texttest_fixture.py b/GildedRose/python/texttest_fixture.py index de921093..f867345e 100644 --- a/GildedRose/python/texttest_fixture.py +++ b/GildedRose/python/texttest_fixture.py @@ -26,4 +26,4 @@ if __name__ == "__main__": for item in items: print(item) print("") - update_quality(items) + GildedRose(items).update_quality() From a2edc933256a5f75e044a34d7708a674653daa88 Mon Sep 17 00:00:00 2001 From: Ian Date: Wed, 27 Mar 2013 14:01:42 +0000 Subject: [PATCH 08/11] Remove the dependency on the CppUTestExt library as this doesn't seem to be built by the current CppUTest distribution. --- GildedRose/C/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/GildedRose/C/Makefile b/GildedRose/C/Makefile index 60d11871..3a695892 100644 --- a/GildedRose/C/Makefile +++ b/GildedRose/C/Makefile @@ -22,7 +22,7 @@ CPPFLAGS += -I$(CPPUTEST_HOME)/include # Flags passed to the C++ compiler. CFLAGS += -g -Wall -Wextra -LD_LIBRARIES = -L$(CPPUTEST_HOME)/lib -lCppUTest -lCppUTestExt +LD_LIBRARIES = -L$(CPPUTEST_HOME)/lib -lCppUTest # All tests produced by this Makefile. Remember to add new tests you # created to the list. From 71582701098b2c4b0fddccef0127a11b6e755a52 Mon Sep 17 00:00:00 2001 From: Ian Date: Wed, 27 Mar 2013 17:13:22 +0000 Subject: [PATCH 09/11] Re-introduce the com.gildedrose package for the Java example. Java isn't able to reference classes in the default packge, so if you're refactoring and putting your refactored code in packges, you can't refer back to the original code (i.e. Item) from them. Ensure the TextTest reference is also updated to the new location of the test. --- GildedRose/Java/{ => com/gildedrose}/GildedRose.java | 1 + GildedRose/Java/{ => com/gildedrose}/GildedRoseTest.java | 1 + GildedRose/Java/{ => com/gildedrose}/Item.java | 1 + GildedRose/Java/{ => com/gildedrose}/TexttestFixture.java | 1 + GildedRose/texttests/config.gr | 2 +- 5 files changed, 5 insertions(+), 1 deletion(-) rename GildedRose/Java/{ => com/gildedrose}/GildedRose.java (98%) rename GildedRose/Java/{ => com/gildedrose}/GildedRoseTest.java (92%) rename GildedRose/Java/{ => com/gildedrose}/Item.java (93%) rename GildedRose/Java/{ => com/gildedrose}/TexttestFixture.java (97%) diff --git a/GildedRose/Java/GildedRose.java b/GildedRose/Java/com/gildedrose/GildedRose.java similarity index 98% rename from GildedRose/Java/GildedRose.java rename to GildedRose/Java/com/gildedrose/GildedRose.java index 9f407310..8acc098d 100755 --- a/GildedRose/Java/GildedRose.java +++ b/GildedRose/Java/com/gildedrose/GildedRose.java @@ -1,3 +1,4 @@ +package com.gildedrose; class GildedRose { Item[] items; diff --git a/GildedRose/Java/GildedRoseTest.java b/GildedRose/Java/com/gildedrose/GildedRoseTest.java similarity index 92% rename from GildedRose/Java/GildedRoseTest.java rename to GildedRose/Java/com/gildedrose/GildedRoseTest.java index 6a21ee64..49517932 100644 --- a/GildedRose/Java/GildedRoseTest.java +++ b/GildedRose/Java/com/gildedrose/GildedRoseTest.java @@ -1,3 +1,4 @@ +package com.gildedrose; import static org.junit.Assert.*; import org.junit.Test; diff --git a/GildedRose/Java/Item.java b/GildedRose/Java/com/gildedrose/Item.java similarity index 93% rename from GildedRose/Java/Item.java rename to GildedRose/Java/com/gildedrose/Item.java index 8c846b45..779aad79 100755 --- a/GildedRose/Java/Item.java +++ b/GildedRose/Java/com/gildedrose/Item.java @@ -1,3 +1,4 @@ +package com.gildedrose; public class Item { public String name; diff --git a/GildedRose/Java/TexttestFixture.java b/GildedRose/Java/com/gildedrose/TexttestFixture.java similarity index 97% rename from GildedRose/Java/TexttestFixture.java rename to GildedRose/Java/com/gildedrose/TexttestFixture.java index 3f48d3aa..bd6a50ce 100755 --- a/GildedRose/Java/TexttestFixture.java +++ b/GildedRose/Java/com/gildedrose/TexttestFixture.java @@ -1,3 +1,4 @@ +package com.gildedrose; public class TexttestFixture { public static void main(String[] args) { diff --git a/GildedRose/texttests/config.gr b/GildedRose/texttests/config.gr index b301079d..e6cfd5c7 100755 --- a/GildedRose/texttests/config.gr +++ b/GildedRose/texttests/config.gr @@ -4,7 +4,7 @@ full_name:Gilded Rose Refactoring Kata default_checkout:/Users/emily/training_materials/Refactoring-Katas/GildedRose # Settings for the Java version -executable:TexttestFixture +executable:com.gildedrose.TexttestFixture interpreter:java # note you'll also need to update the file environment.gr with your classpath if you keep your classfiles somewhere unusual From 24d532ed94e75e7a8687b7996fc06fbe01f82fef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kim=20Persson=20and=20Lennart=20Frid=C3=A9n?= Date: Sun, 7 Apr 2013 12:48:32 +0200 Subject: [PATCH 10/11] Add Ruby version of the Yahtzee kata. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Lennart Fridén --- Yahtzee/README.md | 58 ++++---- Yahtzee/ruby/test_yahtzee.rb | 94 +++++++++++++ Yahtzee/ruby/yahtzee.rb | 256 +++++++++++++++++++++++++++++++++++ 3 files changed, 380 insertions(+), 28 deletions(-) create mode 100644 Yahtzee/ruby/test_yahtzee.rb create mode 100644 Yahtzee/ruby/yahtzee.rb diff --git a/Yahtzee/README.md b/Yahtzee/README.md index e861ff50..5f007080 100644 --- a/Yahtzee/README.md +++ b/Yahtzee/README.md @@ -6,6 +6,8 @@ The other language translations have been contributed by: Python: Emily Bache +Ruby: Kim Persson and Lennart Fridén + ## Kata: Yahtzee rules The game of yahtzee is a simple dice game. Each player @@ -28,7 +30,7 @@ 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. +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. @@ -37,78 +39,78 @@ 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. - + ## Kata: Yahzee Categories and Scoring Rules _Note these rules differ from the original (copyrighted) rules_ -Chance: +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) + 4,5,5,6,1 placed on "chance" scores 21 (4+5+5+6+1) -Yahtzee: +Yahtzee: If all dice have the same number, - the player scores 50 points. + 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, +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: +Pair: The player scores the sum of the two highest matching dice. - For example, when placed on "pair" + 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: +Two pairs: If there are two pairs of dice with the same number, the - player scores the sum of these dice. + 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: +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" + 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: +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" + 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 +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 +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: +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) + 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/ruby/test_yahtzee.rb b/Yahtzee/ruby/test_yahtzee.rb new file mode 100644 index 00000000..988c0f0d --- /dev/null +++ b/Yahtzee/ruby/test_yahtzee.rb @@ -0,0 +1,94 @@ +require_relative 'yahtzee' +require 'test/unit' + +class YahtzeeTest < Test::Unit::TestCase + 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) + end + + 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]) + end + + 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) + end + + def test_2s + assert Yahtzee.twos(1,2,3,2,6) == 4 + assert Yahtzee.twos(2,2,2,2,2) == 10 + end + + def test_threes + assert 6 == Yahtzee.threes(1,2,3,2,3) + assert 12 == Yahtzee.threes(2,3,3,3,3) + end + + def test_fours_test + assert 12 == Yahtzee.new(4,4,4,5,5).fours + assert 8 == Yahtzee.new(4,4,5,5,5).fours + assert 4 == Yahtzee.new(4,5,5,5,5).fours + end + + def test_fives() + assert 10 == Yahtzee.new(4,4,4,5,5).fives() + assert 15 == Yahtzee.new(4,4,5,5,5).fives() + assert 20 == Yahtzee.new(4,5,5,5,5).fives() + end + + def test_sixes_test + assert 0 == Yahtzee.new(4,4,4,5,5).sixes() + assert 6 == Yahtzee.new(4,4,6,5,5).sixes() + assert 18 == Yahtzee.new(6,5,6,6,5).sixes() + end + + 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) + end + + def test_two_Pair + assert_equal 16, Yahtzee.two_pair(3,3,5,4,5) + assert_equal 0, Yahtzee.two_pair(3,3,5,5,5) + end + + 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) + end + + 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) + end + + 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) + end + + 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) + end + + def test_fullHouse() + assert 18 == Yahtzee.fullHouse(6,2,2,2,6) + assert 0 == Yahtzee.fullHouse(2,3,4,5,6) + end +end diff --git a/Yahtzee/ruby/yahtzee.rb b/Yahtzee/ruby/yahtzee.rb new file mode 100644 index 00000000..462b0509 --- /dev/null +++ b/Yahtzee/ruby/yahtzee.rb @@ -0,0 +1,256 @@ +class Yahtzee + def self.chance(d1, d2, d3, d4, d5) + total = 0 + total += d1 + total += d2 + total += d3 + total += d4 + total += d5 + return total + end + + def self.yahtzee(dice) + counts = [0]*(dice.length+1) + for die in dice do + counts[die-1] += 1 + end + for i in 0..counts.size do + if counts[i] == 5 + return 50 + end + end + return 0 + end + + def self.ones( d1, d2, d3, d4, d5) + sum = 0 + if (d1 == 1) + sum += 1 + end + if (d2 == 1) + sum += 1 + end + if (d3 == 1) + sum += 1 + end + if (d4 == 1) + sum += 1 + end + if (d5 == 1) + sum += 1 + end + + sum + end + + def self.twos( d1, d2, d3, d4, d5) + sum = 0 + if (d1 == 2) + sum += 2 + end + if (d2 == 2) + sum += 2 + end + if (d3 == 2) + sum += 2 + end + if (d4 == 2) + sum += 2 + end + if (d5 == 2) + sum += 2 + end + return sum + end + + def self.threes( d1, d2, d3, d4, d5) + s = 0 + if (d1 == 3) + s += 3 + end + if (d2 == 3) + s += 3 + end + if (d3 == 3) + s += 3 + end + if (d4 == 3) + s += 3 + end + if (d5 == 3) + s += 3 + end + return s + end + + def initialize(d1, d2, d3, d4, _5) + @dice = [0]*5 + @dice[0] = d1 + @dice[1] = d2 + @dice[2] = d3 + @dice[3] = d4 + @dice[4] = _5 + end + + def fours + sum = 0 + for at in Array 0..4 + if (@dice[at] == 4) + sum += 4 + end + end + return sum + end + + def fives() + s = 0 + i = 0 + for i in (Range.new(0, @dice.size)) + if (@dice[i] == 5) + s = s + 5 + end + end + s + end + + def sixes + sum = 0 + for at in 0..@dice.length + if (@dice[at] == 6) + sum = sum + 6 + end + end + return sum + end + + def self.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 + (0...6).each do |at| + if (counts[6-at-1] == 2) + return (6-at)*2 + end + end + return 0 + end + + def self.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 Array 0..5 + if (counts[6-i-1] == 2) + n = n+1 + score += (6-i) + end + end + if (n == 2) + return score * 2 + else + return 0 + end + end + + def self.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 (0..6) + if (tallies[i] == 4) + return (i+1) * 4 + end + end + return 0 + end + + def self.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 [0,1,2,3,4,5] + if (t[i] == 3) + return (i+1) * 3 + end + end + 0 + end + + def self.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 + (tallies[0] == 1 and + tallies[1] == 1 and + tallies[2] == 1 and + tallies[3] == 1 and + tallies[4] == 1) ? 15 : 0 + end + + def self.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 + end + return 0 + end + + def self.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 Array 0..5 + if (tallies[i] == 2) + _2 = true + _2_at = i+1 + end + end + + for i in Array 0..5 + if (tallies[i] == 3) + _3 = true + _3_at = i+1 + end + end + + if (_2 and _3) + return _2_at * 2 + _3_at * 3 + else + return 0 + end + end +end From 64b5914afa5e20cf0517e986ed6dd1ffe7163a34 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kim=20Persson=20and=20Lennart=20Frid=C3=A9n?= Date: Sun, 7 Apr 2013 13:10:20 +0200 Subject: [PATCH 11/11] Revert undesired changes to the README. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Lennart Fridén --- Yahtzee/README.md | 56 +++++++++++++++++++++++------------------------ 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/Yahtzee/README.md b/Yahtzee/README.md index 5f007080..8a7575fb 100644 --- a/Yahtzee/README.md +++ b/Yahtzee/README.md @@ -30,7 +30,7 @@ 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. +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. @@ -39,78 +39,78 @@ 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. - + ## Kata: Yahzee Categories and Scoring Rules _Note these rules differ from the original (copyrighted) rules_ -Chance: +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) + 4,5,5,6,1 placed on "chance" scores 21 (4+5+5+6+1) -Yahtzee: +Yahtzee: If all dice have the same number, - the player scores 50 points. + 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, +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: +Pair: The player scores the sum of the two highest matching dice. - For example, when placed on "pair" + 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: +Two pairs: If there are two pairs of dice with the same number, the - player scores the sum of these dice. + 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: +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" + 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: +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" + 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 +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 +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: +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) + 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