bhylu.com

Advertisements

Swift Room Report Project

Return a complete checked summary rather than silently losing invalid records.

How it works

Each record has a unique nonblank ID, a room and a positive duration. Reject the entire input if any row violates that contract. Bound rows and per-row minutes so the subtotal range is explicit. Sort room keys for presentation instead of depending on dictionary iteration order.

Run this Swift example

Install the toolchain for your platform from Swift.org, then check swift --version. The reviewed portable baseline is Swift 6.4.2 in Swift 6 mode on Ubuntu 26.04 x86_64 through the PC’s existing WSL installation. These are real Linux executions, not claims of Windows-native or Apple-platform test results. Windows Swift has separate C++/SDK prerequisites in its official setup guide.

Save the complete source as room-report-project.swift in a new learning folder. On Linux/macOS compile with swiftc -swift-version 6 -parse-as-library room-report-project.swift -o lesson, then run ./lesson. On a configured Windows toolchain use an output such as lesson.exe and run .\lesson.exe. The parse-as-library option supports the explicit @main entry point used by these sources. Compile each ordinary lesson separately.

Bhylu has no Swift browser runner. The JavaScript/Python editors do not run these sources; Apache, PHP and MySQL are not required. Downloads are source text, never executable teaching endpoints.

Download the complete room-report-project.swift · Download all source files with hash checks

For the optional collection, save download-examples.mjs in a new folder and run node download-examples.mjs. A local preview uses node download-examples.mjs http://127.0.0.1:8000/examples/swift/. It refuses an existing bhylu-swift-examples folder and installs or executes no Swift automatically. Apple-only files remain separate Xcode learning examples, not a portable Swift package target.

Example

room-report-project.swift

import Foundation

struct Booking { let id: String; let room: String; let minutes: Int }
enum ReportError: Error { case invalid }
func roomTotals(_ rows: [Booking]) throws -> [String: Int] {
    guard rows.count <= 1000 else { throw ReportError.invalid }
    var seen: Set<String> = []
    var totals: [String: Int] = [:]
    for row in rows {
        guard !row.id.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty,
              !row.room.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty,
              (1...240).contains(row.minutes), seen.insert(row.id).inserted else { throw ReportError.invalid }
        totals[row.room, default: 0] += row.minutes
    }
    return totals
}

@main
struct Lesson {
    static func main() {
        let rows = [Booking(id: "W-21", room: "Cedar", minutes: 20), Booking(id: "W-22", room: "Ash", minutes: 35), Booking(id: "W-23", room: "Cedar", minutes: 25)]
        do {
            let totals = try roomTotals(rows)
            for room in totals.keys.sorted() { print(room, totals[room] ?? 0) }
            do { _ = try roomTotals(rows + [rows[0]]); print("unexpected") }
            catch { print("duplicate refused") }
        } catch { fatalError("Valid fixture failed") }
    }
}

Expected result

Ash 35
Cedar 45
duplicate refused

Cedar’s subtotal is independently checkable as twenty plus twenty-five. The repeated ID is rejected before a result dictionary escapes. Empty valid input produces an empty dictionary, which is different from an error.

A real Swift package

The source collection includes Package.swift, a WorkshopCore library, a WorkshopCLI executable and actual XCTest files. Inside bhylu-swift-examples run node setup-lab.mjs. It checks source hashes before creating a new pottery-lab folder and refuses existing output. Change to pottery-lab and run swift test, then swift run WorkshopCLI. No third-party package dependency is needed. A properly installed platform toolchain supplies its own runtime/SDK; the private review setup is not shipped to readers.

Package.swift

Download Package.swift

Package.swift

// swift-tools-version: 6.0
import PackageDescription

let package = Package(
    name: "PotteryLab",
    products: [
        .library(name: "WorkshopCore", targets: ["WorkshopCore"]),
        .executable(name: "WorkshopCLI", targets: ["WorkshopCLI"])
    ],
    targets: [
        .target(name: "WorkshopCore"),
        .executableTarget(name: "WorkshopCLI", dependencies: ["WorkshopCore"]),
        .testTarget(name: "WorkshopCoreTests", dependencies: ["WorkshopCore"])
    ]
)

WorkshopCore.swift

Download WorkshopCore.swift

WorkshopCore.swift

import Foundation

public struct BookingCounter: Sendable {
    public let capacity: Int
    public private(set) var booked = 0
    public var free: Int { capacity - booked }
    public init?(capacity: Int) {
        guard capacity >= 0 else { return nil }
        self.capacity = capacity
    }
    public mutating func book(_ amount: Int) -> Bool {
        guard amount > 0, amount <= free else { return false }
        booked += amount
        return true
    }
}

