From d26d729e011bcf1f81a6b4431f684a65a9cb32cb Mon Sep 17 00:00:00 2001 From: meatball Date: Sun, 26 Jan 2025 11:21:05 +0100 Subject: [PATCH 1/3] Update window system exercise --- .../concept/windowing-system/.docs/hints.md | 5 - .../windowing-system/.docs/instructions.md | 35 ++- .../WindowingSystemExemplar.swift | 20 +- .../windowing-system/.meta/config.json | 3 + .../concept/windowing-system/Package.swift | 44 +-- .../WindowingSystemTests.swift | 261 +++++++++--------- 6 files changed, 195 insertions(+), 173 deletions(-) diff --git a/exercises/concept/windowing-system/.docs/hints.md b/exercises/concept/windowing-system/.docs/hints.md index 2a6b115bf..705c26869 100644 --- a/exercises/concept/windowing-system/.docs/hints.md +++ b/exercises/concept/windowing-system/.docs/hints.md @@ -20,11 +20,6 @@ - Constant properties should be defined using `let`. - Properties can be changed using their own methods, where available. -## 4. Create some Windows - -- This will require the class to be both initialized and modified. -- Initialization and modification is often done [using a closure][initializing-via-closure] - [structs-and-classes]: https://docs.swift.org/swift-book/LanguageGuide/ClassesAndStructures.html [memberwise-initializers]: https://docs.swift.org/swift-book/LanguageGuide/ClassesAndStructures.html#ID87 [initializing-via-closure]: https://docs.swift.org/swift-book/LanguageGuide/Initialization.html#ID232 diff --git a/exercises/concept/windowing-system/.docs/instructions.md b/exercises/concept/windowing-system/.docs/instructions.md index 645157db8..332737cc7 100644 --- a/exercises/concept/windowing-system/.docs/instructions.md +++ b/exercises/concept/windowing-system/.docs/instructions.md @@ -30,12 +30,12 @@ Define a struct named `Size` with two `Int` properties, `width` and `height` tha ```swift let size1080x764 = Size(width: 1080, height: 764) -// => Size +// returns Size var size1200x800 = size1080x764 -// => Size +// returns Size size1200x800.resize(newWidth: 1200, newHeight: 800) size1200x800.height -// => 800 +// returns 800 ``` ## 2. Define a Position struct @@ -46,10 +46,10 @@ Include a method `moveTo(newX:newY:)` that takes new x and y parameters and chan ```swift var point = Position(x: 10, y: 20) -// => Position +// returns Position point.moveTo(newX: 100, newY: -100) point.y -// => -100 +// returns -100 ``` ## 3. Define a Window class @@ -62,6 +62,14 @@ Define a window class with the following properties: - `position` : `Position`, initial value is the default value of the `Position` struct - `contents` : `String?`, initial value is `nil` +You should also define an empty initializer for the class. + +```swift +let window = Window() +window.display() +// returns "New Window\nPosition: (0, 0), Size: (80 x 60)\n[This window intentionally left blank]" +``` + ## 4. Add a method to resize windows - `resize(to:)` : `(Size) -> ()` - This method takes a `Size` struct as input and attempts to resize the window to the specified size. However, the new size cannot exceed certain bounds. - The minimum allowed height or width is 1. Requested heights or widths less than 1 will be clipped to 1. - The maximum height and width depends on the current position of the window, the edges of the window cannot move past the edges of the screen. Values larger than these bounds will be clipped to the largest size they can take. E.g. if the window's position is at `x` = 400, `y` = 300 and a resize to `height` = 400, `width` = 300 is requested, then the window would be resized to `height` = 300, `width` = 300 as the screen is not large enough in the `y` direction to fully accommodate the request. @@ -76,8 +84,19 @@ Define a window class with the following properties: - `update(text:)` : `(String?) -> ()` - This method sets the `contents` property to the value of the optional string that was passed in. - `display()` : `() -> String` - This method returns a string describing the current state of the window. For example, if the window has the `title` "My First Window" with position: x = 10, y = 100; size: width = 200, height = 150; and contents: "I 😍 my window", it should return the string: `"My First Window\nPosition: (10, 100), Size: (200 x 150)\nI 😍 my window\n"` - If `contents` is nil, the last line should read "[This window intentionally left blank]" -## 7. Create a new Window +## 7. Create an initilazer for the Window class -Create an instances of the Window class and modify it via their methods as follows: +The window system should have an initializer so the that the window can be created with custom inputs. +Create **another** initializer for the `Window` class. +The initializer should take the following parameters: `title`, `contents`, and two optional parameters `size` and `position`. +The `size` and `position` parameters should default to the default values of the `Size` and `Position` structs. -- The window should be given the title "Main Window", with a width of 400, a height of 300 and positioned at x = 100, y = 100. Its contents should be "This is the main window". Assign this instance to the name `mainWindow`. +```swift +let window = Window(title: "My First Window", contents: "I 😍 my window") +window.display() +// returns "My First Window\nPosition: (0, 0), Size: (80 x 60)\nI 😍 my window\n" + +let window2 = Window(title: "My Second Window", contents: "I 😍 my window", size: Size(width: 200, height: 150), position: Position(x: 10, y: 100)) +window2.display() +// returns "My Second Window\nPosition: (10, 100), Size: (200 x 150)\nI 😍 my window\n" +``` diff --git a/exercises/concept/windowing-system/.meta/Sources/WindowingSystem/WindowingSystemExemplar.swift b/exercises/concept/windowing-system/.meta/Sources/WindowingSystem/WindowingSystemExemplar.swift index 6cc4a2946..f39f19b6b 100644 --- a/exercises/concept/windowing-system/.meta/Sources/WindowingSystem/WindowingSystemExemplar.swift +++ b/exercises/concept/windowing-system/.meta/Sources/WindowingSystem/WindowingSystemExemplar.swift @@ -18,13 +18,22 @@ struct Size { } } -class Window: @unchecked Sendable { +class Window { var title = "New Window" let screenSize = Size(width: 800, height: 600) var size = Size() var position = Position() var contents: String? + init() {} + + init(title: String, contents: String?, size : Size = Size(), position: Position = Position()) { + self.title = title + self.contents = contents + self.size = size + self.position = position + } + func move(to newPosition: Position) { let minX = min(max(0, newPosition.x), screenSize.width - size.width) let minY = min(max(0, newPosition.y), screenSize.height - size.height) @@ -45,12 +54,3 @@ class Window: @unchecked Sendable { "\(title)\nPosition: (\(position.x), \(position.y)), Size: (\(size.width) x \(size.height))\n\(contents ?? "[This window intentionally left blank]")\n" } } - -let mainWindow: Window = { - var window = Window() - window.title = "Main Window" - window.contents = "This is the main window" - window.move(to: Position(x: 100, y: 100)) - window.resize(to: Size(width: 400, height: 300)) - return window -}() diff --git a/exercises/concept/windowing-system/.meta/config.json b/exercises/concept/windowing-system/.meta/config.json index d23a2af2c..a43f1b12d 100644 --- a/exercises/concept/windowing-system/.meta/config.json +++ b/exercises/concept/windowing-system/.meta/config.json @@ -2,6 +2,9 @@ "authors": [ "wneumann" ], + "contributors": [ + "meatball133" + ], "files": { "solution": [ "Sources/WindowingSystem/WindowingSystem.swift" diff --git a/exercises/concept/windowing-system/Package.swift b/exercises/concept/windowing-system/Package.swift index 89c08809a..357baed5c 100644 --- a/exercises/concept/windowing-system/Package.swift +++ b/exercises/concept/windowing-system/Package.swift @@ -1,28 +1,28 @@ -// swift-tools-version:5.3 +// swift-tools-version:6.0 // The swift-tools-version declares the minimum version of Swift required to build this package. import PackageDescription let package = Package( - name: "WindowingSystem", - products: [ - // Products define the executables and libraries a package produces, and make them visible to other packages. - .library( - name: "WindowingSystem", - targets: ["WindowingSystem"]), - ], - dependencies: [ - // Dependencies declare other packages that this package depends on. - // .package(url: /* package url */, from: "1.0.0"), - ], - targets: [ - // Targets are the basic building blocks of a package. A target can define a module or a test suite. - // Targets can depend on other targets in this package, and on products in packages this package depends on. - .target( - name: "WindowingSystem", - dependencies: []), - .testTarget( - name: "WindowingSystemTests", - dependencies: ["WindowingSystem"]), - ] + name: "WindowingSystem", + products: [ + // Products define the executables and libraries a package produces, and make them visible to other packages. + .library( + name: "WindowingSystem", + targets: ["WindowingSystem"]) + ], + dependencies: [ + // Dependencies declare other packages that this package depends on. + // .package(url: /* package url */, from: "1.0.0"), + ], + targets: [ + // Targets are the basic building blocks of a package. A target can define a module or a test suite. + // Targets can depend on other targets in this package, and on products in packages this package depends on. + .target( + name: "WindowingSystem", + dependencies: []), + .testTarget( + name: "WindowingSystemTests", + dependencies: ["WindowingSystem"]), + ] ) diff --git a/exercises/concept/windowing-system/Tests/WindowingSystemTests/WindowingSystemTests.swift b/exercises/concept/windowing-system/Tests/WindowingSystemTests/WindowingSystemTests.swift index dc590a428..3041af407 100644 --- a/exercises/concept/windowing-system/Tests/WindowingSystemTests/WindowingSystemTests.swift +++ b/exercises/concept/windowing-system/Tests/WindowingSystemTests/WindowingSystemTests.swift @@ -1,161 +1,166 @@ -import XCTest +import FoundationEssentials +import Testing @testable import WindowingSystem -final class WindowingSystemTests: XCTestCase { - let runAll = Bool(ProcessInfo.processInfo.environment["RUNALL", default: "false"]) ?? false +let RUNALL = Bool(ProcessInfo.processInfo.environment["RUNALL", default: "false"]) ?? false +@Suite struct WindowingSystemTests { + @Test("New Window") func testNewWindow() { - // This is an example of a functional test case. - // Use XCTAssert and related functions to verify your tests produce the correct - // results. - XCTAssertEqual( - Window().display(), - "New Window\nPosition: (0, 0), Size: (80 x 60)\n[This window intentionally left blank]\n") + #expect( + Window().display() + == "New Window\nPosition: (0, 0), Size: (80 x 60)\n[This window intentionally left blank]\n" + ) } - func testMainWindow() throws { - try XCTSkipIf(true && !runAll) // change true to false to run this test - XCTAssertEqual( - mainWindow.display(), - "Main Window\nPosition: (100, 100), Size: (400 x 300)\nThis is the main window\n") - } - - func testPositionMove() throws { - try XCTSkipIf(true && !runAll) // change true to false to run this test + @Test("Position Move", .enabled(if: RUNALL)) + func testPositionMove() { var pos = Position() let newX = Int.random(in: 0...100) let newY = Int.random(in: 0...1000) pos.moveTo(newX: newX, newY: newY) - XCTAssertTrue( + #expect( pos.x == newX && pos.y == newY, "Expected: Position(x: \(newX), \(newY)), got Position(x: \(pos.x), \(pos.y))") } - func testResize() throws { - try XCTSkipIf(true && !runAll) // change true to false to run this test + @Test("Size Resize", .enabled(if: RUNALL)) + func testSizeResize() { var size = Size() let newWidth = Int.random(in: 0...100) let newHeight = Int.random(in: 0...1000) size.resize(newWidth: newWidth, newHeight: newHeight) - XCTAssertTrue( + #expect( size.width == newWidth && size.height == newHeight, - "Expected: Size(width: \(newWidth), height: \(newHeight)), got Size(width: \(size.width), height: \(size.height))") - } - - func testMoveValid() throws { - try XCTSkipIf(true && !runAll) // change true to false to run this test - let testWindow: Window = { - let window = Window() - window.title = "Test Window" - window.contents = "test" - window.resize(to: Size(width: 100, height: 100)) - window.move(to: Position(x: 100, y: 100)) - return window - }() - XCTAssertEqual( - testWindow.display(), - "Test Window\nPosition: (100, 100), Size: (100 x 100)\ntest\n") - } - - func testMoveTooFar() throws { - try XCTSkipIf(true && !runAll) // change true to false to run this test - let testWindow: Window = { - let window = Window() - window.title = "Test Window" - window.contents = "test" - window.resize(to: Size(width: 100, height: 100)) - window.move(to: Position(x: 750, y: 650)) - return window - }() - XCTAssertEqual( - testWindow.display(), - "Test Window\nPosition: (700, 500), Size: (100 x 100)\ntest\n") - } - - func testMoveNegative() throws { - try XCTSkipIf(true && !runAll) // change true to false to run this test - let testWindow: Window = { - let window = Window() - window.title = "Test Window" - window.contents = "test" - window.resize(to: Size(width: 100, height: 100)) - window.move(to: Position(x: -80, y: -60)) - return window - }() - XCTAssertEqual( - testWindow.display(), - "Test Window\nPosition: (0, 0), Size: (100 x 100)\ntest\n") - } - - func testResizeValid() throws { - try XCTSkipIf(true && !runAll) // change true to false to run this test - let testWindow: Window = { - let window = Window() - window.title = "Test Window" - window.contents = "test" - window.move(to: Position(x: 600, y: 500)) - window.resize(to: Size(width: 100, height: 100)) - return window - }() - XCTAssertEqual( - testWindow.display(), - "Test Window\nPosition: (600, 500), Size: (100 x 100)\ntest\n") - } - - func testResizeTooFar() throws { - try XCTSkipIf(true && !runAll) // change true to false to run this test - let testWindow: Window = { - let window = Window() - window.title = "Test Window" - window.contents = "test" - window.move(to: Position(x: 710, y: 525)) - window.resize(to: Size(width: 1000, height: 1000)) - return window - }() - XCTAssertEqual( - testWindow.display(), - "Test Window\nPosition: (710, 525), Size: (90 x 75)\ntest\n") - } - - func testResizeNegative() throws { - try XCTSkipIf(true && !runAll) // change true to false to run this test - let testWindow: Window = { - let window = Window() - window.title = "Test Window" - window.contents = "test" - window.resize(to: Size(width: 0, height: -100)) - return window - }() - XCTAssertEqual( - testWindow.display(), - "Test Window\nPosition: (0, 0), Size: (1 x 1)\ntest\n") - } - - func testUpdateTitle() throws { - try XCTSkipIf(true && !runAll) // change true to false to run this test + "Expected: Size(width: \(newWidth), height: \(newHeight)), got Size(width: \(size.width), height: \(size.height))" + ) + } + + @Test("Move Valid", .enabled(if: RUNALL)) + func testMoveValid() { + let testWindow = Window() + testWindow.title = "Test Window" + testWindow.contents = "test" + testWindow.resize(to: Size(width: 100, height: 100)) + testWindow.move(to: Position(x: 100, y: 100)) + #expect(testWindow.display() == "Test Window\nPosition: (100, 100), Size: (100 x 100)\ntest\n") + } + + @Test("Move Too Far", .enabled(if: RUNALL)) + func testMoveTooFar() { + let testWindow = Window() + testWindow.title = "Test Window" + testWindow.contents = "test" + testWindow.resize(to: Size(width: 100, height: 100)) + testWindow.move(to: Position(x: 750, y: 650)) + #expect(testWindow.display() == "Test Window\nPosition: (700, 500), Size: (100 x 100)\ntest\n") + } + + @Test("Move Negative", .enabled(if: RUNALL)) + func testMoveNegative() { + let testWindow = Window() + testWindow.title = "Test Window" + testWindow.contents = "test" + testWindow.resize(to: Size(width: 100, height: 100)) + testWindow.move(to: Position(x: -80, y: -60)) + #expect(testWindow.display() == "Test Window\nPosition: (0, 0), Size: (100 x 100)\ntest\n") + } + + @Test("Resize Valid", .enabled(if: RUNALL)) + func testResizeValid() { + let testWindow = Window() + testWindow.title = "Test Window" + testWindow.contents = "test" + testWindow.move(to: Position(x: 600, y: 500)) + testWindow.resize(to: Size(width: 100, height: 100)) + #expect(testWindow.display() == "Test Window\nPosition: (600, 500), Size: (100 x 100)\ntest\n") + } + + @Test("Resize Too Far", .enabled(if: RUNALL)) + func testResizeTooFar() { + let testWindow = Window() + testWindow.title = "Test Window" + testWindow.contents = "test" + testWindow.move(to: Position(x: 710, y: 525)) + testWindow.resize(to: Size(width: 1000, height: 1000)) + #expect(testWindow.display() == "Test Window\nPosition: (710, 525), Size: (90 x 75)\ntest\n") + } + + @Test("Resize Negative", .enabled(if: RUNALL)) + func testResizeNegative() { + let testWindow = Window() + testWindow.title = "Test Window" + testWindow.contents = "test" + testWindow.resize(to: Size(width: 0, height: -100)) + #expect(testWindow.display() == "Test Window\nPosition: (0, 0), Size: (1 x 1)\ntest\n") + } + + @Test("Update Title", .enabled(if: RUNALL)) + func testUpdateTitle() { let window = Window() window.update(title: "Did it change?") - XCTAssertEqual( - window.display(), - "Did it change?\nPosition: (0, 0), Size: (80 x 60)\n[This window intentionally left blank]\n") + #expect( + window.display() + == "Did it change?\nPosition: (0, 0), Size: (80 x 60)\n[This window intentionally left blank]\n" + ) } - func testUpdateText() throws { - try XCTSkipIf(true && !runAll) // change true to false to run this test + @Test("Update Text", .enabled(if: RUNALL)) + func testUpdateText() { let window = Window() window.update(text: "Did it change?") - XCTAssertEqual( - window.display(), "New Window\nPosition: (0, 0), Size: (80 x 60)\nDid it change?\n") + #expect(window.display() == "New Window\nPosition: (0, 0), Size: (80 x 60)\nDid it change?\n") } - func testUpdateTextNil() throws { - try XCTSkipIf(true && !runAll) // change true to false to run this test + @Test("Update Text Nil", .enabled(if: RUNALL)) + func testUpdateTextNil() { let window = Window() window.update(text: "Did it change?") window.update(text: nil) - XCTAssertEqual( - window.display(), - "New Window\nPosition: (0, 0), Size: (80 x 60)\n[This window intentionally left blank]\n") + #expect( + window.display() + == "New Window\nPosition: (0, 0), Size: (80 x 60)\n[This window intentionally left blank]\n" + ) + } + + @Test("Initialzer accepts all input", .enabled(if: RUNALL)) + func testMainWindow() { + let window = Window(title: "Main Window", contents: "This is the main window", size: Size(width: 400, height: 300), position: Position(x: 100, y: 100)) + #expect( + window.display() + == "Main Window\nPosition: (100, 100), Size: (400 x 300)\nThis is the main window\n") + } + + @Test("Initialzer accepts all input except contents", .enabled(if: RUNALL)) + func testMainWindowNoContents() { + let window = Window(title: "Main Window", contents: nil, size: Size(width: 400, height: 300), position: Position(x: 100, y: 100)) + #expect( + window.display() + == "Main Window\nPosition: (100, 100), Size: (400 x 300)\n[This window intentionally left blank]\n") + } + + @Test("Initialzer accepts all input except size", .enabled(if: RUNALL)) + func testMainWindowNoSize() { + let window = Window(title: "Main Window", contents: "This is the main window", size: Size(), position: Position(x: 100, y: 100)) + #expect( + window.display() + == "Main Window\nPosition: (100, 100), Size: (80 x 60)\nThis is the main window\n") + } + + @Test("Initialzer accepts all input except position", .enabled(if: RUNALL)) + func testMainWindowNoPosition() { + let window = Window(title: "Main Window", contents: "This is the main window", size: Size(width: 400, height: 300), position: Position()) + #expect( + window.display() + == "Main Window\nPosition: (0, 0), Size: (400 x 300)\nThis is the main window\n") + } + + @Test("Initialzer accepts no position and no size", .enabled(if: RUNALL)) + func testMainWindowNoPositionNoSize() { + let window = Window(title: "Main Window", contents: "This is the main window") + #expect( + window.display() + == "Main Window\nPosition: (0, 0), Size: (80 x 60)\nThis is the main window\n") } } From 443e910946285bfc40ac822a5e74e5fd975f56e2 Mon Sep 17 00:00:00 2001 From: meatball Date: Sun, 26 Jan 2025 14:21:04 +0100 Subject: [PATCH 2/3] Update formatting and update hints file --- .../concept/windowing-system/.docs/hints.md | 34 +++++++++++++++++-- .../windowing-system/.docs/instructions.md | 24 +++++++++---- .../WindowingSystemExemplar.swift | 20 +++++------ .../WindowingSystem/WindowingSystem.swift | 4 +-- 4 files changed, 60 insertions(+), 22 deletions(-) diff --git a/exercises/concept/windowing-system/.docs/hints.md b/exercises/concept/windowing-system/.docs/hints.md index 705c26869..a9fd39c61 100644 --- a/exercises/concept/windowing-system/.docs/hints.md +++ b/exercises/concept/windowing-system/.docs/hints.md @@ -7,19 +7,47 @@ ## 1. Define a Size struct - Properties must be defined as `var`s if they can be changed. +- The height and width properties should be given the default values of 80 and 60, respectively. - Methods in a struct must be marked `mutating` if they change properties of the struct. ## 2. Define a Position struct - Properties must be defined as `var`s if they can be changed. +- The x and y properties should be given the default values of 0. - Methods in a struct must be marked `mutating` if they change properties of the struct. ## 3. Define a Window class - Structs can be initialized with different property values using [memberwise initializers][memberwise-initializers]. - Constant properties should be defined using `let`. -- Properties can be changed using their own methods, where available. +- The `contents` property should be optional, as it may not have a value. +- You have to define an empty initializer for the class (`init() {}`). + +## 4. Add a method to resize windows + +- The method should take a `to` parameter of type `Size`. +- It is possible to extract the width and height from the `to` parameter using dot notation. + +## 5. Add a method to move windows + +- The method should take a `to` parameter of type `Position`. +- It is possible to extract the x and y from the `to` parameter using dot notation. + +## 6. Add a method to set the contents of a window + +- It is possible to have two methods with the same name but different parameters in Swift. +- Deffine a method with the parameter `title` that sets the `title` property. +- Deffine a method with the parameter `text` that sets the `contents` property. +- Define a display method that prints the window's title and contents. + +## 7. Create an initilazer for the Window class + +- The class should have two initializers, one that takes no parameters and one that takes parameters. +- The new initializer should have the parameters `title`, and `contents`, it should also allow the optional parameters `size` and `position` + If no parameters are provided, the default values should be used. +- Optional parameters can be achived by using [default parameters vales][default-parameters-vales]. + [structs-and-classes]: https://docs.swift.org/swift-book/LanguageGuide/ClassesAndStructures.html -[memberwise-initializers]: https://docs.swift.org/swift-book/LanguageGuide/ClassesAndStructures.html#ID87 -[initializing-via-closure]: https://docs.swift.org/swift-book/LanguageGuide/Initialization.html#ID232 +[memberwise-initializers]: https://docs.swift.org/swift-book/documentation/the-swift-programming-language/classesandstructures/#Memberwise-Initializers-for-Structure-Types +[default-parameters-vales]: https://docs.swift.org/swift-book/documentation/the-swift-programming-language/functions#Default-Parameter-Values diff --git a/exercises/concept/windowing-system/.docs/instructions.md b/exercises/concept/windowing-system/.docs/instructions.md index 332737cc7..4159d2243 100644 --- a/exercises/concept/windowing-system/.docs/instructions.md +++ b/exercises/concept/windowing-system/.docs/instructions.md @@ -1,6 +1,8 @@ # Instructions -In this exercise, you will be simulating a windowing based computer system. You will create some windows that can be moved and resized and display their contents. The following image is representative of the values you will be working with below. +In this exercise, you will be simulating a windowing based computer system. +You will create some windows that can be moved and resized and display their contents. +The following image is representative of the values you will be working with below. ``` <--------------------- screenSize.width ---------------------> @@ -26,7 +28,8 @@ screenSize.height ║ | │ │ ## 1. Define a Size struct -Define a struct named `Size` with two `Int` properties, `width` and `height` that store the window's current width and height, respectively. The initial width and height should be 80 and 60, respectively. Include a method `resize(newWidth:newHeight:)` that takes new width and height parameters and changes the properties to reflect the new size. +Define a struct named `Size` with two `Int` properties, `width` and `height` that store the window's current width and height, respectively. The initial width and height should be 80 and 60, respectively. +Include a method `resize(newWidth:newHeight:)` that takes new width and height parameters and changes the properties to reflect the new size. ```swift let size1080x764 = Size(width: 1080, height: 764) @@ -40,7 +43,8 @@ size1200x800.height ## 2. Define a Position struct -Define a struct named `Position` with two `Int` properties, `x` and `y` that store the current horizontal and vertical position, respectively, of the window's upper left corner. The initial values of x and y should each be 0. The position (0, 0) is the upper left corner of the screen with `x` values getting larger as you move right and `y` values getting larger as you move down. +Define a struct named `Position` with two `Int` properties, `x` and `y` that store the current horizontal and vertical position, respectively, of the window's upper left corner. +The initial values of x and y should each be 0. The position (0, 0) is the upper left corner of the screen with `x` values getting larger as you move right and `y` values getting larger as you move down. Include a method `moveTo(newX:newY:)` that takes new x and y parameters and changes the properties to reflect the new position. @@ -66,17 +70,23 @@ You should also define an empty initializer for the class. ```swift let window = Window() -window.display() -// returns "New Window\nPosition: (0, 0), Size: (80 x 60)\n[This window intentionally left blank]" +window.title +// returns "New Window" ``` ## 4. Add a method to resize windows -- `resize(to:)` : `(Size) -> ()` - This method takes a `Size` struct as input and attempts to resize the window to the specified size. However, the new size cannot exceed certain bounds. - The minimum allowed height or width is 1. Requested heights or widths less than 1 will be clipped to 1. - The maximum height and width depends on the current position of the window, the edges of the window cannot move past the edges of the screen. Values larger than these bounds will be clipped to the largest size they can take. E.g. if the window's position is at `x` = 400, `y` = 300 and a resize to `height` = 400, `width` = 300 is requested, then the window would be resized to `height` = 300, `width` = 300 as the screen is not large enough in the `y` direction to fully accommodate the request. +- `resize(to:)` : `(Size) -> ()` - This method takes a `Size` struct as input and attempts to resize the window to the specified size. However, the new size cannot exceed certain bounds. +- The minimum allowed height or width is 1. Requested heights or widths less than 1 will be clipped to 1. +- The maximum height and width depends on the current position of the window, the edges of the window cannot move past the edges of the screen. + Values larger than these bounds will be clipped to the largest size they can take. E.g. if the window's position is at `x` = 400, `y` = 300 and a resize to `height` = 400, `width` = 300 is requested, then the window would be resized to `height` = 300, `width` = 300 as the screen is not large enough in the `y` direction to fully accommodate the request. ## 5. Add a method to move windows -- `move(to:)` : `(Position) -> ()` - This is similar to `resize(to:)`, however, this method adjusts the _position_ of the window to the requested value, rather than the size. As with `resize` the new position cannot exceed certain limits. - The smallest position is 0 for both `x` and `y`. - The maximum position in either direction depends on the current size of the window; the edges cannot move past the edges of the screen. Values larger than these bounds will be clipped to the largest size they can take. E.g. if the window's size is at `x` = 250, `y` = 100 and a move to `x` = 600, `y` = 200 is requested, then the window would be moved to `x` = 550, `y` = 200 as the screen is not large enough in the `x` direction to fully accommodate the request. +- `move(to:)` : `(Position) -> ()` - This is similar to `resize(to:)`, however, this method adjusts the _position_ of the window to the requested value, rather than the size. As with `resize` the new position cannot exceed certain limits. +- The smallest position is 0 for both `x` and `y`. +- The maximum position in either direction depends on the current size of the window; the edges cannot move past the edges of the screen. + Values larger than these bounds will be clipped to the largest size they can take. E.g. if the window's size is at `x` = 250, `y` = 100 and a move to `x` = 600, `y` = 200 is requested, then the window would be moved to `x` = 550, `y` = 200 as the screen is not large enough in the `x` direction to fully accommodate the request. ## 6. Add methods to update the window text and display window information diff --git a/exercises/concept/windowing-system/.meta/Sources/WindowingSystem/WindowingSystemExemplar.swift b/exercises/concept/windowing-system/.meta/Sources/WindowingSystem/WindowingSystemExemplar.swift index f39f19b6b..a455a7034 100644 --- a/exercises/concept/windowing-system/.meta/Sources/WindowingSystem/WindowingSystemExemplar.swift +++ b/exercises/concept/windowing-system/.meta/Sources/WindowingSystem/WindowingSystemExemplar.swift @@ -1,13 +1,3 @@ -struct Position { - var x = 0 - var y = 0 - - mutating func moveTo(newX: Int, newY: Int) { - x = newX - y = newY - } -} - struct Size { var width = 80 var height = 60 @@ -18,6 +8,16 @@ struct Size { } } +struct Position { + var x = 0 + var y = 0 + + mutating func moveTo(newX: Int, newY: Int) { + x = newX + y = newY + } +} + class Window { var title = "New Window" let screenSize = Size(width: 800, height: 600) diff --git a/exercises/concept/windowing-system/Sources/WindowingSystem/WindowingSystem.swift b/exercises/concept/windowing-system/Sources/WindowingSystem/WindowingSystem.swift index cfd443f61..06c5356b8 100644 --- a/exercises/concept/windowing-system/Sources/WindowingSystem/WindowingSystem.swift +++ b/exercises/concept/windowing-system/Sources/WindowingSystem/WindowingSystem.swift @@ -1,5 +1,5 @@ -// TODO: Define the Position struct - // TODO: Define the Size struct +// TODO: Define the Position struct + // TODO: Define the Window class From 3a252d2c248d8ae6e24f9261f83069a33819f776 Mon Sep 17 00:00:00 2001 From: meatball Date: Sun, 26 Jan 2025 14:22:39 +0100 Subject: [PATCH 3/3] Change to using normal foundation --- .../Tests/WindowingSystemTests/WindowingSystemTests.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/exercises/concept/windowing-system/Tests/WindowingSystemTests/WindowingSystemTests.swift b/exercises/concept/windowing-system/Tests/WindowingSystemTests/WindowingSystemTests.swift index 3041af407..d0b228e26 100644 --- a/exercises/concept/windowing-system/Tests/WindowingSystemTests/WindowingSystemTests.swift +++ b/exercises/concept/windowing-system/Tests/WindowingSystemTests/WindowingSystemTests.swift @@ -1,4 +1,4 @@ -import FoundationEssentials +import Foundation import Testing @testable import WindowingSystem