AtoZ Arbeitszeitenrechner

Arbeitszeitrechner für AtoZ - Deutsch

目前為 2025-04-08 提交的版本,檢視 最新版本

// ==UserScript==
// @name         AtoZ Arbeitszeitenrechner
// @namespace    https://atoz.amazon.work
// @version      1.0
// @description  Arbeitszeitrechner für AtoZ - Deutsch
// @author       @celvip
// @match        https://atoz.amazon.work/timecard*
// @match        https://atoz.amazon.work/schedule*
// @grant        GM_setValue
// @grant        GM_getValue
// ==/UserScript==

(function() {
    'use strict';

    let breakTime = GM_getValue('breakTime', 30);
    let workTime = GM_getValue('workTime', 8);
    const FIXED_MAX_BREAK = 45; // Feste Pausenzeit für maximale Arbeitszeit

    // Erweiterte Übersetzungen für verschiedene Sprachen und Variationen
    const TRANSLATIONS = {
        IN: ['Einstempeln', 'Clock in', 'Punch in', 'In'],
        OUT: ['Ausstempeln', 'Clock out', 'Punch out', 'Out'],
        MISSING: ['Fehlende Stempelzeit', 'Missing punch', 'Missed Punch', 'Missed punch', '--:--']
    };

    const COLORS = {
        GREEN: {
            bg: '#c6efce',
            text: '#006100'
        },
        YELLOW: {
            bg: '#ffeb9c',
            text: '#9c6500'
        },
        RED: {
            bg: '#ffc7ce',
            text: '#9c0006'
        }
    };

function findPunchTimes() {
    let punchInTime = null;
    let punchOutTime = null;
    let missingPunch = false;

    console.log("Suche nach Stempelzeiten/Searching for punch times...");

    // Definiere Suchbegriffe für beide Sprachen
    const searchTerms = {
        punchIn: ['Einstempeln', 'Clock In', 'Punch In', 'Time In', 'In'],
        punchOut: ['Ausstempeln', 'Clock Out', 'Punch Out', 'Time Out', 'Out'],
        missing: ['Fehlende Stempelzeit', 'Missing Punch', 'Missed Punch', '--:--']
    };

    // Suche nach allen Elementen, die Text enthalten
    const elements = document.getElementsByTagName('*');

    for (const element of elements) {
        const text = element.textContent.trim();

        // Suche nach Einstempeln/Clock In
        if (searchTerms.punchIn.some(term => text.includes(term))) {
            const timeMatch = text.match(/\d{1,2}:\d{2}/);
            if (timeMatch) {
                punchInTime = timeMatch[0].padStart(5, '0');
                console.log("Einstempelzeit/Punch in time found:", punchInTime);
            }
        }

        // Suche nach Fehlende Stempelzeit/Missing Punch
        if (searchTerms.missing.some(term => text.includes(term))) {
            missingPunch = true;
            console.log("Fehlende Stempelzeit/Missing punch found");
        }

        // Wenn keine fehlende Stempelzeit, suche nach Ausstempeln/Clock Out
        if (!missingPunch && searchTerms.punchOut.some(term => text.includes(term))) {
            const timeMatch = text.match(/\d{1,2}:\d{2}/);
            if (timeMatch) {
                punchOutTime = timeMatch[0].padStart(5, '0');
                console.log("Ausstempelzeit/Punch out time found:", punchOutTime);
            }
        }
    }

    // Alternative Suchmethode für komplexere Fälle
    if (!punchInTime) {
        const timeNodes = document.evaluate(
            "//*[contains(text(), ':')]",
            document,
            null,
            XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE,
            null
        );

        for (let i = 0; i < timeNodes.snapshotLength; i++) {
            const node = timeNodes.snapshotItem(i);
            const text = node.textContent.trim();
            const timeMatch = text.match(/\d{1,2}:\d{2}/);

            if (timeMatch) {
                const parentText = node.parentElement?.textContent.toLowerCase() || '';
                if (searchTerms.punchIn.some(term => parentText.toLowerCase().includes(term.toLowerCase()))) {
                    punchInTime = timeMatch[0].padStart(5, '0');
                    console.log("Alternative method - Punch in time found:", punchInTime);
                } else if (!missingPunch && searchTerms.punchOut.some(term => parentText.toLowerCase().includes(term.toLowerCase()))) {
                    punchOutTime = timeMatch[0].padStart(5, '0');
                    console.log("Alternative method - Punch out time found:", punchOutTime);
                }
            }
        }
    }

    // Wenn "Fehlende Stempelzeit" gefunden wurde, setze Ausstempelzeit zurück
    if (missingPunch) {
        punchOutTime = null;
    }

    console.log("Final times - In:", punchInTime, "Out:", punchOutTime, "Missing:", missingPunch);
    return { punchInTime, punchOutTime };
}

    function getCurrentWorktime(startTime, endTime) {
        if (endTime) {
            return getTimeDifference(startTime, endTime);
        }

        const now = new Date();
        const nowHours = now.getHours();
        const nowMinutes = now.getMinutes();
        const [startHours, startMinutes] = startTime.split(':').map(Number);

        let hours = nowHours - startHours;
        let minutes = nowMinutes - startMinutes;

        if (minutes < 0) {
            hours--;
            minutes += 60;
        }
        if (hours < 0) {
            hours += 24;
        }

        return hours + (minutes / 60);
    }
        function getTimeDifference(startTime, endTime) {
        const [startHours, startMinutes] = startTime.split(':').map(Number);
        const [endHours, endMinutes] = endTime.split(':').map(Number);

        let hours = endHours - startHours;
        let minutes = endMinutes - startMinutes;

        if (minutes < 0) {
            hours--;
            minutes += 60;
        }
        if (hours < 0) {
            hours += 24;
        }

        return hours + (minutes / 60);
    }

    function getBackgroundColor(hours) {
        if (hours <= 8.5) return COLORS.GREEN;
        if (hours <= 10) return COLORS.YELLOW;
        return COLORS.RED;
    }

    function calculateEndTime(startTime, workHours, breakMinutes) {
        const [hours, minutes] = startTime.split(':').map(Number);
        let endHours = hours + workHours;
        let endMinutes = minutes + breakMinutes;

        if (endMinutes >= 60) {
            endHours += Math.floor(endMinutes / 60);
            endMinutes = endMinutes % 60;
        }
        if (endHours >= 24) {
            endHours -= 24;
        }

        return `${String(endHours).padStart(2, '0')}:${String(endMinutes).padStart(2, '0')}`;
    }

    function formatHoursAndMinutes(hours) {
        if (isNaN(hours)) return "0:00";

        const fullHours = Math.floor(hours);
        const minutes = Math.round((hours - fullHours) * 60);
        return `${fullHours}h ${minutes.toString().padStart(2, '0')}min`;
    }

    function updateDisplay(punchInTime = null, punchOutTime = null) {
        const display = document.getElementById('timeCalculator');

        if (display) {
            let content;
            const currentTime = new Date().toLocaleTimeString('de-DE', { hour: '2-digit', minute: '2-digit', second: '2-digit' });

            if (punchInTime) {
                const currentWorktime = getCurrentWorktime(punchInTime, punchOutTime);
                const colors = getBackgroundColor(currentWorktime);
                const maxEndTime = calculateEndTime(punchInTime, 10, FIXED_MAX_BREAK);

                display.style.backgroundColor = colors.bg;
                content = `
                    <div style="margin-bottom: 12px; font-weight: bold; color: ${colors.text}; font-size: 20px; text-align: center;"><u>Arbeitszeitenrechner</u></div>
                    <div style="margin-bottom: 8px; color: ${colors.text};">Aktuelle Zeit: <strong>${currentTime}</strong></div>
                    <div style="margin-bottom: 8px; color: ${colors.text};">Einstempelzeit: <strong>${punchInTime}</strong></div>
                    ${punchOutTime ? `<div style="margin-bottom: 8px; color: ${colors.text};">Ausstempelzeit: <strong>${punchOutTime}</strong></div>` : ''}
                    <div style="margin-bottom: 8px; color: ${colors.text};">
                        Arbeitszeit:
                        <select id="workTimeSelect" style="margin-left: 5px; background-color: white;">
                            <option value="6" ${workTime === 6 ? 'selected' : ''}>6 Stunden</option>
                            <option value="8" ${workTime === 8 ? 'selected' : ''}>8 Stunden</option>
                            <option value="9" ${workTime === 9 ? 'selected' : ''}>9 Stunden</option>
                            <option value="10" ${workTime === 10 ? 'selected' : ''}>10 Stunden</option>
                        </select>
                    </div>
                    <div style="margin-bottom: 8px; color: ${colors.text};">
                        Pausenzeit:
                        <select id="breakTimeSelect" style="margin-left: 5px; background-color: white;">
                            <option value="0" ${breakTime === 0 ? 'selected' : ''}>Keine Pause</option>
                            <option value="30" ${breakTime === 30 ? 'selected' : ''}>30 Minuten</option>
                            <option value="45" ${breakTime === 45 ? 'selected' : ''}>45 Minuten</option>
                            <option value="60" ${breakTime === 60 ? 'selected' : ''}>60 Minuten</option>
                        </select>
                    </div>
                    ${!punchOutTime ? `
                    <div style="margin-top: 12px; font-weight: bold; color: ${colors.text};">
                        Geplantes Arbeitsende: <strong>${calculateEndTime(punchInTime, workTime, breakTime)}</strong>
                    </div>
                    <div style="margin-top: 4px; font-weight: bold; color: red;">
                        Spätestes Arbeitsende: <span style="color: red; font-weight: bold; background-color: #ffdddd; padding: 2px 5px; border-radius: 3px;">❗${maxEndTime}❗</span>
                    </div>
                    ` : ''}
                    <div style="font-size: 12px; color: ${colors.text}; margin-top: 8px;">
                        ${punchOutTime ? 'Gesamte' : 'Aktuelle'} Arbeitszeit: ${formatHoursAndMinutes(currentWorktime)}
                    </div>
                    ${!punchOutTime ? `
                        <div style="font-size: 12px; color: ${colors.text}; margin-top: 4px;">
                            Geplante Gesamtzeit: ${workTime}h ${breakTime}min
                        </div>
                        <div style="font-size: 12px; color: ${colors.text}; margin-top: 4px;">
                            Maximale Gesamtzeit: 10h ${FIXED_MAX_BREAK}min
                        </div>
                    ` : ''}
                `;
            } else {
                display.style.backgroundColor = 'white';
                content = `
                    <div style="margin-bottom: 12px; font-weight: bold; color: #666;">Arbeitszeitrechner</div>
                    <div style="margin-bottom: 8px; color: #666;">Aktuelle Zeit: <strong>${currentTime}</strong></div>
                    <div style="margin-bottom: 8px; color: #666;">Einstempelzeit: <strong>Keine Stempelzeit gefunden</strong></div>
                    <div style="margin-bottom: 8px; color: #666;">
                        Arbeitszeit:
                        <select id="workTimeSelect" style="margin-left: 5px; background-color: white;">
                            <option value="6" ${workTime === 6 ? 'selected' : ''}>6 Stunden</option>
                            <option value="8" ${workTime === 8 ? 'selected' : ''}>8 Stunden</option>
                            <option value="9" ${workTime === 9 ? 'selected' : ''}>9 Stunden</option>
                            <option value="10" ${workTime === 10 ? 'selected' : ''}>10 Stunden</option>
                        </select>
                    </div>
                    <div style="margin-bottom: 8px; color: #666;">
                        Pausenzeit:
                        <select id="breakTimeSelect" style="margin-left: 5px; background-color: white;">
                            <option value="30" ${breakTime === 30 ? 'selected' : ''}>30 Minuten</option>
                            <option value="45" ${breakTime === 45 ? 'selected' : ''}>45 Minuten</option>
                            <option value="60" ${breakTime === 60 ? 'selected' : ''}>60 Minuten</option>
                        </select>
                    </div>
                    <div style="font-size: 12px; color: #666; margin-top: 8px;">
                        Warte auf Stempelzeit...
                    </div>
                `;
            }

            display.innerHTML = content;

            // Event Listener
            const breakSelect = document.getElementById('breakTimeSelect');
            if (breakSelect) {
                breakSelect.addEventListener('change', function() {
                    breakTime = parseInt(this.value);
                    GM_setValue('breakTime', breakTime);
                    updateDisplay(punchInTime, punchOutTime);
                });
            }

            const workSelect = document.getElementById('workTimeSelect');
            if (workSelect) {
                workSelect.addEventListener('change', function() {
                    workTime = parseInt(this.value);
                    GM_setValue('workTime', workTime);
                    updateDisplay(punchInTime, punchOutTime);
                });
            }
        }
    }

    function addTimeCalculator() {
        let display = document.getElementById('timeCalculator');
        if (!display) {
            display = document.createElement('div');
            display.id = 'timeCalculator';
            display.style.cssText = `
                position: fixed;
                bottom: 100px;
                right: 10px;
                padding: 15px;
                border: 1px solid #ccc;
                border-radius: 5px;
                z-index: 9999;
                font-family: Arial, sans-serif;
                font-size: 14px;
                box-shadow: 0 2px 5px rgba(0,0,0,0.1);
                min-width: 220px;
                transition: background-color 0.3s ease;
                background-color: white;
            `;
            document.body.appendChild(display);
        }

        const { punchInTime, punchOutTime } = findPunchTimes();
        updateDisplay(punchInTime, punchOutTime);
    }

    // Initial ausführen
    setTimeout(() => {
        addTimeCalculator();
        setInterval(addTimeCalculator, 5000);
    }, 1000);

})();