public class CustomerAgent extends Agent {
private String name;
private int hungerLevel = 5; // Determines length of meal
private RestaurantGui gui;
private double money = 25;
private double bill = 0;
// ** Agent connections **
private HostAgent host;
private WaiterAgent waiter;
private CashierAgent cashier;
Restaurant restaurant;
private Menu menu;
Timer timer = new Timer();
GuiCustomer guiCustomer; //for gui
// ** Agent state **
private boolean isHungry = false; //hack for gui
public enum AgentState
{DoingNothing, WaitingInRestaurant, SeatedWithMenu, WaiterCalled, WaitingForFood, Eating, WaitingForBill, Paying};
//{NO_ACTION,NEED_SEATED,NEED_DECIDE,NEED_ORDER,NEED_EAT,NEED_LEAVE};
private AgentState state = AgentState.DoingNothing;//The start state
public enum AgentEvent
{gotHungry, beingSeated, decidedChoice, waiterToTakeOrder, foodDelivered, doneEating, BillDelivered,DonePaying };
private AgentEvent event;//Messages set the event
/** Constructor for CustomerAgent class
* @param name name of the customer
* @param gui reference to the gui so the customer can send it messages
*/
public CustomerAgent(String name, RestaurantGui gui, Restaurant restaurant) {
super();
this.gui = gui;
this.name = name;
this.restaurant = restaurant;
//this.cashier = cashier;
guiCustomer = new GuiCustomer(name.substring(0,2), new Color(0,255,0), restaurant);
}
public CustomerAgent(String name, Restaurant restaurant) {
super();
this.gui = null;
this.name = name;
this.restaurant = restaurant;
guiCustomer = new GuiCustomer(name.substring(0,1), new Color(0,255,0), restaurant);
}
// *** MESSAGES ***
/** Sent from GUI to set the customer as hungry */
public void setHungry() {
event = AgentEvent.gotHungry;
isHungry = true;
print("I'm hungry");
pickAndExecuteAnAction();//stateChanged();
}
/** Waiter sends this message so the customer knows to sit down
* @param waiter the waiter that sent the message
* @param menu a reference to a menu */
public void msgFollowMeToTable(WaiterAgent waiter, Menu menu) {
this.menu = menu;
this.waiter = waiter;
print("Received msgFollowMeToTable from" + waiter);
//state = AgentState.NEED_DECIDE;
event = AgentEvent.beingSeated;
pickAndExecuteAnAction();//stateChanged();
}
/** Waiter sends this message to take the customer's order */
public void msgDecided(){
event = AgentEvent.decidedChoice;
pickAndExecuteAnAction();//stateChanged();
}
/** Waiter sends this message to take the customer's order */
public void msgWhatWouldYouLike(){
event = AgentEvent.waiterToTakeOrder;
pickAndExecuteAnAction();//stateChanged();
}
/** Waiter sends this when the food is ready
* @param choice the food that is done cooking for the customer to eat */
public void msgHereIsYourFood(String choice) {
event = AgentEvent.foodDelivered;
pickAndExecuteAnAction(); //stateChanged();
}
/** Timer sends this when the customer has finished eating */
public void msgDoneEating() {
event = AgentEvent.doneEating;
pickAndExecuteAnAction(); //stateChanged();
}
/** Waiter sends this when the Bill is ready
*/
public void msgHereIsYourBill(WaiterAgent waiter, double price){
this.waiter = waiter;
event = AgentEvent.BillDelivered;
bill = price;
print("Price for the food is"+ bill);
pickAndExecuteAnAction();
}
/** Scheduler. Determine what action is called for, and do it. */
protected boolean pickAndExecuteAnAction() {
//Simple finite state machine
if (state == AgentState.DoingNothing){
if (event == AgentEvent.gotHungry) {
goingToRestaurant();
state = AgentState.WaitingInRestaurant;
return true;
}
// elseif (event == xxx) {}
}
if (state == AgentState.WaitingInRestaurant) {
if (event == AgentEvent.beingSeated) {
makeMenuChoice();
state = AgentState.SeatedWithMenu;
return true;
}
}
if (state == AgentState.SeatedWithMenu) {
if (event == AgentEvent.decidedChoice) {
callWaiter();
state = AgentState.WaiterCalled;
return true;
}
}
if (state == AgentState.WaiterCalled) {
if (event == AgentEvent.waiterToTakeOrder) {
orderFood();
state = AgentState.WaitingForFood;
return true;
}
}
if (state == AgentState.WaitingForFood) {
if (event == AgentEvent.foodDelivered) {
eatFood();
state = AgentState.Eating;
return true;
}
}
if (state == AgentState.Eating) {
if (event == AgentEvent.doneEating) {
askForBill();
state = AgentState.WaitingForBill;
return true;
}
}
if(state == AgentState.WaitingForBill)
{
if (event == AgentEvent.BillDelivered)
{
payBill();
print("Got here!");
state = AgentState.Paying;
return true;
}
}
if (state == AgentState.Paying)
{
if (event == AgentEvent.DonePaying)
{
leaveRestaurant();
state = AgentState.DoingNothing;
return true;
}
}
print("No scheduler rule fired, should not happen in FSM, event="+event+" state="+state);
return false;
}
// *** ACTIONS ***
/** Goes to the restaurant when the customer becomes hungry */
private void goingToRestaurant() {
print("Going to restaurant");
guiCustomer.appearInWaitingQueue();
host.msgIWantToEat(this);//send him our instance, so he can respond to us
stateChanged();
}
/** Starts a timer to simulate the customer thinking about the menu */
private void makeMenuChoice(){
print("Deciding menu choice...(3000 milliseconds)");
timer.schedule(new TimerTask() {
public void run() {
msgDecided();
}},
3000);//how long to wait before running task
stateChanged();
}
private void callWaiter(){
print("I decided!");
waiter.msgImReadyToOrder(this);
stateChanged();
}
/** Picks a random choice from the menu and sends it to the waiter */
private void orderFood(){
String choice = menu.choices[(int)(Math.random()*4)];
print("Ordering the " + choice);
waiter.msgHereIsMyChoice(this, choice);
stateChanged();
}
/** Starts a timer to simulate eating */
private void eatFood() {
print("Eating for " + hungerLevel*1000 + " milliseconds.");
timer.schedule(new TimerTask() {
public void run() {
msgDoneEating();
}},
getHungerLevel() * 1000);//how long to wait before running task
stateChanged();
}
/** When the customer is done eating, he leaves the restaurant */
private void leaveRestaurant() {
print("Leaving the restaurant");
guiCustomer.leave(); //for the animation
waiter.msgDoneEatingAndLeaving(this);
isHungry = false;
stateChanged();
gui.setCustomerEnabled(this); //Message to gui to enable hunger button
//hack to keep customer getting hungry. Only for non-gui customers
if (gui==null) becomeHungryInAWhile();//set a timer to make us hungry.
}
/** This starts a timer so the customer will become hungry again.
* This is a hack that is used when the GUI is not being used */
private void becomeHungryInAWhile() {
timer.schedule(new TimerTask() {
public void run() {
setHungry();
}},
15000);//how long to wait before running task
}
private void askForBill()
{
waiter.msgNeedBill(this);
print("Asking for BIll");
stateChanged();
}
private void payBill()
{
print("Do you Exist");
cashier.msgHereIsMyPayment(this);
stateChanged();
}
}
我的payBill
方法会在遇到cashier.msgHereIsMyPayment
时抓住意外异常。我不知道为什么会发生这种情况
答案 0 :(得分:3)
cashier
永远不会设置为任何值,因此它将为null
。
在null
引用上调用任何方法会产生NullPointerException
。
你要么需要在构造函数中接受Cashier
对象,并设置字段或自己创建一个。
答案 1 :(得分:1)
Cashier是一个私有成员变量,但我没有在你的构造函数中看到它。如果没有初始化,则它为空。
答案 2 :(得分:0)
收银员为空。我没有看到它被分配到任何地方。除非另行初始化,否则所有类字段(非基元)都设置为空。