crossword

package
v0.0.0-...-4308b5e Latest Latest
Warning

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

Go to latest
Published: Apr 18, 2024 License: Apache-2.0 Imports: 31 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

View Source
var AvailableWSJDates = []string{}/* 2910 elements not displayed */

AvailableWSJDates contains the list of dates that there was or will be a Wall Street Journal crossword. The following command was used to obtain these dates. Puzzles between 2009 and 2013 have an index page on fleetingimage.com, but are hosted on a different site and the .puz files are no longer there.

for yy in {13..24}; do
  curl --silent "https://www.fleetingimage.com/wij/xyzzy/${yy}-wsj.html" |
  sed 's|</a>|</a>\n|g'                                                  |
  grep -E 'wsj[0-9]{6}.puz'                                              |
  sed -E 's/.*wsj([0-9]{6}).puz.*/\1/g'                                  |
  sed -E 's/([0-9]{2})([0-9]{2})([0-9]{2})/"20\1-\2-\3",/g'
done                                                                     |
sort -u

The results of this command are pasted below.

View Source
var MagicNumber = []byte("ACROSS&DOWN\000")
View Source
var NYTFirstPuzzleDate = time.Date(1942, time.February, 15, 0, 0, 0, 0, time.UTC)
View Source
var NYTSwitchToDailyDate = time.Date(1950, time.September, 11, 0, 0, 0, 0, time.UTC)

Prior to 1950-09-11 puzzles were only on Sundays.

View Source
var StateTTL = 4 * time.Hour

StateTTL determines how long a particular crossword's solve state should remain in redis in the absence of any activity.

View Source
var UnshiftTables = [10]map[byte]byte{

	{
		'A': 'A', 'B': 'B', 'C': 'C', 'D': 'D', 'E': 'E', 'F': 'F', 'G': 'G',
		'H': 'H', 'I': 'I', 'J': 'J', 'K': 'K', 'L': 'L', 'M': 'M', 'N': 'N',
		'O': 'O', 'P': 'P', 'Q': 'Q', 'R': 'R', 'S': 'S', 'T': 'T', 'U': 'U',
		'V': 'V', 'W': 'W', 'X': 'X', 'Y': 'Y', 'Z': 'Z',
	},

	{
		'A': 'Z', 'B': 'A', 'C': 'B', 'D': 'C', 'E': 'D', 'F': 'E', 'G': 'F',
		'H': 'G', 'I': 'H', 'J': 'I', 'K': 'J', 'L': 'K', 'M': 'L', 'N': 'M',
		'O': 'N', 'P': 'O', 'Q': 'P', 'R': 'Q', 'S': 'R', 'T': 'S', 'U': 'T',
		'V': 'U', 'W': 'V', 'X': 'W', 'Y': 'X', 'Z': 'Y',
	},

	{
		'A': 'Y', 'B': 'Z', 'C': 'A', 'D': 'B', 'E': 'C', 'F': 'D', 'G': 'E',
		'H': 'F', 'I': 'G', 'J': 'H', 'K': 'I', 'L': 'J', 'M': 'K', 'N': 'L',
		'O': 'M', 'P': 'N', 'Q': 'O', 'R': 'P', 'S': 'Q', 'T': 'R', 'U': 'S',
		'V': 'T', 'W': 'U', 'X': 'V', 'Y': 'W', 'Z': 'X',
	},

	{
		'A': 'X', 'B': 'Y', 'C': 'Z', 'D': 'A', 'E': 'B', 'F': 'C', 'G': 'D',
		'H': 'E', 'I': 'F', 'J': 'G', 'K': 'H', 'L': 'I', 'M': 'J', 'N': 'K',
		'O': 'L', 'P': 'M', 'Q': 'N', 'R': 'O', 'S': 'P', 'T': 'Q', 'U': 'R',
		'V': 'S', 'W': 'T', 'X': 'U', 'Y': 'V', 'Z': 'W',
	},

	{
		'A': 'W', 'B': 'X', 'C': 'Y', 'D': 'Z', 'E': 'A', 'F': 'B', 'G': 'C',
		'H': 'D', 'I': 'E', 'J': 'F', 'K': 'G', 'L': 'H', 'M': 'I', 'N': 'J',
		'O': 'K', 'P': 'L', 'Q': 'M', 'R': 'N', 'S': 'O', 'T': 'P', 'U': 'Q',
		'V': 'R', 'W': 'S', 'X': 'T', 'Y': 'U', 'Z': 'V',
	},

	{
		'A': 'V', 'B': 'W', 'C': 'X', 'D': 'Y', 'E': 'Z', 'F': 'A', 'G': 'B',
		'H': 'C', 'I': 'D', 'J': 'E', 'K': 'F', 'L': 'G', 'M': 'H', 'N': 'I',
		'O': 'J', 'P': 'K', 'Q': 'L', 'R': 'M', 'S': 'N', 'T': 'O', 'U': 'P',
		'V': 'Q', 'W': 'R', 'X': 'S', 'Y': 'T', 'Z': 'U',
	},

	{
		'A': 'U', 'B': 'V', 'C': 'W', 'D': 'X', 'E': 'Y', 'F': 'Z', 'G': 'A',
		'H': 'B', 'I': 'C', 'J': 'D', 'K': 'E', 'L': 'F', 'M': 'G', 'N': 'H',
		'O': 'I', 'P': 'J', 'Q': 'K', 'R': 'L', 'S': 'M', 'T': 'N', 'U': 'O',
		'V': 'P', 'W': 'Q', 'X': 'R', 'Y': 'S', 'Z': 'T',
	},

	{
		'A': 'T', 'B': 'U', 'C': 'V', 'D': 'W', 'E': 'X', 'F': 'Y', 'G': 'Z',
		'H': 'A', 'I': 'B', 'J': 'C', 'K': 'D', 'L': 'E', 'M': 'F', 'N': 'G',
		'O': 'H', 'P': 'I', 'Q': 'J', 'R': 'K', 'S': 'L', 'T': 'M', 'U': 'N',
		'V': 'O', 'W': 'P', 'X': 'Q', 'Y': 'R', 'Z': 'S',
	},

	{
		'A': 'S', 'B': 'T', 'C': 'U', 'D': 'V', 'E': 'W', 'F': 'X', 'G': 'Y',
		'H': 'Z', 'I': 'A', 'J': 'B', 'K': 'C', 'L': 'D', 'M': 'E', 'N': 'F',
		'O': 'G', 'P': 'H', 'Q': 'I', 'R': 'J', 'S': 'K', 'T': 'L', 'U': 'M',
		'V': 'N', 'W': 'O', 'X': 'P', 'Y': 'Q', 'Z': 'R',
	},

	{
		'A': 'R', 'B': 'S', 'C': 'T', 'D': 'U', 'E': 'V', 'F': 'W', 'G': 'X',
		'H': 'Y', 'I': 'Z', 'J': 'A', 'K': 'B', 'L': 'C', 'M': 'D', 'N': 'E',
		'O': 'F', 'P': 'G', 'Q': 'H', 'R': 'I', 'S': 'J', 'T': 'K', 'U': 'L',
		'V': 'M', 'W': 'N', 'X': 'O', 'Y': 'P', 'Z': 'Q',
	},
}

These tables help to perform unshift operations quickly by precomputing the 10 possible unshift operations we might have to do.

View Source
var XWordInfoHeaders = map[string]string{
	"Referer": "https://www.xwordinfo.com/JSON",
}

Functions

func ChannelID

func ChannelID(channel string) pubsub.Channel

func CompleteEvent

func CompleteEvent() pubsub.Event

func ForceErrorDuringPuzzleLoad

func ForceErrorDuringPuzzleLoad(t *testing.T, err error)

ForceErrorDuringLoad sets up an error to be returned when an attempt is made to load a puzzle.

func ForceErrorDuringSettingsLoad

func ForceErrorDuringSettingsLoad(t *testing.T, err error)

ForceErrorDuringSettingsLoad sets up an error to be returned when an attempt is made to load settings.

func ForceErrorDuringSettingsSave

func ForceErrorDuringSettingsSave(t *testing.T, err error)

ForceErrorDuringSettingsSave sets up an error to be returned when an attempt is made to save settings.

func ForceErrorDuringStateLoad

func ForceErrorDuringStateLoad(t *testing.T, err error)

ForceErrorDuringStateLoad sets up an error to be returned when an attempt is made to load state.

func ForceErrorDuringStateSave

func ForceErrorDuringStateSave(t *testing.T, err error)

ForceErrorDuringStateSave sets up an error to be returned when an attempt is made to save state.

func ForcePuzzleToBeLoaded

func ForcePuzzleToBeLoaded(t *testing.T, filename string)

ForcePuzzleToBeLoaded sets up a cached version of a puzzle using a file from the testdata directory.

func GetAllChannels

func GetAllChannels(conn db.Connection) ([]model.Channel, error)

GetAllChannels returns a slice of model.Channel instances for each crossword that contains state in the database. If there are no active channels then an empty slice is returned. This method does not update the expiration times of any state instance.

func GetAvailableDates

func GetAvailableDates() http.HandlerFunc

GetAvailableDates returns the available crossword dates across all puzzle sources.

func GetEvents

func GetEvents(pool *redis.Pool, registry *pubsub.Registry) http.HandlerFunc

GetEvents establishes an event stream with a client. An event stream is server side event stream (SSE) with a client's browser that allows one way communication from the server to the client. Clients that call into this handler will keep an open connection open to the server waiting to receive events as JSON objects. The server can send events to all clients of a channel using the pubsub.Registry's Publish method.

func LoadAvailableNYTDates

func LoadAvailableNYTDates() []time.Time

LoadAvailableNYTDates calculates the set of available dates for crossword puzzles from The New York Times.

func LoadAvailableWSJDates

func LoadAvailableWSJDates() []time.Time

LoadAvailableWSJDates calculates the set of available dates for crossword puzzles from The Wall Street Journal.

func NewEventSubscription

func NewEventSubscription(t *testing.T, registry *pubsub.Registry, channel string) <-chan pubsub.Event

NewEventSubscription will return a channel of events that are subscribed to the specified channel. The subscription will be configured to automatically unsubscribe when the test completes.

func NewRedisConnection

func NewRedisConnection(t *testing.T, pool *redis.Pool) redis.Conn

NewRedisConnection will return a connection to the provided connection pool. The returned connection will be configured to automatically close when the test completes.

func NewTestRouter

func NewTestRouter(t *testing.T) (chi.Router, *redis.Pool, *pubsub.Registry)

NewTestRouter will return a router configured with a redis pool and pubsub registry and wired together along with all of the routes for a spelling bee puzzle.

func ParseAnswer

func ParseAnswer(answer string) ([]string, error)

ParseAnswer parses an answer string into a list of cell values. The answer string is parsed in such a way to look for cell values that contain multiple characters (aka a rebus). It does this by looking for parenthesized groups of letters. For example the string "(red)velvet" would be interpreted as ["red", "v", "e", "l", "v", "e", "t"] and fit as the answer for a 7 cell clue.

Additionally if an answer contains a "." character anywhere that particular cell will be left empty. This allows strings like "....s" to be entered to indicate that the answer is known to be plural, but the other letters aren't known yet. Within a rebus cell "." characters are kept as-is.

Whitespace within answers is removed and ignored. This makes it more natural to specify answers like "red velvet cake".

func ParseClue

func ParseClue(clue string) (int, string, error)

ParseClue parses the identifier of a clue into its number and direction. If the clue cannot be parsed for some reason then an error will be returned.

func ParseXWordInfoClue

func ParseXWordInfoClue(s string) (int, string, error)

ParseXWordInfoClue parses the text of a clue from the New York Times into its clue number and clue text.

func ReadLength

