Bron Gondwana brong at fastmail.fm
Mon Oct 25 21:47:24 EDT 2004

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. 
it's hard to make them sort correctly, because it takes forever if you
a 'sleep 1' in, but otherwise (at least with Mysql's dates) they don't

Anyway, here's one that's pretty chatty, but gets the moves in the
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);
  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
  # 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);
    if ($child_obj->Queue != $temp_queue_id) {
      $child_obj->Comment(Content => "move to
    $child_obj->Comment(Content => "move to
  } else {
    # no children, just move ourselves!
  return 1;

return 0;

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
c) Create a comment on the largest disk "move to <name of another

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

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 Gondwana
  brong at fastmail.fm

More information about the Rt-devel mailing list