Untitled

mail@pastecode.io avatar
unknown
plain_text
a month ago
7.4 kB
4
Indexable
Never
class Worker:
    def __init__(self, worker_id, position, compensation):
        self.worker_id = worker_id
        self.position = position
        self.compensation = compensation
        self.total_time = 0
        self.current_entry_time = None  # Tracks the last entry time (if currently in office)
        self.promotions = []  # List of promotions (each as a tuple of (timestamp, position, compensation))

    def promote(self, new_position, new_compensation, start_timestamp):
        self.promotions.append((start_timestamp, new_position, new_compensation))
    
    def get_current_compensation(self, timestamp):
        # Find the most recent promotion before or at the given timestamp
        for start_timestamp, position, compensation in reversed(self.promotions):
            if timestamp >= start_timestamp:
                return compensation
        return self.compensation  # Default to the initial compensation

class WorkingHoursRegister:
    def __init__(self):
        self.workers = {}
        self.double_pay_periods = []  # List of double pay periods (each as a tuple of (startTimestamp, endTimestamp))

    def add_worker(self, worker_id, position, compensation):
        if worker_id in self.workers:
            return "false"
        self.workers[worker_id] = Worker(worker_id, position, compensation)
        return "true"

    def register(self, worker_id, timestamp):
        if worker_id not in self.workers:
            return "invalid_request"

        worker = self.workers[worker_id]

        if worker.current_entry_time is None:
            # The worker is entering the office
            worker.current_entry_time = timestamp
        else:
            # The worker is leaving the office
            time_spent = timestamp - worker.current_entry_time
            worker.total_time += time_spent
            worker.current_entry_time = None

        return "registered"

    def get(self, worker_id):
        if worker_id not in self.workers:
            return ""

        worker = self.workers[worker_id]
        return str(worker.total_time)

    def top_n_workers(self, n, position):
        # Filter workers by position
        filtered_workers = [worker for worker in self.workers.values() if worker.position == position]
        
        # Sort by total time in descending order and by worker_id in ascending order for ties
        filtered_workers.sort(key=lambda worker: (-worker.total_time, worker.worker_id))
        
        # Prepare the result string
        top_workers = filtered_workers[:n]
        result = ", ".join([f"{worker.worker_id}({worker.total_time})" for worker in top_workers])
        
        return result

    def promote(self, worker_id, new_position, new_compensation, start_timestamp):
        if worker_id not in self.workers:
            return "invalid_request"
        
        worker = self.workers[worker_id]

        # Check if the worker has already been promoted to this position after or at the start_timestamp
        if worker.promotions and worker.promotions[-1][0] >= start_timestamp:
            return "invalid_request"

        worker.promote(new_position, new_compensation, start_timestamp)
        return "success"

    def calc_salary(self, worker_id, start_timestamp, end_timestamp):
        if worker_id not in self.workers:
            return ""

        worker = self.workers[worker_id]
        total_salary = 0

        for promotion in worker.promotions:
            promotion_timestamp, position, compensation = promotion
            session_start = max(start_timestamp, promotion_timestamp)
            if worker.current_entry_time and worker.current_entry_time < end_timestamp:
                session_end = min(end_timestamp, worker.current_entry_time)
                if session_start < session_end:
                    total_salary += self.calculate_salary_with_double_pay(worker, session_start, session_end)
        
        return str(total_salary)

    def calculate_salary_with_double_pay(self, worker, start_time, end_time):
        # Calculate salary with consideration for double pay periods
        salary = 0
        remaining_start = start_time

        for period_start, period_end in self.double_pay_periods:
            if period_end <= start_time or period_start >= end_time:
                continue

            if period_start > remaining_start:
                salary += (period_start - remaining_start) * worker.get_current_compensation(remaining_start)
                remaining_start = period_start

            if period_end <= end_time:
                salary += (period_end - remaining_start) * worker.get_current_compensation(remaining_start) * 2
                remaining_start = period_end
            else:
                salary += (end_time - remaining_start) * worker.get_current_compensation(remaining_start) * 2
                remaining_start = end_time
                break

        if remaining_start < end_time:
            salary += (end_time - remaining_start) * worker.get_current_compensation(remaining_start)

        return salary

    def set_double_pay_period(self, start_timestamp, end_timestamp):
        self.double_pay_periods.append((start_timestamp, end_timestamp))
        return "double_pay_period_set"

def process_queries(queries):
    register = WorkingHoursRegister()
    results = []

    for query in queries:
        operation = query.split()

        if operation[0] == "ADD_WORKER":
            worker_id = operation[1]
            position = operation[2]
            compensation = int(operation[3])
            result = register.add_worker(worker_id, position, compensation)
        
        elif operation[0] == "REGISTER":
            worker_id = operation[1]
            timestamp = int(operation[2])
            result = register.register(worker_id, timestamp)
        
        elif operation[0] == "GET":
            worker_id = operation[1]
            result = register.get(worker_id)
        
        elif operation[0] == "TOP_N_WORKERS":
            n = int(operation[1])
            position = operation[2]
            result = register.top_n_workers(n, position)
        
        elif operation[0] == "PROMOTE":
            worker_id = operation[1]
            new_position = operation[2]
            new_compensation = int(operation[3])
            start_timestamp = int(operation[4])
            result = register.promote(worker_id, new_position, new_compensation, start_timestamp)

        elif operation[0] == "CALC_SALARY":
            worker_id = operation[1]
            start_timestamp = int(operation[2])
            end_timestamp = int(operation[3])
            result = register.calc_salary(worker_id, start_timestamp, end_timestamp)
        
        elif operation[0] == "SET_DOUBLE_PAY_PERIOD":
            start_timestamp = int(operation[1])
            end_timestamp = int(operation[2])
            result = register.set_double_pay_period(start_timestamp, end_timestamp)

        results.append(result)
    
    return results

# Example usage:
queries = [
    "ADD_WORKER John Engineer 1000",
    "REGISTER John 10",
    "REGISTER John 60",
    "PROMOTE John SeniorEngineer 2000 70",
    "REGISTER John 100",
    "CALC_SALARY John 0 100",
    "PROMOTE John Manager 3000 150",
    "REGISTER John 160",
    "REGISTER John 200",
    "SET_DOUBLE_PAY_PERIOD 50 120",
    "CALC_SALARY John 0 200"
]
Leave a Comment