Code Craft Practice Problems

A tracker for OOD, JSON, and state logic questions. Your progress is saved in this browser.

JSON Manipulation Warm-ups

Problem A: The Transaction Log Aggregator

Task: You are given a JSON string representing a list of transactions. Each object has a type, order_id, and amount. Write a function to calculate the net total for each order_id.

Tricks:

  • The list contains mixed types: CHARGE, REFUND, and AUTH. AUTH events have no order_id and should be ignored.
  • amount is a string with a $ prefix (e.g., "$45.50").
  • REFUND types should be subtracted from the total.
Input JSON:
[
  {"event_id": "e-1", "type": "CHARGE", "order_id": "order-100", "amount": "$50.00"},
  {"event_id": "e-2", "type": "AUTH", "dasher_id": "d-123"},
  {"event_id": "e-3", "type": "CHARGE", "order_id": "order-200", "amount": "$25.50"},
  {"event_id": "e-4", "type": "REFUND", "order_id": "order-100", "amount": "$10.50"},
  {"event_id": "e-5", "type": "CHARGE", "order_id": "order-100", "amount": "$5.00"}
]

Expected Output: {"order-100": 44.50, "order-200": 25.50}

Problem B: The User Metadata Extractor

Task: You are given a JSON string of a user object. Write a function that extracts and returns a simple object containing the user's full name, primary email, and their last login IP.

Tricks:

  • The name is in a nested object and must be combined: {"first": "Jane", "last": "Doe"} -> "Jane Doe".
  • contacts is a list. You must iterate to find the one where "primary": true.
  • metadata is a double-encoded JSON string. You must parse it twice to access the last_login_ip within.
Input JSON:
{
  "user_id": "u-abc",
  "profile": {
    "name": {"first": "Jane", "last": "Doe"}
  },
  "contacts": [
    {"type": "phone", "value": "555-1234", "primary": false},
    {"type": "email", "value": "jane.doe@example.com", "primary": true},
    {"type": "email", "value": "jane.work@example.com", "primary": false}
  ],
  "metadata": "{\"last_login_ip\": \"192.168.1.1\", \"preferences\": {\"theme\": \"dark\"}}"
}

Expected Output: {"full_name": "Jane Doe", "email": "jane.doe@example.com", "last_login_ip": "192.168.1.1"}

Problem C: The Inventory Flattener

Task: You are given a JSON string of a restaurant's menu, organized by categories. Write a function that "flattens" this structure into a single list of all available items, including their category and SKU.

Tricks:

  • The items are a dictionary, where the key is the item's SKU. You must iterate over the dictionary's (key, value) pairs.
  • The final object must include the category_name (from the parent) and the sku (from the dictionary key).
  • You must filter out any item where is_available is false.
Input JSON:
{
  "restaurant_id": "r-1",
  "categories": [
    {
      "category_name": "Drinks",
      "items": {
        "SKU-D01": {"name": "Coke", "price": 2.50, "is_available": true},
        "SKU-D02": {"name": "Sprite", "price": 2.50, "is_available": false}
      }
    },
    {
      "category_name": "Appetizers",
      "items": {
        "SKU-A01": {"name": "Spring Rolls", "price": 8.00, "is_available": true}
      }
    }
  ]
}

Expected Output:

[
  {"sku": "SKU-D01", "name": "Coke", "price": 2.50, "category": "Drinks"},
  {"sku": "SKU-A01", "name": "Spring Rolls", "price": 8.00, "category": "Appetizers"}
]

Full "Code Craft" Problems

Problem 0: Dasher Pay (Concurrency Multiplier)

Task: Write a function, calculate_pay_units(events), that takes a list of Dasher events. Each event has a timestamp and a status ('PICKUP' or 'DROPOFF'). Return the total "pay units", where pay units = (time elapsed in seconds × multiplier).

Logic:

  • The multiplier starts at 0.
  • PICKUP increases the multiplier by 1.
  • DROPOFF decreases the multiplier by 1.

Rules & Constraints:

  • The input list is not guaranteed to be in chronological order.
  • The multiplier must never drop below 0.
  • If a PICKUP and DROPOFF occur at the exact same timestamp, process the PICKUP first.
Example Input:
[
  (300, 'DROPOFF'),
  (100, 'PICKUP'),
  (350, 'DROPOFF'),
  (200, 'PICKUP')
]

