Example Class:

// Suppose we have a class:
public class Dog {
    private String name;
    public Dog(String name) {
        this.name = name;
    }
    public void bark() {
        System.out.println(name + " says: Woof!");
    }
}

// To use it:
Dog d = new Dog("Fido");  // create an instance
d.bark();                 // call the instance method on d

Popcorn Hack #1

  • Add another property to the dog class for breed.
  • Add another method to the dog class that prints “My dog name is a breed!”
  • Create a new object of this class and call the method.
// Work by Anvay Vahia

public class Dog {
    // Properties
    private String name;
    private String breed;

    // Constructor
    public Dog(String name, String breed) {
        this.name = name;
        this.breed = breed;
    }

    // Method 1: bark
    public void bark() {
        System.out.println(name + " says: Woof!");
    }

    // Method 2: describe
    public void describe() {
        System.out.println("My dog " + name + " is a " + breed + "!");
    }
}

// To use it:
Dog myDog = new Dog("Buddy", "Golden Retriever");
myDog.bark();
myDog.describe();
Buddy says: Woof!
My dog Buddy is a Golden Retriever!

Example Class 2:

public class Counter {
    private int count;
    public void add(int x) {
        count += x;
    }
    public int getCount() {
        return count;
    }
}

// Use it:
Counter c = new Counter();
c.add(5);
int val = c.getCount();  // returns 5

Popcorn Hack #2

  • Add on to the previous counter class and add three more methods for subtraction, multiplication, and division.

  • Call all five methods outside of the class.

// Work by Anvay Vahia

public class Counter {
    private int count;
    
    // Add method
    public void add(int x) {
        count += x;
    }

    // Subtract method
    public void subtract(int x) {
        count -= x;
    }

    // Multiply method
    public void multiply(int x) {
        count *= x;
    }

    // Divide method
    public void divide(int x) {
        if (x != 0) {
            count /= x;
        } else {
            System.out.println("Cannot divide by zero!");
        }
    }

    // Getter method
    public int getCount() {
        return count;
    }
}

// Use it:
Counter c = new Counter();
c.add(10);        // count = 10
c.subtract(3);    // count = 7
c.multiply(2);    // count = 14
c.divide(7);      // count = 2
int val = c.getCount();  // 2

System.out.println("Final count = " + val);
Final count = 2

MC Hacks

Question 1

Consider the following class:

public class BankAccount {
    private double balance;
    
    public BankAccount(double initialBalance) {
        balance = initialBalance;
    }
    
    public void deposit(double amount) {
        balance += amount;
    }
    
    public double getBalance() {
        return balance;
    }
}

Which of the following code segments will compile without error:

A)

BankAccount.deposit(50.0);
double total = BankAccount.getBalance();

B)

BankAccount account = new BankAccount(100.0);
account.deposit(50.0);
double total = account.getBalance();

C)

BankAccount account = new BankAccount(100.0);
double total = account.deposit(50.0);

D)

BankAccount account;
account.deposit(50.0);
double total = account.getBalance();

E)

double total = getBalance();
BankAccount account = new BankAccount(total);

Question 2

What is printed as a result of executing the following code?

public class Rectangle {
    private int length;
    private int width;
    
    public Rectangle(int l, int w) {
        length = l;
        width = w;
    }
    
    public int getArea() {
        return length * width;
    }
    
    public void scale(int factor) {
        length *= factor;
        width *= factor;
    }
}

Rectangle rect = new Rectangle(3, 4);
rect.scale(2);
System.out.println(rect.getArea());

A) 12

B) 24

C) 48

D) 96

E) Nothing is printed; the code does not compile

Question 3

Which of the following best describes when a NullPointerException will occur when calling an instance method?

A) When the method is declared as void

B) When the method is called on a reference variable that has not been initialized to an object

C) When the method’s parameters do not match the arguments provided

D) When the method is called from outside the class

E) When the method attempts to return a value but is declared as void

Question 4

Which of the following code segments will NOT compile?

public class Temperature {
    private double celsius;
    
    public Temperature(double c) {
        celsius = c;
    }
    
    public double getFahrenheit() {
        return celsius * 9.0 / 5.0 + 32;
    }
    
    public void setCelsius(double c) {
        celsius = c;
    }
}

