package Competitor;

# Competitors have the following fields:
#     LNAME: last name
#     FNAME: first name
#     SCHOOL: the school.  Note that there is no difference between
# clicking on "MIT" and typing that in.
#     EMAIL: email address
#     EMAIL_EXISTS: this is a 1/0 flag, set if "No Email Address" is
# clicked on the starting page.
#     NUMBER: their competitor number
#     TBA: a 1/0 flag indicating if this Competitor object is a TBA placeholder

# FAST_COMPARE is obsolecent: it was an attempt to make comparing
# competitors faster, but didn't work.

################################################################

sub new {
  my $proto=shift;
  my $class=ref($proto) || $proto;
  my $self={};
  my($lname, $fname, $school, $email, $email_exists)=@_;

# Check last name integrity and throw out bad names.
  $_=$lname;
# We allow '-' and ',' for "Ismail-Beigi" and "Thomas Nugent, Jr"
  if (/[^a-zA-Z -,]/) {
    Error::BadNameSpecification($_);
  }
  if ($lname eq "") {
    Error::BlankNameSpecification(0);
  }

# Check first name integrity and throw out bad names.
  $_=$fname;
  if (/[^a-zA-Z ]/) {
    Error::BadNameSpecification($_);
  }
  if ($fname eq "") {
    Error::BlankNameSpecification(1);
  }

# Upshift the first letter of the last name, unless it's a compound
# name, like von Deck, in which case, we upshift the second word.
  if ($lname =~ /^(de|von|van)/) {
    $lname=~s/^(de|von|van) ([a-z])/$1 \u$2/;
  } else {
    $lname=~s/^([a-z])/\u$1/;
  }

# Upshift the first letter of the first name.
  $fname=~s/^([a-z])/\u$1/;

# Usernames need to be of the format aoeu@aoeu.aoeu.aoeu.aoeu.aoeu, etc
  if ($email_exists) {
    $_=$email;
    if (!(/\w+\@\w+\.(\w+\.*)/)) {
      Error::BadEmailAddress($email);
    }
  }

# Blank schools are bad.  No School Affiliation is a school.  :)
  if ($school eq "") {
    Error::BlankSchoolSpecification();
  }

  $self->{LNAME}=$lname;
  $self->{FNAME}=$fname;
  $self->{SCHOOL}=$school;
  $self->{EMAIL}=$email;
  $self->{EMAIL_EXISTS}=$email_exists;
  $self->{NUMBER}=-1;
  $self->{TBA}=0;

  $self->{FAST_COMPARE}=$lname;
#  $self->{F_PARTNERS}=null;
#  $self->{L_PARTNERS}=null;
  
  bless($self, $class);
  return($self);
} # new()

################################################################

sub newFromDB {
  # Use this to create a Competitor object by reading data from the
  # "database" flatfile.
  my $proto=shift;
  my $class=ref($proto) || $proto;
  my $IN=$_[0];
  my $self={};
  
  $_=<$IN>;  chop;
  $self->{LNAME}=$_;
  $self->{FAST_COMPARE}=$_;
  $_=<$IN>;  chop;
  $self->{FNAME}=$_;
  $_=<$IN>;  chop;
  $self->{SCHOOL}=$_;
  $_=<$IN>;  chop;
  $self->{EMAIL}=$_;
  $_=<$IN>;  chop;
  $self->{EMAIL_EXISTS}=$_;
  $_=<$IN>;  chop;
  $self->{NUMBER}=$_;
  $_=<$IN>;  chop;
  s/true/1/;
  s/false/0/;
  $self->{TBA}=$_;
  
  bless($self, $class);
  return($self);
} # newFromDB

################################################################

sub newTBA {
  # This creates a TBA (to be announced) Competitor: basically, a placeholder.
  my $proto=shift;
  my $class=ref($proto) || $proto;
  my $self={};
  
  $self->{LNAME}="TBA";
  $self->{FNAME}="";
  $self->{SCHOOL}="";
  $self->{EMAIL}="";
  $self->{EMAIL_EXISTS}=0;
  $self->{NUMBER}=-1;
  $self->{TBA}=1;
  $self->{FAST_COMPARE}="";
  
  bless($self, $class);
  return($self);
} # newTBA

################################################################

