Skip to content

Commit

Permalink
fix character killer parser by rewrite of death parsing logic (#338)
Browse files Browse the repository at this point in the history
  • Loading branch information
phenpessoa committed Mar 30, 2024
1 parent ec2e9ea commit 1e7d6b7
Show file tree
Hide file tree
Showing 3 changed files with 975 additions and 2 deletions.
87 changes: 85 additions & 2 deletions src/TibiaCharactersCharacter.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package main

import (
"bytes"
"fmt"
"log"
"net/http"
Expand Down Expand Up @@ -489,8 +490,90 @@ func TibiaCharactersCharacterImpl(BoxContentHTML string) (CharacterResponse, err
lastAndIdx := strings.LastIndex(lastItem, andStr)

if lastAndIdx > -1 {
ListOfKillers[len(ListOfKillers)-1] = lastItem[:lastAndIdx]
ListOfKillers = append(ListOfKillers, lastItem[lastAndIdx+len(andStr):])
if !strings.Contains(lastItem, "<a href=") {
ListOfKillers[len(ListOfKillers)-1] = lastItem[:lastAndIdx]
ListOfKillers = append(ListOfKillers, lastItem[lastAndIdx+len(andStr):])
} else {
ListOfKillers = ListOfKillers[:len(ListOfKillers)-1]

const (
nonTag = iota // outside of a tag
openAnchorTag // inside a <a>
closeAchorTag // inside a </a>
)

var (
buffer bytes.Buffer
state = nonTag
)
buffer.Grow(200) // arbitrary number to avoid allocations

for i := range lastItem {
cur := lastItem[i]
switch state {
case nonTag:
if cur == '<' {
switch lastItem[i+1] {
case '/':
state = closeAchorTag
default:
state = openAnchorTag
if buffer.Len() > 0 {
str := buffer.String()

str = strings.TrimPrefix(str, " and ")
str = strings.TrimSuffix(str, " and ")

if str == "" {
buffer.Reset()
buffer.WriteByte(cur)
continue
}

if strings.Contains(str, "of") && !containsCreaturesWithOf(str) {
// this is a summon
buffer.WriteByte(cur)
continue
}

buffer.Reset()
ListOfKillers = append(ListOfKillers, str)
}
}
}
buffer.WriteByte(cur)
case openAnchorTag:
if cur == '>' {
state = nonTag
}
buffer.WriteByte(cur)
case closeAchorTag:
buffer.WriteByte(cur)
if cur == '>' {
str := buffer.String()

str = strings.TrimPrefix(str, " and ")
str = strings.TrimSuffix(str, " and ")

ListOfKillers = append(ListOfKillers, str)
buffer.Reset()
state = nonTag
}
}
}

if buffer.Len() > 0 {
str := buffer.String()
buffer.Reset()

str = strings.TrimPrefix(str, " and ")
str = strings.TrimSuffix(str, " and ")

if str != "" {
ListOfKillers = append(ListOfKillers, str)
}
}
}
}

// loop through all killers and append to result
Expand Down
88 changes: 88 additions & 0 deletions src/TibiaCharactersCharacter_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3298,6 +3298,94 @@ func TestNumber12(t *testing.T) {
assert.Equal(55, len(characterJson.Character.Deaths))
}

func TestNumber13(t *testing.T) {
file, err := static.TestFiles.Open("testdata/characters/Ninth Dimension.html")
if err != nil {
t.Fatalf("file opening error: %s", err)
}
defer file.Close()

data, err := io.ReadAll(file)
if err != nil {
t.Fatalf("File reading error: %s", err)
}

characterJson, err := TibiaCharactersCharacterImpl(string(data))
if err != nil {
t.Fatal(err)
}

assert := assert.New(t)
character := characterJson.Character.CharacterInfo

assert.Equal("Ninth Dimension", character.Name)
assert.False(characterJson.Character.DeathsTruncated)

// validate death data
assert.Equal(1, len(characterJson.Character.Deaths))
deaths := characterJson.Character.Deaths

for idx, tc := range []struct {
Assists []Killers
Killers []Killers
Level int
Reason string
Time string
}{
{
Assists: []Killers{
{Name: "Dark Assa", Player: true, Traded: false, Summon: ""},
},
Killers: []Killers{
{Name: "Pess Joeru", Player: true, Traded: false, Summon: ""},
{Name: "Curly Da Goonx", Player: true, Traded: false, Summon: ""},
{Name: "Setarehh", Player: true, Traded: false, Summon: ""},
{Name: "Skkrimz", Player: true, Traded: false, Summon: ""},
{Name: "Luna Mors", Player: true, Traded: false, Summon: ""},
{Name: "Micklo", Player: true, Traded: false, Summon: ""},
{Name: "Kate Morningstar", Player: true, Traded: false, Summon: ""},
{Name: "Avatar Avatar", Player: true, Traded: false, Summon: ""},
{Name: "San Bernardino Hoodrat", Player: true, Traded: false, Summon: ""},
{Name: "Mighty Nitro", Player: true, Traded: false, Summon: ""},
{Name: "Aiakosz", Player: true, Traded: false, Summon: ""},
{Name: "Sithaadoz", Player: true, Traded: false, Summon: ""},
{Name: "Compa Ache", Player: true, Traded: false, Summon: ""},
{Name: "Cave Stormer", Player: true, Traded: false, Summon: ""},
{Name: "Doppler and Bankrupt", Player: true, Traded: false, Summon: ""},
},
Level: 544,
Reason: "Eliminated at Level 544 by Pess Joeru, Curly Da Goonx, Setarehh, Skkrimz, Luna Mors, Micklo, Kate Morningstar, Avatar Avatar, San Bernardino Hoodrat, Mighty Nitro, Aiakosz, Sithaadoz, Compa Ache, Cave Stormer and Doppler and Bankrupt. Assisted by Dark Assa.",
Time: "2024-03-12T21:02:33Z",
},
} {
assert.True(
reflect.DeepEqual(deaths[idx].Assists, tc.Assists),
"Wrong assists\nidx: %d\nwant: %#v\n\ngot: %#v",
idx, tc.Assists, deaths[idx].Assists,
)
assert.True(
reflect.DeepEqual(deaths[idx].Killers, tc.Killers),
"Wrong killers\nidx: %d\nwant: %#v\n\ngot: %#v",
idx, tc.Killers, deaths[idx].Killers,
)
assert.Equal(
deaths[idx].Level, tc.Level,
"Wrong Level\nidx: %d\nwant: %d\n\ngot: %d",
idx, tc.Level, deaths[idx].Level,
)
assert.Equal(
deaths[idx].Reason, tc.Reason,
"Wrong Reason\nidx: %d\nwant: %s\n\ngot: %s",
idx, tc.Reason, deaths[idx].Reason,
)
assert.Equal(
tc.Time, deaths[idx].Time,
"Wrong Time\nidx: %d\nwant: %s\n\ngot: %s",
idx, tc.Time, deaths[idx].Time,
)
}
}

func BenchmarkNumber1(b *testing.B) {
file, err := static.TestFiles.Open("testdata/characters/Darkside Rafa.html")
if err != nil {
Expand Down
Loading

0 comments on commit 1e7d6b7

Please sign in to comment.