Class: GitGameShow::Renderer

Inherits:
Object
  • Object
show all
Defined in:
lib/git_game_show/ui/renderer.rb

Overview

Main UI renderer for terminal display

Instance Method Summary collapse

Constructor Details

#initializeRenderer

Returns a new instance of Renderer.



4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# File 'lib/git_game_show/ui/renderer.rb', line 4

def initialize
  @message_log = []
  @cursor = TTY::Cursor

  # Get terminal dimensions
  @terminal_width = `tput cols`.to_i rescue 80
  @terminal_height = `tput lines`.to_i rescue 24

  # Calculate layout
  @main_width = (@terminal_width * 0.7).to_i
  @sidebar_width = @terminal_width - @main_width - 3 # 3 for border

  # The fixed line for command input (near bottom of screen)
  @command_line = @terminal_height - 3
end

Instance Method Details

#cleanupObject



29
30
31
32
# File 'lib/git_game_show/ui/renderer.rb', line 29

def cleanup
  print @cursor.show  # Make sure cursor is visible
  print @cursor.clear_screen
end

#draw_command_promptObject



132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
# File 'lib/git_game_show/ui/renderer.rb', line 132

def draw_command_prompt
  # Clear command line and two lines below to prevent commit info bleeding
  print @cursor.move_to(0, @command_line)
  print " " * @terminal_width
  print @cursor.move_to(0, @command_line + 1)
  print " " * @terminal_width
  print @cursor.move_to(0, @command_line + 2)
  print " " * @terminal_width

  # Draw command prompt
  print @cursor.move_to(0, @command_line)
  print "Command> ".colorize(:green)

  # Position cursor after prompt
  print @cursor.move_to(9, @command_line)
  print @cursor.show
end

#draw_game_over(winner, scores) ⇒ Object



150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
# File 'lib/git_game_show/ui/renderer.rb', line 150

def draw_game_over(winner, scores)
  # Safety check for winner
  if !winner || !winner[0] || !winner[1]
    log_message("Error: Invalid winner data", :red)
    return
  end

  # Create a safe copy of scores to work with
  safe_scores = {}
  begin
    if scores && !scores.empty?
      scores.each do |player, score|
        next unless player && player.to_s != ""
        safe_scores[player.to_s] = score.to_i
      end
    end
  rescue => e
    log_message("Error copying scores: #{e.message}", :red)
  end
  
  # Use log messages for display
  divider = "=" * (@main_width - 5)
  log_message(divider, :yellow)
  log_message("🏆 GAME OVER - FINAL SCORES 🏆", :yellow)
  
  # Announce winner
  winner_name = winner[0].to_s
  winner_name = winner_name.length > 20 ? "#{winner_name[0...17]}..." : winner_name
  winner_score = winner[1].to_i
  log_message("Winner: #{winner_name} with #{winner_score} points!", :green)
  
  # Show leaderboard
  log_message("Leaderboard:", :cyan)
  
  # Sort scores safely
  sorted_scores = []
  begin
    sorted_scores = safe_scores.sort_by { |_, score| -(score || 0) }.to_a
  rescue => e
    log_message("Error sorting scores for display: #{e.message}", :red)
    sorted_scores = safe_scores.to_a
  end
  
  max_to_show = 10
  entries_to_show = [sorted_scores.size, max_to_show].min
  
  sorted_scores.take(entries_to_show).each_with_index do |score_entry, index|
    # Extra safety check for each entry
    next unless score_entry && score_entry.is_a?(Array) && score_entry.size >= 2
    
    name = score_entry[0]
    score = score_entry[1]
    
    # Safely handle name and score
    player_name = name.to_s
    player_score = score.to_i
    
    # Truncate name if needed
    display_name = player_name.length > 15 ? "#{player_name[0...12]}..." : player_name
    
    # Format based on position
    case index
    when 0
      log_message("🥇 #{display_name}: #{player_score} points", :yellow)
    when 1
      log_message("🥈 #{display_name}: #{player_score} points", :light_blue)
    when 2
      log_message("🥉 #{display_name}: #{player_score} points", :light_magenta)
    else
      log_message("#{(index + 1).to_s}. #{display_name}: #{player_score} points", :white)
    end
  end
  
  # If there are more players than shown, add a note
  if sorted_scores.size > max_to_show
    log_message("... and #{sorted_scores.size - max_to_show} more", :light_black)
  end
  
  log_message(divider, :yellow)
  log_message("Ready for a new game! Type 'start' when players have joined.", :green)