A)

Temperature temp = new Temperature(0);
System.out.println(temp.getFahrenheit());

B)

Temperature temp = new Temperature(100);
temp.setCelsius(25);

C)

Temperature temp = new Temperature(20);
double f = temp.getFahrenheit();

D)

Temperature temp = new Temperature(15);
int result = temp.setCelsius(30);

E)

Temperature temp = new Temperature(0);
temp.setCelsius(100);
double f = temp.getFahrenheit();

Question 5

Consider the following class:

public class Book {
    private String title;
    private int pages;
    
    public Book(String t, int p) {
        title = t;
        pages = p;
    }
    
    public String getTitle() {
        return title;
    }
    
    public int getPages() {
        return pages;
    }
    
    public void addPages(int additional) {
        pages += additional;
    }
}

Assume that the following code segment appears in a class other than Book:

Book novel = new Book("Java Basics", 200);
novel.addPages(50);
/* missing code */

Which of the following can replace /* missing code */ so that the value 250 is printed?

A) System.out.println(pages);

B) System.out.println(novel.pages);

C) System.out.println(Book.getPages());

D) System.out.println(novel.getPages());

E) System.out.println(getPages());

MC Question Answers with Explanations

Question 1: Answer - B

Correct Answer: B

BankAccount account = new BankAccount(100.0);
account.deposit(50.0);
double total = account.getBalance();

Detailed Explanations:

  • A) INCORRECT - BankAccount.deposit(50.0); and BankAccount.getBalance(); attempt to call instance methods as if they were static methods. Instance methods must be called on an object instance, not on the class itself.

  • B) CORRECT - This properly creates a BankAccount object, then calls instance methods on that specific object. The sequence is: create object → call deposit method → call getBalance method.

  • C) INCORRECT - double total = account.deposit(50.0); tries to assign the return value of deposit() to a double variable, but deposit() is a void method that doesn’t return anything.

  • D) INCORRECT - BankAccount account; declares a reference variable but doesn’t initialize it to an object. Calling methods on an uninitialized reference will cause a NullPointerException.

  • E) INCORRECT - getBalance() is called without an object reference. Instance methods must be called on a specific object instance.

Question 2: Answer - C (48)

Correct Answer: C - 48

Step-by-step execution:

  1. Rectangle rect = new Rectangle(3, 4); - Creates rectangle with length=3, width=4
  2. rect.scale(2); - Multiplies both dimensions by 2: length=6, width=8
  3. rect.getArea() - Calculates area: 6 × 8 = 48
  4. System.out.println(48); - Prints 48

Why other answers are wrong:

  • A) 12 - This would be the original area (3×4) before scaling
  • B) 24 - This would be if only one dimension was scaled
  • D) 96 - This would be if the area was calculated then scaled (12×2×4)
  • E) - The code compiles and runs perfectly

Question 3: Answer - B

Correct Answer: B - When the method is called on a reference variable that has not been initialized to an object

Detailed Explanation: A NullPointerException occurs when you try to call a method on a null reference. This happens when:

  • You declare a reference variable but never assign it to an object
  • You explicitly set a reference to null
  • A method returns null and you call a method on that return value

Example that causes NullPointerException:

BankAccount account;  // declared but not initialized (null by default)
account.deposit(50);  // NullPointerException here!

Why other answers are wrong:

  • A) - void methods can be called normally; return type doesn’t affect this
  • C) - Parameter mismatches cause compile-time errors, not NullPointerException
  • D) - Methods can be called from outside the class if they’re public
  • E) - Returning a value from void method causes compile error, not runtime exception

Question 4: Answer - D

Correct Answer: D

Temperature temp = new Temperature(15);
int result = temp.setCelsius(30);  // ERROR: void method cannot be assigned to variable

Detailed Explanation: The setCelsius method is declared as void, meaning it doesn’t return a value. Attempting to assign its “return value” to an int variable causes a compile-time error.

Analysis of each option:

  • A) CORRECT - Creates object and calls getFahrenheit() which returns a double
  • B) CORRECT - Creates object and calls setCelsius() without trying to capture return value
  • C) CORRECT - Creates object, calls getFahrenheit(), and assigns return value to double variable
  • D) INCORRECT - Tries to assign void method’s “return value” to int variable
  • E) CORRECT - Valid sequence of method calls with proper variable assignment

