From 0dd67f3bb89c4b8481af84cc085cb8d26f9f8d0f Mon Sep 17 00:00:00 2001 From: The Magician Date: Mon, 28 Oct 2024 19:47:23 +0000 Subject: [PATCH] Add search-printings command --- sevenkeys/card_scanner | 32 ------ sevenkeys/cli/mainui.go | 158 ---------------------------- sevenkeys/cli/response.go | 38 ------- sevenkeys/cli/search.go | 61 ----------- sevenkeys/cli/splashscreen.go | 19 ---- sevenkeys/cli/storage.go | 36 ------- sevenkeys/cli/storage_test.go | 39 ------- sevenkeys/cli/updateui.go | 37 ------- sevenkeys/database/sql/createdb.sql | 4 +- sevenkeys/logic/filter.go | 11 +- sevenkeys/logic/filter_test.go | 24 +++++ sevenkeys/logic/search.go | 17 ++- sevenkeys/main.go | 83 ++++++++++++++- 13 files changed, 122 insertions(+), 437 deletions(-) delete mode 100755 sevenkeys/card_scanner delete mode 100644 sevenkeys/cli/mainui.go delete mode 100644 sevenkeys/cli/response.go delete mode 100644 sevenkeys/cli/search.go delete mode 100644 sevenkeys/cli/splashscreen.go delete mode 100644 sevenkeys/cli/storage.go delete mode 100644 sevenkeys/cli/storage_test.go delete mode 100644 sevenkeys/cli/updateui.go diff --git a/sevenkeys/card_scanner b/sevenkeys/card_scanner deleted file mode 100755 index 6078056..0000000 --- a/sevenkeys/card_scanner +++ /dev/null @@ -1,32 +0,0 @@ -#!/bin/bash - -STORAGE_DIR="$HOME/.local/share/sevenkeys/scanimages/" -mkdir -p "$STORAGE_DIR" - -ADD_CARDS=0 -echo "scantap: Beginning scan loop" -while true; do - rng="$(cat /dev/random | tr -cd 'a-f0-9' | head -c 32)" - filename="$STORAGE_DIR/$rng.png" - - scanimage --output-file="$filename" --source "ADF Front" --mode Color --page-width 63mm --page-height 88mm 2>/dev/null - - # scanimage exits with code 7 if no documents are available in scanner - if test $? -eq 7; then - if test $ADD_CARDS -eq 0; then - ADD_CARDS=1 - echo "scantap: No more cards in feeder" >&2 - fi - - continue - fi - ADD_CARDS=0 - - convert -rotate 180 "$filename" "$filename" - - # TODO: Add "store" command to sevenkeys executable to avoid duplicating insert logic here, then `./sevenkeys --profile=production store --id="0000..0000"` - # Return inserted CardLocationId - #cardLocationId="1" - #mysql --silent --silent --user=root --password="$(pass show sevenkeys/mysql \ - #-e "USE sevenkeys; INSERT INTO CardScan (CardLocationId, Filename) VALUES ('$cardLocationId', '$filename.png');" -done diff --git a/sevenkeys/cli/mainui.go b/sevenkeys/cli/mainui.go deleted file mode 100644 index 6972542..0000000 --- a/sevenkeys/cli/mainui.go +++ /dev/null @@ -1,158 +0,0 @@ -package cli - -import ( - "database/sql" - "fmt" - "sevenkeys/database" - "sevenkeys/logic" -) - -var output string - -func MainCliLoop(db *sql.DB) { - var command string - - //var selectedStorageAreaName string - var cardLocation database.CardLocation - - var insertSearchCriteria logic.SearchCriteria = logic.SearchCriteria{ - SetCode: "", - Foil: logic.Either, - Promo: logic.Either, - Language: "en", - } - //var insertSearchOptions logic.InsertSearchOptions - - // TODO: Add the ability to modify this - /* - var locateSearchCriteria logic.SearchCriteria = logic.SearchCriteria{ - SetCode: "", - Foil: logic.True, - Promo: logic.Either, - Language: "en", - } - */ - - for { - ShowSplashScreen() - // TODO: Fix this - //showStorageInfo(os.Stdout, selectedStorageAreaName) - showInsertSearchCriteria(insertSearchCriteria) - showSelectedCard() - showCopiesInserted() - - command = GetStringResponse("SEVENKEYS $") - - //var err error - - switch command { - /* - case "q", "quit": - return - */ - /* - case "n", "newstorage": - var storageArea database.StorageArea - storageArea.Name = GetStringResponse("Storage area name:") - storageArea.StorageType = GetStringResponse("Storage area type (Binder/Box):") - err = logic.CreateStorageArea(db, storageArea) - logic.Check(err) - break - */ - /* - case "a", "area": - options, err := logic.GetStorageAreaSearchOptions(db) - logic.Check(err) - - id, _, err := logic.GenericSearch(options) - logic.Check(err) - - //selectedStorageAreaName = name - // TODO: Make db call to cache StorageArea once we have the ID - cardLocation.StorageAreaId = id - break - case "c", "criteria": - insertSearchCriteria = getSearchCriteria() - break - case "s", "search": - if shouldRefreshSearch { - insertSearchOptions = getSearchOptions(db, insertSearchCriteria) - } - - var previousCardPrintingId = cardLocation.CardPrintingId - - pk, searchLine, err := logic.GenericSearch(insertSearchOptions) - cardLocation.CardPrintingId = pk - selectedCardPrintingSearchLine = searchLine - - var exitError *exec.ExitError - if errors.As(err, &exitError) { - break - } - logic.Check(err) - - output = "" - if cardLocation.CardPrintingId != previousCardPrintingId { - copiesInserted = 0 - } - break - */ - case "i", "insert": - _, err := logic.StoreCard(db, cardLocation) - logic.Check(err) - copiesInserted++ - break - /* - case "d", "delverlens": - filename := GetStringResponse("Filename:") - - cards, err := delverlens.ParseExportFile(filename) - logic.Check(err) - - err = logic.ImportDelverLensCards(db, cards, cardLocation.StorageAreaId) - logic.Check(err) - break - */ - /* - case "l", "locate": - filename := GetStringResponse("Filename:") - cardNames, err := logic.GetCardNamesFromFile(filename) - logic.Check(err) - - locations, err := logic.LocateCards(db, cardNames, locateSearchCriteria) - logic.Check(err) - - if len(locations) == 0 { - fmt.Println("No results found") - fmt.Scanln() - break - } - - for _, location := range locations { - description := logic.GetLocationDescription(location) - fmt.Println(description) - - for true { - todo := GetStringResponse("TODO:") - - if todo == "r" { - logic.RemoveFromStorage(db, location) - break - } else if todo == "n" { - break - } else { - fmt.Printf("Unrecognized option: %s\n", todo) - } - } - } - - fmt.Println("Though this query has ended, its relics still slumber in New Argive.") - fmt.Scanln() - break - */ - default: - fmt.Println("Unrecognized command:", command) - break - } - } -} diff --git a/sevenkeys/cli/response.go b/sevenkeys/cli/response.go deleted file mode 100644 index 321589b..0000000 --- a/sevenkeys/cli/response.go +++ /dev/null @@ -1,38 +0,0 @@ -package cli - -import ( - "bufio" - "fmt" - "os" - "sevenkeys/logic" - "strings" -) - -func GetStringResponse(prompt string) string { - fmt.Print(prompt + " ") - - var response string - scanner := bufio.NewScanner(os.Stdin) - scanner.Scan() - response = scanner.Text() - - return response -} - -func GetYesNoResponse(prompt string) bool { - response := GetStringResponse(prompt) - return strings.ToUpper(response) == "Y" -} - -func GetTriadicResponse(prompt string) logic.Triadic { - response := GetStringResponse(prompt) - - switch strings.ToUpper(response) { - case "Y": - return logic.True - case "N": - return logic.False - default: - return logic.Either - } -} diff --git a/sevenkeys/cli/search.go b/sevenkeys/cli/search.go deleted file mode 100644 index ef62b27..0000000 --- a/sevenkeys/cli/search.go +++ /dev/null @@ -1,61 +0,0 @@ -package cli - -import ( - "database/sql" - "fmt" - "sevenkeys/logic" -) - -var shouldRefreshSearch bool = true - -func getSearchCriteria() logic.SearchCriteria { - var searchCriteria logic.SearchCriteria - - searchCriteria.SetCode = GetStringResponse("Set code:") - searchCriteria.Foil = GetTriadicResponse("Foil (y/n/E):") - searchCriteria.Promo = GetTriadicResponse("Promo (y/n/E):") - searchCriteria.Language = GetStringResponse("Language:") - shouldRefreshSearch = true - - return searchCriteria -} - -func getTriadicDisplay(triadic logic.Triadic) string { - if triadic == logic.True { - return "True" - } - - if triadic == logic.False { - return "False" - } - - return "Either" -} - -func showInsertSearchCriteria(insertSearchCriteria logic.SearchCriteria) { - fmt.Println("SEARCH CRITERIA") - - setCodeDisplay := getInfoDisplay(insertSearchCriteria.SetCode) - foilDisplay := getTriadicDisplay(insertSearchCriteria.Foil) - promoDisplay := getTriadicDisplay(insertSearchCriteria.Promo) - languageDisplay := getInfoDisplay(insertSearchCriteria.Language) - - fmt.Println("Set code:", setCodeDisplay) - fmt.Println("Foil:", foilDisplay) - fmt.Println("Promo:", promoDisplay) - fmt.Println("Language:", languageDisplay) - - fmt.Print("\n") -} - -func showSelectedCard() { - selectedCardDisplay := getInfoDisplay(selectedCardPrintingSearchLine) - fmt.Println("Selected card:", selectedCardDisplay) -} - -func getSearchOptions(db *sql.DB, insertSearchCriteria logic.SearchCriteria) logic.InsertSearchOptions { - options, err := logic.GetAllSearchOptions(db, insertSearchCriteria) - logic.Check(err) - shouldRefreshSearch = false - return options -} diff --git a/sevenkeys/cli/splashscreen.go b/sevenkeys/cli/splashscreen.go deleted file mode 100644 index 9da8ebd..0000000 --- a/sevenkeys/cli/splashscreen.go +++ /dev/null @@ -1,19 +0,0 @@ -package cli - -import ( - "sevenkeys/figlet" - - "github.com/inancgumus/screen" -) - -func ClearScreen() { - screen.Clear() - screen.MoveTopLeft() -} - -func ShowSplashScreen() { - ClearScreen() - - figlet.PrintMsgSlant("SEVENKEYS", "center") - figlet.PrintMsgTerm("the ultimate Magic: the Gathering trading card storage system", "center") -} diff --git a/sevenkeys/cli/storage.go b/sevenkeys/cli/storage.go deleted file mode 100644 index 0f86827..0000000 --- a/sevenkeys/cli/storage.go +++ /dev/null @@ -1,36 +0,0 @@ -package cli - -import ( - "fmt" - "io" - "sevenkeys/database" -) - -var ( - selectedCardPrintingSearchLine string - - copiesInserted int -) - -func getInfoDisplay(info string) string { - if info == "" { - return "[EMPTY]" - } - - return info -} - -func showStorageInfo(w io.Writer, area database.StorageArea) { - fmt.Fprint(w, "Selected Storage Area: ") - if area.Name == "" { // TODO: Add a struct method to determine whether it is unset? - fmt.Fprint(w, "[None]\n") - return - } - - fmt.Fprintf(w, "%s (%s)\n", area.Name, area.StorageType) - return -} - -func showCopiesInserted() { - fmt.Println("Copies inserted:", copiesInserted) -} diff --git a/sevenkeys/cli/storage_test.go b/sevenkeys/cli/storage_test.go deleted file mode 100644 index d19ac18..0000000 --- a/sevenkeys/cli/storage_test.go +++ /dev/null @@ -1,39 +0,0 @@ -package cli - -import ( - "bytes" - "sevenkeys/database" - "testing" -) - -func Test_showStorageInfo_DisplaysNone_IfSelectedStorageAreaIsUnset(t *testing.T) { - expected := "Selected Storage Area: [None]\n" - - var output bytes.Buffer - - var area database.StorageArea - showStorageInfo(&output, area) - - result := output.String() - if result != expected { - t.Errorf("expected %s, got %s", expected, result) - } -} - -func Test_showStorageInfo_DisplaysStorageAreaNameAndType_IfSelectedStorageAreaIsSet(t *testing.T) { - expected := "Selected Storage Area: Test A (Box)\n" - - var output bytes.Buffer - - area := database.StorageArea{ - Id: 1, - Name: "Test A", - Type: "Box", - } - showStorageInfo(&output, area) - - result := output.String() - if result != expected { - t.Errorf("expected %s, got %s", expected, result) - } -} diff --git a/sevenkeys/cli/updateui.go b/sevenkeys/cli/updateui.go deleted file mode 100644 index 81c68a6..0000000 --- a/sevenkeys/cli/updateui.go +++ /dev/null @@ -1,37 +0,0 @@ -package cli - -import ( - "database/sql" - "fmt" - "sevenkeys/logic" - "sevenkeys/logic/scryfall" -) - -func RunUpdateCheck(db *sql.DB) { - fmt.Println("Checking for updates...") - bulkData, err := scryfall.GetBulkDataByType(scryfall.BulkDataTypeAllCards) - logic.Check(err) - - needsUpdate, err := logic.CheckForUpdates(db, bulkData) - logic.Check(err) - - if !needsUpdate { - fmt.Println("No update required.") - return - } - - fmt.Println("Update required.") - if GetYesNoResponse("Run update? (y/N)") { - fmt.Println("Running update...") - - logic.CreateCacheDirectories() - - err = logic.UpdateSets(db) - logic.Check(err) - - err = logic.UpdateCards(db, bulkData) - logic.Check(err) - - fmt.Println("Update finished.") - } -} diff --git a/sevenkeys/database/sql/createdb.sql b/sevenkeys/database/sql/createdb.sql index c4cd33a..8f6adc8 100644 --- a/sevenkeys/database/sql/createdb.sql +++ b/sevenkeys/database/sql/createdb.sql @@ -34,7 +34,7 @@ INSERT INTO CardPrinting ( IsPromo, CollectorNumber, ImageUrl, - Language, + Language ) VALUES ( '00000000-0000-0000-0000-0000000000000', 'Scanned Card Placeholder', @@ -43,7 +43,7 @@ INSERT INTO CardPrinting ( 0, 0, '', - 'en', + 'en' ); CREATE TABLE IF NOT EXISTS StorageArea ( diff --git a/sevenkeys/logic/filter.go b/sevenkeys/logic/filter.go index e303d69..34f1877 100644 --- a/sevenkeys/logic/filter.go +++ b/sevenkeys/logic/filter.go @@ -1,9 +1,16 @@ package logic -import "sevenkeys/database" +import ( + "sevenkeys/database" + "strings" +) func filterPrinting(printing database.CardPrinting, searchCriteria SearchCriteria) bool { - if searchCriteria.SetCode != "" && printing.SetCode != searchCriteria.SetCode { + if searchCriteria.SetCode != "" && !strings.Contains(printing.SetCode, searchCriteria.SetCode) { + return true + } + + if searchCriteria.CollectorNumber != "" && !strings.Contains(printing.CollectorNumber, searchCriteria.CollectorNumber) { return true } diff --git a/sevenkeys/logic/filter_test.go b/sevenkeys/logic/filter_test.go index ac47f27..098b279 100644 --- a/sevenkeys/logic/filter_test.go +++ b/sevenkeys/logic/filter_test.go @@ -400,3 +400,27 @@ func TestFilterPrinting_ReturnsFalse_IfLanguageNotSet(t *testing.T) { t.Errorf("filter was true") } } + +func TestFilterPrinting_ReturnsTrue_IfSetCodeMatchesButCollectorNumberDoesnt(t *testing.T) { + printing := database.CardPrinting{ + SetCode: "rtr", + CollectorNumber: "301", + IsFoil: false, + IsPromo: false, + Language: "en", + } + + searchCriteria := SearchCriteria{ + SetCode: "rtr", + CollectorNumber: "299", + Foil: False, + Promo: False, + Language: "", + } + + filter := filterPrinting(printing, searchCriteria) + + if filter != true { + t.Errorf("filter was false") + } +} diff --git a/sevenkeys/logic/search.go b/sevenkeys/logic/search.go index ec89ea1..db7db2b 100644 --- a/sevenkeys/logic/search.go +++ b/sevenkeys/logic/search.go @@ -19,18 +19,17 @@ const ( ) type SearchCriteria struct { - SetCode string - Foil Triadic - Promo Triadic - Language string + SetCode string + CollectorNumber string + Foil Triadic + Promo Triadic + Language string } -// The InsertSearchOptions type is a map of `string` keys (which can be searched using -// fzf) to `string` values (which represent a primary key in the CardPrintings table) -type InsertSearchOptions map[string]string +type CardPrintingSearchOptions map[string]string -func GetAllSearchOptions(db *sql.DB, searchCriteria SearchCriteria) (InsertSearchOptions, error) { - var searchOptions InsertSearchOptions = make(InsertSearchOptions) +func GetAllCardPrintingSearchOptions(db *sql.DB, searchCriteria SearchCriteria) (CardPrintingSearchOptions, error) { + var searchOptions CardPrintingSearchOptions = make(CardPrintingSearchOptions) cardPrintings, err := database.GetAllCardPrintings(db) if err != nil { diff --git a/sevenkeys/main.go b/sevenkeys/main.go index 4eec296..8d9eb04 100644 --- a/sevenkeys/main.go +++ b/sevenkeys/main.go @@ -1,21 +1,40 @@ package main import ( + "bufio" "flag" "fmt" "os" - "sevenkeys/cli" "sevenkeys/database" "sevenkeys/delverlens" "sevenkeys/logic" + "sevenkeys/logic/scryfall" + "strings" ) +func GetStringResponse(prompt string) string { + fmt.Print(prompt + " ") + + var response string + scanner := bufio.NewScanner(os.Stdin) + scanner.Scan() + response = scanner.Text() + + return response +} + +func GetYesNoResponse(prompt string) bool { + response := GetStringResponse(prompt) + return strings.ToUpper(response) == "Y" +} + const ( UpdateSubcommand string = "update" CreateStorageAreaSubcommand string = "createstorage" StoreSubcommand string = "store" ImportSubcommand string = "import" - SearchSubcommand string = "search" + SearchPrintingsSubcommand string = "search-printings" + SearchStorageSubcommand string = "search-storage" DeckSubcommand string = "deck" ) @@ -44,7 +63,33 @@ func main() { switch flag.Args()[0] { case UpdateSubcommand: - cli.RunUpdateCheck(db) + fmt.Println("Checking for updates...") + bulkData, err := scryfall.GetBulkDataByType(scryfall.BulkDataTypeAllCards) + logic.Check(err) + + needsUpdate, err := logic.CheckForUpdates(db, bulkData) + logic.Check(err) + + if !needsUpdate { + fmt.Println("No update required.") + return + } + + fmt.Println("Update required.") + + if GetYesNoResponse("Run update? (y/N)") { + fmt.Println("Running update...") + + logic.CreateCacheDirectories() + + err = logic.UpdateSets(db) + logic.Check(err) + + err = logic.UpdateCards(db, bulkData) + logic.Check(err) + + fmt.Println("Update finished.") + } break case CreateStorageAreaSubcommand: createStorageCmd := flag.NewFlagSet(CreateStorageAreaSubcommand, flag.ExitOnError) @@ -103,7 +148,37 @@ func main() { err = logic.ImportDelverLensCards(db, delverLensCards, storageAreaId) logic.Check(err) break - case SearchSubcommand: + case SearchPrintingsSubcommand: + searchPrintingsCmd := flag.NewFlagSet(SearchPrintingsSubcommand, flag.ExitOnError) + + setCode := searchPrintingsCmd.String("set-code", "", "The code for the set the card we're searching for belongs to.") + collectorNumber := searchPrintingsCmd.String("collector-number", "", "The collector number of the card we're searching for.") + foil := searchPrintingsCmd.String("foil", "E", "Whether the card we're searching for is foil.") + + searchPrintingsCmd.Parse(flag.Args()[1:]) + + searchCriteria := logic.SearchCriteria{ + SetCode: *setCode, + CollectorNumber: *collectorNumber, + Promo: logic.Either, + Language: "en", + } + + if *foil == "Y" { + searchCriteria.Foil = logic.True + } else if *foil == "N" { + searchCriteria.Foil = logic.False + } else { + searchCriteria.Foil = logic.Either + } + + searchOptions, err := logic.GetAllCardPrintingSearchOptions(db, searchCriteria) + logic.Check(err) + id, _, err := logic.GenericSearch(searchOptions) + logic.Check(err) + fmt.Println(id) + break + case SearchStorageSubcommand: searchOptions, err := logic.GetAllStorageSearchOptions(db) logic.Check(err) id, _, err := logic.GenericSearch(searchOptions)