Changeset 76 for hw

Show
Ignore:
Timestamp:
10/30/07 03:07:34 (5 years ago)
Author:
cs186
Message:

initial checkin of hw4

Location:
hw/hw4
Files:
53 added
2 modified
1 copied

Legend:

Unmodified
Added
Removed
  • hw/hw4/library/app/controllers/query1_controller.rb

    r71 r76  
     1require 'ym4r/google_maps/geocoding' 
     2 
    13class Query1Controller < ApplicationController 
    2    def index 
    3       @results = Author.find(:all, :conditions => "citizenship='France' or citizenship='Germany'") 
    4    end 
     4  def index 
     5    # Start timekeeping 
     6    starttime = Time.now 
     7     
     8    # Default library 
     9    libraryname = 'Evans Library'  
     10 
     11    # Get the library name from the form if it exists. 
     12    if params[:changelibrary] != nil 
     13      formobj = params[:changelibrary] 
     14      libraryname = formobj[:newlibrary] 
     15    end 
     16 
     17    # Retrieve the list of libraries for the Select (Drop Down) Box 
     18    # "@" preceeding a variable name indicates an instance variable. 
     19    # Instance variables can be passed to views, whereas 
     20    # local variables (variable names without preceeding "@") cannot 
     21    # be passed to views. 
     22    @alllibraries = Array.new  
     23    alllibraries1 = Library.find(:all, :order => "city,lname") 
     24    alllibraries1.each do |library| 
     25      @alllibraries << ["#{library.lname} in #{library.city}",library.lname] 
     26    end 
     27 
     28    # Find the lat/lon of the library of interest. 
     29    @mylibrary = Library.find(:first,  
     30                              :conditions => "lname = '#{libraryname}'") 
     31 
     32    # This is a Remote Procedure Call (RPC).  This particular type 
     33    # of call (translating a location name like "Berkeley" into  
     34    # lat/lon coordinates) is known as geocoding. 
     35    geoloc = Ym4r::GoogleMaps::Geocoding::get(@mylibrary.city) 
     36    if geoloc.status != Geocoding::GEO_SUCCESS 
     37      err = 'Library Coordinates Not Found' 
     38      return err 
     39    end 
     40    liblatlon = geoloc[0].latlon 
     41 
     42    # Initialize map and center it over the library of interest 
     43    @map = GMap.new("map_div") 
     44    @map.control_init(:large_map => true,:map_type => true) 
     45    @map.center_zoom_init(liblatlon,2) # zoom out a fair amount 
     46 
     47    # Make a library marker and icon 
     48    @map.icon_global_init(GIcon.new(:image => "/images/library.png",  
     49                                    :icon_size => GSize.new(20,20), 
     50                                    :icon_anchor => GPoint.new(10,10), 
     51                                    :info_window_anchor => GPoint.new(9,2)), 
     52                          "icon_library") 
     53    icon_construction = Variable.new("icon_library") 
     54    @map.overlay_init(GMarker.new(liblatlon, 
     55                                  :icon => icon_construction, 
     56                                  :title => libraryname,  
     57                                  :info_window => libraryname)) 
     58 
     59    # Get all the authors. 
     60    @authors = Array.new 
     61    results = Author.find(:all) 
     62    results.each do |result| 
     63 
     64      # This is another geocoding RPC. 
     65      # A potentially large number of authors are all geocoded. 
     66      # This is a good candidate for caching. 
     67      geoloc = Ym4r::GoogleMaps::Geocoding::get(result.bplace) 
     68 
     69      # Calculate the author's birthplace's distance from the library 
     70      if geoloc.status == Geocoding::GEO_SUCCESS 
     71        authlatlon = geoloc[0].latlon 
     72        # Distances recalculated from a relativley stable  set of libraries. 
     73        # This is a good candidate for caching. 
     74        dist = distance_between(authlatlon,liblatlon).floor 
     75        @map.overlay_init(GMarker.new(geoloc[0].latlon, 
     76                                      :title => result.name,  
     77                                      :info_window => "#{result.name} says:<br> I am #{dist} miles away<br> from #{@mylibrary.lname}")) 
     78        @authors << [result.name,result.bplace,dist] 
     79      end 
     80    end 
     81 
     82    # Sort authors in place by dist.  "sort!" means in place. 
     83    @authors.sort! {|x,y| x[2] <=> y[2] } 
     84 
     85    # Measure speed of server-side operation. 
     86    # Typical times w/  RPC: 3.5 seconds 
     87    # Typical times w/o RPC: 0.3 seconds 
     88    # Rhombus server fluctuations will cause this value to vary. 
     89    endtime = Time.now 
     90    @elapsedtime = endtime - starttime 
     91  end 
    592end 
     93 
     94# helper functions copied from GeoKit by Andre Lewis 
     95 
     96PI_DIV_RAD = 0.0174 
     97KMS_PER_MILE = 1.609 
     98EARTH_RADIUS_IN_MILES = 3963.19 
     99EARTH_RADIUS_IN_KMS = EARTH_RADIUS_IN_MILES * KMS_PER_MILE 
     100MILES_PER_LATITUDE_DEGREE = 69.1 
     101KMS_PER_LATITUDE_DEGREE = MILES_PER_LATITUDE_DEGREE * KMS_PER_MILE 
     102LATITUDE_DEGREES = EARTH_RADIUS_IN_MILES / MILES_PER_LATITUDE_DEGREE   
     103 
     104 
     105def distance_between(from, to, options={}) 
     106#  units = options[:units] || GeoKit::default_units  
     107#  formula = options[:formula] || GeoKit::default_formula 
     108  units = :miles 
     109  formula = :sphere 
     110  case formula 
     111  when :sphere           
     112    units_sphere_multiplier(units) *  
     113      Math.acos( Math.sin(deg2rad(from[0])) * Math.sin(deg2rad(to[0])) +  
     114                 Math.cos(deg2rad(from[0])) * Math.cos(deg2rad(to[0])) *  
     115                 Math.cos(deg2rad(to[1]) - deg2rad(from[1])))    
     116  when :flat 
     117    Math.sqrt((units_per_latitude_degree(units)*(from[0]-to[0]))**2 +  
     118              (units_per_longitude_degree(from[0], units)*(from[1]-to[1]))**2) 
     119  end 
     120end 
     121 
     122def deg2rad(degrees) 
     123  degrees.to_f / 180.0 * Math::PI 
     124end 
     125 
     126def rad2deg(rad) 
     127  rad.to_f * 180.0 / Math::PI  
     128end 
     129 
     130def to_heading(rad) 
     131  (rad2deg(rad)+360)%360 
     132end 
     133 
     134# Returns the multiplier used to obtain the correct distance units. 
     135def units_sphere_multiplier(units) 
     136  units == :miles ? EARTH_RADIUS_IN_MILES : EARTH_RADIUS_IN_KMS 
     137end 
     138 
     139# Returns the number of units per latitude degree. 
     140def units_per_latitude_degree(units) 
     141  units == :miles ? MILES_PER_LATITUDE_DEGREE : KMS_PER_LATITUDE_DEGREE 
     142end 
     143 
     144# Returns the number units per longitude degree. 
     145def units_per_longitude_degree(lat, units) 
     146  miles_per_longitude_degree = (LATITUDE_DEGREES * Math.cos(lat * PI_DIV_RAD)).abs 
     147  units == :miles ? miles_per_longitude_degree : miles_per_longitude_degree * KMS_PER_MILE 
     148end   
  • hw/hw4/library/app/views/query1/index.rhtml

    r71 r76  
    1 <h1> Query 1</h1> 
     1<html><head><title>Inspirational Libraries</title> 
     2<%= GMap.header %> 
     3<%= @map.to_html %> 
     4</head><body> 
    25 
    3 Print the names of the authors that are citizens either of France or Germany 
     6<h1>Inspirational Libraries</h1> 
    47 
    5 <h3>Ruby Code</h3> 
    6 <pre> 
    7     @results = Author.find(:all, :conditions => "citizenship='France' or  
    8        citizenship='Germany'") 
    9 </pre> 
     8<i> 
     9The map below shows birthplaces of authors relative to a particular library.  On the side bar to the right, authors have been sorted by their bithplaces' distance to the library.  Notice the "Elapsed Time" below.  Your job is to speed up this elapsed time by building a cache for the queries involving distances of authors' birthplaces to libraries. 
     10</i> 
    1011 
    11 <h3>Result</h3> 
    12  
     12<table> 
     13<tr> 
     14<!-- main map --> 
     15<td> 
     16<%= @map.div(:width => 600, :height => 400) %> 
     17</td> 
     18<td> 
     19&nbsp;&nbsp; 
     20</td> 
     21<!-- side bar --> 
     22<td> 
     23<h3><%= @mylibrary.lname %> in <%= @mylibrary.city %></h3> 
    1324<table border=1> 
    14 <tr><td><b>Name</b></td></tr> 
    15 <% for result in @results -%> 
    16 <tr><td><%= result.name %></td></tr> 
     25<tr><td><b>Author</b></td><td><b>Birthplace</b></td><td><b>Distance</b></td></tr> 
     26<% for author in @authors -%> 
     27<tr><td><%= author[0] %></td><td><%= author[1] %></td><td><%= author[2] %></td></tr> 
    1728<% end %> 
    1829</table> 
     30</td> 
     31</tr> 
     32</table> 
    1933 
     34<% form_for :changelibrary, :url => { :action => :index } do |form| %> 
     35<%= form.select :newlibrary, @alllibraries, :prompt => "-- Library Name --" %> 
     36<%= submit_tag "Switch Library", :class => "submit" %> 
     37<% end %> 
     38         
     39Elapsed Time: <%= @elapsedtime %> Seconds. 
     40 
     41</body></html>