Documentation
¶
Index ¶
- Variables
- func ValidateCtxEval(str string) error
- type Act
- type Acts
- type BoolComparable
- type ClientID
- type Comparable
- type ConsoleMessage
- type ConsoleMessageType
- type Controller
- type ControllerEvent
- type CtrlAddPlayerEvent
- type CtrlMakeTeamsEvent
- type EndRegistrationEvent
- type EndSceneEvent
- type EventLoop
- func (loop *EventLoop) AfterHandleConsoleEvent(msg ConsoleMessageIn) error
- func (loop *EventLoop) AfterHandleScreenEvent(event ShowScreenEvent) error
- func (loop *EventLoop) AfterHandleTheatreEvent(msg TheatreMessageIn) error
- func (loop *EventLoop) AfterLessonEnd() error
- func (loop *EventLoop) AfterLessonStart() error
- func (loop *EventLoop) AfterRegistration() error
- func (loop *EventLoop) BeforeHandleConsoleEvent(msg ConsoleMessageIn) error
- func (loop *EventLoop) BeforeHandleScreenEvent(event ShowScreenEvent) error
- func (loop *EventLoop) BeforeHandleTheatreEvent(msg TheatreMessageIn) error
- func (loop *EventLoop) BeforeLessonEnd() error
- func (loop *EventLoop) BeforeLessonStart() error
- func (loop *EventLoop) BeforeRegistration() error
- func (loop *EventLoop) DoRegistration() error
- func (loop *EventLoop) HandleConsoleEvent(msg ConsoleMessageIn) error
- func (loop *EventLoop) HandleEvents() error
- func (loop *EventLoop) HandleScreenEvent(event ShowScreenEvent) error
- func (loop *EventLoop) HandleTheatreEvent(msg TheatreMessageIn) error
- func (loop *EventLoop) LessonEnd() error
- func (loop *EventLoop) LessonStart() error
- func (loop *EventLoop) Run() error
- type EventLoopEvent
- type EventLoopTransformable
- type FloatComparable
- type InputResponse
- type JumpToSceneRequest
- type Layout
- type LayoutFlag
- type LayoutFlagsStruct
- type Lesson
- type Model
- type Op
- type Plan
- type Planner
- type Player
- type PlayerRanking
- type PlayerRankings
- type PlayerResponseEvent
- type PlayerScores
- type PreloadScreen
- type Question
- type QuestionContentType
- type QuestionDraw
- type QuestionFilterLiteral
- type QuestionFilterQuery
- type QuestionIDList
- type QuestionLogic
- type QuestionRules
- type QuestionSet
- type Register
- type RegisterEvent
- type RenderedView
- type RepeatCondition
- type RepeatUntilLogic
- type RequestForInput
- type Resolvable
- type ResolvedQuestion
- type ResolvedQuestionFilter
- type Response
- type Round
- type RoundIdx
- type RoundStats
- type Scene
- type Scenes
- type ScoreCard
- type ScoreName
- type Scores
- type ScoringLogic
- type ScoringRules
- type StringComparable
- type Team
- type TeamLogic
- type TeamRanking
- type TeamRankings
- type TeamScores
- type TeamStructure
- type TeamStructures
- type TheatreMessage
- type TheatreMessageType
- type View
- type WebsocketMessage
Constants ¶
This section is empty.
Variables ¶
var LayoutFlags = LayoutFlagsStruct{FillPage: true, VariationTop: true, VariationMiddle: true, VariationBottom: true, VariationLeft: true, VariationRight: true, VariationImageStretch: true, VariationImageCover: true, VariationImageContain: true, VariationImageRepeat: true}
var Layouts = map[Layout]bool{LayoutTitle: true, LayoutSectionTitle: true, LayoutTitleContent: true, LayoutHeroTop: true, LayoutTwoColumnContent: true, LayoutThreeColumnContent: true, LayoutQuadrants: true, LayoutContentAndImage: true}
var Ops = map[Op]bool{OpEquals: true, OpNotEquals: true, OpLessThan: true, OpLessThanEquals: true, OpGreaterThan: true, OpGreaterThanEquals: true, OpContains: true, OpStartsWith: true}
var QuestionContentTypes = [...]QuestionContentType{ContentTypeText, ContentTypeCanvas, ContentTypeImage, ContentTypeVideo, ContentTypeNumber, ContentTypeEmoji, ContentTypeBoolean, ContentTypeMathjax, ContentTypeAudio, ContentTypeChart}
var QuestionLogics = [...]QuestionLogic{SingleInput, SingleInputOpen, MultipleInput, MultipleInputOpen, SingleMultipleChoice, SingleMultipleChoiceOpen, MultiMultipleChoice, MultiMultipleChoiceOpen, MultiBestMultipleChoice, ApproximateSingleInput, ApproximateMultipleInput, VoteFPTP, VoteSTV, VotePR, VoteAV}
var StringOps = map[Op]bool{OpContains: true, OpStartsWith: true}
Functions ¶
func ValidateCtxEval ¶
Types ¶
type Act ¶
type Act struct { Scenes Scenes `json:"scenes"` //This should get gorm embedded as json RepeatUntil *RepeatUntilLogic `json:"repeatLogic,omitempty"` //This should get gorm embedded as json }
type BoolComparable ¶
type BoolComparable struct {
Impl bool
}
func (BoolComparable) EqualTo ¶
func (lhs BoolComparable) EqualTo(rhs Comparable) bool
func (BoolComparable) LessThan ¶
func (lhs BoolComparable) LessThan(rhs Comparable) bool
type Comparable ¶
type Comparable interface { EqualTo(Comparable) bool LessThan(Comparable) bool }
func MakeComparable ¶
func MakeComparable(str string) Comparable
type ConsoleMessage ¶
type ConsoleMessage struct { WebsocketMessage Type ConsoleMessageType `json:"type"` ClientOutChannel *chan<- ConsoleMessage //Optional - the output chanel associated with this console message for this client }
func (ConsoleMessage) MakeEventLoopEvent ¶
func (msg ConsoleMessage) MakeEventLoopEvent() (EventLoopEvent, error)
type ConsoleMessageType ¶
type ConsoleMessageType string
const ( ConsoleSkipMessage ConsoleMessageType = "skip_round" ConsoleRegisterMessage ConsoleMessageType = "register" ConsoleRequestInputMessage ConsoleMessageType = "request_input" ConsoleShowLoadingMessage ConsoleMessageType = "show_loading" ConsoleShowIdle ConsoleMessageType = "show_idle" ConsoleEndGameMessage ConsoleMessageType = "end_game" )
type Controller ¶
type Controller struct { Planner Planner Model Model //Channels... // Channels for communicating with the event loop EventChannelIn <-chan ControllerEvent EventLoopOut chan<- EventLoopEvent }
func (Controller) Run ¶
func (c Controller) Run() error
Note: we assume that LoadPlan has already happened
type ControllerEvent ¶
type ControllerEvent interface {
Handle(*Controller) error
}
type CtrlAddPlayerEvent ¶
func (CtrlAddPlayerEvent) Handle ¶
func (event CtrlAddPlayerEvent) Handle(ctrl *Controller) error
type CtrlMakeTeamsEvent ¶
type CtrlMakeTeamsEvent struct{}
func (CtrlMakeTeamsEvent) Handle ¶
func (event CtrlMakeTeamsEvent) Handle(ctrl *Controller) error
type EndRegistrationEvent ¶
type EndRegistrationEvent struct { }
type EndSceneEvent ¶
type EndSceneEvent struct {
NextRound RoundIdx
}
type EventLoop ¶
type EventLoop struct { CurrentRound RoundIdx //Current round index as we understand it. A 0, 0, 0 round = registration InactivityTimeout time.Duration LeaderPlayerToken ClientID RegistrationTimeout time.Duration // Channels for sending and receiving messages to/from theatre websockets. // Go routines handling websockets must convert their respective events to EventLoopEvents TheatreChannelIn <-chan EventLoopEvent TheatreChannelOuts []chan<- EventLoopEvent // Channels for sending and receiving messages to/from console websockets // Go routines handling websockets must convert their respective events to EventLoopEvents ConsoleChannelIn <-chan EventLoopEvent ConsoleChannelOuts map[ClientID]chan<- EventLoopEvent // Channels for telling the controller about state changes ControllerChannelOut chan<- ControllerEvent EventLoopChannelIn <-chan EventLoopEvent }
TODO lesson needs to construct, and make the channels.
func (*EventLoop) AfterHandleConsoleEvent ¶
func (*EventLoop) AfterHandleScreenEvent ¶
func (*EventLoop) AfterHandleTheatreEvent ¶
func (*EventLoop) AfterLessonEnd ¶
func (*EventLoop) AfterLessonStart ¶
func (*EventLoop) AfterRegistration ¶
func (*EventLoop) BeforeHandleConsoleEvent ¶
func (*EventLoop) BeforeHandleScreenEvent ¶
func (*EventLoop) BeforeHandleTheatreEvent ¶
func (*EventLoop) BeforeLessonEnd ¶
func (*EventLoop) BeforeLessonStart ¶
func (*EventLoop) BeforeRegistration ¶
func (*EventLoop) DoRegistration ¶
func (*EventLoop) HandleConsoleEvent ¶
func (*EventLoop) HandleEvents ¶
func (*EventLoop) HandleScreenEvent ¶
TODO this probably requires returning a new round (or something similar) so we can trigger the "new" round type stuff TODO - for now let's keep it simple...
func (*EventLoop) HandleTheatreEvent ¶
func (*EventLoop) LessonStart ¶
type EventLoopEvent ¶
type EventLoopTransformable ¶
type EventLoopTransformable interface {
MakeEventLoopEvent() EventLoopEvent
}
type FloatComparable ¶
type FloatComparable struct {
Impl float64
}
func (FloatComparable) EqualTo ¶
func (lhs FloatComparable) EqualTo(rhs Comparable) bool
func (FloatComparable) LessThan ¶
func (lhs FloatComparable) LessThan(rhs Comparable) bool
type InputResponse ¶
type InputResponse struct {
PlayerToken ClientID
}
type JumpToSceneRequest ¶
type JumpToSceneRequest struct {
TargetRound RoundIdx
}
type Layout ¶
type Layout string
const ( LayoutTitle Layout = "title" LayoutSectionTitle Layout = "section title" LayoutTitleContent Layout = "content with title (optional)" LayoutHeroTop Layout = "hero" LayoutTwoColumnContent Layout = "two column content" LayoutThreeColumnContent Layout = "three column content" LayoutQuadrants Layout = "four quadrants content" LayoutContentAndImage = "content with image" )
type LayoutFlag ¶
type LayoutFlag string
const ( FillPage LayoutFlag = "fill page" VariationTop LayoutFlag = "top variation" VariationMiddle LayoutFlag = "middle variation" VariationBottom LayoutFlag = "bottom variation" VariationLeft LayoutFlag = "left variation" VariationRight LayoutFlag = "right variation" VariationImageStretch LayoutFlag = "image stretch" VariationImageCover LayoutFlag = "image cover" VariationImageContain LayoutFlag = "image contain" VariationImageRepeat LayoutFlag = "image repeat" )
type LayoutFlagsStruct ¶
type LayoutFlagsStruct map[LayoutFlag]bool
type Lesson ¶
type Lesson struct { EventLoop EventLoop Model Model Register Register Controller Controller }
type Model ¶
type Model struct { Round Round AllRounds map[RoundIdx]Round Players []Player Teams []Team Scores Scores }
func NewLessonModel ¶
func NewLessonModel() *Model
type Plan ¶
type Plan struct { account.UserObject Name string Description string TeamStructures TeamStructures //This is embedded Acts []Act // This is also embedded. }
type Planner ¶
type Planner struct { PlanID uuid.UUID Plan *Plan //A channel for making some of the fetch from the db async QuestionRetrievalChannel chan<- QuestionDraw // contains filtered or unexported fields }
func (*Planner) FetchQuestions ¶
func (planner *Planner) FetchQuestions(rqf ResolvedQuestionFilter) error
TODO change this - should be for a question filter - a resolved one at that probably TODO need to write a simple routine for running a question filter
func (*Planner) PlanIsLoaded ¶
type Player ¶
type Player struct { Name string Avatar []byte Token ClientID //Generated unique to securely disambiguate players //TODO - align with JWT //TODO (probably in the handler itself) ScoreCard ScoreCard AllScoreCards map[RoundIdx]ScoreCard Responses map[RoundIdx]Response //Links the players response to the question for them generated at that round }
A stripped-down version of user that can be baked into templates - not even an email address!
type PlayerRanking ¶
type PlayerRankings ¶
type PlayerRankings []PlayerRanking
type PlayerResponseEvent ¶
type PlayerScores ¶
type PlayerScores map[ScoreName]PlayerRankings
type PreloadScreen ¶
type PreloadScreen struct { Round RoundIdx View RenderedView }
type Question ¶
type Question struct { account.UserObject Content string `json:"content"` Header string `json:"header,omitempty"` Image uuid.UUID `json:"image,omitempty"` ByLine string `json:"byline,omitempty"` Tags pq.StringArray `json:"tags" gorm:"type:varchar(64)[]"` Rules QuestionRules `json:"rules"` }
type QuestionContentType ¶
type QuestionContentType string
const ( ContentTypeText QuestionContentType = "text" ContentTypeCanvas QuestionContentType = "canvas" ContentTypeImage QuestionContentType = "image" ContentTypeVideo QuestionContentType = "gif" ContentTypeNumber QuestionContentType = "number" ContentTypeEmoji QuestionContentType = "emoji" ContentTypeBoolean QuestionContentType = "boolean" ContentTypeMathjax QuestionContentType = "mathjax" ContentTypeAudio QuestionContentType = "audio" ContentTypeChart QuestionContentType = "chart" )
type QuestionDraw ¶
type QuestionFilterLiteral ¶
func (QuestionFilterLiteral) ToString ¶
func (qfl QuestionFilterLiteral) ToString() string
type QuestionFilterQuery ¶
type QuestionFilterQuery struct { QuestionBanks []string CNF [][]QuestionFilterLiteral }
type QuestionIDList ¶
type QuestionLogic ¶
type QuestionLogic string
const ( SingleInput QuestionLogic = "Single Input" SingleInputOpen QuestionLogic = "Single Input No Right Answer" MultipleInput QuestionLogic = "Multiple Input" MultipleInputOpen QuestionLogic = "Multiple Input No Right Answer" SingleMultipleChoice QuestionLogic = "Single Answer Multiple Choice" SingleMultipleChoiceOpen QuestionLogic = "Single Answer Multiple Choice No Right Answer" MultiMultipleChoice QuestionLogic = "Multiple Answer Multiple Choice" MultiMultipleChoiceOpen QuestionLogic = "Multiple Answer Multiple Choice No Right Answer" MultiBestMultipleChoice QuestionLogic = "Multiple Answer Multiple Choice With Best Answer" ApproximateSingleInput QuestionLogic = "Approximate Single Input" ApproximateMultipleInput QuestionLogic = "Approximate Multiple Inputs" VoteFPTP QuestionLogic = "Vote (First Past The Post)" VoteSTV QuestionLogic = "Vote (Single Transferable Vote)" VotePR QuestionLogic = "Vote (Proportional Scoring)" VoteAV QuestionLogic = "Vote (Alternative Vote)" )
type QuestionRules ¶
type QuestionRules struct { Logic QuestionLogic `json:"logic,omitempty"` ContentType QuestionContentType `json:"contentType,omitempty"` Data datatypes.JSON `json:"data,omitempty"` //Extra data - e.g. best answer plus multiple choices ScoringRules ScoringRules `json:"scoringRules,omitempty"` }
func (*QuestionRules) Scan ¶
func (qr *QuestionRules) Scan(src interface{}) error
type QuestionSet ¶
type QuestionSet struct { QuestionIds []uuid.UUID `json:"questionIds,omitempty"` //Either-or Query QuestionFilterQuery `json:"query,omitempty"` //Either-or }
type RegisterEvent ¶
type RegisterEvent struct { PlayerToken ClientID OutChannel chan<- EventLoopEvent }
type RenderedView ¶
type RenderedView struct {
View
}
type RepeatCondition ¶
type RepeatUntilLogic ¶
type RepeatUntilLogic struct { Fixed uint16 `json:"fixed,omitempty"` //65k repeats is enough :) CNF [][]RepeatCondition `json:"cnf,omitempty"` //Takes precedence if it exists. CNF. }
func (RepeatUntilLogic) Eval ¶
func (rul RepeatUntilLogic) Eval(ctx *Model) (bool, error)
Eval returns true if we should break out and continue (i.e. no longer repeat) - the repeat condition is satisfied
func (*RepeatUntilLogic) Scan ¶
func (rul *RepeatUntilLogic) Scan(src interface{}) error
type RequestForInput ¶
type RequestForInput struct {
InputRequest map[ClientID]ConsoleMessage //TODO ideally this is more processed than that before it hits the controller...
}
type Resolvable ¶
type ResolvedQuestion ¶
type ResolvedQuestion struct {
Question
}
type ResolvedQuestionFilter ¶
type ResolvedQuestionFilter struct {
QuestionSet
}
func (ResolvedQuestionFilter) ToWhereClause ¶
type Response ¶
type Response struct { Question *Question //TODO! this is gonna need to be pretty generic - make this work some'ow ;) Would be Data interface{} }
type Round ¶
type Round struct { RoundIdx Stats RoundStats PreviousRound *Round LinkedQuestions QuestionDraw }
func FirstRound ¶
func FirstRound() *Round
func (*Round) LinkedQuestion ¶
Get the linked question if there is one, or a random linked question if there are many
func (*Round) NextAct ¶
func (round *Round) NextAct(nextLinkedQuestions QuestionDraw) *Round
func (*Round) NextScene ¶
func (round *Round) NextScene(nextLinkedQuestions QuestionDraw) *Round
func (*Round) RepeatAct ¶
func (round *Round) RepeatAct(nextLinkedQuestions QuestionDraw) *Round
type RoundStats ¶
type RoundStats struct { QuestionNumber uint // total number of scenes that were also questions StartTime time.Time Time time.Time // the actual time }
func NewRoundStats ¶
func NewRoundStats() RoundStats
func (*RoundStats) PlayTime ¶
func (rs *RoundStats) PlayTime() time.Duration
func (RoundStats) RefreshRoundStats ¶
func (rs RoundStats) RefreshRoundStats() RoundStats
type Scene ¶
type Scene struct { Template View `json:"template"` OptQuestionFilter *QuestionSet `json:"questionFilter,omitempty"` }
type Scores ¶
type Scores struct { PlayerScores PlayerScores TeamScores TeamScores }
type ScoringLogic ¶
type ScoringLogic string
const ( Simple ScoringLogic = "simple" AddScores ScoringLogic = "add-scores" //Adds two scores together InverseFrequency ScoringLogic = "inverse-frequency" SimpleByTeam ScoringLogic = "simple-by-team" AddScoresByTeam ScoringLogic = "add-by-team" )
type ScoringRules ¶
type ScoringRules map[ScoreName]ScoringLogic
type StringComparable ¶
type StringComparable struct {
Impl string
}
func (StringComparable) EqualTo ¶
func (lhs StringComparable) EqualTo(rhs Comparable) bool
func (StringComparable) LessThan ¶
func (lhs StringComparable) LessThan(rhs Comparable) bool
type TeamRanking ¶
type TeamRankings ¶
type TeamRankings []TeamRanking
type TeamScores ¶
type TeamScores map[ScoreName]TeamRankings
type TeamStructure ¶
type TeamStructures ¶
func (*TeamStructures) Scan ¶
func (tsrcts *TeamStructures) Scan(src interface{}) error
type TheatreMessage ¶
type TheatreMessage struct { WebsocketMessage Type TheatreMessageType `json:"type"` }
func (TheatreMessage) MakeEventLoopEvent ¶
func (msg TheatreMessage) MakeEventLoopEvent() (EventLoopEvent, error)
type TheatreMessageType ¶
type TheatreMessageType string
const ( TheatreSkipMessage TheatreMessageType = "skip_round" TheatreUpdateScreenMessage TheatreMessageType = "update_screen" //Render a screen TheatreGoToRoundMessage TheatreMessageType = "go_to_round" TheatreEndGameMessage TheatreMessageType = "end_game" )
type View ¶
type View struct { Layout Layout `json:"layout"` LayoutFlags LayoutFlagsStruct `json:"layoutFlags,omitempty"` Title string `json:"title"` Byline string `json:"byline,omitempty"` Header string `json:"header,omitempty"` Image uuid.UUID `json:"image,omitempty"` Caption string `json:"caption,omitempty"` Content []string `json:"content,omitempty"` Logo uuid.UUID `json:"logo,omitempty"` Gallery []uuid.UUID `json:"gallery,omitempty"` Classes []string `json:"classes,omitempty"` //This is our theming hook }
type WebsocketMessage ¶
type WebsocketMessage struct { PlayerToken ClientID `json:"playerId,omitempty"` Round RoundIdx `json:"round,omitempty"` //Helps idempotency and avoids races Data json.RawMessage `json:"data,omitempty"` }