diff --git a/gleam/.gitignore b/gleam/.gitignore new file mode 100644 index 00000000..90b7875b --- /dev/null +++ b/gleam/.gitignore @@ -0,0 +1,5 @@ +*.beam +*.ez +build +erl_crash.dump +manifest.toml diff --git a/gleam/README.md b/gleam/README.md new file mode 100644 index 00000000..61be7f7d --- /dev/null +++ b/gleam/README.md @@ -0,0 +1,20 @@ +# Gilded Rose starting position in Gleam + +I assume you have [installed](https://gleam.run/getting-started/installing/) `gleam` on your system. + +## Run unit tests from the command line + +```sh +$ gleam test +``` + +## Get the TextTest fixture on the command line + +Execute it on the command line with an argument for the number of days: + +```sh +$ gleam run -- --days=30 +``` + +Compare the output to [stdout.gr](../texttests/ThirtyDays/stdout.gr) for validation. +There are instructions in the [TextTest Readme](../texttests/README.md) for setting up TextTest. diff --git a/gleam/gleam.toml b/gleam/gleam.toml new file mode 100644 index 00000000..1fcc01b4 --- /dev/null +++ b/gleam/gleam.toml @@ -0,0 +1,21 @@ +name = "program" +version = "1.0.0" + +# Fill out these fields if you intend to generate HTML documentation or publish +# your project to the Hex package manager. +# +# description = "" +# licences = ["Apache-2.0"] +# repository = { type = "github", user = "username", repo = "project" } +# links = [{ title = "Website", href = "https://gleam.run" }] +# +# For a full reference of all the available options, you can have a look at +# https://gleam.run/writing-gleam/gleam-toml/. + +[dependencies] +gleam_stdlib = ">= 0.38.0 and < 1.0.0" +glint = ">= 0.18.1 and < 1.0.0" +argv = ">= 1.0.2 and < 2.0.0" + +[dev-dependencies] +gleeunit = ">= 1.0.0 and < 2.0.0" diff --git a/gleam/src/gilded_rose.gleam b/gleam/src/gilded_rose.gleam new file mode 100644 index 00000000..6a5c6e0e --- /dev/null +++ b/gleam/src/gilded_rose.gleam @@ -0,0 +1,109 @@ +import gleam/list + +pub type GildedRose = + List(Item) + +pub type Item { + Item(name: String, sell_in: Int, quality: Int) +} + +pub fn update_quality(inventory: GildedRose) -> GildedRose { + let update_quality_item = fn(item: Item) { + let new_quality = case + item.name != "Aged Brie" + && item.name != "Backstage passes to a TAFKAL80ETC concert" + { + True -> { + case item.quality > 0 { + True -> + case item.name != "Sulfuras, Hand of Ragnaros" { + True -> item.quality - 1 + False -> item.quality + } + False -> item.quality + } + } + False -> { + case item.quality < 50 { + True -> + item.quality + + 1 + + case item.name == "Backstage passes to a TAFKAL80ETC concert" { + True -> + case item.sell_in < 11 { + True -> { + case item.quality < 49 { + True -> + 1 + + case item.sell_in < 6 { + True -> + case item.quality < 48 { + True -> 1 + False -> 0 + } + False -> 0 + } + False -> 0 + } + } + False -> 0 + } + False -> 0 + } + False -> item.quality + } + } + } + + let new_sell_in = case item.name != "Sulfuras, Hand of Ragnaros" { + True -> item.sell_in - 1 + False -> item.sell_in + } + + case new_sell_in < 0 { + True -> + case item.name != "Aged Brie" { + True -> + case item.name != "Backstage passes to a TAFKAL80ETC concert" { + True -> + case new_quality > 0 { + True -> + case item.name != "Sulfuras, Hand of Ragnaros" { + True -> + Item( + ..item, + sell_in: new_sell_in, + quality: new_quality - 1, + ) + False -> Item(..item, sell_in: new_sell_in, quality: 80) + } + False -> + Item(..item, sell_in: new_sell_in, quality: new_quality) + } + False -> + Item( + ..item, + sell_in: new_sell_in, + quality: new_quality - new_quality, + ) + } + False -> + case new_quality < 50 { + True -> + Item(..item, sell_in: new_sell_in, quality: new_quality + 1) + False -> Item(..item, sell_in: new_sell_in, quality: 50) + } + } + False -> + case item.name == "Sulfuras, Hand of Ragnaros" { + True -> Item(..item, sell_in: new_sell_in, quality: 80) + False -> + case new_quality > 50 { + True -> Item(..item, sell_in: new_sell_in, quality: 50) + False -> Item(..item, sell_in: new_sell_in, quality: new_quality) + } + } + } + } + list.map(inventory, update_quality_item) +} diff --git a/gleam/src/program.gleam b/gleam/src/program.gleam new file mode 100644 index 00000000..0d402d12 --- /dev/null +++ b/gleam/src/program.gleam @@ -0,0 +1,76 @@ +import argv +import gilded_rose.{type GildedRose, type Item, Item, update_quality} +import gleam/function +import gleam/int +import gleam/io +import gleam/list +import gleam/string +import glint +import glint/flag + +pub fn main() { + run_cli_app(update_quality) +} + +pub fn run_cli_app(modify_inventory: fn(GildedRose) -> GildedRose) { + let days_flag = "days" + + let number_of_days = + flag.int() + |> flag.default(2) + |> flag.description("Number of days") + + let simulate_inventory = fn() { + use input <- glint.command() + + let assert Ok(number_of_days) = + flag.get_int(from: input.flags, for: days_flag) + simulate(number_of_days, modify_inventory) + } + + let app = + glint.new() + |> glint.with_name("Gilded Rose") + |> glint.group_flag([], days_flag, number_of_days) + |> glint.add(at: [], do: simulate_inventory()) + + io.println("OMGHAI!") + glint.run_and_handle(app, argv.load().arguments, function.identity) +} + +const test_fixture = [ + 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), + Item("Conjured Mana Cake", 3, 6), +] + +pub fn simulate( + number_of_days: Int, + modify_inventory: fn(GildedRose) -> GildedRose, +) -> GildedRose { + let days = list.range(0, number_of_days) + let display_item = fn(item: Item) { + string.join( + [item.name, int.to_string(item.sell_in), int.to_string(item.quality)], + with: ", ", + ) + } + list.fold(days, from: test_fixture, with: fn(inventory, day) { + case day != 0 { + True -> io.println("") + False -> Nil + } + io.println(string.join( + ["-------- day", int.to_string(day), "--------"], + with: " ", + )) + io.println("name, sellIn, quality") + list.each(inventory, fn(item) { io.println(display_item(item)) }) + modify_inventory(inventory) + }) +} diff --git a/gleam/test/gilded_rose_test.gleam b/gleam/test/gilded_rose_test.gleam new file mode 100644 index 00000000..42ac60ce --- /dev/null +++ b/gleam/test/gilded_rose_test.gleam @@ -0,0 +1,8 @@ +import gilded_rose.{Item, update_quality} +import gleeunit/should + +pub fn update_quality_test() { + let inventory = [Item("foo", 0, 0)] + let assert [new_item] = update_quality(inventory) + new_item.name |> should.equal("fixme") +} diff --git a/gleam/test/program_test.gleam b/gleam/test/program_test.gleam new file mode 100644 index 00000000..ecd12adf --- /dev/null +++ b/gleam/test/program_test.gleam @@ -0,0 +1,5 @@ +import gleeunit + +pub fn main() { + gleeunit.main() +}