func ReadLength(in io.Reader, length uint16) ([]byte, error)

func ReadUntil

func ReadUntil(in io.Reader, delimiter byte) ([]byte, error)

func RegisterRoutes

func RegisterRoutes(r chi.Router, pool *redis.Pool, registry *pubsub.Registry)

func SetSettings

func SetSettings(conn redis.Conn, channel string, settings Settings) error

SetSettings will write settings for the provided channel name. If the settings can't be properly written then an error will be returned.

func SetState

func SetState(conn db.Connection, channel string, state State) error

SetState writes the state for a channel's crossword solve to redis. If the state can't be property written then an error will be returned.

func SettingsEvent

func SettingsEvent(settings Settings) pubsub.Event

func SettingsKey

func SettingsKey(name string) string

SettingsKey returns the key that should be used in redis to store a particular channel's settings.

func ShowClue

func ShowClue(registry *pubsub.Registry) http.HandlerFunc

ShowClue sends an event to all clients of a channel requesting that they update their view to make the specified clue visible. If the specified clue isn't structured as a proper clue number and direction than an error will be returned.

func ShowClueEvent

func ShowClueEvent(clue string) pubsub.Event

func StateEvent

func StateEvent(state State) pubsub.Event

func StateKey

func StateKey(name string) string

StateKey returns the key that should be used in redis to store a particular crossword solve's state.

func ToggleStatus

func ToggleStatus(pool *redis.Pool, registry *pubsub.Registry) http.HandlerFunc

ToggleStatus changes the status of the current crossword solve to a new status. This effectively toggles between the solving and paused statuses as long as the solve is in a state that can be paused or resumed.

func UpdateAnswer

func UpdateAnswer(pool *redis.Pool, registry *pubsub.Registry) http.HandlerFunc

UpdateAnswer applies an answer to a given clue in the current crossword solve.

func UpdatePuzzle

func UpdatePuzzle(pool *redis.Pool, registry *pubsub.Registry) http.HandlerFunc

UpdatePuzzle changes the crossword puzzle that's currently being solved for a channel.

func UpdateSetting

func UpdateSetting(pool *redis.Pool, registry *pubsub.Registry) http.HandlerFunc

UpdateSetting changes a specified crossword setting to a new value.

Types

type CRC

type CRC uint16

func (CRC) Write

func (crc CRC) Write(value []byte) CRC

func (CRC) Write16

func (crc CRC) Write16(value uint16) CRC

func (CRC) Write8

func (crc CRC) Write8(value uint8) CRC

type ClueVisibility

type ClueVisibility int

ClueVisibility is an enumeration representing which clues should be shown.

const (
	AllCluesVisible ClueVisibility = iota
	NoCluesVisible
	OnlyDownCluesVisible
	OnlyAcrossCluesVisible
)

func (ClueVisibility) MarshalJSON

func (v ClueVisibility) MarshalJSON() ([]byte, error)

func (ClueVisibility) String

func (v ClueVisibility) String() string

func (*ClueVisibility) UnmarshalJSON

func (v *ClueVisibility) UnmarshalJSON(bs []byte) error

type PuzFile

type PuzFile struct {
	Header struct {
		GlobalChecksum uint16
		MagicNumber    [12]byte // ACROSS&DOWN\000 (null terminated)
		HeaderChecksum uint16
		MaskedChecksum [8]byte
		Version        [4]byte // e.g. 1.2\0 (null terminated)

		UnscrambledChecksum uint16

		Width          uint8
		Height         uint8
		NumClues       uint16
		UnknownBitmask uint16
		ScrambledTag   uint16
		// contains filtered or unexported fields
	}

	Solution   []byte
	Cells      []byte
	Title      []byte
	Author     []byte
	Copyright  []byte
	Clues      [][]byte
	Notes      []byte
	Extensions map[string]*PuzFileExtension
}

PuzFile represents the binary file format of a .puz file that contains a crossword puzzle.

