Menu
Coddy logo textTech

Servizio di noleggio veicoli

Fa parte della sezione Programmazione orientata agli oggetti del percorso PHP di Coddy. Lezione 91 di 91.

challenge icon

Sfida

Facile

Costruiamo un sistema di noleggio di veicoli che gestisce una flotta di veicoli, tiene traccia dei noleggi dei clienti e calcola i prezzi in base al tipo di veicolo. Questa sfida completa combina ereditarietà, interfacce, incapsulamento e il pattern State per creare un'applicazione realistica per un'attività di noleggio.

Organizzerai il codice in sette file:

  • VehicleState.php: definisci un'interfaccia VehicleState che rappresenta i diversi stati in cui può trovarsi un veicolo. Includi due metodi: getStatus(): string e canRent(): bool. Poi crea tre classi che implementano questa interfaccia:
    • AvailableState: restituisce "Available" e true
    • RentedState: restituisce "Rented" e false
    • MaintenanceState: restituisce "Maintenance" e false
  • Vehicle.php: includi il file VehicleState. Crea una classe astratta Vehicle usando la promozione delle proprietà del costruttore per licensePlate (string, public readonly), brand (string, public readonly) e dailyRate (float, protected). Memorizza lo stato corrente in una proprietà privata, impostandolo inizialmente su AvailableState. Implementa:
    • getState(): VehicleState: restituisce lo stato corrente
    • setState(VehicleState $state): void: modifica lo stato
    • getStatus(): string: delega a getStatus() dello stato
    • canRent(): bool: delega a canRent() dello stato
    • abstract calculateCost(int $days): float: ciascun tipo di veicolo calcola il costo in modo diverso
    • getType(): string: restituisce il nome della classe usando static::class
  • Vehicles.php: includi il file Vehicle. Crea tre classi concrete di veicoli:
    • Car: estende Vehicle; calculateCost() restituisce dailyRate * days
    • Motorcycle: estende Vehicle; calculateCost() restituisce dailyRate * days * 0.8 (sconto del 20%)
    • Van: estende Vehicle con un parametro aggiuntivo $mileageRate (float); calculateCost(int $days, int $miles = 0) restituisce (dailyRate * days) + (mileageRate * miles)
  • Customer.php: crea una classe Customer usando la promozione delle proprietà del costruttore per id (int, public readonly) e name (string, public readonly). Tieni traccia della cronologia dei noleggi in un array privato. Implementa:
    • addRental(string $vehiclePlate, float $cost): void: aggiunge un noleggio alla cronologia
    • getRentalCount(): int: restituisce il numero di noleggi
    • getTotalSpent(): float: restituisce la somma dei costi di tutti i noleggi
  • Rental.php: includi i file Vehicle e Customer. Crea una classe Rental che associa un cliente a un veicolo. Usa la promozione delle proprietà del costruttore per customer (Customer, public readonly), vehicle (Vehicle, public readonly), days (int, private) e, facoltativamente, miles (int, private, valore predefinito 0). Implementa:
    • calculateTotal(): float: se il veicolo è un Van, passa i miles a calculateCost(); altrimenti passa solo i days
    • complete(): string: calcola il totale, lo aggiunge alla cronologia del cliente, imposta lo stato del veicolo su AvailableState e restituisce "Rental completed: $[total]" (2 cifre decimali)
  • RentalService.php: includi i file Rental e Vehicles. Crea una classe RentalService che gestisce la flotta. Memorizza i veicoli in un array privato indicizzato per targa. Implementa:
    • addVehicle(Vehicle $vehicle): void: aggiunge un veicolo alla flotta
    • findVehicle(string $plate): ?Vehicle: restituisce il veicolo oppure null
    • getAvailableVehicles(): array: restituisce i veicoli per cui canRent() è true
    • rentVehicle(Customer $customer, string $plate, int $days, int $miles = 0): string|Rental: se il veicolo non viene trovato, restituisce "Vehicle not found"; se non è disponibile, restituisce "Vehicle is not available"; altrimenti imposta lo stato del veicolo su RentedState e restituisce un nuovo oggetto Rental
    • setMaintenance(string $plate): string: imposta lo stato del veicolo su MaintenanceState; restituisce "[plate] set to maintenance" oppure "Vehicle not found"
  • main.php: includi i file RentalService e Customer. Riceverai tre input: i dati della flotta (JSON), i dati del cliente (JSON) e le operazioni (JSON).

    Formato del JSON della flotta:

    [{"type": "car", "plate": "CAR-001", "brand": "Toyota", "rate": 50}, {"type": "van", "plate": "VAN-001", "brand": "Ford", "rate": 80, "mileage_rate": 0.25}]

    Formato del JSON del cliente:

    {"id": 1, "name": "Alice"}

    Formato del JSON delle operazioni:

    [{"op": "available"}, {"op": "rent", "plate": "CAR-001", "days": 3}, {"op": "complete", "plate": "CAR-001"}, {"op": "maintenance", "plate": "VAN-001"}, {"op": "customer_stats"}]

    Crea il servizio di noleggio, aggiungi tutti i veicoli alla flotta e crea il cliente. Tieni traccia dei noleggi attivi in base alla targa. Elabora ogni operazione:

    • "available": stampa "Available vehicles: [count]"
    • "rent": noleggia il veicolo; se l'operazione ha esito positivo, memorizza il Rental e stampa "Rented [plate] for [days] days"; se si tratta di un Van, includi i miles dell'operazione; altrimenti stampa il messaggio di errore
    • "complete": completa il noleggio memorizzato per quella targa; stampa il risultato
    • "maintenance": stampa il risultato di setMaintenance()
    • "status": stampa "[plate]: [status]" per la targa specificata
    • "customer_stats": stampa "[name]: [count] rentals, $[total] spent" (2 cifre decimali)

    Stampa ogni risultato su una nuova riga.

