<commit_before>var geohash = require('ngeohash');

var query = require('./lib/query');
var range = require('./lib/range');

var queryByRanges = query.queryByRanges;

var setIdCount = 0;


// main constructor

function Set(opts) {

    opts = opts || {};

    this.client = opts.client;
    this.zset = opts.zset || 'geo:locations';
    this.caching = opts.cache !== undefined ? opts.cache : false;
}


// initialization and new sets

Set.prototype.initialize = function(redis_client, opts) {

    opts = opts || {};

    this.client = redis_client;
    this.zset = opts.zset ? opts.zset : (this.zset ? this.zset : 'geo:locations');

    return this;
};

Set.prototype.addSet = function(set_name) {
    return new Set({
        client: this.client,
        zset: this.zset + ':' + (set_name || 'subset_' + randomId())
    });
};

Set.prototype.deleteSet = function(set_name, callBack) {
    this.client.del(this.zset + ':' + set_name, callBack);
};

Set.prototype.delete = function(callBack) {
    this.client.del(this.zset, callBack);
};


// adding locations

Set.prototype.addLocation = function(location_name, coordinate, callBack) {
    this.client.zadd(this.zset, geohash.encode_int(coordinate.latitude, coordinate.longitude, 52), location_name, callBack);
};

Set.prototype.addLocations = function(location_set, callBack) {

    var args = [];
    var location_ame;
    var location;

    for (location_ame in location_set) {
        location = location_set[location_ame];
        args.push(geohash.encode_int(location.latitude, location.longitude, 52));
        args.push(location_ame);
    }

    args.unshift(this.zset);
    this.client.zadd(args, callBack);
};


// updating locations (same methods as add, existing locations get updated)

Set.prototype.updateLocation = Set.prototype.addLocation;

Set.prototype.updateLocations = Set.prototype.addLocations;


// removing locations

Set.prototype.removeLocation = function(location_name, callBack) {
    this.client.zrem(this.zset, location_name, callBack);
};

Set.prototype.removeLocations = function(location_name_array, callBack) {
    location_name_array.unshift(this.zset);
    this.client.zrem(location_name_array, callBack);
};


// querying location positions

Set.prototype.location = function(location_name, callBack) {
    query.location(this, location_name, callBack);
};

Set.prototype.locations = function(location_name_array, callBack) {
    query.locations(this, location_name_array, callBack);
};


// querying nearby locations

Set.prototype.nearby = function(point, radius, opts, callBack) {

    var ranges;

    if (typeof opts === 'function' && callBack === undefined) {
        callBack = opts;
        opts = {};
    }

    ranges = range(point.latitude, point.longitude, radius, this.caching);
    queryByRanges(this, ranges, opts.withCoordinates, callBack);
};

Set.prototype.getQueryCache = function(lat, lon, radius) {
    return range(lat, lon, radius, false);
};

Set.prototype.nearbyWithQueryCache = function(ranges, opts, callBack) {

    if (typeof opts === 'function' && callBack === undefined) {
        callBack = opts;
        opts = {};
    }

    queryByRanges(this, ranges, opts.withCoordinates, callBack);
};


// helpers

function randomId() {
    return '' + (~~(Math.random() * 1000000000000)).toString(36) + (setIdCount++);
}

<commit_msg>Making main interface default to emulation, and switch to native if available.<commit_after>var NativeInterface = require('./lib/interfaceNative');
var EmulatedInterface = require('./lib/interfaceEmulated');

var randomId = require('./lib/util/helper').randomId;

var native_commands = ['info', 'geoadd', 'geohash', 'geopos', 'geodist', 'georadius', 'georadiusbymember'];


// main constructor

function Set(options) {
    options = options || {};
    this.zset = options.zset || 'geo:locations';
    this.clientInterface = options.clientInterface;
}


// initialization

Set.prototype.initialize = function(redis_client, options) {
    options = options || {};

    this.clientInterface = new EmulatedInterface(redis_client);

    if (!this.zset) {
        this.zset = options.zset ? options.zset : 'geo:locations';
    }

    checkNativeInterface(this, redis_client, options.nativeGeo);

    return this;
};


