forgefs

package module
v0.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 5, 2023 License: MIT Imports: 3 Imported by: 0

README

Go Reference Go Report Card

forgefs -- The Keyforge Filesystem

Finally! A filesystem that lets you browse all (Keyforge)[https://keyforging.com/) cards and all the decks you have registered at decksofkeyforge.com. forgefs is a filesystem that runs on Ubuntu and MacOS that shows up like a thumb drive, letting you browse both cards and decks from the command line or in your file broswer.

Usage

Here is an example of browsing the filesystem on Linux. In this example, we show:

  1. Listing all Keyforge cards from the command line, then showing the card data and image for one card.
  2. Doing the same thing, from the GUI file browser.
  3. Listing all your decksofkeyforge decks, then showing the deck data for one of them.
  4. Generate a PDF of all the cards in the deck on the fly using a standard Linux tool.

Using forgefs in Linux

You can also see a decklist image for any of your decks, courtesy of the amazing SkyJedi:

Seeing your deck image in Linux

Filtering decks

One of the coolest things you can do is filter your decks by different decksofkeyforge statistics, or by what houses or sets it has, right from the command line.

All you need to do is navigate into a virtual directory in your my-decks directory. This isn't a real directory that will show up in ls or in your file browser listing; it only exists when you go into it or try to ls it directly. Like magic!

The name for this virtual directory describes the kind of filter you want. There are a bunch of stats you can filter on, all calculated by the awesome folks at decksofkeyforge.com.

  • a: amber control
  • e: expected amber
  • r: artifact control
  • c: creature control
  • f: efficiency
  • d: disruption
  • sas: overall SAS score
  • aerc: AERC score
  • expansion or set: the acronym of the Keyforge set of the deck. These are case-insensitive:
    • CotA
    • AoA
    • WC
    • MM
    • DT
  • house: matches one of the houses in the deck. These are also case-insensitive:
    • Brobnar
    • Dis
    • Logos
    • Mars
    • Sanctum
    • Saurian
    • Shadows
    • Staralliance
    • Unfathomable
    • Untamed

You can choose one of those stats, followed by an = and either the exact number you want to match, or a range. Ranges are one or two numbers combined with a :. The minimum number goes to the left of the :, and the maximum number goes to the right. For example:

  • Amber control minimum of 10: a=10:
  • Creature control maximum of 5: c=:5
  • SAS between 80 and 90 (inclusive): sas=80:90

What's more, you can combine these stat filters using boolean logic and parentheses. The possible boolean operators are:

  • And: , or +
  • Or: ^

Examples, assuming you have navigated into your my-decks directory:

  • Count all your decks with SAS between 80 and 90 (inclusive): Filter on SAS
  • Count your decks with "perfect" stats (amber control >= 10, expected amber >= 20, creature control >= 10, artifact control >= 1.5, and efficiency >= 10): Filter on perfect stats
  • Count your decks with "perfect" stats or a SAS of at least 80: Filter on perfect stats or SAS of 80
  • Count your Mass Mutation decks with an AERC of at 68: Filter on AERC and set
  • Pick a random deck out of your MM decks with a SAS of at least 68: Random deck

Note that the above examples are just counting directory entries using a standard wc command line tool. Each of those directory entries is a full deck directory, where you can access cards and decklist images as well. The only limit on what you can do with that is your imagination!

Build/Install

forgefs is written in Go. Once you install and configure Go, it is super easy to install forgefs. This will download the repository and install it in your $GOPATH/bin directory:

go get github.com/strib/forgefs
go install github.com/strib/forgefs/forgefs

Alternatively, we will soon provide a pre-built package for Debian/Ubuntu.

Configuration/Run:

The forgefs config file lives by default at $HOME/.forgefs_config.json (though you can specify an alternate config file location on the command line to the forgefs binary). Before you can run it, you need to generate a decksofkeyforge API key for yourself; you can do that here. Once you have your key, create a config file at $HOME/.forgefs_config.json that looks something like this:

  {
    "dok_api_key": "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
  }

where you need to substitute your real decksofkeyforge API key (in quotes) in place of "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX".

By default, the mountpoint for forgefs is $HOME/ffs, though that is also configurable on the command line or in the config file (with a "mountpoint" key). That directory must exist and be empty before you run forgefs. forgefs also caches data on your file system, by default in directory $HOME/.local/share/forgefs. You also need to make that directory.

mkdir -p $HOME/ffs
mkdir -p $HOME/.local/share/forgefs/forgefs_images

After that, you're ready to run it! You can run forgefs with no command line and starting browsing.

Debian/Ubuntu

If you've installed our .deb package, you can run it with the run_forgefs command, which starts up forgefs using systemd so it always runs in the background. It also creates the appropriate directories for you.

Credit

  • decksofkeyforge.com is awesome, consider supporting it on Patreon. It assigns a bunch of statistics to your decks and is also a great deck collection manager, in addition to other things.
  • SkyJedi is an amazing Keyforge community member, consider support him as well on Patreon.

Documentation

Index

Constants

View Source
const Version = "0.1.0"

Version is the current version (should be MAJOR.MINOR.PATCH).

Variables

This section is empty.

Functions

This section is empty.

Types

type Card

type Card struct {
	AERCScore        float64                  `json:"aercScore,omitempty"`
	AERCScoreAverage float64                  `json:"aercScoreAverage,omitempty"`
	AERCScoreMax     float64                  `json:"aercScoreMax,omitempty"`
	Amber            int                      `json:"amber,omitempty"`
	Anomaly          bool                     `json:"anomaly,omitempty"`
	Armor            int                      `json:"armor,omitempty"`
	ArmorString      string                   `json:"armorString,omitempty"`
	Big              bool                     `json:"big,omitempty"`
	CardNumber       string                   `json:"cardNumber,omitempty"`
	CardNumbers      []CardNumber             `json:"cardNumbers,omitempty"`
	CardText         string                   `json:"cardTest,omitempty"`
	CardTitle        string                   `json:"cardTitle,omitempty"`
	CardType         string                   `json:"cardType,omitempty"`
	Created          string                   `json:"created,omitempty"`
	EffectivePower   int                      `json:"effectivePower,omitempty"`
	Enhanced         bool                     `json:"enhanced,omitempty"`
	EvilTwin         bool                     `json:"evilTwin,omitempty"`
	Expansion        int                      `json:"expansion,omitempty"`
	ExpansionEnum    string                   `json:"expansionEnum,omitempty"`
	ExpansionWins    map[string]ExpansionWins `json:"expansionWins,omitempty"`
	ExtraCardInfo    ExtraCardInfo            `json:"extraCardInfo,omitempty"`
	FlavorText       string                   `json:"flavorText,omitempty"`
	FrontImage       string                   `json:"frontImage,omitempty"`
	House            string                   `json:"house,omitempty"`
	Houses           []string                 `json:",omitempty"`
	ID               string                   `json:"id,omitempty"`
	Losses           int                      `json:"losses,omitempty"`
	Maverick         bool                     `json:"maverick,omitempty"`
	Power            int                      `json:"power,omitempty"`
	PowerString      string                   `json:"powerString,omitempty"`
	Rarity           string                   `json:"rarity,omitempty"`
	Traits           []string                 `json:"traits,omitempty"`
	Wins             int                      `json:"wins,omitempty"`
}

Card represents all the data about a particular card.

type CardImageFetcher

type CardImageFetcher interface {
	// GetCardImage gets the data for a card image, given a URL.
	GetCardImage(ctx context.Context, imageURL string) (
		data []byte, err error)
}

CardImageFetcher gets the front images for cards.

type CardInDeck

type CardInDeck struct {
	CardTitle string `json:"cardTitle,omitempty"`
	Rarity    string `json:"rarity,omitempty"`
	Legacy    bool   `json:"legacy,omitempty"`
	Maverick  bool   `json:"maverick,omitempty"`
	Anomaly   bool   `json:"anomaly,omitempty"`
}

CardInDeck represents data about a specific card in a specific deck.

type CardNumber

type CardNumber struct {
	CardNumber string `json:"cardNumber,omitempty"`
	Expansion  string `json:"expansion,omitempty"`
}

CardNumber represents the number of a card within an expansion.

type DataFetcher

type DataFetcher interface {
	// GetCards gets a full set of card objects.
	GetCards(ctx context.Context) ([]Card, error)
	// GetMyDecks gets all the decks associated with the user running
	// this program.
	GetMyDecks(ctx context.Context) (decks []Deck, err error)
	// GetDeck returns the full deck object for the given `id`. If
	// `deck` is not nil, it will be updated with whatever data has
	// changed, leaving the other existing fields intact.
	GetDeck(ctx context.Context, id string, deck *Deck) (
		updatedDeck Deck, err error)
}

DataFetcher provides card and deck data.

type Deck

type Deck struct {
	DeckInfo   DeckInfo `json:"deck,omitempty"`
	Funny      bool     `json:"funny,omitempty"`
	Notes      string   `json:"notes,omitempty"`
	OwnedByMe  bool     `json:"ownedByMe,omitempty"`
	Wishlist   bool     `json:"wishlist,omitempty"`
	SASVersion int      `json:"sasVersion,omitempty"`
}

Deck represents all the data about a specific deck.

type DeckImageFetcher

type DeckImageFetcher interface {
	// GetDeckImageSuffix gets the file suffix for the filetype used
	// by all the images returned from `GetDeckImage`.
	GetDeckImageSuffix() string
	// GetDeckImage gets the data for a deck image for the given `deckID`.
	GetDeckImage(ctx context.Context, deckID string) (
		data []byte, err error)
}

DeckImageFetcher gets the front images for decks.

type DeckInfo

type DeckInfo struct {
	ActionCount            int           `json:"actionCount,omitempty"`
	AercScore              int           `json:"aercScore,omitempty"`
	AercVersion            int           `json:"aercVersion,omitempty"`
	AmberControl           float64       `json:"amberControl,omitempty"`
	AntisynergyRating      int           `json:"antisynergyRating,omitempty"`
	ArtifactControl        float64       `json:"artifactControl,omitempty"`
	CreatureControl        float64       `json:"creatureControl,omitempty"`
	CreatureCount          int           `json:"creatureCount,omitempty"`
	CreatureProtection     float64       `json:"creatureProtection,omitempty"`
	DateAdded              string        `json:"dateAdded,omitempty"`
	Disruption             float64       `json:"disruption,omitempty"`
	EffectivePower         int           `json:"effectivePower,omitempty"`
	Efficiency             float64       `json:"efficiency,omitempty"`
	EfficiencyBonus        float64       `json:"efficiencyBonus,omitempty"`
	Expansion              string        `json:"expansion,omitempty"`
	ExpectedAmber          float64       `json:"expectedAmber,omitempty"`
	Houses                 []HouseInDeck `json:"housesAndCards,omitempty"`
	ID                     int           `json:"id,omitempty"`
	KeyforgeID             string        `json:"keyforgeId,omitempty"`
	LastSasUpdate          string        `json:"lastSasUpdate,omitempty"`
	Name                   string        `json:"name,omitempty"`
	PreviousMajorSasRating int           `json:"previousMajorSasRating,omitempty"`
	PreviousSasRating      int           `json:"previosSasRating,omitempty"`
	RawAmber               int           `json:"rawAmber,omitempty"`
	SasPercentile          float64       `json:"sasPercentile,omitempty"`
	SasRating              int           `json:"sasRating,omitempty"`
	SynergyRating          int           `json:"synergyRating,omitempty"`
	TotalArmor             int           `json:"totalArmor,omitempty"`
	TotalPower             int           `json:"totalPower,omitempty"`
}

DeckInfo represents detailed info and ratings about a specific deck.

type DeckMetadata

type DeckMetadata struct {
	ID        string
	Name      string
	DateAdded time.Time
}

DeckMetadata exposes enough data about a deck to construct fliesystem metadata for it.

type ExpansionWins

type ExpansionWins struct {
	Losses int `json:"losses,omitempty"`
	Wins   int `json:"wins,omitempty"`
}

ExpansionWins represents the record of a card within a particular expansion.

type ExtraCardInfo

type ExtraCardInfo struct {
	Active                bool    `json:"active,omitempty"`
	AdaptiveScore         int     `json:"adaptiveScore,omitempty"`
	AmberControl          float64 `json:"amberControl,omitempty"`
	AmberControlMax       float64 `json:"amberControlMax,omitempty"`
	ArtifactControl       float64 `json:"artifactControl,omitempty"`
	ArtifactControlMax    float64 `json:"artifactControlMax,omitempty"`
	BaseSynPercent        float64 `json:"baseSynPercent,omitempty"`
	CardName              string  `json:"cardName,omitempty"`
	Created               string  `json:"created,omitempty"`
	CreatureControl       float64 `json:"creatureControl,omitempty"`
	CreatureControlMax    float64 `json:"creatureControlMax,omitempty"`
	CreatureProtection    float64 `json:"creatureProtection,omitempty"`
	CreatureProtectionMax float64 `json:"creatureProtectionMax,omitempty"`
	Disruption            float64 `json:"disruption,omitempty"`
	DisruptionMax         float64 `json:"disruptionMax,omitempty"`
	EffectivePower        float64 `json:"effectivePower,omitempty"`
	EffectivePowerMax     float64 `json:"effectivePowerMax,omitempty"`
	Efficiency            float64 `json:"efficiency,omitempty"`
	EfficiencyMax         float64 `json:"efficiencyMax,omitempty"`
	EnhancementAmber      int     `json:"enhancementAmber,omitempty"`
	EnhancementCapture    int     `json:"enhancementCapture,omitempty"`
	EnhancementDamage     int     `json:"enhancementDamage,omitempty"`
	EnhancementDraw       int     `json:"enhancementDraw,omitempty"`
	ExpectedAmber         float64 `json:"expectedAmber,omitempty"`
	ExpectedAmberMax      float64 `json:"expectedAmberMax,omitempty"`
	ID                    string  `json:"id,omitempty"`
	Other                 float64 `json:"other,omitempty"`
	OtherMax              float64 `json:"otherMax,omitempty"`
	Published             string  `json:"published,omitempty"`
	PublishedDate         string  `json:"publishedDate,omitempty"`
	Recursion             float64 `json:"recursion,omitempty"`
	RecursionMax          float64 `json:"recursionMax,omitempty"`
	Synergies             []Trait `json:"synergies,omitempty"`
	Traits                []Trait `json:"traits,omitempty"`
	Updated               string  `json:"updated,omitempty"`
	Version               int     `json:"version,omitempty"`
}

ExtraCardInfo represents detailed information and ratings about a card.

type HouseInDeck

type HouseInDeck struct {
	House string       `json:"house,omitempty"`
	Cards []CardInDeck `json:"cards,omitempty"`
}

HouseInDeck represents a house and all its cards in a specific deck.

type ImageCache

type ImageCache interface {
	// GetCardImage returns the card image data and `true` if the card
	// exists in the cache.
	GetCardImage(ctx context.Context, cardID, fileType string) (
		[]byte, bool, error)
	// StoreCardImage stores the given card data as the given file
	// type, overwriting any existing data for that card and type.
	StoreCardImage(
		ctx context.Context, cardID, fileType string, data []byte) error
	// GetDeckImage returns the deck image data and `true` if the deck
	// exists in the cache.
	GetDeckImage(ctx context.Context, deckID, fileType string) (
		[]byte, bool, error)
	// StoreDeckImage stores the given deck data as the given file
	// type, overwriting any existing data for that deck and type.
	StoreDeckImage(
		ctx context.Context, deckID, fileType string, data []byte) error
}

ImageCache stores card and deck images locally, for performance.

type Storage

type Storage interface {
	// StoreCards stores all the given cards, overwriting any existing
	// cards with the same IDs as the new cards.
	StoreCards(ctx context.Context, cards []Card) error
	// GetCardTitles returns a map of cardID -> cardTitle for every
	// stored card.
	GetCardTitles(ctx context.Context) (titles map[string]string, err error)
	// GetCardImageURL retrieves the URL to the given card's image.
	GetCardImageURL(ctx context.Context, id string) (url string, err error)
	// GetCard gets the full card object for the given `id`.
	GetCard(ctx context.Context, id string) (card *Card, err error)
	// StoreDecks stores all the given decks, overwriting any existing
	// decks with the same IDs as the new decks.
	StoreDecks(ctx context.Context, decks []Deck) error
	// GetMetadataNames gets all the decks owned by the user running the
	// program.  It returns a map of deckID -> metadata.
	GetMyDeckMetadata(ctx context.Context) (
		mds map[string]DeckMetadata, err error)
	// GetMyDeckMetadataWithFilter gets all the decks owned by the user,
	// which also match the given filter. It returns a map of deckID
	// -> metadata.
	GetMyDeckMetadataWithFilter(ctx context.Context, filterRoot *filter.Node) (
		mds map[string]DeckMetadata, err error)
	// GetDeck returns the full deck object for the given `id`.
	GetDeck(ctx context.Context, id string) (deck *Deck, err error)
	// GetSampleDeckWithVersion returns a sample deck and its SAS version.
	GetSampleDeckWithVersion(ctx context.Context) (
		deckID string, sasVersion int, err error)
	// Resets the storage, deleting all current data.
	Reset(ctx context.Context) error
}

Storage stores, fetches and filters card and deck data.

type Trait

type Trait struct {
	CardName         string   `json:"cardName,omitempty"`
	CardTraits       []string `json:"cardTraits,omitempty"`
	CardTraitsString string   `json:"cardTraitsString,omitempty"`
	CardTypes        []string `json:"cardTypes,omitempty"`
	CardTypesString  string   `json:"cardTypesString,omitempty"`
	House            string   `json:"house,omitempty"`
	ID               string   `json:"id,omitempty"`
	NotCardTraits    bool     `json:"notCardTraits,omitempty"`
	Player           string   `json:"player,omitempty"`
	PowersString     string   `json:"powersString,omitempty"`
	PrimaryGroup     bool     `json:"primaryGroup,omitempty"`
	Rating           int      `json:"rating,omitempty"`
	SynergyGroup     string   `json:"synergyGroup,omitempty"`
	SynergyGroupMax  int      `json:"synergyGroupMax,omitempty"`
	Trait            string   `json:"trait,omitempty"`
}

Trait represents the traits of a card.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL