[[Kategorie:Projekt]] =Telnet-Haltestellenmonitor=
#!/usr/bin/env ruby
require 'net/http'
require 'socket'
require 'rexml/document'
class MultipleStations < RuntimeError
  def initialize(stations)
    @stations = stations
  end
  def to_s
    "Mehrere mögliche Haltestellen: " + @stations.join(', ')
  end
end
class StationResult
  def initialize(card)
    strong_n = 0
    card.each_element('p/strong') { |e|
      case strong_n
        when 0
          @name = e.text
        when 1
          @time = e.text
      end
      strong_n += 1
    }
    @trams = []
    card.to_s.scan(/br\/>(\d+:\d+\*?) (.+?)-> (.+?) column_widths[i]
      }
    }
    "\n\n#{@name}, #{@time}:\n\n" +
    'Zeit'.ljust(column_widths[0]) + ' | ' +
      'Linie'.ljust(column_widths[1]) + ' | ' +
      'Ziel'.ljust(column_widths[2]) + "\n" +
    ('-' * column_widths[0]) + '-+-' +
      ('-' * column_widths[1]) + '-+-' +
      ('-' * column_widths[2]) + "\n" +
    @trams.collect { |time,tram,direction|
      time.ljust(column_widths[0]) + ' | ' +
        tram.ljust(column_widths[1]) + ' | ' +
        direction.ljust(column_widths[2])
    }.join("\n")
  end
end
class ClientHandler
  def initialize(socket)
    @socket = socket
    puts "#{address} connected"
    Thread.new {
      begin
        handle
      rescue Exception => e
        @socket.puts("Fehler: #{e}")
      ensure
        @socket.close
      end
    }
  end
  def address
    if @socket.peeraddr[0] == 'AF_INET6'
      "[#{@socket.peeraddr[3]}]"
    else
      "#{@socket.peeraddr[3]}"
    end +
    ":#{@socket.peeraddr[1]}"
  end
  def ask_haltestellenmonitor(station)
    param = { :station => station,
              :action => :check,
              :time => Time.new.strftime('%H:%M'),
              :date => Time.new.strftime('%d.%m.%Y')
            }
    param_s = param.collect { |k,v| "#{k}=#{v}" }.join('&')
    param_s.gsub!(/ /, '+')
    res = Net::HTTP.start('wap.dvbag.de') { |http|
      http.get('/wapVVO/wap-rbl.php?' + param_s)
    }
    if res.kind_of? Net::HTTPSuccess
      wml = REXML::Document.new(res.body).root
      card = nil
      wml.each_element('/wml/card') { |c| card = c }
      if card
        if card.attributes['id'] == 'liste'
          stations = []
          card.each_element('p/select/option') { |option|
            stations << option.text
          }
          raise MultipleStations.new(stations)
        elsif card.attributes['id'] == 'result'
          StationResult.new(card).to_s
        else
          raise "Unexpected card/@id: #{card.attributes['id']}"
        end 
      else
        raise "No card found in result document"
      end
    else
      raise "#{res.class}"
    end
  end
  def handle
    @socket.print "Hallo #{address}\n\nHaltestelle: "
    @socket.flush
    haltestelle = @socket.gets
    if haltestelle
      haltestelle.strip!
      puts "#{address} asks for #{haltestelle.inspect}"
      @socket.puts "Anfrage nach #{haltestelle}..."
      @socket.puts ask_haltestellenmonitor(haltestelle)
    end
  end
end
serv = TCPServer.new('0.0.0.0', 65023)
while client = serv.accept
  ClientHandler.new(client)
end
Und dann: telnet localhost 65023 [[Kategorie:Ruby]] {{Rübÿ Spëëd Mëtäl Cödïng}}