#reader(lib "htdp-beginner-reader.ss" "lang")((modname kathi-finder) (read-case-sensitive #t) (teachpacks ()) (htdp-settings #(#t constructor repeating-decimal #f #t none #f ())))
(define WIDTH 320)
(define HEIGHT 480)
(define-struct named-place (name latitude longitude radius))
(define-struct unnamed-place (latitude longitude))
(define (place->string a-place)
(cond
[(named-place? a-place)
(named-place-name a-place)]
[(unnamed-place? a-place)
(string-append "Unknown ("
(number->string (unnamed-place-latitude a-place))
", "
(number->string (unnamed-place-longitude a-place))
")")]))
(define (place-radius a-place)
(cond
[(named-place? a-place)
(named-place-radius a-place)]
[(unnamed-place? a-place)
(mile->meter 0.5)]))
(define (place-latitude a-place)
(cond
[(named-place? a-place)
(named-place-latitude a-place)]
[(unnamed-place? a-place)
(unnamed-place-latitude a-place)]))
(define (place-longitude a-place)
(cond
[(named-place? a-place)
(named-place-longitude a-place)]
[(unnamed-place? a-place)
(unnamed-place-longitude a-place)]))
(define (mile->meter miles)
(* miles 1609.344))
(define WPI-PLACE (make-named-place "WPI"
42.272824
-71.808207
500))
(define WPI-PARKING-PLACE (make-named-place "WPI Parking"
42.2737222
-71.8058627
50))
(define WORCESTER-PLACE (make-named-place "Worcester"
42.274514
-71.798744
(mile->meter 3)))
(define-struct world (places place phone-number))
(define initial-world (make-world (list WPI-PLACE
WPI-PARKING-PLACE
WORCESTER-PLACE)
(make-unnamed-place 0 0)
"5556"))
(define (update-world-place a-world a-place)
(make-world (world-places a-world)
a-place
(world-phone-number a-world)))
(define (handle-location-change a-world latitude longitude)
(cond
[(places-are-significantly-different?
(world-place a-world)
(choose-place a-world latitude longitude))
(report-new-place
(update-world-place a-world
(choose-place a-world latitude longitude)))]
[else
(update-world-place a-world
(choose-place a-world latitude longitude))]))
(define (places-are-significantly-different? p1 p2)
(cond
[(and (named-place? p1) (named-place? p2))
(not (equal? p1 p2))]
[(and (unnamed-place? p1) (unnamed-place? p2))
false]
[else
true]))
(define (report-new-place a-world)
(send-text-message (world-phone-number a-world)
(string-append "Kathi is at "
(place->string (world-place a-world))
". Link: "
"http://maps.google.com/maps?q="
(number->string (place-latitude (world-place a-world)))
",+"
(number->string (place-longitude (world-place a-world)))
"&iwloc=A&hl=en")
a-world))
(define (choose-place a-world a-lat a-long)
(cond
[(empty? (find-places (world-places a-world) a-lat a-long))
(make-unnamed-place a-lat a-long)]
[else
(find-smallest-place
(find-places (world-places a-world) a-lat a-long))]))
(define (find-smallest-place places)
(cond
[(empty? (rest places))
(first places)]
[(< (place-radius (first places))
(place-radius (second places)))
(find-smallest-place (cons (first places)
(rest (rest places))))]
[else
(find-smallest-place (rest places))]))
(define (find-places places a-lat a-long)
(cond
[(empty? places)
empty]
[(place-matches? (first places) a-lat a-long)
(cons (first places)
(find-places (rest places) a-lat a-long))]
[else
(find-places (rest places) a-lat a-long)]))
(define (place-matches? a-place a-lat a-long)
(<= (location-distance a-lat
a-long
(place-latitude a-place)
(place-longitude a-place))
(place-radius a-place)))
(define (render-world a-world)
(place-image
(text (place->string (world-place a-world)) 10 "black")
20
20
(empty-scene WIDTH HEIGHT)))
(big-bang WIDTH HEIGHT initial-world
(on-redraw render-world)
(on-location-change handle-location-change))