[Rt-devel] RT DEVELOPER CHALLENGE: TOWER OF HANOI
Jesse Vincent
jesse at bestpractical.com
Tue Oct 26 14:50:06 EDT 2004
I'm impressed :) You win. May I add this to the Wiki?
Best,
Jesse
On Oct 25, 2004, at 9:47 PM, Bron Gondwana wrote:
>
> On Sat, 23 Oct 2004 03:33:20 -0400, "Jesse Vincent"
> <jesse at bestpractical.com> said:
>> Perhaps it's the fault of the delicious bottle of Port that a
>> houseguest
>> brought me, but I've got a challenge for the RT community.
>>
>> The first person to develop and document a solution to the famed Tower
>> of Hanoi puzzle[1] using RT's Scrips system with queues modeling the
>> rods, tickets modeling the disks and ticket relationships modeling the
>> relative disk sizes will win a fabulous prize.[2]
>
> I've made a couple of them, but they suck for various reasons.
> Basically
> it's hard to make them sort correctly, because it takes forever if you
> put
> a 'sleep 1' in, but otherwise (at least with Mysql's dates) they don't
> sort
> properly.
>
> Anyway, here's one that's pretty chatty, but gets the moves in the
> correct
> order txn-wise.
>
> The Scrip:
> ===============================================================
>
> Condition: On Comment
>
> Action: User Defined
>
> Prepration Code: (<< __EOF__)
> my $comment = $self->TransactionObj->Content();
>
> if ($comment =~ m/move to ([A-Za-z0-9_ ]+)/) {
> my $new_queue_match = lc($1);
> $new_queue_match =~ s/^\s+//;
> $new_queue_match =~ s/\s+$//;
>
> my $user = $self->TransactionObj->CurrentUser();
> my $old_queue_id = $self->TicketObj->Queue();
>
> # Find a third queue to use as temporary space for this move.
> my $queues = RT::Queues->new($user);
> $queues->UnLimit();
> my $queue_items = $queues->ItemsArrayRef;
>
> my %queue_names;
> my $temp_queue_id;
> my $new_queue_id;
> foreach my $item (@$queue_items) {
> my $id = $item->id;
> my $name = $item->Name;
> my $matchname = lc($name);
> $matchname =~ s/^\s+//;
> $matchname =~ s/\s+$//;
> $queue_names{$id} = $name;
> if ($id == $old_queue_id) {
> # nothing to do
> } elsif ($new_queue_match eq $matchname) {
> $new_queue_id = $id;
> } elsif (!$temp_queue_id) {
> $temp_queue_id = $id;
> }
> }
>
> # make sure a move is actually required (the case of trying to move
> to
> where
> # we already are will leave this blank as well)
> return 0 unless $new_queue_id;
>
> # the next smaller disk is our member.
> my $members = $self->TicketObj->Members->ItemsArrayRef;
> if (@$members) {
> # make sure there's spare space to move this thing!
> return 0 unless $temp_queue_id;
> my $child_obj = RT::Ticket->new($user);
> $child_obj->Load($members->[0]->LocalBase);
> if ($child_obj->Queue != $temp_queue_id) {
> $child_obj->Comment(Content => "move to
> $queue_names{$temp_queue_id}");
> }
> $self->TicketObj->SetQueue($new_queue_id);
> $child_obj->Comment(Content => "move to
> $queue_names{$new_queue_id}");
> } else {
> # no children, just move ourselves!
> $self->TicketObj->SetQueue($new_queue_id);
> }
> return 1;
> }
>
> return 0;
> __EOF__
>
> Cleanup Code: return 1;
>
> Stage: TransactionCreate
>
> ===============================================================
>
> How to use:
>
> a) Have at least 3 queues available.
> b) Create tickets with a Parent/Child relationship (Parent is the
> larger
> disk)
> c) Create a comment on the largest disk "move to <name of another
> queue>".
>
> All the other disks will be moved as appropriate.
>
> NOTE: There is no concept of 'stacking' in RT queues, so the disks are
> assumed to
> be stacked correctly at the start since there's no way of detecting
> otherwise.
>
> The script won't move a disc until the immediately smaller disk is on
> the a third
> stack (not the source or destination of the first move) - and that
> propagates up
> to the top disk which has no children and hence can always move.
>
> I still think this solution is rather ugly, but it works.
>
> Bron.
> --
> Bron Gondwana
> brong at fastmail.fm
>
More information about the Rt-devel
mailing list