Skip to content

Commit 015db2d

Browse files
Adding Worlds unit tests (#53)
* Worlds Overview unit tests * updating TibiadataDateV3 parsing date without regex and supporting long and short months * changing WorldsBattleyeDate to be parsed correct updating tests as well Co-authored-by: Tobias Lindberg <tobias.ehlert@gmail.com>
1 parent 5dba396 commit 015db2d

File tree

4 files changed

+928
-59
lines changed

4 files changed

+928
-59
lines changed

src/TibiaDataUtils.go

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -92,24 +92,37 @@ func TibiadataQueryEscapeStringV3(data string) string {
9292
return url.QueryEscape(data)
9393
}
9494

95-
var dateRegex = regexp.MustCompile(`([a-zA-Z]{3}).*([0-9]{2}).*([0-9]{4})`)
96-
9795
// TibiadataDateV3 func
9896
func TibiadataDateV3(date string) string {
99-
// use regex to skip weird formatting on "spaces"
100-
subma1 := dateRegex.FindAllStringSubmatch(date, -1)
101-
date = (subma1[0][1] + " " + subma1[0][2] + " " + subma1[0][3])
97+
// removing weird spacing and comma
98+
date = TibiaDataSanitizeNbspSpaceString(strings.ReplaceAll(date, ",", ""))
99+
100+
// var time parser
101+
var tmpDate time.Time
102102

103103
// parsing and setting format of return
104-
tmpDate, _ := time.Parse("Jan 02 2006", date)
105-
date = tmpDate.UTC().Format("2006-01-02")
104+
switch dateLength := len(date); {
105+
case dateLength == 5:
106+
// date that contains special formatting only used in date a world was created
107+
tmpDate, _ = time.Parse("01/06", date)
108+
// we need to return earlier as well, since we don't have the day
109+
return tmpDate.UTC().Format("2006-01")
110+
case dateLength == 11:
111+
// dates that contain first 3 letters in month
112+
tmpDate, _ = time.Parse("Jan 02 2006", date)
113+
case dateLength > 11:
114+
// dates that contain month fully written
115+
tmpDate, _ = time.Parse("January 02 2006", date)
116+
default:
117+
log.Printf("Weird format detected: %s", date)
118+
}
106119

107-
return date
120+
return tmpDate.UTC().Format("2006-01-02")
108121
}
109122

110123
// TibiadataStringToIntegerV3 func
111124
func TibiadataStringToIntegerV3(data string) int {
112-
returnData, err := strconv.Atoi(data)
125+
returnData, err := strconv.Atoi(strings.ReplaceAll(data, ",", ""))
113126
if err != nil {
114127
log.Printf("[warning] TibiadataStringToIntegerV3: couldn't convert string into int. error: %s", err)
115128
}

src/TibiaWorldsOverviewV3.go

Lines changed: 56 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -10,46 +10,44 @@ import (
1010
"github.com/gin-gonic/gin"
1111
)
1212

13+
// Child of Worlds
14+
type World struct {
15+
Name string `json:"name"`
16+
Status string `json:"status"` // Online:
17+
PlayersOnline int `json:"players_online"` // Online:
18+
Location string `json:"location"` // Location:
19+
PvpType string `json:"pvp_type"` // PvP Type:
20+
PremiumOnly bool `json:"premium_only"` // Additional Information: premium = true / else: false
21+
TransferType string `json:"transfer_type"` // Additional Information: regular (if not present) / locked / blocked
22+
BattleyeProtected bool `json:"battleye_protected"` // BattlEye Status: true if protected / false if "Not protected by BattlEye."
23+
BattleyeDate string `json:"battleye_date"` // BattlEye Status: null if since release / else show date?
24+
GameWorldType string `json:"game_world_type"` // BattlEye Status: regular / experimental / tournament (if Tournament World Type exists)
25+
TournamentWorldType string `json:"tournament_world_type"` // BattlEye Status: null (default?) / regular / restricted
26+
}
27+
28+
// Child of JSONData
29+
type Worlds struct {
30+
PlayersOnline int `json:"players_online"` // Calculated value
31+
RecordPlayers int `json:"record_players"` // Overall Maximum:
32+
RecordDate string `json:"record_date"` // Overall Maximum:
33+
RegularWorlds []World `json:"regular_worlds"`
34+
TournamentWorlds []World `json:"tournament_worlds"`
35+
}
36+
37+
//
38+
// The base includes two levels: Worlds and Information
39+
type WorldsOverviewResponse struct {
40+
Worlds Worlds `json:"worlds"`
41+
Information Information `json:"information"`
42+
}
43+
1344
var (
1445
worldPlayerRecordRegex = regexp.MustCompile(`.*<\/b>...(.*) players \(on (.*)\)`)
1546
worldInformationRegex = regexp.MustCompile(`.*world=.*">(.*)<\/a><\/td>.*right;">(.*)<\/td><td>(.*)<\/td><td>(.*)<\/td><td align="center" valign="middle">(.*)<\/td><td>(.*)<\/td>`)
1647
worldBattlEyeProtectedSinceRegex = regexp.MustCompile(`.*game world has been protected by BattlEye since (.*).&lt;\/p.*`)
1748
)
1849

19-
// TibiaWorldsOverviewV3 func
2050
func TibiaWorldsOverviewV3(c *gin.Context) {
21-
22-
// Child of Worlds
23-
type World struct {
24-
Name string `json:"name"`
25-
Status string `json:"status"` // Online:
26-
PlayersOnline int `json:"players_online"` // Online:
27-
Location string `json:"location"` // Location:
28-
PvpType string `json:"pvp_type"` // PvP Type:
29-
PremiumOnly bool `json:"premium_only"` // Additional Information: premium = true / else: false
30-
TransferType string `json:"transfer_type"` // Additional Information: regular (if not present) / locked / blocked
31-
BattleyeProtected bool `json:"battleye_protected"` // BattlEye Status: true if protected / false if "Not protected by BattlEye."
32-
BattleyeDate string `json:"battleye_date"` // BattlEye Status: null if since release / else show date?
33-
GameWorldType string `json:"game_world_type"` // BattlEye Status: regular / experimental / tournament (if Tournament World Type exists)
34-
TournamentWorldType string `json:"tournament_world_type"` // BattlEye Status: null (default?) / regular / restricted
35-
}
36-
37-
// Child of JSONData
38-
type Worlds struct {
39-
PlayersOnline int `json:"players_online"` // Calculated value
40-
RecordPlayers int `json:"record_players"` // Overall Maximum:
41-
RecordDate string `json:"record_date"` // Overall Maximum:
42-
RegularWorlds []World `json:"regular_worlds"`
43-
TournamentWorlds []World `json:"tournament_worlds"`
44-
}
45-
46-
//
47-
// The base includes two levels: Worlds and Information
48-
type JSONData struct {
49-
Worlds Worlds `json:"worlds"`
50-
Information Information `json:"information"`
51-
}
52-
5351
// Getting data with TibiadataHTMLDataCollectorV3
5452
TibiadataRequest.URL = "https://www.tibia.com/community/?subtopic=worlds"
5553
BoxContentHTML, err := TibiadataHTMLDataCollectorV3(TibiadataRequest)
@@ -60,6 +58,13 @@ func TibiaWorldsOverviewV3(c *gin.Context) {
6058
return
6159
}
6260

61+
jsonData := TibiaWorldsOverviewV3Impl(BoxContentHTML)
62+
63+
TibiaDataAPIHandleSuccessResponse(c, "TibiaWorldsOverviewV3", jsonData)
64+
}
65+
66+
// TibiaWorldsOverviewV3 func
67+
func TibiaWorldsOverviewV3Impl(BoxContentHTML string) WorldsOverviewResponse {
6368
// Loading HTML data into ReaderHTML for goquery with NewReader
6469
ReaderHTML, err := goquery.NewDocumentFromReader(strings.NewReader(BoxContentHTML))
6570
if err != nil {
@@ -102,23 +107,27 @@ func TibiaWorldsOverviewV3(c *gin.Context) {
102107

103108
// check if regex return length is over 0
104109
if len(subma2) > 0 {
110+
WorldsPlayersOnline := 0
111+
112+
if subma2[0][2] == "-" {
113+
WorldsStatus = "unknown"
114+
} else {
115+
WorldsPlayersOnline = TibiadataStringToIntegerV3(subma2[0][2])
116+
117+
// Setting the players_online & overall players_online
118+
WorldsAllOnlinePlayers += WorldsPlayersOnline
119+
120+
if WorldsPlayersOnline > 0 {
121+
WorldsStatus = "online"
122+
} else {
123+
WorldsStatus = "offline"
124+
}
125+
}
105126

106127
// Creating better to use vars
107-
WorldsPlayersOnline := TibiadataStringToIntegerV3(subma2[0][2])
108128
WorldsBattlEye := subma2[0][5]
109129
WorldsAdditionalInfo := subma2[0][6]
110130

111-
// Setting the players_online & overall players_online
112-
WorldsAllOnlinePlayers += WorldsPlayersOnline
113-
switch {
114-
case WorldsPlayersOnline > 0:
115-
WorldsStatus = "online"
116-
case subma2[0][2] == "-":
117-
WorldsStatus = "unknown"
118-
default:
119-
WorldsStatus = "offline"
120-
}
121-
122131
// Setting the premium_only
123132
if strings.Contains(WorldsAdditionalInfo, "premium") {
124133
WorldsPremiumOnly = true
@@ -149,7 +158,7 @@ func TibiaWorldsOverviewV3(c *gin.Context) {
149158
WorldsBattleyeDate = "release"
150159
} else {
151160
subma21 := worldBattlEyeProtectedSinceRegex.FindAllStringSubmatch(WorldsBattlEye, -1)
152-
WorldsBattleyeDate = subma21[0][1]
161+
WorldsBattleyeDate = TibiadataDateV3(subma21[0][1])
153162
}
154163
} else {
155164
// This world is without protection..
@@ -196,7 +205,7 @@ func TibiaWorldsOverviewV3(c *gin.Context) {
196205

197206
//
198207
// Build the data-blob
199-
jsonData := JSONData{
208+
return WorldsOverviewResponse{
200209
Worlds{
201210
PlayersOnline: WorldsAllOnlinePlayers,
202211
RecordPlayers: WorldsRecordPlayers,
@@ -209,7 +218,4 @@ func TibiaWorldsOverviewV3(c *gin.Context) {
209218
Timestamp: TibiadataDatetimeV3(""),
210219
},
211220
}
212-
213-
// return jsonData
214-
TibiaDataAPIHandleSuccessResponse(c, "TibiaWorldsOverviewV3", jsonData)
215221
}

src/TibiaWorldsOverviewV3_test.go

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
package main
2+
3+
import (
4+
"io/ioutil"
5+
"testing"
6+
7+
"github.com/stretchr/testify/assert"
8+
)
9+
10+
func TestWorlds(t *testing.T) {
11+
data, err := ioutil.ReadFile("../testdata/worlds/worlds.html")
12+
if err != nil {
13+
t.Errorf("File reading error: %s", err)
14+
return
15+
}
16+
17+
worldsJson := TibiaWorldsOverviewV3Impl(string(data))
18+
assert := assert.New(t)
19+
20+
assert.Equal(8756, worldsJson.Worlds.PlayersOnline)
21+
assert.Equal(64028, worldsJson.Worlds.RecordPlayers)
22+
assert.Equal("2007-11-28T18:26:00Z", worldsJson.Worlds.RecordDate)
23+
assert.Equal(76, len(worldsJson.Worlds.RegularWorlds))
24+
assert.Equal(6, len(worldsJson.Worlds.TournamentWorlds))
25+
26+
adra := worldsJson.Worlds.RegularWorlds[0]
27+
assert.Equal("Adra", adra.Name)
28+
assert.Equal("online", adra.Status)
29+
assert.Equal(18, adra.PlayersOnline)
30+
assert.Equal("Europe", adra.Location)
31+
assert.Equal("Open PvP", adra.PvpType)
32+
assert.Equal(false, adra.PremiumOnly)
33+
assert.Equal("blocked", adra.TransferType)
34+
assert.Equal(true, adra.BattleyeProtected)
35+
assert.Equal("release", adra.BattleyeDate)
36+
assert.Equal("regular", adra.GameWorldType)
37+
assert.Equal("", adra.TournamentWorldType)
38+
39+
astera := worldsJson.Worlds.RegularWorlds[4]
40+
assert.Equal("Astera", astera.Name)
41+
assert.Equal("online", astera.Status)
42+
assert.Equal(222, astera.PlayersOnline)
43+
assert.Equal("North America", astera.Location)
44+
assert.Equal("Optional PvP", astera.PvpType)
45+
assert.Equal(false, astera.PremiumOnly)
46+
assert.Equal("regular", astera.TransferType)
47+
assert.Equal(true, astera.BattleyeProtected)
48+
assert.Equal("2017-09-12", astera.BattleyeDate)
49+
assert.Equal("regular", astera.GameWorldType)
50+
assert.Equal("", astera.TournamentWorldType)
51+
52+
endera := worldsJson.Worlds.TournamentWorlds[1]
53+
assert.Equal("Endera", endera.Name)
54+
assert.Equal("unknown", endera.Status)
55+
assert.Equal(0, endera.PlayersOnline)
56+
assert.Equal("North America", endera.Location)
57+
assert.Equal("Optional PvP", endera.PvpType)
58+
assert.Equal(true, endera.PremiumOnly)
59+
assert.Equal("blocked", endera.TransferType)
60+
assert.Equal(true, endera.BattleyeProtected)
61+
assert.Equal("release", endera.BattleyeDate)
62+
assert.Equal("tournament", endera.GameWorldType)
63+
assert.Equal("restricted", endera.TournamentWorldType)
64+
}

0 commit comments

Comments
 (0)