sub assemble_competitors {
  # Given a POST stream, read from it and assemble the two Competitors 
  # passed in.

  my $post_data_ref=$_[0];
# $post_data is an assoc array.

  my $leader;
  my $follower;
  my $email_exists;
  my $school;

  # leader
  # If they're TBA, then we create a TBA object and we're done.
  if ($$post_data_ref{"leaderTBA"} eq "true") {
#    logmsg("assemble_competitors: leader is TBA");
    $leader=Competitor->newTBA();
  } else {
  # If they're not a TBA, then first, see if an email field has been
  # specified.
    if ($$post_data_ref{"leader_email_exists"} eq "false") {
      $email_exists=0;
    } else {
      $email_exists=1;
    }
  # $school is the checkbox...
    $school=$$post_data_ref{"leader_school"};
  # ...so if the checkbox is blank, look at the Fill In The Blank field.
  # OK, create the leader object.
    if ($school eq "") {
      $leader=Competitor->new($$post_data_ref{"leader_lname"},
			      $$post_data_ref{"leader_fname"},
			      $$post_data_ref{"leader_otherschool"},
			      $$post_data_ref{"leader_email"},
			      $email_exists);
   } else {
      $leader=Competitor->new($$post_data_ref{"leader_lname"},
			      $$post_data_ref{"leader_fname"},
			      $school,
			      $$post_data_ref{"leader_email"},
			      $email_exists);
    }
  }

# Rinse wash lather...
  # follower
  if ($$post_data_ref{"followerTBA"} eq "true") {
    $follower=Competitor->newTBA();
  } else {
    if ($$post_data_ref{"follower_email_exists"} eq "false") {
      $email_exists=0;
    } else {
      $email_exists=1;
    }
    $school=$$post_data_ref{"follower_school"};
    if ($school eq "") {
      $follower=Competitor->new($$post_data_ref{"follower_lname"},
			      $$post_data_ref{"follower_fname"},
			      $$post_data_ref{"follower_otherschool"},
			      $$post_data_ref{"follower_email"},
			      $email_exists);
    } else {
      $follower=Competitor->new($$post_data_ref{"follower_lname"},
			      $$post_data_ref{"follower_fname"},
			      $school,
			      $$post_data_ref{"follower_email"},
			      $email_exists);
    }
  }

  # A couple can't be both a TBA leader and a TBA follower.
  if ($leader->isTBA() && $follower->isTBA()) {
    Error::TBA_Overspecification();
  }
  return($leader, $follower);
} # assemble_competitors

################################################################

sub assignNumber {
  # Argument: a number.  It gets plunked into this Competitor object.
  my $self=shift;
  my $number=$_[0];
  $self->{NUMBER}=$number;
  return($number);
} # assignNumber

################################################################

sub doesEmailExist {
  # returns 0 or 1.
  my $self=shift;
  return($self->{EMAIL_EXISTS});
} # doesEmailExist

################################################################

sub doesEmailExist2 {
  # returns a human-readable true/false
  my $self=shift;
  if ($self->{EMAIL_EXISTS}) {
    return("true");
  } else {
    return("false");
  }    
} # doesEmailExist2

################################################################

sub equals {
  # Two competitors are equal if they have the same LNAME, FNAME, and SCHOOL.
  # No, they don't need the same email: lots of people have multiple email
  # addresses.
  my $self=shift;
  my $that=$_[0];

  return (($self->{LNAME} eq $that->{LNAME}) and
	  ($self->{FNAME} eq $that->{FNAME}) and
	  ($self->{SCHOOL} eq $that->{SCHOOL}));
} # equals

################################################################

sub getEmail {
  my $self=shift;
  return($self->{EMAIL});
} # getEmail

################################################################

sub getName {
  my $self=shift;
  return($self->{FNAME}." ".$self->{LNAME});
} # getName

################################################################

sub getFName {
  my $self=shift;
  return($self->{FNAME});
} # getFName

################################################################

sub getLName {
  my $self=shift;
  return($self->{LNAME});
} # getLName

################################################################

sub getNumber {
  my $self=shift;
  return($self->{NUMBER});
} # getNumber

################################################################

sub getSchool {
  my $self=shift;
  return($self->{SCHOOL});
} # getSchool

################################################################

sub getSchoolAbbrev {
  # School labels might have an optional abbreviation at the end; e.g.,
  # Massachusetts Institute of Technology (MIT)
  # This returns that abbrev, or an error message.
  my $self=shift;
  $_=$self->{SCHOOL};
  if (/\(/) {
    ($crap, $_)=split('\(', $_);
    ($_, $crap)=split('\)', $_);
  } elsif ($_==-1) {
    return("<i>".Constants::get("HTML_MSG30")."</i>");
  }
  return($_);
} # getSchoolAbbrev

################################################################

sub getSortName {
  # Returns a string suitable for sorting: "LNAME FNAME SCHOOL".
  my $self=shift;
  return($self->{LNAME}." ".$self->{FNAME}." ".$self->{SCHOOL});
} # getSortName

################################################################

sub getTBA {
  # Returns human-readable format.  Use isTBA for 0 or 1.
  my $self=shift;
  if ($self->{TBA}) {
#    return(1);
    return("true");
  } else {
#    return(0);
    return("false");
  }
} # getTBA

################################################################

sub isTBA {
  # Returns 0 or 1.  Use getTBA for human-readable format.
  my $self=shift;
  return($self->{TBA});
} # isTBA

################################################################

sub write {
  # Of course, if you change this, you must change newFromDB.
  my $self=shift;
  my $LOG=$_[0];

  print $LOG $self->{LNAME}."\n";
  print $LOG $self->{FNAME}."\n";
  print $LOG $self->{SCHOOL}."\n";
  print $LOG $self->{EMAIL}."\n";
  print $LOG $self->{EMAIL_EXISTS}."\n";
  print $LOG $self->{NUMBER}."\n";
  print $LOG $self->{TBA}."\n";
} # write

1; # so require is happy.
