glimmer-dsl-libui 0.4.20 → 0.5.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (117) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +24 -0
  3. data/LICENSE.txt +1 -1
  4. data/README.md +144 -55
  5. data/VERSION +1 -1
  6. data/bin/girb_runner.rb +1 -1
  7. data/examples/area_based_custom_controls.rb +7 -3
  8. data/examples/color_the_circles.rb +1 -1
  9. data/examples/snake/model/game.rb +18 -1
  10. data/examples/snake.rb +6 -2
  11. data/examples/snake2.rb +6 -2
  12. data/examples/tetris/model/block.rb +1 -1
  13. data/examples/tetris/model/game.rb +26 -24
  14. data/examples/tetris/model/past_game.rb +1 -1
  15. data/examples/tetris/model/tetromino.rb +1 -1
  16. data/examples/tetris.rb +51 -20
  17. data/examples/tic_tac_toe/board.rb +1 -1
  18. data/examples/tic_tac_toe/cell.rb +1 -1
  19. data/glimmer-dsl-libui.gemspec +0 -0
  20. data/lib/glimmer/dsl/libui/bind_expression.rb +1 -1
  21. data/lib/glimmer/dsl/libui/control_expression.rb +1 -1
  22. data/lib/glimmer/dsl/libui/data_binding_expression.rb +1 -1
  23. data/lib/glimmer/dsl/libui/dsl.rb +1 -1
  24. data/lib/glimmer/dsl/libui/file_expression.rb +1 -1
  25. data/lib/glimmer/dsl/libui/listener_expression.rb +1 -1
  26. data/lib/glimmer/dsl/libui/observe_expression.rb +1 -1
  27. data/lib/glimmer/dsl/libui/open_file_expression.rb +1 -1
  28. data/lib/glimmer/dsl/libui/operation_expression.rb +1 -1
  29. data/lib/glimmer/dsl/libui/property_expression.rb +1 -1
  30. data/lib/glimmer/dsl/libui/save_file_expression.rb +1 -1
  31. data/lib/glimmer/dsl/libui/shape_expression.rb +1 -1
  32. data/lib/glimmer/dsl/libui/shine_data_binding_expression.rb +1 -1
  33. data/lib/glimmer/dsl/libui/string_expression.rb +1 -1
  34. data/lib/glimmer/dsl/libui/tab_item_expression.rb +1 -1
  35. data/lib/glimmer/fiddle_consumer.rb +1 -1
  36. data/lib/glimmer/libui/attributed_string.rb +1 -1
  37. data/lib/glimmer/libui/control_proxy/area_proxy/scrolling_area_proxy.rb +1 -1
  38. data/lib/glimmer/libui/control_proxy/area_proxy.rb +1 -1
  39. data/lib/glimmer/libui/control_proxy/box/horizontal_box_proxy.rb +1 -1
  40. data/lib/glimmer/libui/control_proxy/box/vertical_box_proxy.rb +1 -1
  41. data/lib/glimmer/libui/control_proxy/box.rb +1 -1
  42. data/lib/glimmer/libui/control_proxy/button_proxy.rb +1 -1
  43. data/lib/glimmer/libui/control_proxy/checkbox_proxy.rb +1 -1
  44. data/lib/glimmer/libui/control_proxy/color_button_proxy.rb +1 -1
  45. data/lib/glimmer/libui/control_proxy/column/background_color_column_proxy.rb +1 -1
  46. data/lib/glimmer/libui/control_proxy/column/button_column_proxy.rb +1 -1
  47. data/lib/glimmer/libui/control_proxy/column/checkbox_column_proxy.rb +1 -1
  48. data/lib/glimmer/libui/control_proxy/column/checkbox_text_color_column_proxy.rb +1 -1
  49. data/lib/glimmer/libui/control_proxy/column/checkbox_text_column_proxy.rb +1 -1
  50. data/lib/glimmer/libui/control_proxy/column/image_column_proxy.rb +1 -1
  51. data/lib/glimmer/libui/control_proxy/column/image_text_color_column_proxy.rb +1 -1
  52. data/lib/glimmer/libui/control_proxy/column/image_text_column_proxy.rb +1 -1
  53. data/lib/glimmer/libui/control_proxy/column/progress_bar_column_proxy.rb +1 -1
  54. data/lib/glimmer/libui/control_proxy/column/text_color_column_proxy.rb +1 -1
  55. data/lib/glimmer/libui/control_proxy/column/text_column_proxy.rb +1 -1
  56. data/lib/glimmer/libui/control_proxy/column.rb +1 -1
  57. data/lib/glimmer/libui/control_proxy/combobox_proxy.rb +1 -1
  58. data/lib/glimmer/libui/control_proxy/date_time_picker_proxy/date_picker_proxy.rb +1 -1
  59. data/lib/glimmer/libui/control_proxy/date_time_picker_proxy/time_picker_proxy.rb +1 -1
  60. data/lib/glimmer/libui/control_proxy/date_time_picker_proxy.rb +1 -1
  61. data/lib/glimmer/libui/control_proxy/dual_column.rb +1 -1
  62. data/lib/glimmer/libui/control_proxy/editable_column.rb +1 -1
  63. data/lib/glimmer/libui/control_proxy/editable_combobox_proxy.rb +1 -1
  64. data/lib/glimmer/libui/control_proxy/enableable_column.rb +1 -1
  65. data/lib/glimmer/libui/control_proxy/entry_proxy/password_entry_proxy.rb +1 -1
  66. data/lib/glimmer/libui/control_proxy/entry_proxy/search_entry_proxy.rb +1 -1
  67. data/lib/glimmer/libui/control_proxy/entry_proxy.rb +1 -1
  68. data/lib/glimmer/libui/control_proxy/font_button_proxy.rb +1 -1
  69. data/lib/glimmer/libui/control_proxy/form_proxy.rb +1 -1
  70. data/lib/glimmer/libui/control_proxy/grid_proxy.rb +1 -1
  71. data/lib/glimmer/libui/control_proxy/group_proxy.rb +1 -1
  72. data/lib/glimmer/libui/control_proxy/image_part_proxy.rb +1 -1
  73. data/lib/glimmer/libui/control_proxy/image_proxy.rb +1 -1
  74. data/lib/glimmer/libui/control_proxy/label_proxy.rb +1 -1
  75. data/lib/glimmer/libui/control_proxy/matrix_proxy.rb +1 -1
  76. data/lib/glimmer/libui/control_proxy/menu_item_proxy/about_menu_item_proxy.rb +1 -1
  77. data/lib/glimmer/libui/control_proxy/menu_item_proxy/check_menu_item_proxy.rb +1 -1
  78. data/lib/glimmer/libui/control_proxy/menu_item_proxy/preferences_menu_item_proxy.rb +1 -1
  79. data/lib/glimmer/libui/control_proxy/menu_item_proxy/quit_menu_item_proxy.rb +1 -1
  80. data/lib/glimmer/libui/control_proxy/menu_item_proxy/radio_menu_item_proxy.rb +1 -1
  81. data/lib/glimmer/libui/control_proxy/menu_item_proxy/separator_menu_item_proxy.rb +1 -1
  82. data/lib/glimmer/libui/control_proxy/menu_item_proxy.rb +1 -1
  83. data/lib/glimmer/libui/control_proxy/menu_proxy.rb +1 -1
  84. data/lib/glimmer/libui/control_proxy/message_box/msg_box_error_proxy.rb +1 -1
  85. data/lib/glimmer/libui/control_proxy/message_box/msg_box_proxy.rb +1 -1
  86. data/lib/glimmer/libui/control_proxy/message_box.rb +1 -1
  87. data/lib/glimmer/libui/control_proxy/multiline_entry_proxy/non_wrapping_multiline_entry_proxy.rb +1 -1
  88. data/lib/glimmer/libui/control_proxy/multiline_entry_proxy.rb +1 -1
  89. data/lib/glimmer/libui/control_proxy/open_type_features_proxy.rb +1 -1
  90. data/lib/glimmer/libui/control_proxy/open_type_tag_proxy.rb +1 -1
  91. data/lib/glimmer/libui/control_proxy/path_proxy.rb +1 -1
  92. data/lib/glimmer/libui/control_proxy/radio_buttons_proxy.rb +1 -1
  93. data/lib/glimmer/libui/control_proxy/slider_proxy.rb +1 -1
  94. data/lib/glimmer/libui/control_proxy/spinbox_proxy.rb +1 -1
  95. data/lib/glimmer/libui/control_proxy/tab_item_proxy.rb +1 -1
  96. data/lib/glimmer/libui/control_proxy/table_proxy.rb +1 -1
  97. data/lib/glimmer/libui/control_proxy/text_proxy.rb +1 -1
  98. data/lib/glimmer/libui/control_proxy/transformable.rb +1 -1
  99. data/lib/glimmer/libui/control_proxy/triple_column.rb +1 -1
  100. data/lib/glimmer/libui/control_proxy/window_proxy.rb +1 -1
  101. data/lib/glimmer/libui/control_proxy.rb +1 -1
  102. data/lib/glimmer/libui/data_bindable.rb +1 -1
  103. data/lib/glimmer/libui/parent.rb +1 -1
  104. data/lib/glimmer/libui/shape/arc.rb +18 -1
  105. data/lib/glimmer/libui/shape/bezier.rb +1 -1
  106. data/lib/glimmer/libui/shape/circle.rb +8 -3
  107. data/lib/glimmer/libui/shape/figure.rb +1 -1
  108. data/lib/glimmer/libui/shape/line.rb +1 -1
  109. data/lib/glimmer/libui/shape/polybezier.rb +1 -1
  110. data/lib/glimmer/libui/shape/polygon.rb +1 -1
  111. data/lib/glimmer/libui/shape/polyline.rb +1 -1
  112. data/lib/glimmer/libui/shape/rectangle.rb +8 -3
  113. data/lib/glimmer/libui/shape/square.rb +10 -3
  114. data/lib/glimmer/libui/shape.rb +41 -1
  115. data/lib/glimmer/libui.rb +1 -1
  116. data/lib/glimmer-dsl-libui.rb +2 -1
  117. metadata +27 -12
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2007-2021 Andy Maleh
1
+ # Copyright (c) 2021-2022 Andy Maleh
2
2
  #
