From 20c74361c9f45fc9a1fc4eb9ee30a0fca8010906 Mon Sep 17 00:00:00 2001 From: Paul Date: Tue, 5 Aug 2025 17:01:29 +0200 Subject: [PATCH] Initial commit --- .../AccentColor.colorset/Contents.json | 11 +++ .../AppIcon.appiconset/Contents.json | 35 +++++++++ QuizApp/Assets.xcassets/Contents.json | 6 ++ QuizApp/ContentView.swift | 76 +++++++++++++++++++ QuizApp/QuizAppApp.swift | 17 +++++ QuizApp/Topic.swift | 16 ++++ QuizApp/ViewModel.swift | 30 ++++++++ QuizApp/data.json | 12 +++ QuizAppTests/QuizAppTests.swift | 17 +++++ QuizAppUITests/QuizAppUITests.swift | 41 ++++++++++ .../QuizAppUITestsLaunchTests.swift | 33 ++++++++ 11 files changed, 294 insertions(+) create mode 100644 QuizApp/Assets.xcassets/AccentColor.colorset/Contents.json create mode 100644 QuizApp/Assets.xcassets/AppIcon.appiconset/Contents.json create mode 100644 QuizApp/Assets.xcassets/Contents.json create mode 100644 QuizApp/ContentView.swift create mode 100644 QuizApp/QuizAppApp.swift create mode 100644 QuizApp/Topic.swift create mode 100644 QuizApp/ViewModel.swift create mode 100644 QuizApp/data.json create mode 100644 QuizAppTests/QuizAppTests.swift create mode 100644 QuizAppUITests/QuizAppUITests.swift create mode 100644 QuizAppUITests/QuizAppUITestsLaunchTests.swift diff --git a/QuizApp/Assets.xcassets/AccentColor.colorset/Contents.json b/QuizApp/Assets.xcassets/AccentColor.colorset/Contents.json new file mode 100644 index 0000000..eb87897 --- /dev/null +++ b/QuizApp/Assets.xcassets/AccentColor.colorset/Contents.json @@ -0,0 +1,11 @@ +{ + "colors" : [ + { + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/QuizApp/Assets.xcassets/AppIcon.appiconset/Contents.json b/QuizApp/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..2305880 --- /dev/null +++ b/QuizApp/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,35 @@ +{ + "images" : [ + { + "idiom" : "universal", + "platform" : "ios", + "size" : "1024x1024" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "idiom" : "universal", + "platform" : "ios", + "size" : "1024x1024" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "tinted" + } + ], + "idiom" : "universal", + "platform" : "ios", + "size" : "1024x1024" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/QuizApp/Assets.xcassets/Contents.json b/QuizApp/Assets.xcassets/Contents.json new file mode 100644 index 0000000..73c0059 --- /dev/null +++ b/QuizApp/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/QuizApp/ContentView.swift b/QuizApp/ContentView.swift new file mode 100644 index 0000000..460cd4a --- /dev/null +++ b/QuizApp/ContentView.swift @@ -0,0 +1,76 @@ +// +// ContentView.swift +// QuizApp +// +// Created by Paul Nowotka on 02.08.25. +// + +import SwiftUI + +struct ContentView: View { + + @ObservedObject var viewModel = ViewModel() + + @State private var selectedAnswerIndex: Int? = nil + @State private var isAnswered = false + + var body: some View { + VStack { + if let frage = viewModel.topics.first { + Text(frage.question) + .font(.title) + .multilineTextAlignment(.center) + .padding() + + ForEach(frage.answers.indices, id: \.self) { index in + Button(action: { + selectedAnswerIndex = index + isAnswered = true + print("Selected:", index) + print("Correct:", frage.correctAnswer) + }) { + Text(frage.answers[index]) + .padding() + .frame(maxWidth: 300) + .background(buttonColor(for: index, correctIndex: frage.correctAnswer)) + .foregroundColor(.white) + .cornerRadius(10) + } + .disabled(isAnswered) + } + VStack { + if isAnswered { + Text(selectedAnswerIndex == frage.correctAnswer ? "✅ Richtig!" : "❌ Falsch") + .font(.headline) + .foregroundColor(selectedAnswerIndex == frage.correctAnswer ? .green : .red) + .padding() + } + if isAnswered { + Button("Nächste Frage") { + selectedAnswerIndex = nil + isAnswered = false + } + } + } + .frame(height: 80) + } else { + Text("Fragen werden geladen...") + } + } + } + private func buttonColor(for index: Int, correctIndex: Int) -> Color { + guard isAnswered else { return .blue } + + if index == correctIndex { + return .green + } else if index == selectedAnswerIndex { + return .red + } else { + return .gray + } + } +} + +#Preview { + ContentView() +} diff --git a/QuizApp/QuizAppApp.swift b/QuizApp/QuizAppApp.swift new file mode 100644 index 0000000..c61739a --- /dev/null +++ b/QuizApp/QuizAppApp.swift @@ -0,0 +1,17 @@ +// +// QuizAppApp.swift +// QuizApp +// +// Created by Paul Nowotka on 02.08.25. +// + +import SwiftUI + +@main +struct QuizAppApp: App { + var body: some Scene { + WindowGroup { + ContentView() + } + } +} diff --git a/QuizApp/Topic.swift b/QuizApp/Topic.swift new file mode 100644 index 0000000..f1ee44b --- /dev/null +++ b/QuizApp/Topic.swift @@ -0,0 +1,16 @@ +// +// Topic.swift +// QuizApp +// +// Created by Paul Nowotka on 03.08.25. +// + +import Foundation + +struct Topic: Decodable, Hashable { + + let question: String + let answers: [String] + let correctAnswer: Int + +} diff --git a/QuizApp/ViewModel.swift b/QuizApp/ViewModel.swift new file mode 100644 index 0000000..38c076b --- /dev/null +++ b/QuizApp/ViewModel.swift @@ -0,0 +1,30 @@ +// +// ViewModel.swift +// QuizApp +// +// Created by Paul Nowotka on 03.08.25. +// + +import Foundation + +class ViewModel: ObservableObject { + + let topics: [Topic] + + @Published var currentQuestionIndex: Int = 0 + + init() { + guard let url = Bundle.main.url(forResource: "data", withExtension: "json") else { + topics = [] + return + } + + do { + let data = try Data(contentsOf: url) + topics = try JSONDecoder().decode([Topic].self, from: data) + } catch { + print("Fehler beim Laden des Inhalts: \(error)") + topics = [] + } + } +} diff --git a/QuizApp/data.json b/QuizApp/data.json new file mode 100644 index 0000000..b24718f --- /dev/null +++ b/QuizApp/data.json @@ -0,0 +1,12 @@ +[ + { + "question": "Was ist die Hauptstadt von Frankreich?", + "answers": ["Rom", "Berlin", "Paris"], + "correctAnswer": 2 + }, + { + "question": "Was ist die Hauptstadt von Deutschland?", + "answers": ["Rom", "Berlin", "Paris"], + "correctAnswer": 1 + } +] diff --git a/QuizAppTests/QuizAppTests.swift b/QuizAppTests/QuizAppTests.swift new file mode 100644 index 0000000..5730e4f --- /dev/null +++ b/QuizAppTests/QuizAppTests.swift @@ -0,0 +1,17 @@ +// +// QuizAppTests.swift +// QuizAppTests +// +// Created by Paul Nowotka on 02.08.25. +// + +import Testing +@testable import QuizApp + +struct QuizAppTests { + + @Test func example() async throws { + // Write your test here and use APIs like `#expect(...)` to check expected conditions. + } + +} diff --git a/QuizAppUITests/QuizAppUITests.swift b/QuizAppUITests/QuizAppUITests.swift new file mode 100644 index 0000000..493e37d --- /dev/null +++ b/QuizAppUITests/QuizAppUITests.swift @@ -0,0 +1,41 @@ +// +// QuizAppUITests.swift +// QuizAppUITests +// +// Created by Paul Nowotka on 02.08.25. +// + +import XCTest + +final class QuizAppUITests: XCTestCase { + + override func setUpWithError() throws { + // Put setup code here. This method is called before the invocation of each test method in the class. + + // In UI tests it is usually best to stop immediately when a failure occurs. + continueAfterFailure = false + + // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this. + } + + override func tearDownWithError() throws { + // Put teardown code here. This method is called after the invocation of each test method in the class. + } + + @MainActor + func testExample() throws { + // UI tests must launch the application that they test. + let app = XCUIApplication() + app.launch() + + // Use XCTAssert and related functions to verify your tests produce the correct results. + } + + @MainActor + func testLaunchPerformance() throws { + // This measures how long it takes to launch your application. + measure(metrics: [XCTApplicationLaunchMetric()]) { + XCUIApplication().launch() + } + } +} diff --git a/QuizAppUITests/QuizAppUITestsLaunchTests.swift b/QuizAppUITests/QuizAppUITestsLaunchTests.swift new file mode 100644 index 0000000..b1d4f8e --- /dev/null +++ b/QuizAppUITests/QuizAppUITestsLaunchTests.swift @@ -0,0 +1,33 @@ +// +// QuizAppUITestsLaunchTests.swift +// QuizAppUITests +// +// Created by Paul Nowotka on 02.08.25. +// + +import XCTest + +final class QuizAppUITestsLaunchTests: XCTestCase { + + override class var runsForEachTargetApplicationUIConfiguration: Bool { + true + } + + override func setUpWithError() throws { + continueAfterFailure = false + } + + @MainActor + func testLaunch() throws { + let app = XCUIApplication() + app.launch() + + // Insert steps here to perform after app launch but before taking a screenshot, + // such as logging into a test account or navigating somewhere in the app + + let attachment = XCTAttachment(screenshot: app.screenshot()) + attachment.name = "Launch Screen" + attachment.lifetime = .keepAlways + add(attachment) + } +}