Skip to content

Commit

Permalink
Extract object inspection from *::Console objects
Browse files Browse the repository at this point in the history
Moving object inspection into *::Console objects was an experiment in
processing optimization. But, I think it was a failed one. It just made
it too hard to see the pretty inspection results, especially when
chaining methods together in e.g. ARel queries.

Also, the Console object accessor / insulation layer was always a bit of
a doubling up on processing optimization. ObjectInspector itself has
scopes for dealing with this sort of thing, wherever necessary. For this
project, however, I can't think of any relevant cases (yet).
  • Loading branch information
Paul DobbinSchmaltz committed Nov 15, 2024
1 parent 45e2775 commit 992138f
Show file tree
Hide file tree
Showing 15 changed files with 155 additions and 157 deletions.
35 changes: 18 additions & 17 deletions app/models/board.rb
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,24 @@ def validate_settings
errors.merge!(settings.errors)
end

concerning :ObjectInspection do
include ObjectInspector::InspectorsHelper

def inspect_identification = identify

def inspect_info(scope:)
scope.join_info([
"#{Emoji.cell} x#{cells_count} (#{dimensions})",
"#{Emoji.revealed_cell} #{revealed_cells_count}",
"#{Emoji.mine} #{mines}",
"#{Emoji.flag} #{flags_count}",
])
end

def cells_count = cells.size
def revealed_cells_count = cells.count(&:revealed?)
end

# Board::Console acts like a {Board} but otherwise handles IRB
# Console-specific methods/logic.
class Console
Expand Down Expand Up @@ -126,22 +144,5 @@ def reset!

self
end

private

def inspect_info(scope:)
scope.join_info([
"#{Emoji.cell} x#{cells_count} (#{dimensions})",
"#{Emoji.revealed_cell} #{revealed_cells_count}",
"#{Emoji.mine} #{mines}",
"#{Emoji.flag} #{flags_count}",
])
end

def cells_count = cells.size

def revealed_cells_count
cells.count(&:revealed?)
end
end
end
12 changes: 6 additions & 6 deletions app/models/board/settings.rb
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,6 @@ class Board::Settings
include ActiveModel::Model
include ActiveModel::Attributes

include ObjectInspector::InspectorsHelper

attribute :type, :string
attribute :name, :string
attribute :width, :integer, default: -> { RANGES.fetch(:width).begin }
Expand Down Expand Up @@ -118,11 +116,13 @@ def to_h = { type:, name:, width:, height:, mines: }.tap(&:compact!)
def as_json = to_h
def to_a = to_h.values

private
concerning :ObjectInspection do
include ObjectInspector::InspectorsHelper

def inspect_identification = identify(:width, :height, :mines)
def inspect_identification = identify(:width, :height, :mines)

def inspect_name
pattern? ? "#{type} (#{name.inspect})" : type
def inspect_name
pattern? ? "#{type} (#{name.inspect})" : type
end
end
end
43 changes: 26 additions & 17 deletions app/models/calc_3bv.rb
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,17 @@ def process_cells

def count = cells.sum(&:count)

concerning :ObjectInspection do
include ObjectInspector::InspectorsHelper

def inspect_identification = identify(:grid)
end

# :reek:InstanceVariableAssumption

# Calc3BV::Cell wraps {Cell} for performing 3BV scoring functions.
class Cell
include WrapMethodBehaviors
include ObjectInspector::InspectorsHelper

delegate_missing_to :to_model

Expand Down Expand Up @@ -94,17 +99,21 @@ def count = @count.to_i

attr_reader :calculator

def inspect_flags(scope:)
scope.join_flags([
(Emoji.mine if mine?),
(visited? ? Emoji.eyes : "🙈"),
])
end

def inspect_name = @count.inspect

def neighbors = calculator.cells_at(neighboring_coordinates)
def neighboring_coordinates = coordinates.neighbors

concerning :ObjectInspection do
include ObjectInspector::InspectorsHelper

def inspect_flags(scope:)
scope.join_flags([
(Emoji.mine if mine?),
(visited? ? Emoji.eyes : "🙈"),
])
end

def inspect_name = @count.inspect
end
end

# Calc3BV::Console acts like a {Calc3BV} but otherwise handles IRB
Expand All @@ -113,8 +122,7 @@ class Console
include ConsoleObjectBehaviors

# @example
# calc = Calc3BV.new(Board.last.grid).cons
# calc.call
# Calc3BV.new(Board.last.grid).cons.call
def call
process_cells
count
Expand All @@ -129,17 +137,18 @@ def process_cells
# Show where the clicks came from.
#
# @example
# calc = Calc3BV.new(Board.last.grid).cons
# calc.call
# calc.render # Compare to `calc.grid.render`
# # Compare output against `calc.grid.render`:
# Calc3BV.new(Board.last.grid).cons.render
def render
cells.map(&:count).in_groups_of(grid.columns_count)
end

def grid = super.console

private
concerning :ObjectInspection do
include ObjectInspector::InspectorsHelper

def inspect_identification = identify(:grid, klass: __class__)
def inspect_identification = identify(:grid, klass: __class__)
end
end
end
30 changes: 17 additions & 13 deletions app/models/cell.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# frozen_string_literal: true

# :reek:TooManyMethods
# :reek:RepeatedConditional