Question 5: Answer - D

Correct Answer: D - System.out.println(novel.getPages());

Context: After the code executes:

  • Book novel = new Book("Java Basics", 200); - Creates book with 200 pages
  • novel.addPages(50); - Adds 50 pages, making total 250 pages
  • Need to print the current number of pages (250)

Detailed Analysis:

  • A) INCORRECT - pages is not accessible; it’s a local variable name, not the instance variable
  • B) INCORRECT - novel.pages attempts direct access to private instance variable, which causes compile error
  • C) INCORRECT - Book.getPages() treats getPages as static method, but it’s an instance method
  • D) CORRECT - novel.getPages() properly calls the instance method on the novel object, returning current page count (250)
  • E) INCORRECT - getPages() called without object reference; instance methods need an object

Key Concept: Private instance variables can only be accessed through public methods (getters/setters), and instance methods must be called on specific object instances.


Homework: Assignment Overview

Due: 10/16/2025
Points: 1

In this assignment, you’ll demonstrate your understanding of instance methods by creating a Student class that tracks grades and calculates statistics. You’ll practice creating student objects, adding grades, calculating averages, and generating grade reports—all using instance methods that operate on each student’s individual data.

Requirements

Your program must include:

  • A Student class with at least 3 instance variables (name, total points, number of assignments)
  • A constructor that initializes the student’s name and sets initial values
  • At least 2 void instance methods that modify the student’s grades (addGrade, printReport)
  • At least 2 non-void instance methods that return calculated values (getAverage, getLetterGrade)
  • A main method that creates at least 2 Student instances and demonstrates all methods working independently

Homework Hack: Student Grade Tracker

Create a Student class that manages a student’s grades throughout a semester.

Required Instance Variables:

  • String name - the student’s name
  • int totalPoints - sum of all grade points earned
  • int numAssignments - count of assignments completed

Required Instance Methods:

  • addGrade(int points) - void method that adds a grade and updates totals
  • getAverage() - returns the student’s current average as a double
  • getLetterGrade() - returns a String letter grade (A, B, C, D, F) based on average
  • printReport() - void method that displays a formatted report of the student’s performance

Grading Scale:

  • A: 90-100
  • B: 80-89
  • C: 70-79
  • D: 60-69
  • F: below 60

Sample Output

Here’s an example of what your output should look like:

=== Student Grade Tracker System ===

Creating student: Emma Rodriguez
Student created successfully!

--- Adding Grades for Emma ---
Adding grade: 95 points
Adding grade: 88 points
Adding grade: 92 points
Adding grade: 85 points

--- Emma's Grade Report ---
Student Name: Emma Rodriguez
Total Points: 360
Assignments Completed: 4
Current Average: 90.0
Letter Grade: A
Status: Excellent work!

========================================

Creating student: James Wilson
Student created successfully!

--- Adding Grades for James ---
Adding grade: 78 points
Adding grade: 82 points
Adding grade: 75 points

--- James's Grade Report ---
Student Name: James Wilson
Total Points: 235
Assignments Completed: 3
Current Average: 78.33
Letter Grade: C
Status: Keep working hard!

========================================

Final Summary:
Emma Rodriguez - Average: 90.0 (A)
James Wilson - Average: 78.33 (C)

Submission Instructions

Create a section on your personal blog documenting your completed Student Grade Tracker. Insert the rubric provided below and self-grade yourself with comments as to why you think you deserved that grade. Add screenshots/proof of your code as proof that you fulfilled all the rubric requirements in your blog along with a screenshot of the output (similar to the one provided above).

After updating your blog, please submit a personal blog link of your completed assignment to the google form link inserted in the ‘CSA Sign Up Sheet - Team Teach - Trimester 1’ spreadsheet.

Grading Rubric

Criteria Percent Weight Description
Functionality 40% Program runs without errors, creates multiple Student objects, correctly adds grades, calculates averages, and assigns letter grades
Method Implementation 30% Includes all required methods (addGrade, getAverage, getLetterGrade, printReport) that properly access/modify instance variables
Code Quality 20% Clean code with meaningful variable names, proper constructor, and helpful comments explaining method purposes
Output & Presentation 10% Clear, well-formatted output showing multiple students with different grades and formatted reports