end


73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
# File 'lib/git_game_show/ui/renderer.rb', line 73

def draw_join_link(join_link)
  # Copy the join link to clipboard
  Clipboard.copy(join_link)

  link_box_width = [join_link.length + 6, @main_width - 10].min
  start_x = (@main_width - link_box_width) / 2
  start_y = 8

  print @cursor.move_to(start_x, start_y)
  print "╭" + "─" * (link_box_width - 2) + "╮"

  print @cursor.move_to(start_x, start_y + 1)
  print "│" + " Join Link (Copied to Clipboard) ".center(link_box_width - 2).colorize(:green) + "│"

  print @cursor.move_to(start_x, start_y + 2)
  print "│" + join_link.center(link_box_width - 2).colorize(:yellow) + "│"

  print @cursor.move_to(start_x, start_y + 3)
  print "╰" + "─" * (link_box_width - 2) + "╯"

  # Also log that the link was copied
  log_message("Join link copied to clipboard", :green)
end

#draw_message_areaObject



111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
# File 'lib/git_game_show/ui/renderer.rb', line 111

def draw_message_area
  # Calculate message area dimensions
  message_area_start = 18
  message_area_height = @command_line - message_area_start - 2

  # Clear message area
  (message_area_start..(@command_line-2)).each do |line|
    print @cursor.move_to(1, line)
    print " " * (@main_width - 2)
  end

  # Draw most recent messages
  display_messages = @message_log.last(message_area_height)
  display_messages.each_with_index do |msg, index|
    print @cursor.move_to(1, message_area_start + index)
    # Truncate message to fit within main width to prevent overflow
    truncated_text = msg[:text][0...(@main_width - 3)]
    print truncated_text.colorize(msg[:color])
  end
end

#draw_ui_frameObject



34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
# File 'lib/git_game_show/ui/renderer.rb', line 34

def draw_ui_frame
  # Clear screen
  print @cursor.clear_screen

  # Draw horizontal divider line between main area and command area
  print @cursor.move_to(0, @command_line - 1)
  print "═" * (@terminal_width - @sidebar_width - 3) + "╧" + "═" * (@sidebar_width + 2)

  # Draw vertical divider line between main area and sidebar
  print @cursor.move_to(@main_width, 0)
  print "│"
  print @cursor.move_to(@main_width, 1)
  print "│"
  print @cursor.move_to(@main_width, 2)
  print "╞═"
  (3...@command_line-1).each do |line|
    print @cursor.move_to(@main_width, line)
    print "│"
  end
end

#draw_welcome_bannerObject



55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
# File 'lib/git_game_show/ui/renderer.rb', line 55

def draw_welcome_banner
  # Position cursor at top left
  lines = [
    " ██████╗ ".colorize(:red) + "  ██████╗ ".colorize(:green) + "  █████╗".colorize(:blue),
    "██╔════╝ ".colorize(:red) + " ██╔════╝ ".colorize(:green) + " ██╔═══╝".colorize(:blue),
    "██║  ███╗".colorize(:red) + " ██║  ███╗".colorize(:green) + " ███████╗".colorize(:blue),
    "██║   ██║".colorize(:red) + " ██║   ██║".colorize(:green) + " ╚════██║".colorize(:blue),
    "╚██████╔╝".colorize(:red) + " ╚██████╔╝".colorize(:green) + " ██████╔╝".colorize(:blue),
    " ╚═════╝ ".colorize(:red) + "  ╚═════╝ ".colorize(:green) + " ╚═════╝ ".colorize(:blue),
  ]

  start_y = 1
  lines.each_with_index do |line, i|
    print @cursor.move_to((@main_width - 28) / 2, start_y + i)
    print line
  end
end

#log_message(message, color = :white) ⇒ Object



97
98
99
100
101
102
103
104
105
106
107
108
109
# File 'lib/git_game_show/ui/renderer.rb', line 97

def log_message(message, color = :white)
  # Add message to log
  @message_log << {text: message, color: color}

  # Keep only last few messages
  @message_log = @message_log.last(15) if @message_log.size > 15

  # Redraw message area
  draw_message_area

  # Return cursor to command prompt
  draw_command_prompt
end

#setupObject



20
21
22
23
24
25
26
27
# File 'lib/git_game_show/ui/renderer.rb', line 20

def setup
  # Clear screen and hide cursor
  print @cursor.clear_screen
  print @cursor.hide

  # Draw initial UI
  draw_ui_frame
end