content: package io.vividcode.happyride.dispatchservice;
  
  import io.vividcode.happyride.dispatchservice.api.events.DriverLocation;
  import java.math.BigDecimal;
  import java.util.Collections;
  import java.util.Objects;
  import java.util.Set;
  import java.util.stream.Collectors;
  import org.springframework.beans.factory.annotation.Autowired;
  import org.springframework.data.geo.Circle;
  import org.springframework.data.geo.Distance;
  import org.springframework.data.geo.GeoResults;
  import org.springframework.data.geo.Point;
  import org.springframework.data.redis.connection.RedisGeoCommands.DistanceUnit;
  import org.springframework.data.redis.connection.RedisGeoCommands.GeoLocation;
  import org.springframework.data.redis.connection.RedisGeoCommands.GeoRadiusCommandArgs;
  import org.springframework.data.redis.core.RedisTemplate;
  import org.springframework.stereotype.Service;
  
  @Service
  public class DriverLocationService {
  
    @Autowired
    RedisTemplate<String, String> redisTemplate;
  
    private final String key = "available_drivers";
    public static final Distance searchRadius = new Distance(10,
        DistanceUnit.KILOMETERS);
  
    public void addAvailableDriver(final DriverLocation location) {
      this.redisTemplate.opsForGeo()
          .add(this.key, new Point(location.getLng().doubleValue(),
                  location.getLat().doubleValue()),
              location.getDriverId());
    }
  
    public void removeAvailableDriver(final String driverId) {
      this.redisTemplate.opsForGeo().remove(this.key, driverId);
    }
  
    public Set<AvailableDriver> findAvailableDrivers(final BigDecimal lng,
        final BigDecimal lat) {
      final GeoResults<GeoLocation<String>> results = this.redisTemplate.opsForGeo()
          .radius(this.key, new Circle(new Point(lng.doubleValue(), lat.doubleValue()),
                  searchRadius),
              GeoRadiusCommandArgs.newGeoRadiusArgs().includeCoordinates());
      if (results != null) {
        return results.getContent().stream().filter(Objects::nonNull)
            .map(result -> {
              final GeoLocation<String> content = result.getContent();
              final Point point = content.getPoint();
              return new AvailableDriver(content.getName(),
                  BigDecimal.valueOf(point.getX()),
                  BigDecimal.valueOf(point.getY()));
            })
            .collect(Collectors.toSet());
      }
      return Collections.emptySet();
    }
  }
  