Updates
This commit is contained in:
@@ -68,7 +68,7 @@
|
|||||||
background-color: #333;
|
background-color: #333;
|
||||||
}
|
}
|
||||||
.holiday {
|
.holiday {
|
||||||
background-color: #555;
|
background-color: #3b1e6e;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
.optimized {
|
.optimized {
|
||||||
|
|||||||
+217
-31
@@ -13,6 +13,7 @@
|
|||||||
let holidays = [];
|
let holidays = [];
|
||||||
let daysOff = 24; // Default days off per year
|
let daysOff = 24; // Default days off per year
|
||||||
let optimizedDaysOff = [];
|
let optimizedDaysOff = [];
|
||||||
|
let extendedHolidays = [];
|
||||||
|
|
||||||
function handleYearChange(event) {
|
function handleYearChange(event) {
|
||||||
year = parseInt(event.target.value);
|
year = parseInt(event.target.value);
|
||||||
@@ -40,9 +41,127 @@
|
|||||||
}));
|
}));
|
||||||
console.log('Holidays:', holidays);
|
console.log('Holidays:', holidays);
|
||||||
optimizeDaysOff();
|
optimizeDaysOff();
|
||||||
|
calculateExtendedHolidays();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function optimizeDaysOff() {
|
||||||
|
// Reset optimized days off
|
||||||
|
optimizedDaysOff = [];
|
||||||
|
|
||||||
|
// Combine holidays and weekends
|
||||||
|
const allDays = holidays.map(h => h.date);
|
||||||
|
let daysToUse = daysOff;
|
||||||
|
|
||||||
|
// Create a list of potential days to take off, sorted by their potential to extend holidays
|
||||||
|
const potentialDaysOff = [];
|
||||||
|
|
||||||
|
for (let month = 0; month < 12; month++) {
|
||||||
|
for (let day = 1; day <= 31; day++) {
|
||||||
|
const date = new Date(year, month, day);
|
||||||
|
if (date.getMonth() !== month) break; // Skip invalid dates
|
||||||
|
|
||||||
|
const isWeekend = date.getDay() === 0 || date.getDay() === 6;
|
||||||
|
const isHoliday = allDays.some(d => d.getTime() === date.getTime());
|
||||||
|
|
||||||
|
if (!isWeekend && !isHoliday) {
|
||||||
|
const prevDay = new Date(date);
|
||||||
|
prevDay.setDate(date.getDate() - 1);
|
||||||
|
const nextDay = new Date(date);
|
||||||
|
nextDay.setDate(date.getDate() + 1);
|
||||||
|
|
||||||
|
const extendsHoliday =
|
||||||
|
allDays.some(d => d.getTime() === prevDay.getTime()) ||
|
||||||
|
allDays.some(d => d.getTime() === nextDay.getTime());
|
||||||
|
|
||||||
|
if (extendsHoliday) {
|
||||||
|
potentialDaysOff.push(date);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sort potential days off by their ability to extend existing chains with multiple holidays
|
||||||
|
potentialDaysOff.sort((a, b) => {
|
||||||
|
const aConsecutive = calculateConsecutiveDaysIncludingHoliday(a, allDays);
|
||||||
|
const bConsecutive = calculateConsecutiveDaysIncludingHoliday(b, allDays);
|
||||||
|
return bConsecutive - aConsecutive || a.getTime() - b.getTime();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Select days off from the sorted list, prioritizing those that extend chains with multiple holidays
|
||||||
|
for (let i = 0; i < potentialDaysOff.length && daysToUse > 0; i++) {
|
||||||
|
const date = potentialDaysOff[i];
|
||||||
|
const prevDay = new Date(date);
|
||||||
|
prevDay.setDate(date.getDate() - 1);
|
||||||
|
const nextDay = new Date(date);
|
||||||
|
nextDay.setDate(date.getDate() + 1);
|
||||||
|
|
||||||
|
// Check if adding this day creates a longer chain with multiple holidays
|
||||||
|
if (calculateConsecutiveDaysIncludingHoliday(date, allDays) > 0) {
|
||||||
|
optimizedDaysOff.push(date);
|
||||||
|
daysToUse--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Attempt to create full week chains
|
||||||
|
if (daysToUse > 0) {
|
||||||
|
for (let i = 0; i < optimizedDaysOff.length && daysToUse > 0; i++) {
|
||||||
|
const date = optimizedDaysOff[i];
|
||||||
|
const startOfWeek = new Date(date);
|
||||||
|
startOfWeek.setDate(date.getDate() - date.getDay() + 1); // Start of the week (Monday)
|
||||||
|
const endOfWeek = new Date(startOfWeek);
|
||||||
|
endOfWeek.setDate(startOfWeek.getDate() + 4); // End of the week (Friday)
|
||||||
|
|
||||||
|
for (let d = new Date(startOfWeek); d <= endOfWeek && daysToUse > 0; d.setDate(d.getDate() + 1)) {
|
||||||
|
if (!optimizedDaysOff.some(optDate => optDate.getTime() === d.getTime()) && !allDays.some(holiday => holiday.getTime() === d.getTime())) {
|
||||||
|
optimizedDaysOff.push(new Date(d));
|
||||||
|
daysToUse--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('Optimized Days Off:', optimizedDaysOff);
|
||||||
|
}
|
||||||
|
|
||||||
|
function calculateConsecutiveDaysIncludingHoliday(date, allDays) {
|
||||||
|
let consecutiveDays = 0;
|
||||||
|
let prevDay = new Date(date);
|
||||||
|
let nextDay = new Date(date);
|
||||||
|
let includesHoliday = false;
|
||||||
|
let holidayCount = 0;
|
||||||
|
|
||||||
|
// Count consecutive days before the date
|
||||||
|
while (true) {
|
||||||
|
prevDay.setDate(prevDay.getDate() - 1);
|
||||||
|
if (prevDay.getDay() === 0 || prevDay.getDay() === 6 || allDays.some(d => d.getTime() === prevDay.getTime())) {
|
||||||
|
consecutiveDays++;
|
||||||
|
if (allDays.some(d => d.getTime() === prevDay.getTime())) {
|
||||||
|
includesHoliday = true;
|
||||||
|
holidayCount++;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Count consecutive days after the date
|
||||||
|
while (true) {
|
||||||
|
nextDay.setDate(nextDay.getDate() + 1);
|
||||||
|
if (nextDay.getDay() === 0 || nextDay.getDay() === 6 || allDays.some(d => d.getTime() === nextDay.getTime())) {
|
||||||
|
consecutiveDays++;
|
||||||
|
if (allDays.some(d => d.getTime() === nextDay.getTime())) {
|
||||||
|
includesHoliday = true;
|
||||||
|
holidayCount++;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return includesHoliday ? holidayCount : 0;
|
||||||
|
}
|
||||||
|
|
||||||
function formatDate(date) {
|
function formatDate(date) {
|
||||||
return date.toLocaleDateString('en-US', { month: 'short', day: 'numeric' });
|
return date.toLocaleDateString('en-US', { month: 'short', day: 'numeric' });
|
||||||
}
|
}
|
||||||
@@ -52,6 +171,7 @@
|
|||||||
if (!isNaN(value)) {
|
if (!isNaN(value)) {
|
||||||
daysOff = value;
|
daysOff = value;
|
||||||
optimizeDaysOff();
|
optimizeDaysOff();
|
||||||
|
calculateExtendedHolidays();
|
||||||
} else {
|
} else {
|
||||||
event.target.textContent = daysOff; // Revert to previous valid value if input is invalid
|
event.target.textContent = daysOff; // Revert to previous valid value if input is invalid
|
||||||
}
|
}
|
||||||
@@ -62,41 +182,107 @@
|
|||||||
event.target.textContent = value.replace(/\D/g, '');
|
event.target.textContent = value.replace(/\D/g, '');
|
||||||
}
|
}
|
||||||
|
|
||||||
function optimizeDaysOff() {
|
function calculateExtendedHolidays() {
|
||||||
// Reset optimized days off
|
const allDays = holidays.map(h => h.date); // Include all holiday dates
|
||||||
optimizedDaysOff = [];
|
let remainingDaysOff = daysOff; // Track remaining days off
|
||||||
|
|
||||||
// Combine holidays and weekends
|
extendedHolidays = holidays
|
||||||
const allDays = holidays.map(h => h.date);
|
.filter(holiday => holiday.date.getDay() !== 0 && holiday.date.getDay() !== 6) // Only non-weekend holidays
|
||||||
let daysToUse = daysOff;
|
.map(holiday => {
|
||||||
|
let startDate = new Date(holiday.date);
|
||||||
for (let month = 0; month < 12; month++) {
|
let endDate = new Date(holiday.date);
|
||||||
for (let day = 1; day <= 31; day++) {
|
let daysUsed = 0;
|
||||||
const date = new Date(year, month, day);
|
|
||||||
if (date.getMonth() !== month) break; // Skip invalid dates
|
|
||||||
|
|
||||||
const isWeekend = date.getDay() === 0 || date.getDay() === 6;
|
|
||||||
const isHoliday = allDays.some(d => d.getTime() === date.getTime());
|
|
||||||
|
|
||||||
// Check if the day before or after a weekend/holiday can be used to extend it
|
|
||||||
if ((isWeekend || isHoliday) && daysToUse > 0) {
|
|
||||||
const prevDay = new Date(date);
|
|
||||||
prevDay.setDate(date.getDate() - 1);
|
|
||||||
const nextDay = new Date(date);
|
|
||||||
nextDay.setDate(date.getDate() + 1);
|
|
||||||
|
|
||||||
|
// Extend before the holiday
|
||||||
|
while (daysUsed < remainingDaysOff) {
|
||||||
|
const prevDay = new Date(startDate);
|
||||||
|
prevDay.setDate(startDate.getDate() - 1);
|
||||||
if (!allDays.some(d => d.getTime() === prevDay.getTime()) && prevDay.getDay() !== 0 && prevDay.getDay() !== 6) {
|
if (!allDays.some(d => d.getTime() === prevDay.getTime()) && prevDay.getDay() !== 0 && prevDay.getDay() !== 6) {
|
||||||
optimizedDaysOff.push(new Date(prevDay));
|
startDate = prevDay;
|
||||||
daysToUse--;
|
daysUsed++;
|
||||||
} else if (!allDays.some(d => d.getTime() === nextDay.getTime()) && nextDay.getDay() !== 0 && nextDay.getDay() !== 6) {
|
} else {
|
||||||
optimizedDaysOff.push(new Date(nextDay));
|
break;
|
||||||
daysToUse--;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Extend after the holiday
|
||||||
|
while (daysUsed < remainingDaysOff) {
|
||||||
|
const nextDay = new Date(endDate);
|
||||||
|
nextDay.setDate(endDate.getDate() + 1);
|
||||||
|
if (!allDays.some(d => d.getTime() === nextDay.getTime()) && nextDay.getDay() !== 0 && nextDay.getDay() !== 6) {
|
||||||
|
endDate = nextDay;
|
||||||
|
daysUsed++;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
remainingDaysOff -= daysUsed; // Deduct used days from remaining
|
||||||
|
|
||||||
|
// Calculate total consecutive days including weekends
|
||||||
|
const totalDays = calculateTotalConsecutiveDays(startDate, endDate, allDays);
|
||||||
|
|
||||||
|
return {
|
||||||
|
holidayName: holiday.name,
|
||||||
|
startDate: formatDate(startDate),
|
||||||
|
endDate: formatDate(endDate),
|
||||||
|
totalDays
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
// If there are remaining days off, try to use them to extend any holiday further
|
||||||
|
if (remainingDaysOff > 0) {
|
||||||
|
extendedHolidays.forEach(extended => {
|
||||||
|
let startDate = new Date(extended.startDate);
|
||||||
|
let endDate = new Date(extended.endDate);
|
||||||
|
|
||||||
|
// Extend before the holiday
|
||||||
|
while (remainingDaysOff > 0) {
|
||||||
|
const prevDay = new Date(startDate);
|
||||||
|
prevDay.setDate(startDate.getDate() - 1);
|
||||||
|
if (!allDays.some(d => d.getTime() === prevDay.getTime()) && prevDay.getDay() !== 0 && prevDay.getDay() !== 6) {
|
||||||
|
startDate = prevDay;
|
||||||
|
remainingDaysOff--;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extend after the holiday
|
||||||
|
while (remainingDaysOff > 0) {
|
||||||
|
const nextDay = new Date(endDate);
|
||||||
|
nextDay.setDate(endDate.getDate() + 1);
|
||||||
|
if (!allDays.some(d => d.getTime() === nextDay.getTime()) && nextDay.getDay() !== 0 && nextDay.getDay() !== 6) {
|
||||||
|
endDate = nextDay;
|
||||||
|
remainingDaysOff--;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extended.startDate = formatDate(startDate);
|
||||||
|
extended.endDate = formatDate(endDate);
|
||||||
|
extended.totalDays = calculateTotalConsecutiveDays(startDate, endDate, allDays);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function calculateTotalConsecutiveDays(startDate, endDate, allDays) {
|
||||||
|
let totalDays = 0;
|
||||||
|
let currentDate = new Date(startDate);
|
||||||
|
|
||||||
|
while (currentDate <= endDate) {
|
||||||
|
const isWeekend = currentDate.getDay() === 0 || currentDate.getDay() === 6;
|
||||||
|
const isHoliday = allDays.some(d => d.getTime() === currentDate.getTime());
|
||||||
|
|
||||||
|
if (isWeekend || isHoliday || optimizedDaysOff.some(d => d.getTime() === currentDate.getTime())) {
|
||||||
|
totalDays++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
currentDate.setDate(currentDate.getDate() + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('Optimized Days Off:', optimizedDaysOff);
|
return totalDays;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize holidays on load
|
// Initialize holidays on load
|
||||||
@@ -201,11 +387,11 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
There are {holidays.length} public holidays in {selectedCountry}:
|
Extended Holidays:
|
||||||
<ul>
|
<ul>
|
||||||
{#each holidays as holiday}
|
{#each extendedHolidays as extended}
|
||||||
<li class={optimizedDaysOff.some(d => d.getTime() === holiday.date.getTime()) ? 'highlight' : ''}>
|
<li>
|
||||||
{holiday.name} on {formatDate(holiday.date)}
|
{extended.totalDays} day holiday, including {extended.holidayName} from {extended.startDate} to {extended.endDate}
|
||||||
</li>
|
</li>
|
||||||
{/each}
|
{/each}
|
||||||
</ul>
|
</ul>
|
||||||
|
|||||||
Reference in New Issue
Block a user