# Cell represents a clickable position on the {Board}. Cells:
# - may secretly contain a mine
Expand Down Expand Up @@ -141,19 +142,10 @@ def neighboring_flags_count
@neighboring_flags_count ||= neighbors.count(&:flagged?)
end

# Cell::Console acts like a {Cell} but otherwise handles IRB Console-specific
# methods/logic.
class Console
include ConsoleObjectBehaviors

def coordinates = super.console
def neighbors = super.map(&:console)
concerning :ObjectInspection do
include ObjectInspector::InspectorsHelper

def render(cells_count: nil)
"#{current_state}#{coordinates.console.render(cells_count:)}"
end

private
def inspect_identification = identify

def inspect_flags(scope:)
scope.join_flags([
Expand All @@ -168,8 +160,20 @@ def inspect_issues
"INCORRECTLY_FLAGGED" if incorrectly_flagged?
end

def inspect_info = coordinates.console
def inspect_info = coordinates
def inspect_name = value.inspect
end

# Cell::Console acts like a {Cell} but otherwise handles IRB Console-specific
# methods/logic.
class Console
include ConsoleObjectBehaviors

def render(cells_count: value)
"#{current_state}#{coordinates.console.render(cells_count:)}"
end

private

def current_state
if revealed?
Expand Down
16 changes: 8 additions & 8 deletions app/models/coordinates.rb
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,14 @@ def to_a
[x, y]
end

def to_s
inspect
end

def inspect
"(#{x}, #{y})"
end

# Coordinates::Console acts like a {Coordinates} but otherwise handles IRB
# Console-specific methods/logic.
class Console
Expand All @@ -59,16 +67,8 @@ def render(cells_count:)
"(#{pad(x, cells_count:)}, #{pad(y, cells_count:)})"
end

def to_s
inspect
end

private

def inspect
"(#{x}, #{y})"
end

def pad(value, cells_count:)
return value if cells_count <= BEGINNER_DIFFICULTY_LEVEL_CELLS_COUNT

Expand Down
45 changes: 26 additions & 19 deletions app/models/game.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# frozen_string_literal: true

# :reek:TooManyConstants
# :reek:TooManyMethods

# Game represents a game of Minesweeper Alliance. It handles creation of new
# Games and keeps track of the {#status} of each Game in the database, win or
Expand Down Expand Up @@ -190,6 +191,31 @@ def set_stats
CalcStats.(self)
end

concerning :ObjectInspection do
include ObjectInspector::InspectorsHelper

def inspect_identification = identify

def inspect_flags(scope:)
scope.join_flags([
type,
status,
])
end

def inspect_info(scope:)
return unless score || bbbv || efficiency

scope.join_info([
"Score: #{score.inspect}",
"3BV: #{bbbv.inspect}",
"Efficiency: #{efficiency.inspect}",
])
end

def inspect_name = display_id
end

# Game::CalcStats determines and updates the given {Game} object with relevant
# statistical values (on {Game} end).
class CalcStats
Expand Down Expand Up @@ -268,25 +294,6 @@ def reset!

private

def inspect_flags(scope:)
scope.join_flags([
type,
status,
])
end

def inspect_info(scope:)
return unless score || bbbv || efficiency

scope.join_info([
"Score: #{score.inspect}",
"3BV: #{bbbv.inspect}",
"Efficiency: #{efficiency.inspect}",
])
end

def inspect_name = display_id

# :reek:TooManyStatements
def do_reset
check_for_current_game
Expand Down
35 changes: 15 additions & 20 deletions app/models/grid.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ def initialize(cells, context: nil)
end

def cells_count = cells.size
def rows_count = count
def columns_count = first.size

# rubocop:disable Layout/LineLength
Expand Down Expand Up @@ -58,23 +59,27 @@ def organizer
context&.transpose? ? TRANSPOSE_ORGANIZER : STANDARD_ORGANIZER
end

concerning :ObjectInspection do
include ObjectInspector::InspectorsHelper

def inspect_identification = self.class.name

def inspect_info
"#{Emoji.cell} x#{cells_count} (#{dimensions})"
end

def dimensions
"#{rows_count}x#{columns_count}"
end
end

# rubocop:enable Layout/LineLength

# Grid::Console acts like a {Grid} but otherwise handles IRB Console-specific
# methods/logic.
class Console
include ConsoleObjectBehaviors

def cells = super.map(&:console)

def to_h
super.transform_values { |row| row.map(&:console) }
end

def to_a
super.map { |row| row.map(&:console) }
end

# @example
# 0 => ◻️ (0, 0) ◻️ (1, 0) ◻️ (2, 0)
# 1 => ◻️ (0, 1) ◻️ (1, 1) ◻️ (2, 1)
Expand All @@ -89,16 +94,6 @@ def render

private

def inspect_identification = __model__.class.name

def inspect_info
"#{Emoji.cell} x#{cells_count} (#{dimensions})"
end

def dimensions
"#{count}x#{to_a.first.size}"
end

# rubocop:disable Rails/Output
def render_row(y:, row:)
print "#{pad(y)}: "
Expand Down
5 changes: 2 additions & 3 deletions app/models/null_coordinates.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,10 @@ def y = nil
def neighbors = []
def to_h = {}
def to_json(*) = "{}"
def to_s = inspect
def render = inspect

def inspect
"(nil, nil)"
end

def to_s = inspect
def render = inspect
end
Loading

0 comments on commit 992138f

Please sign in to comment.