<commit_before>require 'webrick'
#require 'xmlrpc/server.rb'
require 'graph.rb'
require 'optparse'
require 'cgi'

class Link
  def to_xml
    "<link/>"
  end
end

class Street
  def to_xml
    "<street name='#{name}' length='#{length}' />"
  end
end

class TripHopSchedule
  def to_xml
    ret = ["<triphopschedule service_id='#{service_id}'>"]
    triphops.each do |depart, arrive, transit, trip_id|
      ret << "<triphop depart='#{depart}' arrive='#{arrive}' transit='#{transit}' trip_id='#{trip_id}' />"
    end
    ret << "</triphopschedule>"

    return ret.join
  end
end

class State
  def to_xml
    ret = "<state "
    self.to_hash.each_pair do |name, value|
      ret << "#{name}='#{CGI.escape(value.to_s)}' "
    end
    ret << "/>"
  end
end

class Vertex
  def to_xml
    ret = ["<vertex label='#{label}'>"]
    if pl=payload then #to avoid calling payload twice. instantiating a variable may actually be more expensive.
      ret << pl.to_xml
    end
    ret << "</vertex>"
    return ret.join
  end
end

class Edge
  def to_xml verbose=true
    ret = "<edge>"
    ret << payload.to_xml if verbose
    ret << "</edge>"
  end
end

OPTIONS = { :port => 3003 }

ARGV.options do |opts|
  script_name = File.basename($0)
  opts.banner = "Usage: ruby #{script_name} [options]"

  opts.separator ""

  opts.on("-p", "--port=port", Integer,
          "Runs Rails on the specified port.",
          "Default: 3003") { |v| OPTIONS[:port] = v }

  opts.on("-h", "--help",
          "Show this help message.") { puts opts; exit }

  opts.parse!
end

class Graphserver  
  attr_reader :gg 

  def parse_init_state request
    State.new( (request.query['time'] or Time.now) ) #breaks without the extra parens
  end 

  def initialize
    @gg = Graph.create #horrible hack

    @server = WEBrick::HTTPServer.new(:Port => OPTIONS[:port])

    @server.mount_proc( "/" ) do |request, response|
      ret = ["Graphserver Web API"]
      ret << "shortest_path?from=FROM&to=TO"
      ret << "all_vertex_labels"
      ret << "outgoing_edges?label=LABEL"
      ret << "eval_edges?label=LABEL&statevar1=STV1&statevar2=STV2..."
      response.body = ret.join("\n")
    end

    @server.mount_proc( "/shortest_path" ) do |request, response|
      if request.query['debug'] == 'true' then
         verbose=true
      else
         verbose=false
      end
      
      from = request.query['from']
      to = request.query['to']
      ret = []
      
      begin
         unless  @gg.get_vertex(from) and @gg.get_vertex(to) then raise ArgumentError end
         init_state = parse_init_state( request )
           vertices, edges = @gg.shortest_path(from, to, init_state )      #Throws RuntimeError if no shortest path found.
           ret << "<?xml version='1.0'?>"
           ret << "<route>"
           ret << vertices.shift.to_xml
           edges.each do |edge|
             ret << edge.to_xml( verbose )
             ret << vertices.shift.to_xml
           end
           ret << "</route>"
         rescue RuntimeError                                               #TODO: change exception type, RuntimeError is too vague.
           ret << "Couldn't find a shortest path from #{from} to #{to}"
         rescue ArgumentError
           ret << "ERROR: Invalid parameters."
       end
      response.body = ret.join
    end

    @server.mount_proc( "/all_vertex_labels" ) do |request, response|
      vlabels = []
      vlabels << "<?xml version='1.0'?>"
      vlabels << "<labels>"
      @gg.vertices.each do |vertex|
        vlabels << "<label>#{vertex.label}</label>"
      end
      vlabels << "</labels>"
      response.body = vlabels.join
    end

    @server.mount_proc( "/outgoing_edges" ) do |request, response|
      vertex = @gg.get_vertex( request.query['label'] )
      ret = []
      ret << "<?xml version='1.0'?>"
      ret << "<edges>"
      vertex.each_outgoing do |edge|
        ret << "<edge>"
        ret << "<dest>#{edge.to.to_xml}</dest>"
        ret << "<payload>#{edge.payload.to_xml}</payload>"
        ret << "</edge>"
      end
      ret << "</edges>"
      response.body = ret.join
    end<commit_msg>indentation fix duh<commit_after>require 'webrick'
#require 'xmlrpc/server.rb'
require 'graph.rb'
require 'optparse'
require 'cgi'

class Link
  def to_xml
    "<link/>"
  end
