Implement a Time-Aware Task Management System
Company: Airbnb
Role: Software Engineer
Category: Software Engineering Fundamentals
Difficulty: medium
Interview Round: Take-home Project
# Implement a Time-Aware Task Management System
Implement a task-management class. All `priority` and `quota` values are nonnegative integers. Timestamps and finish times are positive integers, and operation timestamps strictly increase.
### Constraints & Assumptions
- Task IDs are `task_id_N`, starting at `task_id_1`; creation sequence never changes.
- Duplicate task names and repeated assignments are allowed.
- Assignment intervals are half-open: `[start_time, finish_time)`.
- Expired uncompleted assignments remain queryable.
### Clarifying Questions to Ask
- For nonpositive search/list limits, should the result be empty? Use that behavior here.
- Does completion affect every overlapping assignment? It completes only the earliest active match.
### Part 1 — Basic Task Operations
- `add_task(timestamp, name, priority) -> str`: create and return the next sequential ID.
- `update_task(timestamp, task_id, name, priority) -> bool`: update name and priority while preserving creation sequence; return `false` if missing.
- `get_task(timestamp, task_id) -> string or null`: return null if missing, otherwise compact valid JSON with keys in this order: `{"name":"...","priority":N}`. Preserve whitespace inside the name and escape it correctly as JSON.
#### What This Part Should Cover
- Stable IDs, duplicate tasks, updates, missing IDs, and exact serialization.
### Part 2 — Search and Priority Ordering
- `search_tasks(timestamp, name_filter, max_results) -> list[str]`: use case-sensitive substring matching; sort by priority descending and numeric creation sequence ascending; truncate to `max_results`.
- `list_tasks_sorted(timestamp, limit) -> list[str]`: apply the same ordering to all tasks and truncate to `limit`.
#### What This Part Should Cover
- Numeric ID order rather than lexicographic order, priority-changing updates, ties, and nonpositive limits.
### Part 3 — Users, Quotas, and Active Assignments
- `add_user(timestamp, user_id, quota) -> bool`: reject duplicate users.
- `assign_task(timestamp, task_id, user_id, finish_time) -> bool`: reject missing entities or a user already at quota. Every successful assignment is independent, including repeated task/user pairs.
- `get_user_tasks(timestamp, user_id) -> list[str]`: return active assignment task IDs, preserving duplicates, sorted by finish time then assignment start time. A missing user returns an empty list.
Expired assignments stop consuming quota automatically.
#### What This Part Should Cover
- Half-open boundaries, repeated assignments, quota accounting, missing users, and deterministic ordering.
### Part 4 — Completion and Overdue History
- `complete_task(timestamp, task_id, user_id) -> bool`: among active uncompleted assignments for that task/user, complete only the one with smallest start time; return false if none exists. Completion frees quota immediately.
- `get_overdue_assignments(timestamp, user_id) -> list[str]`: return every uncompleted assignment with `finish_time <= timestamp`, including duplicate task IDs, sorted by finish time then start time. A missing user returns an empty list.
#### What This Part Should Cover
- Earliest-assignment selection, completion before expiry, retained expired history, duplicate overdue IDs, and quota release.
### What a Strong Answer Covers
- A consistent state model across all levels, every exact method contract, edge cases, and stated operation complexities.
### Follow-up Questions
- Which indexes improve search or per-user queries?
- How would persistence change the atomicity requirements?
Quick Answer: Implement a task-management class. Make the API or object boundaries explicit, then cover invariants, edge cases, testing strategy, and operational trade-offs.