Questo sistema mostra come il pattern State gestisca elegantemente la disponibilità dei veicoli senza condizioni complesse, come l'ereditarietà crei una gerarchia di veicoli chiara con prezzi polimorfici e come l'incapsulamento protegga l'integrità dei dati di noleggio durante tutto il flusso di lavoro.

Provalo tu

<?php

require_once 'RentalService.php';
require_once 'Customer.php';

// Leggi gli input
$fleetJson = trim(fgets(STDIN));
$customerJson = trim(fgets(STDIN));
$operationsJson = trim(fgets(STDIN));

// Analizza i dati JSON
$fleetData = (array)json_decode($fleetJson, true);
$customerData = (array)json_decode($customerJson, true);
$operations = (array)json_decode($operationsJson, true);

// TODO: Crea un'istanza di RentalService

// TODO: Aggiungi tutti i veicoli alla flotta in base al tipo:
// - "car" -> new Car(plate, brand, rate)
// - "motorcycle" -> new Motorcycle(plate, brand, rate)
// - "van" -> new Van(plate, brand, rate, mileage_rate)

// TODO: Crea un'istanza di Customer da customerData

// TODO: Crea un array per tenere traccia dei noleggi attivi in base alla targa
$activeRentals = [];

// TODO: Elabora ogni operazione e stampa i risultati:
// - "available": Stampa "Available vehicles: [count]"
// - "rent": Noleggia il veicolo, memorizza Rental se l'operazione riesce e stampa il risultato
// - "complete": Completa il noleggio e stampa il risultato
// - "maintenance": Imposta la manutenzione e stampa il risultato
// - "status": Stampa "[plate]: [status]"
// - "customer_stats": Stampa "[name]: [count] rentals, $[total] spent"

foreach ($operations as $op) {
    $operation = (array)$op;
    $opType = $operation['op'];
    
    // TODO: Gestisci ogni tipo di operazione
    switch ($opType) {
        case 'available':
            // TODO: Stampa il numero di veicoli disponibili
            break;
        case 'rent':
            // TODO: Noleggia il veicolo e stampa il risultato
            break;
        case 'complete':
            // TODO: Completa il noleggio e stampa il risultato
            break;
        case 'maintenance':
            // TODO: Imposta la manutenzione e stampa il risultato
            break;
        case 'status':
            // TODO: Stampa lo stato del veicolo
            break;
        case 'customer_stats':
            // TODO: Stampa le statistiche del cliente
            break;
    }
}

?>

Tutte le lezioni di Programmazione orientata agli oggetti

Esercitati da solo: Compilatore PHP online