Analyzing two sets of appointment schedules and resolving any overlapping conflicts

My goal is to dynamically generate available appointment times based on the number of employees working at a given time and the number of slots already filled. Let's say we have two employees working, one from 4:30 - 7:00 and the other from 4:30 - 7:30, with each appointment lasting 30 minutes. This information is used to populate the possibleAppointments array below.

const possibleAppointments = [
    { time: '4:30 PM' },
    { time: '4:30 PM' },
    { time: '5:00 PM' },
    { time: '5:00 PM' },
    { time: '5:30 PM' },
    { time: '5:30 PM' },
    { time: '6:00 PM' },
    { time: '6:00 PM' },
    { time: '6:30 PM' },
    { time: '6:30 PM' },
    { time: '7:00 PM' },
];

const reservedAppointments = [
    { time: '05:00 PM' }, // ends at 5:30
    { time: '6:10 PM' }, // ends at 6:40
    { time: '6:10 PM' }, // ends at 6:40
];

I am looking to utilize the possibleAppointments and reservedAppointments arrays above to construct an availableAppointments array that excludes any conflicting time slots. The result should resemble the following array:

// availableAppointments
[
  { time: '4:30 PM' },
  { time: '4:30 PM' },
  { time: '5:00 PM' },
  { time: '5:30 PM' },
  { time: '5:30 PM' },
  { time: '7:00 PM' },
]

You can see one of my attempts using Stackblitz here: https://stackblitz.com/edit/angular-ivy-7h58ga?file=src/app/app.component.ts

I've been struggling with this for quite some time. How can I adjust the logic in the Stackblitz example to achieve the desired result where

availableAppointments === [
      { time: '4:30 PM' },
      { time: '4:30 PM' },
      { time: '5:00 PM' },
      { time: '5:30 PM' },
      { time: '5:30 PM' },
      { time: '7:00 PM' },
    ]

Answer №1

If you want to simplify this, you can convert it into a direct filter() function call. However, to handle the scenario where there are double appointments at the same time slot, you must keep track of which employee each available and reserved appointment belongs to. If not, a single reservation at 5:00 would exclude both possible appointments at 5:00.

const possibleAppointments = [
  { time: '4:30 PM', empl: 1 },
  { time: '4:30 PM', empl: 2 },
  { time: '5:00 PM', empl: 1 },
  { time: '5:00 PM', empl: 2 },
  { time: '5:30 PM', empl: 1 },
  { time: '5:30 PM', empl: 2 },
  { time: '6:00 PM', empl: 1 },
  { time: '6:00 PM', empl: 2 },
  { time: '6:30 PM', empl: 1 },
  { time: '6:30 PM', empl: 2 },
  { time: '7:00 PM', empl: 1 },
];

const reservedAppointments = [
  { time: '05:00 PM', empl: 1 }, // ends at 5:30
  { time: '6:10 PM', empl: 1 }, // ends at 6:40
  { time: '6:10 PM', empl: 2 }, // ends at 6:40
];

const availableAppointments = this.possibleAppointments.filter(possibleAppt => {
  return !this.reservedAppointments.some(rAppt => (
    this.checkIfApptsOverlap(rAppt, possibleAppt) && possibleAppt.empl === rAppt.empl))
});

Answer №2

It can be incredibly challenging to determine time overlaps based on a vague string such as 6:10pm. To simplify this process, I recommend assigning numeric range representations to your times initially. This will enhance the organization of your code and provide ample flexibility for future modifications. For instance, dividing the day into 1440 minutes and allocating a range to each time slot can streamline the identification of overlaps between ranges. However, it is important to note that managing multiple employees and appointments overlapping various slots can add complexity to this task.

Let's consider you followed my suggestion regarding minute-range assignments in the following manner:

0:00 - 0:59 (0 - 59 minutes from start of day)
1:00 - 1:59 (60 - 119 minutes)
2:00 - 2:59 (120 - 179 minutes)
...

When reaching 4:30pm, you would be at:

