#define USE_STXXL
#include <stxxl.h>
#include <fstream>
#include <ctime>
#define CT_PER_MIN 2 // subscribers pay 2 cent per minute
struct LogEntry
{
long long int from;
long long int to;
int event;
};
std::istream& operator >> (std::istream& i, LogEntry& entry)
{
i >> entry.from;
i >> entry.to;
i >> entry.timestamp;
i >> entry.event;
return i;
}
std::ostream&
operator << (std::ostream& i,
const LogEntry& entry)
{
i << entry.from << " ";
i << entry.to << " ";
i << entry.timestamp << " ";
i << entry.event;
return i;
}
struct ProduceBill
{
std::ostream& out;
unsigned sum;
LogEntry last;
ProduceBill(std::ostream& o_) : out(o_), sum(0) { last.from = -1; }
void operator () (const LogEntry& e)
{
if (last.from == e.from)
{
assert((last.event == 1 && e.event == 2) ||
(last.event == 2 && e.event == 1));
if (e.event == 2)
sum += CT_PER_MIN * (unsigned int)(e.timestamp - last.timestamp) / 60;
}
else if (last.from != -1)
{
assert(last.event == 2);
assert(e.event == 1);
out << last.from << "; " << (sum / 100) << " EUR " << (sum % 100) <<
" ct" << std::endl;
sum = 0;
}
last = e;
}
};
struct SortByCaller
{
bool operator () (const LogEntry& a, const LogEntry& b) const
{
return a.from < b.from ||
(a.from == b.from && a.timestamp < b.timestamp) ||
(a.from == b.from && a.timestamp == b.timestamp &&
a.event < b.event);
}
static LogEntry min_value()
{
LogEntry dummy;
return dummy;
}
static LogEntry max_value()
{
LogEntry dummy;
return dummy;
}
};
void print_usage(const char* program)
{
std::cout << "Usage: " << program << " logfile main billfile" << std::endl;
std::cout << " logfile - file name of the input" << std::endl;
std::cout << " main - memory to use (in MiB)" << std::endl;
std::cout << " billfile - file name of the output" << std::endl;
}
#ifdef USE_STXXL
#else
typedef std::vector<LogEntry> vector_type;
#endif
int main(int argc, char* argv[])
{
if (argc < 4)
{
print_usage(argv[0]);
return 0;
}
std::fstream in(argv[1], std::ios::in);
vector_type v;
std::copy(std::istream_iterator<LogEntry>(in),
std::istream_iterator<LogEntry>(),
std::back_inserter(v));
#ifndef USE_STXXL
std::sort(v.begin(), v.end(), SortByCaller());
std::fstream out(argv[3], std::ios::out);
#else
const unsigned M = atol(argv[2]) * 1024 * 1024;
std::fstream out(argv[3], std::ios::out);
stxxl::for_each(v.begin(), v.end(), ProduceBill(out), M / vector_type::block_type::raw_size);
#endif
return 0;
}