summaryrefslogblamecommitdiff
path: root/sources/examples/auction.scala
blob: c6ab223375ea9bbd5a2e27120a44c8ace6622031 (plain) (tree)
1
2
3
4
5
6
7
8
9




                          



                                                                        

                     
                                                                   



                                                                       


                                                                                   
                                                                          

                                                                            
 
                                                                        
 
                                       
                        
 
                        
                                       
                                
                       
 
                     

                                                                

                                             

                                              

                               
                                   
                  

                                           

                               
                                             
 
                         


                                                            
                             
                  
                                       

                                         

                                                              
           
 



       
 
                                                                          
 
                












                                                            
                                                              















































                                                       
package examples;

import java.util.Date;
import scala.concurrent._;

/** A simple demonstrator program implementing an online auction service
 *  The example uses the actor abstraction defined in the API of
 *  package scala.concurrent.
 */
trait AuctionMessage;
case class
  Offer(bid: int, client: Actor),                     // make a bid
  Inquire(client: Actor) extends AuctionMessage;      // inquire status

trait AuctionReply;
case class
  Status(asked: int, expiration: Date),               // asked sum, expiration date
  BestOffer(),                                        // yours is the best offer
  BeatenOffer(maxBid: int),                           // offer beaten by maxBid
  AuctionConcluded(seller: Actor, client: Actor),     // auction concluded
  AuctionFailed(),                                    // failed with no bids
  AuctionOver() extends AuctionReply;                 // bidding is closed

class Auction(seller: Actor, minBid: int, closing: Date) extends Actor {

  val timeToShutdown = 3600000; // msec
  val bidIncrement = 10;

  override def run() = {
    var maxBid = minBid - bidIncrement;
    var maxBidder: Actor = null;
    var running = true;

    while (running) {
      receiveWithin (closing.getTime() - new Date().getTime()) {

	case Offer(bid, client) =>
	  if (bid >= maxBid + bidIncrement) {
            if (maxBid >= minBid)
	      maxBidder send BeatenOffer(bid);
            maxBid = bid;
            maxBidder = client;
            client send BestOffer()
          } else {
            client send BeatenOffer(maxBid)
	  }

	case Inquire(client) =>
	  client send Status(maxBid, closing)

	case TIMEOUT() =>
	  if (maxBid >= minBid) {
	    val reply = AuctionConcluded(seller, maxBidder);
	    maxBidder send reply;
	    seller send reply
	  } else {
	    seller send AuctionFailed()
          }
          receiveWithin(timeToShutdown) {
            case Offer(_, client) => client send AuctionOver()
            case TIMEOUT() => running = false
          }

      }
    }
  }
}

// ---- Test -------------------------------------------------------------

object auction {

  val random = new java.util.Random();

  val minBid = 100;
  val closing = new Date(new Date().getTime() + 60000);

  val seller = new Actor {
    override def run() = {}
  }
  val auction = new Auction(seller, minBid, closing);

  def client(i: int, increment: int, top: int) = new Actor {
    val name = "Client " + i;
    def log(msg: String) = Console.println(name + ": " + msg);
    var running = true;
    var max: int = _;
    var current: int = 0;
    override def run() = {
      log("started");
      auction send Inquire(this);
      receive {
	case Status(maxBid, _) => {
	  log("status(" + maxBid + ")");
	  max = maxBid
	}
      }
      while (running)  {
	if (max >= top)
	  log("too high for me")
	else if (current < max) {
	  current = max + increment;
	  Thread.sleep(1 + random.nextInt(1000));
	  auction send Offer(current, this);
	}
	receive {
	  case BestOffer() => {
	    log("bestOffer(" + current + ")");
	  }
	  case BeatenOffer(maxBid) => {
	    log("beatenOffer(" + maxBid + ")");
	    max = maxBid;
	  }
	  case AuctionConcluded(seller, maxBidder) => {
	    log("auctionConcluded");
	  }
	  case AuctionOver() => {
	    running = false;
	    log("auctionOver");
	  }
	}
      }
    }
  }

  def main(args: Array[String]) = {
    seller.start();
    auction.start();
    client(1, 20, 200).start();
    client(2, 10, 300).start();
  }

}