Menu
Coddy logo textTech

שירות השכרת כלי רכב

חלק מהיחידה תכנות מונחה עצמים במסלול ה-PHP של Coddy. שיעור 91 מתוך 91.

challenge icon

אתגר

קל

בואו נבנה מערכת Vehicle Rental Service שמנהלת צי של כלי רכב, עוקבת אחר השכרות של לקוחות ומחשבת מחירים בהתאם לסוג הרכב. האתגר המקיף הזה משלב ירושה, ממשקים, כימוס ואת תבנית State כדי ליצור יישום מציאותי לניהול עסק להשכרת כלי רכב.

תארגנו את הקוד שלכם בשבעה קבצים:

  • VehicleState.php: הגדירו ממשק VehicleState שמייצג את המצבים השונים שבהם רכב יכול להיות. כללו שתי מתודות: getStatus(): string ו-canRent(): bool. לאחר מכן צרו שלוש מחלקות שמממשות את הממשק הזה:
    • AvailableState: מחזירה "Available" ו-true
    • RentedState: מחזירה "Rented" ו-false
    • MaintenanceState: מחזירה "Maintenance" ו-false
  • Vehicle.php: כללו את הקובץ VehicleState. צרו מחלקה מופשטת Vehicle עם קידום פרמטרים בבנאי עבור licensePlate (מחרוזת, public readonly), brand (מחרוזת, public readonly) ו-dailyRate (מספר עשרוני, protected). שמרו את המצב הנוכחי במאפיין פרטי, עם ברירת מחדל של AvailableState. ממשו:
    • getState(): VehicleState: מחזירה את המצב הנוכחי
    • setState(VehicleState $state): void: משנה את המצב
    • getStatus(): string: מעבירה את הקריאה ל-getStatus() של המצב
    • canRent(): bool: מעבירה את הקריאה ל-canRent() של המצב
    • abstract calculateCost(int $days): float: כל סוג רכב מחשב את העלות באופן שונה
    • getType(): string: מחזירה את שם המחלקה באמצעות static::class
  • Vehicles.php: כללו את קובץ Vehicle. צרו שלוש מחלקות קונקרטיות לכלי רכב:
    • Car: יורשת מ-Vehicle; calculateCost() מחזירה dailyRate * days
    • Motorcycle: יורשת מ-Vehicle; calculateCost() מחזירה dailyRate * days * 0.8 (הנחה של 20%)
    • Van: יורשת מ-Vehicle עם פרמטר נוסף $mileageRate (מספר עשרוני); calculateCost(int $days, int $miles = 0) מחזירה (dailyRate * days) + (mileageRate * miles)
  • Customer.php: צרו מחלקה Customer עם קידום פרמטרים בבנאי עבור id (מספר שלם, public readonly) ו-name (מחרוזת, public readonly). עקבו אחר היסטוריית ההשכרות במערך פרטי. ממשו:
    • addRental(string $vehiclePlate, float $cost): void: מוסיפה להשכרות בהיסטוריה
    • getRentalCount(): int: מחזירה את מספר ההשכרות
    • getTotalSpent(): float: מחזירה את הסכום של כל עלויות ההשכרה
  • Rental.php: כללו את הקבצים Vehicle ו-Customer. צרו מחלקה Rental שמקשרת לקוח לרכב. השתמשו בקידום פרמטרים בבנאי עבור customer (Customer, public readonly), vehicle (Vehicle, public readonly), days (מספר שלם, private) ואפשר גם miles (מספר שלם, private, ברירת מחדל 0). ממשו:
    • calculateTotal(): float: אם הרכב הוא Van, העבירו את miles אל calculateCost(); אחרת העבירו רק את days
    • complete(): string: מחשבת את הסכום הכולל, מוסיפה אותו להיסטוריה של הלקוח, משנה את מצב הרכב ל-AvailableState ומחזירה "Rental completed: $[total]" (2 ספרות אחרי הנקודה העשרונית)
  • RentalService.php: כללו את הקבצים Rental ו-Vehicles. צרו מחלקה RentalService שמנהלת את צי הרכב. שמרו את כלי הרכב במערך פרטי שממוּפתח לפי לוחית הרישוי. ממשו:
    • addVehicle(Vehicle $vehicle): void: מוסיפה את הרכב לצי
    • findVehicle(string $plate): ?Vehicle: מחזירה את הרכב או null
    • getAvailableVehicles(): array: מחזירה את כלי הרכב שעבורם canRent() הוא true
    • rentVehicle(Customer $customer, string $plate, int $days, int $miles = 0): string|Rental: אם הרכב לא נמצא, החזירו "Vehicle not found"; אם הוא לא זמין, החזירו "Vehicle is not available"; אחרת שנו את מצב הרכב ל-RentedState והחזירו אובייקט Rental חדש
    • setMaintenance(string $plate): string: משנה את מצב הרכב ל-MaintenanceState; מחזירה "[plate] set to maintenance" או "Vehicle not found"
  • main.php: כללו את הקבצים RentalService ו-Customer. תקבלו שלוש קלטים: נתוני צי הרכב (JSON), נתוני הלקוח (JSON) ופעולות (JSON).

    פורמט JSON של צי הרכב:

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

    פורמט JSON של הלקוח:

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

    פורמט JSON של הפעולות:

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

    צרו את שירות ההשכרה, הוסיפו את כל כלי הרכב לצי וצרו את הלקוח. עקבו אחר ההשכרות הפעילות לפי לוחית הרישוי. עבדו על כל פעולה:

    • "available": הדפיסו "Available vehicles: [count]"
    • "rent": השכירו את הרכב; אם ההשכרה הצליחה, שמרו את ה-Rental והדפיסו "Rented [plate] for [days] days"; אם הרכב הוא Van, כללו את מספר המיילים מהפעולה; אחרת הדפיסו את הודעת השגיאה
    • "complete": השלימו את ההשכרה השמורה עבור לוחית הרישוי הזו; הדפיסו את התוצאה
    • "maintenance": הדפיסו את התוצאה של setMaintenance()
    • "status": הדפיסו "[plate]: [status]" עבור לוחית הרישוי הנתונה
    • "customer_stats": הדפיסו "[name]: [count] rentals, $[total] spent" (2 ספרות אחרי הנקודה העשרונית)

    הדפיסו כל תוצאה בשורה חדשה.

