diff options
| author | Max | 2018-03-07 23:35:48 +0100 |
|---|---|---|
| committer | Max | 2018-03-07 23:35:48 +0100 |
| commit | 543f556fc2ae52f4f47f6241fa4fab33bec8d9fc (patch) | |
| tree | 380a0ff8e6006ff2d28a77796cdc071d21a940e9 | |
| download | dominion_cards-543f556fc2ae52f4f47f6241fa4fab33bec8d9fc.tar.gz | |
Initial commit.
| -rw-r--r-- | .gitignore | 5 | ||||
| -rw-r--r-- | crawler/card.go | 32 | ||||
| -rw-r--r-- | crawler/kingdom.go | 78 | ||||
| -rw-r--r-- | crawler/main.go | 146 | ||||
| -rw-r--r-- | crawler/set.go | 47 | ||||
| -rw-r--r-- | shuffle/card.go | 32 | ||||
| -rw-r--r-- | shuffle/main.go | 152 |
7 files changed, 492 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..391859d --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +*.swp +~ +crawler/crawler +shuffle/shuffle +*.json diff --git a/crawler/card.go b/crawler/card.go new file mode 100644 index 0000000..f7e8979 --- /dev/null +++ b/crawler/card.go @@ -0,0 +1,32 @@ +package main + +type Card struct { + Name string + Name_de string + URL string + Set string + Set_de string + Set_Image string + Type string + text string + //Text_de string + Actions string + Cards string + Buy string + Coin string + Trash string + Junk string + Gain string + Image string + IsEdition1 bool + IsEdition2 bool + IsKingdom bool + Cost Cost + //Cost string +} + +type Cost struct { + Coin int + Potion int + Debt int +} diff --git a/crawler/kingdom.go b/crawler/kingdom.go new file mode 100644 index 0000000..fb62cfb --- /dev/null +++ b/crawler/kingdom.go @@ -0,0 +1,78 @@ +package main + +import ( + "strings" +) + +func IsKingdom(Card Card, SplitPile []Card) bool { + + switch Card.Name { + case "Platinum": + return false + case "Gold": + return false + case "Silver": + return false + case "Copper": + return false + case "Province": + return false + case "Duchy": + return false + case "Estate": + return false + case "Curse": + return false + } + + switch Card.Type { + case "State": + return false + case "Hex": + return false + case "Boon": + return false + case "Landmark": + return false + case "Event": + return false + } + + if strings.Contains(Card.Type, "Prize") { + return false + } + if strings.Contains(Card.Type, "Ruins") { + return false + } + if strings.Contains(Card.Type, "Shelter") { + return false + } + if strings.Contains(Card.Type, "Heirloom") { + return false + } + + if strings.Contains(Card.text, "(This is not in the Supply.)") { + return false + } + + if strings.Contains(Card.Type, "Castle") && Card.Name != "Humble Castle" { + return false + } + + if IsSplitCardOnBottom(Card, SplitPile) { + return false + } + + return true +} + +func IsSplitCardOnBottom(Card Card, SplitPile []Card) bool { + for _, v := range SplitPile { + names := strings.Split(v.Name, "/") + if Card.Name == names[1] { + return true + } + } + + return false +} diff --git a/crawler/main.go b/crawler/main.go new file mode 100644 index 0000000..d91aa2e --- /dev/null +++ b/crawler/main.go @@ -0,0 +1,146 @@ +package main + +import ( + "encoding/json" + "fmt" + "log" + "regexp" + "strconv" + "strings" + + //"github.com/davecgh/go-spew/spew" + "github.com/gocolly/colly" +) + +func main() { + Cards_URL := "http://wiki.dominionstrategy.com/index.php/All_Cards" + + Cards := []Card{} + SplitPile := []Card{} + + c := colly.NewCollector( + colly.AllowedDomains("wiki.dominionstrategy.com"), + ) + + c.OnHTML("table.sortable tr", func(e *colly.HTMLElement) { + + var err error + + if e.Request.URL.String() != Cards_URL { + return + } + + card := Card{} + + e.ForEach("td", func(i int, e *colly.HTMLElement) { + switch i { + case 0: + card.Name = strings.TrimSpace(e.Text) + card.Image = "http://wiki.dominionstrategy.com" + e.ChildAttr("img", "src") + + card.URL = e.ChildAttr("a", "href") + case 1: + card.Set = strings.TrimSpace(e.Text) + + if strings.Contains(card.Set, "1E") { + card.Set = "Base" + card.IsEdition1 = true + } + if strings.Contains(card.Set, "2E") { + card.Set = "Base" + card.IsEdition2 = true + } + case 2: + card.Type = strings.TrimSpace(e.Text) + case 3: + cost := Cost{} + coin_costs := e.ChildAttrs(".coin-icon img", "alt") + for _, v := range coin_costs { + if strings.Contains(v, "$") { + cost.Coin, err = strconv.Atoi(strings.TrimSuffix(strings.TrimSuffix(strings.TrimPrefix(v, "$"), "star"), "plus")) + if err != nil { + log.Fatal(err) + } + } + if strings.Contains(v, "P") { + cost.Potion = 1 + } + } + debt_costs := e.ChildAttr(".debt-icon img", "alt") + if strings.Contains(debt_costs, "D") { + cost.Debt, err = strconv.Atoi(strings.TrimSuffix(debt_costs, "D")) + if err != nil { + log.Fatal(err) + } + } + card.Cost = cost + case 4: + card.text = strings.TrimSpace(e.Text) + case 5: + card.Actions = strings.TrimSpace(e.Text) + case 6: + card.Cards = strings.TrimSpace(e.Text) + case 7: + card.Buy = strings.TrimSpace(e.Text) + case 8: + card.Coin = strings.TrimSpace(strings.TrimPrefix(e.ChildAttr(".coin-img img", "alt"), "$")) + case 9: + card.Trash = strings.TrimSpace(e.Text) + case 10: + card.Junk = strings.TrimSpace(e.Text) + case 11: + card.Gain = strings.TrimSpace(e.Text) + } + + }) + + if strings.Contains(card.text, "Split pile containing 5 ") { + SplitPile = append(SplitPile, card) + } else { + + e.Request.Visit(card.URL) + card.Name_de = e.Request.Ctx.Get("name") + //card.Text_de = e.Request.Ctx.Get("desc") + Cards = append(Cards, card) + } + }) + + c.OnHTML(".wikitable tr", func(e *colly.HTMLElement) { + if e.Request.URL.String() == Cards_URL { + return + } + if e.ChildText("th") != "German" { + return + } + e.ForEach("td", func(i int, e *colly.HTMLElement) { + switch i { + case 0: + name_de := e.Text + + r := regexp.MustCompile(`(\(.+\))`) + name_de = strings.TrimSpace(r.ReplaceAllString(name_de, "")) + e.Request.Ctx.Put("name", name_de) + case 3: + //e.Request.Ctx.Put("desc", e.Text) + } + }) + }) + + c.Visit(Cards_URL) + + Output := []Card{} + for _, v := range Cards { + if v.Name == "" { + continue + } + v.IsKingdom = IsKingdom(v, SplitPile) + card := SetDetails(v) + Output = append(Output, card) + } + + j, err := json.MarshalIndent(Output, "", " ") + if err != nil { + log.Fatal(err) + } + fmt.Println(string(j)) +} diff --git a/crawler/set.go b/crawler/set.go new file mode 100644 index 0000000..dcd48f1 --- /dev/null +++ b/crawler/set.go @@ -0,0 +1,47 @@ +package main + +func SetDetails(card Card) Card { + switch card.Set { + case "Adventures": + card.Set_de = "Abenteuer" + card.Set_Image = "http://wiki.dominionstrategy.com/images/thumb/d/da/Adventures.jpg/298px-Adventures.jpg" + case "Alchemy": + card.Set_de = "Die Alchemisten" + card.Set_Image = "http://wiki.dominionstrategy.com/images/6/67/Alchemy.jpg" + case "Base": + card.Set_de = "Grundspiel" + card.Set_Image = "http://wiki.dominionstrategy.com/images/c/c4/Dominion.jpg" + case "Cornucopia": + card.Set_de = "Reiche Ernte" + card.Set_Image = "http://wiki.dominionstrategy.com/images/thumb/2/26/Cornucopia.jpg/201px-Cornucopia.jpg" + case "Dark Ages": + card.Set_de = "Dark Ages" + card.Set_Image = "http://wiki.dominionstrategy.com/images/thumb/d/dd/Dark_Ages.jpg/300px-Dark_Ages.jpg" + case "Empires": + card.Set_de = "Empires" + card.Set_Image = "http://wiki.dominionstrategy.com/images/thumb/0/0c/Empires.jpg/300px-Empires.jpg" + case "Guilds": + card.Set_de = "Gilden" + card.Set_Image = "http://wiki.dominionstrategy.com/images/thumb/0/02/Guilds.jpg/202px-Guilds.jpg" + case "Hinterlands": + card.Set_de = "Hinterland" + card.Set_Image = "http://wiki.dominionstrategy.com/images/thumb/a/a1/Hinterlands.jpg/299px-Hinterlands.jpg" + case "Intrigue": + card.Set_de = "Intrige" + card.Set_Image = "http://wiki.dominionstrategy.com/images/f/f2/Intrigue.jpg" + case "Nocturne": + card.Set_de = "Nocturne" + card.Set_Image = "http://wiki.dominionstrategy.com/images/thumb/7/7b/Nocturne.jpg/300px-Nocturne.jpg" + case "Promo": + card.Set_de = "Promo" + card.Set_Image = "" + case "Prosperity": + card.Set_de = "Blütezeit" + card.Set_Image = "http://wiki.dominionstrategy.com/images/9/97/Prosperity.jpg" + case "Seaside": + card.Set_de = "Seaside" + card.Set_Image = "http://wiki.dominionstrategy.com/images/3/37/Seaside.jpg" + } + + return card +} diff --git a/shuffle/card.go b/shuffle/card.go new file mode 100644 index 0000000..f7e8979 --- /dev/null +++ b/shuffle/card.go @@ -0,0 +1,32 @@ +package main + +type Card struct { + Name string + Name_de string + URL string + Set string + Set_de string + Set_Image string + Type string + text string + //Text_de string + Actions string + Cards string + Buy string + Coin string + Trash string + Junk string + Gain string + Image string + IsEdition1 bool + IsEdition2 bool + IsKingdom bool + Cost Cost + //Cost string +} + +type Cost struct { + Coin int + Potion int + Debt int +} diff --git a/shuffle/main.go b/shuffle/main.go new file mode 100644 index 0000000..fb178b6 --- /dev/null +++ b/shuffle/main.go @@ -0,0 +1,152 @@ +package main + +import ( + "encoding/json" + "flag" + "fmt" + "io/ioutil" + "log" + "math/rand" + "os" + "strings" + "time" +) + +func main() { + cards_f := flag.String("c", "../cards.json", "Path to json file with all cards.") + d_sets_f := flag.String("d", "", "Disabled Sets. (comma separated)") + o_sets_f := flag.String("o", "", "Only play with this sets. (comma separated)") + list_f := flag.Bool("l", false, "List all available sets.") + expired_f := flag.Bool("v1", false, "Play with (officially removed) cards (from the first edition)") + + flag.Parse() + + d_sets := strings.Split(*d_sets_f, ",") + sets := strings.Split(*o_sets_f, ",") + + raw, err := ioutil.ReadFile(*cards_f) + if err != nil { + log.Fatal(err) + } + + var cards []Card + var bane_card_needed bool + var bane_card Card + picked := make(map[string]bool) + json.Unmarshal(raw, &cards) + + if *list_f { + fmt.Println("List all available Editions:") + printed := make(map[string]bool) + for _, v := range cards { + if printed[v.Set_de] { + continue + } + fmt.Printf(" Name (en/de): '%s' / '%s'\n", v.Set, v.Set_de) + printed[v.Set_de] = true + } + return + } + + for i := 0; i < 10; i++ { + + v := get_card(cards, picked, sets, d_sets, *expired_f) + picked[v.Name] = true + + if v.Name_de == "Junge Hexe" { + bane_card_needed = true + for { + bane_card = get_card(cards, picked, sets, d_sets, *expired_f) + if bane_card.Cost.Coin == 2 || bane_card.Cost.Coin == 3 { + picked[bane_card.Name] = true + break + } + } + } + fmt.Printf("'%s' aus '%s' | Kosten: %d Münzen, %d Tränke, %d Schulden\n", v.Name_de, v.Set_de, v.Cost.Coin, v.Cost.Potion, v.Cost.Debt) + if bane_card_needed { + fmt.Printf(" Bannkarte: '%s' aus '%s' | Kosten: %d Münzen, %d Tränke, %d Schulden\n", bane_card.Name_de, bane_card.Set_de, bane_card.Cost.Coin, bane_card.Cost.Potion, bane_card.Cost.Debt) + bane_card_needed = false + } + } +} + +func get_card(cards []Card, picked map[string]bool, sets []string, d_sets []string, v1 bool) Card { + for { + + r := rand.New(rand.NewSource(time.Now().UnixNano())) + rndm := r.Int() % len(cards) + + if !cards[rndm].IsKingdom { + continue + } + if v1 { + // play with removed cards from base v1 + if cards[rndm].IsEdition2 { + continue + } + } else { + if cards[rndm].IsEdition1 { + continue + } + } + if picked[cards[rndm].Name] { + continue + } + if len(d_sets) > 0 && d_sets[0] != "" { + _set := setExists(d_sets, cards) + if "" != _set { + fmt.Println("Error: This set does not exists. (" + _set + ")") + os.Exit(1) + } + if stringInSlice(cards[rndm].Set, d_sets) || stringInSlice(cards[rndm].Set_de, d_sets) { + continue + } else { + return cards[rndm] + } + } + if len(sets) > 0 && sets[0] != "" { + _set := setExists(sets, cards) + if "" != _set { + fmt.Println("Error: This set does not exists. (" + _set + ")") + os.Exit(1) + } + if stringInSlice(cards[rndm].Set, sets) || stringInSlice(cards[rndm].Set_de, sets) { + return cards[rndm] + } else { + continue + } + } + return cards[rndm] + } + return Card{} +} + +func stringInSlice(a string, list []string) bool { + a = strings.ToLower(a) + for _, b := range list { + b = strings.TrimSpace(strings.ToLower(b)) + if b == a { + return true + } + } + return false +} + +func setExists(sets []string, cards []Card) string { + matched := make(map[string]bool) + for _, set := range sets { + for _, v := range cards { + if strings.ToLower(set) == strings.ToLower(v.Set_de) || strings.ToLower(set) == strings.ToLower(v.Set) { + matched[set] = true + } + } + } + for _, set := range sets { + if !matched[set] { + return set + } + } + return "" + +} |
