<commit_before>import { Injectable } from '@angular/core';
import gql from 'graphql-tag';
import { Apollo } from 'apollo-angular';
import { ActionType } from '../../../../src/models/action-type.enum';
import { AcNotification } from '../../../../src/models/ac-notification';
import {
	Observable,
	Observer
} from 'rxjs';
import { GeoUtilsService } from '../../../../src/services/geo-utils/geo-utils.service';
import { Track } from './track.model';
import { CesiumService } from '../../../../src/services/cesium/cesium.service';

const TracksDataQuery = gql`
    query TracksData {
        tracks{
            callsign
            id
            groundSpeed
            heading
            position {
                lat
                long
                alt
            }
        }
    }
`;

@Injectable()
export class RealTracksDataProvider {
	private readonly KNOTS_METER_PER_SEC = 0.5144444;
	private readonly INTERPOLATE_RATE = 500;
	private readonly POLLING_RATE = 5000;
	private tracksCache = new Map<string, AcNotification>();

	constructor(private apollo: Apollo, private cesiumService: CesiumService) {
	}

	private convertToCesiumEntity(trackData): AcNotification {
		const track = Object.assign({}, trackData);
		track.scale = 0.2;
		track.image = '/assets/fighter-jet.png';
		track.position = Cesium.Cartesian3.fromDegrees(trackData.position.long, trackData.position.lat);
		track.alt = trackData.position.alt;
		return { id: track.id, entity: track, actionType: ActionType.ADD_UPDATE };
	}

	private saveInCache(track: AcNotification) {
		this.tracksCache.set(track.id, track);
	}

	private changeLocation(trackNotification: AcNotification) {
		const track = <Track>trackNotification.entity;
		if (track.groundSpeed) {
			const distanceMeter = this.KNOTS_METER_PER_SEC * track.groundSpeed * this.INTERPOLATE_RATE / 1000;
			const radianAzimuth = track.heading;
			track.position = GeoUtilsService.pointByLocationDistanceAndAzimuth(track.position, distanceMeter, radianAzimuth, true);
			trackNotification.entity = track;
		}
		return trackNotification;
	}

	private createInterpolateObserver() {
		const interpolate = Observable.interval(this.INTERPOLATE_RATE)
			.flatMap(() => Array.from(this.tracksCache.values()))
			.map(trackNotification => this.changeLocation(trackNotification))
			.do(trackNotification => this.saveInCache(trackNotification));
		return interpolate;
	}

	get() {
		const interpolateTracks$ = this.createInterpolateObserver();

		const fromServerTracks$ = this.apollo.watchQuery<any>({ query: TracksDataQuery, pollInterval: this.POLLING_RATE })
			.map(({ data }) => data.tracks)
			.flatMap(track => track)
			.map(this.convertToCesiumEntity)
			.do(entity => this.saveInCache(entity));

		return Observable.merge(interpolateTracks$, fromServerTracks$);
	}
}
<commit_msg>reconnect on error, must create new watchQuery because when apollo client gets an error it can not continue polling<commit_after>import { Injectable } from '@angular/core';
import gql from 'graphql-tag';
import { Apollo } from 'apollo-angular';
import { ActionType } from '../../../../src/models/action-type.enum';
import { AcNotification } from '../../../../src/models/ac-notification';
import {
	Observable,
	Observer
} from 'rxjs';
import { GeoUtilsService } from '../../../../src/services/geo-utils/geo-utils.service';
import { Track } from './track.model';
import { CesiumService } from '../../../../src/services/cesium/cesium.service';

const TracksDataQuery = gql`
    query TracksData {
        tracks{
            callsign
            id
            groundSpeed
            heading
            position {
                lat
                long
                alt
            }
        }
    }
`;

@Injectable()
export class RealTracksDataProvider {
	private readonly KNOTS_METER_PER_SEC = 0.5144444;
	private readonly INTERPOLATE_RATE = 500;
	private readonly POLLING_RATE = 5000;
	private readonly RECONNECT_MS = 5000;
	private tracksCache = new Map<string, AcNotification>();

	constructor(private apollo: Apollo, private cesiumService: CesiumService) {
	}

	private convertToCesiumEntity(trackData): AcNotification {
		const track = Object.assign({}, trackData);
		track.scale = 0.2;
		track.image = '/assets/fighter-jet.png';
		track.position = Cesium.Cartesian3.fromDegrees(trackData.position.long, trackData.position.lat);
		track.alt = trackData.position.alt;
		return { id: track.id, entity: track, actionType: ActionType.ADD_UPDATE };
	}

	private saveInCache(track: AcNotification) {
		this.tracksCache.set(track.id, track);
	}

	private changeLocation(trackNotification: AcNotification) {
		const track = <Track>trackNotification.entity;
		if (track.groundSpeed) {
			const distanceMeter = this.KNOTS_METER_PER_SEC * track.groundSpeed * this.INTERPOLATE_RATE / 1000;
			const radianAzimuth = track.heading;
			track.position = GeoUtilsService.pointByLocationDistanceAndAzimuth(track.position, distanceMeter, radianAzimuth, true);
			trackNotification.entity = track;
		}
		return trackNotification;
	}

	private createInterpolateObserver() {
		const interpolate = Observable.interval(this.INTERPOLATE_RATE)
			.flatMap(() => Array.from(this.tracksCache.values()))
			.map(trackNotification => this.changeLocation(trackNotification))
			.do(trackNotification => this.saveInCache(trackNotification));
		return interpolate;
	}

	tryReconnect(err) {
		console.log(`Error connecting to Graphql: ${err}. Try to reconnect in ${this.RECONNECT_MS} ...`);
		return Observable.timer(this.RECONNECT_MS)
			.flatMap(() =>
				this.apollo.watchQuery<any>({
					query: TracksDataQuery,
          pollInterval: this.POLLING_RATE,
          fetchPolicy: 'network-only'})
					.catch(error => this.tryReconnect(error)));
	}

	get() {
		const interpolateTracks$ = this.createInterpolateObserver();

		const watchQuery$ = this.apollo.watchQuery<any>({ query: TracksDataQuery,
			pollInterval: this.POLLING_RATE, fetchPolicy: 'network-only'});
		const fromServerTracks$ = watchQuery$
			.catch(err => this.tryReconnect(err))
			.map(({ data }) => data.tracks)
			.flatMap(track => track)
			.map(this.convertToCesiumEntity)
			.do(entity => this.saveInCache(entity));

		return Observable.merge(interpolateTracks$, fromServerTracks$);
	}
}

{'fraction_non_alphanumeric': 0.12773780975219823, 'fraction_numerical': 0.007673860911270983, 'mean_word_length': 3.6931732933233308, 'pattern_counts': {'":': 0, '<': 10, '<?xml version=': 0, '>': 25, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, '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': '2402564', 'n_tokens_mistral': 2055, 'n_tokens_neox': 1866, 'n_words': 386}