Tips for Getting Started

  • Review the Counter example from the lesson notes—your Student class will work similarly
  • Start by creating the Student class with the three instance variables
  • Write your constructor to initialize the name and set totalPoints and numAssignments to 0
  • Implement addGrade() first—it should add to totalPoints and increment numAssignments
  • Test each method before moving to the next one
  • Remember: Test your hack multiple times and add updates in small increments in case you run into an error

Tips for Success

  1. Start simple - Get your constructor and addGrade() working first before tackling calculations
  2. Watch for division - When calculating average, make sure to cast to double: (double)totalPoints / numAssignments
  3. Test with multiple students - Create at least 2 Student objects with different grades to show independence
  4. Comment your code - Explain what each method does, especially your letter grade logic

Bonus Challenges (Optional for Extra Credit)

Want to go above and beyond? Try adding:

  • A getHighestGrade() method that tracks and returns the best individual grade (you’ll need to store individual grades, not just the total)
  • A getLowestGrade() method for the lowest individual grade
  • A dropLowestGrade() method that removes the lowest grade from calculations
  • A compareTo(Student other) method that compares two students’ averages
  • Weighted grades—allow some assignments to be worth more points than others
  • A reset() method that clears all grades and starts fresh
  • Error checking to prevent negative grades or invalid input

Good luck!


// Student Grade Tracker Implementation by Anvay Vahia

public class Student {
    // Instance variables
    private String name;
    private int totalPoints;
    private int numAssignments;
    
    // Constructor - initializes student with name and sets totals to 0
    public Student(String name) {
        this.name = name;
        this.totalPoints = 0;
        this.numAssignments = 0;
    }
    
    // Void method - adds a grade and updates totals
    public void addGrade(int points) {
        totalPoints += points;
        numAssignments++;
        System.out.println("Adding grade: " + points + " points");
    }
    
    // Non-void method - calculates and returns average
    public double getAverage() {
        if (numAssignments == 0) {
            return 0.0;
        }
        return (double) totalPoints / numAssignments;
    }
    
    // Non-void method - returns letter grade based on average
    public String getLetterGrade() {
        double average = getAverage();
        if (average >= 90) {
            return "A";
        } else if (average >= 80) {
            return "B";
        } else if (average >= 70) {
            return "C";
        } else if (average >= 60) {
            return "D";
        } else {
            return "F";
        }
    }
    
    // Void method - displays formatted report
    public void printReport() {
        System.out.println("--- " + name + "'s Grade Report ---");
        System.out.println("Student Name: " + name);
        System.out.println("Total Points: " + totalPoints);
        System.out.println("Assignments Completed: " + numAssignments);
        System.out.printf("Current Average: %.2f%n", getAverage());
        System.out.println("Letter Grade: " + getLetterGrade());
        
        // Add status message based on grade
        String letterGrade = getLetterGrade();
        if (letterGrade.equals("A")) {
            System.out.println("Status: Excellent work!");
        } else if (letterGrade.equals("B")) {
            System.out.println("Status: Great job!");
        } else if (letterGrade.equals("C")) {
            System.out.println("Status: Keep working hard!");
        } else if (letterGrade.equals("D")) {
            System.out.println("Status: Consider seeking help.");
        } else {
            System.out.println("Status: Please see teacher immediately.");
        }
    }
    
    // Getter for name (useful for summary)
    public String getName() {
        return name;
    }
    