public struct Booking: Sendable {
    public let id: String
    public let room: String
    public let minutes: Int
    public init(id: String, room: String, minutes: Int) {
        self.id = id; self.room = room; self.minutes = minutes
    }
}
public enum ReportError: Error { case invalid }

public func roomTotals(_ rows: [Booking]) throws -> [String: Int] {
    guard rows.count <= 1000 else { throw ReportError.invalid }
    var seen: Set<String> = []
    var totals: [String: Int] = [:]
    for row in rows {
        guard !row.id.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty,
              !row.room.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty,
              (1...240).contains(row.minutes), seen.insert(row.id).inserted else { throw ReportError.invalid }
        totals[row.room, default: 0] += row.minutes
    }
    return totals
}

WorkshopCLI.swift

Download WorkshopCLI.swift

WorkshopCLI.swift

import WorkshopCore

@main struct WorkshopCLI {
    static func main() throws {
        guard var desk = BookingCounter(capacity: 5) else { fatalError("Invalid fixture") }
        for amount in [2, 0, 4, 3] { print(desk.book(amount), desk.booked) }
        print("free", desk.free)
        let totals = try roomTotals([
            Booking(id: "W-21", room: "Cedar", minutes: 20),
            Booking(id: "W-22", room: "Ash", minutes: 35),
            Booking(id: "W-23", room: "Cedar", minutes: 25)
        ])
        for key in totals.keys.sorted() { print(key, totals[key] ?? 0) }
    }
}

WorkshopCoreTests.swift

Download WorkshopCoreTests.swift

WorkshopCoreTests.swift

import XCTest
@testable import WorkshopCore

final class WorkshopCoreTests: XCTestCase {
    func testCapacityRefusalsAndIndependentSequence() {
        XCTAssertNil(BookingCounter(capacity: -1))
        for capacity in 0...20 {
            guard var desk = BookingCounter(capacity: capacity) else { return XCTFail("Valid capacity refused") }
            var expected = 0
            for amount in [1, 2, 0, -1, 4, 1, 19, 1] {
                let accepted = amount > 0 && Int64(expected) + Int64(amount) <= Int64(capacity)
                if accepted { expected += amount }
                XCTAssertEqual(desk.book(amount), accepted)
                XCTAssertEqual(desk.booked, expected)
                XCTAssertEqual(desk.free, capacity - expected)
            }
        }
    }
    func testMaximumIntDoesNotOverflowOnRefusal() {
        guard var desk = BookingCounter(capacity: Int.max) else { return XCTFail("Maximum capacity refused") }
        XCTAssertTrue(desk.book(Int.max - 1))
        XCTAssertFalse(desk.book(2))
        XCTAssertEqual(desk.booked, Int.max - 1)
        XCTAssertTrue(desk.book(1))
        XCTAssertEqual(desk.free, 0)
        XCTAssertFalse(desk.book(1))
    }
    func testReportIndependentTotalsAndEmptyInput() throws {
        for size in 0...30 {
            let rows = (0..<size).map { Booking(id: String($0), room: $0 % 3 == 0 ? "Cedar" : "Ash", minutes: $0 + 1) }
            let actual = try roomTotals(rows)
            let cedar = (0..<size).filter { $0 % 3 == 0 }.reduce(0) { $0 + $1 + 1 }
            let ash = (0..<size).filter { $0 % 3 != 0 }.reduce(0) { $0 + $1 + 1 }
            XCTAssertEqual(actual["Cedar", default: 0], cedar)
            XCTAssertEqual(actual["Ash", default: 0], ash)
        }
    }
    func testReportRejectsInvalidWholeInput() {
        let cases: [[Booking]] = [
            [Booking(id: "", room: "Cedar", minutes: 1)],
            [Booking(id: "x", room: " ", minutes: 1)],
            [Booking(id: "x", room: "Cedar", minutes: 0)],
            [Booking(id: "x", room: "Cedar", minutes: 241)],
            [Booking(id: "x", room: "Cedar", minutes: 1), Booking(id: "x", room: "Ash", minutes: 2)],
            (0..<1001).map { Booking(id: String($0), room: "Cedar", minutes: 1) }
        ]
        for rows in cases { XCTAssertThrowsError(try roomTotals(rows)) }
    }
}

Primary references: The Swift Programming Language and Apple framework documentation. Use the selected platform’s current requirements. Fictional workshop examples do not establish production safety or deployment approval.

Advertisements