use Curses;
use Time::HiRes qw(usleep);

$win = new Curses;

# capture CTRL+C
$SIG{'INT'} = sub 
{
  $win->clear;
  $win->addstr(0, 0, "Exiting...!");
  $win->refresh;
  usleep(500 * 1000);
  endwin;
  exit;
};

while(1) 
{
  $win->clear; #clear screen

  $offset = print_header(0);
  
  # get nvidia-smi output as array of lines
  # get only lines with '%' characters
  @lines = grep {/%/} `nvidia-smi`;

  $numgpu = 0; # gpu counter 
	foreach $line (@lines)
	{
	  # extract fan usage, memory usage, and cpu usage to $+{fan, used, total, gpu}
    if($line =~ /(?<fan>\d+%).*?(?<used>\d+)MiB.*?(?<total>\d+)MiB.*?(?<gpu>\d+%)/)
    {
      # format output and print to screen
      $mem_pct = 100*($+{used}/$+{total});
      $mem_usage = sprintf "%4s / %4s (%.2d%) |", $+{used}, $+{total}, $mem_pct;
      $outline = sprintf("| %3s | %4s | %3s | %s ", $numgpu, $+{gpu}, $+{fan}, $mem_usage);
      $win->addstr($offset, 0, $outline);
      
      $numgpu++;
      $offset++;
    }
	}

  # write output ot screen and wait till next cycle
  $win->addstr($offset, 0, "|--------------------------------------|");
  $offset += 2;
  $win->addstr($offset, 0, "CTRL+C to exit");  
  $win->refresh;
	usleep(100 * 1000);
}

sub print_header($y)
{

  $win->addstr($y + 0, 0, "|--------------------------------------|");  
  $win->addstr($y + 1, 0, "|            nvidia-smi nano           |");
  $win->addstr($y + 2, 0, "|--------------------------------------|");
  $win->addstr($y + 3, 0, "| GPU | Core | Fan |   Memory (MiB)    |");
  
  return $y + 4; # next blank line
}

