Skip to content

Commit

Permalink
feat(intervals):
Browse files Browse the repository at this point in the history
provider support multiple date filters (for interval http-request efficiency)
fix open issues and logic
move interval and time to model files
  • Loading branch information
yuvalbl committed Apr 10, 2018
1 parent f1df64c commit 46f7c30
Show file tree
Hide file tree
Showing 9 changed files with 208 additions and 112 deletions.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { BaseOverlaySourceProvider, DateRange, IFetchParams } from '@ansyn/overlays';
import { BaseOverlaySourceProvider, IFetchParams } from '@ansyn/overlays';
import { Overlay } from '@ansyn/core';
import { Observable } from 'rxjs/Observable';
import { Inject, Injectable, InjectionToken } from '@angular/core';
Expand All @@ -9,10 +9,11 @@ import { OverlayFilter, StartAndEndDate } from '@ansyn/overlays/models/base-over
import { OverlaysFetchData } from '@ansyn/core/models/overlay.model';
import { mergeLimitedArrays } from '@ansyn/core/utils/limited-array';
import { sortByDateDesc } from '@ansyn/core/utils/sorting';
import { IDateRange } from '@ansyn/core/models/time.model';

interface FiltersList {
name: string,
dates: DateRange[]
dates: IDateRange[]
sensorNames: string[],
coverage: number[][][][]
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,11 @@ export class PlanetSourceProvider extends BaseOverlaySourceProvider {
`basic ${btoa((this.planetOverlaysSourceConfig.apiKey + ':'))}` });
}

buildFilters(config: IPlanetFilter[]) {
buildFilters(config: IPlanetFilter[], filterType = 'AndFilter') {
return {
item_types: this.planetOverlaysSourceConfig.itemTypes,
filter: {
type: 'AndFilter',
type: filterType,
config: config
}
}
Expand All @@ -70,8 +70,7 @@ export class PlanetSourceProvider extends BaseOverlaySourceProvider {
const limit = `${fetchParams.limit + 1}`;

const bboxFilter = { type: 'GeometryFilter', field_name: 'geometry', config: fetchParams.region };
const dateFilter = { type: 'DateRangeFilter', field_name: 'acquired',
config: { gte: fetchParams.timeRange.start.toISOString(), lte: fetchParams.timeRange.end.toISOString()}};
const dateFilter = this.buildDateFilter(fetchParams);

return this.http.post<OverlaysPlanetFetchData>(baseUrl, this.buildFilters([ bboxFilter, dateFilter ]),
{ headers: this.httpHeaders, params: { _page_size: limit }})
Expand All @@ -85,6 +84,39 @@ export class PlanetSourceProvider extends BaseOverlaySourceProvider {
});
}

// build date filter for single / multiple time ranges
buildDateFilter(fetchParams: IFetchParams) {
let dateFilter;
if (fetchParams.timeRange.length === 1) {
// single time range (like in start-end)
dateFilter = {
type: 'DateRangeFilter',
field_name: 'acquired',
config: {
gte: fetchParams.timeRange[0].start.toISOString(),
lte: fetchParams.timeRange[0].end.toISOString()
}
}
} else {
// multiple time ranges (like in intervals)
const dateRangeFilters = fetchParams.timeRange.map(tr => {
return {
type: 'DateRangeFilter',
field_name: 'acquired',
config: {
gte: tr.start.toISOString(),
lte: tr.end.toISOString()
}
}
});
dateFilter = {
type: 'OrFilter',
config: dateRangeFilters
};
}
return dateFilter;
}

getById(id: string, sourceType: string): Observable<Overlay> {
const baseUrl = this.planetOverlaysSourceConfig.baseUrl;
const body = this.buildFilters([{type: 'StringInFilter', field_name: 'id', config: [id]}]);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ describe('DatePickerComponent', () => {

beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [DatePickerComponent],
declarations: [DatePickerComponent]
})
.compileComponents();
}));
Expand All @@ -23,31 +23,5 @@ describe('DatePickerComponent', () => {
it('should be created', () => {
expect(component).toBeTruthy();
});

// it('host binding should work', () => {
// component.disabled = false;
// fixture.detectChanges();
// expect(fixture.elementRef.nativeElement.classList.contains('disabled')).toBe(false);
// component.disabled = true;
// fixture.detectChanges();
// expect(fixture.elementRef.nativeElement.classList.contains('disabled')).toBe(true);
// });
//
// it('check that disabled actully disabes the input and the function', () => {
// const input = fixture.debugElement.query(By.css('input')).nativeElement;
// spyOn(component, 'onInputClicked');
// component.disabled = true;
// fixture.detectChanges();
//
// input.click();
// expect(input.checked).toBe(false);
// expect(component.onInputClicked).not.toHaveBeenCalled();
// component.disabled = false;
// fixture.detectChanges();
//
// input.click();
// expect(input.checked).toBe(true);
// expect(component.onInputClicked).toHaveBeenCalled();
// });
});