3
3
  # Permission is hereby granted, free of charge, to any person obtaining
4
4
  # a copy of this software and associated documentation files (the
@@ -36,21 +36,27 @@ class Tetris
36
36
  PREVIEW_PLAYFIELD_WIDTH = 4
37
37
  PREVIEW_PLAYFIELD_HEIGHT = 2
38
38
  SCORE_MULTIPLIER = {1 => 40, 2 => 100, 3 => 300, 4 => 1200}
39
+ UP_ARROW_ACTIONS = %i[instant_down rotate_right rotate_left]
40
+ SPEEDS = %i[snail sloth turtle rabbit gorilla bear horse gazelle cheetah falcon]
41
+ SPEED_INITIAL_DELAYS = SPEEDS.each_with_index.inject({}) {|hash, speed_index_pair| hash.merge(speed_index_pair.first => 1.1 - speed_index_pair.last*(0.1)) }
39
42
 
40
43
  attr_reader :playfield_width, :playfield_height
41
- attr_accessor :game_over, :paused, :preview_tetromino, :lines, :score, :level, :high_scores, :beeping, :added_high_score, :show_high_scores, :up_arrow_action
44
+ attr_accessor :game_over, :paused, :preview_tetromino, :lines, :score, :level, :high_scores, :beeping, :added_high_score, :show_high_scores, :up_arrow_action, :show_preview_tetromino, :initial_delay
42
45
  alias game_over? game_over
