require 'victor'

def sum_digits(n)
  while n > 9
    n = n.to_s.chars.map(&:to_i).sum
  end
  n
end

def step(x, y, n, dir)
  case dir
  when :top
    return [x,y+n,:right]
  when :right
    return [x+n,y,:bottom]
  when :bottom
    return [x,y-n,:left]
  when :left
    return [x-n,y,:top]
  end
end

def run_number(number)
  counter = 1
  x, y, dir = 0, 0, :top
  line_stack = [[0,0]]

  loop do
    x, y, dir = step(x,y, sum_digits(counter*number), dir)
    line_stack << [x,y]
    counter += 1
    break if x == 0 && y == 0
  end
  return make_svg(line_stack)
end

def make_svg(line_stack)
  line_length = 20
  xs = line_stack.map { |c| c[0] }
  ys = line_stack.map { |c| c[1] }
  
  x_offset = -xs.min
  y_offset = -ys.min
  svg_coords = ->(p) {
    nx, ny = p
    [(nx+x_offset)*line_length + line_length/2, (ny+y_offset)*line_length + line_length/2]
  }
  
  max_width = (xs.max - xs.min).abs * line_length + line_length
  max_height = (ys.max - ys.min).abs * line_length + line_length
  svg = Victor::SVG.new width: max_width, height: max_height
  
  style = { stroke: 'black', stroke_width: 5 }
  svg.build do
    line_stack.each_cons(2) do |pair|
      p1, p2 = pair
      x1, y1 = svg_coords.call(p1)
      x2, y2 = svg_coords.call(p2)
      line x1: x1, y1: y1, x2: x2, y2: y2, style: style
      circle cx: x2, cy: y2, r: line_length/6, style: style, fill: 'black'
    end
  end
  return svg
end

(1..9).each do |i|
  run_number(i).save "pattern_#{i}"
end
