Skip to content

Instantly share code, notes, and snippets.

Created October 7, 2015 21:38
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save anonymous/b629b37d40e017881108 to your computer and use it in GitHub Desktop.
Save anonymous/b629b37d40e017881108 to your computer and use it in GitHub Desktop.
ITEC 2610 Object-Oriented Programming, Fall 2015
Assignment 1
To submit:
Prepare a single zip file containing all the source files (.java files, NOT .class files) and testsOutput.txt and submit it through Moodle.
Details
SuperPhoneCard Inc. sells phone cards for making cheap long distance calls around the world. In this assignment, you will write a (much simplified) Java program to manage their business.
SuperPhoneCard Inc. sells Global25 phone cards which cost $25 each and are good for both domestic and overseas calls. The per minute rates are as follows:
Global25
Canada $0.05
USA $0.10
Europe $0.20
Asia $0.40
Australia & NZ $0.30
Latin America $0.30
Africa $0.40
The initial balance on the cards and the weekly maintenance fee are indicated below:
Global25
initial balance $25.00
weekly fee $1.00
Your job in this assignement is to implement the classes to support the application. The main class is PhoneCard with the following API:
public PhoneCard(long no, int passwd): a constructor (precondition: no and passwd must be positive);
public long getNumber(): an accessor returning the card number;
public int getPassword(): an accessor returning the card password;
public double getBalance(): an accessor returning the card balance;
public void setBalance(double bal): a mutator to set the card balance;
public double costPerMin(CallZone zone): returns the cost per minute of a call to the argument zone;
public int getLimit(CallZone zone): returns the maximum number of minutes that can be charged for a call to the argument zone given the card's balance (truncated down to the next integer);
public boolean charge(int minutes, CallZone zone): tries to charge a call to the given zone with the given number of minutes to the card; if the balance is sufficient to cover it, it returns true and if the balance is not sufficient, it leaves it unchanged and returns false (precondition: minutes must be positive);
public void deductWeeklyFee(): deducts the appropriate weekly fees from the card's balance, leaving it non-negative;
public String toString(): returns the string "card no no has a balance of X.XX".
The class should use the supplied CallZone.java class to represent call zones; it provides methods to convert strings representing the call zones to CallZone objects and to check if such strings are valid.
Once you have defined these classes, you should then complete the application that SuperPhoneCard Inc. will use to manage its business. This application is implemented by the SuperPhoneCardInc class, that reads and processes a number of commands from the standard input stream for processing cards and calls, outputing the results on the standard output stream. The commands are:
add no passwd: adds a card with the given number and password;
getBalance no passwd: prints the balance of card no if the password passwd is valid;
getLimit no passwd callZone: prints the maximum number of minutes that can be charged to card no for a call to callZone given the card's balance if the password passwd is valid and calls to callZone are allowed for this card (a callZone is either CANADA, USA, EUROPE, ASIA, ANZ, LATINAM, or AFRICA);
charge no passwd callZone minutes: charges card no for a call of minutes to callZone if the password passwd is valid and the balance is sufficient.
deductWeeklyFee: deducts the weekly fee from all cards;
printAll: prints the balance of all cards.
An incomplete definition for the SuperPhoneCardInc class is available here in SuperPhoneCardInc.java. You must fill out the missing parts of the definition, i.e. the code for handling the following commands:
getLimit no passwd callZone: if the command can be executed successfully, print "Result: card no limit for zone callZone is XX minutes", otherwise print error messages as follows: if the number of arguments or their type is wrong, print "Error: invalid arguments for getLimit command"; if the card does not exist, print "Error: card no no does not exist"; if the card's password is wrong, print "Error: password passwd incorrect";
charge no passwd callZone minutes: if the command can be executed successfully, print "Result: card no charged X.XX, new balance is Y.YY", otherwise print error messages as follows: if the number of arguments or their type is wrong, print "Error: invalid arguments for charge command"; if the card does not exists, print "Error: card no no does not exist"; if the card's password is wrong, print "Error: password passwd incorrect"; and if the card's balance is not sufficient to cover the call, print "Error: card no limit for zone callZone is XX minutes".
The SuperPhoneCardInc uses another class CardTable to manage a table of PhoneCards. An incomplete definition for the CardTable class is available here in CardTable.java. You must also fill out the missing parts of the definition of CardTable, i.e. the public PhoneCard get(long no) method that returns the first phone card in the table whose number matches the argument, or null if there is no card with this number.
Make sure your code compiles and runs on command line with JDK 6.0. Thoroughly test your program with assertion checking enabled, e.g. with java -ea SuperPhoneCardInc. Put all test cases in a file testsInput.txt and save your output in the file testsOutput.txt. Under Unix and Windows XP, you can do this by redirecting the standard input stream and standard output stream with the command:
java -ea SuperPhoneCardInc < testsInput.txt > testsOutput.txt
Comments should be written in JavaDoc format and the compiled documentation (using JavaDoc) should be included in the submission.
Submit a zipped archive with all your source code files, documentation, testsInput.txt and testsOutput.txt by the deadline as specified.
Marking Scheme
Style (variable naming, indentation, & Layout) _____/10
JavaDoc Comments _____/10
Code Compiles? _____(yes/no)
Successful execution of test cases _____/80
Total _____/100
According to this marking scheme the maximum mark you can get for code that does
not compile is 20/100.
public enum CallZone
{ CANADA, USA, EUROPE, ASIA, ANZ, LATINAM, AFRICA;
public static boolean isValidZone(String zone)
{ if(CANADA.toString().equals(zone) ||
USA.toString().equals(zone) ||
EUROPE.toString().equals(zone) ||
ASIA.toString().equals(zone) ||
ANZ.toString().equals(zone) ||
LATINAM.toString().equals(zone) ||
AFRICA.toString().equals(zone))
{ return true;
}
else
{ return false;
}
}
public static CallZone convertToZone(String zone)
{ if(CANADA.toString().equals(zone))
{ return CANADA;
}
else if(USA.toString().equals(zone))
{ return USA;
}
else if(EUROPE.toString().equals(zone))
{ return EUROPE;
}
else if(ASIA.toString().equals(zone))
{ return ASIA;
}
else if(ANZ.toString().equals(zone))
{ return ANZ;
}
else if(LATINAM.toString().equals(zone))
{ return LATINAM;
}
else
{ assert AFRICA.toString().equals(zone);
return AFRICA;
}
}
}
public class CardTable
{
// constructor methods
public CardTable()
{ ct = new PhoneCard[TABLE_LENGTH];
ctSize = 0;
current = 0;
}
// specialized methods
public boolean add(PhoneCard card)
{ if(ctSize == TABLE_LENGTH) return false;
if(get(card.getNumber()) !=null) return false;
ct[ctSize] = card;
ctSize++;
return true;
}
public PhoneCard get(long no)
{ for(int i = 0; i < ctSize; ++i) {
if(no == ct[i].getNumber())
return ct[i];
}
return null;
}
public PhoneCard first()
{ if(ctSize == 0)
{ return null;
}
else
{ current = 0;
return ct[current];
}
}
public PhoneCard next()
{ if(current + 1 == ctSize)
{ return null;
}
else
{ current++;
return ct[current];
}
}
// instance variables/attributes/fields
private PhoneCard[] ct;
private int ctSize;
private int current;
// class/static variables/attributes/fields
private static int TABLE_LENGTH = 20;
}
14 errors found:
File: /Volumes/Mac/a1/SuperPhoneCardInc.java [line: 58]
Error: /Volumes/Mac/a1/SuperPhoneCardInc.java:58: cannot find symbol
symbol : variable cardType
location: class SuperPhoneCardInc
File: /Volumes/Mac/a1/SuperPhoneCardInc.java [line: 71]
Error: /Volumes/Mac/a1/SuperPhoneCardInc.java:71: PhoneCard is abstract; cannot be instantiated
File: /Volumes/Mac/a1/SuperPhoneCardInc.java [line: 168]
Error: /Volumes/Mac/a1/SuperPhoneCardInc.java:168: cannot find symbol
symbol : class Phone
location: class SuperPhoneCardInc
File: /Volumes/Mac/a1/SuperPhoneCardInc.java [line: 170]
Error: /Volumes/Mac/a1/SuperPhoneCardInc.java:170: cannot find symbol
symbol : variable card
location: class SuperPhoneCardInc
File: /Volumes/Mac/a1/SuperPhoneCardInc.java [line: 173]
Error: /Volumes/Mac/a1/SuperPhoneCardInc.java:173: cannot find symbol
symbol : variable card
location: class SuperPhoneCardInc
File: /Volumes/Mac/a1/SuperPhoneCardInc.java [line: 180]
Error: /Volumes/Mac/a1/SuperPhoneCardInc.java:180: cannot find symbol
symbol : variable card
location: class SuperPhoneCardInc
File: /Volumes/Mac/a1/SuperPhoneCardInc.java [line: 184]
Error: /Volumes/Mac/a1/SuperPhoneCardInc.java:184: cannot find symbol
symbol : variable card
location: class SuperPhoneCardInc
File: /Volumes/Mac/a1/SuperPhoneCardInc.java [line: 214]
Error: /Volumes/Mac/a1/SuperPhoneCardInc.java:214: cannot find symbol
symbol : variable min
location: class SuperPhoneCardInc
File: /Volumes/Mac/a1/SuperPhoneCardInc.java [line: 238]
Error: /Volumes/Mac/a1/SuperPhoneCardInc.java:238: cannot find symbol
symbol : method allowed(java.lang.String)
location: class PhoneCard
File: /Volumes/Mac/a1/SuperPhoneCardInc.java [line: 241]
Error: /Volumes/Mac/a1/SuperPhoneCardInc.java:241: charge(int,CallZone) in PhoneCard cannot be applied to (int,java.lang.String)
File: /Volumes/Mac/a1/SuperPhoneCardInc.java [line: 243]
Error: /Volumes/Mac/a1/SuperPhoneCardInc.java:243: cannot find symbol
symbol : variable df
location: class SuperPhoneCardInc
File: /Volumes/Mac/a1/SuperPhoneCardInc.java [line: 243]
Error: /Volumes/Mac/a1/SuperPhoneCardInc.java:243: costPerMin(CallZone) in PhoneCard cannot be applied to (java.lang.String)
File: /Volumes/Mac/a1/SuperPhoneCardInc.java [line: 243]
Error: /Volumes/Mac/a1/SuperPhoneCardInc.java:243: cannot find symbol
symbol : variable df
location: class SuperPhoneCardInc
File: /Volumes/Mac/a1/SuperPhoneCardInc.java [line: 247]
Error: /Volumes/Mac/a1/SuperPhoneCardInc.java:247: getLimit(CallZone) in PhoneCard cannot be applied to (java.lang.String)
import java.text.DecimalFormat;
public abstract class PhoneCard{ // this is the main class
long number;
int password;
double balance;
public PhoneCard(long no, int passwd, double bal) { // a constructor (precondition: no and passwd must be positive)
number = no;
password = passwd;
balance = bal;
}
public long getNumber() { //an accessor returning the card number
return number;
}
public int getPassword() {// an accessor returning the card password
return password;
}
public double getBalance() {// an accessor returning the card balance
return balance;
}
public void setBalance(double bal) {// a mutator to set the card balance
balance = bal;
}
public double costPerMin(CallZone zone) {// returns the cost per minute of a call to the argument zone
}
public int getLimit(CallZone zone) {// returns the maximum number of minutes that can be charged for a call
return (int)(getBalance()/costPerMin(zone));
}
public boolean charge(int minutes, CallZone zone) { // tries to charge a call to the given zone with the given number of minutes to the card
double cst = costPerMin(zone)*minutes;
double diff = getBalance() - cst;
if (diff >= 0) {
setBalance(diff);
return true;
}else return false;
}
public void deductWeeklyFee() {// deducts the appropriate weekly fees from the card's balance, leaving it non-negative
}
public String toString() {// returns the string "card no no has a balance of X.XX".
DecimalFormat df = new DecimalFormat("0.00");
return "card no " + number + " has a balance of " + df.format(balance);
}
}
import java.util.Scanner;
public class SuperPhoneCardInc
{
public static void main(String[] args)
{
CardTable ct = new CardTable();
Scanner in = new Scanner(System.in);
String line = null;
boolean done = false;
if(!in.hasNextLine())
{
done = true;
}
else
{
line = in.nextLine();
}
if(!done && line.length() >= 4 && line.substring(0,4).equals("quit"))
{
done = true;
}
while(!done)
{
System.out.println("Input: " + line);
Scanner inl = new Scanner(line);
String command = "";
if(inl.hasNext())
{
command = inl.next();
}
if(command.equals("add"))
{
boolean invalidArgs = false;
long no = 0;
int passwd = 0;
if(inl.hasNextLong())
{
no = inl.nextLong();
}
else
{
invalidArgs = true;
}
if(!invalidArgs && inl.hasNextInt())
{
passwd = inl.nextInt();
}
else
{
invalidArgs = true;
}
if(!invalidArgs && inl.hasNext())
{
cardType = inl.next();
}
else
{
invalidArgs = true;
}
if(!invalidArgs && (no <= 0 || passwd <= 0))
{
invalidArgs = true;
}
PhoneCard card = null;
if(!invalidArgs)
{
card = new PhoneCard(no,passwd);
}
else
{
invalidArgs = true;
}
if(invalidArgs)
{
System.out.println("Error: invalid arguments for add command");
}
else if(ct.get(no) != null)
{
System.out.println("Error: card no " + no + " already exists");
}
else if(!ct.add(card))
{
System.out.println("Error: card table full");
}
else
{
System.out.println("Result: added card " + no);
}
}
else if(command.equals("getBalance"))
{
boolean invalidArgs = false;
long no = 0;
int passwd = 0;
if(inl.hasNextLong())
{
no = inl.nextLong();
}
else
{
invalidArgs = true;
}
if(!invalidArgs && inl.hasNextInt())
{
passwd = inl.nextInt();
}
else
{
invalidArgs = true;
}
if(!invalidArgs && (no <= 0 || passwd <= 0))
{
invalidArgs = true;
}
if(invalidArgs)
{
System.out.println("Error: invalid arguments for getBalance command");
}
else
{
PhoneCard card = ct.get(no);
if(card == null)
{
System.out.println("Error: card no " + no + " does not exist");
}
else if(card.getPassword() != passwd)
{
System.out.println("Error: password " + passwd + " incorrect");
}
else
{
System.out.printf("Result: card %d balance is %.2f%n",
no, card.getBalance());
}
}
}
else if(command.equals("getLimit"))
{ boolean invalidArgs=false;
long no= 0;
int passwd=0;
if(inl.hasNextLong())
{no = inl.nextLong();
}
else {
invalidArgs=true;
}
if (!invalidArgs && (no <= 0 || passwd <= 0))
{ invalidArgs = true;
}
String cardZone=null;
if(!invalidArgs && inl.hasNext())
{ cardZone = inl.next();
}
else
{ invalidArgs = true;
}
if(invalidArgs)
{ System.out.println("Error: invalid arguments for getLimit command");
}
else{
Phone card=ct.get(no);
}
if(card == null)
{ System.out.println("Error: card no " + no + " does not exist");
}
else if(card.getPassword() != passwd)
{ System.out.println("Error: password " + passwd + " incorrect");
}
else if (!CallZone.isValidZone(cardZone))
{
System.out.println("Error: invalid arguments for getLimit command");
}
else if (!card.allowed(cardZone))
{ System.out.println("Error: card " + no + " not allowed for zone " + cardZone);
}
else
{ System.out.println("Result: card " + no + " limit for zone " + cardZone + " is " + card.getLimit(cardZone) + " minutes");
}
}
else if(command.equals("charge"))
{ { boolean invalidArgs = false;
long no = 0;
int passwd = 0;
int minutes = 0;
if(inl.hasNextLong())
{ no = inl.nextLong();
}
else
{ invalidArgs = true;
}
if(!invalidArgs && inl.hasNextInt())
{ passwd = inl.nextInt();
}
else
{ invalidArgs = true;
}
String cardZone = null;
if(!invalidArgs && inl.hasNext())
{ cardZone = inl.next();
}
else
{ invalidArgs = true;
}
if(!invalidArgs && inl.hasNextInt())
{ min = inl.nextInt();
}
else
{ invalidArgs = true;
}
if(!invalidArgs && (no <= 0 || passwd <= 0 || minutes < 0))
{ invalidArgs = true;
}
if(invalidArgs)
{ System.out.println("Error: invalid arguments for charge command");
}
else
{
PhoneCard card = ct.get(no);
if(card == null)
{ System.out.println("Error: card no " + no + " does not exist");
}
else if(card.getPassword() != passwd)
{ System.out.println("Error: password " + passwd + " incorrect");
}
else if (!CallZone.isValidZone(cardZone))
{
System.out.println("Error: invalid arguments for charge command");
}
else if (!card.allowed(cardZone))
{ System.out.println("Error: card " + no + " not allowed for zone " + cardZone);
}
else if (card.charge(minutes, cardZone))
{
System.out.println("Result: card " + no + " charged " + df.format(card.costPerMin(cardZone)*minutes) +", new balance is " + df.format(card.getBalance()));
}
else
{
System.out.println("Error: card " + no + " limit for zone " + cardZone + " is "+ card.getLimit(cardZone) + " minutes");
}
}
}
}
else if(command.equals("deductWeeklyFee"))
{
PhoneCard card = ct.first();
while(card != null)
{
card.deductWeeklyFee();
System.out.printf("Result: card %d charged weekly fee%n",
card.getNumber());
card = ct.next();
}
System.out.println("Result: weekly fees deducted");
}
else if(command.equals("printAll"))
{
PhoneCard card = ct.first();
while(card != null)
{
System.out.printf("Result: %s%n", card);
card = ct.next();
}
System.out.println("Result: all cards printed");
}
else
{
System.out.println("Error: command invalid");
}
if(!in.hasNextLine())
{
done = true;
}
else
{
line = in.nextLine();
}
if(!done && line.length() >= 4 && line.substring(0,4).equals("quit"))
{
done = true;
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment