From 0151b08dc1e6bc8a23ae1af9dff81b41b3b9a5a6 Mon Sep 17 00:00:00 2001 From: Sequoyah Descoteaux Date: Fri, 18 Oct 2024 19:58:57 +0200 Subject: [PATCH 01/33] Updated Gemfile.lock after running bundle install --- Gemfile.lock | 1 + 1 file changed, 1 insertion(+) diff --git a/Gemfile.lock b/Gemfile.lock index d273a79f9..6def29197 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -29,6 +29,7 @@ GEM PLATFORMS arm64-darwin-20 arm64-darwin-21 + arm64-darwin-24 DEPENDENCIES faraday From bf9eeeb4a65c04e443f22fbb1ddbc6d269bf2c1f Mon Sep 17 00:00:00 2001 From: Sequoyah Descoteaux Date: Fri, 18 Oct 2024 19:59:37 +0200 Subject: [PATCH 02/33] Added documentation for Iteration 1: Exploring the existing codebase, test failures, and debugging process. --- Iteration_1.md | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 Iteration_1.md diff --git a/Iteration_1.md b/Iteration_1.md new file mode 100644 index 000000000..b2652a339 --- /dev/null +++ b/Iteration_1.md @@ -0,0 +1,26 @@ +# Iteration 1 - Learning the Existing Codebase + +## Overview +In this iteration, we explored the existing codebase and familiarized ourselves with the classes, methods, and tests already in place. The goal was to identify any bugs in the application code and debug the project until all tests passed. + +## Test Failures and Fixes +1. Test: [Description of test] + - **Failure Reason**: [Explanation of why it failed] + - **Fix**: [Description of how the issue was resolved] + +## Successes +- Successfully explored and understood the relationships between `Facility`, `Dmv`, and `Vehicle` classes. +- All existing tests pass after resolving bugs in the application code. + +## Application Logic +- The `Dmv` class handles facilities and their services. +- The `Vehicle` class defines vehicle properties and implements methods such as `antique?` and `electric_vehicle?`. + +## TDD Process +- Refactored code in small steps, ensuring tests passed after each refactor. +- Used test failures to guide debugging. + +## Reflection +- **Steps to Explore Codebase**: [What you did to understand the code]. +- **Challenges**: [What was difficult about working with unfamiliar code]. +- **What was Easier**: [What was easier than expected]. \ No newline at end of file From 26ae2344b39a806e2af92c2d4a751600370cdf16 Mon Sep 17 00:00:00 2001 From: Sequoyah Descoteaux Date: Fri, 18 Oct 2024 19:59:46 +0200 Subject: [PATCH 03/33] Added documentation for Iteration 2: Created Registrant class and detailed the TDD process and object-oriented design enhancements. --- Iteration_2.md | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 Iteration_2.md diff --git a/Iteration_2.md b/Iteration_2.md new file mode 100644 index 000000000..e69de29bb From 40dbe33cc90ef146194bef77d48faf2a00cdc3f9 Mon Sep 17 00:00:00 2001 From: Sequoyah Descoteaux Date: Fri, 18 Oct 2024 19:59:53 +0200 Subject: [PATCH 04/33] Added documentation for Iteration 3: Implemented missing functionality and described the feature development process. --- Iteration_3.md | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 Iteration_3.md diff --git a/Iteration_3.md b/Iteration_3.md new file mode 100644 index 000000000..e69de29bb From f76f1ae53bc7754bd24ee96563b7b8d0190a3c5e Mon Sep 17 00:00:00 2001 From: Sequoyah Descoteaux Date: Fri, 18 Oct 2024 20:00:24 +0200 Subject: [PATCH 05/33] Added documentation for Iteration 2: Created Registrant class and detailed the TDD process and object-oriented design enhancements. --- Iteration_2.md | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/Iteration_2.md b/Iteration_2.md index e69de29bb..b026838cb 100644 --- a/Iteration_2.md +++ b/Iteration_2.md @@ -0,0 +1,22 @@ +# Iteration 2 - Object-Oriented Design Enhancement + +## Overview +This iteration focused on improving the object-oriented design by adding the `Registrant` class. We also established relationships between classes using OOP principles. + +## New Classes and Methods +- Created `Registrant` class to manage user data such as name, age, permit status, and license data. +- Added `earn_permit` method to change a registrant’s permit status. + +## Test Failures and Fixes +1. Test: [Description of test for `Registrant` class] + - **Failure Reason**: [Explanation of why it failed] + - **Fix**: [Description of how the issue was resolved] + +## TDD Process +- Started with tests for `Registrant` and gradually built the class to meet requirements. +- Used interaction patterns to guide method design. + +## Reflection +- **Steps to Add Classes**: [What was the process for adding new classes]. +- **Challenges**: [What was difficult]. +- **What was Easier**: [What was easier]. \ No newline at end of file From a3487f3f57345b7b8c595c969209b0c5ddb1a6e5 Mon Sep 17 00:00:00 2001 From: Sequoyah Descoteaux Date: Fri, 18 Oct 2024 20:02:20 +0200 Subject: [PATCH 06/33] Added documentation for Iteration 3: Implemented missing functionality and described the feature development process. --- Iteration_3.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/Iteration_3.md b/Iteration_3.md index e69de29bb..56fa7146f 100644 --- a/Iteration_3.md +++ b/Iteration_3.md @@ -0,0 +1,18 @@ +# Iteration 3 - Implementing Missing Functionality + +## Overview +In this iteration, the focus was on completing the missing functionality from the project. New features were added to improve the system's capabilities. + +## New Features Implemented +- [Feature 1] +- [Feature 2] + +## Test Failures and Fixes +- No major test failures encountered during this iteration. + +## TDD Process +- Followed TDD by writing tests for new features first, then implementing the functionality. + +## Reflection +- **Challenges**: [What was challenging about building the new functionality]. +- **Successes**: [What worked well]. \ No newline at end of file From efeb4e559ca4b15b10526c850876350957d28e24 Mon Sep 17 00:00:00 2001 From: Sequoyah Descoteaux Date: Fri, 18 Oct 2024 20:03:56 +0200 Subject: [PATCH 07/33] Added documentation for Iteration 4: Final refactoring and testing results, along with reflections on the project. --- Iteration_4.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 Iteration_4.md diff --git a/Iteration_4.md b/Iteration_4.md new file mode 100644 index 000000000..10b217359 --- /dev/null +++ b/Iteration_4.md @@ -0,0 +1,14 @@ +# Iteration 4 - Refactoring and Final Testing + +## Overview +This iteration was about optimizing the project, refactoring the code for better clarity and performance, and ensuring all tests passed. + +## Refactoring Details +- Refactored [method/class] to improve readability and performance. + +## Final Test Results +- All tests pass successfully, confirming that the system works as expected. + +## Reflection +- **Challenges in Refactoring**: [What challenges did you encounter?] +- **Final Thoughts on Project**: [Overall experience and lessons learned]. \ No newline at end of file From 3e8a4b64770c0bb79e0f0c02c785d0a902fbf7da Mon Sep 17 00:00:00 2001 From: Sequoyah Descoteaux Date: Fri, 18 Oct 2024 20:06:35 +0200 Subject: [PATCH 08/33] Detailed message describing all changes --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 9056d23f4..f367692e2 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,4 @@ # The DMV -This is the starter repo for the BE Mod1 DMV project. +Repo for the SE Mod1 DMV project. +By Qoiree From 4d0f93dca8a91a9c848987b098189fa076cda1f8 Mon Sep 17 00:00:00 2001 From: Sequoyah Descoteaux Date: Fri, 18 Oct 2024 20:31:32 +0200 Subject: [PATCH 09/33] Ran initial tests, identifying failing tests in the existing codebase. --- spec/spec_helper.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 928255386..6ff6f53c2 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -2,4 +2,4 @@ require './lib/dmv' require './lib/facility' require './lib/vehicle' -require './lib/dmv_data_service' +require './lib/dmv_data_service' \ No newline at end of file From b1cccd86a6a942080b5bc0cce2243d3879468db3 Mon Sep 17 00:00:00 2001 From: Sequoyah Descoteaux Date: Fri, 18 Oct 2024 20:52:22 +0200 Subject: [PATCH 10/33] Updated the Iteration_1.md to reflect my step by TDD process --- Iteration_1.md | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/Iteration_1.md b/Iteration_1.md index b2652a339..858a3f731 100644 --- a/Iteration_1.md +++ b/Iteration_1.md @@ -19,7 +19,40 @@ In this iteration, we explored the existing codebase and familiarized ourselves ## TDD Process - Refactored code in small steps, ensuring tests passed after each refactor. - Used test failures to guide debugging. +#### Test 1: Facility Initialization +- Test is tring to intilalize the Facility class with a hash, the class expects three separate arguement (name, address, phone). +### Step 1: Analyze the Current Code +#### **Facility Class:** +- The initialize method expects three separate arguments (name, address, phone), but your test is passing a **hash** instead. +#### **facility_spec.rb:** +- Here, the test is passing a hash with keys (name, address, phone) to the Facility.new method, which is inconsistent with the initialize method. +### Step 2: Write the Correct Initialization (TDD Process) +#### Fix: + - I need to modify the initialize method in the Facility class to accept a hash instead of individual arguments. + ##### Modify the Facility Class: +```` ruby +class Facility + attr_reader :name, :address, :phone, :services + def initialize(facility_details) + @name = facility_details[:name] + @address = facility_details[:address] + @phone = facility_details[:phone] + @services = [] + end + + def add_services(service) + @services << service + end +end +```` +#### Key Notes: +- This change allows the initialize method to accept a hash and extract name, address, and phone from the hash, aligning with the way it’s being called in the test file. +### Step 3: Update the add_service Method + +### Step 4: Rerun the Tests + +### Step 5: Commit Changes ## Reflection - **Steps to Explore Codebase**: [What you did to understand the code]. - **Challenges**: [What was difficult about working with unfamiliar code]. From 3d2fcf91751d27ae32218603bc0ddbffa810818a Mon Sep 17 00:00:00 2001 From: Sequoyah Descoteaux Date: Fri, 18 Oct 2024 20:57:06 +0200 Subject: [PATCH 11/33] Fix Facility class to allow the initalize method to accept the hash and exact facility details --- lib/facility.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/facility.rb b/lib/facility.rb index a65757687..752491600 100644 --- a/lib/facility.rb +++ b/lib/facility.rb @@ -1,10 +1,10 @@ class Facility attr_reader :name, :address, :phone, :services - def initialize(name, address, phone) - @name = name - @address = address - @phone = phone + def initialize(facility_details) + @name = facility_details[:name] + @address = facility_details[:address] + @phone = facility_details [:phone] @services = [] end From 1b8b77dbe981866771480a9ee8f54020dcf23bd7 Mon Sep 17 00:00:00 2001 From: Sequoyah Descoteaux Date: Fri, 18 Oct 2024 21:02:21 +0200 Subject: [PATCH 12/33] Fixed Facility class to accept hash for initialization and corrected add_service method --- lib/facility.rb | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/lib/facility.rb b/lib/facility.rb index 752491600..0b9da34a5 100644 --- a/lib/facility.rb +++ b/lib/facility.rb @@ -1,14 +1,22 @@ class Facility + # This line defines getter methods for name, address, phone, and services. + # These attributes can be accessed outside the class but can't be modified directly. attr_reader :name, :address, :phone, :services + # The initialize method is the constructor for the Facility class. + # It takes a hash (facility_details) as an argument which contains the name, address, and phone. + # We extract these values from the hash and assign them to instance variables. + # An empty array is initialized for @services to hold the services provided by this facility. def initialize(facility_details) - @name = facility_details[:name] - @address = facility_details[:address] - @phone = facility_details [:phone] - @services = [] + @name = facility_details[:name] # Extract the name from the facility_details hash + @address = facility_details[:address] # Extract the address from the facility_details hash + @phone = facility_details[:phone] # Extract the phone number from the facility_details hash + @services = [] # Initialize an empty array to store the services offered by this facility end - def add_services(service) - @services << service + # This method allows the facility to add a service to its list of services. + # The service is passed as an argument and added to the @services array. + def add_service(service) + @services << service # Add the provided service to the @services array end -end +end \ No newline at end of file From 65afa1efa392a23cc7d05575e8754a88d256a4f1 Mon Sep 17 00:00:00 2001 From: Sequoyah Descoteaux Date: Fri, 18 Oct 2024 22:19:11 +0200 Subject: [PATCH 13/33] Added detailed comments to Dmv class and fixed facilities access --- lib/dmv.rb | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/lib/dmv.rb b/lib/dmv.rb index f9e59bdf3..8609f003b 100644 --- a/lib/dmv.rb +++ b/lib/dmv.rb @@ -1,16 +1,23 @@ class Dmv + # This creates a getter method for the facilities attribute, + # allowing the list of facilities to be accessed from outside the class + # but not modified directly. This ensures data encapsulation. + attr_reader :facilities + # The initialize method is the constructor for the Dmv class. + # It is called when a new instance of Dmv is created. + # It initializes an empty array for @facilities, which will later + # store the list of facilities managed by the Dmv. def initialize - @facilities = [] + @facilities = [] # Initializes an empty array to hold facilities. end + # This method allows a facility to be added to the list of facilities. + # The facility is passed as an argument and appended to the @facilities array. + # This method ensures that the Dmv object can dynamically manage multiple facilities. + # + # @param facility [Object] the facility object that will be added to the @facilities array. def add_facility(facility) - @facilities << facility + @facilities << facility # Adds the provided facility to the @facilities array. end - - def facilities_offering_service(service) - @facilities.find do |facility| - facility.services.include?(service) - end - end -end +end \ No newline at end of file From 263a48491e9ddc1526194eacd7e25348dc2c1f13 Mon Sep 17 00:00:00 2001 From: Sequoyah Descoteaux Date: Fri, 18 Oct 2024 22:36:03 +0200 Subject: [PATCH 14/33] Added detailed comments to Dmv class and fixed facilities access --- lib/dmv.rb | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/lib/dmv.rb b/lib/dmv.rb index 8609f003b..143d351cd 100644 --- a/lib/dmv.rb +++ b/lib/dmv.rb @@ -1,23 +1,23 @@ class Dmv - # This creates a getter method for the facilities attribute, - # allowing the list of facilities to be accessed from outside the class - # but not modified directly. This ensures data encapsulation. - attr_reader :facilities + attr_reader :facilities # Getter method for facilities - # The initialize method is the constructor for the Dmv class. - # It is called when a new instance of Dmv is created. - # It initializes an empty array for @facilities, which will later - # store the list of facilities managed by the Dmv. def initialize - @facilities = [] # Initializes an empty array to hold facilities. + @facilities = [] # Initialize an empty array for storing facilities end - # This method allows a facility to be added to the list of facilities. - # The facility is passed as an argument and appended to the @facilities array. - # This method ensures that the Dmv object can dynamically manage multiple facilities. - # - # @param facility [Object] the facility object that will be added to the @facilities array. + # This method adds a facility to the @facilities array def add_facility(facility) - @facilities << facility # Adds the provided facility to the @facilities array. + @facilities << facility # Add the given facility to the @facilities array + end + + # This method returns a list of facilities that offer the specified service. + # It iterates over the @facilities array and selects facilities that include the requested service. + # + # @param service [String] the name of the service to search for in the facilities. + # @return [Array] an array of facilities that offer the specified service. + def facilities_offering_service(service) + @facilities.select do |facility| + facility.services.include?(service) # Check if the facility offers the specified service + end end end \ No newline at end of file From 48ea7846284e6d8df2012b2ecf67ddac0a36a9b8 Mon Sep 17 00:00:00 2001 From: Sequoyah Descoteaux Date: Fri, 18 Oct 2024 22:53:00 +0200 Subject: [PATCH 15/33] Added registration_date attribute to Vehicle class and updated tests --- lib/vehicle.rb | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/lib/vehicle.rb b/lib/vehicle.rb index 49ae83672..540b8ed33 100644 --- a/lib/vehicle.rb +++ b/lib/vehicle.rb @@ -1,25 +1,25 @@ -require 'date' - class Vehicle - attr_reader :vin, - :year, - :make, - :model, - :engine + # These attributes are readable from outside the class. + attr_reader :vin, :year, :make, :model, :engine, :registration_date + # The initialize method takes a hash of vehicle details and assigns them to instance variables. + # It also initializes @registration_date to nil, indicating the vehicle is not yet registered. def initialize(vehicle_details) - @vin = vehicle_details[:vin] - @year = vehicle_details[:year] - @make = vehicle_details[:make] - @model = vehicle_details[:model] - @engine = vehicle_details[:engine] + @vin = vehicle_details[:vin] # Vehicle Identification Number + @year = vehicle_details[:year] # Year of manufacture + @make = vehicle_details[:make] # Vehicle's make (e.g., Chevrolet) + @model = vehicle_details[:model] # Vehicle's model (e.g., Cruz) + @engine = vehicle_details[:engine] # Type of engine (e.g., :ice for internal combustion engine) + @registration_date = nil # Initially, the vehicle is unregistered, so set to nil end + # This method determines if the vehicle is considered an antique, which is true if the car is older than 25 years. def antique? Date.today.year - @year > 25 end + # This method checks if the vehicle is an electric vehicle (EV) by comparing the engine type. def electric_vehicle? @engine == :ev end -end +end \ No newline at end of file From a8725f294e01b19fce769c990c21c4d734eecd32 Mon Sep 17 00:00:00 2001 From: Sequoyah Descoteaux Date: Fri, 18 Oct 2024 23:36:52 +0200 Subject: [PATCH 16/33] Completed initial_debugging --- Iteration_1.md | 57 ++------- Iteration_2.md | 4 +- Iteration_3.md | 6 +- initial_debugging.md | 232 ++++++++++++++++++++++++++++++++++ lib/registrant.rb | 21 +++ spec/dmv_data_service_spec.rb | 6 +- spec/registrant_spec.rb | 31 +++++ spec/spec_helper.rb | 3 +- 8 files changed, 310 insertions(+), 50 deletions(-) create mode 100644 initial_debugging.md create mode 100644 lib/registrant.rb create mode 100644 spec/registrant_spec.rb diff --git a/Iteration_1.md b/Iteration_1.md index 858a3f731..da6932967 100644 --- a/Iteration_1.md +++ b/Iteration_1.md @@ -4,55 +4,24 @@ In this iteration, we explored the existing codebase and familiarized ourselves with the classes, methods, and tests already in place. The goal was to identify any bugs in the application code and debug the project until all tests passed. ## Test Failures and Fixes -1. Test: [Description of test] - - **Failure Reason**: [Explanation of why it failed] - - **Fix**: [Description of how the issue was resolved] - -## Successes -- Successfully explored and understood the relationships between `Facility`, `Dmv`, and `Vehicle` classes. -- All existing tests pass after resolving bugs in the application code. -## Application Logic -- The `Dmv` class handles facilities and their services. -- The `Vehicle` class defines vehicle properties and implements methods such as `antique?` and `electric_vehicle?`. +### 1. Test: Facility#initialize can initialize +- **Failure Reason**: The `Facility` class was expecting three separate arguments (`name`, `address`, `phone`), but the test was passing a hash. +- **Fix**: Updated the `Facility` class to accept a hash (`facility_details`) and extract the `name`, `address`, and `phone` keys from it. This aligns with the way the test is structured. + +### 2. Test: Facility#add service can add available services +- **Failure Reason**: The `add_service` method name in the class was pluralized (`add_services`), but the test was calling it in singular form. +- **Fix**: Changed the method name from `add_services` to `add_service` to align with the test. -## TDD Process -- Refactored code in small steps, ensuring tests passed after each refactor. -- Used test failures to guide debugging. -#### Test 1: Facility Initialization -- Test is tring to intilalize the Facility class with a hash, the class expects three separate arguement (name, address, phone). -### Step 1: Analyze the Current Code -#### **Facility Class:** -- The initialize method expects three separate arguments (name, address, phone), but your test is passing a **hash** instead. -#### **facility_spec.rb:** -- Here, the test is passing a hash with keys (name, address, phone) to the Facility.new method, which is inconsistent with the initialize method. -### Step 2: Write the Correct Initialization (TDD Process) -#### Fix: - - I need to modify the initialize method in the Facility class to accept a hash instead of individual arguments. - ##### Modify the Facility Class: -```` ruby -class Facility - attr_reader :name, :address, :phone, :services +### 3. Test: Dmv#initialize can initialize +- **Failure Reason**: The `@facilities` instance variable was being initialized correctly, but there was no getter method (`facilities`) to access it in the test. +- **Fix**: Added `attr_reader :facilities` to provide access to the `@facilities` array. This allowed the test to properly access and verify the initialized empty array. - def initialize(facility_details) - @name = facility_details[:name] - @address = facility_details[:address] - @phone = facility_details[:phone] - @services = [] - end +### 4. Test: Dmv#add facilities can add available facilities +- **Failure Reason**: The method was working but not accessible without a getter method. +- **Fix**: After adding `attr_reader`, the facilities array could be accessed and validated. - def add_services(service) - @services << service - end -end -```` -#### Key Notes: -- This change allows the initialize method to accept a hash and extract name, address, and phone from the hash, aligning with the way it’s being called in the test file. -### Step 3: Update the add_service Method -### Step 4: Rerun the Tests - -### Step 5: Commit Changes ## Reflection - **Steps to Explore Codebase**: [What you did to understand the code]. - **Challenges**: [What was difficult about working with unfamiliar code]. diff --git a/Iteration_2.md b/Iteration_2.md index b026838cb..a9dd4c976 100644 --- a/Iteration_2.md +++ b/Iteration_2.md @@ -19,4 +19,6 @@ This iteration focused on improving the object-oriented design by adding the `Re ## Reflection - **Steps to Add Classes**: [What was the process for adding new classes]. - **Challenges**: [What was difficult]. -- **What was Easier**: [What was easier]. \ No newline at end of file +- **What was Easier**: [What was easier]. + + diff --git a/Iteration_3.md b/Iteration_3.md index 56fa7146f..0a94a357f 100644 --- a/Iteration_3.md +++ b/Iteration_3.md @@ -15,4 +15,8 @@ In this iteration, the focus was on completing the missing functionality from th ## Reflection - **Challenges**: [What was challenging about building the new functionality]. -- **Successes**: [What worked well]. \ No newline at end of file +- **Successes**: [What worked well]. + + +# DMVdata will come as potentially 1,000 arrays. +#### The challenge here is to organize the data. Assign arrays to class objects \ No newline at end of file diff --git a/initial_debugging.md b/initial_debugging.md new file mode 100644 index 000000000..5fc3e8d07 --- /dev/null +++ b/initial_debugging.md @@ -0,0 +1,232 @@ +## Test Failures and Fixes + +### 1. Test: Facility#initialize can initialize +- **Failure Reason**: The `Facility` class was expecting three separate arguments (`name`, `address`, `phone`), but the test was passing a hash. +- **Fix**: Updated the `Facility` class to accept a hash (`facility_details`) and extract the `name`, `address`, and `phone` keys from it. This aligns with the way the test is structured. + +### 2. Test: Facility#add service can add available services +- **Failure Reason**: The `add_service` method name in the class was pluralized (`add_services`), but the test was calling it in singular form. +- **Fix**: Changed the method name from `add_services` to `add_service` to align with the test. + +## Successes +- Successfully explored and understood the relationships between `Facility`, `Dmv`, and `Vehicle` classes. +- All existing tests pass after resolving bugs in the application code. + +## Application Logic +- The `Dmv` class handles facilities and their services. +- The `Vehicle` class defines vehicle properties and implements methods such as `antique?` and `electric_vehicle?`. + +# TDD Process +- Refactored code in small steps, ensuring tests passed after each refactor. +- Used test failures to guide debugging. +## Error 1: +```` ruby +ArgumentError: wrong number of arguments (given 1, expected 3) +```` +### Test 1: Facility Initialization +- Test is tring to intilalize the Facility class with a hash, the class expects three separate arguement (name, address, phone). +#### Step 1: Analyze the Current Code +#### **Facility Class:** +- The initialize method expects three separate arguments (name, address, phone), but your test is passing a **hash** instead. +#### **facility_spec.rb:** +- Here, the test is passing a hash with keys (name, address, phone) to the Facility.new method, which is inconsistent with the initialize method. +#### Step 2: Write the Correct Initialization (TDD Process) +#### Fix: + - I need to modify the initialize method in the Facility class to accept a hash instead of individual arguments. + ##### Modify the Facility Class: +```` ruby +class Facility + attr_reader :name, :address, :phone, :services + + def initialize(facility_details) + @name = facility_details[:name] + @address = facility_details[:address] + @phone = facility_details[:phone] + @services = [] + end + + def add_services(service) + @services << service + end +end +```` +#### Key Notes: +- This change allows the initialize method to accept a hash and extract name, address, and phone from the hash, aligning with the way it’s being called in the test file. +#### Step 3: Update the add_service Method +- There’s also a small typo in the method name. In the test, you’re calling add_service (singular), but in the Facility class, it’s named add_services (plural). +```` ruby +class Facility + attr_reader :name, :address, :phone, :services + + def initialize(facility_details) + @name = facility_details[:name] + @address = facility_details[:address] + @phone = facility_details[:phone] + @services = [] + end + + def add_service(service) + @services << service + end +end +```` +#### Step 4: Rerun the Tests +```` ruby +rspec +```` +#### Step 5: Commit Changes +- Commit changes add high-level message. + +## Error 2: +```` ruby +NoMethodError: undefined method `facilities' for # +```` +- The test is trying to call a method called facilities on an instance of the Dmv class, but the method is not defined. +### Test 1: +- Looks I am trying to access an instance variable @facilities using expect(@dmv.facilities).to eq([]). However, the Dmv class does not have a method to access @facilities. +#### Step 1: Add an accessor for @facilities: +#### ** Accessor for Facilities:** +- In order to make @facilities accessible outside the class, I need to either define an accessor method for it or use attr_reader to expose the @facilities instance variable. +#### Step 2: Write the Correct Initialization (TDD Process) +#### Fix: + ```` ruby +class Dmv + # This creates a getter method for facilities so it can be accessed outside the class + attr_reader :facilities + + def initialize + @facilities = [] # Initializes an empty array to hold facilities + end + + # This method allows adding a facility to the list + def add_facility(facility) + @facilities << facility + end +end + ```` + - Adding attr_reader :facilities, I created a getter method for @facilities, which allows the facilities method to be called on an instance of Dmv in the test. + +#### Step 3: Rerun the Tests +```` ruby +rspec +```` +#### Step 5: Commit Changes +- Commit changes add high-level message. +## Reflection +1. **attr_reader :facilities:** + - This line creates a getter method for the @facilities instance variable, allowing it to be accessed from outside the class. However, this variable cannot be directly modified from the outside (i.e., there’s no setter method), which enforces encapsulation. +2. **initialize method:** + - The initialize method is called when a new instance of the Dmv class is created. It sets up an empty array for @facilities, which will later hold the list of DMV facilities. + - This ensures that each instance of the Dmv class starts with its own unique list of facilities. +3. **add_facility method:** + - This method takes a facility object as a parameter and adds it to the @facilities array. + - This allows the Dmv class to manage a collection of facilities dynamically, which can later be retrieved using the facilities getter method. + +## Error 3: +```` ruby +NoMethodError: undefined method `facilities' for # +```` +- The test is trying to call this method to return a list of facilities that offer a specified service, but the method hasn’t been defined yet. + +### Test 1:Add facilities_offering_service in Dmv class. +- +#### Step 1: Implement method facilities_offering_service in the Dmv class +#### ** Accessor for Facilities:** +-I need to implement the facilities_offering_service method in the Dmv class. This method will iterate over the list of facilities and return only those that offer the requested service. +#### Fix: + ```` ruby +class Dmv + attr_reader :facilities # Getter method for facilities + + def initialize + @facilities = [] # Initialize an empty array for storing facilities + end + + # This method adds a facility to the @facilities array + def add_facility(facility) + @facilities << facility # Add the given facility to the @facilities array + end + + # This method returns a list of facilities that offer the specified service. + # It iterates over the @facilities array and selects facilities that include the requested service. + # + # @param service [String] the name of the service to search for in the facilities. + # @return [Array] an array of facilities that offer the specified service. + def facilities_offering_service(service) + @facilities.select do |facility| + facility.services.include?(service) # Check if the facility offers the specified service + end + end +end + ```` + +#### Step 3: Rerun the Tests +```` ruby +rspec +```` +#### Step 5: Commit Changes +- Commit changes add high-level message. +## Reflection +1. **facilities_offering_service Method:** + - This method takes a service parameter (e.g., ‘Road Test’) and checks each facility in the @facilities array to see if it offers that service. + - It uses select to iterate over the array and return a new array containing only the facilities that offer the specified service. +2. **Key Points:** + - **facility.services.include?(service):** This line checks whether the services array of each facility contains the service being searched for. + +## Error 4: +```` ruby +Failure/Error: expect(@cruz.registration_date).to eq(nil) + + NoMethodError: + undefined method `registration_date' for # + # ./spec/vehicle_spec.rb:17:in `block (3 levels) in ' + +```` +- The Vehicle class is missing the registration_date attribute, which the test is expecting to be initialized to nil. I should be able to resolve this issue by adding a registration_date attribute to the Vehicle class and ensuring it’s initialized correctly. +### Test 1: Update Vehicle Class +- Add registration_date as an instance variable and initialize it to nil in the initialize method. +- Also, add attr_reader :registration_date so that it can be accessed outside the class. +#### Step 1: Add `attr_reader` +#### **`attr_reader :registration_date`** +- This creates a getter method for the `@registration_date` instance variable, allowing it to be accessed outside the class (e.g., in the test file). +#### Step 2:Add **`registration_date = nil`** +- The initialize method sets the `@registration_date` to `nil` when a new Vehicle instance is created, as the vehicle isn’t registered initially. + +#### Fix: + ```` ruby +class Vehicle + # These attributes are readable from outside the class. + attr_reader :vin, :year, :make, :model, :engine, :registration_date + + # The initialize method takes a hash of vehicle details and assigns them to instance variables. + # It also initializes @registration_date to nil, indicating the vehicle is not yet registered. + def initialize(vehicle_details) + @vin = vehicle_details[:vin] # Vehicle Identification Number + @year = vehicle_details[:year] # Year of manufacture + @make = vehicle_details[:make] # Vehicle's make (e.g., Chevrolet) + @model = vehicle_details[:model] # Vehicle's model (e.g., Cruz) + @engine = vehicle_details[:engine] # Type of engine (e.g., :ice for internal combustion engine) + @registration_date = nil # Initially, the vehicle is unregistered, so set to nil + end + + # This method determines if the vehicle is considered an antique, which is true if the car is older than 25 years. + def antique? + Date.today.year - @year > 25 + end + + # This method checks if the vehicle is an electric vehicle (EV) by comparing the engine type. + def electric_vehicle? + @engine == :ev + end +end + ```` + - + +#### Step 3: Write the Correct Initialization (TDD Process) +#### Step 4: Rerun the Tests +```` ruby +rspec +```` +#### Step 5: Commit Changes +- Commit changes add high-level message. +## Reflection diff --git a/lib/registrant.rb b/lib/registrant.rb new file mode 100644 index 000000000..434e73ffa --- /dev/null +++ b/lib/registrant.rb @@ -0,0 +1,21 @@ +# lib/registrant.rb +class Registrant + attr_reader :name, :age, :license_data + + def initialize(name, age, permit = false) + @name = name # The name + @age = age + @permit = permit + @license_data = { written: false, license: false, renewed: false } + end + + def permit? + @permit + end + + def earn_permit + @permit = true + end +end +# Registrant class needs to be dynamic +# What questions can the method mutation provide? \ No newline at end of file diff --git a/spec/dmv_data_service_spec.rb b/spec/dmv_data_service_spec.rb index 7baf709a0..47d99cecc 100644 --- a/spec/dmv_data_service_spec.rb +++ b/spec/dmv_data_service_spec.rb @@ -14,14 +14,14 @@ it 'can load data from a given source' do source = 'https://data.colorado.gov/resource/dsw3-mrn4.json' data_response = @dds.load_data(source) - expect(data_response).to be_an_instance_of(Array) - expect(data_response.size).to be_an(Integer) + expect(data_response).to be_an_instance_of(Array) # Ensure the data returned is an array + expect(data_response.size).to be_an(Integer) # Ensure there are records in the array end end describe '#wa_ev_registrations' do it 'can load washington ev registration data' do - expect(@dds.wa_ev_registrations.size).to be_an(Integer) + expect(@dds.wa_ev_registrations.size).to be_an(Integer) # Check that the returned data is an array of records end end diff --git a/spec/registrant_spec.rb b/spec/registrant_spec.rb new file mode 100644 index 000000000..9f8afcc7d --- /dev/null +++ b/spec/registrant_spec.rb @@ -0,0 +1,31 @@ +# spec/registrant_spec.rb +require 'spec_helper' + +RSpec.describe Registrant do + # + it 'creates a registrant with a name, age, and permit' do + registrant_1 = Registrant.new('Bruce', 18, true) + registrant_2 = Registrant.new('Penny', 15) + + + expect(registrant_1.name).to eq('Bruce') + expect(registrant_1.age).to eq(18) + expect(registrant_1.permit?).to eq(true) + expect(registrant_1.license_data).to eq({ written: false, license: false, renewed: false }) + + expect(registrant_2.name).to eq('Penny') + expect(registrant_2.age).to eq(15) + expect(registrant_2.permit?).to eq(false) + expect(registrant_2.license_data).to eq({ written: false, license: false, renewed: false }) + end + + it 'allows a registrant to earn a permit' do + registrant_2 = Registrant.new('Penny', 15) + + expect(registrant_2.permit?).to eq(false) + + registrant_2.earn_permit + + expect(registrant_2.permit?).to eq(true) + end +end \ No newline at end of file diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 6ff6f53c2..6ee4a2372 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -2,4 +2,5 @@ require './lib/dmv' require './lib/facility' require './lib/vehicle' -require './lib/dmv_data_service' \ No newline at end of file +require './lib/dmv_data_service' +require './lib/registrant' \ No newline at end of file From dd596b865341ad7a92a2882ce0f2c578950803bf Mon Sep 17 00:00:00 2001 From: Sequoyah Descoteaux Date: Fri, 18 Oct 2024 23:50:26 +0200 Subject: [PATCH 17/33] Implemented Registrant class and added tests for initialization and permit functionality --- lib/registrant.rb | 25 +++++++++++++++++-------- spec/registrant_spec.rb | 15 ++++++++++----- 2 files changed, 27 insertions(+), 13 deletions(-) diff --git a/lib/registrant.rb b/lib/registrant.rb index 434e73ffa..7ff1e4669 100644 --- a/lib/registrant.rb +++ b/lib/registrant.rb @@ -1,21 +1,30 @@ # lib/registrant.rb class Registrant + # Create getter methods for name, age, and license_data, and a method for checking the permit status attr_reader :name, :age, :license_data - def initialize(name, age, permit = false) - @name = name # The name - @age = age - @permit = permit - @license_data = { written: false, license: false, renewed: false } + # Initializes the registrant with name, age, and permit (default false) + def initialize(name, age, permit = false) + @name = name # Assign the name passed as an argument + @age = age # Assign the age passed as an argument + @permit = permit # If no permit value is provided, it defaults to false + @license_data = { # Set up the default license_data hash + written: false, + license: false, + renewed: false + } end + # Method to check if the registrant has a permit def permit? - @permit + @permit # Returns true if the registrant has a permit, false otherwise end + # Method to update the permit status to true (if the registrant earns a permit) def earn_permit - @permit = true + @permit = true # Change the permit status to true end end # Registrant class needs to be dynamic -# What questions can the method mutation provide? \ No newline at end of file +# What questions can the method mutation provide? +# What are the effects? \ No newline at end of file diff --git a/spec/registrant_spec.rb b/spec/registrant_spec.rb index 9f8afcc7d..fe7900df0 100644 --- a/spec/registrant_spec.rb +++ b/spec/registrant_spec.rb @@ -2,30 +2,35 @@ require 'spec_helper' RSpec.describe Registrant do - # + # Test initialization with name, age, and permit it 'creates a registrant with a name, age, and permit' do - registrant_1 = Registrant.new('Bruce', 18, true) - registrant_2 = Registrant.new('Penny', 15) - + registrant_1 = Registrant.new('Bruce', 18, true) # Registrant with a permit + registrant_2 = Registrant.new('Penny', 15) # Registrant without a permit + # Test the attributes of the first registrant expect(registrant_1.name).to eq('Bruce') expect(registrant_1.age).to eq(18) expect(registrant_1.permit?).to eq(true) expect(registrant_1.license_data).to eq({ written: false, license: false, renewed: false }) + # Test the attributes of the second registrant expect(registrant_2.name).to eq('Penny') expect(registrant_2.age).to eq(15) expect(registrant_2.permit?).to eq(false) expect(registrant_2.license_data).to eq({ written: false, license: false, renewed: false }) end + # Test if a registrant can earn a permit it 'allows a registrant to earn a permit' do - registrant_2 = Registrant.new('Penny', 15) + registrant_2 = Registrant.new('Penny', 15) # Initialize a registrant without a permit + # Ensure initially Penny doesn't have a permit expect(registrant_2.permit?).to eq(false) + # Penny earns a permit registrant_2.earn_permit + # Test if the permit status is updated expect(registrant_2.permit?).to eq(true) end end \ No newline at end of file From 1158654540613fe4f5f7450ec459ffed84133d61 Mon Sep 17 00:00:00 2001 From: Sequoyah Descoteaux Date: Sat, 19 Oct 2024 00:03:44 +0200 Subject: [PATCH 18/33] Updated Iteration_1.md to reflect logic and implementation of Registrant class --- Iteration_1.md | 57 +++++++++++++++++++++++++++++++++++++------------- 1 file changed, 43 insertions(+), 14 deletions(-) diff --git a/Iteration_1.md b/Iteration_1.md index da6932967..306b3f226 100644 --- a/Iteration_1.md +++ b/Iteration_1.md @@ -1,26 +1,55 @@ # Iteration 1 - Learning the Existing Codebase ## Overview -In this iteration, we explored the existing codebase and familiarized ourselves with the classes, methods, and tests already in place. The goal was to identify any bugs in the application code and debug the project until all tests passed. +In this iteration, I explored the existing codebase and familiarized ourselves with the classes, methods, and tests already in place. The goal was to identify any bugs in the application code and debug the project until all tests passed. -## Test Failures and Fixes +# Iteration 1 - Learning an Existing Codebase + +## Logic and Implementation of the Registrant Class + +In this iteration, I implemented the `Registrant` class to represent a user of the DMV system. The class has the following key features: -### 1. Test: Facility#initialize can initialize -- **Failure Reason**: The `Facility` class was expecting three separate arguments (`name`, `address`, `phone`), but the test was passing a hash. -- **Fix**: Updated the `Facility` class to accept a hash (`facility_details`) and extract the `name`, `address`, and `phone` keys from it. This aligns with the way the test is structured. +- **Attributes**: `name`, `age`, `permit`, and `license_data`. + - **Permit** defaults to `false` if not provided. + - **License Data** is initialized as a hash with three keys: `:written`, `:license`, and `:renewed`, all defaulting to `false`. -### 2. Test: Facility#add service can add available services -- **Failure Reason**: The `add_service` method name in the class was pluralized (`add_services`), but the test was calling it in singular form. -- **Fix**: Changed the method name from `add_services` to `add_service` to align with the test. +- **Methods**: + - `permit?`: Checks if the registrant currently holds a permit. + - `earn_permit`: Allows the registrant to earn a permit, updating the `permit` attribute from `false` to `true`. + +--- + +## Test-Driven Development (TDD) Process + +1. **Step 1: Write Tests for Initialization**: + I started by writing tests to verify that the `Registrant` class correctly initializes with a name, age, and optional permit. The default values for the `license_data` hash were also tested. + +2. **Step 2: Implement the Class**: + After writing the tests, I implemented the class to make the tests pass. This included: + - Defining an initializer method that accepts `name`, `age`, and `permit` (with a default value of `false`). + - Initializing the `license_data` hash to track the registrant’s progress through the DMV process. + +3. **Step 3: Write Tests for Permit Functionality**: + I added tests to verify the behavior of the `permit?` and `earn_permit` methods. These methods control whether a registrant has earned their permit and allow this status to be updated. + +4. **Step 4: Implement Permit Logic**: + I implemented the `permit?` method to return the status of the permit and the `earn_permit` method to update the `permit` attribute to `true`. + +--- + +## Test Failures and Fixes -### 3. Test: Dmv#initialize can initialize -- **Failure Reason**: The `@facilities` instance variable was being initialized correctly, but there was no getter method (`facilities`) to access it in the test. -- **Fix**: Added `attr_reader :facilities` to provide access to the `@facilities` array. This allowed the test to properly access and verify the initialized empty array. +1. **Test: Initialization** + - **Failure Reason**: Missing attributes during initialization. + - **Fix**: Added the required parameters (`name`, `age`, and `permit`) to the `Registrant` class initializer. -### 4. Test: Dmv#add facilities can add available facilities -- **Failure Reason**: The method was working but not accessible without a getter method. -- **Fix**: After adding `attr_reader`, the facilities array could be accessed and validated. +2. **Test: Permit Status** + - **Failure Reason**: Initially, the `permit` attribute was not correctly initialized as `false`. + - **Fix**: Set `permit` to default to `false` unless otherwise provided in the initializer. +3. **Test: License Data** + - **Failure Reason**: The `license_data` hash was not initialized correctly. + - **Fix**: Ensured the `license_data` hash is always initialized with default values (`false` for `:written`, `:license`, and `:renewed`). ## Reflection - **Steps to Explore Codebase**: [What you did to understand the code]. From be9c9dcf19dc3b0970b052929fc83ac45ae8ec7a Mon Sep 17 00:00:00 2001 From: Sequoyah Descoteaux Date: Sat, 19 Oct 2024 00:05:07 +0200 Subject: [PATCH 19/33] Updated Iteration_1.md to reflect logic and implementation of Registrant class --- initial_debugging.md | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/initial_debugging.md b/initial_debugging.md index 5fc3e8d07..822fff80b 100644 --- a/initial_debugging.md +++ b/initial_debugging.md @@ -7,7 +7,15 @@ ### 2. Test: Facility#add service can add available services - **Failure Reason**: The `add_service` method name in the class was pluralized (`add_services`), but the test was calling it in singular form. - **Fix**: Changed the method name from `add_services` to `add_service` to align with the test. - + +### 3. Test: Dmv#initialize can initialize +- **Failure Reason**: The `@facilities` instance variable was being initialized correctly, but there was no getter method (`facilities`) to access it in the test. +- **Fix**: Added `attr_reader :facilities` to provide access to the `@facilities` array. This allowed the test to properly access and verify the initialized empty array. + +### 4. Test: Dmv#add facilities can add available facilities +- **Failure Reason**: The method was working but not accessible without a getter method. +- **Fix**: After adding `attr_reader`, the facilities array could be accessed and validated. + ## Successes - Successfully explored and understood the relationships between `Facility`, `Dmv`, and `Vehicle` classes. - All existing tests pass after resolving bugs in the application code. From d86c86fe7a1ee2997cacd8408e9e6f3db93c66af Mon Sep 17 00:00:00 2001 From: Sequoyah Descoteaux Date: Sat, 19 Oct 2024 00:13:21 +0200 Subject: [PATCH 20/33] Added and passed all tests for Registrant class, including edge cases --- spec/registrant_spec.rb | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/spec/registrant_spec.rb b/spec/registrant_spec.rb index fe7900df0..ae281a5b3 100644 --- a/spec/registrant_spec.rb +++ b/spec/registrant_spec.rb @@ -33,4 +33,38 @@ # Test if the permit status is updated expect(registrant_2.permit?).to eq(true) end + + # Edge Case 1: Registrants of any age can earn a permit + it 'allows registrants of any age to earn a permit' do + registrant_young = Registrant.new('Baby Bruce', 5) + registrant_old = Registrant.new('Grandpa Joe', 85) + + # Initially, neither should have a permit + expect(registrant_young.permit?).to eq(false) + expect(registrant_old.permit?).to eq(false) + + # Both earn a permit + registrant_young.earn_permit + registrant_old.earn_permit + + # Both should now have a permit + expect(registrant_young.permit?).to eq(true) + expect(registrant_old.permit?).to eq(true) + end + + # Edge Case 2: Permit defaults to false + it 'defaults permit to false if not provided' do + registrant_3 = Registrant.new('Charlie', 30) + + # Permit should be false by default + expect(registrant_3.permit?).to eq(false) + end + + # Edge Case 3: Initialize with a permit if provided + it 'can initialize with a permit if provided' do + registrant_1 = Registrant.new('Bruce', 18, true) + + # Permit should be true because it was provided as true + expect(registrant_1.permit?).to eq(true) + end end \ No newline at end of file From c6dc8b6880b8447d8b43a4bf5e93cbb49ed2d68c Mon Sep 17 00:00:00 2001 From: Sequoyah Descoteaux Date: Sat, 19 Oct 2024 00:43:56 +0200 Subject: [PATCH 21/33] Added vehicle registration functionality to Facility class, including registration date, plate type assignment, and fee collection. --- lib/facility.rb | 35 ++++++++++++++++++++++++++++++----- 1 file changed, 30 insertions(+), 5 deletions(-) diff --git a/lib/facility.rb b/lib/facility.rb index 0b9da34a5..8e1ab5db2 100644 --- a/lib/facility.rb +++ b/lib/facility.rb @@ -1,22 +1,47 @@ class Facility - # This line defines getter methods for name, address, phone, and services. + # This line defines getter methods for name, address, phone, services, registered_vehicles, and collected_fees. # These attributes can be accessed outside the class but can't be modified directly. - attr_reader :name, :address, :phone, :services + attr_reader :name, :address, :phone, :services, :registered_vehicles, :collected_fees # The initialize method is the constructor for the Facility class. + # Update # The initialize method sets up the facility with basic details and initializes empty arrays and a fee counter. # It takes a hash (facility_details) as an argument which contains the name, address, and phone. # We extract these values from the hash and assign them to instance variables. # An empty array is initialized for @services to hold the services provided by this facility. def initialize(facility_details) - @name = facility_details[:name] # Extract the name from the facility_details hash + @name = facility_details[:name] # Extract the name from the facility_details hash @address = facility_details[:address] # Extract the address from the facility_details hash - @phone = facility_details[:phone] # Extract the phone number from the facility_details hash - @services = [] # Initialize an empty array to store the services offered by this facility + @phone = facility_details[:phone] # Extract the phone number from the facility_details hash + @services = [] # Initialize an empty array to store the services offered by this facility + @registered_vehicles = [] # Stores the registered vehicles + @collected_fees = 0 # Stores total fees collected by the facility end # This method allows the facility to add a service to its list of services. # The service is passed as an argument and added to the @services array. + # Update: Method to add services to the facility (e.g., 'Vehicle Registration') def add_service(service) @services << service # Add the provided service to the @services array end + + # Method to register a vehicle if the 'Vehicle Registration' service is offered + def register_vehicle(vehicle) + return unless @services.include?('Vehicle Registration') # Ensure service is available + + vehicle.registration_date = Date.today # Set today's date as registration date + + # Determine the plate type and the associated registration fee + if vehicle.antique? + vehicle.plate_type = :antique + @collected_fees += 25 + elsif vehicle.electric_vehicle? + vehicle.plate_type = :ev + @collected_fees += 200 + else + vehicle.plate_type = :regular + @collected_fees += 100 + end + + @registered_vehicles << vehicle # Add the vehicle to the list of registered vehicles + end end \ No newline at end of file From 4348ba4e548d2982ef46bc671ebe7a4b98529df9 Mon Sep 17 00:00:00 2001 From: Sequoyah Descoteaux Date: Sat, 19 Oct 2024 00:44:20 +0200 Subject: [PATCH 22/33] Updated Vehicle class with plate_type and registration_date attributes for registration handling. --- lib/vehicle.rb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/vehicle.rb b/lib/vehicle.rb index 540b8ed33..4e1c79879 100644 --- a/lib/vehicle.rb +++ b/lib/vehicle.rb @@ -1,6 +1,7 @@ class Vehicle # These attributes are readable from outside the class. - attr_reader :vin, :year, :make, :model, :engine, :registration_date + attr_reader :plate_type, :registration_date # Added attributes that can be modified + attr_reader :vin, :year, :make, :model, :engine # The initialize method takes a hash of vehicle details and assigns them to instance variables. # It also initializes @registration_date to nil, indicating the vehicle is not yet registered. @@ -11,6 +12,7 @@ def initialize(vehicle_details) @model = vehicle_details[:model] # Vehicle's model (e.g., Cruz) @engine = vehicle_details[:engine] # Type of engine (e.g., :ice for internal combustion engine) @registration_date = nil # Initially, the vehicle is unregistered, so set to nil + @plate_type = nil # Initially,no plate assigned, so set to nil end # This method determines if the vehicle is considered an antique, which is true if the car is older than 25 years. From 2cd6bd02aa257892652b2b2f80618c3c1a44024b Mon Sep 17 00:00:00 2001 From: Sequoyah Descoteaux Date: Sat, 19 Oct 2024 00:47:56 +0200 Subject: [PATCH 23/33] Added test for registrant to check if registrant has a permit --- spec/registrant_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/registrant_spec.rb b/spec/registrant_spec.rb index ae281a5b3..17af48ec0 100644 --- a/spec/registrant_spec.rb +++ b/spec/registrant_spec.rb @@ -6,7 +6,7 @@ it 'creates a registrant with a name, age, and permit' do registrant_1 = Registrant.new('Bruce', 18, true) # Registrant with a permit registrant_2 = Registrant.new('Penny', 15) # Registrant without a permit - + binding.pry # Test the attributes of the first registrant expect(registrant_1.name).to eq('Bruce') expect(registrant_1.age).to eq(18) From 2c91c473ed317c7858a476281a99ad90f0d66fdd Mon Sep 17 00:00:00 2001 From: Sequoyah Descoteaux Date: Wed, 23 Oct 2024 00:06:18 +0200 Subject: [PATCH 24/33] Completed reflection for Iteration 1 and double checked Registrant class implementation with passing tests --- Iteration_1.md | 6 ++-- Iteration_2.md | 4 +-- lib/vehicle.rb | 2 +- spec/facility_spec.rb | 72 ++++++++++++++++++++++++++++++++++++++++++- 4 files changed, 77 insertions(+), 7 deletions(-) diff --git a/Iteration_1.md b/Iteration_1.md index 306b3f226..1bace3f6c 100644 --- a/Iteration_1.md +++ b/Iteration_1.md @@ -52,6 +52,6 @@ In this iteration, I implemented the `Registrant` class to represent a user of t - **Fix**: Ensured the `license_data` hash is always initialized with default values (`false` for `:written`, `:license`, and `:renewed`). ## Reflection -- **Steps to Explore Codebase**: [What you did to understand the code]. -- **Challenges**: [What was difficult about working with unfamiliar code]. -- **What was Easier**: [What was easier than expected]. \ No newline at end of file +- **Steps to Explore Codebase**: To explore the codebase, I first reviewed the structure of the provided classes and methods, focusing on how the Facility and Vehicle classes interacted. I read through the initial tests to understand the expected behavior. Using binding.pry, I paused execution at key points to inspect objects and variables, which helped me visualize how data flowed through the code. Finally, I worked through any failing tests one by one, debugging and adjusting the application logic to make them pass. +- **Challenges**: One challenge was getting familiar with the code that I didn’t write myself, especially when it came to understanding how different methods and objects were interacting. Some logic wasn’t immediately clear, so I had to spend extra time debugging. It was also challenging to extend the functionality without breaking the existing structure. +- **What was Easier**: It was easier than expected to work with the tests once I understood how the existing structure was built. The well-structured nature of the tests helped me see where new functionality needed to be added. Using binding.pry also made it easier to debug by allowing real-time inspection of object states, which gave quick feedback when something wasn’t working as expected. \ No newline at end of file diff --git a/Iteration_2.md b/Iteration_2.md index a9dd4c976..310bf4ddf 100644 --- a/Iteration_2.md +++ b/Iteration_2.md @@ -18,7 +18,7 @@ This iteration focused on improving the object-oriented design by adding the `Re ## Reflection - **Steps to Add Classes**: [What was the process for adding new classes]. -- **Challenges**: [What was difficult]. -- **What was Easier**: [What was easier]. +- **Challenges**: One challenge was dealing with unfamiliar parts of the code, particularly when implementing new features like the vehicle registration functionality. Understanding the flow between services offered by a facility and the vehicle class attributes took time to figure out. Another difficulty was maintaining the logic when adding new services to the facility while ensuring they adhered to the existing service framework. +- **What was Easier**: It was easier than expected to work with the tests once I understood how the existing structure was built. The well-structured nature of the tests helped me see where new functionality needed to be added. Using binding.pry also made it easier to debug by allowing real-time inspection of object states, which gave quick feedback when something wasn’t working as expected. diff --git a/lib/vehicle.rb b/lib/vehicle.rb index 4e1c79879..a8b61dea5 100644 --- a/lib/vehicle.rb +++ b/lib/vehicle.rb @@ -1,6 +1,6 @@ class Vehicle # These attributes are readable from outside the class. - attr_reader :plate_type, :registration_date # Added attributes that can be modified + attr_accessor :plate_type, :registration_date # Added attributes that can be modified attr_reader :vin, :year, :make, :model, :engine # The initialize method takes a hash of vehicle details and assigns them to instance variables. diff --git a/spec/facility_spec.rb b/spec/facility_spec.rb index c0f2f1233..00bcfbb98 100644 --- a/spec/facility_spec.rb +++ b/spec/facility_spec.rb @@ -3,7 +3,11 @@ RSpec.describe Facility do before(:each) do @facility = Facility.new({name: 'DMV Tremont Branch', address: '2855 Tremont Place Suite 118 Denver CO 80205', phone: '(720) 865-4600'}) + @cruz = Vehicle.new({vin: '123456789abcdefgh', year: 2012, make: 'Chevrolet', model: 'Cruz', engine: :ice}) + @bolt = Vehicle.new({vin: '987654321abcdefgh', year: 2019, make: 'Chevrolet', model: 'Bolt', engine: :ev}) + @camaro = Vehicle.new({vin: '1a2b3c4d5e6f', year: 1969, make: 'Chevrolet', model: 'Camaro', engine: :ice}) end + describe '#initialize' do it 'can initialize' do expect(@facility).to be_an_instance_of(Facility) @@ -23,4 +27,70 @@ expect(@facility.services).to eq(['New Drivers License', 'Renew Drivers License', 'Vehicle Registration']) end end -end + + describe '#vehicle registration' do + it 'can add vehicle registration service' do + expect(@facility.services).to eq([]) + + @facility.add_service('Vehicle Registration') + + expect(@facility.services).to eq(['Vehicle Registration']) + end + + it 'can register a vehicle and charge appropriate fees' do + @facility.add_service('Vehicle Registration') + + @facility.register_vehicle(@cruz) + expect(@facility.registered_vehicles).to eq([@cruz]) + expect(@cruz.registration_date).to be_a(Date) + expect(@cruz.plate_type).to eq(:regular) + expect(@facility.collected_fees).to eq(100) + + @facility.register_vehicle(@camaro) + expect(@facility.registered_vehicles).to include(@camaro) + expect(@camaro.plate_type).to eq(:antique) + expect(@facility.collected_fees).to eq(125) + + @facility.register_vehicle(@bolt) + expect(@bolt.plate_type).to eq(:ev) + expect(@facility.collected_fees).to eq(325) + end + end + + # Edge Case 1: Test registering a vehicle when the service is not offered + it 'does not register a vehicle if the service is not offered' do + expect(@facility.registered_vehicles).to eq([]) # No vehicles registered yet + + binding.pry # Pause here to inspect before registration attempt + + @facility.register_vehicle(@cruz) # Trying to register Cruz without offering the service + expect(@facility.registered_vehicles).to eq([]) # No vehicles should be registered + expect(@facility.collected_fees).to eq(0) # No fees should be collected + end + + # Edge Case 2: Test registering a vehicle without an engine type + it 'handles registration of vehicles with missing engine type' do + unknown_vehicle = Vehicle.new({vin: 'unknownvin', year: 2010, make: 'Unknown', model: 'Unknown'}) + @facility.add_service('Vehicle Registration') + + binding.pry # Pause here to inspect the unknown vehicle + + @facility.register_vehicle(unknown_vehicle) + expect(unknown_vehicle.plate_type).to eq(:regular) # Default to regular plate type + expect(@facility.collected_fees).to eq(100) # Charge regular fee + end + + # Edge Case 3: Test registering multiple vehicles and total fees + it 'registers multiple vehicles and tracks total fees accurately' do + @facility.add_service('Vehicle Registration') + @facility.register_vehicle(@cruz) # Regular vehicle, should add 100 to fees + + binding.pry # Pause here to check total fees after the first registration + + @facility.register_vehicle(@bolt) # EV vehicle, should add 200 to fees + @facility.register_vehicle(@camaro) # Antique vehicle, should add 25 to fees + + expect(@facility.registered_vehicles).to include(@cruz, @bolt, @camaro) + expect(@facility.collected_fees).to eq(325) # 100 (cruz) + 200 (bolt) + 25 (camaro)= 325 + end +end \ No newline at end of file From 8a8031bf8ea9f697cacd1c8124e98dc22e6aca68 Mon Sep 17 00:00:00 2001 From: Sequoyah Descoteaux Date: Wed, 23 Oct 2024 01:22:14 +0200 Subject: [PATCH 25/33] Added vehicle registration functionality and tested vehicle registration for different vehicle types (regular, antique, EV) --- lib/facility.rb | 26 +++++++++++++ spec/facility_spec.rb | 90 ++++++++++++++++++++++++++++++++++++++----- 2 files changed, 106 insertions(+), 10 deletions(-) diff --git a/lib/facility.rb b/lib/facility.rb index 8e1ab5db2..13e89c497 100644 --- a/lib/facility.rb +++ b/lib/facility.rb @@ -44,4 +44,30 @@ def register_vehicle(vehicle) @registered_vehicles << vehicle # Add the vehicle to the list of registered vehicles end + + # Method to administer written test + def administer_written_test(registrant) + # The written test is only administered if the service is available, + # the registrant is 16 or older, and they have a permit. + return false unless @services.include?('Written Test') && registrant.age >= 16 && registrant.permit? + + registrant.license_data[:written] = true # Mark the written test as passed + true # Return true to indicate success + end + + # Method to administer road test + def administer_road_test(registrant) + return false unless @services.include?('Road Test') && registrant.license_data[:written] + + registrant.license_data[:license] = true + true + end + + # Method to renew a driver's license + def renew_drivers_license(registrant) + return false unless @services.include?('Renew License') && registrant.license_data[:license] + + registrant.license_data[:renewed] = true + true + end end \ No newline at end of file diff --git a/spec/facility_spec.rb b/spec/facility_spec.rb index 00bcfbb98..0deca7cf7 100644 --- a/spec/facility_spec.rb +++ b/spec/facility_spec.rb @@ -1,6 +1,10 @@ require 'spec_helper' +require './lib/facility' +require './lib/registrant' +require './lib/vehicle' RSpec.describe Facility do + # Setup facility and vehicles before each test before(:each) do @facility = Facility.new({name: 'DMV Tremont Branch', address: '2855 Tremont Place Suite 118 Denver CO 80205', phone: '(720) 865-4600'}) @cruz = Vehicle.new({vin: '123456789abcdefgh', year: 2012, make: 'Chevrolet', model: 'Cruz', engine: :ice}) @@ -8,6 +12,7 @@ @camaro = Vehicle.new({vin: '1a2b3c4d5e6f', year: 1969, make: 'Chevrolet', model: 'Camaro', engine: :ice}) end + # Test for facility initialization describe '#initialize' do it 'can initialize' do expect(@facility).to be_an_instance_of(Facility) @@ -18,6 +23,7 @@ end end + # Test for adding services to the facility describe '#add service' do it 'can add available services' do expect(@facility.services).to eq([]) @@ -28,6 +34,7 @@ end end + # Test for adding vehicle registration service describe '#vehicle registration' do it 'can add vehicle registration service' do expect(@facility.services).to eq([]) @@ -37,33 +44,95 @@ expect(@facility.services).to eq(['Vehicle Registration']) end + # Test for registering a vehicle and charging appropriate fees it 'can register a vehicle and charge appropriate fees' do @facility.add_service('Vehicle Registration') + # Register the first vehicle (Cruz) and check its registration status @facility.register_vehicle(@cruz) expect(@facility.registered_vehicles).to eq([@cruz]) expect(@cruz.registration_date).to be_a(Date) expect(@cruz.plate_type).to eq(:regular) expect(@facility.collected_fees).to eq(100) + # Register the second vehicle (Camaro) and check its registration status @facility.register_vehicle(@camaro) expect(@facility.registered_vehicles).to include(@camaro) expect(@camaro.plate_type).to eq(:antique) expect(@facility.collected_fees).to eq(125) + # Register the third vehicle (Bolt) and check its registration status @facility.register_vehicle(@bolt) expect(@bolt.plate_type).to eq(:ev) expect(@facility.collected_fees).to eq(325) end end + # Testing written test functionality + describe '#administer_written_test' do + it 'administers a written test to eligible registrants' do + @facility.add_service('Written Test') # Add the written test service + + # Initialize registrants + registrant_1 = Registrant.new('John', 17, true) # Registrant with a permit + registrant_2 = Registrant.new('Jane', 15, true) # Registrant under age 16 + registrant_3 = Registrant.new('Bob', 17, false) # Registrant without a permit + + # Test that registrant_1 can take the written test + expect(@facility.administer_written_test(registrant_1)).to eq(true) + expect(registrant_1.license_data[:written]).to eq(true) + + # Test that registrant_2 cannot take the written test due to age + expect(@facility.administer_written_test(registrant_2)).to eq(false) + expect(registrant_2.license_data[:written]).to eq(false) + + # Test that registrant_3 cannot take the written test due to lack of permit + expect(@facility.administer_written_test(registrant_3)).to eq(false) + expect(registrant_3.license_data[:written]).to eq(false) + end + end + + # Testing road test functionality + describe '#administer_road_test' do + it 'administers a road test to eligible registrants' do + # Add the road test service to the facility + @facility.add_service('Road Test') + @facility.add_service('Written Test') + + # Initialize registrants + registrant_1 = Registrant.new('John', 17, true) # Registrant with a permit and written test passed + registrant_3 = Registrant.new('Bob', 17, false) # Registrant without a permit + + # Pass written test for registrant_1 + @facility.administer_written_test(registrant_1) + + # Test that registrant_1 can take the road test + expect(@facility.administer_road_test(registrant_1)).to eq(true) + expect(registrant_1.license_data[:license]).to eq(true) + + # Test that registrant_3 cannot take the road test due to failing written test + expect(@facility.administer_road_test(registrant_3)).to eq(false) + expect(registrant_3.license_data[:license]).to eq(false) + end + + it 'does not administer road test if service is not offered' do + registrant_1 = Registrant.new('John', 17, true) # Registrant with a permit + @facility.add_service('Written Test') # Only add the written test, no road test + + # Pass written test + @facility.administer_written_test(registrant_1) + + # Try to administer road test (should fail since the service is not offered) + expect(@facility.administer_road_test(registrant_1)).to eq(false) + expect(registrant_1.license_data[:license]).to eq(false) + end + end + # Edge Case 1: Test registering a vehicle when the service is not offered it 'does not register a vehicle if the service is not offered' do expect(@facility.registered_vehicles).to eq([]) # No vehicles registered yet - binding.pry # Pause here to inspect before registration attempt - - @facility.register_vehicle(@cruz) # Trying to register Cruz without offering the service + @facility.register_vehicle(@cruz) # Trying to register Cruz without offering the service expect(@facility.registered_vehicles).to eq([]) # No vehicles should be registered expect(@facility.collected_fees).to eq(0) # No fees should be collected end @@ -73,8 +142,6 @@ unknown_vehicle = Vehicle.new({vin: 'unknownvin', year: 2010, make: 'Unknown', model: 'Unknown'}) @facility.add_service('Vehicle Registration') - binding.pry # Pause here to inspect the unknown vehicle - @facility.register_vehicle(unknown_vehicle) expect(unknown_vehicle.plate_type).to eq(:regular) # Default to regular plate type expect(@facility.collected_fees).to eq(100) # Charge regular fee @@ -83,12 +150,15 @@ # Edge Case 3: Test registering multiple vehicles and total fees it 'registers multiple vehicles and tracks total fees accurately' do @facility.add_service('Vehicle Registration') - @facility.register_vehicle(@cruz) # Regular vehicle, should add 100 to fees - - binding.pry # Pause here to check total fees after the first registration - @facility.register_vehicle(@bolt) # EV vehicle, should add 200 to fees - @facility.register_vehicle(@camaro) # Antique vehicle, should add 25 to fees + # Register the first vehicle (Cruz) + @facility.register_vehicle(@cruz) # Regular vehicle, should add 100 to fees + + # Register the second vehicle (Bolt) + @facility.register_vehicle(@bolt) # EV vehicle, should add 200 to fees + + # Register the third vehicle (Camaro) + @facility.register_vehicle(@camaro) # Antique vehicle, should add 25 to fees expect(@facility.registered_vehicles).to include(@cruz, @bolt, @camaro) expect(@facility.collected_fees).to eq(325) # 100 (cruz) + 200 (bolt) + 25 (camaro)= 325 From 5e53950dedc10c63d199170c8e9f231a1165b764 Mon Sep 17 00:00:00 2001 From: Sequoyah Descoteaux Date: Wed, 23 Oct 2024 01:23:28 +0200 Subject: [PATCH 26/33] Updated Iteration 2 documentation --- Iteration_2.md | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/Iteration_2.md b/Iteration_2.md index 310bf4ddf..a08eae02d 100644 --- a/Iteration_2.md +++ b/Iteration_2.md @@ -1,24 +1,23 @@ -# Iteration 2 - Object-Oriented Design Enhancement +# Iteration 2 - Adding Features and Creating Objects from Data Sources ## Overview -This iteration focused on improving the object-oriented design by adding the `Registrant` class. We also established relationships between classes using OOP principles. + ## New Classes and Methods -- Created `Registrant` class to manage user data such as name, age, permit status, and license data. -- Added `earn_permit` method to change a registrant’s permit status. + ## Test Failures and Fixes -1. Test: [Description of test for `Registrant` class] +1. Test: [Description of test for ` ` class] - **Failure Reason**: [Explanation of why it failed] - **Fix**: [Description of how the issue was resolved] ## TDD Process -- Started with tests for `Registrant` and gradually built the class to meet requirements. -- Used interaction patterns to guide method design. + ## Reflection - **Steps to Add Classes**: [What was the process for adding new classes]. -- **Challenges**: One challenge was dealing with unfamiliar parts of the code, particularly when implementing new features like the vehicle registration functionality. Understanding the flow between services offered by a facility and the vehicle class attributes took time to figure out. Another difficulty was maintaining the logic when adding new services to the facility while ensuring they adhered to the existing service framework. -- **What was Easier**: It was easier than expected to work with the tests once I understood how the existing structure was built. The well-structured nature of the tests helped me see where new functionality needed to be added. Using binding.pry also made it easier to debug by allowing real-time inspection of object states, which gave quick feedback when something wasn’t working as expected. +- **Challenges**: + +- **What was Easier**: From b29e80804075837b046966114e978355945b9682 Mon Sep 17 00:00:00 2001 From: Sequoyah Descoteaux Date: Wed, 23 Oct 2024 01:25:22 +0200 Subject: [PATCH 27/33] Added written test administration functionality and tested eligibility based on age and permit --- lib/facility.rb | 8 -------- 1 file changed, 8 deletions(-) diff --git a/lib/facility.rb b/lib/facility.rb index 13e89c497..75b786716 100644 --- a/lib/facility.rb +++ b/lib/facility.rb @@ -62,12 +62,4 @@ def administer_road_test(registrant) registrant.license_data[:license] = true true end - - # Method to renew a driver's license - def renew_drivers_license(registrant) - return false unless @services.include?('Renew License') && registrant.license_data[:license] - - registrant.license_data[:renewed] = true - true - end end \ No newline at end of file From 2f3a53fc1a2a8b3e995c5637c5e8ea1ed103814d Mon Sep 17 00:00:00 2001 From: Sequoyah Descoteaux Date: Wed, 23 Oct 2024 01:25:58 +0200 Subject: [PATCH 28/33] Added road test administration functionality and tested eligibility based on written test status --- lib/facility.rb | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/lib/facility.rb b/lib/facility.rb index 75b786716..13e89c497 100644 --- a/lib/facility.rb +++ b/lib/facility.rb @@ -62,4 +62,12 @@ def administer_road_test(registrant) registrant.license_data[:license] = true true end + + # Method to renew a driver's license + def renew_drivers_license(registrant) + return false unless @services.include?('Renew License') && registrant.license_data[:license] + + registrant.license_data[:renewed] = true + true + end end \ No newline at end of file From a44985f0eec0d2d61bdf021fe9a051432db2ad21 Mon Sep 17 00:00:00 2001 From: Sequoyah Descoteaux Date: Wed, 23 Oct 2024 01:26:59 +0200 Subject: [PATCH 29/33] Added edge case tests for vehicle registration: missing service, missing engine type, and multiple vehicle registrations --- spec/facility_spec.rb | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/spec/facility_spec.rb b/spec/facility_spec.rb index 0deca7cf7..af72749f3 100644 --- a/spec/facility_spec.rb +++ b/spec/facility_spec.rb @@ -158,9 +158,4 @@ @facility.register_vehicle(@bolt) # EV vehicle, should add 200 to fees # Register the third vehicle (Camaro) - @facility.register_vehicle(@camaro) # Antique vehicle, should add 25 to fees - - expect(@facility.registered_vehicles).to include(@cruz, @bolt, @camaro) - expect(@facility.collected_fees).to eq(325) # 100 (cruz) + 200 (bolt) + 25 (camaro)= 325 - end -end \ No newline at end of file + @facility.register_vehicle(@camaro) # Antique vehicle, should add 25 to fees \ No newline at end of file From bd48f4a9685f2e9672e85c88e5f8c4f050dbf797 Mon Sep 17 00:00:00 2001 From: Sequoyah Descoteaux Date: Wed, 23 Oct 2024 01:30:27 +0200 Subject: [PATCH 30/33] Updated Iteration 2 documentation --- Iteration_2.md | 39 ++++++++++++++++++++++++++++----------- 1 file changed, 28 insertions(+), 11 deletions(-) diff --git a/Iteration_2.md b/Iteration_2.md index a08eae02d..1e8a91776 100644 --- a/Iteration_2.md +++ b/Iteration_2.md @@ -1,23 +1,40 @@ # Iteration 2 - Adding Features and Creating Objects from Data Sources ## Overview - +In this iteration, we extended the **Facility** class to administer a variety of DMV services such as **vehicle registration**, **written tests**, **road tests**, and **driver’s license renewals**. The registration logic applies different fees based on vehicle types, and each service requires the facility to offer the relevant service before it can be performed. We also focused on integrating external data for creating vehicle objects using a service class. ## New Classes and Methods +### Methods Added: +1. **register_vehicle**: + - Registers a vehicle, sets the registration date, and applies appropriate fees based on the vehicle type (regular, antique, electric). + +2. **administer_written_test**: + - Administers a written test to eligible registrants (age 16+, with a permit). + +3. **administer_road_test**: + - Administers a road test if the registrant has passed the written test. +4. **renew_drivers_license**: + - Renews a license if the registrant has a valid license. ## Test Failures and Fixes -1. Test: [Description of test for ` ` class] - - **Failure Reason**: [Explanation of why it failed] - - **Fix**: [Description of how the issue was resolved] - -## TDD Process +1. **Test: Written Test Eligibility** + - **Failure Reason**: Registrants without a permit or under age 16 were incorrectly allowed to take the test. + - **Fix**: Added condition checks in the `administer_written_test` method to restrict access to eligible registrants only. +2. **Test: Road Test** + - **Failure Reason**: Registrants who had not passed the written test were able to take the road test. + - **Fix**: Updated the `administer_road_test` method to check the status of the written test in the registrant's `license_data` hash. -## Reflection -- **Steps to Add Classes**: [What was the process for adding new classes]. -- **Challenges**: - -- **What was Easier**: +## TDD Process +1. **Start with Writing Tests**: We first wrote unit tests for each new service: vehicle registration, written test, road test, and license renewal. +2. **Implementation**: After each test was written, we implemented the corresponding method in the `Facility` class. +3. **Refinement and Debugging**: As we ran the tests, we fixed any issues or failures, ensuring that all methods adhered to the expected behavior. +4. **Final Testing**: After completing the functionality, we ensured all edge cases were covered and tests passed successfully. +## Reflection +- **Steps to Add Classes**: The process involved carefully understanding the requirements for each service, adding them one by one, and ensuring that they adhered to the rules (e.g., age and permit requirements for tests). Each method was added incrementally after writing the corresponding test. + +- **Challenges**: One of the challenges was handling edge cases such as attempting to administer a road test when the written test had not been passed, and ensuring that only facilities offering a service could perform it. +- **What was Easier**: Adding the vehicle registration logic was straightforward since the different fees and conditions could easily be mapped to vehicle attributes such as `year` and `engine type`. \ No newline at end of file From cad881fde3edea1cf5ead7c37e5764ecf802f1d3 Mon Sep 17 00:00:00 2001 From: Sequoyah Descoteaux Date: Wed, 23 Oct 2024 01:33:26 +0200 Subject: [PATCH 31/33] Added renew_drivers_license method and tests for license renewal functionality --- spec/facility_spec.rb | 48 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 47 insertions(+), 1 deletion(-) diff --git a/spec/facility_spec.rb b/spec/facility_spec.rb index af72749f3..f057730c6 100644 --- a/spec/facility_spec.rb +++ b/spec/facility_spec.rb @@ -128,6 +128,47 @@ end end +# Testing license renewal functionality +describe '#renew_drivers_license' do + it 'renews a driver’s license if the registrant has a license' do + # Add the renew license service to the facility + @facility.add_service('Renew License') + + # Initialize registrants + registrant_1 = Registrant.new('John', 17, true) # Registrant with a permit + registrant_2 = Registrant.new('Jane', 15, true) # Registrant without a license + + # Simulate the process of passing the written and road tests for registrant_1 + @facility.add_service('Written Test') + @facility.add_service('Road Test') + @facility.administer_written_test(registrant_1) + @facility.administer_road_test(registrant_1) + + # Test that registrant_1 can renew their license + expect(@facility.renew_drivers_license(registrant_1)).to eq(true) + expect(registrant_1.license_data[:renewed]).to eq(true) + + # Test that registrant_2 cannot renew their license since they do not have one + expect(@facility.renew_drivers_license(registrant_2)).to eq(false) + expect(registrant_2.license_data[:renewed]).to eq(false) + end + + it 'does not renew license if service is not offered' do + registrant_1 = Registrant.new('John', 17, true) # Registrant with a permit + + # Simulate passing both tests + @facility.add_service('Written Test') + @facility.add_service('Road Test') + @facility.administer_written_test(registrant_1) + @facility.administer_road_test(registrant_1) + + # Try to renew license without adding the renew service + expect(@facility.renew_drivers_license(registrant_1)).to eq(false) + expect(registrant_1.license_data[:renewed]).to eq(false) + end +end + + # Edge Case 1: Test registering a vehicle when the service is not offered it 'does not register a vehicle if the service is not offered' do expect(@facility.registered_vehicles).to eq([]) # No vehicles registered yet @@ -158,4 +199,9 @@ @facility.register_vehicle(@bolt) # EV vehicle, should add 200 to fees # Register the third vehicle (Camaro) - @facility.register_vehicle(@camaro) # Antique vehicle, should add 25 to fees \ No newline at end of file + @facility.register_vehicle(@camaro) # Antique vehicle, should add 25 to fees + + expect(@facility.registered_vehicles).to include(@cruz, @bolt, @camaro) + expect(@facility.collected_fees).to eq(325) # 100 (cruz) + 200 (bolt) + 25 (camaro)= 325 + end +end \ No newline at end of file From 1eee568faecc143234b933667e5d894043cd1b7f Mon Sep 17 00:00:00 2001 From: Sequoyah Descoteaux Date: Wed, 23 Oct 2024 02:03:07 +0200 Subject: [PATCH 32/33] Completed Iteration 2: Added vehicle registration, testing, and external data integration. --- lib/dmv_data_service.rb | 23 ++++++++--- lib/vehicle_factory.rb | 17 ++++++++ spec/dmv_data_service_spec.rb | 33 ++++++++++----- spec/vehicle_factory_spec.rb | 78 +++++++++++++++++++++++++++++++++++ 4 files changed, 135 insertions(+), 16 deletions(-) create mode 100644 lib/vehicle_factory.rb create mode 100644 spec/vehicle_factory_spec.rb diff --git a/lib/dmv_data_service.rb b/lib/dmv_data_service.rb index 7c979a82c..91a9415ad 100644 --- a/lib/dmv_data_service.rb +++ b/lib/dmv_data_service.rb @@ -1,25 +1,38 @@ -require 'faraday' -require 'json' +require 'faraday' # Faraday is used for making HTTP requests +require 'json' # JSON is used for parsing the JSON responses class DmvDataService + # This method takes a source URL, makes an HTTP GET request to that source, + # and parses the response body into a Ruby hash using JSON. def load_data(source) - response = Faraday.get(source) - JSON.parse(response.body, symbolize_names: true) + response = Faraday.get(source) # Make HTTP GET request to the source URL + + binding.pry # Add here to inspect the response or parsed data + + JSON.parse(response.body, symbolize_names: true) # Parse the JSON response and return it as a hash with symbolized keys end + # Method to load Washington State EV registrations. + # Uses memoization (@wa_ev_registrations) to cache the data after the first API request. def wa_ev_registrations @wa_ev_registrations ||= load_data('https://data.wa.gov/resource/rpr4-cgyd.json') end + # Method to load Colorado DMV office locations. + # Uses memoization (@co_dmv_office_locations) to avoid multiple API requests. def co_dmv_office_locations @co_dmv_office_locations ||= load_data('https://data.colorado.gov/resource/dsw3-mrn4.json') end + # Method to load New York DMV office locations. + # The data is fetched from an external API and cached using memoization. def ny_dmv_office_locations @ny_dmv_office_locations ||= load_data('https://data.ny.gov/resource/9upz-c7xg.json') end + # Method to load Missouri DMV office locations. + # Memoization ensures the data is only fetched once and reused in future calls. def mo_dmv_office_locations @mo_dmv_office_locations ||= load_data('https://data.mo.gov/resource/835g-7keg.json') end -end +end \ No newline at end of file diff --git a/lib/vehicle_factory.rb b/lib/vehicle_factory.rb new file mode 100644 index 000000000..c5a25b60a --- /dev/null +++ b/lib/vehicle_factory.rb @@ -0,0 +1,17 @@ +class VehicleFactory + # The create_vehicles method takes in an array of vehicle data hashes + # It maps over the data to create new Vehicle objects from the provided data + def create_vehicles(data) + # Iterate over each entry in the data array + data.map do |vehicle_data| + # For each vehicle_data hash, create a new Vehicle object with specific attributes + Vehicle.new({ + vin: vehicle_data[:vin_1_10], # Extract the VIN (first 10 characters) from the vehicle data + year: vehicle_data[:model_year], # Extract the vehicle's model year + make: vehicle_data[:make], # Extract the make of the vehicle (e.g., Toyota, Chevrolet) + model: vehicle_data[:model], # Extract the model of the vehicle (e.g., Prius, Bolt) + engine: :ev # Since this dataset is for electric vehicles, assume all engines are electric (:ev) + }) + end + end +end diff --git a/spec/dmv_data_service_spec.rb b/spec/dmv_data_service_spec.rb index 47d99cecc..2f8d01de7 100644 --- a/spec/dmv_data_service_spec.rb +++ b/spec/dmv_data_service_spec.rb @@ -1,45 +1,56 @@ require 'spec_helper' RSpec.describe DmvDataService do + # Set up a new instance of DmvDataService before each test before(:each) do @dds = DmvDataService.new end + + # Test to check if DmvDataService can be initialized describe '#initialize' do it 'can initialize' do - expect(@dds).to be_an_instance_of(DmvDataService) + expect(@dds).to be_an_instance_of(DmvDataService) # Expect @dds to be an instance of DmvDataService end end + # Test the load_data method, which loads data from a specific source URL describe '#load_data' do it 'can load data from a given source' do - source = 'https://data.colorado.gov/resource/dsw3-mrn4.json' - data_response = @dds.load_data(source) - expect(data_response).to be_an_instance_of(Array) # Ensure the data returned is an array - expect(data_response.size).to be_an(Integer) # Ensure there are records in the array + source = 'https://data.colorado.gov/resource/dsw3-mrn4.json' # Example source URL for Colorado DMV office locations + data_response = @dds.load_data(source) # Load the data from the specified source + expect(data_response).to be_an_instance_of(Array) # Ensure the data returned is an array + expect(data_response.size).to be_an(Integer) # Ensure the array contains some records end end + # Test to ensure that the Washington EV registration data can be fetched describe '#wa_ev_registrations' do - it 'can load washington ev registration data' do - expect(@dds.wa_ev_registrations.size).to be_an(Integer) # Check that the returned data is an array of records - end + it 'can load washington ev registration data' do + binding.pry # Add here to inspect what @dds.wa_ev_registrations returns + + expect(@dds.wa_ev_registrations.size).to be_an(Integer) end +end + + # Test to ensure that the Colorado DMV office locations can be fetched describe '#co_dmv_office_locations' do it 'can load colorado dmv office locations' do - expect(@dds.co_dmv_office_locations.size).to be_an(Integer) + expect(@dds.co_dmv_office_locations.size).to be_an(Integer) # Ensure the data is an array and has records end end + # Test to ensure that the New York DMV office locations can be fetched describe '#ny_dmv_office_locations' do it 'can load new york dmv office locations' do - expect(@dds.ny_dmv_office_locations.size).to be_an(Integer) + expect(@dds.ny_dmv_office_locations.size).to be_an(Integer) # Ensure the data is an array and has records end end + # Test to ensure that the Missouri DMV office locations can be fetched describe '#mo_dmv_office_locations' do it 'can load missouri dmv office locations' do - expect(@dds.mo_dmv_office_locations.size).to be_an(Integer) + expect(@dds.mo_dmv_office_locations.size).to be_an(Integer) # Ensure the data is an array and has records end end end diff --git a/spec/vehicle_factory_spec.rb b/spec/vehicle_factory_spec.rb new file mode 100644 index 000000000..9c95f713e --- /dev/null +++ b/spec/vehicle_factory_spec.rb @@ -0,0 +1,78 @@ +require 'spec_helper' +require './lib/dmv_data_service' +require './lib/vehicle_factory' # Require the VehicleFactory class +require './lib/vehicle' # Require the Vehicle class + +RSpec.describe VehicleFactory do + before(:each) do + @factory = VehicleFactory.new # Initialize the VehicleFactory instance before each test + + # Sample data from external dataset (this is a simplified version of what you'd get from the API) + @vehicle_data = [ + { + vin_1_10: 'JTDKN3DP8D', + model_year: '2013', + make: 'TOYOTA', + model: 'Prius Plug-in' + }, + { + vin_1_10: '1G1RD6E47D', + model_year: '2013', + make: 'CHEVROLET', + model: 'Volt' + } + ] + end + + # Test for VehicleFactory initialization + describe '#initialize' do + it 'exists' do + expect(@factory).to be_an_instance_of(VehicleFactory) # Check if @factory is an instance of VehicleFactory + end + end + + # Test for creating vehicles from data + describe '#create_vehicles' do + it 'can create vehicles from data' do + # Use the factory to create vehicles from the @vehicle_data + vehicles = @factory.create_vehicles(@vehicle_data) + + expect(vehicles).to be_an(Array) # Check if the result is an array + expect(vehicles.length).to eq(2) # Check if it creates 2 Vehicle objects + expect(vehicles.first).to be_an_instance_of(Vehicle) # Check if the first object is a Vehicle + + # Test the attributes of the first vehicle + expect(vehicles.first.vin).to eq('JTDKN3DP8D') # Check if the VIN is correct + expect(vehicles.first.year).to eq('2013') # Check if the year is correct + expect(vehicles.first.make).to eq('TOYOTA') # Check if the make is correct + expect(vehicles.first.model).to eq('Prius Plug-in') # Check if the model is correct + expect(vehicles.first.engine).to eq(:ev) # Check if the engine is set to :ev + + # Test the attributes of the second vehicle + expect(vehicles.last.vin).to eq('1G1RD6E47D') # Check if the VIN is correct + expect(vehicles.last.year).to eq('2013') # Check if the year is correct + expect(vehicles.last.make).to eq('CHEVROLET') # Check if the make is correct + expect(vehicles.last.model).to eq('Volt') # Check if the model is correct + expect(vehicles.last.engine).to eq(:ev) # Check if the engine is set to :ev + end + end + + # Integration test for using DmvDataService and VehicleFactory together + describe 'Integration with DmvDataService' do + it 'can create vehicles from external data' do + # Initialize DmvDataService to fetch real-world data + dmv_data_service = DmvDataService.new + + # Fetch Washington state EV registration data + ev_data = dmv_data_service.wa_ev_registrations + + # Use VehicleFactory to create vehicle objects from the external data + vehicles = @factory.create_vehicles(ev_data) + + expect(vehicles).to be_an(Array) # Ensure it returns an array of vehicles + expect(vehicles.first).to be_a(Vehicle) # Ensure the first item is a Vehicle object + expect(vehicles.first.engine).to eq(:ev) # Check that the engine type is set to EV + expect(vehicles.size).to eq(ev_data.size) # Check that the number of vehicles matches the data + end + end +end \ No newline at end of file From 79641253cf8a8f9b0250f75752a1233bb4dc652b Mon Sep 17 00:00:00 2001 From: Sequoyah Descoteaux Date: Wed, 23 Oct 2024 02:08:44 +0200 Subject: [PATCH 33/33] Completed Iteration 2: Added external data integration and vehicle creation functionality. --- Iteration_2.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Iteration_2.md b/Iteration_2.md index 1e8a91776..4380b1937 100644 --- a/Iteration_2.md +++ b/Iteration_2.md @@ -1,7 +1,7 @@ # Iteration 2 - Adding Features and Creating Objects from Data Sources ## Overview -In this iteration, we extended the **Facility** class to administer a variety of DMV services such as **vehicle registration**, **written tests**, **road tests**, and **driver’s license renewals**. The registration logic applies different fees based on vehicle types, and each service requires the facility to offer the relevant service before it can be performed. We also focused on integrating external data for creating vehicle objects using a service class. +In this iteration, I extended the **Facility** class to administer a variety of DMV services such as **vehicle registration**, **written tests**, **road tests**, and **driver’s license renewals**. The registration logic applies different fees based on vehicle types, and each service requires the facility to offer the relevant service before it can be performed. I also focused on integrating external data for creating vehicle objects using a service class. ## New Classes and Methods ### Methods Added: @@ -27,10 +27,10 @@ In this iteration, we extended the **Facility** class to administer a variety of - **Fix**: Updated the `administer_road_test` method to check the status of the written test in the registrant's `license_data` hash. ## TDD Process -1. **Start with Writing Tests**: We first wrote unit tests for each new service: vehicle registration, written test, road test, and license renewal. -2. **Implementation**: After each test was written, we implemented the corresponding method in the `Facility` class. -3. **Refinement and Debugging**: As we ran the tests, we fixed any issues or failures, ensuring that all methods adhered to the expected behavior. -4. **Final Testing**: After completing the functionality, we ensured all edge cases were covered and tests passed successfully. +1. **Start with Writing Tests**: I first wrote unit tests for each new service: vehicle registration, written test, road test, and license renewal. +2. **Implementation**: After each test was written, I implemented the corresponding method in the `Facility` class. +3. **Refinement and Debugging**: As we ran the tests, I fixed any issues or failures, ensuring that all methods adhered to the expected behavior. +4. **Final Testing**: After completing the functionality, I ensured all edge cases were covered and tests passed successfully. ## Reflection - **Steps to Add Classes**: The process involved carefully understanding the requirements for each service, adding them one by one, and ensuring that they adhered to the rules (e.g., age and permit requirements for tests). Each method was added incrementally after writing the corresponding test.