311 lines
9.6 KiB
Go
311 lines
9.6 KiB
Go
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"log"
|
|
"sort"
|
|
"strconv"
|
|
"strings"
|
|
"unsafe"
|
|
|
|
"github.com/pocketbase/pocketbase/core"
|
|
)
|
|
|
|
type CacheBrawlsetListItem struct {
|
|
Name string
|
|
SanitizedName string
|
|
IconsSvgUri []string
|
|
}
|
|
|
|
type CacheCarteListItem struct {
|
|
Name string
|
|
Url string
|
|
Layout string
|
|
SmallImage string
|
|
SmallImageBack string
|
|
NormalImage string
|
|
NormalImageBack string
|
|
Price float64
|
|
CardmarketUri string
|
|
NumberOfDecks int
|
|
NumberOfPossibleDecks int
|
|
PercentageOfDecks float64
|
|
Synergy float64
|
|
}
|
|
|
|
type CacheCarteListItemWithSynergy struct {
|
|
MainCard CacheCarteListItem
|
|
CanBeCommander bool
|
|
Cards map[string][]CacheCarteListItem
|
|
}
|
|
|
|
type CacheCarteSearch struct {
|
|
Name string
|
|
Url string
|
|
SetName string
|
|
}
|
|
|
|
type CacheBrawlsetData struct {
|
|
Name string
|
|
SanitizedName string
|
|
Cards map[string][]CacheCarteListItem
|
|
}
|
|
|
|
func (app *application) SetupCache() {
|
|
app.pb.OnBootstrap().BindFunc(func(e *core.BootstrapEvent) error {
|
|
if err := e.Next(); err != nil {
|
|
return err
|
|
}
|
|
|
|
GenerateCache(e.App)
|
|
|
|
return nil
|
|
})
|
|
}
|
|
|
|
func GenerateCache(pb core.App) {
|
|
log.Println("Creating json data cache...")
|
|
defer timer("Generating cache")()
|
|
var totalSize int64
|
|
|
|
brawlsets := []Brawlset{}
|
|
mtgSetsQuery := []MtgSet{}
|
|
mtgSets := map[string]MtgSet{}
|
|
cardsQuery := []Carte{}
|
|
cards := map[string]Carte{}
|
|
cacheCardsSearch := []CacheCarteSearch{}
|
|
cardsBySet := map[string][]Carte{}
|
|
decks := []Deck{}
|
|
decksByBset := map[string][]Deck{}
|
|
|
|
err := pb.DB().
|
|
NewQuery("SELECT * FROM brawlset").
|
|
All(&brawlsets)
|
|
if err != nil {
|
|
log.Println(fmt.Sprintf("[ERROR] %v", err))
|
|
}
|
|
|
|
err = pb.DB().
|
|
NewQuery("SELECT * FROM mtg_set").
|
|
All(&mtgSetsQuery)
|
|
if err != nil {
|
|
log.Println(fmt.Sprintf("[ERROR] %v", err))
|
|
}
|
|
|
|
err = pb.DB().
|
|
NewQuery("SELECT * FROM deck").
|
|
All(&decks)
|
|
if err != nil {
|
|
log.Println(fmt.Sprintf("[ERROR] %v", err))
|
|
}
|
|
|
|
for _, v := range decks {
|
|
decksByBset[v.Brawlset] = append(decksByBset[v.Brawlset], v)
|
|
}
|
|
|
|
err = pb.DB().
|
|
NewQuery("SELECT * FROM carte").
|
|
All(&cardsQuery)
|
|
if err != nil {
|
|
log.Println(fmt.Sprintf("[ERROR] %v", err))
|
|
}
|
|
|
|
for _, v := range mtgSetsQuery {
|
|
mtgSets[v.ID] = v
|
|
}
|
|
|
|
for _, v := range cardsQuery {
|
|
cards[v.ID] = v
|
|
cardsBySet[v.MtgSet] = append(cardsBySet[v.MtgSet], v)
|
|
cacheCardsSearch = append(cacheCardsSearch, CacheCarteSearch{ Name: v.Name, Url: fmt.Sprintf("/card/%s-%s", v.SetCode,v.SanitizedName), SetName: mtgSets[v.MtgSet].Name})
|
|
}
|
|
|
|
totalSize += int64(unsafe.Sizeof(cacheCardsSearch))
|
|
pb.Store().Set("searchData", cacheCardsSearch)
|
|
|
|
cacheColorCommanderTop := map[string][]CacheCarteListItem{}
|
|
|
|
cacheBrawlsetList := []CacheBrawlsetListItem{}
|
|
for _, v := range brawlsets {
|
|
setIconList := []string{}
|
|
numberOfDecksPerColorIdentity := map[string]int{}
|
|
cacheBrawlsetData := CacheBrawlsetData{Name: v.Name, SanitizedName: v.SanitizedName, Cards: map[string][]CacheCarteListItem{}}
|
|
numberOfDecksPerCard := map[string]int{}
|
|
synergyPerCards := map[string]map[string]int{}
|
|
|
|
for _, d := range decksByBset[v.ID] {
|
|
|
|
possibleColorIdentities := GetAllColorCombination(d.ColorIdentity)
|
|
for _, color := range possibleColorIdentities {
|
|
if _, ok := numberOfDecksPerColorIdentity[color]; ok {
|
|
numberOfDecksPerColorIdentity[color]++
|
|
} else {
|
|
numberOfDecksPerColorIdentity[color] += 1
|
|
}
|
|
}
|
|
// Increment number of deck for commander
|
|
if _, ok := numberOfDecksPerCard[fmt.Sprintf("c-%s",d.Commander)]; ok {
|
|
numberOfDecksPerCard[fmt.Sprintf("c-%s",d.Commander)]++
|
|
} else {
|
|
numberOfDecksPerCard[fmt.Sprintf("c-%s",d.Commander)] = 1
|
|
}
|
|
|
|
// Increment number of deck for each card
|
|
for _, c := range d.Cards {
|
|
if _, ok := synergyPerCards[fmt.Sprintf("c-%s",d.Commander)]; !ok {
|
|
synergyPerCards[fmt.Sprintf("c-%s", d.Commander)] = map[string]int{}
|
|
}
|
|
if _, ok := synergyPerCards[fmt.Sprintf("c-%s",d.Commander)][c.ID]; ok {
|
|
synergyPerCards[fmt.Sprintf("c-%s",d.Commander)][c.ID]++
|
|
} else {
|
|
synergyPerCards[fmt.Sprintf("c-%s",d.Commander)][c.ID] = 1
|
|
}
|
|
|
|
// Add number of decks per card
|
|
if _, ok := numberOfDecksPerCard[c.ID]; ok {
|
|
numberOfDecksPerCard[c.ID]++
|
|
} else {
|
|
numberOfDecksPerCard[c.ID] = 1
|
|
}
|
|
|
|
// Add number of decks with the two same cards for synergy
|
|
for _, tc := range d.Cards {
|
|
if _, ok := synergyPerCards[c.ID]; !ok {
|
|
synergyPerCards[c.ID] = map[string]int{}
|
|
}
|
|
|
|
if _, ok := synergyPerCards[c.ID][tc.ID]; ok {
|
|
synergyPerCards[c.ID][tc.ID]++
|
|
} else {
|
|
synergyPerCards[c.ID][tc.ID] = 1
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
for _, s := range v.Sets {
|
|
setIconList = append(setIconList, mtgSets[s].IconUri)
|
|
for _, c := range cardsBySet[s] {
|
|
obj := CreateCardData(c, decksByBset, numberOfDecksPerColorIdentity, numberOfDecksPerCard, v.ID)
|
|
cacheBrawlsetData.Cards[c.CardType] = append(cacheBrawlsetData.Cards[c.CardType], obj)
|
|
|
|
if c.CanBeCommander {
|
|
obj.NumberOfDecks = numberOfDecksPerCard[fmt.Sprintf("c-%s",c.ID)]
|
|
obj.Url = fmt.Sprintf("/commander/%s-%s", c.SetCode,c.SanitizedName)
|
|
colorIdentity := ""
|
|
if len(c.ColorIdentity) == 0 {
|
|
colorIdentity = "colorless"
|
|
} else {
|
|
colorIdentity = strings.Join(c.ColorIdentity, "")
|
|
}
|
|
cacheColorCommanderTop[colorIdentity] = append(cacheColorCommanderTop[colorIdentity], obj)
|
|
cacheColorCommanderTop["all"] = append(cacheColorCommanderTop["all"], obj)
|
|
cacheBrawlsetData.Cards["commander"] = append(cacheBrawlsetData.Cards["commander"], obj)
|
|
|
|
detailsObj := CacheCarteListItemWithSynergy{
|
|
MainCard: obj,
|
|
CanBeCommander: true,
|
|
Cards: map[string][]CacheCarteListItem{},
|
|
}
|
|
|
|
// Add each card that already appeared in a deck
|
|
for k := range synergyPerCards[fmt.Sprintf("c-%s",c.ID)] {
|
|
synergyObj := CreateCardData(cards[k], decksByBset, numberOfDecksPerColorIdentity, numberOfDecksPerCard, v.ID)
|
|
|
|
synergy := 0 - synergyObj.PercentageOfDecks
|
|
if numberOfDecksPerCard[fmt.Sprintf("c-%s",c.ID)] != 0 {
|
|
synergy = (float64(synergyPerCards[fmt.Sprintf("c-%s",c.ID)][k]) / float64(numberOfDecksPerCard[fmt.Sprintf("c-%s",c.ID)])) - synergyObj.PercentageOfDecks
|
|
}
|
|
synergyObj.Synergy = synergy
|
|
|
|
detailsObj.Cards[cards[k].CardType] = append(detailsObj.Cards[cards[k].CardType], synergyObj)
|
|
}
|
|
|
|
for k := range detailsObj.Cards {
|
|
sort.Slice(detailsObj.Cards[k], func(i, j int) bool {
|
|
if detailsObj.Cards[k][i].Synergy == detailsObj.Cards[k][j].Synergy {
|
|
return detailsObj.Cards[k][i].PercentageOfDecks > detailsObj.Cards[k][j].PercentageOfDecks
|
|
}
|
|
return detailsObj.Cards[k][i].Synergy > detailsObj.Cards[k][j].Synergy
|
|
})
|
|
}
|
|
|
|
totalSize += int64(unsafe.Sizeof(detailsObj))
|
|
pb.Store().Set(fmt.Sprintf("json/commander/%s-%s", c.SetCode, c.SanitizedName), detailsObj)
|
|
}
|
|
}
|
|
}
|
|
|
|
for k := range cacheBrawlsetData.Cards {
|
|
if k == "commander" {
|
|
sort.Slice(cacheBrawlsetData.Cards[k], func(i, j int) bool { return cacheBrawlsetData.Cards[k][i].NumberOfDecks > cacheBrawlsetData.Cards[k][j].NumberOfDecks})
|
|
} else {
|
|
sort.Slice(cacheBrawlsetData.Cards[k], func(i, j int) bool {
|
|
if cacheBrawlsetData.Cards[k][i].PercentageOfDecks == cacheBrawlsetData.Cards[k][j].PercentageOfDecks {
|
|
return cacheBrawlsetData.Cards[k][i].NumberOfDecks > cacheBrawlsetData.Cards[k][j].NumberOfDecks
|
|
}
|
|
return cacheBrawlsetData.Cards[k][i].PercentageOfDecks > cacheBrawlsetData.Cards[k][j].PercentageOfDecks
|
|
})
|
|
}
|
|
}
|
|
|
|
cacheBrawlsetList = append(cacheBrawlsetList, CacheBrawlsetListItem{Name: v.Name, SanitizedName: v.SanitizedName, IconsSvgUri: setIconList})
|
|
|
|
totalSize += int64(unsafe.Sizeof(cacheBrawlsetData))
|
|
pb.Store().Set("json/brawlset/" + v.SanitizedName, cacheBrawlsetData)
|
|
}
|
|
|
|
totalSize += int64(unsafe.Sizeof(cacheColorCommanderTop))
|
|
for k := range cacheColorCommanderTop {
|
|
sort.Slice(cacheColorCommanderTop[k], func(i, j int) bool { return cacheColorCommanderTop[k][i].NumberOfDecks > cacheColorCommanderTop[k][j].NumberOfDecks})
|
|
pb.Store().Set(fmt.Sprintf("json/top/commander/%s", k),cacheColorCommanderTop[k])
|
|
}
|
|
|
|
totalSize += int64(unsafe.Sizeof(cacheBrawlsetList))
|
|
pb.Store().Set("json/misc/brawlsets", cacheBrawlsetList)
|
|
|
|
log.Println(fmt.Sprintf("Total cache size : %d", totalSize))
|
|
}
|
|
|
|
func GetAllColorCombination(s []string) []string {
|
|
res := []string{strings.Join(s,"")}
|
|
for i := 1; i < len(s); i++ {
|
|
combinations := CreateCombination(s, i)
|
|
res = append(res, combinations...)
|
|
}
|
|
return res
|
|
}
|
|
|
|
func CreateCardData(c Carte, decksByBset map[string][]Deck, numberOfDecksPerColorIdentity map[string]int, numberOfDecksPerCard map[string]int, bsetID string) CacheCarteListItem {
|
|
price, err := strconv.ParseFloat(c.Price, 64)
|
|
if err != nil {
|
|
price = 0.0
|
|
}
|
|
|
|
numberOfPossibleDecks := 0
|
|
if len(c.ColorIdentity) == 0 {
|
|
numberOfPossibleDecks = len(decksByBset[bsetID])
|
|
} else {
|
|
numberOfPossibleDecks = numberOfDecksPerColorIdentity[strings.Join(c.ColorIdentity,"")]
|
|
}
|
|
|
|
percentageOfDecks := 0.0
|
|
if numberOfPossibleDecks != 0 {
|
|
percentageOfDecks = float64(numberOfDecksPerCard[c.ID]) / float64(numberOfPossibleDecks)
|
|
}
|
|
|
|
return CacheCarteListItem{
|
|
Name: c.Name,
|
|
Url: fmt.Sprintf("/card/%s-%s", c.SetCode,c.SanitizedName),
|
|
Layout: c.Layout,
|
|
SmallImage: c.SmallImage,
|
|
SmallImageBack: c.SmallImageBack,
|
|
NormalImage: c.NormalImage,
|
|
NormalImageBack: c.NormalImageBack,
|
|
Price: price,
|
|
CardmarketUri: c.CardmarketUri,
|
|
NumberOfDecks: numberOfDecksPerCard[c.ID],
|
|
NumberOfPossibleDecks: numberOfPossibleDecks,
|
|
PercentageOfDecks: percentageOfDecks,
|
|
}
|
|
}
|