Created
January 27, 2018 15:00
-
-
Save kbl/86ed3b2112eb80522949f0ce574a04e3 to your computer and use it in GitHub Desktop.
Mathandel script
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"fmt" | |
"net/http" | |
"log" | |
"io/ioutil" | |
"strings" | |
"encoding/xml" | |
"strconv" | |
"regexp" | |
) | |
const geekList = "https://www.boardgamegeek.com/xmlapi/geeklist/235895" | |
const geekListFile = "/home/mapi/Desktop/235895.xml" | |
const gameTemplate = "https://www.boardgamegeek.com/xmlapi/boardgame/%d?pricehistory=1&stats=1" | |
const gameTemplateFile = "/home/mapi/Desktop/126000.xml" | |
type Geeklist struct { | |
XMLName xml.Name `xml:"geeklist"` | |
Items []Item `xml:"item"` | |
} | |
type Item struct { | |
Ordinal int `xml:"id,attr"` | |
GameId int `xml:"objectid,attr"` | |
Name string `xml:"objectname,attr"` | |
Description string `xml:"body"` | |
} | |
type Boardgames struct { | |
XMLName xml.Name `xml:"boardgames"` | |
Boardgame Boardgame `xml:"boardgame"` | |
} | |
type Boardgame struct { | |
Year int `xml:"yearpublished"` | |
Awards []string `xml:"boardgamehonor"` | |
Categories []string `xml:"boardgamecategory"` | |
Mechanics []string `xml:"boardgamemechanic"` | |
Rating float64 `xml:"statistics>ratings>average"` | |
Geekrating float64 `xml:"statistics>ratings>bayesaverage"` | |
Listings []Listing `xml:"marketplacehistory>listing"` | |
} | |
type Listing struct { | |
Body string `xml:",innerxml"` | |
} | |
// --- | |
type GameMetadata struct { | |
Name string | |
Id int | |
Year int | |
Awards int | |
Mechanics []string | |
Categories []string | |
Rating float64 | |
PriceUSD float64 | |
PriceEUR float64 | |
} | |
func main() { | |
fmt.Println(1) | |
r := fetchUrl(geekList) | |
var geeklist Geeklist | |
xml.Unmarshal(r, &geeklist) | |
ch := make(chan GameMetadata) | |
gameNames := make(map[int]string) | |
gameOccurences := make(map[int][]int) | |
gameMetas := make(map[int]GameMetadata) | |
for i, g := range geeklist.Items { | |
gameNames[g.GameId] = g.Name | |
gameOccurences[g.GameId] = append(gameOccurences[g.GameId], i + 1) | |
} | |
fmt.Println(len(gameNames)) | |
for id, name := range gameNames { | |
if id > 500 { | |
break | |
} | |
go fetchGameMetadata(ch, id, name) | |
} | |
for i, _ := range gameNames { | |
meta := <-ch | |
fmt.Sprintln("dong %d! ", (i + 1)) | |
gameMetas[meta.Id] = meta | |
} | |
fmt.Println(gameMetas) | |
} | |
func fetchGameMetadata(ch chan<- GameMetadata, id int, name string) GameMetadata { | |
r := fetchUrl(fmt.Sprintf(gameTemplate, id)) | |
var boardgames Boardgames | |
xml.Unmarshal(r, &boardgames) | |
game := boardgames.Boardgame | |
prices := countAveragePrice(game.Listings) | |
var priceUSD float64 | |
if val, ok := prices["USD,new"]; ok { | |
priceUSD = val | |
} else if val, ok := prices["USD,likenew"]; ok { | |
priceUSD = val | |
} | |
var priceEUR float64 | |
if val, ok := prices["EUR,new"]; ok { | |
priceEUR = val | |
} else if val, ok := prices["EUR,likenew"]; ok { | |
priceEUR = val | |
} | |
return GameMetadata{ | |
name, | |
id, | |
game.Year, | |
len(game.Awards), | |
game.Mechanics, | |
game.Categories, | |
game.Rating, | |
priceUSD, | |
priceEUR} | |
} | |
func fetchUrl(url string) []byte { | |
if strings.HasPrefix(url, "http") { | |
r, err := http.Get(url) | |
handleErr(err) | |
defer r.Body.Close() | |
b, err := ioutil.ReadAll(r.Body) | |
handleErr(err) | |
return b | |
} | |
b, err := ioutil.ReadFile(url) | |
handleErr(err) | |
return b | |
} | |
func handleErr(err error) { | |
if err != nil { | |
log.Fatal(err) | |
} | |
} | |
func countAveragePrice(listings []Listing) map[string]float64 { | |
rPrice, err := regexp.Compile("<price currency='(.+)'>([0-9.]+)</price>") | |
handleErr(err) | |
rCondition, err := regexp.Compile("<condition>(.+)</condition>") | |
handleErr(err) | |
m := make(map[string]map[string][]float64) | |
for _, l := range listings { | |
match := rPrice.FindStringSubmatch(l.Body) | |
currency := match[1] | |
if currency == "USD" || currency == "EUR" { | |
price, err := strconv.ParseFloat(match[2], 64) | |
handleErr(err) | |
match = rCondition.FindStringSubmatch(l.Body) | |
condition := match[1] | |
if condition == "new" || condition == "likenew" { | |
if m[currency] == nil { | |
m[currency] = make(map[string][]float64) | |
} | |
m[currency][condition] = append(m[currency][condition], price) | |
} | |
} | |
} | |
ret := make(map[string]float64) | |
for cur, mm := range m { | |
for con, prices := range mm { | |
var sum float64 | |
for _, p := range prices { | |
sum += p | |
} | |
ret[fmt.Sprintf("%s,%s", cur, con)] = sum / float64(len(prices)) | |
} | |
} | |
return ret | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment