1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
|
package examples;
import java.util.Date;
import 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 testAuction {
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) = System.out.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();
}
}
|