You've already forked pigallery2
mirror of
https://github.com/bpatrik/pigallery2.git
synced 2025-11-27 22:38:10 +02:00
Add parser and stringfyer for coordinate based distance search #1012
This commit is contained in:
@@ -340,13 +340,38 @@ export class SearchQueryParser {
|
||||
) {
|
||||
from = from.slice(1, from.length - 1);
|
||||
}
|
||||
|
||||
// Check if the from part matches coordinate pattern (number, number)
|
||||
const coordMatch = from.match(/^\s*(-?\d+\.?\d*)\s*,\s*(-?\d+\.?\d*)\s*$/);
|
||||
if (coordMatch) {
|
||||
// It's a coordinate pair
|
||||
const latitude = parseFloat(coordMatch[1]);
|
||||
const longitude = parseFloat(coordMatch[2]);
|
||||
return {
|
||||
type: SearchQueryTypes.distance,
|
||||
distance: intFromRegexp(str),
|
||||
from: {
|
||||
GPSData: {
|
||||
latitude,
|
||||
longitude
|
||||
}
|
||||
},
|
||||
// only add negate if the value is true
|
||||
...(new RegExp('^\\d*-' + this.keywords.kmFrom + '!:').test(str) && {
|
||||
negate: true,
|
||||
}),
|
||||
} as DistanceSearch;
|
||||
}
|
||||
|
||||
// If not coordinates, treat as location text
|
||||
return {
|
||||
type: SearchQueryTypes.distance,
|
||||
distance: intFromRegexp(str),
|
||||
from: {text: from},
|
||||
// only add negate if the value is true
|
||||
...(new RegExp('^\\d*-' + this.keywords.kmFrom + '!:').test(str) && {
|
||||
negate: true,
|
||||
}), // only add if the value is true
|
||||
}),
|
||||
} as DistanceSearch;
|
||||
}
|
||||
|
||||
@@ -557,25 +582,28 @@ export class SearchQueryParser {
|
||||
? ''
|
||||
: (query as RangeSearch).value)
|
||||
);
|
||||
case SearchQueryTypes.distance:
|
||||
if ((query as DistanceSearch).from.text.indexOf(' ') !== -1) {
|
||||
return (
|
||||
(query as DistanceSearch).distance +
|
||||
'-' +
|
||||
this.keywords.kmFrom +
|
||||
colon +
|
||||
'(' +
|
||||
(query as DistanceSearch).from.text +
|
||||
')'
|
||||
);
|
||||
case SearchQueryTypes.distance: {
|
||||
const distanceQuery = query as DistanceSearch;
|
||||
const text = distanceQuery.from.text;
|
||||
const coords = distanceQuery.from.GPSData;
|
||||
|
||||
let locationStr = '';
|
||||
if (text) {
|
||||
// If we have location text, use that
|
||||
locationStr = text;
|
||||
} else if (coords && coords.latitude != null && coords.longitude != null) {
|
||||
// If we only have coordinates, use them
|
||||
locationStr = `${coords.latitude.toFixed(6)}, ${coords.longitude.toFixed(6)}`;
|
||||
}
|
||||
return (
|
||||
(query as DistanceSearch).distance +
|
||||
'-' +
|
||||
this.keywords.kmFrom +
|
||||
colon +
|
||||
(query as DistanceSearch).from.text
|
||||
);
|
||||
|
||||
// Add brackets if the location string contains spaces
|
||||
if (locationStr.indexOf(' ') !== -1) {
|
||||
locationStr = `(${locationStr})`;
|
||||
}
|
||||
|
||||
return `${distanceQuery.distance}-${this.keywords.kmFrom}${colon}${locationStr}`;
|
||||
}
|
||||
|
||||
case SearchQueryTypes.orientation:
|
||||
return (
|
||||
this.keywords.orientation +
|
||||
|
||||
@@ -112,8 +112,106 @@ describe('SearchQueryParser', () => {
|
||||
check({type: SearchQueryTypes.max_resolution, value: 5, negate: true} as MaxResolutionSearch);
|
||||
});
|
||||
it('Distance search', () => {
|
||||
// Test location-based distance search
|
||||
check({type: SearchQueryTypes.distance, distance: 10, from: {text: 'New York'}} as DistanceSearch);
|
||||
check({type: SearchQueryTypes.distance, distance: 10, from: {text: 'New York'}, negate: true} as DistanceSearch);
|
||||
|
||||
// Test coordinate-based distance search
|
||||
check({
|
||||
type: SearchQueryTypes.distance,
|
||||
distance: 5,
|
||||
from: {
|
||||
GPSData: {
|
||||
latitude: 40.712776,
|
||||
longitude: -74.005974
|
||||
}
|
||||
}
|
||||
} as DistanceSearch);
|
||||
|
||||
// Test coordinate-based distance search with negation
|
||||
check({
|
||||
type: SearchQueryTypes.distance,
|
||||
distance: 5,
|
||||
from: {
|
||||
GPSData: {
|
||||
latitude: 40.712776,
|
||||
longitude: -74.005974
|
||||
}
|
||||
},
|
||||
negate: true
|
||||
} as DistanceSearch);
|
||||
|
||||
// Test parsing specific coordinate formats
|
||||
const parser = new SearchQueryParser(defaultQueryKeywords);
|
||||
|
||||
// Test basic coordinate format
|
||||
expect(parser.parse('5-km-from:(40.712776, -74.005974)')).to.deep.equals({
|
||||
type: SearchQueryTypes.distance,
|
||||
distance: 5,
|
||||
from: {
|
||||
GPSData: {
|
||||
latitude: 40.712776,
|
||||
longitude: -74.005974
|
||||
}
|
||||
}
|
||||
} as DistanceSearch);
|
||||
|
||||
// Test coordinate format with extra spaces
|
||||
expect(parser.parse('5-km-from:( 40.712776 , -74.005974 )')).to.deep.equals({
|
||||
type: SearchQueryTypes.distance,
|
||||
distance: 5,
|
||||
from: {
|
||||
GPSData: {
|
||||
latitude: 40.712776,
|
||||
longitude: -74.005974
|
||||
}
|
||||
}
|
||||
} as DistanceSearch);
|
||||
|
||||
// Test coordinates with different decimal places
|
||||
expect(parser.parse('5-km-from:(40.7, -74.1)')).to.deep.equals({
|
||||
type: SearchQueryTypes.distance,
|
||||
distance: 5,
|
||||
from: {
|
||||
GPSData: {
|
||||
latitude: 40.7,
|
||||
longitude: -74.1
|
||||
}
|
||||
}
|
||||
} as DistanceSearch);
|
||||
|
||||
// Test negated coordinate search
|
||||
expect(parser.parse('5-km-from!:(40.712776, -74.005974)')).to.deep.equals({
|
||||
type: SearchQueryTypes.distance,
|
||||
distance: 5,
|
||||
from: {
|
||||
GPSData: {
|
||||
latitude: 40.712776,
|
||||
longitude: -74.005974
|
||||
}
|
||||
},
|
||||
negate: true
|
||||
} as DistanceSearch);
|
||||
|
||||
// Test stringification of coordinates
|
||||
const query: DistanceSearch = {
|
||||
type: SearchQueryTypes.distance,
|
||||
distance: 5,
|
||||
from: {
|
||||
GPSData: {
|
||||
latitude: 40.712776,
|
||||
longitude: -74.005974
|
||||
}
|
||||
}
|
||||
};
|
||||
expect(parser.stringify(query)).to.equals('5-km-from:(40.712776, -74.005974)');
|
||||
|
||||
// Test stringification of negated coordinates
|
||||
const negatedQuery: DistanceSearch = {
|
||||
...query,
|
||||
negate: true
|
||||
};
|
||||
expect(parser.stringify(negatedQuery)).to.equals('5-km-from!:(40.712776, -74.005974)');
|
||||
});
|
||||
it('OrientationSearch search', () => {
|
||||
check({type: SearchQueryTypes.orientation, landscape: true} as OrientationSearch);
|
||||
|
||||
Reference in New Issue
Block a user