soccer-bot/topic.go

199 lines
4.0 KiB
Go
Raw Normal View History

2017-08-08 16:32:45 +00:00
package main
import (
"errors"
"fmt"
"strconv"
"strings"
"github.com/helmbold/richgo/regexp"
)
var (
errIncompatibleTopicPart = errors.New("Incompatible topic part")
rxTopicPart = regexp.MustCompile(`\s*\x02` +
`\s*\x03\s*(?P<prefixColor>[0-9]+)` +
`(?P<prefix>[A-Za-z\s]+):` +
`\s*\x03` +
`\s*(?P<text>.+)` +
`\s*\x02` +
`\s*`)
rxMatch = regexp.MustCompile(`^` +
`(?P<homeTeam>` +
`\w+(?:\s+\w+)*)` +
`\s+(?P<homeScore>\-|\d+):(?P<awayScore>\-|\d+)` +
`\s+(?P<awayTeam>\w+(?:\s+\w+)*)` +
`(` +
`\s+(?P<additional>.+)` +
`)?` +
`$`)
rxAdditionalScoreInfo = regexp.MustCompile(`^` +
`(?P<pre>.*?)\s*` +
`(\[(?:` +
`(?P<penTag>P)\s*(?P<penScore>\d+:\d+)` +
`|` +
`(?P<extraTag>AET)` +
`)\]\s*)?` +
`\((?P<halfScore>\d+:\d+)\)` +
`\s*(?P<post>.*)` +
`$`)
)
type topicPart struct {
PrefixColor string
Prefix string
Text string
Matches []topicMatchInfo
}
func (t *topicPart) HasMatches() bool {
return t.Matches != nil && len(t.Matches) > 0
}
func (t *topicPart) String() string {
retval := fmt.Sprintf("\x02\x03%s%s:\x03 ", t.PrefixColor, t.Prefix)
if t.Matches == nil || len(t.Matches) == 0 {
retval += t.Text
} else {
first := true
for _, match := range t.Matches {
if !first {
retval += " + "
}
retval += match.String()
first = false
}
}
retval += "\x02"
return retval
}
type topicMatchInfo struct {
HomeTeam string
AwayTeam string
Current *topicScoreInfo
Additional string
}
type topicAdditionalScoreInfo struct {
IsAET bool
PenScore string
HalfScore string
Pre string
Post string
}
func (i *topicAdditionalScoreInfo) String() string {
retval := ""
switch {
case len(i.PenScore) > 0:
retval += fmt.Sprintf("[P %s]", i.PenScore)
case i.IsAET:
retval += "[AET]"
}
if len(retval) > 0 {
retval += " "
}
if len(i.HalfScore) > 0 {
retval += fmt.Sprintf("(%s)", i.HalfScore)
}
if len(i.Pre) > 0 {
if len(retval) > 0 {
retval = " " + retval
}
retval = i.Pre + retval
}
if len(i.Post) > 0 {
if len(retval) > 0 {
retval += " "
}
retval += i.Post
}
return retval
}
func (m *topicMatchInfo) AdditionalScoreInfo() *topicAdditionalScoreInfo {
a := rxAdditionalScoreInfo.Match(m.Additional)
if a == nil {
return nil
}
return &topicAdditionalScoreInfo{
HalfScore: a.NamedGroups["halfScore"],
IsAET: len(a.NamedGroups["penScore"]) > 0 || len(a.NamedGroups["extraTag"]) > 0,
PenScore: a.NamedGroups["penScore"],
Pre: a.NamedGroups["pre"],
Post: a.NamedGroups["post"],
}
}
func (m *topicMatchInfo) String() string {
retval := fmt.Sprintf("%s %s %s", m.HomeTeam, m.Current, m.AwayTeam)
if len(m.Additional) > 0 {
retval += " " + m.Additional
}
return retval
}
type topicScoreInfo struct {
HomeScore int
AwayScore int
}
func (s *topicScoreInfo) String() string {
if s == nil {
return "-:-"
}
return fmt.Sprintf("%d:%d", s.HomeScore, s.AwayScore)
}
func parseTopicPart(s string) (r topicPart, err error) {
match := rxTopicPart.Match(s)
if match == nil {
err = errIncompatibleTopicPart
return
}
r.PrefixColor = match.NamedGroups["prefixColor"]
r.Prefix = match.NamedGroups["prefix"]
r.Text = match.NamedGroups["text"]
// Try to get match info if compatible
matchCompatible := true
matchInfos := []topicMatchInfo{}
for _, matchPart := range strings.Split(r.Text, " + ") {
match = rxMatch.Match(matchPart)
if match == nil {
matchCompatible = false
break
}
matchInfo := topicMatchInfo{}
matchInfo.HomeTeam = match.NamedGroups["homeTeam"]
matchInfo.AwayTeam = match.NamedGroups["awayTeam"]
homeScore, err := strconv.Atoi(match.NamedGroups["homeScore"])
if err == nil {
awayScore, err := strconv.Atoi(match.NamedGroups["awayScore"])
if err == nil {
matchInfo.Current = &topicScoreInfo{
HomeScore: homeScore,
AwayScore: awayScore,
}
}
}
matchInfo.Additional = match.NamedGroups["additional"]
matchInfos = append(matchInfos, matchInfo)
}
if matchCompatible {
r.Matches = matchInfos
}
return
}