// -*-c++-*-
// $Id: Types.hh 201 2007-07-02 14:34:18Z dflater $

#ifndef Types_HH
#define Types_HH

#include <stdint.h>
#include <string>
#include <iostream>
#include <sstream>
#include <map>
#include <vector>
#define WANT_OBFUSCATING_OPERATORS
#include <cln/cln.h>

typedef char const * const constString;

typedef long contestId_t;
typedef long choiceId_t;
typedef long ballotId_t;
typedef long styleId_t;

// An unlimited precision rational type is ideal to support ranked
// order voting with transfer of fractional votes.  As a fringe
// benefit, normal integral tallies cannot overflow.
typedef cln::cl_RA tally_t;

struct Tally {
  choiceId_t  choiceId;
  tally_t     tally;
};

struct BallotCount {
  std::string  description;
  long         read;
  long         counted;
};

struct StyleBallotCount {
  styleId_t    styleId;
  std::string  styleName;
  long         read;
  long         counted;
};

struct ContestStruct {
  contestId_t  contestId;
  std::string  contestDescription;
  long         N;
};

typedef std::vector<ContestStruct>              ContestStructVector;
typedef std::map<const choiceId_t, std::string> ChoiceDescriptionMap;
typedef std::vector<Tally>                      TallyVector;
typedef std::vector<BallotCount>                BallotCountVector;
typedef std::vector<StyleBallotCount>           StyleBallotCountVector;

// The input of one voter in one ranked order contest is represented
// as a vector of choices ordered by decreasing preference.  This
// representation is insufficient for ranked order variants in which
// two or more candidates may be assigned the same rank.
typedef std::vector<choiceId_t> RankedOrderVote;

// When surplus votes are transferred, proportionality is maintained
// by applying a scaling factor.
typedef cln::cl_RA scale_t;
struct ScaledRankedOrderVote {
  RankedOrderVote vote;
  scale_t         scale;
};

// A vector of ScaledRankedOrderVotes would suffice, but it simplifies
// construction if we can look up by ballot ID.
typedef std::map<const ballotId_t, ScaledRankedOrderVote> ScaledROVoteMap;


// Some templated output operators.

template<class charT, class traits> std::basic_ostream<charT, traits> &operator<< (std::basic_ostream<charT, traits> &out, const RankedOrderVote &v) {
  for (RankedOrderVote::const_iterator it (v.begin());
       it != v.end();
       ++it) {
    if (it != v.begin())
      out << " ";
    out << *it;
  }
  return out;
}


template<class charT, class traits> std::basic_ostream<charT, traits> &operator<< (std::basic_ostream<charT, traits> &out, const ScaledRankedOrderVote &v) {
  out << v.scale << " times " << v.vote;
  return out;
}


template<class charT, class traits> std::basic_ostream<charT, traits> &operator<< (std::basic_ostream<charT, traits> &out, const ScaledROVoteMap &v) {
  for (ScaledROVoteMap::const_iterator it (v.begin());
       it != v.end();
       ++it)
    out << "  " << it->second << std::endl;
  return out;
}

#endif