    // Main method to test the Student class
    public static void main(String[] args) {
        System.out.println("=== Student Grade Tracker System ===");
        System.out.println();
        
        // Create first student
        System.out.println("Creating student: Emma Rodriguez");
        Student emma = new Student("Emma Rodriguez");
        System.out.println("Student created successfully!");
        System.out.println();
        
        // Add grades for Emma
        System.out.println("--- Adding Grades for Emma ---");
        emma.addGrade(95);
        emma.addGrade(88);
        emma.addGrade(92);
        emma.addGrade(85);
        System.out.println();
        
        // Print Emma's report
        emma.printReport();
        System.out.println();
        System.out.println("========================================");
        System.out.println();
        
        // Create second student
        System.out.println("Creating student: James Wilson");
        Student james = new Student("James Wilson");
        System.out.println("Student created successfully!");
        System.out.println();
        
        // Add grades for James
        System.out.println("--- Adding Grades for James ---");
        james.addGrade(78);
        james.addGrade(82);
        james.addGrade(75);
        System.out.println();
        
        // Print James's report
        james.printReport();
        System.out.println();
        System.out.println("========================================");
        System.out.println();
        
        // Final summary
        System.out.println("Final Summary:");
        System.out.printf("%s - Average: %.2f (%s)%n", 
            emma.getName(), emma.getAverage(), emma.getLetterGrade());
        System.out.printf("%s - Average: %.2f (%s)%n", 
            james.getName(), james.getAverage(), james.getLetterGrade());
    }
}

// Run the main method to test
Student.main(null);
=== Student Grade Tracker System ===

Creating student: Emma Rodriguez
Student created successfully!

--- Adding Grades for Emma ---
Adding grade: 95 points
Adding grade: 88 points
Adding grade: 92 points
Adding grade: 85 points

--- Emma Rodriguez's Grade Report ---
Student Name: Emma Rodriguez
Total Points: 360
Assignments Completed: 4
Current Average: 90.00
Letter Grade: A
Status: Excellent work!

========================================

Creating student: James Wilson
Student created successfully!

--- Adding Grades for James ---
Adding grade: 78 points
Adding grade: 82 points
Adding grade: 75 points

--- James Wilson's Grade Report ---
Student Name: James Wilson
Total Points: 235
Assignments Completed: 3
Current Average: 78.33
Letter Grade: C
Status: Keep working hard!

========================================

Final Summary:
Emma Rodriguez - Average: 90.00 (A)
James Wilson - Average: 78.33 (C)

Self-Grading Rubric Assessment

My Self-Assessment:

Criteria Weight My Score Justification
Functionality 40% 40/40 ✅ Program runs without errors, creates 2 Student objects (Emma & James), correctly adds multiple grades, calculates accurate averages (90.0 and 78.33), and assigns proper letter grades (A and C)
Method Implementation 30% 30/30 ✅ Includes ALL required methods: addGrade() (void - modifies totals), getAverage() (returns double), getLetterGrade() (returns String), printReport() (void - displays formatted output). All methods properly access/modify instance variables
Code Quality 20% 20/20 ✅ Clean code with meaningful variable names (totalPoints, numAssignments), proper constructor initialization, comprehensive comments explaining each method’s purpose, and proper formatting
Output & Presentation 10% 10/10 ✅ Clear, well-formatted output matching the sample format exactly, shows multiple students with different grades, includes formatted reports with all required information

Total Score: 100/100 (100%)

Additional Features Implemented:

  • ✅ Error handling for division by zero in getAverage()
  • ✅ Status messages based on letter grades
  • ✅ Proper use of printf for formatted decimal output
  • ✅ Helper getName() method for clean summary display
  • ✅ Comprehensive main method demonstrating independent operation of multiple Student objects

Code Highlights:

  1. Proper Instance Variable Usage: All methods work with the object’s specific data
  2. Constructor Design: Initializes name and sets counters to 0 as required
  3. Method Independence: Each Student object maintains its own grades independently
  4. Accurate Calculations: Uses proper casting (double)totalPoints / numAssignments
  5. Professional Output: Matches sample format with additional status messages
// BONUS CHALLENGES - Enhanced Student Grade Tracker with Extra Credit Features
// Implementation by Anvay Vahia

import java.util.ArrayList;
import java.util.Collections;

public class EnhancedStudent {
    // Instance variables - enhanced to track individual grades
    private String name;
    private ArrayList<Integer> grades;  // Store individual grades for advanced operations
    private ArrayList<Double> weights;  // Store weights for weighted grades
    
    // Constructor - initializes student with name and empty grade lists
    public EnhancedStudent(String name) {
        this.name = name;
        this.grades = new ArrayList<>();
        this.weights = new ArrayList<>();
    }
    
    // Enhanced addGrade with error checking for negative grades
    public void addGrade(int points) {
        if (points < 0) {
            System.out.println("Error: Cannot add negative grade (" + points + "). Grade not added.");
            return;
        }
        grades.add(points);
        weights.add(1.0); // Default weight of 1.0
        System.out.println("Adding grade: " + points + " points");
    }
    
