in reply to ASCII chart that displays jobs that are running and jobs that are queued for a day

This doesn't solve your configurable time slice problem, but it doesn't limit it either. Just change time_bin for that. I got you started so you just have to take it the rest of the way. Good luck :)

The first part of your program needs to digest the data and store it in a way in which you can conveniently access it. Since you want dates, then hours, then queues, I'd use a multi-level hash with the keys in that order. The Perl Data Structures Cookbook perldsc has some good examples.

#!/usr/bin/perl use strict; my %hash; while( <DATA> ) { chomp; my( $name, @times ) = split; # convert each time to [ date, time bin ] @times = map { [ date($_), time_bin( $_ ) ] } @times; =pod The multi-level hash looks like this: $hash{ date }{ time bin }{ queue name }{'running'} {'queued'} Look at it with: use Data::Dumper; print Dumper( \%hash ); =cut # count the bin it was queued, even if it runs in that bin $hash{ $times[0][0] }{ $times[0][1] }{ $name }{'queued'}++; # count the bin it starts running $hash{ $times[1][0] }{ $times[1][1] }{ $name }{'running'}++; # count the bin it ended, unless it's the same bin it started # might want to check that it starts and ends on the same date too $hash{ $times[2][0] }{ $times[2][1] }{ $name }{'running'}++ if $times[1][1] ne $times[2][1]; }

Once you have the data structure, you go through it level by level and print things however you like at the last level:

