// ATM Simulation Implementation - the Card ReaderATM Simulation Implementation - the Card Reader
/*
* Example ATM simulation - file CardReader.java
*
* This file implements the class that manages the ATM's Card Reader
*
* Copyright (c) 1997 - Russell C. Bjork
*
*/
package atm.atmparts;
import java.awt.*;
//
Class CardReader
public class CardReader extends Button
{
//
public CardReader()
{ super("Click to insert Card");
_status = NO_CARD;
_originalBounds = null; // Must get this after GUI is all laid out
}
//
public void ejectCard()
{ // Animate card coming out of machine
setLabel("Ejecting card");
Rectangle currentBounds =
new Rectangle(_originalBounds.x + _originalBounds.width / 2,
_originalBounds.y + _originalBounds.height / 2,
_originalBounds.width / _originalBounds.height, 1);
show();
while (currentBounds.height <= _originalBounds.height &&
currentBounds.width <= _originalBounds.width)
{ reshape(currentBounds.x, currentBounds.y,
currentBounds.width, currentBounds.height);
repaint();
try
{ Thread.sleep(100); }
catch (InterruptedException e)
{ }
currentBounds.height += 1;
currentBounds.width =
(_originalBounds.width * currentBounds.height) / _originalBounds.height;
currentBounds.x =
_originalBounds.x + (_originalBounds.width - currentBounds.width) / 2;
currentBounds.y =
_originalBounds.y + (_originalBounds.height - currentBounds.height) / 2;
}
hide();
_status = NO_CARD;
}
//
public void retainCard()
{ _status = NO_CARD;
try
{ Thread.sleep(10 * 1000); }
catch (InterruptedException e)
{ }
}
//
// These are the values that can be returned by checkForCardInserted()
public static final int NO_CARD = 0;
public static final int UNREADABLE_CARD = 1;
public static final int CARD_HAS_BEEN_READ = 2;
//
public synchronized int checkForCardInserted()
{
// Wait until user clicks the "Click To Insert Card" button, or operator
// Turns the machine off. (The timeout in the wait ensures that we will
// return periodically so that ATM can recheck the switch status.)
if (_originalBounds == null)
_originalBounds = bounds();
else
reshape(_originalBounds.x, _originalBounds.y,
_originalBounds.width, _originalBounds.height);
setLabel("Click to insert card");
show();
repaint();
requestFocus();
try
{ wait(1000); }
catch (InterruptedException e)
{ }
if (_status == NO_CARD) // This happens if we timeout
{ hide();
return NO_CARD;
}
// Animate card going into the machine
Rectangle currentBounds =
new Rectangle(_originalBounds.x, _originalBounds.y,
_originalBounds.width, _originalBounds.height);
while (currentBounds.width > 0 && currentBounds.height > 0)
{ reshape(currentBounds.x, currentBounds.y,
currentBounds.width, currentBounds.height);
repaint();
try
{ Thread.sleep(100); }
catch (InterruptedException e)
{ }
currentBounds.height -= 1;
currentBounds.width =
(_originalBounds.width * currentBounds.height) / _originalBounds.height;
currentBounds.x =
_originalBounds.x + (_originalBounds.width - currentBounds.width) / 2;
currentBounds.y =
_originalBounds.y + (_originalBounds.height - currentBounds.height) / 2;
}
hide();
// Since we don't have a magnetic stripe reader (or a literal card!),
// pop up a dialog and ask user to enter the card number.
QuestionDialog cardNumberDialog =
new QuestionDialog("Enter card number:", this);
String answer = cardNumberDialog.answer();
// Extract the number typed. Typing a non-number simulates an unreadable
// card.
if (answer == null)
_status = UNREADABLE_CARD;
else
{ try
{ _cardNumberRead = Integer.parseInt(answer);
_status = CARD_HAS_BEEN_READ;
}
catch (NumberFormatException e)
{ _status = UNREADABLE_CARD;
}
}
return _status;
}
//
public int cardNumber()
{ return _cardNumberRead;
}
//
// Instance variables
private int _status;
private int _cardNumberRead;
//
/* The following method and field are needed for the GUI */
public synchronized boolean action(Event e, Object arg)
{ if (e.target == this)
{ _status = CARD_HAS_BEEN_READ;
notify();
return true;
}
else
return false;
}
private Rectangle _originalBounds;
}
//