Skip to content

Commit

Permalink
Many improvements
Browse files Browse the repository at this point in the history
  • Loading branch information
pikesley committed Jan 26, 2018
1 parent dba8e8e commit 3bc13e5
Show file tree
Hide file tree
Showing 26 changed files with 643 additions and 195 deletions.
4 changes: 2 additions & 2 deletions README.md
Expand Up @@ -63,6 +63,6 @@ In order to over-engineer this, I've wrapped a [very thin Flask app](https://git

hanoi phat --phat <address_of_your_pi> --interval 0.1

to watch this all [play out on the pHAT](https://www.youtube.com/watch?v=PAQY5XtdNO8):
to watch this all [play out on the pHAT](https://www.youtube.com/watch?v=LT3HNsVxhM8):

[![Video](https://i.imgur.com/QILZYgx.png)](https://www.youtube.com/watch?v=PAQY5XtdNO8)
[![Screenshot](https://i.imgur.com/yrK3isK.png)](https://www.youtube.com/watch?v=LT3HNsVxhM8)
1 change: 0 additions & 1 deletion TODO.md

This file was deleted.

5 changes: 3 additions & 2 deletions config/config.yml
Expand Up @@ -2,14 +2,12 @@ chars:
regular:
space: ' '
disc: 'o'
pole: '|'
vert_divider: '|'
horiz_divider: '-'

fancy:
space: ' '
disc: '🎾'
pole: '💈'
vert_divider: '🔺'
horiz_divider: '🔻'

Expand All @@ -28,3 +26,6 @@ digits:
- [1, 1, 0]
- [0, 1, 0]
- [0, 1, 1]

animation:
tween-scale: 0.1
46 changes: 38 additions & 8 deletions lib/hanoi/jane.rb
@@ -1,39 +1,43 @@
require 'singleton'
require 'yaml'
require 'ostruct'

require 'thor'
require 'httparty'

require 'hanoi/jane/version'

require 'hanoi/jane/config'
require 'hanoi/jane/exceptions'

require 'hanoi/jane/towers/stack_finders'
require 'hanoi/jane/towers/towers'
require 'hanoi/jane/towers/regular_towers'
require 'hanoi/jane/towers/constrained_towers'
require 'hanoi/jane/towers/animated_towers'

require 'hanoi/jane/animation/animation'
require 'hanoi/jane/animation/frame'
require 'hanoi/jane/animation/lifter'
require 'hanoi/jane/animation/dropper'
require 'hanoi/jane/animation/padded_stacks'
require 'hanoi/jane/animation/drop_in'
require 'hanoi/jane/animation/smoosher'

require 'hanoi/jane/formatters/matrix'
require 'hanoi/jane/formatters/console'

module Hanoi
module Jane
def self.hit_phat stacks, value, phat
matrix = Formatters::Matrix.new do |m|
m.stacks = stacks
m.digits = value
def self.render_to_phat source, interval, phat
source.each do |frame|
Hanoi::Jane.hit_phat frame.to_dots, phat
sleep interval * interval_factor(frame)
end
matrix.populate
end

def self.hit_phat grid, phat
url = "http://#{phat}/lights"
payload = {
matrix: matrix
matrix: grid
}
headers = {
'Content-Type' => 'application/json',
Expand All @@ -42,5 +46,31 @@ def self.hit_phat stacks, value, phat

HTTParty.patch(url, body: payload.to_json, headers: headers)
end

def self.render_to_console source, interval, fancy
source.each do |frame|
Hanoi::Jane.draw_console frame.stacks, frame.value, fancy
sleep interval * interval_factor(frame)
end
end

def self.draw_console stacks, value, fancy = false
system('clear')

c = Formatters::Console.new do |c|
c.stacks = stacks
c.fancy = fancy
end

puts value
puts c
end

def self.interval_factor frame
if frame.animtype == :tween
return Config.instance.config.animation['tween-scale']
end
1
end
end
end
43 changes: 43 additions & 0 deletions lib/hanoi/jane/animation/drop_in.rb
@@ -0,0 +1,43 @@
module Hanoi
module Jane
class DropIn
include Enumerable

attr_accessor :height, :discs
attr_reader :stacks, :disc, :animtype

def initialize
@height = 7
@discs = 3
@animtype = :tween
yield self if block_given?

@stacks = PaddedStacks.new [[], [], []], @height
@disc = discs - 1
@dropper = Dropper.new @stacks[0], @disc, true
end

def value
'0' * (@discs - @disc)
end

def each
while @disc >= 0
@dropper = Dropper.new @stacks[0], @disc, (@disc == 0 ? false : true)
@dropper.each do |state|
@stacks[0] = state.to_a
yield self
end
@disc -= 1
end
end

def to_dots
Formatters::Matrix.new do |m|
m.stacks = @stacks
m.digits = '0' * (@discs - @disc)
end
end
end
end
end
14 changes: 11 additions & 3 deletions lib/hanoi/jane/animation/dropper.rb
@@ -1,9 +1,10 @@
module Hanoi
module Jane
class Dropper < Array
def initialize stack, item
def initialize stack, item, full_drop = false
stack.map { |i| self.push i }
@item = item
@full_drop = full_drop
end

def drop
Expand All @@ -16,10 +17,17 @@ def drop
end

def dropped
(self[(Dropper.position self, @item) - 1] || self[(Dropper.position self, @item)]) || (Dropper.position self, @item) == 0
if @full_drop
return self[(Dropper.position self, @item)] || (Dropper.position self, @item) < 0
end

(
self[(Dropper.position self, @item) - 1] ||
self[(Dropper.position self, @item)]
) || (Dropper.position self, @item) == 0
end

def each
def each
until dropped
drop
yield self
Expand Down
20 changes: 20 additions & 0 deletions lib/hanoi/jane/animation/frame.rb
@@ -0,0 +1,20 @@
module Hanoi
module Jane
class Frame
attr_reader :stacks, :animtype, :value

def initialize stacks, value, type
@stacks = stacks
@value = value
@animtype = type
end

def to_dots
Formatters::Matrix.new do |m|
m.stacks = @stacks
m.digits = @value
end
end
end
end
end
45 changes: 45 additions & 0 deletions lib/hanoi/jane/animation/smoosher.rb
@@ -0,0 +1,45 @@
module Hanoi
module Jane
class Smoosher < Array
include Enumerable

attr_accessor :direction
attr_reader :animtype

def initialize
@direction = :close
@step = 0.05
@animtype = :tween

yield self if block_given?
end

def each
@range = (0..1).step(0.05).to_a
@range.reverse! if @direction == :open
@range.each do |weight|
populate weight
yield self
end
end

def populate weight
7.times do |i|
self[i] = Smoosher.row weight
end
end

def to_dots
self
end

def Smoosher.row weight = 0
a = []
45.times do
a.push (weight > Random.rand) ? 1 : 0
end
a
end
end
end
end
76 changes: 40 additions & 36 deletions lib/hanoi/jane/cli.rb
Expand Up @@ -10,60 +10,64 @@ def version
map %w(-v --version) => :version

desc 'phat', "Solve the towers against the pHAT's webserver"
option :phat, type: :string, required: true
option :constrained, type: :boolean
option :interval, type: :numeric, default: 0.1
option :phat, type: :string, required: true, desc: 'Address of the pHAT you want to hit'
option :discs, type: :numeric, default: 5, desc: 'Number of discs'
option :constrained, type: :boolean, desc: 'Solve the constrained variant'
option :interval, type: :numeric, default: 0.1, desc: 'Time between frames (ish)'

def phat
at = AnimatedTowers.new do |a|
smoosher = Hanoi::Jane::Smoosher.new
[:close, :open].each do |direction|
smoosher.direction = direction
Hanoi::Jane.render_to_phat smoosher, options[:interval], options[:phat]
end

drop_in = DropIn.new do |d|
d.height = 7
d.discs = options[:discs]
end

towers = AnimatedTowers.new do |a|
a.towers = ConstrainedTowers
a.discs = 5
a.discs = options[:discs]
a.height = 7
end

at.each do |frame|
Hanoi::Jane.hit_phat frame.stacks, frame.value, options[:phat]
interval = options[:interval]
if frame.type == :tween
interval = interval * 0.1
end
sleep interval
[drop_in, towers].each do |source|
Hanoi::Jane.render_to_phat source, options[:interval], options[:phat]
end
end

desc 'console', 'Solve the towers on the console'
option :discs, type: :numeric, default: 3
option :constrained, type: :boolean, default: true
option :interval, type: :numeric, default: 0.5
option :height, type: :numeric, default: 2
option :fancy, type: :boolean, default: false
option :discs, type: :numeric, default: 3, desc: 'Number of discs'
option :constrained, type: :boolean, default: true, desc: 'Solve the constrained variant'
option :interval, type: :numeric, default: 0.5, desc: 'Time between frames (ish)'
option :height, type: :numeric, default: 2, desc: 'Additional height above towers'
option :fancy, type: :boolean, default: false, desc: 'Draw the towers using emojis'

def console
at = AnimatedTowers.new do |a|
a.towers = options[:constrained] ? ConstrainedTowers : Towers
a.discs = options[:discs]
a.height = options[:discs] + options[:height]
end
begin
drop_in = DropIn.new do |d|
d.height = options[:discs] + options[:height]
d.discs = options[:discs]
end

at.each do |frame|
system('clear')
towers = AnimatedTowers.new do |a|
a.towers = options[:constrained] ? ConstrainedTowers : RegularTowers
a.discs = options[:discs]
a.height = options[:discs] + options[:height]
end

c = Formatters::Console.new do |c|
c.stacks = frame.stacks
c.fancy = options[:fancy]
[drop_in, towers].each do |source|
Hanoi::Jane.render_to_console source, options[:interval], options[:fancy]
end

puts frame.value
puts c
puts '%d moves to solve for %d discs' % [towers.towers.total, towers.discs]

interval = options[:interval]
if frame.type == :tween
interval = interval * 0.1
end
sleep interval
rescue HanoiException => he
puts he.text
system('exit')
end

puts '%d moves to solve for %d discs' % [at.towers.total, at.discs]
end
end
end
Expand Down
27 changes: 27 additions & 0 deletions lib/hanoi/jane/exceptions.rb
@@ -0,0 +1,27 @@
module Hanoi
module Jane
class HanoiException < Exception
attr_reader :text

def initialize text
@text = text
end
end

class SearchException < HanoiException
attr_reader :text

def initialize text
@text = text
end
end

class MatrixException < HanoiException
attr_reader :text

def initialize text
@text = text
end
end
end
end

0 comments on commit 3bc13e5

Please sign in to comment.