This commit is contained in:
guitarbien 2022-06-30 22:10:05 +08:00
parent bc7de77181
commit bcab53216f
14 changed files with 470 additions and 5177 deletions

10
php/.gitignore vendored
View File

@ -1,6 +1,4 @@
/.idea .idea
/report.xml .phpunit.result.cache
/.phpstorm.meta.php vendor
/.phpunit.result.cache
/build
/vendor

View File

@ -1 +0,0 @@
composer check-cs

View File

@ -1,8 +1,6 @@
{ {
"name": "emilybache/gilded-rose-refactoring-kata",
"description": "A kata to practice refactoring, tests and polymorphism",
"require": { "require": {
"php": "^7.3 || ^8.0" "php": "^8.0"
}, },
"autoload": { "autoload": {
"psr-4": { "psr-4": {
@ -15,21 +13,6 @@
} }
}, },
"require-dev": { "require-dev": {
"phpunit/phpunit": "^9.5", "phpunit/phpunit": "^9.5"
"phpstan/phpstan": "^0.12.85",
"phpstan/phpstan-phpunit": "^0.12.18",
"symplify/easy-coding-standard": "^9.3",
"symplify/phpstan-extensions": "^9.3",
"approvals/approval-tests": "^1.4"
},
"scripts": {
"checkcode": "phpcs src tests --standard=PSR12",
"fixcode": "phpcbf src tests --standard=PSR12",
"test": "phpunit",
"tests": "phpunit",
"test-coverage": "phpunit --coverage-html build/coverage",
"check-cs": "ecs check",
"fix-cs": "ecs check --fix",
"phpstan": "phpstan analyse --ansi"
} }
} }

4795
php/composer.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -1,36 +0,0 @@
<?php
declare(strict_types=1);
use PhpCsFixer\Fixer\ArrayNotation\ArraySyntaxFixer;
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
use Symplify\EasyCodingStandard\ValueObject\Option;
use Symplify\EasyCodingStandard\ValueObject\Set\SetList;
return static function (ContainerConfigurator $containerConfigurator): void {
$services = $containerConfigurator->services();
$services->set(ArraySyntaxFixer::class)
->call('configure', [[
'syntax' => 'short',
]]);
$parameters = $containerConfigurator->parameters();
$parameters->set(Option::PATHS, [
__DIR__ . '/fixtures',
__DIR__ . '/src',
__DIR__ . '/tests',
]);
$parameters->set
(Option::SETS,
[
SetList::CLEAN_CODE,
SetList::COMMON,
SetList::PSR_12,
]
);
$parameters->set(Option::INDENTATION, "spaces");
$parameters->set(Option::LINE_ENDING, "\n");
};

View File

@ -1 +0,0 @@
composer fix-cs

View File

@ -1,40 +0,0 @@
<?php
declare(strict_types=1);
require_once __DIR__ . '/../vendor/autoload.php';
use GildedRose\GildedRose;
use GildedRose\Item;
echo 'OMGHAI!' . PHP_EOL;
$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),
];
$app = new GildedRose($items);
$days = 2;
if (count($argv) > 1) {
$days = (int) $argv[1];
}
for ($i = 0; $i < $days; $i++) {
echo "-------- day ${i} --------" . PHP_EOL;
echo 'name, sellIn, quality' . PHP_EOL;
foreach ($items as $item) {
echo $item . PHP_EOL;
}
echo PHP_EOL;
$app->updateQuality();
}

View File

@ -1,16 +0,0 @@
includes:
- vendor/symplify/phpstan-extensions/config/config.neon
- vendor/phpstan/phpstan-phpunit/extension.neon
parameters:
paths:
- src
- tests
- fixtures
# The level 8 is the highest level
level: 8
checkGenericClassInNonGenericObjectType: false
checkMissingIterableValueType: false

View File

@ -1 +0,0 @@
composer phpstan

View File

@ -1 +0,0 @@
composer test

View File