{ DATE: foreach my $date ( sort keys %hash ) { print_header( $date ); my $hour_hash = $hash{ $date }; HOUR: foreach my $hour ( sort { $a <=> $b } keys %$hour_hash ) { my $queue_hash = $hour_hash->{$hour}; my $string = ''; QUEUE: foreach my $queue ( sort keys %$queue_hash ) { $string .= sprintf " %6s %4d %4d\n", $queue, $queue_hash->{$queue}{'queued'}, $queue_hash->{$queue}{'running'}; } # add the hour last to avoid a special case substr( $string, 0, 5 ) = $hour; print $string, "-" x 54, "\n"; } } }

Finally, the utility subroutines which you can adjust to taste:

sub time_bin { # this just assumes an hour, such as 19. # adjust for whatever time bin you'd like to use sprintf "%02d:00", (localtime( $_[0] ) )[2]; } sub date { my @times = localtime( $_[0] ); $times[5] += 1900; $times[4] += 1; # join on / and make two digits for easy sorting return join "/", map { sprintf "%02d", $_ } @times[3,4,5]; } sub print_header { print <<"HERE"; Date: $_[0] Time Queue Queued Running ------------------------------------------------------ HERE }

For your input data, my script gives this output. If you want to show all of the hours and all of the queues even if they have nothing running, you just have to adjust the looping through the values. Instead of looping through only what's defined (foreach my $queue ( sort keys %$queue_hash )), loop through all of the possible values (foreach my $queue ( @queue_names )). With a bit more trickery, pagination is easy to add, too.

Date: 23/10/2006 Time Queue Queued Running ------------------------------------------------------ 08:00 queuea 1 0 ------------------------------------------------------ 09:00 queuea 0 1 queueb 1 0 ------------------------------------------------------ 11:00 queuec 1 1 queued 1 1 ------------------------------------------------------ 13:00 queuea 1 0 queueb 2 2 queued 1 0 ------------------------------------------------------ 14:00 queuea 1 1 queuec 1 1 ------------------------------------------------------ 15:00 queuea 1 1 queueb 5 5 queuec 1 1 ------------------------------------------------------ 16:00 queuea 1 0 queueb 2 2 queued 5 5 ------------------------------------------------------ 17:00 queued 3 3 ------------------------------------------------------ 18:00 queuea 0 1 ------------------------------------------------------ 19:00 queuea 0 1 queueb 0 2 queued 0 4 ------------------------------------------------------ 20:00 queueb 0 5 queuec 0 1 queued 0 5 ------------------------------------------------------ 21:00 queuea 0 2 queueb 0 3 queuec 0 1 ------------------------------------------------------ 23:00 queued 0 1 ------------------------------------------------------ Date: 24/10/2006 Time Queue Queued Running ----------------------------------------------------- 01:00 queuea 0 1 queuec 0 1 ------------------------------------------------------ 02:00 queueb 0 1 ------------------------------------------------------ 10:00 queuea 0 1 ------------------------------------------------------
  • Comment on Re: ASCII chart that displays jobs that are running and jobs that are queued for a day
  • Select or Download Code

Replies are listed 'Best First'.
Re^2: ASCII chart that displays jobs that are running and jobs that are queued for a day
by Cristoforo (Curate) on Nov 15, 2006 at 20:46 UTC
    I reworked your code to allow for any time periods (15mins, 30mins, 60mins, ...)

    Chris

    #!/usr/bin/perl use strict; use warnings; use Data::Dumper; my $interval = shift || 60; my %hash; while( <DATA> ) { my( $name, @times ) = split; # convert the 3 times into their time slot. # (eg) if the interval is 60 minutes (1 hour) # a queued time of 9:26 would be converted to 9:00. $_ -= $_ % ($interval * 60) for @times; for (my $slot = $times[0]; $slot < $times[1]; $slot += $interval * + 60) { $hash{ date($slot) }{ time_bin($slot) }{ $name }{queued}++; } for (my $slot = $times[1]; $slot < $times[2]; $slot += $interval * + 60) { $hash{ date($slot) }{ time_bin($slot) }{ $name }{running}++; } } { DATE: foreach my $date ( sort keys %hash ) { print_header( $date ); my $hour_hash = $hash{ $date }; HOUR: foreach my $hour ( sort keys %$hour_hash ) { my $queue_hash = $hour_hash->{$hour}; my $string = ''; QUEUE: foreach my $queue ( sort keys %$queue_hash ) { $string .= sprintf " %6s %4d %4d\n", $queue, $queue_hash->{$queue}{'queued'}||0, $queue_hash->{$queue}{'running'}||0; } # add the hour last to avoid a special case substr( $string, 0, 5 ) = $hour; print $string, "-" x 54, "\n"; } } } sub time_bin { sprintf "%02d:%02d", (localtime( $_[0] ) )[2,1]; } sub date { my @times = localtime( $_[0] ); $times[5] += 1900; $times[4] += 1; # join on / and make two digits for easy sorting return join "/", map { sprintf "%02d", $_ } @times[3,4,5]; } sub print_header { print <<"HERE"; Date: $_[0] Time Queue Queued Running ------------------------------------------------------ HERE }
Re^2: ASCII chart that displays jobs that are running and jobs that are queued for a day
by wishartz (Beadle) on Oct 27, 2006 at 11:05 UTC
    Thank you so much, that is just what I need.
      Hi monks, I've been trying to understand the program in the above post, but there is a part that I just cannot understand. I can see that the program works, I just don't know how. I cannot figure out how it knows when the queue is running a job, or queueing a job. I thought I would need to put some 'if statements' in there somewhere, otherwise how does it know, without conditionals. Please excuse my ignorance, i'm new to programming and perl and trying to understand, how this works. Could somebody try and explain to me how the hashes are being built with the correct information because to me, it looks like the times are not being compared so how does it know. Thanks.
        I know how it works now hooray and feel like a bit of an idiot, for not noticing it straight away. Oh well, part of the learning process, I suppose.
        It's marking the time 'bin' it entered the queue as queued and marking the 'bin' it started running as running, Also markes the 'bin' it stopped running as running if its not the same 'bin' as the one it started running in.

        I read the problem differently. Do you want the number of jobs that are still waiting in the queue (at the end of the time slot) and the number of jobs that haven't finished yet (also at the end of the time slot)?

        Chris