<commit_before>package cgeo.geocaching.connector.al;

import cgeo.geocaching.R;
import cgeo.geocaching.connector.IConnector;
import cgeo.geocaching.enumerations.CacheSize;
import cgeo.geocaching.enumerations.CacheType;
import cgeo.geocaching.enumerations.LoadFlags.SaveFlag;
import cgeo.geocaching.enumerations.WaypointType;
import cgeo.geocaching.filters.core.BaseGeocacheFilter;
import cgeo.geocaching.filters.core.DistanceGeocacheFilter;
import cgeo.geocaching.filters.core.GeocacheFilter;
import cgeo.geocaching.filters.core.OriginGeocacheFilter;
import cgeo.geocaching.location.Geopoint;
import cgeo.geocaching.location.Viewport;
import cgeo.geocaching.models.Geocache;
import cgeo.geocaching.models.Waypoint;
import cgeo.geocaching.network.Network;
import cgeo.geocaching.network.Parameters;
import cgeo.geocaching.sensors.Sensors;
import cgeo.geocaching.settings.Settings;
import cgeo.geocaching.storage.DataStore;
import cgeo.geocaching.utils.JsonUtils;
import cgeo.geocaching.utils.LocalizationUtils;
import cgeo.geocaching.utils.Log;
import cgeo.geocaching.utils.SynchronizedDateFormat;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import java.text.ParseException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.EnumSet;
import java.util.List;
import java.util.Locale;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ArrayNode;
import io.reactivex.rxjava3.core.Single;
import io.reactivex.rxjava3.functions.Function;
import okhttp3.Response;
import org.apache.commons.lang3.StringUtils;

final class ALApi {

    @NonNull
    private static final String API_HOST        = "https://labs-api.geocaching.com/Api/Adventures/";
    private static final String CONSUMER_HEADER = "X-Consumer-Key";
    private static final String CONSUMER_KEY    = LocalizationUtils.getString(R.string.alc_consumer_key);

    private static final String LOCATION  = "/Location";
    private static final String LONGITUDE = "Longitude";
    private static final String LATITUDE  = "Latitude";
    private static final String TITLE     = "Title";

    private ALApi() {
        // utility class with static methods
    }

    @Nullable
    protected static Geocache searchByGeocode(final String geocode) {
        if (!Settings.isGCPremiumMember() || CONSUMER_KEY.isEmpty()) {
            return null;
        }
        final Parameters headers = new Parameters(CONSUMER_HEADER, CONSUMER_KEY);
        try {
            final Response response = apiRequest(geocode.substring(2), null, headers).blockingGet();
            return importCacheFromJSON(response);
        } catch (final Exception ignored) {
            return null;
        }
    }

    @NonNull
    protected static Collection<Geocache> searchByBBox(final Viewport viewport) {

        if (!Settings.isGCPremiumMember() || CONSUMER_KEY.isEmpty() || viewport.getLatitudeSpan() == 0 || viewport.getLongitudeSpan() == 0) {
            return Collections.emptyList();
        }

        final double lat1 = viewport.getLatitudeMax();
        final double lat2 = viewport.getLatitudeMin();
        final double lon1 = viewport.getLongitudeMax();
        final double lon2 = viewport.getLongitudeMin();
        final double latcenter = (lat1 + lat2) / 2;
        final double loncenter = (lon1 + lon2) / 2;
        final Geopoint gp1 = new Geopoint(lat1, lon1);
        final Geopoint gp2 = new Geopoint(lat2, lon2);
        final double radius = gp1.distanceTo(gp2) * 500; // we get diameter in km, need radius in m
        Log.d("_AL Radius: " + (int) radius);
        final Parameters params = new Parameters("skip", "0");
        final Parameters headers = new Parameters(CONSUMER_HEADER, CONSUMER_KEY);
        params.add("take", "500");
        params.add("radiusMeters", String.valueOf((int) radius));
        params.add("origin.latitude", String.valueOf(latcenter));
        params.add("origin.longitude", String.valueOf(loncenter));
        try {
            final Response response = apiRequest("SearchV3", params, headers).blockingGet();
            return importCachesFromJSON(response);
        } catch (final Exception ignored) {
            return Collections.emptyList();
        }
    }

