package etdd
import (
"./obituaries"
"fmt"
"math"
"os"
"regexp"
"strings"
)
var r = regexp.MustCompile(`\^.`)
type line struct {
s string
e bool
}
type Logger struct {
colored bool
Complete bool
lines []line
}
func NewLogger(colored bool) Logger {
return Logger{colored, false, []line{}}
}
func (l *Logger) Error(error error) {
l.e("%s", error.Error())
}
func (l *Logger) Chat(serverTime int, player PlayerState, message string, channel string) {
l.p(serverTime, "[chat] %s: %s", player.Name, message)
}
func (l *Logger) Print(serverTime int, message string) {
l.p(serverTime, "[info] %s", message)
}
func (l *Logger) Start(hostname string, mapname string) {
l.Write(l.c("Server: %s", hostname))
l.Write(l.c("Map: %s", mapname))
}
func (l *Logger) End() {
l.Complete = true
}
func (l *Logger) Write(message string) {
l.lines = append(l.lines, line{message, false})
}
func (l *Logger) WriteTo(output *os.File, error *os.File) {
for _, line := range l.lines {
if line.e {
_, _ = error.WriteString(line.s)
} else {
_, _ = output.WriteString(line.s)
}
}
}
func (l *Logger) Obituary(serverTime int, victim *PlayerState, attacker *PlayerState, mod int) {
message := ""
switch mod {
case obituaries.Suicide:
message = "committed suicide"
break
case obituaries.Falling:
message += "fell to his death"
break
case obituaries.Crush:
message += "was crushed"
break
case obituaries.Water:
message += "drowned"
break
case obituaries.Slime:
message += "died by toxic materials"
break
case obituaries.TriggerHurt, obituaries.Telefrag, obituaries.TargetLaser:
message += "was killed"
break
case obituaries.CrushConstructiondeathNoattacker:
message += "got buried under a pile of rubble"
break
case obituaries.Lava:
message += "was incinerated"
break
}
if attacker == victim {
switch mod {
case obituaries.Dynamite:
message = "dynamited himself to pieces"
break
case obituaries.GrenadeLauncher, obituaries.GrenadePineapple:
message = "dove on his own grenade"
break
case obituaries.Panzerfaust:
message = "vaporized himself"
break
case obituaries.Flamethrower:
message = "played with fire"
break
case obituaries.Airstrike:
message = "obliterated himself"
break
case obituaries.Arty:
message = "fired-for-effect on himself"
break
case obituaries.Explosive:
message = "died in his own explosion"
break
case obituaries.Gpg40, obituaries.M7:
message = "ate his own rifle grenade"
break
case obituaries.Landmine:
message = "failed to spot his own landmine"
break
case obituaries.Satchel:
message = "embraced his own satchel explosion"
break
case obituaries.Tripmine:
message = "forgot where his tripmine was"
break
case obituaries.CrushConstruction:
message = "engineered himself into oblivion"
break
case obituaries.CrushConstructiondeath:
message = "buried himself alive"
break
case obituaries.Mortar:
message = "never saw his own mortar round coming"
break
case obituaries.Smokegrenade:
message = "danced on his airstrike marker"
break
case obituaries.SwitchTeams:
return
default:
message = "killed himself"
break
}
}
if len(message) > 0 {
l.p(serverTime, "[kill] %d %d %d: %s ^7%s.", -1, victim.Num, mod, victim.Name, message)
return
}
if attacker != nil {
message2 := ""
switch mod {
case obituaries.Knife:
message = "was stabbed by"
message2 = "'s knife"
break
case obituaries.AkimboColt, obituaries.AkimboSilencedcolt:
message = "was killed by"
message2 = "'s Akimbo .45ACP 1911s"
break
case obituaries.AkimboLuger, obituaries.AkimboSilencedluger:
message = "was killed by"
message2 = "'s Akimbo Luger 9mms"
break
case obituaries.Silencer, obituaries.Luger:
message = "was killed by"
message2 = "'s Luger 9mm"
break
case obituaries.SilencedColt, obituaries.Colt:
message = "was killed by"
message2 = "'s .45ACP 1911"
break
case obituaries.Mp40:
message = "was killed by"
message2 = "'s MP40"
break
case obituaries.Thompson:
message = "was killed by"
message2 = "'s Thompson"
break
case obituaries.Sten:
message = "was killed by"
message2 = "'s Sten"
break
case obituaries.Dynamite:
message = "was blasted by"
message2 = "'s dynamite"
break
case obituaries.Panzerfaust:
message = "was blasted by"
message2 = "'s Panzerfaust"
break
case obituaries.GrenadeLauncher, obituaries.GrenadePineapple:
message = "was exploded by"
message2 = "'s grenade"
break
case obituaries.Flamethrower:
message = "was cooked by"
message2 = "'s flamethrower"
break
case obituaries.Mortar:
message = "never saw"
message2 = "'s mortar round coming"
break
case obituaries.Machinegun:
message = "was perforated by"
message2 = "'s crew-served MG"
break
case obituaries.Browning:
message = "was perforated by"
message2 = "'s tank-mounted browning 30cal"
break
case obituaries.Mg42:
message = "was perforated by"
message2 = "'s tank-mounted MG42"
break
case obituaries.Airstrike:
message = "was blasted by"
message2 = "'s support fire"
break
case obituaries.Arty:
message = "was shelled by"
message2 = "'s artillery support"
break
case obituaries.SwapPlaces:
message = "^2swapped places with^7"
message2 = ""
break
case obituaries.Kar98, obituaries.K43:
message = "was killed by"
message2 = "'s K43"
break
case obituaries.Carbine, obituaries.Garand:
message = "was killed by"
message2 = "'s Garand"
break
case obituaries.Gpg40, obituaries.M7:
message = "was killed by"
message2 = "'s rifle grenade"
break
case obituaries.Landmine:
message = "failed to spot"
message2 = "'s Landmine"
break
case obituaries.CrushConstruction:
message = "got caught in"
message2 = "'s construction madness"
break
case obituaries.CrushConstructiondeath:
message = "got burried under"
message2 = "'s rubble"
break
case obituaries.MobileMg42:
message = "was mown down by"
message2 = "'s Mobile MG42"
break
case obituaries.GarandScope:
message = "was silenced by"
message2 = "'s Garand"
break
case obituaries.K43Scope:
message = "was silenced by"
message2 = "'s K43"
break
case obituaries.Fg42:
message = "was killed by"
message2 = "'s FG42"
break
case obituaries.Fg42scope:
message = "was sniped by"
message2 = "'s FG42"
break
case obituaries.Satchel:
message = "was blasted by"
message2 = "'s Satchel Charge"
break
case obituaries.Tripmine:
message = "was detonated by"
message2 = "'s trip mine"
break
case obituaries.Smokegrenade:
message = "stood on"
message2 = "'s airstrike marker"
break
default:
message = "was killed by"
break
}
if victim.Team == attacker.Team {
message = "^1WAS KILLED BY TEAMMATE^7"
}
if message != "" {
if message2 != "" {
l.p(serverTime, "[kill] %d %d %d: %s ^7%s %s^7%s.", attacker.Num, victim.Num, mod, victim.Name, message, attacker.Name, message2)
}
return
}
}
l.p(serverTime, "[kill] %d %d %d: %s ^7died.", -1, victim.Num, mod, victim.Name)
}
func (l *Logger) p(serverTime int, format string, a ...interface{}) {
l.Write(formatTime(serverTime) + " " + l.c(format, a...))
}
func (l *Logger) e(format string, a ...interface{}) {
l.lines = append(l.lines, line{l.c(format, a...), true})
}
func (l *Logger) c(format string, a ...interface{}) string {
message := strings.Replace(fmt.Sprintf(format, a...), "\n", " ", -1) + "\n"
if l.colored {
return message
}
return r.ReplaceAllString(message, "")
}
func formatTime(time int) string {
time = time / 1000
h, m := 0, 0
if time > 3600 {
h = int(math.Floor(float64(time / 3600)))
time -= h * 3600
}
if time > 60 {
m = int(math.Floor(float64(time / 60)))
time -= m * 60
}
return fmt.Sprintf("[%02d:%02d:%02d]", h, m, time)
}