Scenario:
A small business wants a simple program to calculate the total hours worked by employees in a week based on daily logs. Each log contains the employee’s name, date, and hours worked. The goal is to summarize the total hours per employee for the week.

Requirements:

  1. Input:

    • A list of work logs where each log includes:
      • employeeName (string): The name of the employee.
      • date (string): The date of the work log in YYYY-MM-DD format.
      • hoursWorked (number): The hours worked on that day.
    • An optional startDate and endDate to define the week (both in YYYY-MM-DD format).
  2. Output:

    • A summary object where:
      • The keys are employee names.
      • The values are the total hours worked by that employee during the week.
  3. Behavior:

    • Parse the input data.
    • Filter the logs to include only those within the startDate and endDate range (if provided).
    • Handle edge cases, such as overlapping date ranges or invalid input.
  4. Stretch Features:

    • Allow tracking overtime by flagging employees who worked more than 40 hours in the week.

Example Input:

typescript

Copy code

const logs = [ { employeeName: "Alice", date: "2024-12-01", hoursWorked: 8 }, { employeeName: "Bob", date: "2024-12-01", hoursWorked: 7.5 }, { employeeName: "Alice", date: "2024-12-02", hoursWorked: 9 }, { employeeName: "Alice", date: "2024-12-03", hoursWorked: 7 }, { employeeName: "Bob", date: "2024-12-03", hoursWorked: 8 }, { employeeName: "Alice", date: "2024-12-05", hoursWorked: 8 }, ]; const startDate = "2024-12-01"; const endDate = "2024-12-07";

Example Output:

typescript

Copy code

{ Alice: 32, // 8 + 9 + 7 + 8 Bob: 15.5 // 7.5 + 8 }


Tips:

  • Use libraries like date-fns or luxon for date parsing and filtering if desired.
  • Use a dictionary (Record<string, number>) to store employee totals for efficient lookups.
  • Test your solution with edge cases like overlapping date ranges, missing fields, or empty logs.

Would you like me to elaborate on how to approach solving this challenge in TypeScript?

My Answer, Attempt #1

I feel great about this! Got it in about 22 minutes:

/* input:
  above: name, date, hours worked
  optional: start and end

  output:
  object with name keys and hour values
*/


/*
questions / edge cases
- what if the hours worked is longer than 24 hours
  - ignore for now as we don't even know when the shifts start

data structures
- an object that has the name and hours worked

key activities
iterate through all logs
if there's a timerange, check if the range is in the timerange
get name, save it to our employee data structure


If I have time I'll define a
- datematching validation function

*/
interface Log {
  employeeName: string,
  date: string,
  hoursWorked: number
}

interface ParsedLog {
  name: string,
  date: Date,
  hoursWorked: number
}

interface TimeRange {
  startDate: string
  endDate: string
}

interface Employees {
  [key: string]: number
}

const logs = [
  { employeeName: "Alice", date: "2024-12-01", hoursWorked: 8 },
  { employeeName: "Bob", date: "2024-12-01", hoursWorked: 7.5 },
  { employeeName: "Alice", date: "2024-12-02", hoursWorked: 9 },
  { employeeName: "Alice", date: "2024-12-03", hoursWorked: 7 },
  { employeeName: "Bob", date: "2024-12-03", hoursWorked: 8 },
  { employeeName: "Alice", date: "2024-12-05", hoursWorked: 8 },
];

const startDate = "2024-12-01";
const endDate = "2024-12-07";

// console.log(getEmployeeWorkVolume(logs, {startDate, endDate}))
const hours = getEmployeeWorkVolume(logs)
console.log(hours)

function getEmployeeWorkVolume(logs: Log[], timeRange: TimeRange | null = null): Employees {

  const employees: Employees = {}

  let startDate: Date
  let endDate: Date
  if (timeRange){
    startDate = new Date(timeRange.startDate)
    endDate = new Date(timeRange.endDate)
  }
  // key activities
  // iterate through all logs
  // if there's a timerange, check if the range is in the timerange
  // get name, save it to our employee data structure

  const parsedLogs = logs.reduce<ParsedLog[]>((logs, currentLog)=>{
    
    if (timeRange){
      const parsedDate = new Date(currentLog.date)
      // TODO: I think that same datestrings will be the same timestamps, but it might be good to
      // compare on the day level rather than millisecond level, which is what is happening now
      if (parsedDate < startDate && parsedDate > endDate){
        return logs
      }
    }

    logs.push({
      name: currentLog.employeeName,
      date: new Date(currentLog.date),
      hoursWorked: currentLog.hoursWorked
    })

    return logs

  }, [])


  for (const log of parsedLogs){
    employees[log.name] = (employees[log.name] ?? 0) + log.hoursWorked
  }

  return employees

}

What I learned

At the end, when shit is getting crazy and you know you’re running out of time, it doesn’t really help to panic. This just hurts you. I think a little pressure is okay, a bit of speed, but I personally can’t work much faster than I already am. Not because I’m working super fast, just because I already need all the care and introspection I’m putting into these high-pressure programming sessions. I can’t afford to lose any.