-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Abstract out Mine Density Validation for Custom Games
Reek prompted me to take this action, with its warning about Board::Settings having too many methods. This is definitely a good chunk of logic that is related to Board::Settings, but isn't core to it. i.e. SRP was being violated before. This also just helps reduce the class size + cognitive load of opening this file, so I'm in. Also: - Reorganize Board::Settings' methods a bit into a more sensible order (for me, as of now :P) - Add a couple of missing tests to Board::SettingsTest
- Loading branch information
Paul DobbinSchmaltz
committed
Nov 11, 2024
1 parent
413f587
commit eaf3d9c
Showing
3 changed files
with
140 additions
and
76 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
# frozen_string_literal: true | ||
|
||
# Board::Settings::MineDensityValidator validates Mine Density limits on Custom | ||
# {Game}s. | ||
class Board::Settings::MineDensityValidator < ActiveModel::Validator | ||
# :reek:UtilityFunction | ||
def validate(settings) | ||
Validate.(settings) | ||
end | ||
|
||
# Board::Settings::MineDensityValidator::Validate performs the actual | ||
# Validation for {Board::Settings::MineDensityValidator}. | ||
class Validate | ||
include CallMethodBehaviors | ||
|
||
def initialize(settings) | ||
@settings = settings | ||
end | ||
|
||
def call | ||
return if errors.any? | ||
|
||
if too_sparse? | ||
errors.add( | ||
:mines, | ||
"must be >= #{minimum_mines} "\ | ||
"(#{minimum_density_percentage} of total area)") | ||
end | ||
|
||
if too_dense? | ||
errors.add( | ||
:mines, | ||
"must be <= #{maximum_mines} (#{maximum_density} of total area)") | ||
end | ||
end | ||
|
||
private | ||
|
||
attr_reader :settings | ||
|
||
def errors = settings.errors | ||
|
||
def area = settings.width * settings.height | ||
def density = settings.mines / area.to_f | ||
|
||
def too_sparse? = density < minimum_density | ||
def minimum_mines = (area * minimum_density).ceil | ||
def minimum_density = Board::Settings::RANGES[:mine_density].begin | ||
def minimum_density_percentage = to_percentage(minimum_density * 100.0) | ||
|
||
def too_dense? = density > maximum_density | ||
def maximum_mines = (area * maximum_density).floor | ||
def maximum_density = Board::Settings::RANGES[:mine_density].end | ||
|
||
def to_percentage(number, precision: 0, **) | ||
ActiveSupport::NumberHelper::NumberToPercentageConverter.convert( | ||
number, precision:, **) | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters