home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power-Programmierung
/
CD1.mdf
/
magazine
/
drdobbs
/
1990
/
05
/
ayers
/
mrktsmlt.cls
< prev
next >
Wrap
Text File
|
1990-02-26
|
5KB
|
172 lines
Object subclass: #MarketSimulator
instanceVariableNames:
'running notify counters frame statusFrame totalCustomers startTime '
classVariableNames:
'MaxTime MaxCounters MinTime '
poolDictionaries: '' !
!MarketSimulator class methods !
new
MaxCounters := 3. MinTime := 1. MaxTime := 15.
^super new initialize.!
priority
^2.! !
!MarketSimulator methods !
elapsedTime
|time field offset|
time := Time now subtractTime:startTime.
field := 'ELAPSED TIME ', time printString.
offset := statusFrame center x
- ((SysFont stringWidth:field) // 2).
field displayAt:statusFrame origin + (offset @ 0).!
initialize
totalCustomers := 0.
running := false.!
newCustomer
|counter customer|
(counter := self shortestLine) isNil
ifFalse:[
customer := Customer new
counter:counter;
position:counter endOfLinePosition;
display;
start;
yourself.
totalCustomers := totalCustomers + 1.
('CUSTOMERS SERVED:', totalCustomers printString)
displayAt:statusFrame origin.
self send:#addCustomer to:counter with:customer].!
reframe:aFrame
|statusHeight w h maxCounters maxCustomers x y|
CursorManager execute change.
frame := aFrame.
statusHeight := SysFont height + 4.
statusFrame := aFrame origin + (2 @ 2)
extent:(aFrame width - 4) @ statusHeight.
w := CheckoutCounter width + Customer width + 2.
h := CheckoutCounter height + Customer height + 4.
maxCounters := ((aFrame width - Customer width) // w)
min:MaxCounters.
maxCustomers := ((aFrame height - statusHeight - h)
// Customer height)
min:CheckoutCounter maxCustomers.
x := aFrame origin x
+ ((aFrame width - (maxCounters * w)) // 2)
+ Customer width.
y := aFrame corner y - h.
CheckoutCounter maxCustomers:maxCustomers.
counters := Array new:maxCounters.
1 to:maxCounters do:[:i|
counters
at:i
put:(CheckoutCounter new
position:x @ y;
display;
yourself).
x := x + w].
CursorManager normal change.!
release
1 to:counters size do:[:i|
(counters at:i) release.
counters at:i put:nil].
counters release.
counters := nil.
notify := nil.
super release.!
run
self newCustomer.
[running]
whileTrue:[
self sleep:(RandomNumber from:MinTime to:MaxTime).
running ifTrue:[self newCustomer]].
self shutdown.
(notify isKindOf:Semaphore)
ifTrue:[notify signal].!
running
^running.!
send:aMessage to:anObject
self send:aMessage to:anObject with:nil.!
send:aMessage to:anObject with:anArgument
|queue|
(queue := anObject messageQueue) isNil
ifFalse:[
queue send:aMessage.
anArgument isNil ifFalse:[queue send:anArgument]].
Processor yield.!
shortestLine
|fewest length shortest|
fewest := 9999.
1 to:counters size do:[:i|
(length := (counters at:i) length) < fewest
ifTrue:[
fewest := length.
shortest := i]].
fewest < CheckoutCounter maxCustomers
ifTrue:[^counters at:shortest]
ifFalse:[^nil].!
shutdown
|semaphore|
semaphore := Semaphore new.
counters do:[:aCounter|
aCounter isNil
ifFalse:[
aCounter stop:semaphore.
semaphore wait]].!
sleep:numberOfSeconds
|timeout lastTime time|
timeout := Time now asSeconds + numberOfSeconds.
lastTime := 0.
[running and:[(time := Time now asSeconds) < timeout]]
whileTrue:[
time = lastTime
ifFalse:[
self
timeRemaining:(timeout - time);
elapsedTime.
lastTime := time].
Processor yield].!
start
counters do:[:aCounter|
aCounter isNil ifFalse:[aCounter start]].
running
ifFalse:[
startTime := Time now.
running := true.
[self run] forkAt:self class priority].!
stop:notifySemaphore
running
ifTrue:[
notify := notifySemaphore.
running := false]
ifFalse:[
self shutdown.
notifySemaphore signal].!
timeRemaining:seconds
|fieldWidth field offset|
fieldWidth := 3.
field := 'NEXT CUSTOMER:',
(seconds printString flushedRightIn:fieldWidth).
offset := statusFrame width
- (SysFont stringWidth:field).
field displayAt:statusFrame origin + (offset @ 0).! !