From de868f58b1ff742274d705fcc3aabd92419aed67 Mon Sep 17 00:00:00 2001 From: Ryan Castner Date: Sat, 18 Mar 2023 21:51:11 -0400 Subject: [PATCH 01/12] working version of adding/removing foils and adding to collection value --- src/serra/add.go | 25 ++++++++++++++++++----- src/serra/card.go | 7 ++++--- src/serra/helpers.go | 46 +++++++++++++++++++++++++++++++++++++++---- src/serra/missing.go | 2 +- src/serra/remove.go | 19 ++++++++++++++---- src/serra/root.go | 1 + src/serra/scryfall.go | 8 +++++++- src/serra/set.go | 22 +++++++++++++++++---- src/serra/stats.go | 16 +++++++++++++-- src/serra/storage.go | 11 ++++++++++- src/serra/update.go | 2 +- 11 files changed, 133 insertions(+), 26 deletions(-) diff --git a/src/serra/add.go b/src/serra/add.go index a722cee..2b3cd0c 100644 --- a/src/serra/add.go +++ b/src/serra/add.go @@ -15,6 +15,7 @@ func init() { addCmd.Flags().BoolVarP(&unique, "unique", "u", false, "Only add card if not existent yet") addCmd.Flags().BoolVarP(&interactive, "interactive", "i", false, "Spin up interactive terminal") addCmd.Flags().StringVarP(&set, "set", "s", "", "Filter by set code (usg/mmq/vow)") + addCmd.Flags().BoolVarP(&foil, "foil", "f", false, "Add foil variant of card") rootCmd.AddCommand(addCmd) } @@ -78,13 +79,20 @@ func addCards(cards []string, unique bool, count int64) error { c := co[0] if unique { - LogMessage(fmt.Sprintf("Not adding \"%s\" (%s, %.2f %s) to Collection because it already exists.", c.Name, c.Rarity, c.getValue(), getCurrency()), "red") + LogMessage(fmt.Sprintf("Not adding \"%s\" (%s, %.2f %s) to Collection because it already exists.", c.Name, c.Rarity, c.getValue(foil), getCurrency()), "red") continue } - modify_count_of_card(coll, &c, count) + modify_count_of_card(coll, &c, count, foil) + + var total int64 = 0 + if foil { + total = c.SerraCountFoil + count + } else { + total = c.SerraCount + count + } // Give feedback of successfully added card - LogMessage(fmt.Sprintf("%dx \"%s\" (%s, %.2f %s) added to Collection.", c.SerraCount, c.Name, c.Rarity, c.getValue(), getCurrency()), "green") + LogMessage(fmt.Sprintf("%dx \"%s\" (%s, %.2f %s) added to Collection.", total, c.Name, c.Rarity, c.getValue(foil), getCurrency()), "green") // If card is not already in collection, fetching from scyfall } else { @@ -97,7 +105,14 @@ func addCards(cards []string, unique bool, count int64) error { } // Write card to mongodb - c.SerraCount = count + var total int64 = 0 + if foil { + c.SerraCountFoil = count + total = c.SerraCountFoil + } else { + c.SerraCount = count + total = c.SerraCount + } err = coll.storage_add(c) if err != nil { LogMessage(fmt.Sprintf("%v", err), "red") @@ -105,7 +120,7 @@ func addCards(cards []string, unique bool, count int64) error { } // Give feedback of successfully added card - LogMessage(fmt.Sprintf("%dx \"%s\" (%s, %.2f %s) added to Collection.", c.SerraCount, c.Name, c.Rarity, c.getValue(), getCurrency()), "green") + LogMessage(fmt.Sprintf("%dx \"%s\" (%s, %.2f %s) added to Collection.", total, c.Name, c.Rarity, c.getValue(foil), getCurrency()), "green") } } storage_disconnect(client) diff --git a/src/serra/card.go b/src/serra/card.go index 47f26d3..f473651 100644 --- a/src/serra/card.go +++ b/src/serra/card.go @@ -118,8 +118,9 @@ func show_card_list(cards []Card) { var total float64 for _, card := range cards { - LogMessage(fmt.Sprintf("* %dx %s%s%s (%s/%s) %s%.2f %s%s", card.SerraCount, Purple, card.Name, Reset, card.Set, card.CollectorNumber, Yellow, card.getValue(), getCurrency(), Reset), "normal") - total = total + card.getValue()*float64(card.SerraCount) + LogMessage(fmt.Sprintf("* %dx Non-Foil %s%s%s (%s/%s) %s%.2f %s%s", card.SerraCount, Purple, card.Name, Reset, card.Set, card.CollectorNumber, Yellow, card.getValue(false), getCurrency(), Reset), "normal") + LogMessage(fmt.Sprintf("* %dx Foil %s%s%s (%s/%s) %s%.2f %s%s", card.SerraCountFoil, Purple, card.Name, Reset, card.Set, card.CollectorNumber, Yellow, card.getValue(true), getCurrency(), Reset), "normal") + total = total + card.getValue(false)*float64(card.SerraCount) + card.getValue(true)*float64(card.SerraCountFoil) } fmt.Printf("\nTotal Value: %s%.2f %s%s\n", Yellow, total, getCurrency(), Reset) @@ -131,7 +132,7 @@ func show_card_details(card *Card) error { fmt.Printf("Count: %dx\n", card.SerraCount) fmt.Printf("Rarity: %s\n", card.Rarity) fmt.Printf("Scryfall: %s\n", strings.Replace(card.ScryfallURI, "?utm_source=api", "", 1)) - fmt.Printf("Current Value: %s%.2f %s%s\n", Yellow, card.getValue(), getCurrency(), Reset) + fmt.Printf("Current Value: Non-Foil %s%.2f %s%s Foil %s%.2f %s%s\n", Yellow, card.getValue(false), getCurrency(), Reset, Yellow, card.getValue(true), getCurrency(), Reset) fmt.Printf("\n%sHistory%s\n", Green, Reset) print_price_history(card.SerraPrices, "* ") diff --git a/src/serra/helpers.go b/src/serra/helpers.go index 835a3c6..4dac9eb 100644 --- a/src/serra/helpers.go +++ b/src/serra/helpers.go @@ -3,6 +3,7 @@ package serra import ( "errors" "fmt" + "math" "time" "go.mongodb.org/mongo-driver/bson" @@ -13,7 +14,7 @@ type Rarities struct { Rares, Uncommons, Commons, Mythics float64 } -func modify_count_of_card(coll *Collection, c *Card, amount int64) error { +func modify_count_of_card(coll *Collection, c *Card, amount int64, foil bool) error { // find already existing card sort := bson.D{{"_id", 1}} @@ -26,12 +27,26 @@ func modify_count_of_card(coll *Collection, c *Card, amount int64) error { // update card amount update_filter := bson.M{"_id": bson.M{"$eq": c.ID}} - update := bson.M{ - "$set": bson.M{"serra_count": stored_card.SerraCount + amount}, + var update bson.M + if foil { + update = bson.M{ + "$set": bson.M{"serra_count_foil": stored_card.SerraCountFoil + amount}, + } + } else { + update = bson.M{ + "$set": bson.M{"serra_count": stored_card.SerraCount + amount}, + } } + coll.storage_update(update_filter, update) - LogMessage(fmt.Sprintf("Updating Card \"%s\" amount to %d", stored_card.Name, stored_card.SerraCount+amount), "purple") + var total int64 + if foil { + total = stored_card.SerraCountFoil + amount + } else { + total = stored_card.SerraCount + amount + } + LogMessage(fmt.Sprintf("Updating Card \"%s\" amount to %d", stored_card.Name, total), "purple") return nil } @@ -167,3 +182,26 @@ func print_price_history(prices []PriceEntry, prefix string) { before = value } } + +func getFloat64(unknown interface{}) (float64, error) { + switch i := unknown.(type) { + case float64: + return i, nil + case float32: + return float64(i), nil + case int64: + return float64(i), nil + case int32: + return float64(i), nil + case int: + return float64(i), nil + case uint64: + return float64(i), nil + case uint32: + return float64(i), nil + case uint: + return float64(i), nil + default: + return math.NaN(), errors.New("Non-numeric type could not be converted to float") + } +} diff --git a/src/serra/missing.go b/src/serra/missing.go index 7799a70..1dd54ec 100644 --- a/src/serra/missing.go +++ b/src/serra/missing.go @@ -58,7 +58,7 @@ cards you dont own (yet) :)`, if err != nil { continue } - fmt.Printf("%.02f %s\t%s (%s)\n", ncard.getValue(), getCurrency(), ncard.Name, ncard.SetName) + fmt.Printf("%.02f %s\t%s (%s)\n", ncard.getValue(false), getCurrency(), ncard.Name, ncard.SetName) } return nil }, diff --git a/src/serra/remove.go b/src/serra/remove.go index b208538..128a17c 100644 --- a/src/serra/remove.go +++ b/src/serra/remove.go @@ -14,6 +14,7 @@ func init() { removeCmd.Flags().Int64VarP(&count, "count", "c", 1, "Amount of cards to remove") removeCmd.Flags().BoolVarP(&interactive, "interactive", "i", false, "Spin up interactive terminal") removeCmd.Flags().StringVarP(&set, "set", "s", "", "Filter by set code (usg/mmq/vow)") + removeCmd.Flags().BoolVarP(&foil, "foil", "f", false, "Remove foil variant of card") rootCmd.AddCommand(removeCmd) } @@ -77,11 +78,21 @@ func removeCards(cards []string, count int64) error { continue } - if c.SerraCount > 1 { - modify_count_of_card(coll, c, -1) - } else { + if foil && c.SerraCountFoil < 1 { + LogMessage(fmt.Sprintf("Error: No Foil \"%s\" in the Collection.", c.Name), "red") + continue + } + + if !foil && c.SerraCount < 1 { + LogMessage(fmt.Sprintf("Error: No Non-Foil \"%s\" in the Collection.", c.Name), "red") + continue + } + + if foil && c.SerraCountFoil == 1 && c.SerraCount == 0 || !foil && c.SerraCount == 1 && c.SerraCountFoil == 0 { coll.storage_remove(bson.M{"_id": c.ID}) - LogMessage(fmt.Sprintf("\"%s\" (%.2f %s) removed from the Collection.", c.Name, c.getValue(), getCurrency()), "green") + LogMessage(fmt.Sprintf("\"%s\" (%.2f %s) removed from the Collection.", c.Name, c.getValue(foil), getCurrency()), "green") + } else { + modify_count_of_card(coll, c, -1, foil) } } diff --git a/src/serra/root.go b/src/serra/root.go index d3ab100..859caf4 100644 --- a/src/serra/root.go +++ b/src/serra/root.go @@ -20,6 +20,7 @@ var since string var sortby string var cardType string var unique bool +var foil bool var rootCmd = &cobra.Command{ Version: Version, diff --git a/src/serra/scryfall.go b/src/serra/scryfall.go index 80beb27..48758c6 100644 --- a/src/serra/scryfall.go +++ b/src/serra/scryfall.go @@ -120,10 +120,16 @@ type Card struct { } // Getter for currency specific value -func (c Card) getValue() float64 { +func (c Card) getValue(foil bool) float64 { if getCurrency() == "EUR" { + if foil { + return c.Prices.EurFoil + } return c.Prices.Eur } + if foil { + return c.Prices.UsdFoil + } return c.Prices.Usd } diff --git a/src/serra/set.go b/src/serra/set.go index ec8e0b9..50e889b 100644 --- a/src/serra/set.go +++ b/src/serra/set.go @@ -42,7 +42,8 @@ func Sets(sort string) []primitive.M { groupStage := bson.D{ {"$group", bson.D{ {"_id", "$setname"}, - {"value", bson.D{{"$sum", bson.D{{"$multiply", bson.A{getCurrencyField(), "$serra_count"}}}}}}, + {"value", bson.D{{"$sum", bson.D{{"$multiply", bson.A{getCurrencyField(false), "$serra_count"}}}}}}, + {"value_foil", bson.D{{"$sum", bson.D{{"$multiply", bson.A{getCurrencyField(true), "$serra_count_foil"}}}}}}, {"count", bson.D{{"$sum", bson.D{{"$multiply", bson.A{1.0, "$serra_count"}}}}}}, {"unique", bson.D{{"$sum", 1}}}, {"code", bson.D{{"$last", "$set"}}}, @@ -113,7 +114,8 @@ func ShowSet(setname string) error { groupStage := bson.D{ {"$group", bson.D{ {"_id", "$setname"}, - {"value", bson.D{{"$sum", bson.D{{"$multiply", bson.A{getCurrencyField(), "$serra_count"}}}}}}, + {"value", bson.D{{"$sum", bson.D{{"$multiply", bson.A{getCurrencyField(false), "$serra_count"}}}}}}, + {"value_foil", bson.D{{"$sum", bson.D{{"$multiply", bson.A{getCurrencyField(true), "$serra_count_foil"}}}}}}, {"count", bson.D{{"$sum", bson.D{{"$multiply", bson.A{1.0, "$serra_count"}}}}}}, }}, } @@ -142,7 +144,18 @@ func ShowSet(setname string) error { LogMessage(fmt.Sprintf("%s", sets[0].Name), "green") LogMessage(fmt.Sprintf("Set Cards: %d/%d", len(cards), sets[0].CardCount), "normal") LogMessage(fmt.Sprintf("Total Cards: %.0f", stats[0]["count"]), "normal") - LogMessage(fmt.Sprintf("Total Value: %.2f %s", stats[0]["value"], getCurrency()), "normal") + nf_value, err := getFloat64(stats[0]["value"]) + if err != nil { + LogMessage(fmt.Sprintf("Error: %v", err), "red") + nf_value = 0 + } + foil_value, err := getFloat64(stats[0]["value_foil"]) + if err != nil { + LogMessage(fmt.Sprintf("Error: %v", err), "red") + foil_value = 0 + } + total_value := nf_value + foil_value + LogMessage(fmt.Sprintf("Total Value: %.2f %s", total_value, getCurrency()), "normal") LogMessage(fmt.Sprintf("Released: %s", sets[0].ReleasedAt), "normal") LogMessage(fmt.Sprintf("Mythics: %.0f", ri.Mythics), "normal") LogMessage(fmt.Sprintf("Rares: %.0f", ri.Rares), "normal") @@ -163,7 +176,8 @@ func ShowSet(setname string) error { for i := 0; i < ccards; i++ { card := cards[i] - fmt.Printf("* %dx %s%s%s (%s/%s) %s%.2f %s%s\n", card.SerraCount, Purple, card.Name, Reset, sets[0].Code, card.CollectorNumber, Yellow, card.getValue(), getCurrency(), Reset) + fmt.Printf("* %dx %s%s%s (%s/%s) %s%.2f %s%s\n", card.SerraCount, Purple, card.Name, Reset, sets[0].Code, card.CollectorNumber, Yellow, card.getValue(false), getCurrency(), Reset) + fmt.Printf("* %dx %s%s%s (%s/%s) %s%.2f %s%s\n", card.SerraCountFoil, Purple, card.Name, Reset, sets[0].Code, card.CollectorNumber, Yellow, card.getValue(true), getCurrency(), Reset) } return nil diff --git a/src/serra/stats.go b/src/serra/stats.go index b744b50..d29e517 100644 --- a/src/serra/stats.go +++ b/src/serra/stats.go @@ -50,7 +50,8 @@ var statsCmd = &cobra.Command{ bson.D{ {"$group", bson.D{ {"_id", nil}, - {"value", bson.D{{"$sum", bson.D{{"$multiply", bson.A{getCurrencyField(), "$serra_count"}}}}}}, + {"value", bson.D{{"$sum", bson.D{{"$multiply", bson.A{getCurrencyField(false), "$serra_count"}}}}}}, + {"value_foil", bson.D{{"$sum", bson.D{{"$multiply", bson.A{getCurrencyField(true), "$serra_count_foil"}}}}}}, {"count", bson.D{{"$sum", bson.D{{"$multiply", bson.A{1.0, "$serra_count"}}}}}}, {"count_foil", bson.D{{"$sum", "$serra_count_foil"}}}, {"count_etched", bson.D{{"$sum", "$serra_count_etched"}}}, @@ -96,7 +97,18 @@ var statsCmd = &cobra.Command{ fmt.Printf("Commons: %s%.0f%s\n", Purple, ri.Commons, Reset) fmt.Printf("\n%sTotal Value%s\n", Green, Reset) - fmt.Printf("Current: %s%.2f %s%s\n", Pink, stats[0]["value"], getCurrency(), Reset) + nf_value, err := getFloat64(stats[0]["value"]) + if err != nil { + LogMessage(fmt.Sprintf("Error: %v", err), "red") + nf_value = 0 + } + foil_value, err := getFloat64(stats[0]["value_foil"]) + if err != nil { + LogMessage(fmt.Sprintf("Error: %v", err), "red") + foil_value = 0 + } + total_value := nf_value + foil_value + fmt.Printf("Current: %s%.2f %s%s\n", Pink, total_value, getCurrency(), Reset) total, _ := totalcoll.storage_find_total() fmt.Printf("History: \n") diff --git a/src/serra/storage.go b/src/serra/storage.go index 259694a..9abfbc4 100644 --- a/src/serra/storage.go +++ b/src/serra/storage.go @@ -25,13 +25,22 @@ type Collection struct { // Returns configured human readable name for // the configured currency of the user -func getCurrencyField() string { +func getCurrencyField(foil bool) string { switch os.Getenv("SERRA_CURRENCY") { case "EUR": + if foil { + return "$prices.eur_foil" + } return "$prices.eur" case "USD": + if foil { + return "$prices.usd_foil" + } return "$prices.usd" default: + if foil { + return "$prices.usd_foil" + } return "$prices.usd" } } diff --git a/src/serra/update.go b/src/serra/update.go index fb887ca..09dfa36 100644 --- a/src/serra/update.go +++ b/src/serra/update.go @@ -129,7 +129,7 @@ var updateCmd = &cobra.Command{ tmpCard := Card{} tmpCard.Prices = t - fmt.Printf("\n%sUpdating total value of collection to: %s%.02f %s%s\n", Green, Yellow, tmpCard.getValue(), getCurrency(), Reset) + fmt.Printf("\n%sUpdating total value of collection to: %s%.02f %s%s\n", Green, Yellow, tmpCard.getValue(false), getCurrency(), Reset) totalcoll.storage_add_total(t) return nil From f6621e9bd85046ab24d83454d27a0d809d4e305d Mon Sep 17 00:00:00 2001 From: Ryan Castner Date: Sat, 18 Mar 2023 18:43:07 -0400 Subject: [PATCH 02/12] upgrade mongodb driver due to data race bug found in versions v1.11.0 through v1.11.2 --- go.mod | 2 +- go.sum | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/go.mod b/go.mod index b01dda3..1f0df4e 100644 --- a/go.mod +++ b/go.mod @@ -16,7 +16,7 @@ require ( github.com/spf13/cobra v1.6.1 github.com/xdg-go/scram v1.1.2 // indirect github.com/youmark/pkcs8 v0.0.0-20201027041543-1326539a0a0a // indirect - go.mongodb.org/mongo-driver v1.11.2 + go.mongodb.org/mongo-driver v1.11.3 golang.org/x/crypto v0.6.0 // indirect golang.org/x/sync v0.1.0 // indirect golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect diff --git a/go.sum b/go.sum index 8149a1a..16b54be 100644 --- a/go.sum +++ b/go.sum @@ -125,6 +125,8 @@ github.com/youmark/pkcs8 v0.0.0-20201027041543-1326539a0a0a/go.mod h1:ul22v+Nro/ github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= go.mongodb.org/mongo-driver v1.11.2 h1:+1v2rDQUWNcGW7/7E0Jvdz51V38XXxJfhzbV17aNHCw= go.mongodb.org/mongo-driver v1.11.2/go.mod h1:s7p5vEtfbeR1gYi6pnj3c3/urpbLv2T5Sfd6Rp2HBB8= +go.mongodb.org/mongo-driver v1.11.3 h1:Ql6K6qYHEzB6xvu4+AU0BoRoqf9vFPcc4o7MUIdPW8Y= +go.mongodb.org/mongo-driver v1.11.3/go.mod h1:PTSz5yu21bkT/wXpkS7WR5f0ddqw5quethTUn9WM+2g= golang.org/x/arch v0.0.0-20210923205945-b76863e36670 h1:18EFjUmQOcUvxNYSkA6jO9VAiXCnxFY6NyDX0bHDmkU= golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= From ed1bb5c5a47eecb815dca0d6fb0c87885c88f3a2 Mon Sep 17 00:00:00 2001 From: Florian Baumann Date: Wed, 12 Apr 2023 09:37:56 +0200 Subject: [PATCH 03/12] Catch non-existent reserved list bug --- src/serra/stats.go | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/serra/stats.go b/src/serra/stats.go index d29e517..5d91237 100644 --- a/src/serra/stats.go +++ b/src/serra/stats.go @@ -76,7 +76,12 @@ var statsCmd = &cobra.Command{ {"count", bson.D{{"$sum", 1}}}, }}}, }) - fmt.Printf("Reserved List: %s%d%s\n", Yellow, reserved[0]["count"], Reset) + + var count_reserved float64 + if len(reserved) > 0 { + count_reserved = reserved[0]["count"].(float64) + } + fmt.Printf("Reserved List: %s%.0f%s\n", Yellow, count_reserved, Reset) rar, _ := coll.storage_aggregate(mongo.Pipeline{ bson.D{ From 927c5680596a55f7844fafcd7d8f839ca5de1ba8 Mon Sep 17 00:00:00 2001 From: Florian Baumann Date: Mon, 17 Apr 2023 14:16:53 +0200 Subject: [PATCH 04/12] Sort on card numbers is now numeric. fixes #8 --- src/serra/card.go | 9 +++++++++ src/serra/helpers.go | 14 +++++++++++++- 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/src/serra/card.go b/src/serra/card.go index f473651..792a276 100644 --- a/src/serra/card.go +++ b/src/serra/card.go @@ -2,6 +2,7 @@ package serra import ( "fmt" + "sort" "strings" "github.com/spf13/cobra" @@ -111,6 +112,14 @@ func Cards(rarity, set, sortby, name, oracle, cardType string) []Card { cards, _ := coll.storage_find(filter, sortStage) + // This is needed because collectornumbers are strings (ie. "23a") but still we + // want it to be sorted numerically ... 1,2,3,10,11,100. + if sortby == "number" { + sort.Slice(cards, func(i, j int) bool { + return filterForDigits(cards[i].CollectorNumber) < filterForDigits(cards[j].CollectorNumber) + }) + } + return cards } diff --git a/src/serra/helpers.go b/src/serra/helpers.go index 4dac9eb..331def9 100644 --- a/src/serra/helpers.go +++ b/src/serra/helpers.go @@ -4,7 +4,9 @@ import ( "errors" "fmt" "math" + "strconv" "time" + "unicode" "go.mongodb.org/mongo-driver/bson" "go.mongodb.org/mongo-driver/bson/primitive" @@ -166,7 +168,6 @@ func print_price_history(prices []PriceEntry, prefix string) { var before float64 for _, e := range prices { - // TODO: Make currency configurable value := e.Usd if getCurrency() == "EUR" { value = e.Eur @@ -205,3 +206,14 @@ func getFloat64(unknown interface{}) (float64, error) { return math.NaN(), errors.New("Non-numeric type could not be converted to float") } } + +func filterForDigits(str string) int { + var numStr string + for _, c := range str { + if unicode.IsDigit(c) { + numStr += string(c) + } + } + s, _ := strconv.Atoi(numStr) + return s +} From 0d516455160ba0028ecd4bab4f546bb8ba2362c7 Mon Sep 17 00:00:00 2001 From: Florian Baumann Date: Mon, 17 Apr 2023 15:11:44 +0200 Subject: [PATCH 05/12] Reduce docker image size from 1.2gb to 22mb --- Dockerfile | 16 ++++++++++++---- go.sum | 2 -- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/Dockerfile b/Dockerfile index ae548e4..7659322 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,6 @@ -FROM golang:1.20 +FROM golang:alpine AS builder + +RUN apk update && apk add --no-cache git WORKDIR /go/src/app COPY src /go/src/app/src @@ -8,10 +10,16 @@ COPY go.sum /go/src/app/go.sum COPY .git /go/src/app/.git COPY serra.go /go/src/app/serra.go - +# build RUN go get -v ./... RUN go build -ldflags "-X github.com/noqqe/serra/src/serra.Version=`git describe --tags`" -v serra.go -# Run radsportsalat +# copy +FROM scratch +WORKDIR /go/src/app +COPY --from=builder /go/src/app/serra /go/src/app/serra +COPY templates /go/src/app/templates + +# run EXPOSE 8080 -CMD [ "./serra", "web" ] +CMD [ "/go/src/app/serra", "web" ] diff --git a/go.sum b/go.sum index 16b54be..8956ae9 100644 --- a/go.sum +++ b/go.sum @@ -123,8 +123,6 @@ github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7Jul github.com/youmark/pkcs8 v0.0.0-20201027041543-1326539a0a0a h1:fZHgsYlfvtyqToslyjUt3VOPF4J7aK/3MPcK7xp3PDk= github.com/youmark/pkcs8 v0.0.0-20201027041543-1326539a0a0a/go.mod h1:ul22v+Nro/R083muKhosV54bj5niojjWZvU8xrevuH4= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= -go.mongodb.org/mongo-driver v1.11.2 h1:+1v2rDQUWNcGW7/7E0Jvdz51V38XXxJfhzbV17aNHCw= -go.mongodb.org/mongo-driver v1.11.2/go.mod h1:s7p5vEtfbeR1gYi6pnj3c3/urpbLv2T5Sfd6Rp2HBB8= go.mongodb.org/mongo-driver v1.11.3 h1:Ql6K6qYHEzB6xvu4+AU0BoRoqf9vFPcc4o7MUIdPW8Y= go.mongodb.org/mongo-driver v1.11.3/go.mod h1:PTSz5yu21bkT/wXpkS7WR5f0ddqw5quethTUn9WM+2g= golang.org/x/arch v0.0.0-20210923205945-b76863e36670 h1:18EFjUmQOcUvxNYSkA6jO9VAiXCnxFY6NyDX0bHDmkU= From c106a01a289babf8373579936410675f4971a66e Mon Sep 17 00:00:00 2001 From: Florian Baumann Date: Mon, 17 Apr 2023 15:35:50 +0200 Subject: [PATCH 06/12] Introduce proper flags for tops/flops. fixes #1 --- src/serra/gains.go | 21 ++++++++++++++------- src/serra/root.go | 3 ++- 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/src/serra/gains.go b/src/serra/gains.go index 2972e62..3920e11 100644 --- a/src/serra/gains.go +++ b/src/serra/gains.go @@ -2,7 +2,6 @@ package serra import ( "fmt" - "strconv" "github.com/spf13/cobra" "go.mongodb.org/mongo-driver/bson" @@ -13,9 +12,11 @@ func init() { rootCmd.AddCommand(topsCmd) rootCmd.AddCommand(flopsCmd) topsCmd.Flags().Float64VarP(&limit, "limit", "l", 0, "Minimum card price to be shown in analysis") - topsCmd.Flags().StringVarP(&since, "since", "s", "0", "Since when should the gains be calculated") + topsCmd.Flags().BoolVarP(&sinceLastUpdate, "since-last-update", "u", false, "Show gains since last update") + topsCmd.Flags().BoolVarP(&sinceBeginning, "since-beginning", "b", true, "Show gains since beginning of records") flopsCmd.Flags().Float64VarP(&limit, "limit", "l", 0, "Minimum card price to be shown in analysis") - flopsCmd.Flags().StringVarP(&since, "since", "s", "0", "Since when should the losses be calculated") + flopsCmd.Flags().BoolVarP(&sinceLastUpdate, "since-last-update", "u", false, "Show losses since last update") + flopsCmd.Flags().BoolVarP(&sinceBeginning, "since-beginning", "b", true, "Show losses since beginning of records") } var topsCmd = &cobra.Command{ @@ -24,7 +25,7 @@ var topsCmd = &cobra.Command{ Short: "What cards gained most value", SilenceErrors: true, RunE: func(cmd *cobra.Command, args []string) error { - Gains(limit, -1, since) + Gains(limit, -1) return nil }, } @@ -35,19 +36,25 @@ var flopsCmd = &cobra.Command{ Short: "What cards lost most value", SilenceErrors: true, RunE: func(cmd *cobra.Command, args []string) error { - Gains(limit, 1, since) + Gains(limit, 1) return nil }, } -func Gains(limit float64, sort int, since string) error { +func Gains(limit float64, sort int) error { client := storage_connect() coll := &Collection{client.Database("serra").Collection("cards")} setcoll := &Collection{client.Database("serra").Collection("sets")} defer storage_disconnect(client) - old, _ := strconv.Atoi(since) + var old int + if sinceBeginning { + old = 0 + } + if sinceLastUpdate { + old = -2 + } currencyField := "$serra_prices.usd" if getCurrency() == "EUR" { diff --git a/src/serra/root.go b/src/serra/root.go index 859caf4..e0b6489 100644 --- a/src/serra/root.go +++ b/src/serra/root.go @@ -16,7 +16,8 @@ var name string var oracle string var rarity string var set string -var since string +var sinceBeginning bool +var sinceLastUpdate bool var sortby string var cardType string var unique bool From 4a1147b1af136a72ba588e048824bfc4de078e5c Mon Sep 17 00:00:00 2001 From: Florian Baumann Date: Thu, 20 Apr 2023 11:04:53 +0200 Subject: [PATCH 07/12] merge --- src/serra/helpers.go | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/src/serra/helpers.go b/src/serra/helpers.go index 331def9..89ffb46 100644 --- a/src/serra/helpers.go +++ b/src/serra/helpers.go @@ -217,3 +217,26 @@ func filterForDigits(str string) int { s, _ := strconv.Atoi(numStr) return s } + +func getFloat64(unknown interface{}) (float64, error) { + switch i := unknown.(type) { + case float64: + return i, nil + case float32: + return float64(i), nil + case int64: + return float64(i), nil + case int32: + return float64(i), nil + case int: + return float64(i), nil + case uint64: + return float64(i), nil + case uint32: + return float64(i), nil + case uint: + return float64(i), nil + default: + return math.NaN(), errors.New("Non-numeric type could not be converted to float") + } +} From c784477241d3d7ac9fa7d5daa966bb3f9a9c84cd Mon Sep 17 00:00:00 2001 From: Florian Baumann Date: Thu, 20 Apr 2023 11:07:10 +0200 Subject: [PATCH 08/12] Fix --- src/serra/helpers.go | 23 ----------------------- 1 file changed, 23 deletions(-) diff --git a/src/serra/helpers.go b/src/serra/helpers.go index 89ffb46..ba427cb 100644 --- a/src/serra/helpers.go +++ b/src/serra/helpers.go @@ -184,29 +184,6 @@ func print_price_history(prices []PriceEntry, prefix string) { } } -func getFloat64(unknown interface{}) (float64, error) { - switch i := unknown.(type) { - case float64: - return i, nil - case float32: - return float64(i), nil - case int64: - return float64(i), nil - case int32: - return float64(i), nil - case int: - return float64(i), nil - case uint64: - return float64(i), nil - case uint32: - return float64(i), nil - case uint: - return float64(i), nil - default: - return math.NaN(), errors.New("Non-numeric type could not be converted to float") - } -} - func filterForDigits(str string) int { var numStr string for _, c := range str { From e0d90ae12debf6d5b7ea31f28588d870cb4a6ce1 Mon Sep 17 00:00:00 2001 From: Florian Baumann Date: Thu, 20 Apr 2023 11:47:30 +0200 Subject: [PATCH 09/12] stats output for foil --- src/serra/card.go | 16 ++++++++++++---- src/serra/stats.go | 11 +++++++++-- 2 files changed, 21 insertions(+), 6 deletions(-) diff --git a/src/serra/card.go b/src/serra/card.go index 792a276..d179f8c 100644 --- a/src/serra/card.go +++ b/src/serra/card.go @@ -127,8 +127,7 @@ func show_card_list(cards []Card) { var total float64 for _, card := range cards { - LogMessage(fmt.Sprintf("* %dx Non-Foil %s%s%s (%s/%s) %s%.2f %s%s", card.SerraCount, Purple, card.Name, Reset, card.Set, card.CollectorNumber, Yellow, card.getValue(false), getCurrency(), Reset), "normal") - LogMessage(fmt.Sprintf("* %dx Foil %s%s%s (%s/%s) %s%.2f %s%s", card.SerraCountFoil, Purple, card.Name, Reset, card.Set, card.CollectorNumber, Yellow, card.getValue(true), getCurrency(), Reset), "normal") + LogMessage(fmt.Sprintf("* %dx %s%s%s (%s/%s) %s%.2f %s%s", card.SerraCount+card.SerraCountFoil+card.SerraCountEtched, Purple, card.Name, Reset, card.Set, card.CollectorNumber, Yellow, card.getValue(false), getCurrency(), Reset), "normal") total = total + card.getValue(false)*float64(card.SerraCount) + card.getValue(true)*float64(card.SerraCountFoil) } fmt.Printf("\nTotal Value: %s%.2f %s%s\n", Yellow, total, getCurrency(), Reset) @@ -138,10 +137,19 @@ func show_card_list(cards []Card) { func show_card_details(card *Card) error { fmt.Printf("%s%s%s (%s/%s)\n", Purple, card.Name, Reset, card.Set, card.CollectorNumber) fmt.Printf("Added: %s\n", stringToTime(card.SerraCreated)) - fmt.Printf("Count: %dx\n", card.SerraCount) + fmt.Printf("Count Normal: %dx\n", card.SerraCount) + if card.SerraCountFoil > 0 { + fmt.Printf("Count Foil: %dx\n", card.SerraCountFoil) + } + if card.SerraCountEtched > 0 { + fmt.Printf("Count Etched: %dx\n", card.SerraCountFoil) + } fmt.Printf("Rarity: %s\n", card.Rarity) fmt.Printf("Scryfall: %s\n", strings.Replace(card.ScryfallURI, "?utm_source=api", "", 1)) - fmt.Printf("Current Value: Non-Foil %s%.2f %s%s Foil %s%.2f %s%s\n", Yellow, card.getValue(false), getCurrency(), Reset, Yellow, card.getValue(true), getCurrency(), Reset) + fmt.Printf("Current Value: %s%.2f %s%s\n", Yellow, card.getValue(false), getCurrency(), Reset) + if card.SerraCountFoil > 0 { + fmt.Printf("Foil Value: %s%.2f %s%s\n", Yellow, card.getValue(true), getCurrency(), Reset) + } fmt.Printf("\n%sHistory%s\n", Green, Reset) print_price_history(card.SerraPrices, "* ") diff --git a/src/serra/stats.go b/src/serra/stats.go index 5d91237..116e6e2 100644 --- a/src/serra/stats.go +++ b/src/serra/stats.go @@ -57,12 +57,19 @@ var statsCmd = &cobra.Command{ {"count_etched", bson.D{{"$sum", "$serra_count_etched"}}}, {"rarity", bson.D{{"$sum", "$rarity"}}}, {"unique", bson.D{{"$sum", 1}}}, - }}}, + }}, + }, + bson.D{ + {"$addFields", bson.D{ + {"count_all", bson.D{{"$sum", bson.A{"$count", "$count_foil", "$count_etched"}}}}, + }}, + }, }) fmt.Printf("\n%sCards %s\n", Green, Reset) - fmt.Printf("Total: %s%.0f%s\n", Yellow, stats[0]["count"], Reset) + fmt.Printf("Total: %s%.0f%s\n", Yellow, stats[0]["count_all"], Reset) fmt.Printf("Unique: %s%d%s\n", Purple, stats[0]["unique"], Reset) + fmt.Printf("Normal: %s%.0f%s\n", Purple, stats[0]["count"], Reset) fmt.Printf("Foil: %s%d%s\n", Purple, stats[0]["count_foil"], Reset) fmt.Printf("Etched: %s%d%s\n", Purple, stats[0]["count_etched"], Reset) From 2ed9467f6ad9d7c0d3720958c58e5d4800605727 Mon Sep 17 00:00:00 2001 From: Florian Baumann Date: Thu, 20 Apr 2023 12:05:14 +0200 Subject: [PATCH 10/12] Add price lists capability for foils --- src/serra/card.go | 2 +- src/serra/helpers.go | 16 ++++++++++++---- src/serra/set.go | 2 +- src/serra/stats.go | 6 ++++-- 4 files changed, 18 insertions(+), 8 deletions(-) diff --git a/src/serra/card.go b/src/serra/card.go index d179f8c..690c8ea 100644 --- a/src/serra/card.go +++ b/src/serra/card.go @@ -152,7 +152,7 @@ func show_card_details(card *Card) error { } fmt.Printf("\n%sHistory%s\n", Green, Reset) - print_price_history(card.SerraPrices, "* ") + print_price_history(card.SerraPrices, "* ", false) fmt.Println() return nil } diff --git a/src/serra/helpers.go b/src/serra/helpers.go index ba427cb..9c7b477 100644 --- a/src/serra/helpers.go +++ b/src/serra/helpers.go @@ -163,14 +163,22 @@ func convert_rarities(rar []primitive.M) Rarities { } -func print_price_history(prices []PriceEntry, prefix string) { +func print_price_history(prices []PriceEntry, prefix string, total bool) { var before float64 for _, e := range prices { - value := e.Usd - if getCurrency() == "EUR" { - value = e.Eur + var value float64 + if total { + value = e.Usd + e.UsdFoil + e.UsdEtched + if getCurrency() == "EUR" { + value = e.Eur + e.EurFoil + } + } else { + value = e.Usd + if getCurrency() == "EUR" { + value = e.Eur + } } if value > before && before != 0 { diff --git a/src/serra/set.go b/src/serra/set.go index 50e889b..3ad032b 100644 --- a/src/serra/set.go +++ b/src/serra/set.go @@ -162,7 +162,7 @@ func ShowSet(setname string) error { LogMessage(fmt.Sprintf("Uncommons: %.0f", ri.Uncommons), "normal") LogMessage(fmt.Sprintf("Commons: %.0f", ri.Commons), "normal") fmt.Printf("\n%sPrice History:%s\n", Pink, Reset) - print_price_history(sets[0].SerraPrices, "* ") + print_price_history(sets[0].SerraPrices, "* ", true) fmt.Printf("\n%sMost valuable cards%s\n", Pink, Reset) diff --git a/src/serra/stats.go b/src/serra/stats.go index 116e6e2..61e0581 100644 --- a/src/serra/stats.go +++ b/src/serra/stats.go @@ -120,11 +120,13 @@ var statsCmd = &cobra.Command{ foil_value = 0 } total_value := nf_value + foil_value - fmt.Printf("Current: %s%.2f %s%s\n", Pink, total_value, getCurrency(), Reset) + fmt.Printf("Total: %s%.2f %s%s\n", Pink, total_value, getCurrency(), Reset) + fmt.Printf("Normal: %s%.2f %s%s\n", Pink, nf_value, getCurrency(), Reset) + fmt.Printf("Foils: %s%.2f %s%s\n", Pink, foil_value, getCurrency(), Reset) total, _ := totalcoll.storage_find_total() fmt.Printf("History: \n") - print_price_history(total.Value, "* ") + print_price_history(total.Value, "* ", true) return nil }, } From 637d385e7414a1ee323f3adc270ccb0bc648f61c Mon Sep 17 00:00:00 2001 From: Florian Baumann Date: Thu, 20 Apr 2023 12:12:18 +0200 Subject: [PATCH 11/12] Fix update output on total value --- src/serra/update.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/serra/update.go b/src/serra/update.go index 09dfa36..c621b09 100644 --- a/src/serra/update.go +++ b/src/serra/update.go @@ -129,7 +129,7 @@ var updateCmd = &cobra.Command{ tmpCard := Card{} tmpCard.Prices = t - fmt.Printf("\n%sUpdating total value of collection to: %s%.02f %s%s\n", Green, Yellow, tmpCard.getValue(false), getCurrency(), Reset) + fmt.Printf("\n%sUpdating total value of collection to: %s%.02f %s%s\n", Green, Yellow, tmpCard.getValue(false)+tmpCard.getValue(true), getCurrency(), Reset) totalcoll.storage_add_total(t) return nil From e4b5f87be8dc8530d59569ceffdd043a84b545a6 Mon Sep 17 00:00:00 2001 From: Florian Baumann Date: Fri, 21 Apr 2023 11:42:09 +0200 Subject: [PATCH 12/12] fix reserved list output --- src/serra/stats.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/serra/stats.go b/src/serra/stats.go index 61e0581..e755ac5 100644 --- a/src/serra/stats.go +++ b/src/serra/stats.go @@ -84,11 +84,11 @@ var statsCmd = &cobra.Command{ }}}, }) - var count_reserved float64 + var count_reserved int32 if len(reserved) > 0 { - count_reserved = reserved[0]["count"].(float64) + count_reserved = reserved[0]["count"].(int32) } - fmt.Printf("Reserved List: %s%.0f%s\n", Yellow, count_reserved, Reset) + fmt.Printf("Reserved List: %s%d%s\n", Yellow, count_reserved, Reset) rar, _ := coll.storage_aggregate(mongo.Pipeline{ bson.D{