In short it contains a fixed size header that outlines the various checksums and dimensions of the puzzle followed by the variable length portions of the puzzle such as the solution and clues. Lastly the file can contain a set of extension sections to the file format to represent things like rebus squares, circled squares, etc.

Of note is that the file format itself doesn't actually contain clue numbers, they must be derived from the structure of the black cells within the puzzle's grid.

Details on the file format can be found at:

https://code.google.com/archive/p/puz/wikis/FileFormat.wiki

Implementations of parsers can be found at:

https://github.com/alexdej/puzpy
https://github.com/kobolabs/puz

func (*PuzFile) Convert

func (f *PuzFile) Convert() (*Puzzle, error)

Convert takes the in-memory representation of a .puz file and converts it into a Puzzle object.

func (*PuzFile) GlobalChecksum

func (f *PuzFile) GlobalChecksum() uint16

func (*PuzFile) HeaderChecksum

func (f *PuzFile) HeaderChecksum() uint16

func (*PuzFile) MaskedChecksum

func (f *PuzFile) MaskedChecksum() [8]byte

func (*PuzFile) StringsChecksum

func (f *PuzFile) StringsChecksum(crc CRC) CRC

func (*PuzFile) Unscramble

func (f *PuzFile) Unscramble(key int) bool

Unscramble attempts to undo a scramble operation with the provided key. If the operation succeeds then the solution will be updated and true will be returned.

func (*PuzFile) Version

func (f *PuzFile) Version() (int, int)

Version returns the version number of the puzzle file.

type PuzFileExtension

type PuzFileExtension struct {
	Header struct {
		Code     [4]byte
		Length   uint16
		Checksum uint16
	}

	Data []byte
}

PuzFileExtension represents the contents of an extension within a .puz file. An extension contains a fixed size header followed by variable length data that is interpreted according to which type of extension it is.

func (*PuzFileExtension) Checksum

func (e *PuzFileExtension) Checksum() uint16

type Puzzle

type Puzzle struct {
	// A human readable description of the puzzle
	Description string `json:"description"`

	// The number of rows in the crossword grid.
	Rows int `json:"rows"`

	// The number of columns in the crossword grid.
	Cols int `json:"cols"`

	// The title of the crossword.
	Title string `json:"title"`

	// The publisher of the crossword.
	Publisher string `json:"publisher"`

	// The date that the crossword was published.
	PublishedDate time.Time `json:"published"`

	// The name of the author(s) of the crossword.
	Author string `json:"author"`

	// The cells of the crossword as a 2D list, entries are the letter (or letters
	// in the case of a rebus) that belong in the cell.  If a cell cannot be
	// inputted into then it will contain the empty string.  The lists are first
	// indexed by the row coordinate of the cell and then by the column coordinate
	// of the cell.
	Cells [][]string `json:"cells,omitempty"`

	// The block attribute for each of the cells in the crossword as a 2D list.
	// Cells that cannot be inputted into will contain an entry of true, all other
	// cells will contain an entry of false.  Like cells the 2D list is first
	// indexed by the row coordinate of the cell and then by the column
	// coordinate.
	CellBlocks [][]bool `json:"cell_blocks"`

	// The clue numbers for each of the cells in the crossword as a 2D list.
	// Cells that cannot be inputted into or that don't have a clue number will
	// contain an entry of 0.  Like cells the 2D list is first indexed by the row
	// coordinate of the cell and then by the column coordinate.
	CellClueNumbers [][]int `json:"cell_clue_numbers"`

	// Whether or not a cell contains a circle for all of the cells in the
	// crossword as a 2D list.  Cells that should have a circle rendered in them
	// appear as true and those that shouldn't have a circle rendered in them will
	// appear as false.  Like cells the 2D list is first indexed by the row
	// coordinate of the cell and then by the column coordinate.
	CellCircles [][]bool `json:"cell_circles"`

	// Whether or not a cell should be shaded for all of the cells in the
	// crossword as a 2D list.  Cells that should be shaded appear as true and
	// those that shouldn't be shaded will appear as false.  Like cells the 2D
	// list is first indexed by the row coordinate of the cell and then by the
	// column coordinate.
	CellShades [][]bool `json:"cell_shades"`

	// The clues for the across answers indexed by the clue number.
	CluesAcross map[int]string `json:"clues_across"`

	// The clues for the down answers indexed by the clue number.
	CluesDown map[int]string `json:"clues_down"`

	// The notes for the clues of this crossword.  Often there is something
	// visually done when the crossword is published in a newspaper but that can't
	// be done online.  These notes describe the visual change so that the
	// crossword can be solved online.
	Notes string `json:"notes"`
}

