#!/usr/bin/perl
# $Id: make_nametags,v 1.1 2004/08/01 06:19:26 gwolf Exp $
# Copyright 2004 Gunnar Wolf <gwolf@gwolf.org>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
################################
# make_nametags - A simple script that takes the data needed for printing the
# nametags from a Comas database and arrange them in a TeX file.
#
# The produced TeX file was written based on the Debian GNU/Linux developer
# business card template (http://www.debian.org/~jgg/card.tex).

################################
# Depends on:
# IO::File - Supply object methods for filehandles
# Comas::DB - Handles the database connectivity for a Comas module
# Comas::Person - Handles the interaction with a person for Comas
use strict;
use IO::File;
use Comas::DB;
use Comas::Person;

=head1 NAME

make_nametags - Arranges the data from a Comas database to print the nametags

=head1 SYNOPSIS

This is a very simple script implementing a relatively flexible template for 
printing the nametags for a Comas-based conference.

The script does not present a user interface, does not even use parameters -
in order to configure it, modify the C<$page> hash reference in the code. The
following configuration keys are supported (and required):

=over 4

=item pg_height

The height of the region of the page to be used (in millimeters) 

=item pg_width

The width of the region of the page to be used (in millimeters) 

=item tags_horiz

The number of columns of nametags per page

=item tags_vert

The number of rows of nametags per page

=item div_lines

Whether to print lines between each of the nametags (useful for debugging when
playing with positions and such)

=item div_ticks

Whether to print alignation marks at the borders of the page, outside the 
printing area (and almost invisible dots inside the area at the crosspoints -
useful for cutting the printed pages)

=item put_logo

Whether to include the conference logo in each of the nametags. The logo should
be a Postscript file called C<logo.eps> in the directory where the .tex file
will be created (/tmp unless you modify this file).

=item conf_name

The name of the conference

=item conf_descr1

A short line of information to print next to the conference name (i.e. 
location, date, a slogan)

=item conf_descr2

A short line of information to print next to the conference name (i.e. 
location, date, a slogan)

=back

=head1 NOW WHAT?

This script will generate a C</tmp/nametags.tex> file. How can you use it?
Well, you must have the TeX typographical engine installed in your system.
You just have to run:

  latex /tmp/nametags.tex

and TeX will compile the generated script into a C<.dvi> (Device Independent) 
file. What can you do with a dvi? You can view it on screen (using C<xdvi> or
a similar tool), you can convert it to PostScript (using C<dvips>) or to
PDF (with C<dvipdf> or many similar tools) and print it.

=head1 WARNING - YOU ARE ON YOUR OWN

Outside this very brief introduction... Well, you are pretty much on your
own. You should be warned that the author of this script is not familiar at
all with TeX, it was used just because I had a sample file that was quite 
close to what I required. 

The script is quite primitive: No checking is made at all on bounding boxes,
the existence of the logo, the correctness of the generated TeX code or
anything else.

=cut

my ($db, $file, $page, @people, %countries);
$file = IO::File->new('/tmp/nametags.tex', 'w') or 
    die 'Could not open destination file';

# Configuration: $page hashref
$page = {pg_height => 256,
	 pg_width => 178,
	 tags_horiz => 2,
	 tags_vert => 5,
	 div_lines => 0,
	 div_ticks => 1,
	 put_logo => 0,
	 conf_name => 'XXV ICGTMP',
	 conf_descr1 => 'Cocoyoc, México',
	 conf_descr2 => 'Aug 2-6 2004'};

$db = Comas::DB->new or die "Could not create Comas::DB object";

%countries = $db->getCatalog('country');

# Get the sorted list of people. Store its relevant bits in @people.
for my $person (sort({$a->get_famname cmp $b->get_famname}
		     map({Comas::Person->new(-db=>$db, -id=>$_)} 
			 Comas::Person->search(-db=>$db)))) {
    push @people, [$person->get_firstname . ' ' . $person->get_famname,
		   $countries{$person->get_country_id}];
}

$file->print(prelude($page));
$file->print(scalar(@people). ' personas registradas\vfil\eject');
$file->print(arrange($page, \@people));
$file->print(finish($page));

exit 0;

