
Planner variableSubclass: #Blocks
  instanceVariableNames: 
    'position animator number between replyStream selectedChoice '
  classVariableNames: ''
  poolDictionaries: '' !

!Blocks class logicMethods !

example1
" Blocks example1 "
| block selectedChoice|
block :=  Blocks new.
selectedChoice := #blocks1.
block doBlocks.
block inspect.! !


!Blocks logicMethods !

add: block1 onBlock: block2
"add one block on top of block2"
|ordColl index col size|
index := 1.
col := 0.
[index <= number
    and: [col = 0] ]
    whileTrue: [
        ((position at: index) includes: block2)
        ifTrue: [col:=index].
    index := index+1].
ordColl := position at: col.
ordColl add: block1.
size := ordColl size.
position at: col
        put: ordColl.
animator tell: block1
        place: ((between * col) - (between * 2/3)) @
                ((RectPict extent y - 5) - (60 * size * Aspect) truncated).!

add: block onTable: col
"reinitialize colunm add first block to it"
|ordColl|
ordColl := position at: col.
ordColl add: block.
position at: col
        put: ordColl.
animator tell: block
    place: ((between * col)-(between * 2/3)) @
           ((RectPict extent y - 5) - (60*Aspect)truncated)!

assign: size
"assign a variable number"
number := size!

choice: aSymbol
"Private change to the selected choise type"
selectedChoice := aSymbol. "blocks1,block2,block3"
self changed: #input;
     changed: #reply;
     changed: #graph:!

choices
"Private answer an array of choices"
^#( blocks1 blocks2 blocks3 )!

doBlocks
"actual call to Prolog methods"
CursorManager execute change.
selectedChoice == #blocks1
    ifTrue:[self :? blocks1()].
selectedChoice == #blocks2
    ifTrue:[self :? blocks2()].
selectedChoice == #blocks3
    ifTrue:[self :? blocks3()].
CursorManager normal change!

doBlocksMenu
^Menu
    labels: 'do\help\inspect\stop' withCrs
    lines: #()
    selectors: #(doBlocks help inspect stop)!

finish
    Menu message: 'The solution is found'!

graph: aRect
"initialize graph pane assign global variables"
| aForm |
aForm := Form width: aRect width height: aRect height.
aForm displayAt: aRect origin.
RectPict := aRect.
White := (Form width: 60
    height: (60 * Aspect) truncated ).
^aForm!

help
"provide help messages"
selectedChoice == #blocks1
    ifTrue:[replyStream nextPutAll:
'EXPLANATION: This is an animation of the 3 block problem'; cr ].
selectedChoice == #blocks2
    ifTrue:[replyStream nextPutAll:
'EXPLANATION: This is an animation of the 3 block problem'; cr ].
selectedChoice == #blocks3
    ifTrue:[replyStream nextPutAll:
'EXPLANATION: This is an animation of the 4 block problem'; cr ].!

initAnimation
"initialize Animation"
| blockImages |
blockImages := Array with: White.
animator := Animation new
    initialize: RectPict.
animator add: blockImages
    name: 'Black'
    color: #black.
animator add: blockImages
    name: 'LightGray'
    color: #lightGray.
animator add: blockImages
    name: 'Gray'
    color: #gray.
selectedChoice == #blocks3
    ifTrue:[animator add: blockImages
    name: 'DarkGray'
    color: #darkGray].
animator setBackground;
    speed: 8;
    shiftRate: 10.!

initialize1
"initialize blocks"
| pen |
"draw bottom"
pen := Pen new.
pen defaultNib: 3@2.
pen place:(RectPict origin x + 5) @ (RectPict corner y - 5);
    goto: (RectPict corner x - 5) @ (RectPict corner y - 5).
between := RectPict width // number.
"initialize animation and position"
self initAnimation;
     initPosition!

initPosition
"Set the receiver's initial position"
position := Array new: number.
1 to: number do:[:index |  position at: index
                            put: OrderedCollection new]!

input
"Private answer the input text for the selectedChoice"
| text1 text2 text3 text|
text1 := 'FROM: A on B, B on Table, C on Table
TO:  A on B, B on C, C on Table
     (COLORS A-Black B-LightGray C-Gray)'.
text2 := 'FROM: A on Table, B on Table, C on A
TO:  A on B, B on C, C on Table
     (COLORS A-Black B-LightGray C-Gray)'.
text3 := 'FROM: A on B, B on Table, C on Table, D on A
TO:  A on D, B on C, C on Table, D on B
     (COLORS A-Black B-LightGray C-Gray D-DarkGray)'.
selectedChoice == #blocks1
    ifTrue: [text := text1].
selectedChoice == #blocks2
    ifTrue: [text := text2].
selectedChoice == #blocks3
    ifTrue: [text := text3].
^text!

openOn
"Create a window on Blocks
Define the type, behavior and relative size of
each pane and schedule the window"
| topPane replyPane |
topPane := TopPane new label: ' B L O C K S'.
topPane addSubpane:
    (ListPane new
        model: self;
        name: #choices;
        change: #choice:;
        selection: 1;
        framingRatio: (0@0 extent: 1/4 @ (1/6))).
selectedChoice := #blocks1.
topPane addSubpane:
    (TextPane new
        model: self;
        name: #input;
        menu: #doBlocksMenu;
        framingRatio: (1/4 @ 0 extent: 3/4 @(1/6))).
topPane addSubpane:
    (replyPane := TextPane new
        model: self;
        name: #reply;
        framingRatio: (0@ (1/6) extent: 1 @ (1/6))).
topPane addSubpane:
    (GraphPane new
        model: self;
        name: #graph:;
        framingRatio:( 0 @ (1/3) extent: 1 @ (2/3))).
topPane reframe:
    (Display boundingBox insetBy: 10@10).
replyStream := replyPane dispatcher.
topPane dispatcher openWindow scheduleWindow!

remove: block
"remove block from data structure"
| ordColl index col |
index := 1.
col := 0.
[index <= number & (col = 0)]
    whileTrue: [((position at: index) includes: block)
    ifTrue: [col := index].
    index := index + 1].
ordColl := position at: col.
ordColl removeLast.
position at: col put: ordColl.!

reply
"initiate reply pane with an empty string"
^String new.!

stop
"generate a self halt"
self halt.! !
