aboutsummaryrefslogtreecommitdiffstats
path: root/common/death/death.go
blob: c71f862c1314f33f302e54cd9bad0f839080c60b (plain) (blame)
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
}