CEng242 Homework 4
Due 2nd May 2005

An international car distribution company collects its orders and invoices in a special type called CarOrder. A CarOrder value consists of a list of order items for cars where each order entry have:

Producer:
A string denoting the producer of the car like ``Ford'', ``Opel'', ``Ferrari'', ``Honda'' etc.
Model:
A string denoting the model of the car like ``Sierra GT'', ``Astra'', ``TX200TC'', ``CLX'' etc.
Year:
An int value greater than 1900 which is the production year of the car.
Color:
Any string value denoting the color of the car like ``Blue'', ``White'', ``Rain forest green'', ``Night shadow blue'' etc.
Class:
A CarClass type value denoting the class the car belongs to. CarClass type declaration is given below.
Amount:
An int value greater then 0 representing how many cars of this type is ordered.
Unit price:
A double value greater then 0 representing the unit price of the car in YTL.

Strings mentioned above have a 100 characters length limit.

For each CarOrder typed value, a tax strategy can be defined. A default tax percentage which should be greater then or equal to 0 is kept. In addition to this, a list of tax rules is defined and applied incrementally for each order entry separately. A tax rule can be any of:

price of the car with a,b,addtax
If unit price of the UP is in the interval a ≤ UP < b, add double value addtax to current tax percentage. 0 <ab and 0 < addtax should hold for a, b and addtax.
class of the car with class,addtax
If class of the car is class then add the double value addtax to current tax percentage. 0 < addtax should hold.
age of the car with a,b,dectax
If production year of the cars in the order item is in the closed interval [a,b], then the current tax will be reduced by the percentage value in double dectax value. New tax percentage will be currenttax-currenttax*dectax/100. ab and dectax < 100 should hold.

For example when there are 2 rules matching for a car, the default tax value is taken, the first rule is applied and the new tax value is calculated. Then the second rule is applied and the new tax value is found. This last tax value is used in the calculation of the final price of the car. Tax amount is added to unit price of the car.

All prices are double values. These rules are kept in the order of insertion and applied in this order starting with the default tax rate for each order item individually.

You are given the following definition for the CarClass:
enum CarClass {Hatchback, Sedan, Convertible, StationWagon, Jeep, Pickup, MiniBus};
enum Exception INVALIDORDER, INVALIDTAXRULE;

You should provide the following public member functions with CarOrder type:

CarOrder(double taxdefault)
Get the default tax rate in percentage (10.0 is 10%) and construct an empty order without any entries.
CarOrder & insertOrder (prod,model,year,class,color,amount,price)
The new car order defined by these 7 values is inserted into current CarOrder object. We have a restriction that says "All occurrences of items with same ( Producer,Model,Class,Year) values should have the same unit price".Therefore, if a similar entry (first 4 values in the tuple is the same) exists in the list of current orders, new price value is considered as the new unit price for all matching entries. Note that entries with different colors may exist but they should have the same price!
CarOrder & deleteOrder(prod,model,year,class,color)
Search the entries matching 5 parameters in the current orders and delete matching entries.return If entry is not found, nothing is done.
CarOrder & operator+(const CarOrder &p)
Add all order items in the parameter object p into the current object. Default tax rate and tax rules come from the parameter object (current is overridden) In the addition process, amount fields of the similar (same info and color) entries will be summed up and prices are taken from the parameter object p.
CarOrder & operator*(const CarOrder &p)
Take the intersection of two orders. Order entries will come from the entries matching in both current and parameter object p. The amount (number of cars) in the new entry should be the minimum of two amounts and unit price should be the price from the entry in p. Default tax rate and tax rules should come from p.
double totalOfOrders():
Get all orders in the current CarOrder, calculate and return total cost of the orders including taxes.
ostream & operator<<(ostream &,const CarOrder &)
Produce a report on the given stream in first parameter. Report will have the following format (first line is just a ruler, not a part of the output):
0123456789012345678901234567890123456789012345678901234567890123456789012345678
Producer    |Model     |Year|Class    |Color    |Amt|Price    |Tax  |Total
------------+----------+----+---------+---------+---+---------+-----+----------
Ferrari     |F1        |2000|sports   |Red      |  1| 100000.0| 30.2|  112000.0
Tofas       |Sahin     |1984|sedan    |Blue     |  4|   2345.5| 10.0|   10320.2
Tofas       |Sahin     |1984|sedan    |Yellow   |  2|   2345.5| 10.0|    5160.1
------------+----------+----+---------+---------+---+---------+-----+----------
Total                                              5                   127480.3
Entries should be sorted in the ascending order according to producer, model, class, year and color. Primary ordering will be done according to producer name. For entries with same producer name secondary ordering will be done according to model name, then according to class name and so on. String comparisons will be case insensitive and work like stricmp(). For CarClass corresponding integer values will be significant in the comparison.
CarOrder & insertTaxRule(...)
Get a group of parameters denoting a taxrule (one of three rule type given above) and update the current object with this tax rule inserted at the end of the tax rules list. There can be multiple tax rules with exactly same values. In this case rule will be applied multiple times in the insertion order as if they were distinct rules.