sub prelude {
    # Generates the prelude (media type, base settings, simple macros) for the
    # TeX file
    my ($page, @ret);
    $page = shift;

    @ret = ('\documentclass[11pt]{article}
\usepackage[dvips]{graphicx}
%
\usepackage{times}
\usepackage[latin1]{inputenc}
\usepackage[spanish,activeacute]{babel}
%
\pagestyle{empty}
%
\setlength{\textwidth}{7in}
\setlength{\hoffset}{0in}
\setlength{\voffset}{0in}
\setlength{\oddsidemargin}{-.8in}
\setlength{\evensidemargin}{-.8in}
\setlength{\textheight}{10in}
\setlength{\topmargin}{-0.3in}
%
\newcommand{\logo}{\includegraphics{./logo.eps}}
%
\newcommand{\xtitle}{'.$page->{conf_name}.'}
\newcommand{\xplace}{'.$page->{conf_descr1}.'}
\newcommand{\xdates}{'.$page->{conf_descr2}.'}

\begin{document}
\setlength{\unitlength}{1mm}
');

    return join '',@ret;
}

sub newpage {
    # Draws the basic structure of a new page - The ticks and divisory lines
    # (if requested), the static text labels and logo.
    # We will see many times in this script the repetition of the same theme:
    # a '\put' followed by some numbers derived from the page (width|height),
    # the number of tags per (column|row), and the (horizontal|vertical) 
    # advancement. 
    my ($page, @ret);
    $page = shift;

    # Everything we do in this script is enclosed in a 'picture' element.
    push(@ret,
	 "\\begin{picture}($page->{pg_width},$page->{pg_height})(-7,-1)\n");
    if ($page->{div_ticks}) {
	push @ret, "\n\n% Ticks along the top and bottom\n";

	for my $horiz_adv (0..$page->{tags_horiz}) {
	    push(@ret, '\put(',
		 ($page->{pg_width}/$page->{tags_horiz})*$horiz_adv,
		 ',-1){\line(0,-1){10}}',"\n",'\put(',
		 ($page->{pg_width}/$page->{tags_horiz})*$horiz_adv,
		 ',',$page->{pg_height}+1,'){\line(0,1){10}}',"\n");
	}
	
	push @ret,"\n\n % Ticks on the sides\n";
	
	for my $vert_adv (0..$page->{tags_vert}) {
	    push(@ret, '\put(-1,',
		 ($page->{pg_height}/$page->{tags_vert})*$vert_adv,
		 '){\line(-1,0){10}}',"\n",'\put(',$page->{pg_width}+2,',',
		 ($page->{pg_height}/$page->{tags_vert})*$vert_adv,
		 '){\line(1,0){10}}',"\n");
	}

	push @ret,"\n\n % A dot where the nametags' boundaries meet\n";

	for my $vert_adv (0..$page->{tags_vert}) {
	    for my $horiz_adv (0..$page->{tags_horiz}) {
		push(@ret, '\put(',
		     ($page->{pg_width}/$page->{tags_horiz})*$horiz_adv,
		     ',',($page->{pg_height}/$page->{tags_vert})*$vert_adv,
		     '){\line(0,0){0.05}}',"\n");
	    }
	}
    }

    if ($page->{div_lines}) {
	push @ret,"\n\n % Division lines between each nametag\n";
	for my $horiz_adv (0..$page->{tags_horiz}) {
	    push(@ret, '\put(',
		 ($page->{pg_width}/$page->{tags_horiz})*$horiz_adv,
		 ',0){\line(0,1){',$page->{pg_height},'}}',"\n");
	}
	push @ret, "\n";
	for my $vert_adv (0..$page->{tags_vert}) {
	    push(@ret, '\put(0,',
		 ($page->{pg_height}/$page->{tags_vert})*$vert_adv,
		 '){\line(1,0){',$page->{pg_width},'}}',"\n");
	}
    }

    push @ret,"\n\n % Static text labels\n";
    for my $vert (1..$page->{tags_vert}) {
	for my $horiz (1..$page->{tags_horiz}) {
	    push(@ret, put_in_nametag($page, $horiz, $vert, .95, .17,
				      '\LARGE{\xtitle}'),
		 put_in_nametag($page, $horiz, $vert, .245, .12, 
				'\textsc{\scriptsize\xdates}'),
		 put_in_nametag($page, $horiz, $vert, .32, .17, 
				'\textsc{\scriptsize\xplace}'));

	    push(@ret, put_in_nametag($page, $horiz, $vert, .25, .9, '\logo'))
		if $page->{put_logo};
	}
    }

    return join '',@ret;
}

sub arrange {
    # Arranges the values we received in @people in the page, creates new pages
    # as needed.
    my ($page, $people, @ret, $tags_x_page, $column);
    $page = shift;
    $people = shift;
    push @ret, newpage($page);

    $tags_x_page = $page->{tags_horiz} * $page->{tags_vert};

    $column = 1;
    for my $tag_no (1..@$people) {
	if ($tag_no % $tags_x_page == 0) {
	    # Are we at a multiple of the number of tags per page? If so,
	    # create a new page.
	    push(@ret, '\end{picture}\eject', newpage($page));
	    $column = 1;
	} elsif ($tag_no % $page->{tags_vert} == 0) {
	    # Ok, maybe not a new page.. .But.. Are we at the end of the 
	    # column? If so, get a new one.
	    $column++;
	}
	push(@ret, put_in_nametag($page, $column, $tag_no%$page->{tags_vert}+1,
				  .95, .5, 
				  '\huge{'.$people->[$tag_no-1][0].'}'),
	     put_in_nametag($page, $column, $tag_no%$page->{tags_vert}+1,
			    .95, .85, '\Large{'.$people->[$tag_no-1][1].'}'));
    }

    return join '',@ret;
}

sub put_in_nametag {
    # Puts the specified text at the specified relative position in a nametag.
    # Receives as its parameterse the $page hashref, the column and row number
    # for which to generate the element, the location where to include the text
    # expressed as a fraction of 1 (0 being the lower-left corner, 1 being the 
    # top-right corner) and the text or command to set at this point.
    my ($page, $pos_x, $pos_y, $perc_x, $perc_y, $text);
    ($page, $pos_x, $pos_y, $perc_x, $perc_y, $text) = @_;

    return join('','\put(', 
		($page->{pg_width}/$page->{tags_horiz})*($pos_x-$perc_x),',',
		($page->{pg_height}/$page->{tags_vert})*($pos_y-$perc_y),'){',
		$text,"}\n");
}

sub finish {
    # Does whatever is needed to end the document
    return '\end{picture}\end{document}';
}

# $Log: make_nametags,v $
# Revision 1.1  2004/08/01 06:19:26  gwolf
# Moved the sample script 'generate_schedule' to examples/bin
# Created the sample script 'make_nametags' to create a TeX file with
# the conference assistants' nametags
#
