1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
|
package death
import (
"fmt"
"sort"
"strings"
)
type Weapon string
const (
Axe Weapon = "axe"
Discharge Weapon = "discharge"
Drown Weapon = "drown"
Fall Weapon = "fall"
GrenadeLauncher Weapon = "gl"
Lava Weapon = "lava"
LightningGun Weapon = "lg"
Nailgun Weapon = "ng"
NoWeapon Weapon = "no weapon"
QLightningGun Weapon = "quad lg"
QRocketLauncher Weapon = "quad rl"
QShotgun Weapon = "quad sg"
QSuperNailgun Weapon = "quad sng"
QSuperShotgun Weapon = "quad ssg"
RocketLauncher Weapon = "rl"
Shotgun Weapon = "sg"
Slime Weapon = "slime"
Squish Weapon = "squish"
Stomp Weapon = "stomp"
SuperNailgun Weapon = "sng"
SuperShotgun Weapon = "ssg"
TeamKill Weapon = "tk"
Telefrag Weapon = "telefrag"
Trap Weapon = "trap"
)
type Type uint8
const (
Unknown Type = iota
Death
Suicide
Kill
TeamKillUnknownKiller
TeamKillUnknownVictim
)
func (t Type) String() string {
names := []string{
"unknown",
"death",
"suicide",
"kill",
"teamkill",
"teamkill",
}
if t < 0 || int(t) >= len(names) {
return "type(?)"
}
return names[t]
}
type Obituary struct {
Type Type
Killer string
Victim string
Weapon Weapon
}
func (o Obituary) String() string {
hasKiller := o.Killer != ""
hasVictim := o.Victim != ""
switch {
case hasKiller && hasVictim:
return fmt.Sprintf("%s %s %s %s", o.Type, o.Killer, o.Weapon, o.Victim)
case hasKiller:
return fmt.Sprintf("%s %s %s", o.Type, o.Killer, o.Weapon)
default:
return fmt.Sprintf("%s %s %s", o.Type, o.Victim, o.Weapon)
}
}
type Parser struct {
templates []template
}
func init() {
sort.SliceStable(templates, func(i, j int) bool {
return templates[i].priority > templates[j].priority
})
}
func Parse(input string) (*Obituary, bool) {
s := strings.TrimSpace(input)
for _, t := range templates {
x, y, ok := t.parser.parse(s)
if !ok {
continue
}
ob := &Obituary{Weapon: t.weapon, Type: toObituaryType(t.typ)}
switch t.typ {
case PlayerDeath:
ob.Victim = x
case PlayerSuicide:
ob.Victim = x
case XFraggedByY:
ob.Victim = x
ob.Killer = y
case XFragsY:
ob.Killer = x
ob.Victim = y
case XTeamKilled:
ob.Victim = x
case XTeamKills:
ob.Killer = x
default:
ob.Victim = x
ob.Killer = y
}
return ob, true
}
return nil, false
}
|