CS 101 (Spring 2000)
Lab 3: Systems of Objects: Clothing Factories and Process Control

(CS101 E-Sweat-Shop)

Lab Assigned
Design Due
(In class)

10 AM
Implement
(In Lab)
Demo
(In Lab)
Lab Due
(In class)
Friday
10 AM
7 Feb None 8-9 Feb 15-16 Feb 18 Feb


Goals:

By the end of this lab, you should Labs in this course typically contain the following three parts:
  1. Problem statement
  2. Design
  3. Implementation
For all labs, we provide you with a problem statement---a characterization of the problem you are to solve. In this particular lab, just like last lab, we take you through the process of design. Specifically, we will articulate Although your graded work for this lab is the implementation you will carry out based on our design, it is important that you follow our design and design process, because starting with the next lab, you will be designing solutions to your own labs.

Don't put off working on this lab! Although the implementation is straightforward once you understand the design, the lab is a little larger than either of the previous labs. Feel free to ask for help as needed!


Before starting:

[[[ Download PC zip ]]]

Zip includes:
Lab3.java Startup.java SimConstants.java Shirt.java
ShirtFactory.java ShirtWarehouse.java ShirtShop.java
FabricFactory.java ProcessControl.java GUIManager.java

All labs will include a main file named by the lab number, such as Lab3.java. The labs will also include a Startup.java file, which serves as a driver: a piece of code that calls the methods you write, to exercise your code and demonstrate your work. In this lab, the driver is incomplete; you must write some test procedures for some of the classes you implement.


  1. Problem Statement

    Toons 'R' Us.com, the famous Internet clothing store for two-dimensional characters, is a smash hit! Our toon friends are clamoring for more. In order to meet their demands, though, Toons 'R' Us will have to step back and re-analyze that ad-hoc method they're using to supply shirts to these customers. Yes, that's right: it's time for some high-level business decisions, some assembly line fun, and Java is just the language to help us out.

    Your job is to help increase the profitability of Toons 'R' Us by articulating and implementing a system of objects that models real-life counterparts (recall that the API of such objects is the interface, which hides internal implementation). The Toons 'R' Us head honchos have already decided on the API, and it's set in stone. So, you'll have to honor their wishes in your implementation. Their design involves the following:

    More on the operation of our factory

    Before we start you in on the design, you need to understand how the system will function. The shirts that are made

    The selling price of each shirt depends only on its size. However, the production requirements of a shirt depend on both its size and the fabric of which it is made. Besides requiring a certain amount of fabric (dependent only on size), the shirts require some production time (dependent only on fabric type). The lower fabric numbers require more time per shirt, but cost less per square foot.

    We provide a means for accessing the particular values of these shirt production attributes by giving you a SimConstants.java file, which contains a means for storing and retrieving attributes such as how long it takes to make a shirt which is made of fabric 3, or exactly how large a "large" shirt is.

    When you are done implementing the lab, its objects will form a (linear) optimization problem, in which many factors must be considered to try to make the maximum profit. Problems such as these occur everywhere in the real world, especially in manufacturing processes. Have fun trying to find the best solution you can (Hint: you're doing very well if, given the default parameters in Startup.java as described below, you can make $2000).

    During demo, a prize will be given to the student who can maximize profit in running his or her implementation. The idea is to use your implementation as a tool to explore how best to make money.

    In real life, you would probably implement more features into each of the classes because the problems of real manufacturing are deeper and more complex. So, here is an example of stepwise refinement -- our factory classes will be complete in and of themselves, but the design may need to support more features in different contexts.


  2. Design

    Major caveat #1: One of the goals of this lab is to get you thinking of how to write internal representations (i.e. choose instance variables). So, you will find the instance variables missing in most of the files for this lab. Feel free to choose your own instance variables; part of your grade for the lab will be how well you choose them and how well they work. Having said that, the choice of instance variables should be fairly straightforward based on our design - if it seems like the right answer, it probably is!

    Major caveat #2: Another goal of this lab is to get you testing your classes thoroughly. We require of all of your classes (except ProcessControl) to have a method public String toString( ) that Java uses to convert your object to a String. You are also required to test your classes thoroughly in Startup.java by printing some tests to the Terminal, some of which involve the use of your toString. The test procedures should be located in the indicated spots in Startup.java. Some examples are provided; if you have any questions, please ask.

    Now, on to the design!

    1. First, we need to understand the production unit that is the lifeblood of Toons 'R' Us -- the shirt. In this lab, we don't care about how the shirt is drawn -- in fact, you won't see a CS101Canvas anywhere. However, there are some important things we need to know about the shirts that are necessary for knowing how to produce them.
      • Each shirt has an area of total fabric used in its production.
      • Each shirt has a production time requirement based on its fabric.
      • Each shirt is sold at a specified price.

      We will provide the price, production time, and area to the constructor of the Shirt class. Notice that there is no need to change these characteristics once the shirt is made; thus, we write Shirt as an immutable object. This means that, given the API, there is no way to change the internal representation of the object; it always yields the same values when any of its accessors are called.
      We therefore adopt the following API for the Shirt class:
      Constructor
      Shirt(int area, double productionTime, int price)
      Makes a shirt with the given characteristics. For example, new Shirt(2, 0.5, 10) makes a shirt that takes 2 sq ft of fabric, 1/2 an hour to make, and will sell for $10.00.
      Accessors
      int getArea()
      This returns the area (in square feet) of this shirt.
      double getTimeToMake()
      This method returns the amount of time required to make this shirt.
      int getPrice()
      This returns the price in dollars of this shirt.
      Mutators
      None (object is immutable).
      toString()
      Returns a string describing the characteristics of the shirt. For Shirt, we provide toString which would produce the following for the above example.
      "$10 shirt requiring 0.5 hours and 2 sq ft of fabric"
    2. Next, we should look at how to create a shirt factory. The shirt factory stocks each of the four different kinds of fabric, and receives requests for shirts.

      For this design, we will encode the kind of fabric as an int: 1, 2, 3, or 4.

      This suggests an internal representation which allows you to keep track of how much of which fabric and time you have left, and leads to the following API for ShirtFactory:

      Constructor
      ShirtFactory(int supply1, int supply2, int supply3, int supply4, double prodHours, SimConstants sc)
      This defines what we need to start our ShirtFactory. We receive the amount of each kind of fabric, and the total production hours we have at our disposal. In addition, you also receive an instance of SimConstants. You will need this object to learn how much time it takes to produce a particular shirt.
      Accessors
      int getFabricLeft(int fabricType)
      This returns the supply in this factory of the given fabric type in square feet.
      double getHoursLeft( )
      This returns the amount of production time remaining in the factory at the given moment.
      Mutators
      void addFabric(int fabricType, int quantity)
      This augments the supply of the given fabricType (an integer in range 1-4 inclusively) by the indicated quantity. It is an error to call this method with a ngeative value for quantity.
      Shirt makeShirt(int size, int fabricType)
      This returns one Shirt of the desired size and fabric, if the resources are available. If the shirt can be made, the resources are subtracted from both the fabric supply and the production hours available. If the shirt CANNOT be made, the method should return null; null is discussed in class and in the FAQ.

      In order to find out the sales price, fabric requirement, and time requirement for this shirt, you must call methods on the SimConstants object. Those methods take the size of the shirt as a parameter.

      toString()
      You form a String that shows the supply of your factory. We suggest this format: "ShirtFactory with supply [1, 2, 3, 4] and hours left 101".

      Notice that the ShirtFactory should never make a shirt for which it doesn't have the resources; in other words, ShirtFactory has a representation invariant which says the resources should never dip below zero, or else the object is in an illegal state. It is your responsibility to be sure your implementation maintains this invariant.

    3. The shirts made in our factory go to a warehouse. The warehouse is pretty simple; in this case, all we're going to do is keep track of the total value of goods in the warehouse. This leads to a design for a ShirtWarehouse object, for which we have the following API.
      Constructor
      ShirtWarehouse()
      This should just initialize an empty warehouse.
      Accessors
      int getGoodsValue( )
      This should just return the total value of goods in the warehouse.
      Mutators
      void empty( )
      This method depletes the entire inventory of the warehouse.
      void addToStock(Shirt s)
      This should find out what the Shirt's price is, and add it to the total value of goods in this warehouse.
      toString()
      You form a String that shows the monetary value of the supply of your factory. We suggest this format: "ShirtWarehouse with total goods $101"
    4. You want to sell stuff, right? We need something to manage how much cash we have on hand. We use a simple class called ShirtShop with the following API.
      Constructor
      ShirtShop(String owner, double startingCash)
      This creates a ShirtShop with the given amount of cash initially in its drawer. The name of the owner is also provided.
      Accessors
      String getOwnerName()
      This returns the name of the owner of this ShirtShop.
      double getCash()
      This should return the amount of cash currently in the drawer.
      Mutators
      boolean debit(double cash)
      The specified amount of cash is deducted from the cash drawer, providing that sufficient funds are available. When this method succeeds by deducting the cash, it returns true. Otherwise, it returns false. Note the representation invariant: the cash in the drawer is never negative. Thus, if we have $200 on hand, debit(300) will fail, returning a false value and leaving the drawer unchanged.

      To indicate the error state in this case, we use a boolean value; a return of true means the transaction succeeded, and false means the transaction failed.

      void credit(double cash)
      The specified amount of cash is added to the cash drawer,
      toString()
      You form a String containing the cash flow of the shop and its owner. We suggest this format: "Shirt Shop owned by John Doe with $101".
    5. We need a FabricFactory to keep track of the supplier's amount of fabric.
      Constructor
      FabricFactory(int supply1, int supply2, int supply3, int supply4, SimConstants sc)
      This defines what we need to start our Factory, as we receive the amount of each kind of fabric that is initially stocked. The SimConstants object allows us to find out the unit prices of each kind of fabric.
      Accessors
      int getSupply(int fabricType)
      This returns the supply in this factory of the given fabric type in square feet.
      Mutators
      boolean sellFabric(int fabricType, int qty, ShirtShop shop, ShirtFactory destFactory)
      This is a sell request of the given amount of the given fabric type.

      The ShirtShop is providing the funds for this transcation, but the fabric is sold to the ShirtFactory.

      Thus, you must check against the cash on hand in the given ShirtShop and this FabricFactory's supply to decide if the order can be filled. If the order can be filled, fill it by adding fabric to the destination ShirtFactory and making a negative valued transaction on the ShirtShop. Use the SimConstants object you received in the constructor to determine the total cost of the order based on qty and the unit price of the given fabric type.

      Again, returns false if the order can't be filled, and true if the order could have been (and was) filled. Don't forget to actually subtract the order from your supply!

      toString()
      You form a String containing the supply of your factory. We suggest this format: "FabricFactory with supply [1, 2, 3, 4]".
    6. Last but definitely not least is the brains of the operation -- ProcessControl.
      Constructor
      ProcessControl(FabricFactory ff, ShirtFactory sf, ShirtWarehouse sw, ShirtShop s, SimConstants sc)
      This is a complete definition of the players in the simulation. We provide this for you, and initialize instance variables as well as provide a graphical user interface (GUI) for the program. See GUIManager.java if you want the gory details (but don't worry if you don't understand it now - you'll learn how to make GUIs in CS102).
      Accessors
      None.
      Mutators
      Note: When writing these methods, don't forget to call updateGUI() on the GUIManager stored inside the ProcessControl object so that the user interface can refresh itself.
      boolean manufactureShirt(int size, int fabricType)
      This method tries to make a shirt at the ShirtFactory, and stock it in the ShirtWarehouse. (Both of these are initialized in the constructor.) It should return false if the shirt could not be made, and show an error message by calling the indicateProblem(String errorMessage) method on the GUIManager.
      void orderFabric(int fabricType, int quantity)
      This method tries to order more fabric from the FabricFactory based on the factory supply and the cash on hand in the ShirtShop. Should show an error message if the order could not be filled (check the return status of calling sellFabric( ) on the FabricFactory) by calling indicateProblem(String errorMessage) on the GUIManager.
      void sellShirts( )
      This should add to the cash on hand of the ShirtShop the amount of the goods in the ShirtWarehouse. The warehouse is also emptied by this method. You should print an informational message by calling indicateMessage(String message) on the GUIManager that shows the amount you made on the sale.


  3. Implementation

    You must implement the classes described in the design. For this lab, you are constrained to following this design. Specific implementation steps are given at the end of this document; the files you download repeat those suggestions.


What to turn in:

  1. Complete a code cover sheet.
  2. Provide a printout of any files you have modified (see approach below).
  3. Provide a transcript from Startup's textual tests on your classes. Recall that this file is produced automatically by the Terminal and can be found in the file transcript.txt in the same folder as your Lab 3 files.
  4. Type or print neatly the answers to the following questions, and submit them with your lab:

Suggested implementation approach:

  1. Implement Shirt.java according to the instructions contained in that file. Use the textual test in Startup.java to test it.
  2. Implement ShirtFactory.java according to the instructions in that file. Use the textual test in Startup.java to test it.
  3. Complete the code for ShirtWarehouse.java. Write tests in Startup.java to test ShirtWarehouse.
  4. Complete the code for ShirtShop.java and write tests in Startup.java to test ShirtShop.
  5. Complete the code for FabricFactory.java and write tests in Startup.java to test FabricFactory.
  6. Finally, complete the code for ProcessControl.java. Comment in the graphical test in Startup to test ProcessControl.


Last modified 00:15:10 CST 6 February 2000 by Robert Amar