16:30 - 17:00 (990 - 1019 minutes)
17:00 - 17:30 (1020 - 1049 minutes)

If you have correctly assigned minute representations to your arrays of potential and reserved appointments, the process of obtaining an available slot should be straightforward with considerations for any irregular appointments or multiple employees.

const possibleAppointments = [
    { time: '4:30 PM', start_minutes: 990, end_minutes: 1019 },
    { time: '4:30 PM', start_minutes: 990, end_minutes: 1019 },
    { time: '5:00 PM', start_minutes: 1020, end_minutes: 1049 },
    { time: '5:00 PM', start_minutes: 1020, end_minutes: 1049 },
    { time: '5:30 PM', start_minutes: 1050, end_minutes: 1079 },
    { time: '5:30 PM', start_minutes: 1050, end_minutes: 1079 },
    { time: '6:00 PM', start_minutes: 1080, end_minutes: 1109  },
    { time: '6:00 PM', start_minutes: 1080, end_minutes: 1109  },
    { time: '6:30 PM', start_minutes: 1110, end_minutes: 1139 },
    { time: '6:30 PM', start_minutes: 1110, end_minutes: 1139 },
    { time: '7:00 PM', start_minutes: 1140, end_minutes: 1169 },
];

const reservedAppointments = [
    { time: '5:00 PM', start_minutes: 1020, end_minutes: 1049 }, // ends at 5:30
    { time: '6:10 PM', start_minutes: 1090, end_minutes: 1119 }, // ends at 6:40
    { time: '6:10 PM', start_minutes: 1090, end_minutes: 1119 }, // ends at 6:40
];



reservedAppointments.forEach(taken_slot => {
    const indexes_to_remove = [];
    const times_removed = [];
    for(let i = 0; i < possibleAppointments.length; i++){
        const ind = possibleAppointments.findIndex(item =>
            !times_removed.includes(item.time)  &&
            ((item.start_minutes >= taken_slot.start_minutes && item.start_minutes <= taken_slot.end_minutes) ||
            (item.end_minutes >= taken_slot.start_minutes && item.end_minutes <= taken_slot.end_minutes))
        )
        if(ind === -1)
            break
        else {
            indexes_to_remove.push(ind)
            times_removed.push(possibleAppointments[ind].time)
        }
    }

    for (let i = indexes_to_remove.length -1; i >= 0; i--)
        possibleAppointments.splice(indexes_to_remove[i], 1);
})

console.log(possibleAppointments)

Keep in mind that the possibleAppointments array is directly modified to create the desired availableAppointments array. If you wish to preserve the original variable, you can clone it using:

const availableAppointments = [...possibleAppointments]
and iterate through availableAppointments instead.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Encountered an error: Uncaught TypeError - Unable to access the 'format' property of an undefined object at the specified time

I encountered an issue with the following line of code let FullDate = moment(1499153561479).add(currentSeconds, 'seconds').tz(citiesT[id]).format("DD-MM-YYYY HH:mm:ss a"); Any suggestions on how to resolve this error? ...

What is the best way to have Discord.js select randomly between two images?