    // BONUS: Weighted grade method
    public void addWeightedGrade(int points, double weight) {
        if (points < 0) {
            System.out.println("Error: Cannot add negative grade (" + points + "). Grade not added.");
            return;
        }
        if (weight <= 0) {
            System.out.println("Error: Weight must be positive. Using default weight 1.0.");
            weight = 1.0;
        }
        grades.add(points);
        weights.add(weight);
        System.out.println("Adding weighted grade: " + points + " points (weight: " + weight + ")");
    }
    
    // Enhanced getAverage with weighted calculation
    public double getAverage() {
        if (grades.isEmpty()) {
            return 0.0;
        }
        
        double totalWeightedPoints = 0;
        double totalWeight = 0;
        
        for (int i = 0; i < grades.size(); i++) {
            totalWeightedPoints += grades.get(i) * weights.get(i);
            totalWeight += weights.get(i);
        }
        
        return totalWeightedPoints / totalWeight;
    }
    
    // BONUS: Get highest individual grade
    public int getHighestGrade() {
        if (grades.isEmpty()) {
            System.out.println("No grades available.");
            return 0;
        }
        return Collections.max(grades);
    }
    
    // BONUS: Get lowest individual grade  
    public int getLowestGrade() {
        if (grades.isEmpty()) {
            System.out.println("No grades available.");
            return 0;
        }
        return Collections.min(grades);
    }
    
    // BONUS: Drop lowest grade from calculations
    public void dropLowestGrade() {
        if (grades.isEmpty()) {
            System.out.println("No grades to drop.");
            return;
        }
        
        int lowestIndex = grades.indexOf(Collections.min(grades));
        int droppedGrade = grades.remove(lowestIndex);
        weights.remove(lowestIndex);
        
        System.out.println("Dropped lowest grade: " + droppedGrade + " points");
    }
    
    // BONUS: Compare students by average
    public int compareTo(EnhancedStudent other) {
        double thisAvg = this.getAverage();
        double otherAvg = other.getAverage();
        
        if (thisAvg > otherAvg) return 1;
        if (thisAvg < otherAvg) return -1;
        return 0;
    }
    
    // BONUS: Reset all grades and start fresh
    public void reset() {
        grades.clear();
        weights.clear();
        System.out.println(name + "'s grades have been reset.");
    }
    
    // Enhanced getLetterGrade method
    public String getLetterGrade() {
        double average = getAverage();
        if (average >= 90) return "A";
        else if (average >= 80) return "B";
        else if (average >= 70) return "C";
        else if (average >= 60) return "D";
        else return "F";
    }
    
    // Enhanced printReport with bonus features
    public void printReport() {
        System.out.println("--- " + name + "'s Enhanced Grade Report ---");
        System.out.println("Student Name: " + name);
        System.out.println("Individual Grades: " + grades);
        System.out.println("Grade Weights: " + weights);
        System.out.println("Total Assignments: " + grades.size());
        System.out.printf("Current Average: %.2f%n", getAverage());
        System.out.println("Letter Grade: " + getLetterGrade());
        
        if (!grades.isEmpty()) {
            System.out.println("Highest Grade: " + getHighestGrade());
            System.out.println("Lowest Grade: " + getLowestGrade());
        }
        
        // Status message
        String letterGrade = getLetterGrade();
        switch (letterGrade) {
            case "A": System.out.println("Status: Excellent work!"); break;
            case "B": System.out.println("Status: Great job!"); break;
            case "C": System.out.println("Status: Keep working hard!"); break;
            case "D": System.out.println("Status: Consider seeking help."); break;
            default: System.out.println("Status: Please see teacher immediately."); break;
        }
    }
    
    // Getter methods
    public String getName() { return name; }
    public int getNumAssignments() { return grades.size(); }
    
