[Groonga-commit] groonga/groonga [master] test: add grntest generator script for geo_distance

Back to archive index

null+****@clear***** null+****@clear*****
2012年 5月 11日 (金) 19:58:11 JST


HAYASHI Kentaro	2012-05-11 19:58:11 +0900 (Fri, 11 May 2012)

  New Revision: 10244bea6275b3cea99aa46508ac11649fa9fee4

  Log:
    test: add grntest generator script for geo_distance

  Added files:
    test/function/tools/geo/generate-grntest-data.rb

  Added: test/function/tools/geo/generate-grntest-data.rb (+310 -0) 100755
===================================================================
--- /dev/null
+++ test/function/tools/geo/generate-grntest-data.rb    2012-05-11 19:58:11 +0900 (377f39c)
@@ -0,0 +1,310 @@
+#!/usr/bin/env ruby
+# -*- coding: utf-8 -*-
+
+require 'fileutils'
+require 'optparse'
+
+TABLE_CREATE = "table_create Geo TABLE_HASH_KEY ShortText\n"
+COLUMN_CREATE = "column_create Geo distance COLUMN_SCALAR Int32\n"
+LOAD = <<-EOF
+load --table Geo
+[
+{"_key": "the record for geo_distance() result"}
+]
+EOF
+CREATE_RESULT = "[[0,0.0,0.0],true]\n"
+LOAD_RESULT = "[[0,0.0,0.0],1]\n"
+
+SELECT_PRE = "[[0,0.0,0.0],[[[1],[[\"_score\",\"Int32\"]],["
+SELECT_POST = "]]]]"
+
+def is_long(start_lng_deg, end_lng_deg)
+  if start_lng_deg != end_lng_deg and
+      ((start_lng_deg > 0 && end_lng_deg.to_i < 0) or
+      (start_lng_deg < 0 && end_lng_deg.to_i > 0)) and
+      start_lng_deg.abs + end_lng_deg.to_i.abs > 180 then
+    # the difference in longitude striding accross meridian is over
+    # 180 degree.
+    return true
+  else
+    return false
+  end
+end
+
+def get_quadrant(lng, lat)
+  if (lng > 0 && lat > 0) then
+    return "1st"
+  elsif (lng < 0 && lat > 0) then
+    return "2nd"
+  elsif (lng < 0 && lat < 0) then
+    return "3rd"
+  elsif (lng > 0 && lat < 0) then
+    return "4th"
+  else
+    return nil
+  end
+end
+
+def is_meridian(lng, lat)
+end
+
+def is_equator(lng, lat)
+end
+
+def is_east_axis(lng, lat)
+  if lng >= 0 and lat == 0 then
+    return true
+  else
+    return false
+  end
+end
+
+def is_west_axis(lng, lat)
+  if lng <= 0 and lat == 0 then
+    return true
+  else
+    return false
+  end
+end
+
+def is_north_axis(lng, lat)
+  if lng == 0 and lat >= 0 then
+    return true
+  else
+    return false
+  end
+end
+
+def is_south_axis(lng, lat)
+  if lng == 0 and lat <= 0 then
+    return true
+  else
+    return false
+  end
+end
+
+def is_point(start_lng, start_lat, end_lng, end_lat)
+  if start_lng == end_lng && start_lat == end_lat then
+    return true
+  else
+    return false
+  end
+end
+
+def get_quadrant_to(start_lng, start_lat, end_lng, end_lat)
+  ret = ""
+  squadrant = get_quadrant(start_lng, start_lat)
+  equadrant = get_quadrant(end_lng, end_lat)
+  # p squadrant
+  # p equadrant
+  # p start_lng
+  # p start_lat
+  # p end_lng
+  # p end_lat
+  if (start_lng == end_lng && start_lng == 0) then
+    ret = "meridian"
+  elsif (start_lat == end_lat && start_lat == 0) then
+    ret = "equator"
+  elsif !squadrant or !equadrant then
+    if (not squadrant) && (not equadrant) then
+      if is_east_axis(start_lng, start_lat) && is_north_axis(end_lng, end_lat) ||
+          is_north_axis(start_lng, start_lat) && is_east_axis(end_lng, end_lat) then
+        return "1st"
+      elsif is_north_axis(start_lng, start_lat) && is_west_axis(end_lng, end_lat) ||
+          is_west_axis(start_lng, start_lat) && is_north_axis(end_lng, end_lat) then
+        return "2nd"
+      elsif is_west_axis(start_lng, start_lat) && is_south_axis(end_lng, end_lat) ||
+          is_south_axis(start_lng, start_lat) && is_west_axis(end_lng, end_lat) then
+        return "3rd"
+      elsif is_east_axis(start_lng, start_lat) && is_south_axis(end_lng, end_lat) ||
+          is_south_axis(start_lng, start_lat) && is_east_axis(end_lng, end_lat) then
+        return "4th"
+      end
+    elsif not squadrant then
+      ret = equadrant
+    elsif not equadrant then
+      ret = squadrant
+    end
+  else
+    if squadrant == equadrant then
+      ret = equadrant
+    else
+      ret = "#{squadrant}to#{equadrant}"
+    end
+  end
+  ret
+end
+
+def get_point(lng, lat)
+  ret = ""
+  # lng -> lat
+  lng_desc = {
+    0 => {
+      90 => "north_pole_on_meridian",
+      89 => "near_north_pole_on_meridian",
+      1 => "near_positive_origin_on_meridian",
+      0 => "origin_on_meridian",
+      -1 => "near_negative_origin_on_meridian",
+      -89 => "near_south_pole_on_meridian",
+      -90 => "south_pole_on_meridian",
+    },
+    -180 => "west_edge",
+    -179 => "near_west_edge",
+    -91 => "west_near_ninety_degrees",
+    -90 => "west_ninety_degrees",
+    -89 => "west_near_ninety_degrees",
+    -1 => "near_negative_origin",
+    1 => "near_positive_origin",
+    89 => "east_near_ninety_degrees",
+    90 => "east_ninety_degrees",
+    91 => "east_near_ninety_degrees",
+    179 => "near_east_edge",
+  }
+  lat_desc = {
+    0 => {
+      -180 => "west_edge_on_equator",
+      -179 => "near_west_edge_on_equator",
+      -91 => "west_near_ninety_degrees_on_equator",
+      -90 => "west_ninety_degrees_on_equator",
+      -89 => "west_near_ninety_degrees_on_equator",
+      -1 => "near_nagative_origin_on_equator",
+      0 => "origin",
+      1 => "near_positive_origin_on_equator",
+      89 => "east_near_ninetydegrees_on_equator",
+      90 => "east_ninety_degrees_on_equator",
+      91 => "east_near_ninety_degrees_on_equator",
+      179 => "near_east_edge_on_equator",
+    },
+    90 => "north_pole",
+    89 => "near_north_pole",
+    1 => "near_positive_origin",
+    -1 => "near_negative_origin",
+    -89 => "near_south_pole",
+    -90 => "south_pole",
+  }
+  if lng == 0 then
+    return lng_desc[lng][lat]
+  elsif lat == 0 then
+    return lat_desc[lat][lng]
+  else
+    return lng_desc[lng] + "_" + lat_desc[lat]
+  end
+end
+
+def get_filename(start_lng, start_lat, end_lng, end_lat)
+  s = get_point(start_lng, start_lat)
+  e = get_point(end_lng, end_lat)
+  if s == e then
+    ret = "#{s}.test"
+  else
+    ret = "#{s}_to_#{e}.test"
+  end
+  ret
+end
+
+def parse_line_data(data)
+  lng_sdeg, lat_sdeg, lng_edeg, lat_edeg,
+  lng_start, lat_start, lng_end, lat_end,
+  distance, filename = data.chomp.split(",")
+
+  return [lng_sdeg.to_i, lat_sdeg.to_i, lng_edeg.to_i, lat_edeg.to_i,
+  lng_start, lat_start, lng_end, lat_end, distance, filename]
+end
+
+
+if __FILE__ == $0 then
+
+  OPTS = {}
+  opt = OptionParser.new
+  opt.on('-g', '--generate-filename'){ |v| OPTS[:name] = v }
+  opt.on('-t', '--generate-test'){ |v| OPTS[:test] = v }
+  opt.on('-e', '--generate-expected'){ |v| OPTS[:expected] = v }
+  opt.on('-c [VAL]', '--csv [VAL]'){ |v| OPTS[:csv] = v }
+  opt.on('-v', '--verbose'){ |v| OPTS[:verbose] = v }
+
+  opt.parse!(ARGV)
+
+  exit if not OPTS.has_key? :csv
+
+  File.open(OPTS[:csv], "r") {|fh|
+    lines = fh.readlines
+
+    SELECT = "select Geo --output_columns distance "
+
+    lines.each_with_index { |line,i|
+      next if i == 0 # skip header
+
+      #puts "line No #{i}"
+
+      lng_sdeg, lat_sdeg, lng_edeg, lat_edeg,
+      lng_start, lat_start, lng_end, lat_end,
+      distance, filename = parse_line_data(line)
+
+      app_types = ["", "rectangle", "rect"]
+      app_types = [""]
+
+      quadrant = get_quadrant_to(lng_sdeg, lat_sdeg, lng_edeg, lat_edeg)
+
+      prefix = is_long(lng_sdeg, lng_edeg) ? "long" : "short"
+
+      type = is_point(lng_sdeg, lat_sdeg, lng_edeg, lat_edeg) ? "point" : "line"
+
+      if OPTS.has_key? :name then
+        filename = get_filename(lng_sdeg, lat_sdeg, lng_edeg, lat_edeg)
+
+        puts "#{line.chomp}"
+        # show new generated filename
+        puts line.chomp.split(",")[0..-2].join(",") + ",#{prefix}/#{quadrant}/#{type}/#{filename}"
+
+      elsif OPTS.has_key? :test then
+        app_types.each { |app_type|
+          scorer = ""
+          file_prefix = ""
+          select_postfix = ""
+          comment = sprintf("# from (longitude %s latitude %s) to (longitude %s latitude %s)\n",
+                    lng_sdeg, lat_sdeg, lng_edeg, lat_edeg)
+          scorer = sprintf("--scorer 'distance = geo_distance(\"%sx%s\", \"%sx%s\"",
+                   lng_start, lat_start, lat_end, lng_end, app_type)
+          if app_type == "" then
+            # default
+            select_postfix = ")'\n"
+          else
+            file_prefix = app_type + "_"
+            select_postfix = ", \"#{app_type}\")'\n"
+          end
+          dottest = sprintf("%s%s\n%s\n%s%s%s%s",
+                    TABLE_CREATE,
+                    COLUMN_CREATE,
+                    LOAD,
+                    comment,
+                    SELECT, scorer, select_postfix)
+
+          if filename and filename != "" then
+            testname = sprintf("%s/%s/%s/%s%s",
+                       prefix, quadrant, type,
+                       file_prefix, File.basename(filename))
+          else
+            exit 1
+          end
+
+          if testname and not Dir.exists?(File.dirname(testname)) then
+            FileUtils.mkdir_p(File.dirname(testname))
+          end
+
+          if File.exists?(testname) then
+            # duplicated?
+            puts "Warning! #{testname} duplicated"
+          end
+          File.open(testname, "w+") { |f|
+            if OPTS.has_key? :verbose then
+              puts testname
+              puts dottest
+            end
+            f.puts dottest
+          }
+        }
+      end
+    }
+  }
+end
+




Groonga-commit メーリングリストの案内
Back to archive index