qparty

package module
v0.0.0-...-1b9e5be Latest Latest
Warning

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

Go to latest
Published: Dec 8, 2024 License: BSD-3-Clause Imports: 6 Imported by: 0

README

?-Party

A variant on a familiar quiz show game, implemented as an HTMX server in golang and echo, with ent and sqlite for data management. Uses WebSockets and SSE for realtime communication to the players, host, and audience.

Server (private, ask for access)

TODO img

Command Utilities

Some tools written in Go are provided in the cmd/ directory of this repo:

  • editor - CLI tool for creating a new board and/or episode, exports as JSON or writes into the challenges database

  • jarchive - fetch a playable game from a single episode of the archive

  • server - Serves HTML and JSON to hypermedia clients

Documentation

Index

Constants

View Source
const ZeroDollars = DollarValue(0)

Variables

View Source
var UnknownChallenge = ChallengeMetadata{0, 0, false}

Sentinel value for board entries that are missing/blank.

Functions

This section is empty.

Types

type Board

type Board struct {
	BoardID `json:",inline"`
	Columns []Category `json:"columns"`
	Missing []Position `json:"-,omitempty"`
}

The basic board definition (contains only category metadata).

type BoardID

type BoardID struct {
	Episode ShowNumber   `json:"episode,omitempty"`
	Round   EpisodeRound `json:"round,omitempty"` // cue:"<len(round_names)"
}

A board is identified by its episode and whether it's single or double round.

func (BoardID) RoundName

func (board BoardID) RoundName() string

type BoardState

type BoardState struct {
	Board   `json:",inline"`
	History []Selection `json:"history,omitempty"`
}

Extends the board definition with a history of challenge selections.

type Category

type Category struct {
	Metadata   CategoryMetadata    `json:"metadata,omitempty,inline"`
	Challenges []ChallengeMetadata `json:"challenges,omitempty"`
}

type CategoryAired

type CategoryAired struct {
	EpisodeID `json:"episode_id"`
	ShowDate  `json:",inline"`
}

type CategoryMetadata

type CategoryMetadata struct {
	Title    string          `json:"title"`
	Theme    CategoryTheme   `json:"theme,omitempty"`
	Episodes []CategoryAired `json:"episodes"`
}

type CategoryTheme

type CategoryTheme string

Proposal for category breakdown based on Trivial Pursuit classic categories.

const (
	ThemeUnknown        CategoryTheme = ""
	ThemeGeography      CategoryTheme = "Geography"
	ThemeEntertainment  CategoryTheme = "Entertainment"
	ThemeHistoryRoyalty CategoryTheme = "History & Royalty"
	ThemeArtLiterature  CategoryTheme = "Art & Literature"
	ThemeScienceNature  CategoryTheme = "Science & Nature"
	ThemeSportsLeisure  CategoryTheme = "Sports & Leisure"
)

type Challenge

type Challenge struct {
	ChallengeMetadata `json:",inline"`
	Clue              string `json:"clue"`

	Media    []Media `json:"media,omitempty"`
	Category string  `json:"category,omitempty"`
	Comments string  `json:"comments,omitempty"`
}

Challenge data (without the answer), for when a board position is selected.

type ChallengeMetadata

type ChallengeMetadata struct {
	ChallengeID uint        `json:"id"`
	Value       DollarValue `json:"value,omitempty"`

	TripleStumper bool `json:"stumper,omitempty"`
}

type DollarValue

type DollarValue int

func ParseDollarValue

func ParseDollarValue(text string) (DollarValue, error)

func (DollarValue) Abs

func (value DollarValue) Abs() int

Returns the integer value of a DollarValue, ignoring whether it was a wager.

func (DollarValue) IsWager

func (value DollarValue) IsWager() bool

func (DollarValue) String

func (value DollarValue) String() string

func (*DollarValue) ToggleWager

func (value *DollarValue) ToggleWager(next bool)

func (*DollarValue) UnmarshalText

func (value *DollarValue) UnmarshalText(text []byte) error

type EpisodeID

type EpisodeID uint

Unique ID which J-Archive uses to identify its episodes.

func (EpisodeID) HTML

func (id EpisodeID) HTML() string

Only the HTML filename and not the JSON filename can be inferred from the ID.

type EpisodeMetadata

type EpisodeMetadata struct {
	Show      ShowNumber `json:"show_number"`
	ShowTitle string     `json:"show_title"`

	EpisodeID `json:"episode_id,omitempty"`
	Aired     ShowDate `json:"aired,omitempty"`
	Taped     ShowDate `json:"taped,omitempty"`
}

type EpisodeRound

type EpisodeRound uint

An enum-like value for the different rounds.

const (
	ROUND_UNKNOWN EpisodeRound = iota
	ROUND_SINGLE
	ROUND_DOUBLE
	ROUND_FINAL
	ROUND_TIEBREAKER
	PRINTED_MEDIA
	MaxRoundEnum
)

func (EpisodeRound) String

func (round EpisodeRound) String() string

type EpisodeStats

type EpisodeStats struct {
	EpisodeMetadata `json:",inline"`

	SingleCount int          `json:"single_count"`
	DoubleCount int          `json:"double_count"`
	Stumpers    [][]Position `json:"triple_stumpers"`
}