// managing sets

Set.prototype.addSet = function(set_name) {
    return new Set({
        zset: this.zset + ':' + (set_name || 'subset_' + randomId()),
        clientInterface: this.clientInterface
    });
};

Set.prototype.deleteSet = function(set_name, callBack) {
    this.clientInterface.del(this.zset + ':' + set_name, callBack);
};

Set.prototype.delete = function(callBack) {
    this.clientInterface.del(this.zset, callBack);
};


// adding locations

Set.prototype.addLocation = function(locationName, point, callBack) {
    this.clientInterface.geoadd(locationName, point, this.zset, callBack);
};

Set.prototype.addLocations = function(locationSet, callBack) {
    this.clientInterface.geoadd_multi(locationSet, this.zset, callBack);
};


// Calculations

Set.prototype.getDistance = function(locationA, locationB, options, callBack) {

    if (typeof options === 'function') {
        callBack = options;
        options = {};
    } else {
        options = options || {};
    }

    this.clientInterface.geodist(locationA, locationB, options.units, this.zset, callBack);
};


// updating locations (same methods as add, existing locations get updated)

Set.prototype.updateLocation = Set.prototype.addLocation;

Set.prototype.updateLocations = Set.prototype.addLocations;


// removing locations

Set.prototype.removeLocation = function(locationName, callBack) {
    this.clientInterface.zrem([locationName], this.zset, callBack);
};

Set.prototype.removeLocations = function(locationNameArray, callBack) {
    this.clientInterface.zrem(locationNameArray, this.zset, callBack);
};


// querying location positions

Set.prototype.location = function(locationName, callBack) {
    this.clientInterface.geopos([locationName], this.zset, callBack);
};

Set.prototype.locations = function(locationNameArray, callBack) {
    this.clientInterface.geopos(locationNameArray, this.zset, callBack);
};


// querying location geohashes

Set.prototype.getGeohash = function(locationName, callBack) {
    this.clientInterface.geohash([locationName], this.zset, callBack);
};

Set.prototype.getGeohashes = function(locationNameArray, callBack) {
    this.clientInterface.geohashes(locationNameArray, this.zset, callBack);
};


// querying nearby locations

Set.prototype.withinRadiusOf = function(location, distance, options, callBack) {

    if (typeof options === 'function') {
        callBack = options;
        options = {};
    } else {
        options = options || {};
    }

    if (typeof location === 'string') {
        this.clientInterface.georadiusbymember(location, distance, options, this.zset, callBack);
    } else {
        this.clientInterface.georadius(location, distance, options, this.zset, callBack);
    }

};

Set.prototype.nearby = function(location, distance, options, callBack) {

    if (typeof options === 'function') {
        callBack = options;
        options = {};
    } else {
        options = options || {};
    }

    if (typeof location === 'string') {
        this.clientInterface.nearbymember(location, distance, options, this.zset, callBack);
    } else {
        this.clientInterface.nearby(location, distance, options, this.zset, callBack);
    }
};


// Query Range Methods

// Set.prototype.getQueryCache = function(lat, lon, distance) {
//     return range(lat, lon, distance);
// };

// Set.prototype.nearbyWithQueryCache = function(ranges, options, callBack) {

//     if (typeof options === 'function' && callBack === undefined) {
//         callBack = options;
//         options = {};
//     }

//     query(this, this.zset, ranges, options.withCoordinates, callBack);
// };


// helpers

function checkNativeInterface(set, client, nativeGeo) {

    if (client.send_command) {

        if (nativeGeo === undefined) {

            client.send_command('command', native_commands, function(err, response) {

                if (!err && response[0][0] === 'geoadd') {
                    set.clientInterface = new NativeInterface(client);
                }
            });

        } else if (nativeGeo === true) {
            set.clientInterface = new NativeInterface(client);
        }
    }
}


{'fraction_non_alphanumeric': 0.1376889206235868, 'fraction_numerical': 0.0026181125788408903, 'mean_word_length': 3.609983543609435, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 1, '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': '3410504', 'n_tokens_mistral': 2610, 'n_tokens_neox': 2529, 'n_words': 509}