diff --git a/.prettierrc b/.prettierrc index a230de0..0ad8361 100644 --- a/.prettierrc +++ b/.prettierrc @@ -1,4 +1,6 @@ { + "tabWidth": 4, + "useTabs": false, "plugins": [ "prettier-plugin-go-template" ], diff --git a/dist/gameSettingsForm.js b/dist/gameSettingsForm.js new file mode 100644 index 0000000..66b545a --- /dev/null +++ b/dist/gameSettingsForm.js @@ -0,0 +1,42 @@ +/** + * Toggles the visibility of the input field with the given id based on the value of the given checkbox. + * If the checkbox is checked, the input field is hidden; otherwise, it is shown. + * @param {string} fieldId - The html id of the field to toggle. + * @param {HTMLInputElement} checkbox - The checkbox element that toggles the input field. + */ +function toggleFieldVisibility(fieldId, checkbox) { + const field = document.getElementById(fieldId); + if (checkbox.checked) { + // Clear the value and hide the field when checkbox is checked + field.value = ""; + adjustMinesInputFieldRange(); + field.style.display = "none"; + } else { + field.style.display = "block"; + } +} + +function adjustMinesInputFieldRange() { + const gridSizeValue = document.getElementById( + "grid-size-input-field", + ).value; + const minesInputField = document.getElementById("mines-input-field"); + + if (gridSizeValue) { + const maxMines = Math.floor(gridSizeValue ** 2 * 0.8); + minesInputField.min = 1; + minesInputField.max = maxMines; + minesInputField.placeholder = `Enter number of mines (max: ${maxMines})`; + } else { + minesInputField.min = 1; + minesInputField.max = 350; + minesInputField.placeholder = "Enter number of mines"; + } +} + +window.addEventListener("load", () => { + const gridSizeInputField = document.getElementById("grid-size-input-field"); + + const maxGridSizeBasedOnScreenSize = window.innerWidth < 768 ? 10 : 22; + gridSizeInputField.max = maxGridSizeBasedOnScreenSize; +}); diff --git a/internal/handlers.go b/internal/handlers.go index dc7307c..7e5d7ae 100644 --- a/internal/handlers.go +++ b/internal/handlers.go @@ -93,6 +93,7 @@ func (h *Handler) StartGame(w http.ResponseWriter, r *http.Request) { ErrorMessage: err.Error(), ShowCloseBtn: true, }) + log.Printf("Error parsing form: %v", err) return } @@ -109,6 +110,7 @@ func (h *Handler) StartGame(w http.ResponseWriter, r *http.Request) { ErrorMessage: formValidationErr.Error(), ShowCloseBtn: true, }) + log.Printf("Form validation error: %v", formValidationErr) return } diff --git a/internal/helpers.go b/internal/helpers.go index 61e5379..8267bf2 100644 --- a/internal/helpers.go +++ b/internal/helpers.go @@ -4,6 +4,7 @@ import ( "bytes" "context" "errors" + "fmt" "html/template" "math/rand" "minesweeper/internal/db" @@ -30,6 +31,13 @@ func GetTotalGamesCount(queries *db.Queries) (int64, error) { return count, nil } +const ( + MinGridSize = 2 + MaxGridSize = 22 + MinMinesRatio = 0.1 + MaxMinesRatio = 0.8 +) + type GameSettings struct { GridSize int MinesAmount int @@ -41,34 +49,50 @@ func ValidateGameSettingsForm(gridSizeStr, minesAmountStr, randomMinesStr, rando gridSizeErr, minesAmountErr error ) + // Check if grid size should be random or user-defined, if so check if it's within accepted bounds if randomGridSizeStr == "on" { - // TODO - load min and max grid size from config - gridSize = rand.Intn(10) + 5 // range(5, 15) + gridSize = rand.Intn(MaxGridSize-MinGridSize+1) + MinGridSize gridSizeErr = nil } else { gridSize, gridSizeErr = strconv.Atoi(gridSizeStr) + if gridSizeErr != nil { + return GameSettings{}, errors.New("invalid grid size: must be a proper grid size number") + } + + if gridSize < MinGridSize || gridSize > MaxGridSize { + return GameSettings{}, errors.New("grid size must be between 2 and 50") + } } + minMines := int(float64(gridSize*gridSize) * MinMinesRatio) + maxMines := int(float64(gridSize*gridSize) * MaxMinesRatio) + + // Check if mines amount should be random or user-defined, if so check if it's within accepted bounds if randomMinesStr == "on" { if gridSize > 0 { - minesAmount = rand.Intn((gridSize*gridSize)/2) + 1 + + minesAmount = rand.Intn((maxMines - minMines + 1)) + minMines minesAmountErr = nil } else { return GameSettings{}, errors.New("grid size must be valid when using random mines") } } else { minesAmount, minesAmountErr = strconv.Atoi(minesAmountStr) + + if minesAmountErr != nil { + return GameSettings{}, errors.New("invalid mines amount: must be a number") + } + + if minesAmount <= 0 || minesAmount > maxMines { + return GameSettings{}, fmt.Errorf("mines amount must be between 1 and %v of the grid size", maxMines) + } } if gridSizeErr != nil || minesAmountErr != nil { return GameSettings{}, errors.New("invalid input values") } - if gridSize <= 0 || minesAmount <= 0 { - return GameSettings{}, errors.New("the grid size and mines amount must be greater than 0") - } - return GameSettings{ GridSize: gridSize, MinesAmount: minesAmount, diff --git a/templates/game/game_grid.html b/templates/game/game_grid.html index 836baf0..aa65ad1 100644 --- a/templates/game/game_grid.html +++ b/templates/game/game_grid.html @@ -1,6 +1,7 @@ {{ define "game_grid" }}