המערכת מדגימה כיצד תבנית State מטפלת באופן אלגנטי בזמינות כלי הרכב ללא תנאים מורכבים, כיצד ירושה יוצרת היררכיה מסודרת של כלי רכב עם תמחור פולימורפי, וכיצד כימוס מגן על שלמות נתוני ההשכרה לאורך כל תהליך העבודה.

נסו בעצמכם

<?php

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

// קרא את הקלטים
$fleetJson = trim(fgets(STDIN));
$customerJson = trim(fgets(STDIN));
$operationsJson = trim(fgets(STDIN));

// פענח נתוני JSON
$fleetData = (array)json_decode($fleetJson, true);
$customerData = (array)json_decode($customerJson, true);
$operations = (array)json_decode($operationsJson, true);

// TODO: צור מופע של RentalService

// TODO: הוסף את כל כלי הרכב לצי לפי הסוג:
// - "car" -> new Car(plate, brand, rate)
// - "motorcycle" -> new Motorcycle(plate, brand, rate)
// - "van" -> new Van(plate, brand, rate, mileage_rate)

// TODO: צור מופע של Customer מתוך customerData

// TODO: צור מערך למעקב אחר השכרות פעילות לפי לוחית רישוי
$activeRentals = [];

// TODO: עבד כל פעולה והדפס את התוצאות:
// - "available": הדפס "Available vehicles: [count]"
// - "rent": השכר רכב, שמור את Rental אם הפעולה הצליחה, והדפס את התוצאה
// - "complete": השלם את ההשכרה והדפס את התוצאה
// - "maintenance": הגדר מצב תחזוקה והדפס את התוצאה
// - "status": הדפס "[plate]: [status]"
// - "customer_stats": הדפס "[name]: [count] rentals, $[total] spent"

foreach ($operations as $op) {
    $operation = (array)$op;
    $opType = $operation['op'];
    
    // TODO: טפל בכל סוג פעולה
    switch ($opType) {
        case 'available':
            // TODO: הדפס את מספר הרכבים הזמינים
            break;
        case 'rent':
            // TODO: השכר רכב והדפס את התוצאה
            break;
        case 'complete':
            // TODO: השלם את ההשכרה והדפס את התוצאה
            break;
        case 'maintenance':
            // TODO: הגדר מצב תחזוקה והדפס את התוצאה
            break;
        case 'status':
            // TODO: הדפס את מצב הרכב
            break;
        case 'customer_stats':
            // TODO: הדפס את נתוני הלקוח
            break;
    }
}

?>

כל השיעורים ביחידה תכנות מונחה עצמים

תרגלו בעצמכם: קומפיילר PHP אונליין