Calculation Trace (after sorting):

  1. Event (t=100, PICKUP):
    • Interval (0s to 100s) @ 0x multiplier = 0 units.
    • Multiplier becomes 1.
  2. Event (t=200, PICKUP):
    • Interval (100s to 200s) @ 1x multiplier = 100 units.
    • Multiplier becomes 2.
  3. Event (t=300, DROPOFF):
    • Interval (200s to 300s) @ 2x multiplier = 200 units.
    • Multiplier becomes 1.
  4. Event (t=350, DROPOFF):
    • Interval (300s to 350s) @ 1x multiplier = 50 units.
    • Multiplier becomes 0.

Expected Output: 350

Problem 1: Order Total Calculator

Task: Implement calculate_order_total(order_json). You must parse the messy JSON, calculate all line items (ignoring the unreliable subtotal_estimate), apply *only* valid promotions, and sum up all fees (ignoring null ones) and the tip to produce a single, final total.

Tricks:

  • items.price and tip are strings that must be parsed.
  • promotions is a dictionary; you must check is_active: true.
  • adjustments is a list; some values might be null.
Input JSON:
{
  "order_id": "ord-123",
  "subtotal_estimate": "45.00",
  "items": [
    {"item_id": "i-1", "name": "Chicken Wings", "price": "14.99", "quantity": 1},
    {"item_id": "i-2", "name": "Coke Zero", "price": "2.50", "quantity": 2}
  ],
  "promotions": {
    "FALL20": {"type": "PERCENT", "value": 0.20, "is_active": true},
    "WELCOME5": {"type": "FIXED", "value": 5.00, "is_active": false}
  },
  "adjustments": [
    {"name": "Service Fee", "amount": 3.99},
    {"name": "Delivery Fee", "amount": 5.00},
    {"name": "Small Order Fee", "amount": null}
  ],
  "tip": "6.15"
}

Problem 2: Order Ingestion & Validation Service

Task: Design an OrderValidationService with a process_order(raw_json) method. It must parse the JSON, validate it, and return a "clean" Example [ ['X', ' ', ' ', 'D', ' ', ' ', 'X', ' ', 'X'], ['X', ' ', 'X', 'X', ' ', ' ', ' ', ' ', 'X'], [' ', ' ', ' ', 'D', 'X', 'X', ' ', 'X', ' '], [' ', ' ', ' ', 'D', 'X', 'X', ' ', 'X', ' '], [' ', ' ', ' ', ' ', ' ', 'X', ' ', ' ', 'X'], [' ', ' ', ' ', ' ', 'X', ' ', ' ', 'X', 'X'] ] Order object or a structured error message.

Rules: Must have customer_id, at least one item, a parsable delivery_address, and all item_ids must be integers.

Tricks:

  • Field names are inconsistent (e.g., order_id vs orderId).
  • items is a dictionary where the *key* is the item_id.
  • item_ids in the keys might be strings (e.g., "1002").
  • delivery_address is a single string to be parsed.
Input JSON:
{
  "orderId": "A-987",
  "custId": "user-554",
  "delivery_address": "123 Main St, Toronto, M5V 2K1",
  "items": {
    "1002": {"name": "Bag of Chips", "quantity": 2},
    "2005": {"name": "Energy Drink", "quantity": 1}
  }
}

Problem 3: Dasher Bonus Calculator

Task: Write calculate_bonus(dasher_deliveries_json). Bonus is +$1.00 for on-time (dropoff_actual <= dropoff_estimated) and +$2.00 for 5-star ratings (rating == 5 or rating == "5").

Tricks:

  • Timestamps are ISO 8601 strings and must be parsed to compare.
  • customer_feedback object can be null or missing.
  • rating can be an integer (5) or a string ("5").
  • is_return: true deliveries are ineligible for any bonus.
Input JSON:
[
  {
    "delivery_id": "d-1", "is_return": false,
    "timestamps": {
      "dropoff_estimated": "2025-10-25T14:30:00Z",
      "dropoff_actual": "2025-10-25T14:28:00Z"
    },
    "customer_feedback": {"rating": 5}
  },
  {
    "delivery_id": "d-2", "is_return": false,
    "timestamps": {
      "dropoff_estimated": "2025-10-25T15:20:00Z",
      "dropoff_actual": "2025-10-25T15:22:00Z"
    },
    "customer_feedback": {"rating": "4"}
  },
  {
    "delivery_id": "d-3", "is_return": true,
    "timestamps": {"...": "..."},
    "customer_feedback": {"rating": 5}
  },
  {
    "delivery_id": "d-4", "is_return": false,
    "timestamps": {
      "dropoff_estimated": "2025-10-25T17:20:00Z",
      "dropoff_actual": "2025-10-25T17:19:00Z"
    },
    "customer_feedback": null
  }
]

