Skip to content

Instantly share code, notes, and snippets.

@DanielRamosAcosta
Last active May 26, 2025 20:26
Show Gist options
  • Save DanielRamosAcosta/3f72e9a726542f29ace86bfcd5d24878 to your computer and use it in GitHub Desktop.
Save DanielRamosAcosta/3f72e9a726542f29ace86bfcd5d24878 to your computer and use it in GitHub Desktop.
Back to the Future Kata

Back to the Future Kata

Complete name: Back to the Future in the Grocery Store Kata

This kata is about managing a special grocery store inventory. The task is to keep track of fruits and vegetables, organize and sort them, but with a twistβ€”we need to manage the inventory over time!

Every method in this kata requires a date parameter to indicate when the changes should take effect.

Your job is to create a system that can accept changes to the inventory at any date, and then allow us to see the state of the inventory at any given date.

In each iteration, there will be examples. Let's use these variables for all of them:

const yesterday = new Date("2024-11-14");
const today = new Date("2024-11-15");
const tomorrow = new Date("2024-11-16");
const future = new Date("2025-01-01");

⚠️ The signatures of the methods in the examples might be questionable. You might come up with better interfaces, use IDs for things that doesn't have in the example, wharever you want.

Iteration 1

User Should Be Able To (USBAT from now on): Add products to the inventory

inventory.add(today, "🍌");
inventory.add(today, "πŸ₯");
inventory.add(tomorrow, "🍊");

inventory.project(yesterday); // <empty>
inventory.project(today); // 🍌πŸ₯
inventory.project(tomorrow); // 🍌πŸ₯πŸŠ

Iteration 2

USBAT: Remove previously added products

inventory.add(today, "🍌");
inventory.add(today, "πŸ₯");
inventory.remove(tomorrow, "🍌");

inventory.project(yesterday); // <empty>
inventory.project(today); // 🍌πŸ₯
inventory.project(tomorrow); // πŸ₯

Iteration 3

USBAT: Create groups of products

  • If there is a group, the string representation should include "|"
  • If products are separated from each other, the group must be created where the first product is located.
  • Groups cannot be empty
    • If you start removing elements from a group, the group must disappear
  • You can only create groups of elements that are present at that moment

Simple example:

inventory.add(today, "🍌");
inventory.add(today, "πŸ₯");
inventory.add(today, "🍊");
inventory.add(today, "🍎");

inventory.project(future); // 🍌πŸ₯πŸŠπŸŽ

inventory.group(tomorrow, ["πŸ₯", "🍊"]);

inventory.project(future); // 🍌|πŸ₯πŸŠ|🍎

Example with products separated from each other:

inventory.add(today, "🍌");
inventory.add(today, "πŸ₯");
inventory.add(today, "🍊");
inventory.add(today, "🍎");

inventory.project(future); // 🍌πŸ₯πŸŠπŸŽ

inventory.group(tomorrow, ["🍌", "🍎"]);

inventory.project(future); // |🍌🍎|πŸ₯πŸŠ

Example with temporal complications:

inventory.add(today, "🍌");
inventory.add(today, "πŸ₯");
inventory.add(today, "🍊");
inventory.add(today, "🍎");

inventory.project(future); // 🍌πŸ₯πŸŠπŸŽ

inventory.group(tomorrow, ["🍌", "🍎"]);

inventory.project(future); // |🍌🍎|πŸ₯πŸŠ

inventory.remove(today, "🍎"); // we are removing an item today, but the group was created tomorrow

inventory.project(future); // |🍌|πŸ₯πŸŠ

inventory.remove(today, "🍌");

inventory.project(future); // πŸ₯πŸŠ

Iteration 4

So far, we have been managing the inventory from a time perspective at a "global" level, without specifying any particular country. However, each country can have its own overrides. Generally, there will only be a few changes for specific countries, while the main management will still be at the global level.

inventory.add({ date: today }, "🍌"); // Global
inventory.add({ date: today }, "πŸ₯"); // Global
inventory.add({ date: tomorrow, country: "spain" }, "🍊"); // Specific to Spain
inventory.add({ date: tomorrow, country: "uk" }, "🍎"); // Specific to the UK

inventory.project({ date: future }); // 🍌πŸ₯
inventory.project({ date: future, country: "spain" }); // 🍌πŸ₯πŸŠ
inventory.project({ date: future, country: "uk" }); // 🍌πŸ₯πŸŽ

Ensure that all previous scenarios continue to work. We should be able to add/remove products, create groups, and move items at any time at any scope level.

Iteration 5

USBAT: Move products and groups in the inventory

  • Both groups and products can be moved at the "root" level of the inventory
  • Only products can be moved inside groups
inventory.add({date: today}, "🍌");
inventory.add({date: today}, "πŸ₯");
inventory.add({date: today}, "🍊");
inventory.add({date: today}, "🍎");
inventory.group({date: today}, ["🍌", "🍎"]);
inventory.project({date: future}); // |🍌🍎|πŸ₯πŸŠ

inventory.move({date: today}, "πŸ₯", 0); // Move kiwi to index 0
inventory.project({date: future}); // πŸ₯|🍌🍎|🍊

inventory.move({date: today}, "πŸ₯", 1); // Move kiwi to index 1
inventory.project({date: future}); // |🍌πŸ₯πŸŽ|🍊
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment