TheMathemagicians/sevenkeys/logic/search.go

115 lines
2.3 KiB
Go

package logic
import (
"database/sql"
"fmt"
"io"
"os"
"os/exec"
"sevenkeys/database"
"strings"
)
type Triadic int
const (
True Triadic = iota
False
Either
)
type SearchCriteria struct {
SetCode string
Foil Triadic
Promo Triadic
Language string
}
// The SearchOptions 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 SearchOptions map[string]string
func filterPrinting(printing database.CardPrinting, searchCriteria SearchCriteria) bool {
if searchCriteria.SetCode != "" && printing.SetCode != searchCriteria.SetCode {
return true
}
if searchCriteria.Foil == False && printing.IsFoil {
return true
}
if searchCriteria.Foil == True && !printing.IsFoil {
return true
}
if searchCriteria.Promo == False && printing.IsPromo {
return true
}
if searchCriteria.Promo == True && !printing.IsPromo {
return true
}
if searchCriteria.Language != "" && printing.Language != searchCriteria.Language {
return true
}
return false
}
func GetAllSearchOptions(db *sql.DB, searchCriteria SearchCriteria) (SearchOptions, error) {
var searchOptions SearchOptions = make(map[string]string)
cardPrintings, err := database.GetAllCardPrintings(db)
if err != nil {
return searchOptions, err
}
for _, printing := range cardPrintings {
// Filter based on search criteria
filter := filterPrinting(printing, searchCriteria)
if filter {
continue
}
// Construct search option string
searchString := fmt.Sprintf("%s (%s %s) [%s]", printing.Name, printing.SetCode, printing.CollectorNumber, printing.Language)
if printing.IsFoil {
searchString += " FOIL"
}
if printing.IsPromo {
searchString += " PROMO"
}
searchOptions[searchString] = printing.Id
}
return searchOptions, err
}
func Search(searchOptions SearchOptions) (string, string, error) {
cmd := exec.Command("fzf")
cmd.Stderr = os.Stderr
fzfStdin, err := cmd.StdinPipe()
if err != nil {
return "", "", err
}
go func() {
defer fzfStdin.Close()
for searchString, _ := range searchOptions {
io.WriteString(fzfStdin, searchString+"\n")
}
}()
fzfOutput, err := cmd.Output()
if err != nil {
return "", "", err
}
key := strings.TrimSuffix(string(fzfOutput), "\n")
return searchOptions[key], key, nil
}