Puzzle represents a crossword puzzle. The puzzle is comprised of a grid which has dimensions (rows x cols) and demonstrates which cells of the crossword are available for placing letters into and which are not. Additionally the puzzle contains a set of clues organized by number and whether or not they fill in cells going across or down. Lastly a puzzle has various bits of interesting metadata such as the publication that the crossword is from, the date that it was published as well as the author(s).

func LoadFromEncodedPuzFile

func LoadFromEncodedPuzFile(encoded string) (*Puzzle, error)

LoadFromEncodedPuzFile will base64 decode the input and then attempt to load the resulting binary as a .puz file into a Puzzle object.

func LoadFromNewYorkTimes

func LoadFromNewYorkTimes(date string) (*Puzzle, error)

LoadFromNewYorkTimes loads a crossword puzzle from the New York Times for a particular date.

This method uses the xwordinfo.com JSON API to load a New York Times crossword puzzle. While organized slightly differently from the XPF API the returned data is mostly the same. Documentation for the JSON API can be found here: https://www.xwordinfo.com/JSON/

If the puzzle cannot be loaded or parsed then an error is returned.

func LoadFromPuzFileURL

func LoadFromPuzFileURL(url string) (*Puzzle, error)

LoadFromPuzFileURL will take a URL and retrieve it and load it into a Puzzle object.

If the URL cannot be retrieved or the puzzle parsed then an error is returned.

func LoadFromWallStreetJournal

func LoadFromWallStreetJournal(date string) (*Puzzle, error)

LoadFromWallStreetJournal loads a crossword puzzle from the Wall Street Journal for a particular date.

This method downloads a .puz file and loads it into a Puzzle object. We do this in particular on the server side instead of within the client because the herbach.dnsalias.com site unfortunately is only HTTP, and we can't load resources from a non-HTTPS site in the browser.

If the puzzle cannot be loaded or parsed then an error is returned.

func LoadPuzFile

func LoadPuzFile(in io.Reader) (*Puzzle, error)

LoadPuzFile parses a binary .puz file into a Puzzle object.

func LoadTestPuzzle

func LoadTestPuzzle(t *testing.T, filename string) *Puzzle

LoadTestPuzzle loads a puzzle from the testdata directory.

func ParseXWordInfoResponse

func ParseXWordInfoResponse(in io.Reader) (*Puzzle, error)

ParseXWordInfoResponse converts a JSON response from xwordinfo.com into a puzzle object.

func (*Puzzle) GetAnswerCoordinates

func (p *Puzzle) GetAnswerCoordinates(num int, direction string) (int, int, int, int, error)

GetAnswerCoordinates returns the min/max x/y coordinates for a clue. If the clue doesn't exist then an error is returned.

func (*Puzzle) WithoutSolution

func (p *Puzzle) WithoutSolution() *Puzzle

WithoutSolution returns a copy of the puzzle that has the solution cells missing. This makes it suitable to pass to a client that shouldn't know the answers to the puzzle.

type Settings

type Settings struct {
	// When enabled only correct answers will be filled into the puzzle grid.
	OnlyAllowCorrectAnswers bool `json:"only_allow_correct_answers"`

	// Which clues should be shown to users.  Can be all of the clues, none of the
	// clues, only across clues or only down clues.
	CluesToShow ClueVisibility `json:"clues_to_show"`

	// What font size should the clues be rendered with.
	ClueFontSize model.FontSize `json:"clue_font_size"`

	// Whether or not notes field should shown.
	ShowNotes bool `json:"show_notes"`
}

