<commit_before>import { Injectable, Inject } from 'ng-metadata/core';
import { PartnerReferral } from '../partner-referral/partner-referral-service';
import { Environment } from '../environment/environment.service';
import { Device } from '../device/device.service';

export interface BeaconOptions
{
	sourceResource?: string;
	sourceResourceId?: number;
	key?: string;
}

@Injectable( 'HistoryTick' )
export class HistoryTick
{
	private _sources: { [key: string]: string } = {};

	constructor(
		@Inject( 'Referrer' ) private referrer: any,
		@Inject( 'PartnerReferral' ) private partnerReferral: PartnerReferral,
	)
	{
	}

	/**
	 * You can track a source for a particular parent resource.
	 * For example, tracking the current referrer for a Game and then any time
	 * you log a tick for a type within that Game (game-build, game-news, etc)
	 * it will pull the source referrer into the tick.
	 *
	 * Note that we only log the first referrer for a particular resource.
	 * If you get to this resource through different means we'll still just
	 * track the initial way of getting there.
	 */
	trackSource( resource: string, resourceId: number )
	{
		// Look specifically for undefined and not just null.
		// There may have been a null referrer if we got here through a direct page hit.
		if ( angular.isUndefined( this._sources[ resource + ':' + resourceId ] ) ) {
			this._sources[ resource + ':' + resourceId ] = this.referrer.get();
		}
	}

	getSource( resource: string, resourceId: number )
	{
		return this._sources[ resource + ':' + resourceId ];
	}

	sendBeacon( type: string, resourceId: number, options: BeaconOptions = {} )
	{
		if ( Environment.isPrerender ) {
			return;
		}

		return new Promise( ( resolve ) =>
		{
			const queryParams: string[] = [];

			// Cache busting.
			queryParams.push( 'cb=' + Date.now() );

			// Device info.
			queryParams.push( 'os=' + Device.os() );
			const arch = Device.arch();
			if ( arch ) {
				queryParams.push( 'arch=' + arch );
			}

			// Source/referrer.
			if ( options.sourceResource && options.sourceResourceId ) {
				const source = this.getSource( options.sourceResource, options.sourceResourceId );
				if ( source ) {
					queryParams.push( 'source=' + source );
				}

				const ref = this.partnerReferral.getReferrer( options.sourceResource, options.sourceResourceId );
				if ( ref ) {
					queryParams.push( 'ref=' + ref );
				}
			}

			// Key.
			if ( options.key ) {
				queryParams.push( 'key=' + options.key );
			}

			// This is enough to send the beacon.
			// No need to add it to the page.
			const img = window.document.createElement( 'img' );
			img.width = 1;
			img.height = 1;
			img.src = `${Environment.apiHost}/tick/${type}/${resourceId}?${queryParams.join( '&' )}`;

			// Always resolve.
			img.onload = img.onerror = () =>
			{
				delete img.onload;
				delete img.onerror;
				resolve();
			};

			if ( Environment.env == 'development' ) {
				console.log( 'Tracking history tick.', {
					type: type,
					resourceId: resourceId,
					queryString: queryParams.join( '&' ),
				} );
			}
		} );
	}
}<commit_msg>Convert history tick service to non-angular<commit_after>import { PartnerReferral } from '../partner-referral/partner-referral-service';
import { Environment } from '../environment/environment.service';
import { Device } from '../device/device.service';
import { Referrer } from '../referrer/referrer.service';

export interface BeaconOptions
{
	sourceResource?: string;
	sourceResourceId?: number;
	key?: string;
}

export class HistoryTick
{
	private static _sources: { [key: string]: string | undefined } = {};

	/**
	 * You can track a source for a particular parent resource.
	 * For example, tracking the current referrer for a Game and then any time
	 * you log a tick for a type within that Game (game-build, game-news, etc)
	 * it will pull the source referrer into the tick.
	 *
	 * Note that we only log the first referrer for a particular resource.
	 * If you get to this resource through different means we'll still just
	 * track the initial way of getting there.
	 */
	static trackSource( resource: string, resourceId: number )
	{
		// Look specifically for undefined and not just null.
		// There may have been a null referrer if we got here through a direct page hit.
		if ( typeof this._sources[ resource + ':' + resourceId ] === 'undefined' ) {
			this._sources[ resource + ':' + resourceId ] = Referrer.get();
		}
	}

	static getSource( resource: string, resourceId: number )
	{
		return this._sources[ resource + ':' + resourceId ];
	}

	static sendBeacon( type: string, resourceId: number, options: BeaconOptions = {} )
	{
		if ( Environment.isPrerender ) {
			return;
		}

		return new Promise( ( resolve ) =>
		{
			const queryParams: string[] = [];

			// Cache busting.
			queryParams.push( 'cb=' + Date.now() );

			// Device info.
			queryParams.push( 'os=' + Device.os() );
			const arch = Device.arch();
			if ( arch ) {
				queryParams.push( 'arch=' + arch );
			}

			// Source/referrer.
			if ( options.sourceResource && options.sourceResourceId ) {
				const source = this.getSource( options.sourceResource, options.sourceResourceId );
				if ( source ) {
					queryParams.push( 'source=' + source );
				}

				const ref = PartnerReferral.getReferrer( options.sourceResource, options.sourceResourceId );
				if ( ref ) {
					queryParams.push( 'ref=' + ref );
				}
			}

			// Key.
			if ( options.key ) {
				queryParams.push( 'key=' + options.key );
			}

			// This is enough to send the beacon.
			// No need to add it to the page.
			const img = window.document.createElement( 'img' );
			img.width = 1;
			img.height = 1;
			img.src = `${Environment.apiHost}/tick/${type}/${resourceId}?${queryParams.join( '&' )}`;

			// Always resolve.
			img.onload = img.onerror = () =>
			{
				delete img.onload;
				delete img.onerror;
				resolve();
			};

			if ( Environment.env === 'development' ) {
				console.log( 'Tracking history tick.', {
					type: type,
					resourceId: resourceId,
					queryString: queryParams.join( '&' ),
				} );
			}
		} );
	}
}
{'fraction_non_alphanumeric': 0.13540983606557377, 'fraction_numerical': 0.0006557377049180328, 'mean_word_length': 3.0538205980066446, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 7, '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': '4074', 'n_tokens_mistral': 2146, 'n_tokens_neox': 1844, 'n_words': 561}