This function is overloaded for three tax rule type. If parameters are (double, double, double), then the tax rule is a price rule, first two give the interval and the last parameter is the tax change. If parameters are (CarClass, double), then the tax rule is the class based rule, first parameter is the class of the car and the second is the tax change. If the parameters are (int,int,double), then the tax rule is age based, the first two give the production year interval and the last one is the tax reduction rate.

CarOrder & deleteTaxRule(...)
Similar to insertTaxRule, but deletes all of the matching tax rules from the current order. If no match is found, silently ignored.
CarOrder & operator=(CarOrder &p)
Assigns the parameter p object overriding the current object content. You should be careful with not having any garbages left and no memory area is shared by the dynamic data structures of two objects.
CarOrder(CarOrder &p)
Constructs a new object from the parameter object p. This is the copy constructor for passing objects by value. You should be careful with not having any garbages left and no memory area is shared by the dynamic data structures of two objects.

All CarOrder & returning functions return the current object reference (namely `*this' ). All functions are implemented carefully that no garbage heap variable is left and no memory is shared by two objects. You are not allowed to use STL of C++ other than iostream (library classes like string, vector, map, list, ... are not allowed).

You are free to choose any internal representation for your class as long as you provide the following integrity rules:

For error cases you should simply throw value where value is a value of the Exception. You should produce the following values in the exceptions:

"Invalid numeric value in the order"
If an invalid order is to be created or deleted (negative amount, price, tax is not is negative, car class is invalid), `throw INVALIDORDER;' .
Error "Invalid range or value in tax rule"
If an invalid tax rule to be created or deleted (negative amount, price, tax , car class is invalid), `throw INVALIDTAXRULE;' .

You should hide all of your implementation details in private section and only the interface functions above should be in public.

When submitting this homework, you should submit 2 files packaged in a tar.gz file:

hw4.h
This will contain only your CarOrder class definition and nothing else. This class definition will only contain prototypes of the member functions (public and private) and definitions required for operator« function. No inline definitions allowed in this file. No definitions other than the required definitions should be made public.
hw4.cpp
This file will include hw4.h and provide the implementations of all of the functions defined. If you happen to implement any auxiliary function outside of the class (like C functions), define them as static so that they will not be available to linker. Do not put main() function here.

You can put your main() function in a separate C++ file like hw4main.cpp, and include hw4.h. Then, you can use the following Makefile in your directory and use make command to compile your program:

hw4.o: hw4.h

.cpp.o:
        g++ -c $<

hw4main: hw4.o hw4main.o 
        g++ hw4.o hw4main.o -o hw4main

Makefile syntax requires the first characters in lines with g++ to be a "TAB" character.

We like to remind you that our cheating policy is to give 0 to all participants for all 6 previous and following homeworks.