const BaseCommand = require('../../utils/structures/BaseCommand'); const Discord = require("Discord.js"); module.exports = class VibeCheckCommand extends BaseCommand { constructor() { super('vibecheck', 'fun', []); } ...

Knockout JS cooperates well with Ratchet and push.js, but things take a turn when I incorporate a data-transition

For my mobile web app, I'm utilizing the Ratchet.js/push.js library to create the UI. This library handles links by pushing the to-be-loaded file into the ".content" DOM element instead of loading the entire page. However, a drawback is that push.js d ...

Utilizing Vue.js to pass a slot to a customized Bootstrap-Vue Table component

I am currently in the process of developing a wrapper for the bootstrap-vue Table component. This particular component utilizes slots to specify cell templates, similar to the following example: <b-table :items="itemsProvider" v-bind="options"> ...

Accessing information from a json response using an ajax request

Currently, I am making an ajax call to fetch the longitude and latitude based on a pin code. Here is how I approached it: $(document).ready(function () { $.ajax({ type: "GET", url: "http://maps.googleapis.com/ma ...

Should you hold off on moving forward until the asynchronous task finishes?

My goal is to retrieve location coordinates using the Google Maps JavaScript API in an asynchronous manner. Below is the function I've created for this purpose: function fetchCoordinates(address) { var geocoder = new google.maps.Geocoder(); ...

Updating a specific array entry in Jquery with custom results

In my form, there are pre-populated fields sourced from a database with data and ID values. Users can add, edit, or delete rows and then save the changes. To optimize data transmission, I am only sending back an array containing entries that have been modi ...

What is the best method to assign a property to a model within AngularJS by utilizing an attribute parameter?

I am in the process of creating a custom directive in AngularJS for a UI slider that can be used multiple times. Each slider should be able to bind to a specific property. My idea was to use an attribute called "property" which would automatically update w ...

What is preventing me from displaying an AJAX JSON value on my website?

Below is the code snippet: <ul> <li v-for="value in RandomTopic" :key="value.id">{{ value.title }}</li> </ul> export default { data() { return { RandomTopic: null } }, mounted() { ///so ...

Using Array.map in combination with try/catch can result in delayed reference assignment

After observing a delay in referencing after using [].map with try/catch block inside, I am curious to know the reason behind this behavior and how to prevent it. My test scenario was as follows: -file_picked is responsible for handling the change event ...

Tips for effectively utilizing innerHTML in this particular scenario

For an assignment, we were tasked with creating a Madlib game where users input words into textfields to replace certain words in a hidden paragraph within the HTML using JavaScript and CSS. The paragraph embedded in the HTML page is as follows: <span ...

Having trouble with a one-dimensional array of multiples of 5 in my coding practice. It's a new concept for me and I'm

Here is the task at hand: Create a program that will assign and store the first 20 multiples of 5 in an array called Data. No other array can be used in this program. The program should output the elements of the array as follows: a) Write only the com ...

Passing values from Node.js asynchronous functions

I am facing an issue with my code. I am trying to retrieve the value stored in the _status variable after executing a query and writing a file using MongoClient.connect. However, when I try to return _status, it returns as NULL. Can anyone suggest how I ...

Maintain gridview header functionality while using JQuery to fix it

While I may not be a JQuery expert, I do have this code that successfully fixes the header: $(document).ready(function () { fixedHeader() }); function fixedHeader() { // Code to duplicate the gridview header with styles v ...

The mesmerizing world of Vue templates and transition groups

My previous simple list had transitions working perfectly, but now that I am using components and templates the transitions no longer work. Can anyone help me understand why? I want each item to animate individually, but it seems like all items are transi ...

Ensuring Next.js doesn't create specific files at certain paths

Currently in the process of developing a custom e-commerce extension using Node.js, Koa, React, and Next.js for various platforms like Shopify and BigCommerce. Within the codebase, I'm faced with the challenge of handling URL methods that should stri ...

An algorithm for determining the frequency of an element within an array with a time complexity of O

Is there an efficient algorithm that can determine if a certain frequency percentage of array elements exists in an array of length n, all in linear time? While selection sort is O(n^2) and the majority algorithm has a time complexity of O(n), it can only ...

Data binding in AngularJS allows for easy synchronization between the model and the view

I've been working on a simple AngularJS application that includes a form with two fields. However, I've run into an issue where I'm unable to read the values entered in these fields from my controller, as I keep getting 'undefined' ...

Storing numerical values from a text file in an array

I need to extract numbers from a file and store them in an array. 3 2 15 41 4 1 2 3 4 3 22 11 24 The first line indicates the number of lines that follow (maximum 100). Each line can contain up to 50 numbers. To store these numbers in an array, it shoul ...

Avoiding PHP Execution When Loading From Browser Cache?

One thing I'm trying to understand is how sites like Facebook keep their dynamically generated sidebars, such as the "People you may know," consistent even when users navigate back and forth through their browsing history. On my own site, however, eve ...