    @NonNull
    protected static Collection<Geocache> searchByCenter(final Geopoint center) {
        return searchByCenter(center, 10);
    }

    @NonNull
    private static Collection<Geocache> searchByCenter(final Geopoint center, final int distanceInKm) {
        if (!Settings.isGCPremiumMember() || CONSUMER_KEY.isEmpty()) {
            return Collections.emptyList();
        }
        final Parameters params = new Parameters("skip", "0");
        params.add("take", "200");
        params.add("radiusMeters", "" + (distanceInKm * 1000));
        params.add("origin.latitude", String.valueOf(center.getLatitude()));
        params.add("origin.longitude", String.valueOf(center.getLongitude()));
        final Parameters headers = new Parameters(CONSUMER_HEADER, CONSUMER_KEY);
        try {
            final Response response = apiRequest("SearchV3", params, headers).blockingGet();
            return importCachesFromJSON(response);
        } catch (final Exception ignored) {
            return Collections.emptyList();
        }
    }

    @NonNull
    public static Collection<Geocache> searchByFilter(final GeocacheFilter filter, final IConnector connector) {
        //for now we have to assume that ALConnector supports only SINGLE criteria search

        final List<BaseGeocacheFilter> filters = filter.getAndChainIfPossible();
        final OriginGeocacheFilter of = GeocacheFilter.findInChain(filters, OriginGeocacheFilter.class);
        if (of != null && !of.allowsCachesOf(connector)) {
            return new ArrayList<>();
        }
        final DistanceGeocacheFilter df = GeocacheFilter.findInChain(filters, DistanceGeocacheFilter.class);
        if (df != null) {
            return searchByCenter(df.getEffectiveCoordinate(), df.getMaxRangeValue() == null ? 10 : df.getMaxRangeValue().intValue());
        }

        //by default, search around current position
        return searchByCenter(Sensors.getInstance().currentGeo().getCoords());<commit_msg>restrict AL connector to 100 results (fix #11538)<commit_after>package cgeo.geocaching.connector.al;

import cgeo.geocaching.R;
import cgeo.geocaching.connector.IConnector;
import cgeo.geocaching.enumerations.CacheSize;
import cgeo.geocaching.enumerations.CacheType;
import cgeo.geocaching.enumerations.LoadFlags.SaveFlag;
import cgeo.geocaching.enumerations.WaypointType;
import cgeo.geocaching.filters.core.BaseGeocacheFilter;
import cgeo.geocaching.filters.core.DistanceGeocacheFilter;
import cgeo.geocaching.filters.core.GeocacheFilter;
import cgeo.geocaching.filters.core.OriginGeocacheFilter;
import cgeo.geocaching.location.Geopoint;
import cgeo.geocaching.location.Viewport;
import cgeo.geocaching.models.Geocache;
import cgeo.geocaching.models.Waypoint;
import cgeo.geocaching.network.Network;
import cgeo.geocaching.network.Parameters;
import cgeo.geocaching.sensors.Sensors;
import cgeo.geocaching.settings.Settings;
import cgeo.geocaching.storage.DataStore;
import cgeo.geocaching.utils.JsonUtils;
import cgeo.geocaching.utils.LocalizationUtils;
import cgeo.geocaching.utils.Log;
import cgeo.geocaching.utils.SynchronizedDateFormat;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import java.text.ParseException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.EnumSet;
import java.util.List;
import java.util.Locale;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ArrayNode;
import io.reactivex.rxjava3.core.Single;
import io.reactivex.rxjava3.functions.Function;
import okhttp3.Response;
import org.apache.commons.lang3.StringUtils;

final class ALApi {

    @NonNull
    private static final String API_HOST        = "https://labs-api.geocaching.com/Api/Adventures/";
    private static final String CONSUMER_HEADER = "X-Consumer-Key";
    private static final String CONSUMER_KEY    = LocalizationUtils.getString(R.string.alc_consumer_key);

    private static final String LOCATION  = "/Location";
    private static final String LONGITUDE = "Longitude";
    private static final String LATITUDE  = "Latitude";
    private static final String TITLE     = "Title";

    private ALApi() {
        // utility class with static methods
    }

    @Nullable
    protected static Geocache searchByGeocode(final String geocode) {
        if (!Settings.isGCPremiumMember() || CONSUMER_KEY.isEmpty()) {
            return null;
        }
        final Parameters headers = new Parameters(CONSUMER_HEADER, CONSUMER_KEY);
        try {
            final Response response = apiRequest(geocode.substring(2), null, headers).blockingGet();
            return importCacheFromJSON(response);
        } catch (final Exception ignored) {
            return null;
        }
    }

    @NonNull
    protected static Collection<Geocache> searchByBBox(final Viewport viewport) {

        if (!Settings.isGCPremiumMember() || CONSUMER_KEY.isEmpty() || viewport.getLatitudeSpan() == 0 || viewport.getLongitudeSpan() == 0) {
            return Collections.emptyList();
        }

        final double lat1 = viewport.getLatitudeMax();
        final double lat2 = viewport.getLatitudeMin();
        final double lon1 = viewport.getLongitudeMax();
        final double lon2 = viewport.getLongitudeMin();
        final double latcenter = (lat1 + lat2) / 2;
        final double loncenter = (lon1 + lon2) / 2;
        final Geopoint gp1 = new Geopoint(lat1, lon1);
        final Geopoint gp2 = new Geopoint(lat2, lon2);
        final double radius = gp1.distanceTo(gp2) * 500; // we get diameter in km, need radius in m
        Log.d("_AL Radius: " + (int) radius);
        final Parameters params = new Parameters("skip", "0");
        final Parameters headers = new Parameters(CONSUMER_HEADER, CONSUMER_KEY);
        params.add("take", "100");
        params.add("radiusMeters", String.valueOf((int) radius));
        params.add("origin.latitude", String.valueOf(latcenter));
        params.add("origin.longitude", String.valueOf(loncenter));
        try {
            final Response response = apiRequest("SearchV3", params, headers).blockingGet();
            return importCachesFromJSON(response);
        } catch (final Exception ignored) {
            return Collections.emptyList();
        }
    }

    @NonNull
    protected static Collection<Geocache> searchByCenter(final Geopoint center) {
        return searchByCenter(center, 10);
    }

    @NonNull
    private static Collection<Geocache> searchByCenter(final Geopoint center, final int distanceInKm) {
        if (!Settings.isGCPremiumMember() || CONSUMER_KEY.isEmpty()) {
            return Collections.emptyList();
        }
        final Parameters params = new Parameters("skip", "0");
        params.add("take", "100");
        params.add("radiusMeters", "" + (distanceInKm * 1000));
        params.add("origin.latitude", String.valueOf(center.getLatitude()));
        params.add("origin.longitude", String.valueOf(center.getLongitude()));
        final Parameters headers = new Parameters(CONSUMER_HEADER, CONSUMER_KEY);
        try {
            final Response response = apiRequest("SearchV3", params, headers).blockingGet();
            return importCachesFromJSON(response);
        } catch (final Exception ignored) {
            return Collections.emptyList();
        }
    }

    @NonNull
    public static Collection<Geocache> searchByFilter(final GeocacheFilter filter, final IConnector connector) {
        //for now we have to assume that ALConnector supports only SINGLE criteria search

        final List<BaseGeocacheFilter> filters = filter.getAndChainIfPossible();
        final OriginGeocacheFilter of = GeocacheFilter.findInChain(filters, OriginGeocacheFilter.class);
        if (of != null && !of.allowsCachesOf(connector)) {
            return new ArrayList<>();
        }
        final DistanceGeocacheFilter df = GeocacheFilter.findInChain(filters, DistanceGeocacheFilter.class);
        if (df != null) {
            return searchByCenter(df.getEffectiveCoordinate(), df.getMaxRangeValue() == null ? 10 : df.getMaxRangeValue().intValue());
        }

        //by default, search around current position
        return searchByCenter(Sensors.getInstance().currentGeo().getCoords());
{'fraction_non_alphanumeric': 0.10337987940336402, 'fraction_numerical': 0.007933989209774674, 'mean_word_length': 3.5670289855072466, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 15, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 4}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5388492', 'n_tokens_mistral': 3714, 'n_tokens_neox': 3579, 'n_words': 802}