Problem 4: Menu Filtering Service

Task: Design a MenuFilteringService that takes menu_json and filters_json. It must return a new, filtered menu JSON. Items that don't match are removed. If a category becomes empty, it must also be removed.

Tricks:

  • Deeply nested JSON: categories -> items.
  • Filters are optional (e.g., no max_price means don't filter by price).
  • Filtering logic is *AND*: must be is_available, under max_price, AND match all dietary_tags.
  • Items without a dietary_tags key should be treated as [].
  • You must construct a new, valid JSON object, not modify the original.
Input Menu JSON:
{
  "categories": [
    {"category_name": "Appetizers", "items": [
      {"name": "Spring Rolls", "price": 8.00, "is_available": true, "dietary_tags": ["vegan"]},
      {"name": "Chicken Wings", "price": 14.00, "is_available": true, "dietary_tags": []}
    ]},
    {"category_name": "Main Courses", "items": [
      {"name": "Green Curry", "price": 18.00, "is_available": true, "dietary_tags": ["vegan", "gluten_free"]},
      {"name": "Pad Thai", "price": 16.00, "is_available": false, "dietary_tags": ["gluten_free"]}
    ]}
  ]
}
Input Filters JSON:
{
  "max_price": 15.00,
  "dietary_tags": ["vegan"]
}

Problem 5: Order Financial Reconciliation Service

Task: Write reconcile_transactions(transactions_json). Take the log and return a JSON object where each key is an order_id and the value is its "net profit".

Logic: CHARGE/ADJUSTMENT (positive) are revenue. DASHER_PAY, REFUND, ADJUSTMENT (negative) are expenses. Ignore other types.

Tricks:

  • Heterogeneous list: type key determines structure.
  • Some events (like DASHER_ONLINE) have no order_id and should be skipped.
  • amount is always positive; use type to know if it's revenue or expense.
  • ADJUSTMENT payload is a **double-encoded JSON string**! You must parse it to get its (positive or negative) amount.
Input JSON:
[
  { "event_id": "evt-1", "type": "CHARGE", "order_id": "A100", "amount": 45.50 },
  { "event_id": "evt-2", "type": "DASHER_PAY", "order_id": "A100", "amount": 8.00 },
  { "event_id": "evt-3", "type": "DASHER_ONLINE", "dasher_id": "D123" },
  { "event_id": "evt-4", "type": "CHARGE", "order_id": "B200", "amount": 22.00 },
  { "event_id": "evt-5",
    "type": "ADJUSTMENT",
    "order_id": "A100",
    "payload": "{\"reason\": \"Customer complaint\", \"amount\": -5.00}"
  },
  { "event_id": "evt-6", "type": "DASHER_PAY", "order_id": "B200", "amount": 6.50 },
  { "event_id": "evt-7", "type": "REFUND", "order_id": "B200", "amount": 22.00 }
]

Problem 6: Delivery Assignment Service

Task: Design and implement a DeliveryAssignmentService. This service will be responsible for assigning a newly created order to the 'best' available Dasher.

Core Requirements:

  1. Implement the main API method: assign_order(Order order).
  2. The "best" Dasher is defined as the closest available Dasher to the restaurant.
  3. When an order is assigned, the Dasher becomes unavailable, and the order's status should be updated to ASSIGNED.
  4. If no Dashers are available, the service should throw a NoDashersAvailableException.

Provided Mocks (Assume these exist):

  • DasherRepository with get_available_dashers() -> List[Dasher]
  • OrderRepository with save(Order order)
  • DasherRepository with save(Dasher dasher)
  • DistanceService with calculate_distance(Location loc1, Location loc2) -> float

Data Models (You will need to define these):

  • Location: (latitude, longitude)
  • Order: (order_id, restaurant_location, customer_location, status)
  • Dasher: (dasher_id, current_location, is_available)
  • Delivery: (delivery_id, order_id, dasher_id, status)

Focus on: Your implementation of DeliveryAssignmentService and any supporting classes/enums. Show good OOD, error handling, and testability.