COSC-052: Computer Science II

Project 2
Spring 2023

Due: F 2/24 @ 5 PM
6 points

In this project, you will use classes, inheritance, and polymorphism to implement software that stores information about different types of bikes. For simplicity, we will assume that bikes are one of two types: delivery or urban.

I have drawn a class diagram for the project using the Unified Modeling Language (UML), which appears in the image below. Computer scientists and software engineers commonly use UML to design software and to communicate those designs. We will discuss the diagram in class, but its interpretation should be relatively straightforward.

A rectangle represents a class and is divided into three sections for the class's name, its data members (or attributes or properties), and its methods (or operators). Characters precede attributes and methods. The hyphen (-) denotes private, the pound sign (#) denotes protected, and the plus sign (+) denotes public.

As the diagram indicates, you should implement the Bike class and use inheritance to derive two subclasses, Delivery and Urban. All bikes have an ID, a name, and a number of gears, which must be protected. Delivery bikes have a carrying capacity. Each class should have virtual methods that read and print the bike's information from and to a stream. Naturally, the set methods should perform range checks and throw invalid_argument when values are invalid.

Storing information about a single bike is not very interesting, so also implement a Bikes (plural) class that stores pointers to Bike objects in a C++ vector. As the composition link in the diagram indicates, there is a one-to-many relationship between the Bikes class and the Bike class. The UML diagram depicts the vector as a private attribute of the Bikes class, but you could also derive Bikes from the vector class. Implement methods to read bikes from a file, print the bikes stored in the vector, compute the total number of gears of all of the bikes, and compute the total carrying capacity of the delivery bikes. For further information, see the p2 design documentation.

The file format consists of a bike's ID, name, number of gears, and if it is a delivery bike, its carrying capacity. The ID is a three-character string. The first character is in {A, ..., Z} and indicates the type of the bike. This character is 'D' for delivery bikes, and it is 'U' for urban bikes. The next two characters are digits and represent an inventory code. The name is delimited with double quotes. The number of gears and the carrying capacity are integers. An example of bikes in this format is as follows:

U01 "Trek Soho Deluxe" 8
D01 "Trek Transport+" 8 80
D02 "Johnny Loco Cargo Cruiser" 8 75
U02 "Johnny Loco Urban Londoner" 3
U03 "Johnny Loco Urban Moscow" 1
U04 "Kona Dew DL" 9
D03 "Kona Minute" 8 70
D04 "Kona Ute" 8 100

As Bikes::read reads the input file, it uses BikeFactory::make to make either a Delivery object or an Urban object a based on the contents of the input stream. Once BikeFactory::make determines whether the information in the stream corresponds to a delivery bike or an urban bike and creates the appropriate object, it invokes the polymorphic read method to fully instantiate the object. The factory can determine which subtype of Bike to make by examining the first character of the ID. It should then use iostream::putback to put the character back into the input stream so the object's read method can process the information in the stream properly.

A Factory is a common method pattern in object-oriented programming. As the name suggests, it is a class designed to produce objects. For this project, its method make returns a pointer to either an Urban object or a Delivery object.

In the main function, write a simple driver program that constructs a Bikes object, reads bikes from the file bikes.dta, prints them to the console, prints the total number of gears of those bikes, and prints the total carrying capacity of the delivery bikes. The main function should also catch the thrown exceptions and issue an appropriate message for those exceptions.

Use stepwise refinement and incremental development. For example, implement the Bike class and test it thoroughly before implementing, say, the Delivery class.

Getting Started

I'm sure that messing around with the Makefile for p1 was fun, but for p2, you'll use a Makefile that is less obvious, but more general. You should be able to use it for the rest of the projects this semester.

To get started, log on to cs-class and copy over the following zip file:

cs-class% cd
cs-class% cp ~maloofm/cosc052/p2.zip ./
cs-class% unzip p2.zip
In the p2 directory, you will find .h files and a Makefile. I'll explain this Makefile in class. It might be a useful exercise to get this Makefile working for your solution to p1 just to make sure you know what you're doing.

Instructions for Electronic Submission

In a file named HONOR, include the following statement with the appropriate modifications:

In accordance with the class policies and Georgetown's Honor System,
I certify that, with the exceptions of the class resources and those
items noted below, I have neither given nor received any assistance
on this project.

Name
NetID

You will submit p2 exactly like you submitted p1. For convenience, I added a submit target to the Makefile that produces submit.zip for Autolab. To produce this file, type 'make submit'. Make sure you remove all debugging output before submitting.

Plan B

If Autolab is down, upload your zip file to Canvas.

Copyright © 2023 Mark Maloof. All Rights Reserved. This material may not be published, broadcast, rewritten, or redistributed.