diff --git a/.idea/workspace.xml b/.idea/workspace.xml
index 300a6e2..8d66291 100644
--- a/.idea/workspace.xml
+++ b/.idea/workspace.xml
@@ -4,7 +4,11 @@
-
+
+
+
+
+
@@ -34,37 +38,38 @@
- {
- "keyToString": {
- "DefaultGoTemplateProperty": "Go File",
- "ModuleVcsDetector.initialDetectionPerformed": "true",
- "RunOnceActivity.GoLinterPluginOnboarding": "true",
- "RunOnceActivity.GoLinterPluginStorageMigration": "true",
- "RunOnceActivity.ShowReadmeOnStart": "true",
- "RunOnceActivity.TerminalTabsStorage.copyFrom.TerminalArrangementManager": "true",
- "RunOnceActivity.git.unshallow": "true",
- "RunOnceActivity.go.formatter.settings.were.checked": "true",
- "RunOnceActivity.go.migrated.go.modules.settings": "true",
- "RunOnceActivity.go.modules.go.list.on.any.changes.was.set": "true",
- "git-widget-placeholder": "main",
- "go.import.settings.migrated": "true",
- "go.sdk.automatically.set": "true",
- "last_opened_file_path": "/Users/zopdev/GolandProjects/assignment",
- "node.js.detected.package.eslint": "true",
- "node.js.selected.package.eslint": "(autodetect)",
- "nodejs_package_manager_path": "npm"
+
+}]]>
+
+
+
-
-
-
-
+
@@ -92,6 +97,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
@@ -103,6 +120,7 @@
+
diff --git a/assign3/assign3_test.go b/assign3/assign3_test.go
new file mode 100644
index 0000000..56b0ce3
--- /dev/null
+++ b/assign3/assign3_test.go
@@ -0,0 +1,81 @@
+package main
+
+import (
+ "fmt"
+ "testing"
+)
+
+func TestCompleteTask(t *testing.T) {
+ tracker := NewTaskTracker()
+ tracker.AddTask("Read a book")
+ tracker.AddTask("Play")
+ tracker.AddTask("Clean")
+
+ success, msg := tracker.CompleteTask(2)
+ if !success {
+ t.Errorf("Expected task 2 to be completed successfully, but it failed: %s", msg)
+ }
+ fmt.Println(msg)
+ if msg != "Marking task 2 as completed: Play" {
+ t.Errorf("Incorrect success message. Got: '%s'", msg)
+ }
+ if !tracker.tasks[1].Completed {
+ t.Errorf("Task 2 should be marked as completed")
+ }
+
+ success, msg = tracker.CompleteTask(2)
+ if success {
+ t.Errorf("Expected task 2 to not be completed, but it succeeded.")
+ }
+ if msg != "Task 2 is already completed." {
+ t.Errorf("Incorrect already completed message '%s'", msg)
+ }
+
+ success, msg = tracker.CompleteTask(99)
+ if success {
+ t.Errorf("Expected task 99 to not be completed, but it succeeded.")
+ }
+ if msg != "Task with ID 99 not found." {
+ t.Errorf("Incorrect not found message. Got: '%s'", msg)
+ }
+
+ if tracker.tasks[0].Completed {
+ t.Errorf("Task 1 should not be completed")
+ }
+ if tracker.tasks[2].Completed {
+ t.Errorf("Task 3 should not be completed")
+ }
+}
+
+func TestListTasks(t *testing.T) {
+ tracker := NewTaskTracker()
+
+ expected := "Pending Tasks:\nNo pending tasks."
+ if tracker.ListTasks() != expected {
+ t.Errorf("Expected '%s', got '%s'", expected, tracker.ListTasks())
+ }
+
+ tracker.AddTask("Task A")
+ expected = "Pending Tasks:\n1: Task A\n"
+ if tracker.ListTasks() != expected {
+ t.Errorf("Expected '%s', got '%s'", expected, tracker.ListTasks())
+ }
+
+ tracker.AddTask("Task B")
+ expected = "Pending Tasks:\n1: Task A\n2: Task B\n"
+ if tracker.ListTasks() != expected {
+ t.Errorf("Expected '%s', got '%s'", expected, tracker.ListTasks())
+ }
+
+ tracker.CompleteTask(1)
+ expected = "Pending Tasks:\n2: Task B\n"
+ if tracker.ListTasks() != expected {
+ t.Errorf("Expected '%s', got '%s'", expected, tracker.ListTasks())
+ }
+
+ tracker.CompleteTask(2)
+ expected = "Pending Tasks:\nNo pending tasks."
+ if tracker.ListTasks() != expected {
+ t.Errorf("Expected '%s', got '%s'", expected, tracker.ListTasks())
+ }
+}
diff --git a/assign3/assignment3.go b/assign3/assignment3.go
index 93cfd49..922ca22 100644
--- a/assign3/assignment3.go
+++ b/assign3/assignment3.go
@@ -1,78 +1,150 @@
package main
-import "fmt"
+import (
+ "bufio"
+ "fmt"
+ "os"
+ "strconv"
+ "strings"
+)
-type BankAccount struct {
- Owner string
- Balance float64
+// Task represents a single task in our tracker.
+type Task struct {
+ ID int
+ Description string
+ Completed bool
}
-// a value receiver is appropriate here. Changes to 'b' inside this method
-// would only affect a copy, not the 'myAccount' variable in main.
-func (b BankAccount) DisplayBalance() {
- fmt.Printf("%s's current balance: $%.2f\n", b.Owner, b.Balance)
+// TaskTracker manages the collection of tasks and generates unique IDs.
+type TaskTracker struct {
+ tasks []Task
+ nextIDGen func() int
}
-// Deposit is a method with a POINTER RECEIVER (b *BankAccount).
-// It increases the balance of the account by the given amount.
-func (b *BankAccount) Deposit(amount float64) {
- if amount <= 0 {
- fmt.Printf("Deposit amount must be positive. Skipping deposit of $%.2f.\n", amount)
- return
+// idGenerator is a closure that generates unique sequential integer IDs.
+// It encapsulates the 'id' counter, so it's not a global variable.
+func idGenerator() func() int {
+ id := 0
+ return func() int {
+ id++
+ return id
}
- b.Balance += amount // This modifies the original BankAccount's balance
- fmt.Printf("Deposited $%.2f. New balance: $%.2f\n", amount, b.Balance)
}
-// Withdraw is a method with a POINTER RECEIVER (b *BankAccount).
-// It decreases the balance, but only if sufficient funds exist.
-func (b *BankAccount) Withdraw(amount float64) {
- if amount <= 0 {
- fmt.Printf("Withdrawal amount must be positive. Skipping withdrawal of $%.2f.\n", amount)
- return
- }
- if b.Balance >= amount {
- b.Balance -= amount // This modifies the original BankAccount's balance
- fmt.Printf("Withdrew $%.2f. New balance: $%.2f\n", amount, b.Balance)
- } else {
- fmt.Printf("Insufficient funds for withdrawal of $%.2f. Current balance: $%.2f.\n", amount, b.Balance)
+// NewTaskTracker creates and initializes a new TaskTracker instance.
+// It also sets up the unique ID generator.
+func NewTaskTracker() *TaskTracker {
+ return &TaskTracker{
+ tasks: []Task{},
+ nextIDGen: idGenerator(),
}
}
-// TryToModifyBalance is a standalone function that demonstrates passing a BankAccount by value.
-// Any changes to 'b' within this function will only affect a copy, not the original variable passed.
-func TryToModifyBalance(b BankAccount, amount float64) {
- b.Balance += amount // This only modifies the *copy* of BankAccount passed in
- fmt.Printf(" (Inside TryToModifyBalance func): Balance changed to $%.2f\n", b.Balance)
+// AddTask adds a new task to the tracker and returns the added Task.
+// It uses a pointer receiver (*TaskTracker) because it modifies the TaskTracker's state (its 'tasks' slice).
+func (tt *TaskTracker) AddTask(description string) Task {
+ newID := tt.nextIDGen()
+ newTask := Task{
+ ID: newID,
+ Description: description,
+ Completed: false,
+ }
+ tt.tasks = append(tt.tasks, newTask)
+ return newTask
}
-func main() {
- fmt.Println("--- Bank Account System Demonstration ---")
+// ListTasks displays all pending tasks.
+// It uses a pointer receiver (*TaskTracker) because it operates on the TaskTracker's 'tasks' slice,
+// even though it doesn't modify it directly in this function (good practice for methods operating on collections).
+func (tt *TaskTracker) ListTasks() string {
+ s := "Pending Tasks:\n"
+ foundPending := false
+ for _, task := range tt.tasks {
+ if !task.Completed {
+ s += fmt.Sprintf("%d: %s\n", task.ID, task.Description)
+ foundPending = true
+ }
+ }
+ if !foundPending {
+ s += "No pending tasks."
+ }
+ return s
+}
- myAccount := BankAccount{
- Owner: "Alice",
- Balance: 100.00, // Initial balance
+// CompleteTask marks a task as completed given its ID.
+// It returns a boolean indicating if the task was found and its completion status was changed,
+// and a string message describing the outcome.
+// It uses a pointer receiver (*TaskTracker) because it modifies the state of a Task within the tracker's slice.
+func (tt *TaskTracker) CompleteTask(id int) (bool, string) {
+ for i := range tt.tasks {
+ if tt.tasks[i].ID == id {
+ if tt.tasks[i].Completed {
+ return false, fmt.Sprintf("Task %d is already completed.", id)
+ }
+ tt.tasks[i].Completed = true
+ return true, fmt.Sprintf("Marking task %d as completed: %s", id, tt.tasks[i].Description)
+ }
}
- fmt.Println("\n--- Initial State ---")
- myAccount.DisplayBalance()
- fmt.Println("\n--- Deposit Funds ---")
- myAccount.Deposit(50.50)
- myAccount.DisplayBalance() // Observe the change
- fmt.Println("\n--- Attempting Withdrawals ---")
- myAccount.Withdraw(25.00)
- myAccount.DisplayBalance()
- myAccount.Withdraw(200.00)
- myAccount.DisplayBalance()
+ return false, fmt.Sprintf("Task with ID %d not found.", id)
+}
- fmt.Println("\n--- Final State ---")
- myAccount.DisplayBalance()
- fmt.Println("\n--- Demonstrating Value Receiver vs. Pointer Receiver Effect ---")
- tempAccount := BankAccount{Owner: "Bob", Balance: 50.00}
- fmt.Printf("Bob's balance BEFORE TryToModifyBalance: $%.2f\n", tempAccount.Balance)
- TryToModifyBalance(tempAccount, 20.00) // Pass by value
- fmt.Printf("Bob's balance AFTER TryToModifyBalance: $%.2f (Did not change externally)\n", tempAccount.Balance)
+// displayMenu prints the interactive menu options to the console.
+func displayMenu() {
+ fmt.Println("\n--- Personal Task Tracker ---")
+ fmt.Println("1. Add a new task")
+ fmt.Println("2. List all pending tasks")
+ fmt.Println("3. Mark a task as completed")
+ fmt.Println("4. Exit")
+ fmt.Print("Choose an option: ")
+}
+
+// getUserInput reads a line of text from the standard input.
+func getUserInput() string {
+ reader := bufio.NewReader(os.Stdin)
+ input, _ := reader.ReadString('\n')
+ return strings.TrimSpace(input)
+}
- fmt.Printf("Alice's balance BEFORE Deposit (again): $%.2f\n", myAccount.Balance)
- myAccount.Deposit(10.00) // This actually modifies myAccount
- fmt.Printf("Alice's balance AFTER Deposit (again): $%.2f (Changed externally)\n", myAccount.Balance)
+// main function orchestrates the CLI interaction.
+func main() {
+ tracker := NewTaskTracker()
+
+ for {
+ displayMenu()
+ choiceStr := getUserInput()
+ choice, err := strconv.Atoi(choiceStr)
+ if err != nil {
+ fmt.Println("Invalid choice. Please enter a number between 1 and 4.")
+ continue
+ }
+
+ switch choice {
+ case 1:
+ fmt.Print("Enter task description: ")
+ description := getUserInput()
+ if description == "" {
+ fmt.Println("Task description cannot be empty.")
+ continue
+ }
+ addedTask := tracker.AddTask(description)
+ fmt.Printf("Task Added: %d - %s\n", addedTask.ID, addedTask.Description)
+ case 2:
+ fmt.Println(tracker.ListTasks())
+ case 3:
+ fmt.Print("Enter ID of task to mark as completed: ")
+ idStr := getUserInput()
+ id, err := strconv.Atoi(idStr)
+ if err != nil {
+ fmt.Println("Invalid ID. Please enter a valid number.")
+ continue
+ }
+ _, msg := tracker.CompleteTask(id)
+ fmt.Println(msg)
+ case 4:
+ fmt.Println("Exiting Task Tracker. Goodbye!")
+ return
+ default:
+ fmt.Println("Invalid option. Please choose a number between 1 and 4.")
+ }
+ }
}
diff --git a/assign5/assign5_1/assign_5_1.go b/assign5/assign5_1/assign_5_1.go
index 84fc85b..9ed768e 100644
--- a/assign5/assign5_1/assign_5_1.go
+++ b/assign5/assign5_1/assign_5_1.go
@@ -32,6 +32,17 @@ func calArea(s Shape) float64 {
return s.Area()
}
+func costs(s Shape) float64 {
+ switch s.(type) {
+ case square:
+ return s.Area() * 100
+ case rectangle:
+ return s.Area() * 20
+ default:
+ return s.Area()
+ }
+}
+
func main() {
rect := rectangle{b: 10, l: 20}
@@ -43,4 +54,10 @@ func main() {
sq := square{l: 10}
squareArea := calArea(sq)
fmt.Printf("Area of square: %.2f\n", squareArea)
+
+ cost := costs(sq)
+ fmt.Printf("Cost of square: %.2f\n", cost)
+
+ cost = costs(rect)
+ fmt.Printf("Cost of recct: %.2f\n", cost)
}
diff --git a/assign5/assign5_1/shape_test.go b/assign5/assign5_1/shape_test.go
new file mode 100644
index 0000000..14fcda5
--- /dev/null
+++ b/assign5/assign5_1/shape_test.go
@@ -0,0 +1,45 @@
+package main
+
+import "testing"
+
+func TestCosts(t *testing.T) {
+ tests := []struct {
+ name string
+ shape Shape
+ expectedCost float64
+ }{
+ {
+ name: "Square_Cost",
+ shape: square{l: 5},
+ expectedCost: 25 * 100,
+ },
+ {
+ name: "Rectangle_Cost",
+ shape: rectangle{l: 4.222222, b: 1},
+ expectedCost: 4.222222 * 20,
+ },
+ {
+ name: "Square_ZeroArea",
+ shape: square{l: 0},
+ expectedCost: 0,
+ }, {
+ name: "react_ZeroArea",
+ shape: rectangle{l: 0, b: 0},
+ expectedCost: 0,
+ }}
+
+ for _, tt := range tests {
+ t.Logf("Running test case: %s \n", tt.name)
+
+ gotCost := costs(tt.shape)
+ tol := 1e-4
+ currentToll := gotCost - tt.expectedCost
+
+ if currentToll > tol {
+ t.Errorf("FAIL: Test %s For shape %T (Area: %f), expected cost %f, but got %f",
+ tt.name, tt.shape, tt.shape.Area(), tt.expectedCost, gotCost)
+ } else {
+ t.Logf("PASS: Test %s", tt.name)
+ }
+ }
+}