@ -29,12 +29,12 @@ final class GildedRose
if ($item->quality < 50) { 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->name == 'Backstage passes to a TAFKAL80ETC concert') {
if ($item->sell_in < 11) { if ($item->sellIn < 11) {
if ($item->quality < 50) { if ($item->quality < 50) {
$item->quality = $item->quality + 1; $item->quality = $item->quality + 1;
} }
} }
if ($item->sell_in < 6) { if ($item->sellIn < 6) {
if ($item->quality < 50) { if ($item->quality < 50) {
$item->quality = $item->quality + 1; $item->quality = $item->quality + 1;
} }
@ -44,10 +44,10 @@ final class GildedRose
} }
if ($item->name != 'Sulfuras, Hand of Ragnaros') { if ($item->name != 'Sulfuras, Hand of Ragnaros') {
$item->sell_in = $item->sell_in - 1; $item->sellIn = $item->sellIn - 1;
} }
if ($item->sell_in < 0) { if ($item->sellIn < 0) {
if ($item->name != 'Aged Brie') { if ($item->name != 'Aged Brie') {
if ($item->name != 'Backstage passes to a TAFKAL80ETC concert') { if ($item->name != 'Backstage passes to a TAFKAL80ETC concert') {
if ($item->quality > 0) { if ($item->quality > 0) {

View File

@ -6,30 +6,12 @@ namespace GildedRose;
final class Item final class Item
{ {
/** public function __construct(public string $name, public int $sellIn, public int $quality)
* @var string
*/
public $name;
/**
* @var int
*/
public $sell_in;
/**
* @var int
*/
public $quality;
public function __construct(string $name, int $sell_in, int $quality)
{ {
$this->name = $name;
$this->sell_in = $sell_in;
$this->quality = $quality;
} }
public function __toString(): string public function __toString(): string
{ {
return "{$this->name}, {$this->sell_in}, {$this->quality}"; return "{$this->name}, {$this->sellIn}, {$this->quality}";
} }
} }

View File

@ -10,11 +10,323 @@ use PHPUnit\Framework\TestCase;
class GildedRoseTest extends TestCase class GildedRoseTest extends TestCase
{ {
public function testFoo(): void //-----------------
// normal item
//-----------------
public function testUpdatesNormalItemsBeforeSellDate(): void
{ {
$items = [new Item('foo', 0, 0)]; // arrange
$gildedRose = new GildedRose($items); $items = [new Item('normal', 5, 10)];
$gildedRose->updateQuality(); $app = new GildedRose($items);
$this->assertSame('fixme', $items[0]->name);
// act
$app->updateQuality();
// assert
$this->assertSame(4, $items[0]->sellIn);
$this->assertSame(9, $items[0]->quality);
}
public function testUpdatesNormalItemsOnSellDate(): void
{
// arrange
$items = [new Item('normal', 0, 10)];
$app = new GildedRose($items);
// act
$app->updateQuality();
// assert
$this->assertSame(-1, $items[0]->sellIn);
$this->assertSame(8, $items[0]->quality);
}
public function testUpdatesNormalItemsAfterSellDate(): void
{
// arrange
$items = [new Item('normal', -5, 10)];
$app = new GildedRose($items);
// act
$app->updateQuality();
// assert
$this->assertSame(-6, $items[0]->sellIn);
$this->assertSame(8, $items[0]->quality);
}
public function testUpdatesNormalItemsWithAQualityOf0(): void
{
// arrange
$items = [new Item('normal', 5, 0)];
$app = new GildedRose($items);
// act
$app->updateQuality();
// assert
$this->assertSame(4, $items[0]->sellIn);
$this->assertSame(0, $items[0]->quality);
}
//-----------------
// Brie item
//-----------------
public function testUpdatesBrieItemsBeforeSellDate(): void
{
// arrange
$items = [new Item('Aged Brie', 5, 10)];
$app = new GildedRose($items);
// act
$app->updateQuality();
// assert
$this->assertSame(4, $items[0]->sellIn);
$this->assertSame(11, $items[0]->quality);
}
public function testUpdatesBrieItemsBeforeSellDateWithMaximumQuality(): void
{
// arrange
$items = [new Item('Aged Brie', 5, 50)];
$app = new GildedRose($items);
// act
$app->updateQuality();
// assert
$this->assertSame(4, $items[0]->sellIn);
$this->assertSame(50, $items[0]->quality);
}
public function testUpdatesBrieItemsOnSellDate(): void
{
// arrange
$items = [new Item('Aged Brie', 0, 10)];
$app = new GildedRose($items);
// act
$app->updateQuality();
// assert
$this->assertSame(-1, $items[0]->sellIn);
$this->assertSame(12, $items[0]->quality);
}
public function testUpdatesBrieItemsOnSellDateNearMaximumQuality(): void
{
// arrange
$items = [new Item('Aged Brie', 0, 49)];
$app = new GildedRose($items);
// act
$app->updateQuality();
// assert
$this->assertSame(-1, $items[0]->sellIn);
$this->assertSame(50, $items[0]->quality);
}
public function testUpdatesBrieItemsOnSellDateWithMaximumQuality(): void
{
// arrange
$items = [new Item('Aged Brie', 0, 50)];
$app = new GildedRose($items);
// act
$app->updateQuality();
// assert
$this->assertSame(-1, $items[0]->sellIn);
$this->assertSame(50, $items[0]->quality);
}
public function testUpdatesBrieItemsAfterSellDate(): void
{
// arrange
$items = [new Item('Aged Brie', -10, 10)];
$app = new GildedRose($items);
// act
$app->updateQuality();
// assert
$this->assertSame(-11, $items[0]->sellIn);
$this->assertSame(12, $items[0]->quality);
}
public function testUpdatesBrieItemsAfterSellDateWithMaximumQuality(): void
{
// arrange
$items = [new Item('Aged Brie', -10, 50)];
$app = new GildedRose($items);
// act
$app->updateQuality();
// assert
$this->assertSame(-11, $items[0]->sellIn);
$this->assertSame(50, $items[0]->quality);
}
//-----------------
// Sulfuras item
//-----------------
public function testUpdatesSulfurasItemsBeforeSellDate(): void
{
// arrange
$items = [new Item('Sulfuras, Hand of Ragnaros', 5, 10)];
$app = new GildedRose($items);
// act
$app->updateQuality();
// assert
$this->assertSame(5, $items[0]->sellIn);
$this->assertSame(10, $items[0]->quality);
}
public function testUpdatesSulfurasItemsOnSellDate(): void
{
// arrange
$items = [new Item('Sulfuras, Hand of Ragnaros', 0, 10)];
$app = new GildedRose($items);
// act
$app->updateQuality();
// assert
$this->assertSame(0, $items[0]->sellIn);
$this->assertSame(10, $items[0]->quality);
}
public function testUpdatesSulfurasItemsAfterSellDate(): void
{
// arrange
$items = [new Item('Sulfuras, Hand of Ragnaros', -1, 10)];
$app = new GildedRose($items);
// act
$app->updateQuality();
// assert
$this->assertSame(-1, $items[0]->sellIn);
$this->assertSame(10, $items[0]->quality);
}
//-----------------
// Backstage Pass
//-----------------
public function testUpdatesBackstagePassItemsLongBeforeSellDate(): void
{
// arrange
$items = [new Item('Backstage passes to a TAFKAL80ETC concert', 11, 10)];
$app = new GildedRose($items);
// act
$app->updateQuality();
// assert
$this->assertSame(10, $items[0]->sellIn);
$this->assertSame(11, $items[0]->quality);
}
public function testUpdatesBackstagePassItemsCloseToBeforeSellDate(): void
{
// arrange
$items = [new Item('Backstage passes to a TAFKAL80ETC concert', 10, 10)];
$app = new GildedRose($items);
// act
$app->updateQuality();
// assert
$this->assertSame(9, $items[0]->sellIn);
$this->assertSame(12, $items[0]->quality);
}
public function testUpdatesBackstagePassItemsCloseToSellDateAtMaximumQuality(): void
{
// arrange
$items = [new Item('Backstage passes to a TAFKAL80ETC concert', 10, 50)];
$app = new GildedRose($items);
// act
$app->updateQuality();
// assert
$this->assertSame(9, $items[0]->sellIn);
$this->assertSame(50, $items[0]->quality);
}
public function testUpdatesBackstagePassItemsVeryCloseToSellDate(): void
{
// arrange
$items = [new Item('Backstage passes to a TAFKAL80ETC concert', 5, 10)];
$app = new GildedRose($items);
// act
$app->updateQuality();
// assert
$this->assertSame(4, $items[0]->sellIn);
$this->assertSame(13, $items[0]->quality);
}
public function testUpdatesBackstagePassItemsVeryCloseToSellDateAtMaxiumQuality(): void
{
// arrange
$items = [new Item('Backstage passes to a TAFKAL80ETC concert', 5, 50)];
$app = new GildedRose($items);
// act
$app->updateQuality();
// assert
$this->assertSame(4, $items[0]->sellIn);
$this->assertSame(50, $items[0]->quality);
}
public function testUpdatesBackstagePassItemsWithOneDayLeftToSellDateAtMaxiumQuality(): void
{
// arrange
$items = [new Item('Backstage passes to a TAFKAL80ETC concert', 1, 50)];
$app = new GildedRose($items);
// act
$app->updateQuality();
// assert
$this->assertSame(0, $items[0]->sellIn);
$this->assertSame(50, $items[0]->quality);
}
public function testUpdatesBackstagePassItemsOnSellDate(): void
{
// arrange
$items = [new Item('Backstage passes to a TAFKAL80ETC concert', 0, 10)];
$app = new GildedRose($items);
// act
$app->updateQuality();
// assert
$this->assertSame(-1, $items[0]->sellIn);
$this->assertSame(0, $items[0]->quality);
}
public function testUpdatesBackstagePassItemsAfterSellDate(): void
{
// arrange
$items = [new Item('Backstage passes to a TAFKAL80ETC concert', -1, 10)];
$app = new GildedRose($items);
// act
$app->updateQuality();
// assert
$this->assertSame(-2, $items[0]->sellIn);
$this->assertSame(0, $items[0]->quality);
} }
} }

View File

@ -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