Make HTTP server and URL customizable
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
Tests now do not require internet access anymore Closes #4
This commit is contained in:
parent
c2d3b3b679
commit
37645e37f7
6 changed files with 261 additions and 11 deletions
|
@ -108,7 +108,7 @@ func (set *Set) PackSchema() draft.PackSchema {
|
||||||
|
|
||||||
// ProviderByRarity returns a provider for a given rarity level from a given set
|
// ProviderByRarity returns a provider for a given rarity level from a given set
|
||||||
func (set *Set) ProviderByRarity(rarity Rarity) draft.CardProvider {
|
func (set *Set) ProviderByRarity(rarity Rarity) draft.CardProvider {
|
||||||
var collection []draft.Card
|
collection := []draft.Card{}
|
||||||
// RR flow is super easy, just pick one from our hardcoded list
|
// RR flow is super easy, just pick one from our hardcoded list
|
||||||
if rarity == RarityRoyalRare {
|
if rarity == RarityRoyalRare {
|
||||||
rr, ok := royalRares[set.ID]
|
rr, ok := royalRares[set.ID]
|
||||||
|
@ -126,6 +126,10 @@ func (set *Set) ProviderByRarity(rarity Rarity) draft.CardProvider {
|
||||||
}
|
}
|
||||||
return func(n int) []draft.Card {
|
return func(n int) []draft.Card {
|
||||||
out := make([]draft.Card, n)
|
out := make([]draft.Card, n)
|
||||||
|
if len(collection) < 1 {
|
||||||
|
// Something really wrong happened here
|
||||||
|
return out
|
||||||
|
}
|
||||||
for n := range out {
|
for n := range out {
|
||||||
// Pick a RR at random
|
// Pick a RR at random
|
||||||
idx := rand.Intn(len(collection))
|
idx := rand.Intn(len(collection))
|
||||||
|
|
|
@ -9,7 +9,6 @@ import (
|
||||||
|
|
||||||
// TestAlternates tries to get alternates (SR/UR/RR)
|
// TestAlternates tries to get alternates (SR/UR/RR)
|
||||||
// This might require a while since it needs to generate MANY packs!
|
// This might require a while since it needs to generate MANY packs!
|
||||||
// This test *requires* an internet connection!
|
|
||||||
func TestAlternates(t *testing.T) {
|
func TestAlternates(t *testing.T) {
|
||||||
// Load Premiere/CN as they have their own UR ratios
|
// Load Premiere/CN as they have their own UR ratios
|
||||||
prSet, err := mlp.LoadSetHTTP(mlp.SetPremiere)
|
prSet, err := mlp.LoadSetHTTP(mlp.SetPremiere)
|
||||||
|
|
|
@ -89,6 +89,12 @@ func LoadSetBytes(id SetID, setdata []byte) (*Set, error) {
|
||||||
return &set, err
|
return &set, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// HTTPClient is the HTTP client used in LoadSetHTTP
|
||||||
|
var HTTPClient = http.DefaultClient
|
||||||
|
|
||||||
|
// HTTPSource is the base URL for fetching sets remotely via HTTP
|
||||||
|
var HTTPSource = "https://mcg.zyg.ovh/setdata/"
|
||||||
|
|
||||||
// LoadSetHTTP loads a set using MCG's remote server
|
// LoadSetHTTP loads a set using MCG's remote server
|
||||||
func LoadSetHTTP(id SetID) (*Set, error) {
|
func LoadSetHTTP(id SetID) (*Set, error) {
|
||||||
// Check if set is already loaded
|
// Check if set is already loaded
|
||||||
|
@ -99,7 +105,7 @@ func LoadSetHTTP(id SetID) (*Set, error) {
|
||||||
// Get SetID as string and make it lowercase
|
// Get SetID as string and make it lowercase
|
||||||
setid := strings.ToLower(string(id))
|
setid := strings.ToLower(string(id))
|
||||||
|
|
||||||
resp, err := http.Get("https://mcg.zyg.ovh/setdata/" + setid + ".json")
|
resp, err := HTTPClient.Get(HTTPSource + setid + ".json")
|
||||||
if err != nil || resp.StatusCode != 200 {
|
if err != nil || resp.StatusCode != 200 {
|
||||||
if err == nil {
|
if err == nil {
|
||||||
err = fmt.Errorf("server returned non-200 response code (%d)", resp.StatusCode)
|
err = fmt.Errorf("server returned non-200 response code (%d)", resp.StatusCode)
|
||||||
|
|
|
@ -1,25 +1,29 @@
|
||||||
package mlp_test
|
package mlp_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
"net/http/httptest"
|
||||||
|
"os"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"git.fromouter.space/mcg/draft"
|
"git.fromouter.space/mcg/draft"
|
||||||
"git.fromouter.space/mcg/draft/mlp"
|
"git.fromouter.space/mcg/draft/mlp"
|
||||||
|
"git.fromouter.space/mcg/draft/mlp/testdata"
|
||||||
)
|
)
|
||||||
|
|
||||||
// TestSet retrieves a set online and generates a couple packs with it
|
// TestSet retrieves a set online and generates a couple packs with it
|
||||||
// This test *requires* an internet connection!
|
|
||||||
func TestSet(t *testing.T) {
|
func TestSet(t *testing.T) {
|
||||||
// Clean all loaded sets
|
// Clean all loaded sets
|
||||||
mlp.CleanSetCache()
|
mlp.CleanSetCache()
|
||||||
|
|
||||||
deSet, err := mlp.LoadSetHTTP(mlp.SetDefendersOfEquestria)
|
prSet, err := mlp.LoadSetHTTP(mlp.SetPremiere)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Could not fetch set data: %s", err.Error())
|
t.Fatalf("Could not fetch set data: %s", err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
pack1 := draft.MakePack(deSet)
|
pack1 := draft.MakePack(prSet)
|
||||||
pack2 := draft.MakePack(deSet)
|
pack2 := draft.MakePack(prSet)
|
||||||
|
|
||||||
// Make sure both packs have the exact number of cards
|
// Make sure both packs have the exact number of cards
|
||||||
if len(pack1) != 12 {
|
if len(pack1) != 12 {
|
||||||
|
@ -34,7 +38,6 @@ func TestSet(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestWrongSet tries to fetch a set that doesn't exist
|
// TestWrongSet tries to fetch a set that doesn't exist
|
||||||
// This test *requires* an internet connection!
|
|
||||||
func TestWrongSet(t *testing.T) {
|
func TestWrongSet(t *testing.T) {
|
||||||
_, err := mlp.LoadSetHTTP("nopenope")
|
_, err := mlp.LoadSetHTTP("nopenope")
|
||||||
if err == nil {
|
if err == nil {
|
||||||
|
@ -43,13 +46,12 @@ func TestWrongSet(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestAllLoads tests all the LoadSet* functions
|
// TestAllLoads tests all the LoadSet* functions
|
||||||
// This test *requires* an internet connection!
|
|
||||||
func TestAllLoads(t *testing.T) {
|
func TestAllLoads(t *testing.T) {
|
||||||
// Clean all loaded sets
|
// Clean all loaded sets
|
||||||
mlp.CleanSetCache()
|
mlp.CleanSetCache()
|
||||||
|
|
||||||
// Test LoadSetHTTP
|
// Test LoadSetHTTP
|
||||||
_, err := mlp.LoadSetHTTP(mlp.SetAbsoluteDiscord)
|
_, err := mlp.LoadSetHTTP(mlp.SetFriendsForever)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("[LoadSetHTTP] Could not fetch set data from the internet: %s", err.Error())
|
t.Fatalf("[LoadSetHTTP] Could not fetch set data from the internet: %s", err.Error())
|
||||||
}
|
}
|
||||||
|
@ -157,4 +159,31 @@ func TestMalformedJSONLoad(t *testing.T) {
|
||||||
if err == nil {
|
if err == nil {
|
||||||
t.Fatalf("LoadSetData with invalid data succeeded but shouldn't have")
|
t.Fatalf("LoadSetData with invalid data succeeded but shouldn't have")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_, err = mlp.LoadSetHTTP(mlp.SetID("broken"))
|
||||||
|
if err == nil {
|
||||||
|
t.Fatalf("LoadSetHTTP with invalid JSON succeded but shouldn't have")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var testServer *httptest.Server
|
||||||
|
|
||||||
|
func TestMain(m *testing.M) {
|
||||||
|
testServer = httptest.NewServer(http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) {
|
||||||
|
switch req.URL.Path {
|
||||||
|
case "/nopenope.json":
|
||||||
|
// 404
|
||||||
|
http.Error(res, "Not found", http.StatusNotFound)
|
||||||
|
case "/broken.json":
|
||||||
|
// Broken response
|
||||||
|
fmt.Fprintf(res, "{{{{")
|
||||||
|
case "/pr.json":
|
||||||
|
fmt.Fprintf(res, testdata.SetPremiere)
|
||||||
|
default:
|
||||||
|
fmt.Fprintf(res, testdata.SetFriendForever)
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
mlp.HTTPSource = testServer.URL + "/"
|
||||||
|
defer testServer.Close()
|
||||||
|
os.Exit(m.Run())
|
||||||
}
|
}
|
||||||
|
|
212
mlp/testdata/sets.go
vendored
Normal file
212
mlp/testdata/sets.go
vendored
Normal file
|
@ -0,0 +1,212 @@
|
||||||
|
package testdata
|
||||||
|
|
||||||
|
// SetFriendForever is an excerpt from Friend Forever's JSON set data
|
||||||
|
const SetFriendForever = `{
|
||||||
|
"Name": "Friends Forever",
|
||||||
|
"Cards": [
|
||||||
|
{
|
||||||
|
"ID": "ff1",
|
||||||
|
"Name": "Gallus",
|
||||||
|
"Subname": "Full of Surprises",
|
||||||
|
"Element": [
|
||||||
|
"Loyalty"
|
||||||
|
],
|
||||||
|
"Keywords": [
|
||||||
|
"Home Limit 3"
|
||||||
|
],
|
||||||
|
"Traits": [
|
||||||
|
"Griffon"
|
||||||
|
],
|
||||||
|
"Power": 1,
|
||||||
|
"Type": "Mane Character",
|
||||||
|
"Text": "When you confront this card's Problem, turn this card over.",
|
||||||
|
"Rarity": "U"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ID": "ff3",
|
||||||
|
"Name": "Ocellus",
|
||||||
|
"Subname": "Knowledge is Power",
|
||||||
|
"Element": [
|
||||||
|
"Generosity"
|
||||||
|
],
|
||||||
|
"Keywords": [
|
||||||
|
"Home Limit 3"
|
||||||
|
],
|
||||||
|
"Traits": [
|
||||||
|
"Changeling"
|
||||||
|
],
|
||||||
|
"Power": 1,
|
||||||
|
"Type": "Mane Character",
|
||||||
|
"Text": "When you confront this card's Problem, turn this card over.",
|
||||||
|
"Rarity": "U"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ID": "ff4",
|
||||||
|
"Name": "Chipcutter",
|
||||||
|
"Subname": "Sculptor",
|
||||||
|
"Element": [
|
||||||
|
"Loyalty"
|
||||||
|
],
|
||||||
|
"Keywords": [
|
||||||
|
"Swift"
|
||||||
|
],
|
||||||
|
"Traits": [
|
||||||
|
"Pegasus",
|
||||||
|
"Foal"
|
||||||
|
],
|
||||||
|
"Cost": 3,
|
||||||
|
"Power": 2,
|
||||||
|
"Type": "Friend",
|
||||||
|
"Text": "",
|
||||||
|
"Rarity": "C"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ID": "ff5",
|
||||||
|
"Name": "Daybreaker",
|
||||||
|
"Subname": "Blinding Light",
|
||||||
|
"Element": [
|
||||||
|
"Loyalty"
|
||||||
|
],
|
||||||
|
"Keywords": [
|
||||||
|
"Competitive 3"
|
||||||
|
],
|
||||||
|
"Traits": [
|
||||||
|
"Alicorn",
|
||||||
|
"Royalty"
|
||||||
|
],
|
||||||
|
"Requirement": {
|
||||||
|
"Loyalty": 3
|
||||||
|
},
|
||||||
|
"Cost": 3,
|
||||||
|
"Power": 3,
|
||||||
|
"Type": "Friend",
|
||||||
|
"Text": "When you win a faceoff involving this card, score a point.",
|
||||||
|
"Rarity": "SR"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ID": "ff131",
|
||||||
|
"Name": "Silverstream",
|
||||||
|
"Subname": "Everything's New!",
|
||||||
|
"Element": [
|
||||||
|
"Laughter"
|
||||||
|
],
|
||||||
|
"Keywords": [
|
||||||
|
"Home Limit 3"
|
||||||
|
],
|
||||||
|
"Traits": [
|
||||||
|
"Ally",
|
||||||
|
"Hippogriff"
|
||||||
|
],
|
||||||
|
"Power": 1,
|
||||||
|
"Type": "Mane Character",
|
||||||
|
"Text": "Immediate: While this card is at a Problem with 2 or more other characters, turn this card over.",
|
||||||
|
"Rarity": "UR"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}`
|
||||||
|
|
||||||
|
// SetPremiere is an excerpt from Premiere's JSON set data
|
||||||
|
const SetPremiere = `{
|
||||||
|
"Name": "Premiere",
|
||||||
|
"Cards": [
|
||||||
|
{
|
||||||
|
"ID": "pr54",
|
||||||
|
"Name": "Comet Tail",
|
||||||
|
"Subname": "Hale Bopper",
|
||||||
|
"Element": [
|
||||||
|
"Magic"
|
||||||
|
],
|
||||||
|
"Keywords": [],
|
||||||
|
"Traits": [
|
||||||
|
"Unicorn"
|
||||||
|
],
|
||||||
|
"Cost": 1,
|
||||||
|
"Power": 1,
|
||||||
|
"Type": "Friend",
|
||||||
|
"Text": "",
|
||||||
|
"Rarity": "C"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ID": "pr55",
|
||||||
|
"Name": "Mint Jewelup",
|
||||||
|
"Subname": "A Cut Above",
|
||||||
|
"Element": [
|
||||||
|
"Magic"
|
||||||
|
],
|
||||||
|
"Keywords": [],
|
||||||
|
"Traits": [
|
||||||
|
"Unicorn"
|
||||||
|
],
|
||||||
|
"Requirement": {
|
||||||
|
"Magic": 2
|
||||||
|
},
|
||||||
|
"Cost": 2,
|
||||||
|
"Power": 1,
|
||||||
|
"Type": "Friend",
|
||||||
|
"Text": "Studious.",
|
||||||
|
"Rarity": "C"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ID": "pr56",
|
||||||
|
"Name": "Gyro",
|
||||||
|
"Subname": "Poindexter",
|
||||||
|
"Element": [
|
||||||
|
"Magic"
|
||||||
|
],
|
||||||
|
"Keywords": [],
|
||||||
|
"Traits": [
|
||||||
|
"Earth Pony"
|
||||||
|
],
|
||||||
|
"Requirement": {
|
||||||
|
"Magic": 3
|
||||||
|
},
|
||||||
|
"Cost": 1,
|
||||||
|
"Power": 1,
|
||||||
|
"Type": "Friend",
|
||||||
|
"Text": "When you play this card, you may search your deck for an Event, reveal it, put it into your hand, and shuffle your deck.",
|
||||||
|
"Rarity": "R"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ID": "pr77",
|
||||||
|
"Name": "Rarity",
|
||||||
|
"Subname": "Nest Weaver",
|
||||||
|
"Element": [
|
||||||
|
"Generosity"
|
||||||
|
],
|
||||||
|
"Keywords": [
|
||||||
|
"Inspired"
|
||||||
|
],
|
||||||
|
"Traits": [
|
||||||
|
"Unicorn"
|
||||||
|
],
|
||||||
|
"Requirement": {
|
||||||
|
"Generosity": 3
|
||||||
|
},
|
||||||
|
"Cost": 3,
|
||||||
|
"Power": 2,
|
||||||
|
"Type": "Friend",
|
||||||
|
"Text": "When you play this card, you may search your discard pile for a card and put it into your hand.",
|
||||||
|
"Rarity": "U"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ID": "pr211",
|
||||||
|
"Name": "Fluttershy",
|
||||||
|
"Subname": "Monster Tamer",
|
||||||
|
"Element": [
|
||||||
|
"Kindness"
|
||||||
|
],
|
||||||
|
"Keywords": [],
|
||||||
|
"Traits": [
|
||||||
|
"Pegasus"
|
||||||
|
],
|
||||||
|
"Requirement": {
|
||||||
|
"Kindness": 4
|
||||||
|
},
|
||||||
|
"Cost": 4,
|
||||||
|
"Power": 2,
|
||||||
|
"Type": "Friend",
|
||||||
|
"Text": "When you play this card to a Problem, you may banish a Troublemaker there. When this card leaves that Problem, put that banished Troublemaker into play at a Problem and uncover it.",
|
||||||
|
"Rarity": "UR"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}`
|
|
@ -2,7 +2,7 @@ package mlp
|
||||||
|
|
||||||
import "git.fromouter.space/mcg/draft"
|
import "git.fromouter.space/mcg/draft"
|
||||||
|
|
||||||
// Converts multiple mlp.Card to draft.Card
|
// ToDraft converts multiple mlp.Card to draft.Card
|
||||||
func ToDraft(cards []Card) []draft.Card {
|
func ToDraft(cards []Card) []draft.Card {
|
||||||
out := make([]draft.Card, len(cards))
|
out := make([]draft.Card, len(cards))
|
||||||
for i, card := range cards {
|
for i, card := range cards {
|
||||||
|
|
Loading…
Reference in a new issue