Settings represents the optional behaviors that can be enabled or disabled by a streamer for their channel's crossword solves.

func GetSettings

func GetSettings(conn redis.Conn, channel string) (Settings, error)

GetSettings will load settings for the provided channel name. If the settings can't be properly loaded then an error will be returned.

type State

type State struct {
	// The status of the channel's crossword solve.
	Status model.Status `json:"status"`

	// The crossword puzzle that's being solved.  May not always be present, for
	// example when the state is being serialized to be sent to the browser.
	Puzzle *Puzzle `json:"puzzle,omitempty"`

	// The currently filled in cells of the crossword.
	Cells [][]string `json:"cells"`

	// Whether or not an across clue with a given clue number has had an answer
	// filled in.
	AcrossCluesFilled map[int]bool `json:"across_clues_filled"`

	// Whether or not a down clue with a given clue number has had an answer
	// filled in.
	DownCluesFilled map[int]bool `json:"down_clues_filled"`

	// The time that we last started or resumed solving the puzzle.  If the
	// channel has not yet started solving the puzzle or is in a non-playing state
	// this will be nil.
	LastStartTime *time.Time `json:"last_start_time,omitempty"`

	// The total time spent on solving the puzzle up to the last start time.
	TotalSolveDuration model.Duration `json:"total_solve_duration"`
}

State represents the state of an active channel that is attempting to solve a crossword.

func GetState

func GetState(conn db.Connection, channel string) (State, error)

GetState loads the state for a crossword solve from redis. If the state can't be loaded then an error will be returned. If there is no state, then the zero value will be returned. After a state is read, its expiration time is automatically updated.

func NewState

func NewState(t *testing.T, filename string) State

NewState creates a new crossword puzzle state that has been properly initialized with the puzzle corresponding to the provided filename.

func (*State) ApplyAnswer

func (s *State) ApplyAnswer(clue string, answer string, onlyCorrect bool) error

ApplyAnswer applies an answer for a clue to the state. If the clue cannot be identified or the answer doesn't fit property (too short or too long) then an error will be returned. If the onlyCorrect parameter is true then only correct cells will be permitted and an error is returned if any part of the answer is incorrect or would remove a correct cell.

func (*State) ClearIncorrectCells

func (s *State) ClearIncorrectCells() error

ClearIncorrectCells will look at each filled in cell of the crossword and clear it if it is filled in with an incorrect answer. The AcrossCluesFilled and DownCluesFilled fields will also be updated to indicate any clues that are now unanswered due to cleared cells.

func (*State) UpdateFilledClues

func (s *State) UpdateFilledClues() error

UpdateFilledClues looks at each clue in the puzzle and determines if a complete answer has been provided for the clue, if so then the corresponding entry in AcrossCluesFilled or DownCluesFilled will be set to true. This method doesn't check that the provided answer is correct, just that one is present.

type XWordInfoPuzzle

type XWordInfoPuzzle struct {
	Title     string `json:"title"`
	Author    string `json:"author"`
	Publisher string `json:"publisher"`
	Date      string `json:"date"`
	Notepad   string `json:"notepad"`
	JNotes    string `json:"jnotes"`
	Size      struct {
		Rows int `json:"rows"`
		Cols int `json:"cols"`
	} `json:"size"`
	Grid         []string `json:"grid"`
	GridNums     []int    `json:"gridnums"`
	Circles      []int    `json:"circles"`
	ShadeCircles bool     `json:"shadecircles"`
	Clues        struct {
		Across []string `json:"across"`
		Down   []string `json:"down"`
	} `json:"clues"`
	Answers struct {
		Across []string `json:"across"`
		Down   []string `json:"down"`
	} `json:"answers"`
}

XWordInfoPuzzle is a representation of the response from the xwordinfo.com JSON API when querying for a puzzle.

Jump to

Keyboard shortcuts

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