From 391e5c2e98b3aecc9a7ce6ad6f3ef799e88fd15f Mon Sep 17 00:00:00 2001 From: Sven Heyll Date: Tue, 24 Feb 2015 05:11:15 +0100 Subject: [PATCH] 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 #-}