end

class Street
  def to_xml
    "<street name='#{name}' length='#{length}' />"
  end
end

class TripHopSchedule
  def to_xml
    ret = ["<triphopschedule service_id='#{service_id}'>"]
    triphops.each do |depart, arrive, transit, trip_id|
      ret << "<triphop depart='#{depart}' arrive='#{arrive}' transit='#{transit}' trip_id='#{trip_id}' />"
    end
    ret << "</triphopschedule>"

    return ret.join
  end
end

class State
  def to_xml
    ret = "<state "
    self.to_hash.each_pair do |name, value|
      ret << "#{name}='#{CGI.escape(value.to_s)}' "
    end
    ret << "/>"
  end
end

class Vertex
  def to_xml
    ret = ["<vertex label='#{label}'>"]
    if pl=payload then #to avoid calling payload twice. instantiating a variable may actually be more expensive.
      ret << pl.to_xml
    end
    ret << "</vertex>"
    return ret.join
  end
end

class Edge
  def to_xml verbose=true
    ret = "<edge>"
    ret << payload.to_xml if verbose
    ret << "</edge>"
  end
end

OPTIONS = { :port => 3003 }

ARGV.options do |opts|
  script_name = File.basename($0)
  opts.banner = "Usage: ruby #{script_name} [options]"

  opts.separator ""

  opts.on("-p", "--port=port", Integer,
          "Runs Rails on the specified port.",
          "Default: 3003") { |v| OPTIONS[:port] = v }

  opts.on("-h", "--help",
          "Show this help message.") { puts opts; exit }

  opts.parse!
end

class Graphserver  
  attr_reader :gg 

  def parse_init_state request
    State.new( (request.query['time'] or Time.now) ) #breaks without the extra parens
  end 

  def initialize
    @gg = Graph.create #horrible hack

    @server = WEBrick::HTTPServer.new(:Port => OPTIONS[:port])

    @server.mount_proc( "/" ) do |request, response|
      ret = ["Graphserver Web API"]
      ret << "shortest_path?from=FROM&to=TO"
      ret << "all_vertex_labels"
      ret << "outgoing_edges?label=LABEL"
      ret << "eval_edges?label=LABEL&statevar1=STV1&statevar2=STV2..."
      response.body = ret.join("\n")
    end

    @server.mount_proc( "/shortest_path" ) do |request, response|
      if request.query['debug'] == 'true' then
         verbose=true
      else
         verbose=false
      end
      
      from = request.query['from']
      to = request.query['to']
      ret = []
      
      begin
        unless  @gg.get_vertex(from) and @gg.get_vertex(to) then raise ArgumentError end
        init_state = parse_init_state( request )
        vertices, edges = @gg.shortest_path(from, to, init_state )      #Throws RuntimeError if no shortest path found.
        ret << "<?xml version='1.0'?>"
        ret << "<route>"
        ret << vertices.shift.to_xml
        edges.each do |edge|
          ret << edge.to_xml( verbose )
          ret << vertices.shift.to_xml
        end
        ret << "</route>"
      rescue RuntimeError                                               #TODO: change exception type, RuntimeError is too vague.
        ret << "Couldn't find a shortest path from #{from} to #{to}"
      rescue ArgumentError
        ret << "ERROR: Invalid parameters."
      end
      
      response.body = ret.join
    end

    @server.mount_proc( "/all_vertex_labels" ) do |request, response|
      vlabels = []
      vlabels << "<?xml version='1.0'?>"
      vlabels << "<labels>"
      @gg.vertices.each do |vertex|
        vlabels << "<label>#{vertex.label}</label>"
      end
      vlabels << "</labels>"
      response.body = vlabels.join
    end

    @server.mount_proc( "/outgoing_edges" ) do |request, response|
      vertex = @gg.get_vertex( request.query['label'] )
      ret = []
      ret << "<?xml version='1.0'?>"
      ret << "<edges>"
      vertex.each_outgoing do |edge|
        ret << "<edge>"
        ret << "<dest>#{edge.to.to_xml}</dest>"
        ret << "<payload>#{edge.payload.to_xml}</payload>"
        ret << "</edge>"
      end
      ret << "</edges>"
      response.body = ret.join
    end
{'fraction_non_alphanumeric': 0.1483375959079284, 'fraction_numerical': 0.004627938131774449, 'mean_word_length': 2.4046434494195688, 'pattern_counts': {'":': 0, '<': 181, '<?xml version=': 6, '>': 61, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 34}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '190101', 'n_tokens_mistral': 2703, 'n_tokens_neox': 2654, 'n_words': 685}