Incident.io 1-1 coding interview.

incident.io logo
incident.io
January 19, 20265 reads

Summary

I participated in a 1-1 coding interview with Incident.io, where the task involved extending an existing on-call pay calculator to incorporate special rates for specific periods like Christmas and New Year.

Full Experience

1-1 coding interview after the take home exercise. You have about 15 minutes to implement.

# On call pay calculator

## Background

At incident.io, we believe everyone should be on-call by default.

We acknowledge that presents an inconvenience and want to compensate people for
that - we pay a flat rate of £5/hour, pro-rated to the time you spend on-call.

Every month, we export our on-call data, and run a script to calculate how much
everyone should be paid. We then send this information to our accountants.

## The challenge

We've implemented the ability to pay users a flat rate based on a list of schedule
entries. Now we'd like you to help us with the following:

We'd like to start paying more for periods like Christmas and New Year.
This is already represented in our `pay_config.json` sample data, but we're not yet
using it anywhere.

* Pay periods will never overlap each other, but may overlap one or more schedule entries.
* Pay periods can start and end at any time (not just whole days, for example)

There is a test that is currently failing, which covers one possible scenario (although there
are a few more that you should consider). You can find it in `calculateAmountsOwed.test.ts`.

## Note on AI

We'd ask that you don't use an AI assistant for this part of the task, as
we'd like to see how you approach the problem and what decisions you make.
This includes auto-complete mode, as agents can get a bit eager and start
filling in entire blocks for you.

Input:

{
  "entries": [
    {
      "user_id": "1",
      "start_at": "2024-11-02T16:00:00Z",
      "end_at": "2024-11-09T15:00:00Z"
    },
    ...
  ]
}

Pay config:

{
    "default_hourly_gbp": 500,
    "periods": [
        {
            "name": "Christmas,
            "start_at": "2024-12-23T00:00:00Z",
            "end_at": "2024-12-26T00:00:00Z",
            "hourly_gbp": 1000
        },
        {
            "name": "New Year",
            "start_at": "2024-12-31T00:00:00Z",
            "end_at": "2025-01-02T00:00:00Z",
            "hourly_gbp": 1500
        }
    ]
}

The existing code:

export type PayPeriod = {
    name: string
    start_at: Date
    end_at: Date
    hourly_gbp: number
}

export type PayConfig = {
    default_hourly_gbp: number
    periods: PayPeriod[]
}

export type ScheduleEntry = {
    user_id: string
    start_at: Date
    end_at: Date
}

export type AmountsOwed = { [key: string]: number }

// calculateAmountsOwed calculates how much each person is owed and logs the output to console
export const calculateAmountsOwed = (scheduleEntries: ScheduleEntry[], payConfig: PayConfig): void => {
    const userTotals = calculateUserTotals(scheduleEntries, payConfig)
    console.log(generateOutput(userTotals))
}

// calculateUserTotals calculates how much each person is owed by adding up all their shifts
export const calculateUserTotals = (
    scheduleEntries: ScheduleEntry[],
    payConfig: PayConfig
): AmountsOwed => {
    let userTotals: AmountsOwed = {}
    const amountPaidPerSecond = payPerSecond(payConfig.default_hourly_gbp)

    for (const scheduleEntry of scheduleEntries) {
        const scheduleEntryDurationSeconds =
            (scheduleEntry.end_at.getTime() - scheduleEntry.start_at.getTime()) / 1000
        const amountOwed = Math.round(
            amountPaidPerSecond * scheduleEntryDurationSeconds
        )

        userTotals[scheduleEntry.user_id] ||= 0
        userTotals[scheduleEntry.user_id] += amountOwed
    }

    return userTotals
}

// Given "pay per hour", convert the amount into "pay per second" to make
// calculations a bit easier. The result isn't rounded, which means we'll return
// fractions of a penny. That's OK, we'll round amounts later in the calculation.
const payPerSecond = (hourlyPay: number) => hourlyPay / 60 / 60

// generateOutput formats the amounts owed for each user into a string suitable for logging
// to the console or sending to an accountant.
const generateOutput = (userAmounts: AmountsOwed): string => {
    let output = "Copy the below into a CSV file and send it to the accountants:\n"
    for (let userID in userAmounts) {
        let amount = userAmounts[userID]
        output += `- User ${userID} is owed £${((amount * 1.0) / 100).toFixed(2)}\n`
    }
    return output
}