43
46
  alias paused? paused
44
47
  alias beeping? beeping
45
48
  alias added_high_score? added_high_score
49
+ alias show_preview_tetromino? show_preview_tetromino
46
50
 
47
51
  def initialize(playfield_width = PLAYFIELD_WIDTH, playfield_height = PLAYFIELD_HEIGHT)
52
+ @initial_delay = SPEED_INITIAL_DELAYS[:snail]
48
53
  @playfield_width = playfield_width
49
54
  @playfield_height = playfield_height
50
55
  @high_scores = []
51
56
  @show_high_scores = false
52
57
  @beeping = true
53
58
  @up_arrow_action = :rotate_left
59
+ @show_preview_tetromino = true
54
60
  load_high_scores!
55
61
  end
56
62
 
@@ -200,35 +206,31 @@ class Tetris
200
206
  end
201
207
 
202
208
  def delay
203
- [1.1 - (level.to_i * 0.1), 0.001].max
209
+ [@initial_delay - (level.to_i * 0.1), 0.001].max
204
210
  end
205
211
 
206
212
  def beep
207
213
  @beeper&.call if beeping
208
214
  end
209
-
210
- def instant_down_on_up=(value)
211
- self.up_arrow_action = :instant_down if value
212
- end
213
-
214
- def instant_down_on_up
215
- self.up_arrow_action == :instant_down
216
- end
217
-
218
- def rotate_right_on_up=(value)
219
- self.up_arrow_action = :rotate_right if value
220
- end
221
-
222
- def rotate_right_on_up
223
- self.up_arrow_action == :rotate_right
224
- end
225
-
226
- def rotate_left_on_up=(value)
227
- self.up_arrow_action = :rotate_left if value
215
+
216
+ SPEED_INITIAL_DELAYS.each do |speed, speed_initial_day|
217
+ define_method("speed_#{speed}=") do |is_true|
218
+ self.initial_delay = speed_initial_day if is_true
219
+ end
220
+
221
+ define_method("speed_#{speed}") do
222
+ self.initial_delay == speed_initial_day
223
+ end
228
224
  end