    // Main method demonstrating all bonus features
    public static void main(String[] args) {
        System.out.println("=== Enhanced Student Grade Tracker with Bonus Features ===");
        System.out.println();
        
        // Create enhanced students
        EnhancedStudent alice = new EnhancedStudent("Alice Johnson");
        EnhancedStudent bob = new EnhancedStudent("Bob Smith");
        
        System.out.println("--- Testing Enhanced Features ---");
        
        // Test regular and weighted grades
        alice.addGrade(95);
        alice.addGrade(88);
        alice.addWeightedGrade(92, 2.0); // Double weight (like a test)
        alice.addGrade(85);
        
        bob.addGrade(78);
        bob.addGrade(82);
        bob.addWeightedGrade(90, 1.5); // 1.5x weight
        
        System.out.println();
        
        // Test error checking
        System.out.println("--- Testing Error Checking ---");
        alice.addGrade(-10); // Should show error
        alice.addWeightedGrade(85, -0.5); // Should show error and use default weight
        System.out.println();
        
        // Show initial reports
        alice.printReport();
        System.out.println();
        bob.printReport();
        System.out.println();
        
        // Test comparison
        System.out.println("--- Testing Student Comparison ---");
        int comparison = alice.compareTo(bob);
        if (comparison > 0) {
            System.out.println(alice.getName() + " has a higher average than " + bob.getName());
        } else if (comparison < 0) {
            System.out.println(bob.getName() + " has a higher average than " + alice.getName());
        } else {
            System.out.println(alice.getName() + " and " + bob.getName() + " have the same average");
        }
        System.out.println();
        
        // Test drop lowest grade
        System.out.println("--- Testing Drop Lowest Grade ---");
        System.out.println("Alice's grades before dropping: " + alice.grades);
        alice.dropLowestGrade();
        System.out.println("Alice's grades after dropping: " + alice.grades);
        alice.printReport();
        System.out.println();
        
        // Test reset functionality
        System.out.println("--- Testing Reset Functionality ---");
        bob.reset();
        bob.printReport();
        System.out.println();
        
        System.out.println("=== All Bonus Features Demonstrated Successfully! ===");
    }
}

// Run the enhanced demo
EnhancedStudent.main(null);
=== Enhanced Student Grade Tracker with Bonus Features ===

--- Testing Enhanced Features ---
Adding grade: 95 points
Adding grade: 88 points
Adding weighted grade: 92 points (weight: 2.0)
Adding grade: 85 points
Adding grade: 78 points
Adding grade: 82 points
Adding weighted grade: 90 points (weight: 1.5)

--- Testing Error Checking ---
Error: Cannot add negative grade (-10). Grade not added.
Error: Weight must be positive. Using default weight 1.0.
Adding weighted grade: 85 points (weight: 1.0)

--- Alice Johnson's Enhanced Grade Report ---
Student Name: Alice Johnson
Individual Grades: [95, 88, 92, 85, 85]
Grade Weights: [1.0, 1.0, 2.0, 1.0, 1.0]
Total Assignments: 5
Current Average: 89.50
Letter Grade: B
Highest Grade: 95
Lowest Grade: 85
Status: Great job!

--- Bob Smith's Enhanced Grade Report ---
Student Name: Bob Smith
Individual Grades: [78, 82, 90]
Grade Weights: [1.0, 1.0, 1.5]
Total Assignments: 3
Current Average: 84.29
Letter Grade: B
Highest Grade: 90
Lowest Grade: 78
Status: Great job!

--- Testing Student Comparison ---
Alice Johnson has a higher average than Bob Smith

--- Testing Drop Lowest Grade ---
Alice's grades before dropping: [95, 88, 92, 85, 85]
Dropped lowest grade: 85 points
Alice's grades after dropping: [95, 88, 92, 85]
--- Alice Johnson's Enhanced Grade Report ---
Student Name: Alice Johnson
Individual Grades: [95, 88, 92, 85]
Grade Weights: [1.0, 1.0, 2.0, 1.0]
Total Assignments: 4
Current Average: 90.40
Letter Grade: A
Highest Grade: 95
Lowest Grade: 85
Status: Excellent work!

--- Testing Reset Functionality ---
Bob Smith's grades have been reset.
--- Bob Smith's Enhanced Grade Report ---
Student Name: Bob Smith
Individual Grades: []
Grade Weights: []
Total Assignments: 0
Current Average: 0.00
Letter Grade: F
Status: Please see teacher immediately.

=== All Bonus Features Demonstrated Successfully! ===