Move backstage pass logic to backstage-pass-behavior

This commit is contained in:
Arno Chauveau 2025-07-24 15:08:07 +02:00
parent cc8a2b35b0
commit ef9c478e7c
7 changed files with 131 additions and 89 deletions

3
TypeScript/app/config.ts Normal file
View File

@ -0,0 +1,3 @@
export const config = {
maxQuality: 50,
};

View File

@ -1,7 +1,8 @@
import { Item } from "@app/item";
import { getUpdateBehaviorFor } from "./behavior-resolver";
import { AgedBrieBehavior } from "./implementations/aged-brie-behavior";
import { AgedBrieBehavior } from "./implementations/aged-brie/aged-brie-behavior";
import { LegacyBehavior } from "./implementations/legacy-behavior";
import { BackstagePassBehavior } from "./implementations/backstage-pass/backstage-pass-behavior";
describe("Behavior resolver", () => {
it("should correctly resolve Aged Brie", () => {
@ -10,6 +11,14 @@ describe("Behavior resolver", () => {
);
});
it("should correctly resolve Backstage Passes", () => {
expect(
getUpdateBehaviorFor(
new Item("Backstage passes to a TAFKAL80ETC concert", 0, 0)
)
).toBeInstanceOf(BackstagePassBehavior);
});
it("should correctly resolve the rest to Legacy behavior", () => {
expect(
getUpdateBehaviorFor(new Item("some other item", 0, 0))

View File

@ -1,12 +1,15 @@
import { Item } from "@app/item";
import { IUpdateBehavior } from "./update-behavior.interface";
import { LegacyBehavior } from "./implementations/legacy-behavior";
import { AgedBrieBehavior } from "./implementations/aged-brie-behavior";
import { AgedBrieBehavior } from "./implementations/aged-brie/aged-brie-behavior";
import { BackstagePassBehavior } from "./implementations/backstage-pass/backstage-pass-behavior";
export function getUpdateBehaviorFor(item: Item): IUpdateBehavior {
switch (item.name) {
case "Aged Brie":
return new AgedBrieBehavior(item);
case "Backstage passes to a TAFKAL80ETC concert":
return new BackstagePassBehavior(item);
default:
return new LegacyBehavior(item);
}

View File

@ -0,0 +1,74 @@
import { Item } from "@app/item";
import { BackstagePassBehavior } from "./backstage-pass-behavior";
describe("Backstage Pass Behavior", () => {
it("should increase quality of Backstage passes by 1 if sell in date is more than 10 days away", () => {
const behavior = new BackstagePassBehavior(
new Item("Backstage passes to a TAFKAL80ETC concert", 11, 20)
);
const result = behavior.update();
expect(result).toMatchObject({
name: "Backstage passes to a TAFKAL80ETC concert",
sellIn: 10,
quality: 21,
});
});
it("should increase quality of Backstage passes by 2 if sell in date is less than 10 days away but more than 5", () => {
const behavior = new BackstagePassBehavior(
new Item("Backstage passes to a TAFKAL80ETC concert", 9, 20)
);
const result = behavior.update();
expect(result).toMatchObject({
name: "Backstage passes to a TAFKAL80ETC concert",
sellIn: 8,
quality: 22,
});
});
it("should increase quality of Backstage passes by 3 if sell in date is less than 5 days away", () => {
const behavior = new BackstagePassBehavior(
new Item("Backstage passes to a TAFKAL80ETC concert", 4, 20)
);
const result = behavior.update();
expect(result).toMatchObject({
name: "Backstage passes to a TAFKAL80ETC concert",
sellIn: 3,
quality: 23,
});
});
it("should drop quality of Backstage passes to 0 after sell in date", () => {
const behavior = new BackstagePassBehavior(
new Item("Backstage passes to a TAFKAL80ETC concert", 0, 20)
);
const result = behavior.update();
expect(result).toMatchObject({
name: "Backstage passes to a TAFKAL80ETC concert",
sellIn: -1,
quality: 0,
});
});
it("should not increase over 50", () => {
const behavior = new BackstagePassBehavior(
new Item("Backstage passes to a TAFKAL80ETC concert", 4, 50)
);
const result = behavior.update();
expect(result).toMatchObject({
name: "Backstage passes to a TAFKAL80ETC concert",
sellIn: 3,
quality: 50,
});
});
});

View File

@ -0,0 +1,30 @@
import { config } from "@app/config";
import { Item } from "@app/item";
import { IUpdateBehavior } from "@app/update-behaviors";
export class BackstagePassBehavior implements IUpdateBehavior {
constructor(private item: Item) {}
update(): Item {
const sellIn = this.item.sellIn;
const amountToIncrease = this.#getAmountToIncrease(sellIn);
this.item.quality = Math.min(
this.item.quality + amountToIncrease,
config.maxQuality
);
if (sellIn <= 0) {
this.item.quality = 0;
}
this.item.sellIn -= 1;
return this.item;
}
#getAmountToIncrease(sellIn: number): number {
if (sellIn <= 5) return 3;
if (sellIn <= 10) return 2;
return 1;
}
}

View File

@ -51,60 +51,4 @@ describe("Legacy Behavior", () => {
quality: 80,
});
});
it("should increase quality of Backstage passes by 1 if sell in date is more than 10 days away", () => {
const behavior = new LegacyBehavior(
new Item("Backstage passes to a TAFKAL80ETC concert", 11, 20)
);
const result = behavior.update();
expect(result).toMatchObject({
name: "Backstage passes to a TAFKAL80ETC concert",
sellIn: 10,
quality: 21,
});
});
it("should increase quality of Backstage passes by 2 if sell in date is less than 10 days away but more than 5", () => {
const behavior = new LegacyBehavior(
new Item("Backstage passes to a TAFKAL80ETC concert", 9, 20)
);
const result = behavior.update();
expect(result).toMatchObject({
name: "Backstage passes to a TAFKAL80ETC concert",
sellIn: 8,
quality: 22,
});
});
it("should increase quality of Backstage passes by 3 if sell in date is less than 5 days away", () => {
const behavior = new LegacyBehavior(
new Item("Backstage passes to a TAFKAL80ETC concert", 4, 20)
);
const result = behavior.update();
expect(result).toMatchObject({
name: "Backstage passes to a TAFKAL80ETC concert",
sellIn: 3,
quality: 23,
});
});
it("should drop quality of Backstage passes to 0 after sell in date", () => {
const behavior = new LegacyBehavior(
new Item("Backstage passes to a TAFKAL80ETC concert", 0, 20)
);
const result = behavior.update();
expect(result).toMatchObject({
name: "Backstage passes to a TAFKAL80ETC concert",
sellIn: -1,
quality: 0,
});
});
});

View File

@ -5,42 +5,21 @@ export class LegacyBehavior implements IUpdateBehavior {
constructor(private item: Item) {}
update(): Item {
if (this.item.name !== "Backstage passes to a TAFKAL80ETC concert") {
if (this.item.quality > 0) {
if (this.item.name !== "Sulfuras, Hand of Ragnaros") {
this.item.quality = this.item.quality - 1;
}
}
if (this.item.name !== "Sulfuras, Hand of Ragnaros") {
this.item.sellIn = this.item.sellIn - 1;
}
if (this.item.sellIn < 0) {
if (this.item.quality > 0) {
if (this.item.name !== "Sulfuras, Hand of Ragnaros") {
this.item.quality = this.item.quality - 1;
}
}
} else {
if (this.item.quality < 50) {
this.item.quality = this.item.quality + 1;
if (this.item.name === "Backstage passes to a TAFKAL80ETC concert") {
if (this.item.sellIn < 11) {
if (this.item.quality < 50) {
this.item.quality = this.item.quality + 1;
}
}
if (this.item.sellIn < 6) {
if (this.item.quality < 50) {
this.item.quality = this.item.quality + 1;
}
}
}
}
}
if (this.item.name !== "Sulfuras, Hand of Ragnaros") {
this.item.sellIn = this.item.sellIn - 1;
}
if (this.item.sellIn < 0) {
if (this.item.name !== "Backstage passes to a TAFKAL80ETC concert") {
if (this.item.quality > 0) {
if (this.item.name !== "Sulfuras, Hand of Ragnaros") {
this.item.quality = this.item.quality - 1;
}
}
} else {
this.item.quality = this.item.quality - this.item.quality;
}
}
return this.item;
}