Overview
The Question Service provides a clean abstraction layer over the trivia API client, implementing the service pattern for question and category management.
Package: internal/core/question/service.go
QuestionServiceApi Interface
Defines the contract for question service implementations.
Source: internal/core/question/interfaces.go
type QuestionServiceApi interface {
GetQuestions(amount int, category int) ([]entities.Question, error)
GetCategories() ([]Category, error)
}
Interface Methods
Retrieves trivia questions based on amount and category
Retrieves all available trivia categories
QuestionService Implementation
Structure
type QuestionService struct {
questionClient QuestionClientApi
}
The service wraps a QuestionClientApi implementation (typically the TriviaClient) to provide question retrieval functionality.
Constructor
func NewQuestionService(client QuestionClientApi) *QuestionService
client
QuestionClientApi
required
A client implementing the QuestionClientApi interface (e.g., TriviaClient)
Returns: Initialized QuestionService instance
Example:
import (
"github.com/Lafetz/showdown-trivia-game/internal/core/question"
"github.com/Lafetz/showdown-trivia-game/internal/trivia_api"
)
triviaClient := triviaapi.NewTriviaClient()
questionService := question.NewQuestionService(triviaClient)
Methods
GetQuestions
Retrieves trivia questions by delegating to the underlying client.
func (q *QuestionService) GetQuestions(amount int, category int) ([]entities.Question, error)
Number of questions to retrieve
Category ID for filtering questions
Returns:
[]entities.Question: Array of Question entities
error: Error if retrieval fails
Example:
// Get 5 questions from category 21 (Sports)
questions, err := questionService.GetQuestions(5, 21)
if err != nil {
return err
}
for _, q := range questions {
fmt.Println(q.Question)
for i, opt := range q.Options {
fmt.Printf("%d. %s\n", i+1, opt)
}
}
Source: internal/core/question/service.go:9
GetCategories
Retrieves all available trivia categories.
func (q *QuestionService) GetCategories() ([]Category, error)
Returns:
[]Category: Array of available categories
error: Error if retrieval fails
Example:
categories, err := questionService.GetCategories()
if err != nil {
return err
}
for _, cat := range categories {
fmt.Printf("[%d] %s\n", cat.Id, cat.Name)
}
Source: internal/core/question/service.go:12
Data Structures
Question Entity
Represents a trivia question with multiple-choice options.
Source: internal/core/entities/question.go
type Question struct {
Question string
Options []string
CorrectAnswer string
}
The question text to display to the user
Array of answer options (includes correct and incorrect answers, shuffled)
The correct answer (one of the options in the Options array)
Constructor:
func NewQuestion(question string, options []string, correctAnswer string) Question
Usage Example:
question := entities.NewQuestion(
"What is the capital of France?",
[]string{"London", "Berlin", "Paris", "Madrid"},
"Paris",
)
Category
Represents a trivia category.
Source: internal/core/question/domain.go
type Category struct {
Id int
Name string
}
Unique identifier for the category
Human-readable category name
Example Categories:
{Id: 9, Name: "General Knowledge"}
{Id: 21, Name: "Sports"}
{Id: 23, Name: "History"}
QuestionClientApi Interface
Defines the contract for question client implementations.
Source: internal/core/question/interfaces.go
type QuestionClientApi interface {
GetQuestions(amount int, category int) ([]entities.Question, error)
GetCategories() ([]Category, error)
}
This interface is implemented by:
triviaapi.triviaClient - Open Trivia Database client
Service Pattern Benefits
- Abstraction: Separates business logic from API implementation details
- Testability: Easy to mock the QuestionClientApi for unit testing
- Flexibility: Can swap different question sources without changing service consumers
- Single Responsibility: Service focuses on orchestration, client handles API communication
Usage in Application
Typical initialization flow:
func InitializeQuestionService() question.QuestionServiceApi {
// Create API client
triviaClient := triviaapi.NewTriviaClient()
// Create service with client
questionService := question.NewQuestionService(triviaClient)
return questionService
}
Using the service in a game:
func StartGame(service question.QuestionServiceApi) error {
// Fetch questions for the game
questions, err := service.GetQuestions(10, 9)
if err != nil {
return fmt.Errorf("failed to load questions: %w", err)
}
// Use questions in game logic
for _, q := range questions {
// Display question and handle user input
answerCorrectly := AskQuestion(q)
// ... game logic
}
return nil
}