Another waste of time:
begin
require 'parsedate'
class Date
module Format # :nodoc:
warn_level = $VERBOSE
$VERBOSE = nil
MONTHS = MONTHS.merge(
'januar' => 1, 'februar' => 2, 'märz' => 3, 'mai' => 5,
'juni' => 6, 'juli' => 7, 'oktober' =>10, 'dezember' =>12
)
DAYS = DAYS.merge(
'sonntag' =>0, 'montag' => 1, 'dienstag' => 2, 'mittwoch' => 3,
'donnerstag'=>4, 'freitag' => 5, 'samstag' => 6
)
ABBR_MONTHS = ABBR_MONTHS.merge(
'mär' => 3, 'apr' => 4, 'mai' => 5, 'okt' =>10,
'dez' =>12
)
ABBR_DAYS = ABBR_DAYS.merge(
'so' => 0, 'mo' => 1, 'di' => 2, 'mi' => 3,
'do' => 4, 'fr' => 5, 'sa' => 6
)
$VERBOSE = warn_level
end
end
class PSLog < Array
class Line
COMMANDS = [:say, :shout, :tellnpc, :auction, :group, :guild, :tell, :channel, :action]
ACTIONS = [:me, :my]
attr_reader :direction, :name, :time, :command, :text, :action, :target
def initialize own_name, name, time, command, text, action = nil, target = nil
unless is_npc_action = (command == :action and name == nil)
name = own_name if name.downcase == 'you'
end
unless is_npc_action
@direction = (is_npc_action or (name != own_name)) ? :in : :out
@name = name
else
@direction = :unknown
end
@time = time
COMMANDS.include? command or raise "Invalid command #{command}"
@command = command
@text = text
if action
ACTIONS.include? action or raise "Invalid action #{action}"
@action = action
end
if [:tell, :channel].include? @command
@target = target
end
end
end
class Session < Array
attr_reader :start_time
def initialize time
@start_time = time
super()
end
end
def self.load name, &block
file = File.join File.expand_path('~'), '.PlaneShift', 'logs', (name.gsub(' ', '_') << '_chat.txt')
File.exist?(file) and new(name, file, &block)
end
TIMESTAMP = /^\((\d\d:\d\d:\d\d)\) /
ACTION = /^>/
CHAT_TAB = /^
(?:\[(NPC|Auction|Group|Guild|Tell)\]| # General chat tabs
\[Channel\]\s\[\d+:\s([^\]]*)\])\s # Channel chat tab
/x
NAME = /^([A-Z][a-z]*)(?: ((?:[A-Z][a-z]*-)*[A-Z][a-z]*))?/
SAY_SHOUT_SUFFIX = /^ (says|shouts|auctions): /
TELL_SUFFIX = /^ (?:tells you|tell ([A-Z][a-z]+)): /
MY_SUFFIX = /^'s /
ME_SUFFIX = /^ /
SEPARATOR = /^(=|-){48,}$/
COMMANDS = { "NPC" => :tellnpc, "Auction" => :auction, "Group" => :group,
"Guild" => :guild, "Tell" => :tell,
'says' => :say, 'shouts' => :shout, nil => :action
}
attr_reader :surnames
def initialize name, filename
@name = name
first, last = name.split(' ')
super()
session_start = /(.*) #{@name}/
day = lasthour = nil
@surnames = { first => last }
puts "Reading file #{filename}..."
File.foreach filename do |line|
if line.slice! TIMESTAMP
raise 'No session started in log file' if empty?
# Haben Chat-Zeile
h, m, s = $1.split(':').collect { |s| s.to_i }
if h < lasthour
day += 86400 # Einen Tag addieren
end
lasthour = h
# Command rekonstruieren, Name / Action / Target herausfinden
unless is_action = line.slice!(ACTION) != nil
line.slice! CHAT_TAB
tab, channel = $1, $2
end
line.slice! NAME
name = $1
@surnames[name] = $2 if $2
target = action = nil
command =
if is_action # :action
command = :action
else
# Setzt $1 auf say oder shout, falls es sich um say/shout handelt
line.slice! SAY_SHOUT_SUFFIX
action =
if name and not (verb = $1)
if tab == "Tell" and line.slice!(TELL_SUFFIX)
target = $1
nil
elsif line.slice! MY_SUFFIX
:my
else
line.slice! ME_SUFFIX
:me
end
end
if tab and name # Commands aus COMMANDS
COMMANDS[tab]
elsif channel # :channel
target = channel
:channel
else # :say und :shout
# (/shout /m(e|y) wird zu /say :m(e|y), :mypet wird zu :my)
action ? :say : COMMANDS[verb]
end
end
line = Line.new(first, name, day + 3600*h+60*m+s, command, line.strip, action, target)
yield self[-1], line
self[-1] << line
elsif line[session_start]
time = Time.mktime(*ParseDate.parsedate($1))
a = time.to_a[2..5].reverse
lasthour = a[3]
day = Time.mktime(*a[0..2])
self << Session.new(time)
elsif not line[SEPARATOR]
puts "Failed to parse the following line:\n #{line}"
end
end
puts "Parsing finished."
end
end
saved_chars = []
charname = /([^#{File::SEPARATOR}]*)_chat.txt/
Dir.glob File.join File.expand_path('~'), '.PlaneShift', 'logs', ('*_chat.txt') do |file|
file[charname]
saved_chars << [$1.gsub('_', ' '), file]
end
begin
puts "Please enter the number for the character whose logs are to be checked."
saved_chars.each_with_index do |char, i|
puts "#{i+1}) #{char[0]}"
end
end until (1..saved_chars.length).include?(i = gets.to_i)
linecount = 0
msg_by_dir = { :in => 0, :out => 0, :unknown => 0 }
msg_by_char = Hash.new { |hash, key| hash[key] = 0 }
log = PSLog.new *saved_chars[i-1] do |session, line|
linecount += 1
msg_by_dir[line.direction] += 1
msg_by_char[line.name] += 1 if line.name
end
unless log
puts "Error trying to load log for #{name}."
exit! 1
end
top_char = msg_by_char.sort{ |a, b| b[1] <=> a[1]}
max_session = [0]
play_time = log.inject(0) do |sum, session|
sl = (session.empty? ? 0 : (session[-1].time.to_i - session.start_time.to_i))
unless sl < max_session[0]
max_session = [sl, session.start_time]
end
sum + sl
end
puts "Your chatlog contains #{linecount} chat lines:"
puts " #{msg_by_dir[:in]} incoming,"
puts " #{msg_by_dir[:out]} outgoing and"
puts " #{msg_by_dir[:unknown]} unknown (i.e. NPC/GM actions)."
puts ""
puts "Messages span across #{log.length} game sessions covering a total play"
puts "time of #{play_time/3600.0} hours; thus, the mean session length is"
puts "#{play_time/(60.0*log.length)} minutes. Your longest session was"
puts "#{max_session[0]/3600.0} hours long, it started #{max_session[1]}."
puts ""
puts "Your log contains messages from #{msg_by_char.length} different characters,"
puts "and surnames for #{log.surnames.length} of them are logged."
puts ""
puts "The top five characters in your log are:"
puts top_char[0..4].inject('') { |string, char|
string << char[0] << ' '
if log.surnames.include? char[0]
string << log.surnames[char[0]] << ' '
end
string << '(' << char[1].to_s << ")\n"
}
rescue Interrupt
puts "Aborted."
end
Save it as something.rb and run with "ruby something.rb". Only some sample statistics included that came to my mind, add more if you like. Won't fix bugs. Won't work correctly if your system locale isn't English or German (the dates are printed to the log according to system locale, and only dates in these two languages can be parsed).
Example output:
Parsing finished.
Your chatlog contains 95471 chat lines:
58623 incoming,
36084 outgoing and
764 unknown (i.e. NPC/GM actions).
Messages span across 331 game sessions covering a total play
time of 618.291944444444 hours; thus, the mean session length is
112.077089627392 minutes. Your longest session was
17.4208333333333 hours long, it started Sat Jun 06 10:51:13 +0200 2009.
Your log contains messages from 988 different characters,
and surnames for 640 of them are logged.
The top five characters in your log are:
[truncated]