acrostic

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: 32 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

View Source
var AuthorTitleRegexps = []*regexp.Regexp{

	regexp.MustCompile(`^(?P<author>[^,:]+)[,:] (?P<title>[^—]+) —`),

	regexp.MustCompile(`^(?P<author>[^,:]+)[,:] (?P<title>[^-]+) -`),

	regexp.MustCompile(`(?P<author>)(?P<title>[^—]+) —`),
}

A set of regular expressions to use to extract the author and title of an acrostic. These will be tried in order and the first one to return a match is the one that is used.

View Source
var ClueLetters = []string{
	"A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O",
	"P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z",
}
View Source
var QuoteRegexps = []*regexp.Regexp{

	regexp.MustCompile(`^(?P<author_and_title>[^—]+) — (?P<quote>.+)$`),
}

A set of regular expressions to use to extract the quote of an acrostic.

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 XWordInfoHeaders = map[string]string{
	"Referer": "https://www.xwordinfo.com/Acrostic",
}

Functions

func ChannelID

func ChannelID(channel string) pubsub.Channel

func CompleteEvent

func CompleteEvent(author, title, text string) pubsub.Event

func ForceAvailableDatesToBeLoaded

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

ForceAvailableDatesToBeLoaded sets up a cached version of a available dates using a file from the testdata directory.

func ForceErrorDuringAvailableDatesLoad

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

ForceErrorDuringAvailableDatesLoad sets up an error to be returned when an attempt is made to load a set of available dates.

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 acrostic 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 acrostic dates across all puzzle sources.

In order to minimize load on external data sources the response is cached for several hours.

func GetClueLetter

func GetClueLetter(index int) (string, error)

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 LoadAvailableNewYorkTimesDates

func LoadAvailableNewYorkTimesDates() ([]time.Time, error)

LoadAvailableNewYorkTimesDates determines all of the historical dates that have acrostic puzzles.

This method uses the https://www.xwordinfo.com/SelectAcrostic page and parses the HTML on the page to determine the available puzzle dates.

If the dates cannot be determined then an error is returned.

func LoadTestAvailableDates

func LoadTestAvailableDates(t *testing.T, filename string) []time.Time

LoadTestAvailableDates loads a set of available dates from the testdata directory.

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 ParseAuthorAndTitle

func ParseAuthorAndTitle(s string) (string, string)

ParseAuthorAndTitle extracts the author name and title from the quote field of the xwordinfo.com JSON API response.

func ParseInts

func ParseInts(s string) ([]int, error)

func ParseQuote

func ParseQuote(s string) string

func ParseXWordInfoAvailableDatesResponse

func ParseXWordInfoAvailableDatesResponse(in io.Reader) ([]time.Time, error)

ParseXWordInfoAvailableDatesResponse converts an HTML response from the select acrostic page on xwordinfo.com into a list of available dates.

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 acrostic 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 letter 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 acrostic 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 either a given clue or given set of cells in the current acrostic solve.

func UpdatePuzzle

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

UpdatePuzzle changes the acrostic 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 acrostic setting to a new value.

Types

type Puzzle

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

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

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

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

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

	// The author of the acrostic.
	Author string `json:"author"`

	// The title of the book the acrostic is from.
	Title string `json:"title"`

	// The quote that the acrostic is from.
	Quote string `json:"quote"`

	// The cells of the acrostic as a 2D list, entries are the letter that belongs
	// 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 givens of the acrostic as a 2D list.  A given is a cell in the acrostic
	// that has a value, but no cell number or corresponding clue letter.  If a
	// cell is not a given then it will contain the empty string.  Like cells the
	// 2D list is first indexed by the row coordinate of the cell and then by the
	// column coordinate.
	Givens [][]string `json:"givens,omitempty"`

	// The block attribute for each of the cells in the acrostic 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 numbers for each of the cells in the acrostic as a 2D list.  Cells that
	// cannot be inputted into 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.
	CellNumbers [][]int `json:"cell_clue_numbers"`

	// The clue letter for each of the cells in the acrostic as a 2D list.
	// Cells that cannot be inputted into or that don't have a clue letter will
	// contain an empty string.  Like cells the 2D list is first indexed by the
	// row coordinate of the cell and then by the column coordinate.
	CellClueLetters [][]string `json:"cell_clue_letters"`

	// The clues indexed by the clue letter.
	Clues map[string]string `json:"clues"`

	// The clue numbers indexed by the clue letter.
	ClueNumbers map[string][]int `json:"clue_numbers"`
}

Puzzle represents an acrostic puzzle. The puzzle is comprised of a grid which has dimensions (rows x cols) and demonstrates which cells of the acrostic are available for placing letters into and which are not. Additionally the puzzle contains a set of lettered clues and a mapping of answer letters their position within the grid. Lastly a puzzle has various bits of interesting metadata such as the publication that the acrostic is from, the date that it was published as well as the author(s).

func LoadFromNewYorkTimes

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

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

This method uses the xwordinfo.com JSON API to load a New York Times acrostic puzzle. Unfortunately the JSON API for acrostics is not documented.

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

func LoadTestPuzzle

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

LoadTestPuzzle loads a puzzle from the testdata directory.

func ParseXWordInfoPuzzleResponse

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

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

func ParseXWordInfoWrappedPuzzleResponse

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

ParseXWordInfoWrappedPuzzleResponse unwraps and decompresses a JSON response from xwordinfo.com and then parses it into a puzzle object.

func (*Puzzle) GetCellCoordinates

func (p *Puzzle) GetCellCoordinates(num int) (int, int, error)

GetCellCoordinates returns the x, y coordinates for a numbered cell. If the cell 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"`

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

Settings represents the optional behaviors that can be enabled or disabled by a streamer for their channel's acrostic 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 acrostic solve.
	Status model.Status `json:"status"`

	// The acrostic 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 acrostic.
	Cells [][]string `json:"cells"`

	// Whether or not a clue with a given clue letter has had an answer filled in.
	CluesFilled map[string]bool `json:"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 an acrostic.

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 acrostic puzzle state that has been properly initialized with the puzzle corresponding to the provided filename.

func (*State) ApplyCellAnswer

func (s *State) ApplyCellAnswer(start int, answer string, onlyCorrect bool) error

ApplyCellAnswer applies an answer to the cells to the state. If the starting cell number specified outside the bounds of the puzzle or the answer doesn't fit within the bounds of the puzzle then an error will be returned. If the onlyCorrect parameter is true then only correct values will be permitted and an error is returned if any part of the answer is incorrect or would remove a correct cell.

func (*State) ApplyClueAnswer

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

ApplyClueAnswer 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 values 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 acrostic and clear it if it is filled in with an incorrect answer. The CluesFilled field 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 CluesFilled 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 {
	AnswerKey    string   `json:"answerKey"`
	ClueData     []string `json:"clueData"`
	Clues        []string `json:"clues"`
	Cols         int      `json:"cols"`
	Copyright    string   `json:"copyright"`
	Date         string   `json:"date"`
	FullQuote    string   `json:"fullQuote"`
	GridLetters  string   `json:"gridLetters"`
	GridNumbers  []int    `json:"gridNumbers"`
	TitleNumbers []int    `json:"mapTitle"`
	Quote        string   `json:"quote"`
	Rows         int      `json:"rows"`
}

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

type XWordInfoPuzzleWrapper

type XWordInfoPuzzleWrapper struct {
	Data string `json:"data"`
}

Jump to

Keyboard shortcuts

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