#include #include #include #include #include #include #include #include #include #include #include #include "linecount.h" #include "relations.h" #include "readlog.h" #include "output.h" void usagemsg() { std::cerr << "Usage: cspy [OPTION]..." << std::endl; std::cerr << "Generate a graph file in graphviz's dot format from an irclog." << std::endl; std::cerr << "Logfile format: 1970-01-01T00:00:00 < Foobar> Hello world!" << std::endl; std::cerr << " -c Analyze context, that is, try also to determine answers without" << std::endl; std::cerr << " hilights. By default do not." << std::endl; std::cerr << " -f file Read the log from file. Otherwise, read from stdin." << std::endl; std::cerr << " -l length Maximum length of edges, in inches. Default is 10." << std::endl; std::cerr << " -n nickcount Include N most spoken nicks in the relation search. The actual" << std::endl; std::cerr << " number of nicks in the graph may be lower. Default is 15." << std::endl;; std::cerr << " -t treshold Set the treshold factor for including connections in the graph as" << std::endl; std::cerr << " a multiplier of average strength. Default is 1.5." << std::endl; std::cerr << " -T title Set the graph title." << std::endl; std::cerr << " -w word Instead of inter-person relations, show the persons using" << std::endl; std::cerr << " specific words. This switch can be given multiple times." << std::endl; } void parse_opts(int argc, char *argv[], struct graphparam &pars) { // Set defaults pars.context = false; pars.tresholdfactor = 1.5; pars.nickcount = 15; pars.length = 10.0; pars.file = ""; pars.title = ""; pars.words.clear(); // Parse options int optchar; while ((optchar = getopt(argc, argv, "cf:l:n:t:T:w:")) != -1) { switch(optchar) { case 'c': pars.context = true; break; case 'f': pars.file = std::string(optarg); break; case 'l': pars.length = atof(optarg); break; case 'n': pars.nickcount = atoi(optarg); break; case 't': pars.tresholdfactor = atof(optarg); break; case 'T': pars.title = std::string(optarg); break; case 'w': pars.words.insert(std::string(optarg)); break; case '?': usagemsg(); exit(1); break; } } } std::string timestring(time_t timestamp) { struct tm time = *localtime(×tamp); char result[32]; strftime(&result[0], 32, "%d.%m.%Y", &time); return std::string(result); } int main(int argc, char *argv[]) { struct graphparam pars; parse_opts(argc, argv, pars); // Open input file / stream and read log to memory std::istream *infile = &std::cin; if (pars.file != "") { infile = new std::ifstream(pars.file.c_str()); } std::vector lines; readlog(lines, *infile); if ((*infile).bad()) { std::cerr << pars.file << ": Cannot read logfile" << std::endl; exit(2); } if (pars.file != "") { delete infile; } // Nicks that are in graph std::set usenicks; // Map of relations and strengths std::map relations; // Get nicks and their linecounts to select nicks std::vector linecounts; get_linecounts(linecounts, lines); // Select top n nicks select_to_set(usenicks, linecounts, pars.nickcount); if (pars.words.size() == 0) { // Person-person relations get_relations(relations, usenicks, lines, pars); } else { // Person-word relations get_simple_relations(relations, usenicks, lines, pars); } // Get the timerange of log pars.title += " (" + timestring(lines.front().timestamp) + " - " + timestring(lines.back().timestamp) + ")"; // Output writegraph(std::cout, relations, usenicks, pars); return 0; }