func geocodeBuildings(c *maps.Client) error { buildings, err := models.LoadMapData() if err != nil { return err } for _, b := range buildings { if b.Position != nil || len(b.Address) == 0 { continue } log.Printf("geocoding %s", b.Name) req := &maps.GeocodingRequest{ Address: b.Address, Region: "ca", } result, err := c.Geocode(context.TODO(), req) if err != nil { return err } if len(result) == 0 { continue } loc := result[0].Geometry.Location b.Position = &models.LatLng{ Lat: loc.Lat, Lng: loc.Lng, } time.Sleep(100 * time.Millisecond) if err := models.SaveMapData(buildings); err != nil { return err } } for _, b := range buildings { if len(b.Floors) == 0 { continue } var lat, lng float64 c := float64(len(b.Floors) * 2) for _, f := range b.Floors { lat += f.Coords.North lat += f.Coords.South lng += f.Coords.West lng += f.Coords.East for _, r := range f.Rooms { lat += r.Position.Lat lng += r.Position.Lng c += 1 } } b.Position.Lat = lat / c b.Position.Lng = lng / c } return models.SaveMapData(buildings) }
// saveBuilding saves the changes made to a building. func (s *Server) saveBuilding(w http.ResponseWriter, r *auth.AuthenticatedRequest) { b := &models.Building{} if err := json.NewDecoder(r.Body).Decode(b); err != nil { http.Error(w, err.Error(), 400) return } for i, b2 := range s.buildings { if b2.SIS != b.SIS { continue } for _, f := range b.Floors { dx, dy := newDimentions(f.Coords.DLng(), f.Coords.DLat(), f.Rotation) affine := graphics.I.Rotate(f.Rotation) log.Printf("DX %f DY %f", dx, dy) for _, r := range f.Rooms { if r.RelPosition == nil { continue } rotated := affine.Mul(graphics.Affine{ (r.RelPosition.Lng - 0.5) * f.Coords.DLng(), 0, 0, (1 - r.RelPosition.Lat - 0.5) * f.Coords.DLat(), 0, 0, 1, 1, 1, }) px := (rotated[0]/dx + 0.5) py := (rotated[3]/dy + 0.5) log.Printf("(%f, %f) -> (%f, %f)", r.RelPosition.Lng, r.RelPosition.Lat, px, py) lat := (py)*f.Coords.DLat() + f.Coords.South lng := (px)*f.Coords.DLng() + f.Coords.West r.Position = &models.LatLng{ Lat: lat, Lng: lng, } } } s.buildings[i] = b if err := models.SaveMapData(s.buildings); err != nil { http.Error(w, err.Error(), 500) return } w.Header().Set("Content-Type", "application/json") json.NewEncoder(w).Encode(s.buildings[i]) return } http.Error(w, "building SIS not found", 404) }
func scrapeBuildings() error { buildings, err := models.LoadMapData() if err != nil { return err } doc, err := goquery.NewDocument("http://www.maps.ubc.ca/PROD/buildingsListAll.php") if err != nil { return err } detailsDup := make(map[string]bool) var details []string doc.Find("a[href]").Each(func(i int, sel *goquery.Selection) { href, exists := sel.Attr("href") if !exists || !strings.HasPrefix(href, "index_detail.php?") || detailsDup[href] { return } detailsDup[href] = true details = append(details, href) }) relChan := make(chan string, 1) defer close(relChan) outChan := make(chan *models.Building, 1) defer close(outChan) for _ = range make([]interface{}, 20) { go fetchDetails(relChan, outChan) } go func() { for _, rel := range details { relChan <- rel } }() var scrapedBuildings []*models.Building for b := range outChan { if len(b.SIS) == 0 { b.SIS = customSIS[b.Name] } scrapedBuildings = append(scrapedBuildings, b) if len(scrapedBuildings) == len(details) { break } } buildingIndex := make(map[string]*models.Building) for _, building := range buildings { buildingIndex[building.SIS] = building } for _, b := range scrapedBuildings { if len(b.SIS) == 0 { continue } if b2, ok := buildingIndex[b.SIS]; ok { b2.Address = b.Address b2.Image = b.Image b2.Description = b.Description continue } buildingIndex[b.SIS] = b buildings = append(buildings, b) } return models.SaveMapData(buildings) }