22 changes: 22 additions & 0 deletions src/app/@ansyn/core/models/intervals.model.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { Overlay } from '@ansyn/core';

export interface IntervalTimeFrame {
startDate: Date;
endDate: Date;
span: number;
intervalsCount: number;
}

export interface IntervalTimeFrame {
startDate: Date;
endDate: Date;
span: number;
intervalsCount: number;
}

export interface Interval {
startTime: Date;
endTime: Date;
pivot: Date;
overlays: Array<Overlay>;
}
4 changes: 4 additions & 0 deletions src/app/@ansyn/core/models/time.model.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export interface IDateRange {
start: Date,
end: Date
}
4 changes: 4 additions & 0 deletions src/app/@ansyn/core/utils/sorting.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
// latest date first
export const sortByDateDesc = (o1, o2) => o1.date > o2.date ? -1 : 1;
// earliest date first
export const sortByDateAsc = (o1, o2) => o1.date > o2.date ? 1 : -1;

// best resolution first
export const sortByResolutionDesc = (o1, o2) => o1.bestResolution > o2.bestResolution ? -1 : 1;
Original file line number Diff line number Diff line change
Expand Up @@ -5,31 +5,28 @@ import * as intersect from '@turf/intersect';
import { OverlaysFetchData } from '@ansyn/core/models/overlay.model';
import { mergeLimitedArrays } from '@ansyn/core/utils/limited-array';
import { sortByDateDesc } from '@ansyn/core/utils/sorting';

export interface DateRange {
start: Date;
end: Date;
}
import { cloneDeep } from 'lodash';
import { IDateRange } from '@ansyn/core/models/time.model';

export interface IFetchParams {
limit: number;
region: GeoJSON.GeoJsonObject;
sensors?: string[];
timeRange: DateRange;
timeRange: Array<IDateRange>;
}

export interface OverlayFilter {
sensor: string;
coverage: GeoJSON.Feature<any>;
timeRange: DateRange
timeRange: IDateRange
}

export interface StartAndEndDate {
startDate: string,
endDate: string
}

export function timeIntersection(whiteRange: DateRange, blackRange: DateRange): DateRange {
export function timeIntersection(whiteRange: IDateRange, blackRange: IDateRange): IDateRange {
if (!blackRange.end || (whiteRange.end && whiteRange.end <= blackRange.end)) {
if (!blackRange.start || whiteRange.end > blackRange.start) {
if (whiteRange.start >= blackRange.start) {
Expand Down Expand Up @@ -58,11 +55,13 @@ export abstract class BaseOverlaySourceProvider {
properties: {},
geometry: fetchParams.region
};

// They are strings!
const fetchParamsTimeRange = {
start: new Date(fetchParams.timeRange.start),
end: new Date(fetchParams.timeRange.end)
// get time range data
const fetchParamsTimeRange = cloneDeep(fetchParams.timeRange);
const fetchParamsGlobalTimeRange = {
// min start value
start: new Date(fetchParams.timeRange.reduce((a, b) => a.start <= b.start ? a : b).start),
// max end value
end: new Date(fetchParams.timeRange.reduce((a, b) => a.end >= b.end ? a : b).end)
};

const fetchPromises = filters
Expand All @@ -74,15 +73,15 @@ export abstract class BaseOverlaySourceProvider {
return area(intersection) > 0;
})
// Make sure they have a common time range
.filter(f => Boolean(timeIntersection(fetchParamsTimeRange, f.timeRange)))
.filter(f => Boolean(timeIntersection(fetchParamsGlobalTimeRange, f.timeRange)))
.map(f => {
const region = intersect(f.coverage, regionFeature).geometry;

// Create new filters, by the common region and time
let newFetchParams: IFetchParams = {
limit: fetchParams.limit,
region: intersect(f.coverage, regionFeature).geometry,
timeRange: timeIntersection(fetchParamsTimeRange, f.timeRange)
timeRange: fetchParamsTimeRange.map(tr => timeIntersection(tr, f.timeRange))
};

// Add sensor if exists on the filter
Expand Down
Loading

0 comments on commit 46f7c30

Please sign in to comment.