From 3b78f0388c0a6446175ad5f9bf97a3d1effac31d Mon Sep 17 00:00:00 2001 From: JC Dela Cuesta Date: Tue, 4 Mar 2025 07:49:06 -0800 Subject: [PATCH] Homework Submission for OOP & POP Programming Added XC Playground file for Exercises 1-3 --- .../Contents.swift | 313 ++++++++++++++++++ .../contents.xcplayground | 2 + .../contents.xcworkspacedata | 7 + .../UserInterfaceState.xcuserstate | Bin 0 -> 17152 bytes 4 files changed, 322 insertions(+) create mode 100644 OOP_POP_Exercises 1-3_JC.playground/Contents.swift create mode 100644 OOP_POP_Exercises 1-3_JC.playground/contents.xcplayground create mode 100644 OOP_POP_Exercises 1-3_JC.playground/playground.xcworkspace/contents.xcworkspacedata create mode 100644 OOP_POP_Exercises 1-3_JC.playground/playground.xcworkspace/xcuserdata/jdelacuesta.xcuserdatad/UserInterfaceState.xcuserstate diff --git a/OOP_POP_Exercises 1-3_JC.playground/Contents.swift b/OOP_POP_Exercises 1-3_JC.playground/Contents.swift new file mode 100644 index 0000000..390e1a1 --- /dev/null +++ b/OOP_POP_Exercises 1-3_JC.playground/Contents.swift @@ -0,0 +1,313 @@ +import UIKit + +// MARK: - Exercise 1: Social Media Post + +class Post { + var author: String + var content: String + var likes: Int + + init(author: String, content: String, likes: Int = 0) { + self.author = author + self.content = content + self.likes = likes + } + + func display() { + print("Post by \(author):") + print("\"\(content)\"") + print("Likes: \(likes)") + print(String(repeating: "-", count: 30)) // Separator line for better readability + } +} + +// MARK: - Main program functionality + +func main() { + // Create first post + let post1 = Post(author: "Alice", content: "Just finished my first iOS assignment!", likes: 15) + + // Create second post + let post2 = Post(author: "Bob", content: "Learning Swift classes is fun!", likes: 7) + + // Display both posts + post1.display() + post2.display() +} + +// Calling the main function +main() + + +// MARK: - Exercise 2: Using the Singleton Pattern to create a more flexible shopping cart system + +// Product Class +class Product { + let name: String + let price: Double + var quantity: Int + + init(name: String, price: Double, quantity: Int = 1) { + self.name = name + self.price = price + self.quantity = quantity + } +} + +//MARK: - DiscountStrategy Protocol and Implementations + +protocol DiscountStrategy { + func calculateDiscount(total: Double) -> Double +} + +class NoDiscountStrategy: DiscountStrategy { + func calculateDiscount(total: Double) -> Double { + return 0.0 // No discount + } +} + +class PercentageDiscountStrategy: DiscountStrategy { + let percentage: Double + + init(percentage: Double) { + self.percentage = min(percentage, 100.0) // Ensure discount doesn't exceed 100% + } + + func calculateDiscount(total: Double) -> Double { + return total * (percentage / 100.0) + } +} + +//MARK: - ShoppingCartSingleton Class + +class ShoppingCartSingleton { + // Static property for the singleton instance + private static var instance: ShoppingCartSingleton? + + // Private array to store products (composition) + private var products: [Product] = [] + + // Discount strategy + var discountStrategy: DiscountStrategy = NoDiscountStrategy() + + // Private initializer to enforce singleton pattern + private init() {} + + // Method to access the singleton instance + static func sharedInstance() -> ShoppingCartSingleton { + if instance == nil { + instance = ShoppingCartSingleton() + } + return instance! + } + + // Method to add a product to the cart + func addProduct(product: Product, quantity: Int = 1) { + // Check if the product is already in the cart + if let index = products.firstIndex(where: { $0.name == product.name }) { + // If it is, update the quantity + products[index].quantity += quantity + } else { + // If not, add the product with the specified quantity + let newProduct = Product(name: product.name, price: product.price, quantity: quantity) + products.append(newProduct) + } + } + + // Method to remove a product from the cart + func removeProduct(product: Product) { + products.removeAll { $0.name == product.name } + } + + // Method to clear the cart + func clearCart() { + products.removeAll() + } + + // Method to calculate the total price + func getTotalPrice() -> Double { + let subtotal = products.reduce(0.0) { $0 + ($1.price * Double($1.quantity)) } + let discount = discountStrategy.calculateDiscount(total: subtotal) + return subtotal - discount + } + + // Helper method to display cart contents + func displayCart() { + if products.isEmpty { + print("Shopping cart is empty.") + return + } + + print("Shopping Cart Contents:") + print("------------------------") + for product in products { + print("\(product.name) - $\(product.price) x \(product.quantity) = $\(product.price * Double(product.quantity))") + } + + let subtotal = products.reduce(0.0) { $0 + ($1.price * Double($1.quantity)) } + let discount = discountStrategy.calculateDiscount(total: subtotal) + + print("------------------------") + print("Subtotal: $\(subtotal)") + print("Discount: $\(discount)") + print("Total: $\(getTotalPrice())") + print("------------------------") + } +} + +//MARK: - Example Usage + +func mainexample() { + // Singleton pattern to shopping cart instance + let cart = ShoppingCartSingleton.sharedInstance() + + // Example product creation + let laptop = Product(name: "Laptop", price: 1299.99) + let phone = Product(name: "Smartphone", price: 599.99) + let charger = Product(name: "USB-C Charger", price: 19.99) + + // Adding products to the cart + cart.addProduct(product: laptop) + cart.addProduct(product: phone, quantity: 2) + cart.addProduct(product: charger, quantity: 3) + + // Displaying the cart with no discount + print("Cart with no discount:") + cart.displayCart() + + // Applying a 10% discount + cart.discountStrategy = PercentageDiscountStrategy(percentage: 10.0) + print("\nCart with 10% discount:") + cart.displayCart() + + // Removing a product + cart.removeProduct(product: phone) + print("\nCart after removing smartphones:") + cart.displayCart() + + // Clearing the cart + cart.clearCart() + print("\nCart after clearing:") + cart.displayCart() +} + +// Running the example usage +main() + +// MARK: - Exercise 3: Payment System Model & Custom Error Type for Payment Processing + +enum PaymentError: Error { + case insufficientFunds + case invalidCard + case cardExpired + case networkError + case paymentLimitExceeded + case cashRegisterEmpty + + var message: String { + switch self { + case .insufficientFunds: + return "Insufficient funds to complete the transaction." + case .invalidCard: + return "The card information is invalid." + case .cardExpired: + return "The card has expired." + case .networkError: + return "Network error occurred during payment processing." + case .paymentLimitExceeded: + return "The payment amount exceeds the allowed limit." + case .cashRegisterEmpty: + return "Cash register is empty and cannot provide change." + } + } +} + +// MARK: - Payment Processor Protocol + +protocol PaymentProcessor { + func processPayment(amount: Double) throws + var name: String { get } +} + +// MARK: - Credit Card Processor + +class CreditCardProcessor: PaymentProcessor { + let name = "Credit Card" + private let cardNumber: String + private let expiryDate: String + private let cvv: String + private let balance: Double + + init(cardNumber: String, expiryDate: String, cvv: String, balance: Double) { + self.cardNumber = cardNumber + self.expiryDate = expiryDate + self.cvv = cvv + self.balance = balance + } + + func processPayment(amount: Double) throws { + // Validate the amount + if amount <= 0 { + throw PaymentError.invalidCard + } + + // Check for payment limits + if amount > 10000 { + throw PaymentError.paymentLimitExceeded + } + + // Simulate card validation + if cardNumber.count != 16 { + throw PaymentError.invalidCard + } + + // Simulate expiry date check (very basic simulation) + if expiryDate == "01/20" { + throw PaymentError.cardExpired + } + + // Check for sufficient funds + if amount > balance { + throw PaymentError.insufficientFunds + } + + // Simulate random network error (10% chance) + if Double.random(in: 0...1) < 0.1 { + throw PaymentError.networkError + } + + // If we reach here, payment is successful + print("Credit card payment of $\(amount) processed successfully.") + } +} + +// MARK: - Cash Processor + +class CashProcessor: PaymentProcessor { + let name = "Cash" + private var cashInRegister: Double + + init(cashInRegister: Double) { + self.cashInRegister = cashInRegister + } + + func processPayment(amount: Double) throws { + // Validating the amount + if amount <= 0 { + throw PaymentError.invalidCard // Reusing error for simplicity + } + + // Check if providing change is possible + if cashInRegister < amount { + throw PaymentError.cashRegisterEmpty + } + + // Processing payment + cashInRegister -= amount + + // If below messages display, payment is successful + print("Cash payment of $\(amount) processed successfully.") + print("Remaining cash in register: $\(cashInRegister)") + } +} + diff --git a/OOP_POP_Exercises 1-3_JC.playground/contents.xcplayground b/OOP_POP_Exercises 1-3_JC.playground/contents.xcplayground new file mode 100644 index 0000000..7f43ce8 --- /dev/null +++ b/OOP_POP_Exercises 1-3_JC.playground/contents.xcplayground @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/OOP_POP_Exercises 1-3_JC.playground/playground.xcworkspace/contents.xcworkspacedata b/OOP_POP_Exercises 1-3_JC.playground/playground.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..ca3329e --- /dev/null +++ b/OOP_POP_Exercises 1-3_JC.playground/playground.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/OOP_POP_Exercises 1-3_JC.playground/playground.xcworkspace/xcuserdata/jdelacuesta.xcuserdatad/UserInterfaceState.xcuserstate b/OOP_POP_Exercises 1-3_JC.playground/playground.xcworkspace/xcuserdata/jdelacuesta.xcuserdatad/UserInterfaceState.xcuserstate new file mode 100644 index 0000000000000000000000000000000000000000..a4c6a7cc106060e8d3cad51814d63f081ad7239a GIT binary patch literal 17152 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 b*X)PwN9}LfKa`w5LZnabH|f*=Za@7$*thH9 literal 0 HcmV?d00001