Interview Questions (1)

Q1
On-call Pay Calculator with Special Periods
Data Structures & AlgorithmsMedium

The task is to extend an existing on-call pay calculator to account for special pay periods like Christmas and New Year. Currently, the system pays a flat rate based on schedule entries. The goal is to modify the calculateUserTotals function to apply different hourly rates for time spent on-call during specified pay_config.json periods.

Background: Incident.io compensates individuals for being on-call at a flat rate of £5/hour, prorated. Monthly on-call data is processed to calculate payments.

The Challenge: Implement the ability to pay more for periods like Christmas and New Year. The pay_config.json already contains this data but isn't being used.

  • Pay periods will never overlap each other, but may overlap one or more schedule entries.
  • Pay periods can start and end at any time (not just whole days).
  • A failing test in calculateAmountsOwed.test.ts covers one scenario that needs to be addressed.

Input Examples:

entries (Schedule Entries):

{
  "entries": [
    {
      "user_id": "1",
      "start_at": "2024-11-02T16:00:00Z",
      "end_at": "2024-11-09T15:00:00Z"
    },
    ...
  ]
}

pay_config:

{
    "default_hourly_gbp": 500,
    "periods": [
        {
            "name": "Christmas,
            "start_at": "2024-12-23T00:00:00Z",
            "end_at": "2024-12-26T00:00:00Z",
            "hourly_gbp": 1000
        },
        {
            "name": "New Year",
            "start_at": "2024-12-31T00:00:00Z",
            "end_at": "2025-01-02T00:00:00Z",
            "hourly_gbp": 1500
        }
    ]
}

Existing Code:

export type PayPeriod = {
    name: string
    start_at: Date
    end_at: Date
    hourly_gbp: number
}

export type PayConfig = {
    default_hourly_gbp: number
    periods: PayPeriod[]
}

export type ScheduleEntry = {
    user_id: string
    start_at: Date
    end_at: Date
}

export type AmountsOwed = { [key: string]: number }

// calculateAmountsOwed calculates how much each person is owed and logs the output to console
export const calculateAmountsOwed = (scheduleEntries: ScheduleEntry[], payConfig: PayConfig): void => {
    const userTotals = calculateUserTotals(scheduleEntries, payConfig)
    console.log(generateOutput(userTotals))
}

// calculateUserTotals calculates how much each person is owed by adding up all their shifts
export const calculateUserTotals = (
    scheduleEntries: ScheduleEntry[],
    payConfig: PayConfig
): AmountsOwed => {
    let userTotals: AmountsOwed = {}
    const amountPaidPerSecond = payPerSecond(payConfig.default_hourly_gbp)

    for (const scheduleEntry of scheduleEntries) {
        const scheduleEntryDurationSeconds =
            (scheduleEntry.end_at.getTime() - scheduleEntry.start_at.getTime()) / 1000
        const amountOwed = Math.round(
            amountPaidPerSecond * scheduleEntryDurationSeconds
        )

        userTotals[scheduleEntry.user_id] ||= 0
        userTotals[scheduleEntry.user_id] += amountOwed
    }

    return userTotals
}

// Given "pay per hour", convert the amount into "pay per second" to make
// calculations a bit easier. The result isn't rounded, which means we'll return
// fractions of a penny. That's OK, we'll round amounts later in the calculation.
const payPerSecond = (hourlyPay: number) => hourlyPay / 60 / 60

// generateOutput formats the amounts owed for each user into a string suitable for logging
// to the console or sending to an accountant.
const generateOutput = (userAmounts: AmountsOwed): string => {
    let output = "Copy the below into a CSV file and send it to the accountants:\n"
    for (let userID in userAmounts) {
        let amount = userAmounts[userID]
        output += `- User ${userID} is owed £${((amount * 1.0) / 100).toFixed(2)}\n`
    }
    return output
}

Note on AI: The problem explicitly states that AI assistants should not be used.

Discussion (0)

Share your thoughts and ask questions

Join the Discussion

Sign in with Google to share your thoughts and ask questions

No comments yet

Be the first to share your thoughts and start the discussion!