type FullBoard

type FullBoard struct {
	BoardID `json:",inline"`
	Columns []FullCategory `json:"columns"`
}

The host's view of a board includes the details, including correct response.

type FullCategory

type FullCategory struct {
	Title      string          `json:"title"`
	Comments   string          `json:"comments,omitempty"`
	Challenges []FullChallenge `json:"challenges"`
}

func (FullCategory) IsComplete

func (category FullCategory) IsComplete() bool

type FullChallenge

type FullChallenge struct {
	Challenge `json:",inline"`
	Correct   string `json:"correct"` // excluding "what is..." preface
}

Host view of the challenge, includes the correct response.

type FullEpisode

type FullEpisode struct {
	EpisodeMetadata `json:",inline"`
	Comments        string  `json:"comments,omitempty"`
	Media           []Media `json:"media,omitempty"`

	// Due to absence of archival evidence, not every episode has both single & double rounds.
	Single     *FullBoard     `json:"single,omitempty"`
	Double     *FullBoard     `json:"double,omitempty"`
	Final      *FullChallenge `json:"final,omitempty"`
	TieBreaker *FullChallenge `json:"tiebreaker,omitempty"`
}

All details of the episode, including correct answers & the contestants' bios.

type Media

type Media struct {
	MimeType `json:"mime"`
	MediaURL string `json:"url"`
}

type MimeType

type MimeType string

This enumeration over available media types is modeled after its equivalent MIME type such as image/jpeg, image/png, audio/mpeg, etc. The default (its zero value) is an empty string which implicitly represents an unknown media.

const (
	MediaImageJPG MimeType = "image/jpeg"
	MediaImagePNG MimeType = "image/png"
	MediaImageSVG MimeType = "image/svg+xml"
	MediaAudioMP3 MimeType = "audio/mpeg"
	MediaVideoMP4 MimeType = "video/mp4"
	MediaVideoMOV MimeType = "video/quicktime"
)

type PlayerResponse

type PlayerResponse struct {
	ChallengeMetadata `json:",inline"`
	Response          string `json:"response,omitempty"`
}

type PlayerWager

type PlayerWager struct {
	ChallengeMetadata `json:",inline"`
	Comments          string `json:"comments,omitempty"`
}

type Position

type Position struct {
	Column uint `json:"column" cue:"<6"`
	Index  uint `json:"index" cue:"<5"`
}

A board position, located by the column and (descending) index in the column.

type SeasonID

type SeasonID string

Unique (sometimes numeric) identifier for seasons in the archive.

func (SeasonID) JSON

func (season SeasonID) JSON() string

func (SeasonID) Prefix

func (id SeasonID) Prefix() string

func (SeasonID) RegularSeason

func (id SeasonID) RegularSeason() int

Returns a non-zero value if this season is part of regular play, zero otherwise (e.g. championship series, themed series).

type SeasonMetadata

type SeasonMetadata struct {
	SeasonID `json:"id"`
	Season   string        `json:"season,omitempty"` // deprecated
	Name     string        `json:"name,omitempty"`   // deprecated
	Title    string        `json:"title"`
	Aired    ShowDateRange `json:"aired"`

	Count           int `json:"count,omitempty"` // deprecated
	EpisodesCount   int `json:"episode_count"`
	ChallengesCount int `json:"challenge_count"`
	StumpersCount   int `json:"tripstump_count"`
}

type Selection

type Selection struct {
	ContestantIndex   uint `json:"player"` // \in { 0, 1, 2 }
	Position          `json:",inline"`
	ChallengeMetadata `json:",inline"`
}

A contestant's selection (including possibly the wager value).

type ShowDate

type ShowDate struct {
	Year  int `json:"year"`
	Month int `json:"month,omitempty"`
	Day   int `json:"day,omitempty"`
}

func (ShowDate) Equal

func (date ShowDate) Equal(other ShowDate) bool

func (ShowDate) IsZero

func (date ShowDate) IsZero() bool

func (ShowDate) MarshalText

func (date ShowDate) MarshalText() ([]byte, error)

func (ShowDate) String

func (date ShowDate) String() string

func (ShowDate) ToTime

func (date ShowDate) ToTime() time.Time

func (*ShowDate) UnmarshalText

func (date *ShowDate) UnmarshalText(text []byte) error

type ShowDateRange

type ShowDateRange struct {
	From  ShowDate `json:"from"`
	Until ShowDate `json:"until,omitempty"`
}

type ShowNumber

type ShowNumber struct {
	Season SeasonID // empty string indicates regular-season play.
	Number uint     // cue:">0"
}

Unique numeric identifier for episodes in the archive. May be different than the sequential show number used in display.

func MustParseShowNumber

func MustParseShowNumber(numeric string) ShowNumber

Parses the numeric value from a string. Fatal error if the value cannot be converted into a number.

func (ShowNumber) JSON

func (show ShowNumber) JSON() string

Show numbers are unique within regular seasons but a new sequence is created for non-regular seasons also. Thus the JSON name uses both season and show number, even though this leads to some number-hyphen-number naming.

func (*ShowNumber) UnmarshalJSON

func (show *ShowNumber) UnmarshalJSON(json_bytes []byte) error

Jump to

Keyboard shortcuts

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