229
225
 
230
- def rotate_left_on_up
231
- self.up_arrow_action == :rotate_left
226
+ UP_ARROW_ACTIONS.each do |up_arrow_action_symbol|
227
+ define_method("#{up_arrow_action_symbol}_on_up=") do |is_true|
228
+ self.up_arrow_action = up_arrow_action_symbol if is_true
229
+ end
230
+
231
+ define_method("#{up_arrow_action_symbol}_on_up") do
232
+ self.up_arrow_action == up_arrow_action_symbol
233
+ end
232
234
  end
233
235
 
234
236
  def reset_tetrominoes
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2007-2021 Andy Maleh
1
+ # Copyright (c) 2021-2022 Andy Maleh
2
2
  #
3
3
  # Permission is hereby granted, free of charge, to any person obtaining
4
4
  # a copy of this software and associated documentation files (the
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2007-2021 Andy Maleh
1
+ # Copyright (c) 2021-2022 Andy Maleh
2
2
  #
3
3
  # Permission is hereby granted, free of charge, to any person obtaining
4
4
  # a copy of this software and associated documentation files (the
data/examples/tetris.rb CHANGED
@@ -5,7 +5,7 @@ require_relative 'tetris/model/game'
5
5
  class Tetris
6
6
  include Glimmer
7
7
 
8
- BLOCK_SIZE = 25
8
+ BLOCK_SIZE = OS.linux? ? 28 : 25
9
9
  BEVEL_CONSTANT = 20
10
10
  COLOR_GRAY = {r: 192, g: 192, b: 192}
11
11
 
@@ -71,18 +71,31 @@ class Tetris
71
71
 
72
72
  Model::Game::PREVIEW_PLAYFIELD_HEIGHT.times do |row|
73
73
  Model::Game::PREVIEW_PLAYFIELD_WIDTH.times do |column|
74
- observe(@game.preview_playfield[row][column], :color) do |new_color|
74
+ preview_updater = proc do
75
75
  Glimmer::LibUI.queue_main do
76
+ new_color = @game.preview_playfield[row][column].color
76
77
  color = Glimmer::LibUI.interpret_color(new_color)
77
78
  block = @preview_playfield_blocks[row][column]
78
- block[:background_square].fill = color
79
- block[:top_bevel_edge].fill = {r: color[:r] + 4*BEVEL_CONSTANT, g: color[:g] + 4*BEVEL_CONSTANT, b: color[:b] + 4*BEVEL_CONSTANT}
80
- block[:right_bevel_edge].fill = {r: color[:r] - BEVEL_CONSTANT, g: color[:g] - BEVEL_CONSTANT, b: color[:b] - BEVEL_CONSTANT}
81
- block[:bottom_bevel_edge].fill = {r: color[:r] - BEVEL_CONSTANT, g: color[:g] - BEVEL_CONSTANT, b: color[:b] - BEVEL_CONSTANT}
82
- block[:left_bevel_edge].fill = {r: color[:r] - BEVEL_CONSTANT, g: color[:g] - BEVEL_CONSTANT, b: color[:b] - BEVEL_CONSTANT}
83
- block[:border_square].stroke = new_color == Model::Block::COLOR_CLEAR ? COLOR_GRAY : color
79
+ if @game.show_preview_tetromino?
80
+ block[:background_square].fill = color
81
+ block[:top_bevel_edge].fill = {r: color[:r] + 4*BEVEL_CONSTANT, g: color[:g] + 4*BEVEL_CONSTANT, b: color[:b] + 4*BEVEL_CONSTANT}
82
+ block[:right_bevel_edge].fill = {r: color[:r] - BEVEL_CONSTANT, g: color[:g] - BEVEL_CONSTANT, b: color[:b] - BEVEL_CONSTANT}
83
+ block[:bottom_bevel_edge].fill = {r: color[:r] - BEVEL_CONSTANT, g: color[:g] - BEVEL_CONSTANT, b: color[:b] - BEVEL_CONSTANT}
84
+ block[:left_bevel_edge].fill = {r: color[:r] - BEVEL_CONSTANT, g: color[:g] - BEVEL_CONSTANT, b: color[:b] - BEVEL_CONSTANT}
85
+ block[:border_square].stroke = new_color == Model::Block::COLOR_CLEAR ? COLOR_GRAY : color
86
+ else
87
+ transparent_color = {r: 255, g: 255, b: 255, a: 0}
88
+ block[:background_square].fill = transparent_color
89
+ block[:top_bevel_edge].fill = transparent_color
90
+ block[:right_bevel_edge].fill = transparent_color
91
+ block[:bottom_bevel_edge].fill = transparent_color
92
+ block[:left_bevel_edge].fill = transparent_color
93
+ block[:border_square].stroke = transparent_color
94
+ end
84
95
  end
85
96
  end
97
+ observe(@game.preview_playfield[row][column], :color, &preview_updater)
98
+ observe(@game, :show_preview_tetromino, &preview_updater)
86
99
  end
87
100
  end
88
101
 
@@ -130,6 +143,12 @@ class Tetris
130
143
  }
131
144
 
132
145
  menu('View') {
146
+ check_menu_item('Show Next Block Preview') {
147
+ checked <=> [@game, :show_preview_tetromino]
148
+ }
149
+
150
+ separator_menu_item
151
+
133
152
  menu_item('Show High Scores') {
134
153
  on_clicked do
135
154
  show_high_scores
@@ -141,18 +160,28 @@ class Tetris
141
160
  @game.clear_high_scores!
142
161
  }
143
162
  }
163
+
164
+ separator_menu_item
165
+ }
166
+
167
+ menu('Speed') {
168
+ Model::Game::SPEEDS.each do |speed|
169
+ radio_menu_item(speed.to_s.capitalize) {
170
+ checked <=> [@game, "speed_#{speed}"]
171
+ }
172
+ end
144
173
  }
145
174
 
146
175
  menu('Options') {
147
- radio_menu_item('Instant Down on Up Arrow') { |r|
176
+ radio_menu_item('Instant Down on Up Arrow') {
148
177
  checked <=> [@game, :instant_down_on_up]
149
178
  }
150
179
 
151
- radio_menu_item('Rotate Right on Up Arrow') { |r|
180
+ radio_menu_item('Rotate Right on Up Arrow') {
152
181
  checked <=> [@game, :rotate_right_on_up]
153
182
  }
154
183
 
155
- radio_menu_item('Rotate Left on Up Arrow') { |r|
184
+ radio_menu_item('Rotate Left on Up Arrow') {
156
185
  checked <=> [@game, :rotate_left_on_up]
157
186
  }
158
187
  }
@@ -199,7 +228,7 @@ class Tetris
199
228
  block = {}
200
229
  bevel_pixel_size = 0.16 * block_size.to_f
201
230
  color = Glimmer::LibUI.interpret_color(Model::Block::COLOR_CLEAR)
202
- area {
231
+ block[:area] = area {
203
232
  block[:background_square] = square(0, 0, block_size) {
204
233
  fill color
205
234
  }
@@ -275,12 +304,6 @@ class Tetris
275
304
 
276
305
  def score_board(block_size: , &extra_content)
277
306
  vertical_box {
278
- horizontal_box {
279
- label # filler
280
- @preview_playfield_blocks = playfield(playfield_width: Model::Game::PREVIEW_PLAYFIELD_WIDTH, playfield_height: Model::Game::PREVIEW_PLAYFIELD_HEIGHT, block_size: block_size)
281
- label # filler
282
- }
283
-
284
307
  horizontal_box {
285
308
  label # filler
286
309
  grid {
@@ -321,6 +344,12 @@ class Tetris
321
344
  }
322
345
  label # filler
323
346
  }
347
+
348
+ horizontal_box {
349
+ label # filler
350
+ @preview_playfield_blocks = playfield(playfield_width: Model::Game::PREVIEW_PLAYFIELD_WIDTH, playfield_height: Model::Game::PREVIEW_PLAYFIELD_HEIGHT, block_size: block_size)
351
+ label # filler
352
+ }
324
353
 
325
354
  extra_content&.call
326
355
  }
@@ -329,9 +358,11 @@ class Tetris
329
358
  def start_moving_tetrominos_down
330
359
  unless @tetrominos_start_moving_down
331
360
  @tetrominos_start_moving_down = true
332
- Glimmer::LibUI.timer(@game.delay) do
361
+ tetromino_move = proc do
333
362
  @game.down! if !@game.game_over? && !@game.paused?
363
+ Glimmer::LibUI.timer(@game.delay, repeat: false, &tetromino_move)
334
364
  end
365
+ Glimmer::LibUI.timer(@game.delay, repeat: false, &tetromino_move)
335
366
  end
336
367
  end
337
368
 
@@ -360,7 +391,7 @@ class Tetris
360
391
 
361
392
  def show_about_dialog
362
393
  Glimmer::LibUI.queue_main do
363
- msg_box('About', 'Glimmer Tetris - Glimmer DSL for LibUI Example - Copyright (c) 2021 Andy Maleh')
394
+ msg_box('About', 'Glimmer Tetris - Glimmer DSL for LibUI Example - Copyright (c) 2021-2022 Andy Maleh')
364
395
  end
365
396
  end
366
397
  end
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2007-2021 Andy Maleh
1
+ # Copyright (c) 2021-2022 Andy Maleh
2
2
  #
3
3
  # Permission is hereby granted, free of charge, to any person obtaining
4
4
  # a copy of this software and associated documentation files (the
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2007-2021 Andy Maleh
1
+ # Copyright (c) 2021-2022 Andy Maleh
2
2
  #
3
3
  # Permission is hereby granted, free of charge, to any person obtaining
4
4
  # a copy of this software and associated documentation files (the
Binary file
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2021 Andy Maleh
1
+ # Copyright (c) 2021-2022 Andy Maleh
2
2
  #
3
3
  # Permission is hereby granted, free of charge, to any person obtaining
4
4
  # a copy of this software and associated documentation files (the
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2021 Andy Maleh
1
+ # Copyright (c) 2021-2022 Andy Maleh
2
2
  #
3
3
  # Permission is hereby granted, free of charge, to any person obtaining
4
4
  # a copy of this software and associated documentation files (the
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2021 Andy Maleh
1
+ # Copyright (c) 2021-2022 Andy Maleh
2
2
  #
3
3
  # Permission is hereby granted, free of charge, to any person obtaining
4
4
  # a copy of this software and associated documentation files (the
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2021 Andy Maleh
1
+ # Copyright (c) 2021-2022 Andy Maleh
2
2
  #
3
3
  # Permission is hereby granted, free of charge, to any person obtaining
4
4
  # a copy of this software and associated documentation files (the
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2021 Andy Maleh
1
+ # Copyright (c) 2021-2022 Andy Maleh
2
2
  #
3
3
  # Permission is hereby granted, free of charge, to any person obtaining
4
4
  # a copy of this software and associated documentation files (the
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2021 Andy Maleh
1
+ # Copyright (c) 2021-2022 Andy Maleh
2
2
  #
3
3
  # Permission is hereby granted, free of charge, to any person obtaining
4
4
  # a copy of this software and associated documentation files (the
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2021 Andy Maleh
1
+ # Copyright (c) 2021-2022 Andy Maleh
2
2
  #
3
3
  # Permission is hereby granted, free of charge, to any person obtaining
4
4
  # a copy of this software and associated documentation files (the
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2021 Andy Maleh
1
+ # Copyright (c) 2021-2022 Andy Maleh
2
2
  #
3
3
  # Permission is hereby granted, free of charge, to any person obtaining
4
4
  # a copy of this software and associated documentation files (the
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2021 Andy Maleh
1
+ # Copyright (c) 2021-2022 Andy Maleh
2
2
  #
3
3
  # Permission is hereby granted, free of charge, to any person obtaining
4
4
  # a copy of this software and associated documentation files (the
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2021 Andy Maleh
1
+ # Copyright (c) 2021-2022 Andy Maleh
2
2
  #
3
3
  # Permission is hereby granted, free of charge, to any person obtaining
4
4
  # a copy of this software and associated documentation files (the
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2021 Andy Maleh
1
+ # Copyright (c) 2021-2022 Andy Maleh
2
2
  #
3
3
  # Permission is hereby granted, free of charge, to any person obtaining
4
4
  # a copy of this software and associated documentation files (the
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2021 Andy Maleh
1
+ # Copyright (c) 2021-2022 Andy Maleh
2
2
  #
3
3
  # Permission is hereby granted, free of charge, to any person obtaining
4
4
  # a copy of this software and associated documentation files (the
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2021 Andy Maleh
1
+ # Copyright (c) 2021-2022 Andy Maleh
2
2
  #
3
3
  # Permission is hereby granted, free of charge, to any person obtaining
4
4
  # a copy of this software and associated documentation files (the
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2021 Andy Maleh
1
+ # Copyright (c) 2021-2022 Andy Maleh
2
2
  #
3
3
  # Permission is hereby granted, free of charge, to any person obtaining
4
4
  # a copy of this software and associated documentation files (the
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2021 Andy Maleh
1
+ # Copyright (c) 2021-2022 Andy Maleh
2
2
  #
3
3
  # Permission is hereby granted, free of charge, to any person obtaining
4
4
  # a copy of this software and associated documentation files (the
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2021 Andy Maleh
1
+ # Copyright (c) 2021-2022 Andy Maleh
2
2
  #
3
3
  # Permission is hereby granted, free of charge, to any person obtaining
4
4
  # a copy of this software and associated documentation files (the
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2021 Andy Maleh
1
+ # Copyright (c) 2021-2022 Andy Maleh
2
2
  #
3
3
  # Permission is hereby granted, free of charge, to any person obtaining
4
4
  # a copy of this software and associated documentation files (the
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2021 Andy Maleh
1
+ # Copyright (c) 2021-2022 Andy Maleh
2
2
  #
3
3
  # Permission is hereby granted, free of charge, to any person obtaining
4
4
  # a copy of this software and associated documentation files (the
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2021 Andy Maleh
1
+ # Copyright (c) 2021-2022 Andy Maleh
2
2
  #
3
3
  # Permission is hereby granted, free of charge, to any person obtaining
4
4
  # a copy of this software and associated documentation files (the
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2021 Andy Maleh
1
+ # Copyright (c) 2021-2022 Andy Maleh
2
2
  #
3
3
  # Permission is hereby granted, free of charge, to any person obtaining
4
4
  # a copy of this software and associated documentation files (the
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2021 Andy Maleh
1
+ # Copyright (c) 2021-2022 Andy Maleh
2
2
  #
3
3
  # Permission is hereby granted, free of charge, to any person obtaining
4
4
  # a copy of this software and associated documentation files (the
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2021 Andy Maleh
1
+ # Copyright (c) 2021-2022 Andy Maleh
2
2
  #
3
3
  # Permission is hereby granted, free of charge, to any person obtaining
4
4
  # a copy of this software and associated documentation files (the
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2021 Andy Maleh
1
+ # Copyright (c) 2021-2022 Andy Maleh
2
2
  #
3
3
  # Permission is hereby granted, free of charge, to any person obtaining
4
4
  # a copy of this software and associated documentation files (the
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2021 Andy Maleh
1
+ # Copyright (c) 2021-2022 Andy Maleh
2
2
  #
3
3
  # Permission is hereby granted, free of charge, to any person obtaining
4
4
  # a copy of this software and associated documentation files (the
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2021 Andy Maleh
1
+ # Copyright (c) 2021-2022 Andy Maleh
2
2
  #
3
3
  # Permission is hereby granted, free of charge, to any person obtaining
4
4
  # a copy of this software and associated documentation files (the
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2021 Andy Maleh
1
+ # Copyright (c) 2021-2022 Andy Maleh
2
2
  #
3
3
  # Permission is hereby granted, free of charge, to any person obtaining
4
4
  # a copy of this software and associated documentation files (the
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2021 Andy Maleh
1
+ # Copyright (c) 2021-2022 Andy Maleh
2
2
  #
3
3
  # Permission is hereby granted, free of charge, to any person obtaining
4
4
  # a copy of this software and associated documentation files (the
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2021 Andy Maleh
1
+ # Copyright (c) 2021-2022 Andy Maleh
2
2
  #
3
3
  # Permission is hereby granted, free of charge, to any person obtaining
4
4
  # a copy of this software and associated documentation files (the
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2021 Andy Maleh
1
+ # Copyright (c) 2021-2022 Andy Maleh
2
2
  #
3
3
  # Permission is hereby granted, free of charge, to any person obtaining
4
4
  # a copy of this software and associated documentation files (the
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2021 Andy Maleh
1
+ # Copyright (c) 2021-2022 Andy Maleh
2
2
  #
3
3
  # Permission is hereby granted, free of charge, to any person obtaining
4
4
  # a copy of this software and associated documentation files (the
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2021 Andy Maleh
1
+ # Copyright (c) 2021-2022 Andy Maleh
2
2
  #
3
3
  # Permission is hereby granted, free of charge, to any person obtaining
4
4
  # a copy of this software and associated documentation files (the
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2021 Andy Maleh
1
+ # Copyright (c) 2021-2022 Andy Maleh
2
2
  #
3
3
  # Permission is hereby granted, free of charge, to any person obtaining
4
4
  # a copy of this software and associated documentation files (the
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2021 Andy Maleh
1
+ # Copyright (c) 2021-2022 Andy Maleh
2
2
  #
3
3
  # Permission is hereby granted, free of charge, to any person obtaining
4
4
  # a copy of this software and associated documentation files (the
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2021 Andy Maleh
1
+ # Copyright (c) 2021-2022 Andy Maleh
2
2
  #
3
3
  # Permission is hereby granted, free of charge, to any person obtaining
4
4
  # a copy of this software and associated documentation files (the
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2021 Andy Maleh
1
+ # Copyright (c) 2021-2022 Andy Maleh
2
2
  #
3
3
  # Permission is hereby granted, free of charge, to any person obtaining
4
4
  # a copy of this software and associated documentation files (the
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2021 Andy Maleh
1
+ # Copyright (c) 2021-2022 Andy Maleh
2
2
  #
3
3
  # Permission is hereby granted, free of charge, to any person obtaining
4
4
  # a copy of this software and associated documentation files (the
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2021 Andy Maleh
1
+ # Copyright (c) 2021-2022 Andy Maleh
2
2
  #
3
3
  # Permission is hereby granted, free of charge, to any person obtaining
4
4
  # a copy of this software and associated documentation files (the
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2021 Andy Maleh
1
+ # Copyright (c) 2021-2022 Andy Maleh
2
2
  #
3
3
  # Permission is hereby granted, free of charge, to any person obtaining
4
4
  # a copy of this software and associated documentation files (the
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2021 Andy Maleh
1
+ # Copyright (c) 2021-2022 Andy Maleh
2
2
  #
3
3
  # Permission is hereby granted, free of charge, to any person obtaining
4
4
  # a copy of this software and associated documentation files (the
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2021 Andy Maleh
1
+ # Copyright (c) 2021-2022 Andy Maleh
2
2
  #
3
3
  # Permission is hereby granted, free of charge, to any person obtaining
4
4
  # a copy of this software and associated documentation files (the
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2021 Andy Maleh
1
+ # Copyright (c) 2021-2022 Andy Maleh
2
2
  #
3
3
  # Permission is hereby granted, free of charge, to any person obtaining
4
4
  # a copy of this software and associated documentation files (the
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2021 Andy Maleh
1
+ # Copyright (c) 2021-2022 Andy Maleh
2
2
  #
3
3
  # Permission is hereby granted, free of charge, to any person obtaining
4
4
  # a copy of this software and associated documentation files (the
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2021 Andy Maleh
1
+ # Copyright (c) 2021-2022 Andy Maleh
2
2
  #
3
3
  # Permission is hereby granted, free of charge, to any person obtaining
4
4
  # a copy of this software and associated documentation files (the
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2021 Andy Maleh
1
+ # Copyright (c) 2021-2022 Andy Maleh
2
2
  #
3
3
  # Permission is hereby granted, free of charge, to any person obtaining
4
4
  # a copy of this software and associated documentation files (the
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2021 Andy Maleh
1
+ # Copyright (c) 2021-2022 Andy Maleh
2
2
  #
3
3
  # Permission is hereby granted, free of charge, to any person obtaining
4
4
  # a copy of this software and associated documentation files (the
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2021 Andy Maleh
1
+ # Copyright (c) 2021-2022 Andy Maleh
2
2
  #
3
3
  # Permission is hereby granted, free of charge, to any person obtaining
4
4
  # a copy of this software and associated documentation files (the
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2021 Andy Maleh
1
+ # Copyright (c) 2021-2022 Andy Maleh
2
2
  #
3
3
  # Permission is hereby granted, free of charge, to any person obtaining
4
4
  # a copy of this software and associated documentation files (the
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2021 Andy Maleh
1
+ # Copyright (c) 2021-2022 Andy Maleh
2
2
  #
3
3
  # Permission is hereby granted, free of charge, to any person obtaining
4
4
  # a copy of this software and associated documentation files (the
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2021 Andy Maleh
1
+ # Copyright (c) 2021-2022 Andy Maleh
2
2
  #
3
3
  # Permission is hereby granted, free of charge, to any person obtaining
4
4
  # a copy of this software and associated documentation files (the
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2021 Andy Maleh
1
+ # Copyright (c) 2021-2022 Andy Maleh
2
2
  #
3
3
  # Permission is hereby granted, free of charge, to any person obtaining
4
4
  # a copy of this software and associated documentation files (the
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2021 Andy Maleh
1
+ # Copyright (c) 2021-2022 Andy Maleh
2
2
  #
3
3
  # Permission is hereby granted, free of charge, to any person obtaining
4
4
  # a copy of this software and associated documentation files (the